@voltro/ai 0.85.0 → 0.86.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +666 -0
  2. package/THIRD-PARTY-NOTICES.md +5 -33
  3. package/dist/agent.js +64 -2
  4. package/dist/agentConstants.js +4 -0
  5. package/dist/agentExecutor.js +51 -0
  6. package/dist/api.js +199 -0
  7. package/dist/appTools.js +80 -0
  8. package/dist/budget.js +201 -0
  9. package/dist/callEvidence.js +51 -0
  10. package/dist/copilot.js +126 -0
  11. package/dist/cost.js +242 -0
  12. package/dist/embed.js +41 -0
  13. package/dist/embeddingProvider.js +51 -0
  14. package/dist/eval.js +130 -0
  15. package/dist/events.d.ts +4 -0
  16. package/dist/events.js +81 -2
  17. package/dist/executableModalities.js +13 -0
  18. package/dist/gateway.js +58 -0
  19. package/dist/gatewayCatalog.js +47 -0
  20. package/dist/gatewayMedia.js +88 -0
  21. package/dist/index.d.ts +11 -0
  22. package/dist/index.js +42 -2750
  23. package/dist/inferenceDispatch.js +493 -0
  24. package/dist/inferenceQueue.js +96 -0
  25. package/dist/jsonOutputValidation.js +27 -0
  26. package/dist/mcpClient.js +332 -0
  27. package/dist/mcpTools.js +80 -0
  28. package/dist/media.js +182 -0
  29. package/dist/mediaBytes.js +19 -0
  30. package/dist/mediaCall.js +13 -0
  31. package/dist/mediaTaskProvider.js +16 -0
  32. package/dist/middleware.js +32 -0
  33. package/dist/observe.js +52 -0
  34. package/dist/prompts.js +103 -0
  35. package/dist/provider.js +303 -0
  36. package/dist/realtimeEvent.js +97 -0
  37. package/dist/realtimeSession.js +154 -0
  38. package/dist/rerank.js +61 -0
  39. package/dist/resumableStream.js +321 -0
  40. package/dist/retrieveReranked.js +16 -0
  41. package/dist/runAndPersist.js +148 -0
  42. package/dist/semanticCache.js +66 -0
  43. package/dist/speechProvider.js +16 -0
  44. package/dist/streamRegistry.js +14 -0
  45. package/dist/streamText.js +170 -0
  46. package/dist/streamTranscribe.js +74 -0
  47. package/dist/streamWakeups.js +44 -0
  48. package/dist/structuredEvidence.js +48 -0
  49. package/dist/test.js +1 -1
  50. package/dist/threads.js +92 -0
  51. package/dist/tools.js +68 -0
  52. package/dist/transcribe.js +64 -0
  53. package/dist/transcriptionEvent.js +46 -0
  54. package/dist/workflow.d.ts +2 -0
  55. package/dist/workflow.js +115 -110
  56. package/package.json +5 -5
  57. package/dist/agentDescriptor-DhoiXVqO.js +0 -63
  58. package/dist/agentEvent-Bl4egdM5.js +0 -211
  59. package/dist/inferenceQueue-DcEulZep.js +0 -1077
  60. package/dist/provider-BnemgE4D.js +0 -409
@@ -0,0 +1,493 @@
1
+ import { gatewayCostUsd as e, recordAiUsageBestEffort as t } from "./cost.js";
2
+ import { generateObjectJson as n, generateText as r } from "./api.js";
3
+ import { mediaCall as i } from "./mediaCall.js";
4
+ import { generateImage as a, generateSpeech as o, generateVideo as s } from "./media.js";
5
+ import { transcribe as c } from "./transcribe.js";
6
+ import { mediaTaskProvider as l } from "./mediaTaskProvider.js";
7
+ import { AI_INFERENCES_TABLE as u, decideInferenceFailure as d, toQueuedInference as f } from "./inferenceQueue.js";
8
+ import { and as p, eq as m, gt as h, gte as g, lt as _, lte as v, or as y, registerRetention as b, retentionTtlMsFromEnv as x } from "@voltro/database";
9
+ //#region src/inferenceDispatch.ts
10
+ var S = 4, C = 250, w = 5e3, T = 36e5, E = {
11
+ examined: !1,
12
+ claimed: 0,
13
+ succeeded: 0,
14
+ failed: 0,
15
+ retried: 0,
16
+ reclaimed: 0,
17
+ polled: 0,
18
+ failures: []
19
+ }, D = (e) => {
20
+ let t = e instanceof Error ? e.message : String(e);
21
+ return t.length > 1e3 ? `${t.slice(0, 1e3)}…` : t;
22
+ }, O = (e) => {
23
+ let t = e;
24
+ if (typeof t?.retryAfterMillis == "number") return t.retryAfterMillis;
25
+ if (typeof t?.retryAfter == "number") return t.retryAfter * 1e3;
26
+ }, k = (e) => {
27
+ if (typeof e != "object" || !e) return;
28
+ let t = e;
29
+ return t.__voltro_inference_delivery === 1 && (t.status === "succeeded" || t.status === "failed") && typeof t.attempts == "number" && "payload" in t && (t.errorMessage === null || typeof t.errorMessage == "string") ? e : void 0;
30
+ }, A = (e) => y(p(m("status", "pending"), v("enqueuedAt", new Date(e))), p(m("status", "running"), _("leaseUntil", new Date(e)))), j = 720, M = () => {
31
+ b({
32
+ source: "framework",
33
+ table: u,
34
+ timeColumn: "completedAt",
35
+ ttlMs: x(process.env.VOLTRO_AI_INFERENCES_TTL_HOURS, 720),
36
+ envVar: "VOLTRO_AI_INFERENCES_TTL_HOURS",
37
+ label: "offloaded inference queue"
38
+ });
39
+ }, N = async (e, t = {}) => {
40
+ M();
41
+ let n = e.now?.() ?? Date.now(), r = t.batch ?? 4, i = t.leaseMs ?? 3e5, a = t.maxAttempts ?? 4, o = e.replicaId ?? `pid-${process.pid}`, s;
42
+ try {
43
+ s = await e.store.query({
44
+ table: u,
45
+ predicate: A(n),
46
+ order: [{
47
+ column: "enqueuedAt",
48
+ direction: "asc"
49
+ }],
50
+ take: r,
51
+ skip: void 0,
52
+ projection: void 0
53
+ });
54
+ } catch (e) {
55
+ return {
56
+ ...E,
57
+ examined: !0,
58
+ failures: [{
59
+ id: u,
60
+ detail: D(e)
61
+ }]
62
+ };
63
+ }
64
+ if (s.length === 0) return {
65
+ ...E,
66
+ examined: !0,
67
+ ...await P(e.store, n)
68
+ };
69
+ let c = [], h = 0, g = 0, y = 0, b = 0, x = 0, S = 0, C = s.map((r) => async () => {
70
+ let s = f(r), C = String(r.status) === "running", w = s.fence + 1, T = 0;
71
+ try {
72
+ T = await e.store.updateMany(u, {
73
+ status: "running",
74
+ leaseUntil: new Date(n + i),
75
+ claimedBy: o,
76
+ startedAt: new Date(n),
77
+ fence: w
78
+ }, { where: p(m("id", s.id), C ? p(m("status", "running"), _("leaseUntil", new Date(n))) : p(m("status", "pending"), v("enqueuedAt", new Date(n)))) });
79
+ } catch (e) {
80
+ c.push({
81
+ id: s.id,
82
+ detail: D(e)
83
+ });
84
+ return;
85
+ }
86
+ if (T !== 1) return;
87
+ h += 1, C && (x += 1);
88
+ let E = async (t) => {
89
+ let n = await e.store.updateMany(u, t, { where: p(m("id", s.id), m("fence", w), m("status", "running")) });
90
+ return n !== 1 && c.push({
91
+ id: s.id,
92
+ detail: `a stale worker (fence ${w}) tried to write; the row has moved on`
93
+ }), n === 1;
94
+ }, A = Date.now(), j = async (r) => {
95
+ c.push({
96
+ id: s.id,
97
+ detail: D(r)
98
+ }), e.log?.warn("ai.infer: recovery deferred without a new submission", {
99
+ id: s.id,
100
+ model: s.model,
101
+ attempts: s.attempts,
102
+ detail: D(r)
103
+ }), await E({ leaseUntil: new Date(n + (t.baseDelayMs ?? 1e3)) }).catch(() => !1) && b++;
104
+ }, M = async (t, n = !1) => {
105
+ try {
106
+ if (!n && !await E({
107
+ result: t,
108
+ errorMessage: t.errorMessage
109
+ }) || (await e.resume({
110
+ executionId: s.executionId,
111
+ workflowName: s.workflowName,
112
+ signalName: s.signalName,
113
+ payload: t.payload
114
+ }), !await E({
115
+ status: t.status,
116
+ result: t.payload,
117
+ attempts: t.attempts,
118
+ errorMessage: t.errorMessage,
119
+ completedAt: /* @__PURE__ */ new Date(),
120
+ durationMs: Date.now() - A,
121
+ leaseUntil: null
122
+ }))) return;
123
+ t.status === "failed" ? (y++, e.log?.warn("ai.infer: offloaded call gave up", {
124
+ id: s.id,
125
+ model: s.model,
126
+ attempts: t.attempts,
127
+ detail: t.errorMessage,
128
+ outcome: t.payload.outcome
129
+ })) : (g++, e.log?.info("ai.infer: offloaded call completed", {
130
+ id: s.id,
131
+ model: s.model,
132
+ durationMs: Date.now() - A,
133
+ recoveredDelivery: n
134
+ }));
135
+ } catch (e) {
136
+ await j(e);
137
+ }
138
+ }, N = async (e, t, n) => {
139
+ c.push({
140
+ id: s.id,
141
+ detail: e
142
+ }), await M({
143
+ __voltro_inference_delivery: 1,
144
+ status: "failed",
145
+ attempts: t,
146
+ errorMessage: e,
147
+ payload: {
148
+ __voltro_ai_error: !0,
149
+ message: e,
150
+ attempts: t,
151
+ outcome: n
152
+ }
153
+ });
154
+ }, P = async (e) => {
155
+ await M({
156
+ __voltro_inference_delivery: 1,
157
+ status: "succeeded",
158
+ payload: e,
159
+ attempts: s.attempts,
160
+ errorMessage: null
161
+ });
162
+ }, I = s.kind === "media" ? l(s.provider) : void 0, L = !1;
163
+ try {
164
+ let n = k(r.result);
165
+ if (n !== void 0) {
166
+ await M(n, !0);
167
+ return;
168
+ }
169
+ if (s.kind === "media" && e.persistMedia === void 0) {
170
+ await N(`inference ${s.id}: no media persistence is wired on this host`, s.attempts, "failed");
171
+ return;
172
+ }
173
+ if (C && s.kind === "media" && s.taskHandle === null && I?.idempotentSubmit !== !0) {
174
+ await N(`media job ${s.id} was claimed by a worker that was lost before it reported; ` + (I === void 0 ? "the provider has no job lookup, so its outcome is unknown and the job is not submitted again" : "no task handle had reached the row, so its outcome is unknown and the job is not submitted again"), s.attempts, "unknown");
175
+ return;
176
+ }
177
+ if (I !== void 0) {
178
+ let n = await z(e, {
179
+ ...s,
180
+ fence: w
181
+ }, I, E, {
182
+ pollMs: t.taskPollMs ?? 5e3,
183
+ timeoutMs: t.taskTimeoutMs ?? 36e5
184
+ });
185
+ if (n.kind === "stale") return;
186
+ if (n.kind === "pending") {
187
+ await E({
188
+ status: "pending",
189
+ leaseUntil: null,
190
+ enqueuedAt: new Date(Date.now() + n.delayMs)
191
+ }).catch(() => !1) && (S += 1);
192
+ return;
193
+ }
194
+ if (n.kind === "failed") {
195
+ if (!n.retryable) {
196
+ await N(n.detail, s.attempts + 1, n.outcome ?? "failed");
197
+ return;
198
+ }
199
+ throw L = !0, Error(n.detail);
200
+ }
201
+ await P(n.payload);
202
+ return;
203
+ }
204
+ await P((await F(e, {
205
+ ...s,
206
+ fence: w
207
+ })).payload);
208
+ } catch (e) {
209
+ if (s.kind === "media" && !L) {
210
+ await j(e);
211
+ return;
212
+ }
213
+ let n = d({
214
+ attempts: s.attempts,
215
+ maxAttempts: a,
216
+ baseDelayMs: t.baseDelayMs ?? 1e3,
217
+ maxDelayMs: t.maxDelayMs ?? 3e4,
218
+ retryAfterMs: O(e)
219
+ }), r = D(e);
220
+ if (c.push({
221
+ id: s.id,
222
+ detail: r
223
+ }), n.kind === "retry") {
224
+ await E({
225
+ status: "pending",
226
+ attempts: n.attempts,
227
+ errorMessage: r,
228
+ leaseUntil: null,
229
+ enqueuedAt: new Date(Date.now() + n.delayMs),
230
+ taskHandle: null,
231
+ taskSubmittedAt: null
232
+ }).catch(() => !1) && (b += 1);
233
+ return;
234
+ }
235
+ c.pop(), await N(r, n.attempts, "failed");
236
+ }
237
+ });
238
+ await Promise.all(C.map((e) => e()));
239
+ let w = h === 0 ? await P(e.store, n) : {};
240
+ return {
241
+ examined: !0,
242
+ claimed: h,
243
+ succeeded: g,
244
+ failed: y,
245
+ retried: b,
246
+ reclaimed: x,
247
+ polled: S,
248
+ failures: c,
249
+ ...w
250
+ };
251
+ }, P = async (e, t) => {
252
+ let n = async (t, n) => {
253
+ let [r] = await e.query({
254
+ table: u,
255
+ predicate: t,
256
+ order: [{
257
+ column: n,
258
+ direction: "asc"
259
+ }],
260
+ take: 1,
261
+ skip: void 0,
262
+ projection: void 0
263
+ }), i = r?.[n], a = i instanceof Date ? i.getTime() : typeof i == "string" || typeof i == "number" ? new Date(i).getTime() : NaN;
264
+ return Number.isFinite(a) ? a : void 0;
265
+ };
266
+ try {
267
+ let [e, r] = await Promise.all([n(p(m("status", "pending"), h("enqueuedAt", new Date(t))), "enqueuedAt"), n(p(m("status", "running"), g("leaseUntil", new Date(t))), "leaseUntil")]), i = [e, r === void 0 ? void 0 : r + 1].filter((e) => e !== void 0);
268
+ return { nextDueAt: i.length === 0 ? null : Math.min(...i) };
269
+ } catch {
270
+ return {};
271
+ }
272
+ }, F = async (e, t) => {
273
+ let i = {
274
+ name: t.provider,
275
+ model: t.model
276
+ }, a = {
277
+ prompt: t.prompt,
278
+ provider: i,
279
+ ...t.system === null ? {} : { system: t.system },
280
+ ...t.maxTokens === null ? {} : { maxTokens: t.maxTokens },
281
+ ...t.providerOptions !== null && t.providerOptions !== void 0 ? { providerOptions: t.providerOptions } : {}
282
+ };
283
+ if (t.kind === "transcription") {
284
+ let n = t.transcription;
285
+ if (n === null) throw Error(`inference ${t.id} is kind 'transcription' but carries no source`);
286
+ let r = await e.run(c({
287
+ ...n,
288
+ provider: i,
289
+ ...e.resolveTranscriptionRef === void 0 ? {} : { resolveRef: e.resolveTranscriptionRef }
290
+ }));
291
+ return await B(e, t, "transcribe", { usage: {} }), { payload: r };
292
+ }
293
+ if (t.kind === "media") return { payload: await I(e, t, i) };
294
+ if (t.kind === "object") {
295
+ if (t.jsonSchema === null) throw Error(`inference ${t.id} is kind 'object' but carries no jsonSchema`);
296
+ let r = await e.run(n({
297
+ ...a,
298
+ jsonSchema: t.jsonSchema
299
+ }));
300
+ return await B(e, t, "generateObject", r), { payload: r.object };
301
+ }
302
+ let o = await e.run(r(a));
303
+ return await B(e, t, "generateText", o), { payload: {
304
+ text: o.text,
305
+ inputTokens: o.usage.inputTokens ?? null,
306
+ outputTokens: o.usage.outputTokens ?? null,
307
+ totalTokens: o.usage.totalTokens ?? null
308
+ } };
309
+ }, I = async (e, t, n) => {
310
+ let r = t.media;
311
+ if (r === null) throw Error(`inference ${t.id} is kind 'media' but carries no job`);
312
+ let i = L(e, t), c = r.params;
313
+ if (r.modality === "image") {
314
+ let o = await e.run(a({
315
+ prompt: t.prompt,
316
+ provider: n,
317
+ ...c,
318
+ ...Object.keys(r.inputs).length > 0 ? { inputs: r.inputs } : {}
319
+ }));
320
+ await B(e, t, "generateImage", {
321
+ usage: o.usage ?? {},
322
+ providerMetadata: o.providerMetadata
323
+ });
324
+ let s = [];
325
+ for (let [e, t] of o.images.entries()) s.push(await i(e, t));
326
+ return {
327
+ artifacts: s,
328
+ usage: o.usage ?? null,
329
+ providerMetadata: o.providerMetadata ?? null
330
+ };
331
+ }
332
+ if (r.modality === "video") {
333
+ let a = await e.run(s({
334
+ prompt: t.prompt,
335
+ provider: n,
336
+ params: c,
337
+ ...Object.keys(r.inputs).length > 0 ? { inputs: r.inputs } : {}
338
+ }));
339
+ return await B(e, t, "generateVideo", {
340
+ usage: a.usage ?? {},
341
+ providerMetadata: a.providerMetadata
342
+ }), {
343
+ artifacts: [await i(0, a.video)],
344
+ usage: a.usage ?? null,
345
+ providerMetadata: a.providerMetadata ?? null
346
+ };
347
+ }
348
+ let l = await e.run(o({
349
+ text: t.prompt,
350
+ provider: n,
351
+ ...c
352
+ }));
353
+ return await B(e, t, "generateSpeech", {
354
+ usage: l.usage ?? {},
355
+ providerMetadata: l.providerMetadata
356
+ }), {
357
+ artifacts: [await i(0, l.audio)],
358
+ usage: l.usage ?? null,
359
+ providerMetadata: l.providerMetadata ?? null
360
+ };
361
+ }, L = (e, t) => {
362
+ let n = t.media?.persist ?? {}, r = e.persistMedia;
363
+ if (r === void 0) throw Error(`inference ${t.id} is a media job, but no media persistence is wired: install the storage plugin (it provides the mediaPersist capability) or pass persistMedia to the dispatcher`);
364
+ let i = (e) => `${t.id}#${t.attempts}#${e}`;
365
+ return async (e, a) => {
366
+ if (a.url !== void 0) {
367
+ if (r.ingestUrl === void 0) return {
368
+ url: a.url,
369
+ refId: null,
370
+ mediaType: a.mediaType
371
+ };
372
+ let o = await r.ingestUrl({
373
+ ...n,
374
+ url: a.url,
375
+ tenantId: t.tenantId,
376
+ operationId: i(e)
377
+ });
378
+ return {
379
+ url: o.url,
380
+ refId: o.refId,
381
+ mediaType: a.mediaType
382
+ };
383
+ }
384
+ if (a.data === void 0) throw Error(`inference ${t.id}: the provider returned an artifact with neither bytes nor a URL`);
385
+ let o = typeof a.data == "string" ? Uint8Array.from(Buffer.from(a.data, "base64")) : a.data, s = await r.put({
386
+ ...n,
387
+ bytes: o,
388
+ mediaType: a.mediaType,
389
+ tenantId: t.tenantId,
390
+ operationId: i(e)
391
+ });
392
+ return {
393
+ url: s.url,
394
+ refId: s.refId,
395
+ mediaType: a.mediaType
396
+ };
397
+ };
398
+ }, R = (e) => {
399
+ if (typeof e != "object" || !e || Array.isArray(e)) return !1;
400
+ try {
401
+ return typeof JSON.stringify(e) == "string";
402
+ } catch {
403
+ return !1;
404
+ }
405
+ }, z = async (e, t, n, r, a) => {
406
+ let o = t.media;
407
+ if (o === null) throw Error(`inference ${t.id} is kind 'media' but carries no job`);
408
+ let s = L(e, t), c = {
409
+ modality: o.modality,
410
+ prompt: t.prompt,
411
+ ...t.model === "unknown" ? {} : { model: t.model },
412
+ params: o.params,
413
+ inputs: o.inputs,
414
+ ...t.providerOptions !== null && t.providerOptions !== void 0 ? { providerOptions: t.providerOptions } : {},
415
+ tenantId: t.tenantId,
416
+ idempotencyKey: `${t.id}#${t.attempts}`
417
+ }, l = t.taskHandle, u = t.taskSubmittedAt;
418
+ if (u !== null && Date.now() - u.getTime() > a.timeoutMs) return {
419
+ kind: "failed",
420
+ retryable: !1,
421
+ detail: `media task ${t.id} is still pending after ${Math.round(a.timeoutMs / 1e3)}s at provider '${t.provider}'; the run is not kept waiting past the task timeout`
422
+ };
423
+ if (l === null) {
424
+ if (u === null && (u = /* @__PURE__ */ new Date(), !await r({ taskSubmittedAt: u }))) return { kind: "stale" };
425
+ let a = await e.run(i((e) => n.submit({
426
+ ...c,
427
+ abortSignal: e
428
+ })));
429
+ if (!R(a)) return {
430
+ kind: "failed",
431
+ retryable: !1,
432
+ outcome: "unknown",
433
+ detail: `media task provider '${t.provider}' returned a task handle that cannot be stored as JSON (a plain object is required); the job cannot be found again`
434
+ };
435
+ if (!await r({
436
+ taskHandle: a,
437
+ taskSubmittedAt: u
438
+ })) return { kind: "stale" };
439
+ l = a;
440
+ }
441
+ if (u !== null && Date.now() - u.getTime() > a.timeoutMs) return {
442
+ kind: "failed",
443
+ retryable: !1,
444
+ detail: `media task ${t.id} is still pending after ${Math.round(a.timeoutMs / 1e3)}s at provider '${t.provider}'; the run is not kept waiting past the task timeout`
445
+ };
446
+ let d = await e.run(i((e) => n.poll(l, {
447
+ ...c,
448
+ abortSignal: e
449
+ })));
450
+ if (d.status === "pending") return {
451
+ kind: "pending",
452
+ delayMs: Math.max(a.pollMs, d.retryAfterMs ?? 0)
453
+ };
454
+ if (d.status === "failed") return {
455
+ kind: "failed",
456
+ retryable: d.retryable === !0,
457
+ detail: `media task provider '${t.provider}' failed the job: ${d.message}`
458
+ };
459
+ await B(e, t, `generate${o.modality[0].toUpperCase()}${o.modality.slice(1)}`, {
460
+ usage: d.usage ?? {},
461
+ providerMetadata: d.providerMetadata
462
+ });
463
+ let f = [];
464
+ for (let [e, t] of d.artifacts.entries()) f.push(await s(e, t));
465
+ return {
466
+ kind: "done",
467
+ payload: {
468
+ artifacts: f,
469
+ usage: d.usage ?? null,
470
+ providerMetadata: d.providerMetadata ?? null
471
+ }
472
+ };
473
+ }, B = async (n, r, i, a) => {
474
+ let o = e(a.providerMetadata);
475
+ await n.run(t(n.store, {
476
+ provider: r.provider,
477
+ model: r.model,
478
+ operation: i,
479
+ agent: r.stepName,
480
+ requestId: r.id,
481
+ attempt: r.attempts,
482
+ usage: a.usage,
483
+ ...r.tenantId === null ? {} : { tenantId: r.tenantId },
484
+ ...o === void 0 ? {} : { actualCostUsd: o },
485
+ ...r.promptId !== null && r.promptDigest !== null ? { prompt: {
486
+ promptId: r.promptId,
487
+ digest: r.promptDigest,
488
+ ...r.promptRevision === null ? {} : { revision: r.promptRevision }
489
+ } } : {}
490
+ }));
491
+ };
492
+ //#endregion
493
+ export { S as DEFAULT_INFERENCE_CONCURRENCY, C as DEFAULT_INFERENCE_POLL_MS, j as DEFAULT_INFERENCE_RETENTION_HOURS, w as DEFAULT_MEDIA_TASK_POLL_MS, T as DEFAULT_MEDIA_TASK_TIMEOUT_MS, N as dispatchInferences };
@@ -0,0 +1,96 @@
1
+ import { id as e, integer as t, json as n, table as r, text as i, timestamp as a } from "@voltro/database";
2
+ import { createHash as o } from "node:crypto";
3
+ //#region src/inferenceQueue.ts
4
+ var s = "_voltro_ai_inferences", c = r(s, {
5
+ id: e({ prefix: "aiinf" }),
6
+ tenantId: i().nullable(),
7
+ executionId: i(),
8
+ workflowName: i(),
9
+ runId: i().nullable(),
10
+ signalName: i(),
11
+ stepName: i(),
12
+ status: i().oneOf([
13
+ "pending",
14
+ "running",
15
+ "succeeded",
16
+ "failed"
17
+ ]).default("pending"),
18
+ kind: i().oneOf([
19
+ "text",
20
+ "object",
21
+ "transcription",
22
+ "media"
23
+ ]).default("text"),
24
+ provider: i(),
25
+ model: i(),
26
+ prompt: i(),
27
+ system: i().nullable(),
28
+ promptId: i().nullable(),
29
+ promptDigest: i().nullable(),
30
+ promptRevision: t().nullable(),
31
+ maxTokens: t().nullable(),
32
+ providerOptions: n().nullable(),
33
+ jsonSchema: n().nullable(),
34
+ transcription: n().nullable(),
35
+ media: n().nullable(),
36
+ taskHandle: n().nullable(),
37
+ taskSubmittedAt: a().nullable(),
38
+ result: n().nullable(),
39
+ errorMessage: i().nullable(),
40
+ attempts: t().default(0),
41
+ fence: t().default(0),
42
+ leaseUntil: a().nullable(),
43
+ claimedBy: i().nullable(),
44
+ queuedAt: a().nullable(),
45
+ enqueuedAt: a().default("now"),
46
+ startedAt: a().nullable(),
47
+ completedAt: a().nullable(),
48
+ durationMs: t().nullable()
49
+ }).index(["status", "enqueuedAt"]).index(["status", "leaseUntil"]).index(["executionId"]).index(["tenantId"]), l = 3e5, u = 4, d = (e, t) => {
50
+ let n = typeof e == "number" ? e : Number(e);
51
+ return Number.isFinite(n) ? Math.trunc(n) : t;
52
+ }, f = (e) => e == null ? null : String(e), p = (e) => {
53
+ if (e instanceof Date) return e;
54
+ if (typeof e == "string" || typeof e == "number") {
55
+ let t = new Date(e);
56
+ return Number.isNaN(t.getTime()) ? null : t;
57
+ }
58
+ return null;
59
+ }, m = (e) => ({
60
+ id: String(e.id),
61
+ tenantId: f(e.tenantId),
62
+ executionId: String(e.executionId),
63
+ workflowName: String(e.workflowName),
64
+ runId: f(e.runId),
65
+ signalName: String(e.signalName),
66
+ stepName: String(e.stepName),
67
+ kind: e.kind === "object" ? "object" : e.kind === "transcription" ? "transcription" : e.kind === "media" ? "media" : "text",
68
+ provider: String(e.provider),
69
+ model: String(e.model),
70
+ prompt: String(e.prompt ?? ""),
71
+ system: f(e.system),
72
+ promptId: f(e.promptId),
73
+ promptDigest: f(e.promptDigest),
74
+ promptRevision: e.promptRevision === null || e.promptRevision === void 0 ? null : d(e.promptRevision, 0),
75
+ maxTokens: e.maxTokens === null || e.maxTokens === void 0 ? null : d(e.maxTokens, 0),
76
+ providerOptions: e.providerOptions ?? null,
77
+ jsonSchema: e.jsonSchema ?? null,
78
+ transcription: e.transcription ?? null,
79
+ media: e.media ?? null,
80
+ taskHandle: typeof e.taskHandle == "object" ? e.taskHandle : null,
81
+ taskSubmittedAt: p(e.taskSubmittedAt),
82
+ attempts: d(e.attempts, 0),
83
+ fence: d(e.fence, 0)
84
+ }), h = (e) => {
85
+ let t = e.attempts + 1;
86
+ return t >= e.maxAttempts ? {
87
+ kind: "give-up",
88
+ attempts: t
89
+ } : {
90
+ kind: "retry",
91
+ attempts: t,
92
+ delayMs: e.retryAfterMs !== void 0 && e.retryAfterMs > 0 ? e.retryAfterMs : Math.min(e.baseDelayMs * 2 ** (t - 1), e.maxDelayMs)
93
+ };
94
+ }, g = (e) => `voltro.ai.infer:${e}`, _ = (e, t) => `aiinf_${o("sha256").update(`${e}\u0000${t}`).digest("hex").slice(0, 40)}`;
95
+ //#endregion
96
+ export { s as AI_INFERENCES_TABLE, u as DEFAULT_INFERENCE_ATTEMPTS, l as DEFAULT_INFERENCE_LEASE_MS, c as aiInferencesTable, h as decideInferenceFailure, g as inferenceSignalName, _ as offloadedInferenceId, m as toQueuedInference };
@@ -0,0 +1,27 @@
1
+ import { jsonSchema as e } from "ai";
2
+ import { Ajv as t } from "ajv";
3
+ import { Ajv2019 as n } from "ajv/dist/2019.js";
4
+ import { Ajv2020 as r } from "ajv/dist/2020.js";
5
+ import i from "ajv-formats";
6
+ //#region src/jsonOutputValidation.ts
7
+ var a = (a) => {
8
+ let o = structuredClone(a), s = {
9
+ strict: !0,
10
+ strictTypes: !1,
11
+ strictTuples: !1,
12
+ strictRequired: !1,
13
+ allowUnionTypes: !0
14
+ }, c = o.$schema, l = c === "https://json-schema.org/draft/2020-12/schema" ? new r(s) : c === "https://json-schema.org/draft/2019-09/schema" ? new n(s) : new t(s);
15
+ i(l);
16
+ let u = l.compile(o);
17
+ if ("$async" in u && u.$async === !0) throw Error("asynchronous output schemas are not supported");
18
+ return e(o, { validate: (e) => u(e) ? {
19
+ success: !0,
20
+ value: e
21
+ } : {
22
+ success: !1,
23
+ error: /* @__PURE__ */ Error("model output does not satisfy the declared JSON Schema")
24
+ } });
25
+ };
26
+ //#endregion
27
+ export { a as validatedOutputSchema };