@voltro/ai 0.57.0 → 0.58.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 +201 -0
- package/dist/index.d.ts +390 -8
- package/dist/index.js +471 -324
- package/dist/inferenceQueue-EQJJepZ8.js +632 -0
- package/dist/{provider-BOC5wBxx.js → provider-BOgeCRkg.js} +50 -25
- package/dist/test.js +1 -1
- package/dist/workflow.d.ts +69 -12
- package/dist/workflow.js +142 -106
- package/package.json +5 -5
- package/dist/inferenceQueue-CJZ4xw3R.js +0 -568
|
@@ -171,7 +171,7 @@ var u = [], d = (...e) => {
|
|
|
171
171
|
e.close();
|
|
172
172
|
} }) };
|
|
173
173
|
}
|
|
174
|
-
}), T = "iVBORw0KGgo=", E = "SUQzBAAAAAAAAA==", D = "video/mp4", O = (e, t) => ({
|
|
174
|
+
}), T = "iVBORw0KGgo=", E = "SUQzBAAAAAAAAA==", D = "video/mp4", O = "mock transcript", k = (e, t) => ({
|
|
175
175
|
specificationVersion: "v4",
|
|
176
176
|
provider: "mock",
|
|
177
177
|
modelId: e,
|
|
@@ -190,7 +190,7 @@ var u = [], d = (...e) => {
|
|
|
190
190
|
totalTokens: 0
|
|
191
191
|
}
|
|
192
192
|
})
|
|
193
|
-
}),
|
|
193
|
+
}), A = (e, t, n) => ({
|
|
194
194
|
specificationVersion: "v4",
|
|
195
195
|
provider: "mock",
|
|
196
196
|
modelId: e,
|
|
@@ -203,7 +203,25 @@ var u = [], d = (...e) => {
|
|
|
203
203
|
},
|
|
204
204
|
...n === void 0 ? {} : { providerMetadata: n }
|
|
205
205
|
})
|
|
206
|
-
}),
|
|
206
|
+
}), j = (e, t, n) => ({
|
|
207
|
+
specificationVersion: "v4",
|
|
208
|
+
provider: "mock",
|
|
209
|
+
modelId: e,
|
|
210
|
+
doGenerate: async () => ({
|
|
211
|
+
text: t,
|
|
212
|
+
segments: [],
|
|
213
|
+
language: "en",
|
|
214
|
+
durationInSeconds: 1,
|
|
215
|
+
warnings: [],
|
|
216
|
+
response: {
|
|
217
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
218
|
+
modelId: e,
|
|
219
|
+
headers: {},
|
|
220
|
+
body: void 0
|
|
221
|
+
},
|
|
222
|
+
...n === void 0 ? {} : { providerMetadata: n }
|
|
223
|
+
})
|
|
224
|
+
}), M = (e, t, n) => ({
|
|
207
225
|
specificationVersion: "v4",
|
|
208
226
|
provider: "mock",
|
|
209
227
|
modelId: e,
|
|
@@ -218,31 +236,38 @@ var u = [], d = (...e) => {
|
|
|
218
236
|
},
|
|
219
237
|
...n === void 0 ? {} : { providerMetadata: n }
|
|
220
238
|
})
|
|
221
|
-
}),
|
|
239
|
+
}), N = (e) => e.apiKey !== void 0 || e.baseURL !== void 0, P = (e) => ({
|
|
222
240
|
...e.apiKey === void 0 ? {} : { apiKey: e.apiKey },
|
|
223
241
|
...e.baseURL === void 0 ? {} : { baseURL: e.baseURL }
|
|
224
|
-
}),
|
|
242
|
+
}), F = (o, s) => m((() => {
|
|
225
243
|
switch (o.name) {
|
|
226
244
|
case "mock": return w(o.model ?? "mock", o.mockText, o.script, o.providerMetadata);
|
|
227
|
-
case "anthropic": return
|
|
228
|
-
case "openai": return
|
|
229
|
-
case "gateway": return
|
|
245
|
+
case "anthropic": return N(o) ? t(P(o))(o.model) : e(o.model);
|
|
246
|
+
case "openai": return N(o) ? n(P(o))(o.model) : r(o.model);
|
|
247
|
+
case "gateway": return N(o) ? i(P(o))(o.model) : a(o.model);
|
|
230
248
|
}
|
|
231
|
-
})(), s),
|
|
249
|
+
})(), s), I = (e) => {
|
|
232
250
|
switch (e.name) {
|
|
233
|
-
case "mock": return
|
|
234
|
-
case "openai": return
|
|
235
|
-
case "gateway": return
|
|
251
|
+
case "mock": return k(e.model ?? "mock", e.mockMedia?.imageBase64 ?? T);
|
|
252
|
+
case "openai": return N(e) ? n(P(e)).image(e.model) : r.image(e.model);
|
|
253
|
+
case "gateway": return N(e) ? i(P(e)).image(e.model) : a.image(e.model);
|
|
236
254
|
case "anthropic": throw Error("Provider 'anthropic' does not support image generation. Use 'openai' or 'gateway'.");
|
|
237
255
|
}
|
|
238
|
-
},
|
|
256
|
+
}, L = (e) => {
|
|
239
257
|
switch (e.name) {
|
|
240
|
-
case "mock": return
|
|
241
|
-
case "openai": return
|
|
242
|
-
case "gateway": return
|
|
258
|
+
case "mock": return A(e.model ?? "mock", e.mockMedia?.audioBase64 ?? E, e.providerMetadata);
|
|
259
|
+
case "openai": return N(e) ? n(P(e)).speech(e.model) : r.speech(e.model);
|
|
260
|
+
case "gateway": return N(e) ? i(P(e)).speech(e.model) : a.speech(e.model);
|
|
243
261
|
case "anthropic": throw Error("Provider 'anthropic' does not support speech generation. Use 'openai' or 'gateway'.");
|
|
244
262
|
}
|
|
245
|
-
},
|
|
263
|
+
}, R = (e) => {
|
|
264
|
+
switch (e.name) {
|
|
265
|
+
case "mock": return j(e.model ?? "mock", e.mockMedia?.transcript ?? O, e.providerMetadata);
|
|
266
|
+
case "openai": return N(e) ? n(P(e)).transcription(e.model) : r.transcription(e.model);
|
|
267
|
+
case "gateway": return N(e) ? i(P(e)).transcription(e.model) : a.transcription(e.model);
|
|
268
|
+
case "anthropic": throw Error("Provider 'anthropic' does not support transcription. Use 'openai' or 'gateway'.");
|
|
269
|
+
}
|
|
270
|
+
}, z = (e) => {
|
|
246
271
|
switch (e.name) {
|
|
247
272
|
case "mock": {
|
|
248
273
|
let t = e.mockMedia, n = t?.videoBase64 === void 0 ? {
|
|
@@ -254,17 +279,17 @@ var u = [], d = (...e) => {
|
|
|
254
279
|
data: t.videoBase64,
|
|
255
280
|
mediaType: D
|
|
256
281
|
};
|
|
257
|
-
return
|
|
282
|
+
return M(e.model ?? "mock", n, e.providerMetadata);
|
|
258
283
|
}
|
|
259
|
-
case "gateway": return
|
|
284
|
+
case "gateway": return N(e) ? i(P(e)).video(e.model) : a.video(e.model);
|
|
260
285
|
case "openai": throw Error("Provider 'openai' does not support video generation. Use 'gateway'.");
|
|
261
286
|
case "anthropic": throw Error("Provider 'anthropic' does not support video generation. Use 'gateway'.");
|
|
262
287
|
}
|
|
263
|
-
},
|
|
264
|
-
let t =
|
|
265
|
-
return
|
|
266
|
-
},
|
|
267
|
-
if (
|
|
288
|
+
}, B = null, V = (e) => {
|
|
289
|
+
let t = B;
|
|
290
|
+
return B = e, t;
|
|
291
|
+
}, H = () => B, U = (e = process.env) => {
|
|
292
|
+
if (B) return B;
|
|
268
293
|
let t = (e.AI_PROVIDER ?? "mock").toLowerCase(), n = e.AI_MODEL;
|
|
269
294
|
switch (t) {
|
|
270
295
|
case "mock": return {
|
|
@@ -291,4 +316,4 @@ var u = [], d = (...e) => {
|
|
|
291
316
|
}
|
|
292
317
|
};
|
|
293
318
|
//#endregion
|
|
294
|
-
export {
|
|
319
|
+
export { c as _, F as a, z as c, p as d, o as f, d as g, h, I as i, V as l, f as m, H as n, L as o, s as p, U as r, R as s, v as t, m as u };
|
package/dist/test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { l as e, t } from "./provider-BOgeCRkg.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 = (e) => {
|
|
4
4
|
let r = new t(n(e));
|
package/dist/workflow.d.ts
CHANGED
|
@@ -34,18 +34,6 @@ declare type AiJsonValue = null | boolean | number | string | {
|
|
|
34
34
|
[key: string]: AiJsonValue;
|
|
35
35
|
} | AiJsonValue[];
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
* A schema-constrained completion as a durable step.
|
|
39
|
-
*
|
|
40
|
-
* The schema is the step's success schema too, so the journaled value is
|
|
41
|
-
* decoded on replay exactly as it was on the first run — a structured result
|
|
42
|
-
* that only validated the first time through would be the worst kind of replay
|
|
43
|
-
* bug.
|
|
44
|
-
*
|
|
45
|
-
* Offloaded, the schema is rendered to JSON Schema for the dispatcher (a
|
|
46
|
-
* JavaScript Schema cannot be journaled) and the DECODE still happens here,
|
|
47
|
-
* where the real schema exists.
|
|
48
|
-
*/
|
|
49
37
|
export declare const aiObjectStep: <A, I>(options: AiObjectStepOptions<A, I>) => Effect.Effect<A, unknown>;
|
|
50
38
|
|
|
51
39
|
export declare interface AiObjectStepOptions<A, I> extends AiStepBaseOptions {
|
|
@@ -394,6 +382,9 @@ declare type ProviderConfig = {
|
|
|
394
382
|
/** base64 the mock video model yields INSTEAD of a URL — exercises the
|
|
395
383
|
* bytes branch of `generateVideo`. Takes precedence over `videoUrl`. */
|
|
396
384
|
readonly videoBase64?: string;
|
|
385
|
+
/** The text the mock transcription model returns. Lets a test assert on
|
|
386
|
+
* an exact transcript without a provider. */
|
|
387
|
+
readonly transcript?: string;
|
|
397
388
|
};
|
|
398
389
|
} | {
|
|
399
390
|
readonly name: 'anthropic';
|
|
@@ -452,4 +443,70 @@ export declare const resolveStepPrompt: (options: Pick<AiStepBaseOptions, "promp
|
|
|
452
443
|
readonly rendered: RenderedPrompt | undefined;
|
|
453
444
|
};
|
|
454
445
|
|
|
446
|
+
/**
|
|
447
|
+
* Transcription as a durable step — with `offload`, which is the point.
|
|
448
|
+
*
|
|
449
|
+
* A ninety-minute recording is not a request. Without offloading, a worker holds
|
|
450
|
+
* a connection for the whole call; `aiStep` and `aiObjectStep` have had
|
|
451
|
+
* `offload: true` all along and transcription — the modality that runs LONGEST —
|
|
452
|
+
* did not. The queue row carries the SOURCE, never the bytes: putting the audio
|
|
453
|
+
* in the row would reintroduce exactly the cost offloading exists to remove.
|
|
454
|
+
*/
|
|
455
|
+
export declare const transcribeStep: (options: TranscribeStepOptions) => Effect.Effect<{
|
|
456
|
+
readonly text: string;
|
|
457
|
+
readonly language?: string;
|
|
458
|
+
readonly durationSec?: number;
|
|
459
|
+
}, unknown>;
|
|
460
|
+
|
|
461
|
+
export declare interface TranscribeStepOptions extends Omit<AiStepBaseOptions, 'prompt' | 'system' | 'promptTemplate' | 'promptVars'> {
|
|
462
|
+
readonly source: TranscriptionSource;
|
|
463
|
+
readonly language?: string;
|
|
464
|
+
readonly timestamps?: TranscriptionTimestamps;
|
|
465
|
+
readonly diarize?: boolean;
|
|
466
|
+
readonly translateToEnglish?: boolean;
|
|
467
|
+
/** Resolve a `storageRef`. Required only for a ref source — and for an
|
|
468
|
+
* OFFLOADED one it must be wired on the dispatcher too, since that is the
|
|
469
|
+
* process that will do the read. */
|
|
470
|
+
readonly resolveRef?: (ref: string) => Promise<{
|
|
471
|
+
bytes: Uint8Array;
|
|
472
|
+
mediaType: string;
|
|
473
|
+
}>;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Where the audio is.
|
|
478
|
+
*
|
|
479
|
+
* `storageRef` is the one to reach for: the file is already in the app's
|
|
480
|
+
* storage, and resolving it there keeps tenancy, signing and lifetime with the
|
|
481
|
+
* component that owns them. The resolver is injected rather than imported so
|
|
482
|
+
* this module stays free of a storage dependency — `@voltro/ai` must not learn
|
|
483
|
+
* about buckets to transcribe a file.
|
|
484
|
+
*/
|
|
485
|
+
declare type TranscriptionSource =
|
|
486
|
+
/** Resolved by the app's own storage — the case to reach for. */
|
|
487
|
+
{
|
|
488
|
+
readonly storageRef: string;
|
|
489
|
+
}
|
|
490
|
+
/** Fetched by this function. Convenient, but the bytes do pass through this
|
|
491
|
+
* process: the SDK takes bytes or base64 and never a location. */
|
|
492
|
+
| {
|
|
493
|
+
readonly url: string;
|
|
494
|
+
}
|
|
495
|
+
/** Already in hand. The one that costs memory by construction. */
|
|
496
|
+
| {
|
|
497
|
+
readonly bytes: Uint8Array;
|
|
498
|
+
readonly mediaType: string;
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
/** What a `transcribeStep` journals. Structural, because a durable step's
|
|
502
|
+
* success schema is what a replay decodes through — see `AiStepText`. */
|
|
503
|
+
export declare const TranscriptionStepResult: Schema.Struct<{
|
|
504
|
+
text: typeof Schema.String;
|
|
505
|
+
language: Schema.optional<typeof Schema.String>;
|
|
506
|
+
durationSec: Schema.optional<typeof Schema.Number>;
|
|
507
|
+
}>;
|
|
508
|
+
|
|
509
|
+
/** How much timestamp detail to ask for. Providers charge for it. */
|
|
510
|
+
declare type TranscriptionTimestamps = 'none' | 'segment' | 'word';
|
|
511
|
+
|
|
455
512
|
export { }
|
package/dist/workflow.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { r as e } from "./provider-
|
|
2
|
-
import {
|
|
3
|
-
import { Effect as
|
|
4
|
-
import { eq as
|
|
5
|
-
import { CurrentWorkflowExecutionId as
|
|
1
|
+
import { r as e } from "./provider-BOgeCRkg.js";
|
|
2
|
+
import { B as t, D as n, O as r, U as i, W as a, b as o, m as s, o as c, p as l, s as u, t as d, w as f, y as p } from "./inferenceQueue-EQJJepZ8.js";
|
|
3
|
+
import { Effect as m, Schema as h } from "effect";
|
|
4
|
+
import { eq as g } from "@voltro/database";
|
|
5
|
+
import { CurrentWorkflowExecutionId as _, awaitSignalSuspending as v, step as y, suspendForBudget as b } from "@voltro/workflow";
|
|
6
6
|
//#region src/inferStep.ts
|
|
7
|
-
var
|
|
7
|
+
var x = {
|
|
8
8
|
maxAttempts: 4,
|
|
9
9
|
strategy: "exponential",
|
|
10
10
|
baseDelay: "1 second",
|
|
11
11
|
maxDelay: "30 seconds",
|
|
12
12
|
jitter: !0,
|
|
13
13
|
respectRetryAfter: !0
|
|
14
|
-
},
|
|
14
|
+
}, S = 36e5, C = "ai-usd", w = (e, t, n, r) => {
|
|
15
15
|
let i = r === void 0 ? {} : {
|
|
16
16
|
promptId: r.promptId,
|
|
17
17
|
promptVersion: r.digest,
|
|
@@ -24,14 +24,14 @@ var b = {
|
|
|
24
24
|
...t === void 0 ? {} : { system: t }
|
|
25
25
|
} : {
|
|
26
26
|
...i,
|
|
27
|
-
promptDigest:
|
|
27
|
+
promptDigest: s(e),
|
|
28
28
|
promptChars: e.length,
|
|
29
29
|
...t === void 0 ? {} : {
|
|
30
|
-
systemDigest:
|
|
30
|
+
systemDigest: s(t),
|
|
31
31
|
systemChars: t.length
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
|
-
},
|
|
34
|
+
}, T = (e) => l(e.prompt) ? {
|
|
35
35
|
text: e.prompt.prompt,
|
|
36
36
|
system: e.system ?? e.prompt.system,
|
|
37
37
|
rendered: e.prompt
|
|
@@ -39,68 +39,68 @@ var b = {
|
|
|
39
39
|
text: e.prompt,
|
|
40
40
|
system: e.system,
|
|
41
41
|
rendered: void 0
|
|
42
|
-
},
|
|
42
|
+
}, E = (e) => ({
|
|
43
43
|
provider: String(e.provider ?? "unknown"),
|
|
44
44
|
model: String(e.model ?? "unknown")
|
|
45
|
-
}),
|
|
46
|
-
let
|
|
47
|
-
if (
|
|
48
|
-
let { provider:
|
|
49
|
-
return i(
|
|
50
|
-
provider:
|
|
51
|
-
model:
|
|
52
|
-
operation:
|
|
45
|
+
}), D = (e, n, r, a, o) => {
|
|
46
|
+
let s = e.store;
|
|
47
|
+
if (s === void 0) return m.void;
|
|
48
|
+
let { provider: c, model: l } = E(n), u = t(a.providerMetadata);
|
|
49
|
+
return i(s, {
|
|
50
|
+
provider: c,
|
|
51
|
+
model: l,
|
|
52
|
+
operation: r,
|
|
53
53
|
agent: e.name,
|
|
54
|
-
usage:
|
|
54
|
+
usage: a.usage,
|
|
55
55
|
...e.tenantId === void 0 ? {} : { tenantId: e.tenantId },
|
|
56
|
-
...
|
|
57
|
-
...
|
|
58
|
-
}).pipe(
|
|
59
|
-
},
|
|
56
|
+
...u === void 0 ? {} : { actualCostUsd: u },
|
|
57
|
+
...o === void 0 ? {} : { prompt: o }
|
|
58
|
+
}).pipe(m.asVoid, m.catchAllCause(() => m.void));
|
|
59
|
+
}, O = (e, t) => {
|
|
60
60
|
let n = e.store;
|
|
61
|
-
return n === void 0 || t === void 0 ?
|
|
61
|
+
return n === void 0 || t === void 0 ? m.void : p(n, {
|
|
62
62
|
...t.definition,
|
|
63
63
|
digest: t.digest
|
|
64
|
-
}).pipe(
|
|
65
|
-
},
|
|
66
|
-
text:
|
|
67
|
-
inputTokens:
|
|
68
|
-
outputTokens:
|
|
69
|
-
totalTokens:
|
|
70
|
-
}),
|
|
64
|
+
}).pipe(m.asVoid, m.catchAllCause(() => m.void));
|
|
65
|
+
}, k = h.Struct({
|
|
66
|
+
text: h.String,
|
|
67
|
+
inputTokens: h.NullOr(h.Number),
|
|
68
|
+
outputTokens: h.NullOr(h.Number),
|
|
69
|
+
totalTokens: h.NullOr(h.Number)
|
|
70
|
+
}), A = (e) => typeof e == "object" && !!e && e.__voltro_ai_error === !0, j = class extends Error {
|
|
71
71
|
attempts;
|
|
72
72
|
constructor(e, t, n) {
|
|
73
73
|
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;
|
|
74
74
|
}
|
|
75
|
-
},
|
|
75
|
+
}, M = class extends Error {
|
|
76
76
|
constructor(e) {
|
|
77
77
|
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
78
|
}
|
|
79
|
-
},
|
|
80
|
-
let
|
|
81
|
-
if (
|
|
82
|
-
let
|
|
83
|
-
if (
|
|
84
|
-
let { provider:
|
|
79
|
+
}, N = (e, t, n, r, i, a) => m.gen(function* () {
|
|
80
|
+
let o = e.store;
|
|
81
|
+
if (o === void 0) return yield* m.die(new M(e.name));
|
|
82
|
+
let s = yield* _;
|
|
83
|
+
if (s === void 0) return yield* m.die(/* @__PURE__ */ Error(`aiStep('${e.name}'): offload: true is only valid inside a workflow body — there is no execution to suspend here.`));
|
|
84
|
+
let { provider: l, model: f } = E(t), p = u(s, e.name), h = yield* m.promise(() => o.query({
|
|
85
85
|
table: "_voltro_workflow_runs",
|
|
86
|
-
predicate:
|
|
86
|
+
predicate: g("executionId", s),
|
|
87
87
|
order: [],
|
|
88
88
|
take: 1,
|
|
89
89
|
skip: void 0,
|
|
90
90
|
projection: void 0
|
|
91
|
-
})),
|
|
92
|
-
return yield*
|
|
93
|
-
id:
|
|
91
|
+
})), v = String(h[0]?.tag ?? ""), y = h[0]?.id;
|
|
92
|
+
return yield* m.promise(() => o.insertIgnore(d, {
|
|
93
|
+
id: p,
|
|
94
94
|
tenantId: e.tenantId ?? null,
|
|
95
|
-
executionId:
|
|
96
|
-
workflowName:
|
|
97
|
-
runId: typeof
|
|
98
|
-
signalName:
|
|
95
|
+
executionId: s,
|
|
96
|
+
workflowName: v,
|
|
97
|
+
runId: typeof y == "string" ? y : null,
|
|
98
|
+
signalName: c(p),
|
|
99
99
|
stepName: e.name,
|
|
100
100
|
status: "pending",
|
|
101
101
|
kind: n,
|
|
102
|
-
provider:
|
|
103
|
-
model:
|
|
102
|
+
provider: l,
|
|
103
|
+
model: f,
|
|
104
104
|
prompt: i.text,
|
|
105
105
|
system: i.system ?? null,
|
|
106
106
|
promptId: i.rendered?.promptId ?? null,
|
|
@@ -109,120 +109,156 @@ var b = {
|
|
|
109
109
|
maxTokens: e.maxTokens ?? null,
|
|
110
110
|
providerOptions: e.providerOptions ?? null,
|
|
111
111
|
jsonSchema: r,
|
|
112
|
+
...a === void 0 ? {} : { transcription: a },
|
|
112
113
|
attempts: 0,
|
|
113
114
|
enqueuedAt: /* @__PURE__ */ new Date()
|
|
114
|
-
}, { conflictColumns: ["id"] })),
|
|
115
|
-
}),
|
|
116
|
-
let
|
|
115
|
+
}, { conflictColumns: ["id"] })), p;
|
|
116
|
+
}), P = (e, t, n, r, i, a, o) => m.gen(function* () {
|
|
117
|
+
let s = yield* y({
|
|
117
118
|
name: `${e.name}:enqueue`,
|
|
118
|
-
success:
|
|
119
|
+
success: h.String,
|
|
119
120
|
input: i,
|
|
120
|
-
execute:
|
|
121
|
+
execute: N(e, t, n, r, a, o)
|
|
121
122
|
});
|
|
122
|
-
yield*
|
|
123
|
-
let
|
|
124
|
-
name: s
|
|
125
|
-
schema:
|
|
123
|
+
yield* O(e, a.rendered);
|
|
124
|
+
let l = yield* v({ store: e.store }, {
|
|
125
|
+
name: c(s),
|
|
126
|
+
schema: h.Unknown,
|
|
126
127
|
timeoutMs: e.offloadTimeoutMs ?? 36e5
|
|
127
128
|
});
|
|
128
|
-
return
|
|
129
|
-
}),
|
|
129
|
+
return A(l) ? yield* m.die(new j(e.name, l.message, l.attempts)) : l;
|
|
130
|
+
}), F = class extends Error {
|
|
130
131
|
constructor(e) {
|
|
131
132
|
super(`aiStep('${e}'): budget needs \`store\` — the reservation counter and the hold both live in tables. Pass ctx.store.`), this.name = "AiBudgetMisuseError";
|
|
132
133
|
}
|
|
133
|
-
},
|
|
134
|
+
}, I = (e) => m.gen(function* () {
|
|
134
135
|
let t = e.budget;
|
|
135
136
|
if (t === void 0) return;
|
|
136
137
|
let n = e.store;
|
|
137
|
-
if (n === void 0) return yield*
|
|
138
|
+
if (n === void 0) return yield* m.die(new F(e.name));
|
|
138
139
|
let r = e.tenantId ?? null, i = t.name ?? "ai-usd", o = () => a(n, {
|
|
139
140
|
tenantId: r,
|
|
140
141
|
limitUsd: t.limitUsd,
|
|
141
142
|
addUsd: 0,
|
|
142
143
|
...t.since === void 0 ? {} : { since: t.since }
|
|
143
|
-
}).pipe(
|
|
144
|
+
}).pipe(m.as(null), m.catchTag("AiBudgetExceeded", (e) => m.succeed(e))), s = () => t.estimateUsd === void 0 ? m.void : a(n, {
|
|
144
145
|
tenantId: r,
|
|
145
146
|
limitUsd: t.limitUsd,
|
|
146
147
|
addUsd: t.estimateUsd,
|
|
147
148
|
...t.since === void 0 ? {} : { since: t.since }
|
|
148
149
|
}), c = yield* o();
|
|
149
150
|
if (c === null) return yield* s();
|
|
150
|
-
if ((t.onExceeded ?? "fail") !== "suspend") return yield*
|
|
151
|
-
let l = yield*
|
|
152
|
-
return l === void 0 ? yield*
|
|
151
|
+
if ((t.onExceeded ?? "fail") !== "suspend") return yield* m.fail(c);
|
|
152
|
+
let l = yield* _;
|
|
153
|
+
return l === void 0 ? yield* m.fail(c) : (yield* b({
|
|
153
154
|
store: n,
|
|
154
155
|
budget: i,
|
|
155
156
|
tenantId: r,
|
|
156
157
|
executionId: l,
|
|
157
|
-
workflowName: yield*
|
|
158
|
+
workflowName: yield* L(n, l),
|
|
158
159
|
stepName: e.name,
|
|
159
160
|
spentMicroUsd: Math.round(c.spentUsd * 1e6),
|
|
160
161
|
limitMicroUsd: Math.round(t.limitUsd * 1e6),
|
|
161
|
-
hasHeadroom: o().pipe(
|
|
162
|
+
hasHeadroom: o().pipe(m.map((e) => e === null)),
|
|
162
163
|
...t.holdTimeoutMs === void 0 ? {} : { timeoutMs: t.holdTimeoutMs },
|
|
163
164
|
...t.recheckEveryMs === void 0 ? {} : { recheckEveryMs: t.recheckEveryMs }
|
|
164
|
-
}).pipe(
|
|
165
|
-
}),
|
|
165
|
+
}).pipe(m.catchAll((e) => m.die(e))), yield* s());
|
|
166
|
+
}), L = (e, t) => m.promise(async () => {
|
|
166
167
|
let n = await e.query({
|
|
167
168
|
table: "_voltro_workflow_runs",
|
|
168
|
-
predicate:
|
|
169
|
+
predicate: g("executionId", t),
|
|
169
170
|
order: [],
|
|
170
171
|
take: 1,
|
|
171
172
|
skip: void 0,
|
|
172
173
|
projection: void 0
|
|
173
174
|
});
|
|
174
175
|
return String(n[0]?.tag ?? "");
|
|
175
|
-
}),
|
|
176
|
-
let
|
|
177
|
-
...
|
|
176
|
+
}), R = (t) => {
|
|
177
|
+
let r = t.provider ?? e(), i = T(t), a = {
|
|
178
|
+
...E(r),
|
|
178
179
|
operation: "generateText",
|
|
179
180
|
offloaded: t.offload === !0,
|
|
180
|
-
...
|
|
181
|
-
}, o = (e) => t.budget === void 0 ? e :
|
|
182
|
-
return t.offload === !0 ? o(
|
|
181
|
+
...w(i.text, i.system, t.recordPrompt ?? "digest", i.rendered)
|
|
182
|
+
}, o = (e) => t.budget === void 0 ? e : m.zipRight(I(t), e);
|
|
183
|
+
return t.offload === !0 ? o(P(t, r, "text", null, a, i)) : o(y({
|
|
183
184
|
name: t.name,
|
|
184
|
-
success:
|
|
185
|
+
success: k,
|
|
185
186
|
input: a,
|
|
186
|
-
retry: t.retry ??
|
|
187
|
-
execute:
|
|
187
|
+
retry: t.retry ?? x,
|
|
188
|
+
execute: n({
|
|
188
189
|
prompt: i.text,
|
|
189
|
-
provider:
|
|
190
|
+
provider: r,
|
|
190
191
|
...i.system === void 0 ? {} : { system: i.system },
|
|
191
192
|
...t.fallbacks === void 0 ? {} : { fallbacks: t.fallbacks },
|
|
192
193
|
...t.maxTokens === void 0 ? {} : { maxTokens: t.maxTokens },
|
|
193
194
|
...t.providerOptions === void 0 ? {} : { providerOptions: t.providerOptions }
|
|
194
|
-
}).pipe(
|
|
195
|
+
}).pipe(m.tap((e) => D(t, r, "generateText", e, i.rendered)), m.tap(() => O(t, i.rendered)), m.map((e) => ({
|
|
195
196
|
text: e.text,
|
|
196
197
|
inputTokens: e.usage.inputTokens ?? null,
|
|
197
198
|
outputTokens: e.usage.outputTokens ?? null,
|
|
198
199
|
totalTokens: e.usage.totalTokens ?? null
|
|
199
200
|
})))
|
|
200
201
|
}));
|
|
201
|
-
},
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
}, z = h.Struct({
|
|
203
|
+
text: h.String,
|
|
204
|
+
language: h.optional(h.String),
|
|
205
|
+
durationSec: h.optional(h.Number)
|
|
206
|
+
}), B = (t) => {
|
|
207
|
+
let n = t.provider ?? e(), r = {
|
|
208
|
+
source: t.source,
|
|
209
|
+
...t.language === void 0 ? {} : { language: t.language },
|
|
210
|
+
...t.timestamps === void 0 ? {} : { timestamps: t.timestamps },
|
|
211
|
+
...t.diarize === void 0 ? {} : { diarize: t.diarize },
|
|
212
|
+
...t.translateToEnglish === void 0 ? {} : { translateToEnglish: t.translateToEnglish }
|
|
213
|
+
}, i = {
|
|
214
|
+
...E(n),
|
|
215
|
+
operation: "transcribe",
|
|
216
|
+
offloaded: t.offload === !0
|
|
217
|
+
}, a = (e) => t.budget === void 0 ? e : m.zipRight(I(t), e);
|
|
218
|
+
return t.offload === !0 ? a(P(t, n, "transcription", null, i, {
|
|
219
|
+
text: "",
|
|
220
|
+
system: void 0,
|
|
221
|
+
rendered: void 0
|
|
222
|
+
}, r)) : a(y({
|
|
223
|
+
name: t.name,
|
|
224
|
+
success: z,
|
|
225
|
+
input: i,
|
|
226
|
+
retry: t.retry ?? x,
|
|
227
|
+
execute: o({
|
|
228
|
+
...r,
|
|
229
|
+
provider: n,
|
|
230
|
+
...t.resolveRef === void 0 ? {} : { resolveRef: t.resolveRef }
|
|
231
|
+
}).pipe(m.map((e) => ({
|
|
232
|
+
text: e.text,
|
|
233
|
+
...e.language === void 0 ? {} : { language: e.language },
|
|
234
|
+
...e.durationSec === void 0 ? {} : { durationSec: e.durationSec }
|
|
235
|
+
})))
|
|
236
|
+
}));
|
|
237
|
+
}, V = (t) => {
|
|
238
|
+
let n = t.provider ?? e(), i = T(t), a = {
|
|
239
|
+
...E(n),
|
|
204
240
|
operation: "generateObject",
|
|
205
|
-
offloaded:
|
|
206
|
-
...
|
|
207
|
-
},
|
|
208
|
-
return
|
|
209
|
-
let e = yield*
|
|
210
|
-
return yield*
|
|
211
|
-
})) :
|
|
212
|
-
name:
|
|
213
|
-
success:
|
|
214
|
-
input:
|
|
215
|
-
retry:
|
|
216
|
-
execute:
|
|
217
|
-
prompt:
|
|
218
|
-
schema:
|
|
219
|
-
provider:
|
|
220
|
-
...
|
|
221
|
-
...
|
|
222
|
-
...
|
|
223
|
-
...
|
|
224
|
-
}).pipe(
|
|
241
|
+
offloaded: t.offload === !0,
|
|
242
|
+
...w(i.text, i.system, t.recordPrompt ?? "digest", i.rendered)
|
|
243
|
+
}, o = (e) => t.budget === void 0 ? e : m.zipRight(I(t), e);
|
|
244
|
+
return t.offload === !0 ? o(m.gen(function* () {
|
|
245
|
+
let e = yield* r(t.schema, "aiObjectStep"), o = yield* P(t, n, "object", e, a, i);
|
|
246
|
+
return yield* h.decodeUnknown(t.schema)(o);
|
|
247
|
+
})) : o(y({
|
|
248
|
+
name: t.name,
|
|
249
|
+
success: t.schema,
|
|
250
|
+
input: a,
|
|
251
|
+
retry: t.retry ?? x,
|
|
252
|
+
execute: f({
|
|
253
|
+
prompt: i.text,
|
|
254
|
+
schema: t.schema,
|
|
255
|
+
provider: n,
|
|
256
|
+
...i.system === void 0 ? {} : { system: i.system },
|
|
257
|
+
...t.fallbacks === void 0 ? {} : { fallbacks: t.fallbacks },
|
|
258
|
+
...t.maxTokens === void 0 ? {} : { maxTokens: t.maxTokens },
|
|
259
|
+
...t.providerOptions === void 0 ? {} : { providerOptions: t.providerOptions }
|
|
260
|
+
}).pipe(m.tap((e) => D(t, n, "generateObject", e, i.rendered)), m.tap(() => O(t, i.rendered)), m.map((e) => e.object))
|
|
225
261
|
}));
|
|
226
262
|
};
|
|
227
263
|
//#endregion
|
|
228
|
-
export {
|
|
264
|
+
export { x as AI_STEP_RETRY, F as AiBudgetMisuseError, j as AiOffloadError, M as AiOffloadMisuseError, C as DEFAULT_AI_BUDGET_NAME, S as DEFAULT_OFFLOAD_TIMEOUT_MS, z as TranscriptionStepResult, V as aiObjectStep, R as aiStep, s as promptDigest, w as promptRecordFor, T as resolveStepPrompt, B as transcribeStep };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.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",
|
|
@@ -57,10 +57,10 @@
|
|
|
57
57
|
"@ai-sdk/gateway": "^4.0.47",
|
|
58
58
|
"@ai-sdk/openai": "^4.0.37",
|
|
59
59
|
"@ai-sdk/provider": "^4.0.7",
|
|
60
|
-
"@voltro/cache": "0.
|
|
61
|
-
"@voltro/database": "0.
|
|
62
|
-
"@voltro/protocol": "0.
|
|
63
|
-
"@voltro/workflow": "0.
|
|
60
|
+
"@voltro/cache": "0.58.0",
|
|
61
|
+
"@voltro/database": "0.58.0",
|
|
62
|
+
"@voltro/protocol": "0.58.0",
|
|
63
|
+
"@voltro/workflow": "0.58.0",
|
|
64
64
|
"ai": "^7.0.59"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|