@voltro/ai 0.74.0 → 0.76.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.
@@ -0,0 +1,1053 @@
1
+ import { c as e, o as t, r as n } from "./provider-BsyDya-H.js";
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, wrapLanguageModel as d } from "ai";
3
+ import { Context as f, Data as p, Effect as m, JSONSchema as h, Metric as g, MetricBoundaries as ee, Runtime as te, Schema as _, Stream as ne } from "effect";
4
+ import { and as v, bigint as re, eq as y, generateId as b, gte as ie, id as x, integer as S, isNull as ae, json as C, queryFor as w, registerRetention as T, retentionTtlMsFromEnv as oe, table as E, text as D, timestamp as O } from "@voltro/database";
5
+ import { Ajv as se } from "ajv";
6
+ import { Ajv2019 as ce } from "ajv/dist/2019.js";
7
+ import { Ajv2020 as le } from "ajv/dist/2020.js";
8
+ import ue from "ajv-formats";
9
+ import { createHash as de } from "node:crypto";
10
+ //#region src/tools.ts
11
+ var fe = (e, t) => e(t), pe = Symbol.for("@voltro/ai/Tool"), me = (e) => ({
12
+ ...e,
13
+ [pe]: !0
14
+ }), he = (e) => typeof e == "object" && !!e && e[pe] === !0, ge = (e) => {
15
+ let t = e.default;
16
+ if (typeof t != "function") return 0;
17
+ let n = 0;
18
+ for (let r of Object.values(e)) he(r) && r.execute === void 0 && r.handler === void 0 && (r.handler = t, n += 1);
19
+ return n;
20
+ }, _e = (e, t, n) => {
21
+ let r = t ?? te.defaultRuntime;
22
+ return te.runPromise(r)(e, n === void 0 ? {} : { signal: n });
23
+ }, ve = (e, t, n) => n ? e.pipe(m.timeoutFail({
24
+ duration: `${n} millis`,
25
+ onTimeout: () => /* @__PURE__ */ Error(`tool '${t}' timed out`)
26
+ })) : e, ye = (e, t, n) => {
27
+ if (e.execute) return _e(ve(fe(e.execute, t), e.name, e.timeoutMs), n.runtime, n.abortSignal);
28
+ if (e.handler) {
29
+ let r = e.handler, i = r(t, n);
30
+ return m.isEffect(i) ? _e(ve(i, e.name, e.timeoutMs), n.runtime, n.abortSignal) : i;
31
+ }
32
+ return Promise.reject(/* @__PURE__ */ Error(`tool '${e.name}' has neither execute nor handler`));
33
+ }, be = (e) => {
34
+ let t = h.make(e);
35
+ return t && t.type === "object" ? t : {
36
+ type: "object",
37
+ properties: {},
38
+ additionalProperties: !1
39
+ };
40
+ }, xe = (e) => {
41
+ let t = e.inputJsonSchema;
42
+ return t === void 0 ? be(e.input) : t.type === "object" ? t : {
43
+ type: "object",
44
+ properties: {},
45
+ additionalProperties: !0
46
+ };
47
+ }, k = (e, t = { store: void 0 }) => {
48
+ let n = {};
49
+ for (let [r, i] of Object.entries(e)) n[i.name || r] = u({
50
+ description: i.description,
51
+ inputSchema: c(xe(i)),
52
+ execute: async (e, n) => {
53
+ let r = t.abortSignal, a = n?.abortSignal, o = r !== void 0 && a !== void 0 && r !== a ? AbortSignal.any([r, a]) : a ?? r;
54
+ o?.throwIfAborted();
55
+ let s = {
56
+ ...t,
57
+ ...n?.toolCallId === void 0 ? {} : { invocationId: n.toolCallId },
58
+ ...o === void 0 ? {} : { abortSignal: o }
59
+ }, c = await m.runPromise(_.decodeUnknown(i.input)(e));
60
+ o?.throwIfAborted();
61
+ let l = await ye(i, c, s);
62
+ return i.output ? m.runPromise(_.decodeUnknown(i.output)(l)) : l;
63
+ }
64
+ });
65
+ return n;
66
+ }, A = class extends _.TaggedError()("AiBudgetExceeded", {
67
+ tenantId: _.NullOr(_.String),
68
+ limitUsd: _.Number,
69
+ spentUsd: _.Number,
70
+ attemptedUsd: _.Number
71
+ }) {}, j = class extends _.TaggedError()("AiBudgetInvalidInput", {
72
+ field: _.Literal("limitUsd", "addUsd", "since", "reservationId", "tenantId"),
73
+ message: _.String
74
+ }) {}, M = class extends _.TaggedError()("AiBudgetReservationConflict", {
75
+ reason: _.Literal("identity-bound", "already-released"),
76
+ message: _.String
77
+ }) {}, N = "_voltro_ai_budget", P = "_voltro_ai_budget_reservations", F = E(N, {
78
+ id: x({ prefix: "aib" }),
79
+ bucket: D().maxLength(191),
80
+ tenantId: D().nullable(),
81
+ reservedMicroUsd: re().default("0").narrowedFrom("integer"),
82
+ updatedAt: O().default("now")
83
+ }).unique("byAiBudgetBucket", ["bucket"]), Se = E(P, {
84
+ id: x({ prefix: "air" }),
85
+ reservationId: D().maxLength(191),
86
+ bucket: D().maxLength(191),
87
+ tenantId: D().nullable(),
88
+ amountMicroUsd: re(),
89
+ releasedAt: O().nullable(),
90
+ updatedAt: O().default("now")
91
+ }).unique("byAiBudgetReservation", ["reservationId"]), I = class extends Error {}, Ce = (e, t, n) => {
92
+ if (!Number.isFinite(e) || e < 0) throw new j({
93
+ field: t,
94
+ message: `${t} must be finite and non-negative`
95
+ });
96
+ let r = e * 1e6, i = n === "up" ? Math.ceil(r) : Math.floor(r);
97
+ if (!Number.isSafeInteger(i)) throw new j({
98
+ field: t,
99
+ message: `${t} exceeds the safe micro-USD range`
100
+ });
101
+ return BigInt(i);
102
+ }, L = (e) => {
103
+ if (typeof e == "number" && !Number.isSafeInteger(e)) throw Error("AI budget counter is not an exact integer");
104
+ let t = String(e);
105
+ if (!/^(0|[1-9][0-9]*)$/.test(t)) throw Error("AI budget counter is invalid; refusing to assume zero");
106
+ return BigInt(t);
107
+ }, we = (e) => {
108
+ if (typeof e != "string" || e.length === 0 || e.length > 191) throw new j({
109
+ field: "reservationId",
110
+ message: "AI budget reservationId must contain 1–191 characters"
111
+ });
112
+ return e;
113
+ }, Te = () => {
114
+ let e = oe(process.env.VOLTRO_AI_USAGE_TTL_HOURS, 8760);
115
+ for (let t of [N, P]) T({
116
+ source: "plugin",
117
+ table: t,
118
+ timeColumn: "updatedAt",
119
+ ttlMs: e
120
+ });
121
+ }, Ee = async (e, t) => {
122
+ for (let n = 0;; n++) try {
123
+ return await e.transactional(t);
124
+ } catch (e) {
125
+ if (!(e instanceof I) || n >= 31) throw e;
126
+ await new Promise((e) => setTimeout(e, n + 1));
127
+ }
128
+ }, De = (e) => e instanceof A || e instanceof j || e instanceof M ? m.fail(e) : m.die(e), Oe = (e) => m.tryPromise({
129
+ try: e,
130
+ catch: (e) => e
131
+ }).pipe(m.catchAll(De)), ke = (e, t) => m.gen(function* () {
132
+ let { limit: n, amount: r, tenantId: i, bucket: a, reservationId: o } = yield* m.try({
133
+ try: () => {
134
+ let e = Ce(t.limitUsd, "limitUsd", "down"), n = Ce(t.addUsd ?? 0, "addUsd", "up"), r = t.tenantId ?? null;
135
+ if (t.since !== void 0 && (!(t.since instanceof Date) || !Number.isFinite(t.since.getTime()))) throw new j({
136
+ field: "since",
137
+ message: "AI budget since must be a valid Date"
138
+ });
139
+ let i = `${r ?? "global"}::${t.since === void 0 ? "all" : t.since.getTime()}`;
140
+ if (i.length > 191) throw new j({
141
+ field: "tenantId",
142
+ message: "AI budget tenant/window key exceeds 191 characters"
143
+ });
144
+ return {
145
+ limit: e,
146
+ amount: n,
147
+ tenantId: r,
148
+ bucket: i,
149
+ reservationId: we(t.reservationId ?? b({
150
+ kind: "typeid",
151
+ prefix: "air"
152
+ }, "_voltro_ai_budget_reservations"))
153
+ };
154
+ },
155
+ catch: (e) => e
156
+ }).pipe(m.catchAll(De));
157
+ Te();
158
+ let s = async (e) => {
159
+ let [t] = await e.query(w(F).where(y("bucket", a)).descriptor);
160
+ if (t && t.tenantId !== i) throw Error("AI budget bucket belongs to a different tenant");
161
+ return t;
162
+ }, c = (e) => {
163
+ if (r === 0n ? e >= n : e + r > n) throw new A({
164
+ tenantId: i,
165
+ limitUsd: t.limitUsd,
166
+ spentUsd: Number(e) / 1e6,
167
+ attemptedUsd: t.addUsd ?? 0
168
+ });
169
+ };
170
+ return r === 0n ? yield* Oe(async () => {
171
+ let t = await s(e);
172
+ return c(t ? L(t.reservedMicroUsd) : 0n), null;
173
+ }) : yield* Oe(() => Ee(e, async (e) => {
174
+ let t = b({
175
+ kind: "typeid",
176
+ prefix: "air"
177
+ }, P), n = /* @__PURE__ */ new Date(), l = await e.insertIgnore(P, {
178
+ id: t,
179
+ reservationId: o,
180
+ bucket: a,
181
+ tenantId: i,
182
+ amountMicroUsd: String(r),
183
+ releasedAt: null,
184
+ updatedAt: n
185
+ }, { conflictColumns: ["reservationId"] });
186
+ if (l.id !== t) {
187
+ if (l.tenantId !== i || l.bucket !== a || L(l.amountMicroUsd) !== r) throw new M({
188
+ reason: "identity-bound",
189
+ message: "AI budget reservationId is already bound to another tenant, amount or window"
190
+ });
191
+ if (l.releasedAt !== null) throw new M({
192
+ reason: "already-released",
193
+ message: "AI budget reservation was released; new spend requires a new reservationId"
194
+ });
195
+ return {
196
+ reservationId: o,
197
+ tenantId: i,
198
+ amountMicroUsd: String(r),
199
+ status: "replayed"
200
+ };
201
+ }
202
+ let u = await s(e), d = u ? L(u.reservedMicroUsd) : 0n;
203
+ if (c(d), u) {
204
+ if (await e.updateMany("_voltro_ai_budget", {
205
+ reservedMicroUsd: String(d + r),
206
+ updatedAt: n
207
+ }, { where: v(y("id", u.id), y("reservedMicroUsd", u.reservedMicroUsd)) }) !== 1) throw new I("AI budget counter changed; discard this receipt and retry");
208
+ } else {
209
+ let t = b({
210
+ kind: "typeid",
211
+ prefix: "aib"
212
+ }, N);
213
+ if ((await e.insertIgnore("_voltro_ai_budget", {
214
+ id: t,
215
+ bucket: a,
216
+ tenantId: i,
217
+ reservedMicroUsd: String(r),
218
+ updatedAt: n
219
+ }, { conflictColumns: ["bucket"] })).id !== t) throw new I("AI budget counter was created concurrently; discard this receipt and retry");
220
+ }
221
+ return {
222
+ reservationId: o,
223
+ tenantId: i,
224
+ amountMicroUsd: String(r),
225
+ status: "reserved"
226
+ };
227
+ }));
228
+ }), Ae = (e, t) => m.gen(function* () {
229
+ return yield* m.try({
230
+ try: () => we(t.reservationId),
231
+ catch: (e) => e
232
+ }).pipe(m.catchAll((e) => e instanceof j ? m.fail(e) : m.die(e))), yield* m.promise(() => Ee(e, async (e) => {
233
+ let n = w(Se).where(v(y("reservationId", t.reservationId), t.tenantId === null ? ae("tenantId") : y("tenantId", t.tenantId))).descriptor, [r] = await e.query(n);
234
+ if (!r) return "not-found";
235
+ if (r.releasedAt !== null) return "already-released";
236
+ let i = /* @__PURE__ */ new Date();
237
+ if (await e.updateMany("_voltro_ai_budget_reservations", {
238
+ releasedAt: i,
239
+ updatedAt: i
240
+ }, { where: v(y("id", r.id), ae("releasedAt")) }) !== 1) {
241
+ let [t] = await e.query(n);
242
+ if (t !== void 0 && t.releasedAt !== null) return "already-released";
243
+ throw new I("AI budget release raced; retry");
244
+ }
245
+ let [a] = await e.query(w(F).where(y("bucket", r.bucket)).descriptor);
246
+ if (!a || a.tenantId !== t.tenantId) throw Error("AI budget counter missing or mismatched; refusing unproved credit");
247
+ let o = L(a.reservedMicroUsd), s = L(r.amountMicroUsd);
248
+ if (s > o) throw Error("AI budget receipt exceeds its counter; refusing unproved credit");
249
+ if (await e.updateMany("_voltro_ai_budget", {
250
+ reservedMicroUsd: String(o - s),
251
+ updatedAt: i
252
+ }, { where: v(y("id", a.id), y("reservedMicroUsd", a.reservedMicroUsd)) }) !== 1) throw new I("AI budget counter changed; discard this release and retry");
253
+ return "released";
254
+ }));
255
+ }), je = {
256
+ "claude-opus-4-8": {
257
+ inputPer1M: 15,
258
+ outputPer1M: 75
259
+ },
260
+ "claude-opus-4-6": {
261
+ inputPer1M: 15,
262
+ outputPer1M: 75
263
+ },
264
+ "claude-sonnet-4-6": {
265
+ inputPer1M: 3,
266
+ outputPer1M: 15
267
+ },
268
+ "claude-haiku-4-5": {
269
+ inputPer1M: 1,
270
+ outputPer1M: 5
271
+ },
272
+ "claude-haiku-4-5-20251001": {
273
+ inputPer1M: 1,
274
+ outputPer1M: 5
275
+ },
276
+ "gpt-5.5": {
277
+ inputPer1M: 5,
278
+ outputPer1M: 30
279
+ },
280
+ "gpt-4o": {
281
+ inputPer1M: 2.5,
282
+ outputPer1M: 10
283
+ },
284
+ "gpt-4o-mini": {
285
+ inputPer1M: .15,
286
+ outputPer1M: .6
287
+ },
288
+ "gemini-2.5-pro": {
289
+ inputPer1M: 1.25,
290
+ outputPer1M: 10
291
+ },
292
+ "gemini-2.5-flash": {
293
+ inputPer1M: .3,
294
+ outputPer1M: 2.5
295
+ },
296
+ "gemini-2.0-flash": {
297
+ inputPer1M: .1,
298
+ outputPer1M: .4
299
+ }
300
+ }, R = {}, Me = (e) => {
301
+ let t = R;
302
+ return R = { ...e }, t;
303
+ }, Ne = () => ({
304
+ ...je,
305
+ ...R
306
+ }), Pe = (e) => {
307
+ let t = Ne();
308
+ if (t[e] !== void 0) return t[e];
309
+ let n = e.indexOf("/");
310
+ if (n > 0) {
311
+ let r = e.slice(n + 1);
312
+ if (t[r] !== void 0) return t[r];
313
+ }
314
+ }, z = (e) => typeof e.unit == "string", Fe = (e) => z(e) ? {
315
+ unit: e.unit,
316
+ input: e.input ?? 0,
317
+ output: e.output ?? 0
318
+ } : {
319
+ unit: "tokens",
320
+ input: e.inputTokens ?? 0,
321
+ output: e.outputTokens ?? 0
322
+ }, Ie = (e, t) => {
323
+ let { unit: n, input: r, output: i } = Fe(e);
324
+ if (t.actualCostUsd !== void 0) {
325
+ if (!Number.isFinite(t.actualCostUsd) || t.actualCostUsd < 0) throw RangeError("estimateCostUsd: actualCostUsd must be a finite, non-negative USD amount.");
326
+ let e = r + i, a = e > 0 ? r / e : 0;
327
+ return {
328
+ inputTokens: r,
329
+ outputTokens: i,
330
+ inputCostUsd: t.actualCostUsd * a,
331
+ outputCostUsd: t.actualCostUsd * (1 - a),
332
+ totalCostUsd: t.actualCostUsd,
333
+ costSource: "gateway",
334
+ unit: n
335
+ };
336
+ }
337
+ if (n !== "tokens" && t.price === void 0) return {
338
+ inputTokens: r,
339
+ outputTokens: i,
340
+ inputCostUsd: 0,
341
+ outputCostUsd: 0,
342
+ totalCostUsd: 0,
343
+ costSource: "unpriced",
344
+ unit: n
345
+ };
346
+ let a = t.price ?? Pe(t.model) ?? {
347
+ inputPer1M: 0,
348
+ outputPer1M: 0
349
+ }, o = r / 1e6 * a.inputPer1M, s = i / 1e6 * a.outputPer1M;
350
+ return {
351
+ inputTokens: r,
352
+ outputTokens: i,
353
+ inputCostUsd: o,
354
+ outputCostUsd: s,
355
+ totalCostUsd: o + s,
356
+ costSource: "estimated",
357
+ unit: n
358
+ };
359
+ }, B = "_voltro_ai_usage", Le = E(B, {
360
+ id: x({ prefix: "aiu" }),
361
+ tenantId: D().nullable(),
362
+ provider: D(),
363
+ model: D(),
364
+ operation: D(),
365
+ agent: D().nullable(),
366
+ inputTokens: S().default(0),
367
+ outputTokens: S().default(0),
368
+ costMicroUsd: S().default(0),
369
+ costSource: D().default("estimated"),
370
+ unit: D().default("tokens"),
371
+ promptId: D().nullable(),
372
+ promptDigest: D().nullable(),
373
+ promptRevision: S().nullable(),
374
+ requestId: D().maxLength(191).nullable(),
375
+ attempt: S().nullable(),
376
+ receiptKey: D().maxLength(191).backfill((e) => `aiu-pre-receipt-${String(e.id)}`),
377
+ calledAt: O().default("now")
378
+ }).index(["tenantId"]).index(["promptDigest"]).unique("byAiUsageReceipt", ["receiptKey"]), Re = (e) => {
379
+ 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;
380
+ return Number.isFinite(r) && r >= 0 ? r : void 0;
381
+ }, ze = class extends p.TaggedError("AiUsageReceiptConflict") {
382
+ get message() {
383
+ let e = Object.keys(this.recorded).filter((e) => this.recorded[e] !== this.attempted[e]).map((e) => `${e} ${String(this.recorded[e])} → ${String(this.attempted[e])}`);
384
+ return `AI usage receipt ${this.receiptKey} was recorded again with different values (${e.join(", ")}). A replay of the same paid call has the same values; the row keeps what was recorded first.`;
385
+ }
386
+ }, Be = class extends p.TaggedError("AiUsageLedgerError") {
387
+ get message() {
388
+ return `AI usage receipt ${this.receiptKey} could not be written: ${this.cause instanceof Error ? this.cause.message : String(this.cause)}`;
389
+ }
390
+ }, Ve = (e) => ({
391
+ tenantId: e.tenantId ?? null,
392
+ provider: String(e.provider),
393
+ model: String(e.model),
394
+ operation: String(e.operation),
395
+ inputTokens: Number(e.inputTokens),
396
+ outputTokens: Number(e.outputTokens),
397
+ costMicroUsd: Number(e.costMicroUsd)
398
+ }), He = (e, t) => (T({
399
+ source: "plugin",
400
+ table: B,
401
+ timeColumn: "calledAt",
402
+ ttlMs: oe(process.env.VOLTRO_AI_USAGE_TTL_HOURS, 8760)
403
+ }), m.gen(function* () {
404
+ let n = Ie(t.usage, {
405
+ model: t.model,
406
+ ...t.price === void 0 ? {} : { price: t.price },
407
+ ...t.actualCostUsd === void 0 ? {} : { actualCostUsd: t.actualCostUsd }
408
+ }), r = t.receiptKey ?? (t.requestId === void 0 ? b({
409
+ kind: "typeid",
410
+ prefix: "aiu"
411
+ }, "_voltro_ai_usage") : `${t.requestId}#${t.attempt ?? 0}`), i = {
412
+ tenantId: t.tenantId ?? null,
413
+ provider: t.provider,
414
+ model: t.model,
415
+ operation: t.operation,
416
+ agent: t.agent ?? null,
417
+ inputTokens: n.inputTokens,
418
+ outputTokens: n.outputTokens,
419
+ costMicroUsd: Math.round(n.totalCostUsd * 1e6),
420
+ costSource: n.costSource,
421
+ unit: n.unit,
422
+ promptId: t.prompt?.promptId ?? null,
423
+ promptDigest: t.prompt?.digest ?? null,
424
+ promptRevision: t.prompt?.revision ?? null,
425
+ requestId: t.requestId ?? null,
426
+ attempt: t.attempt ?? null,
427
+ receiptKey: r,
428
+ calledAt: t.calledAt ?? /* @__PURE__ */ new Date()
429
+ }, a = yield* m.tryPromise({
430
+ try: () => e.insertIgnoreWithOutcome(B, i, { conflictColumns: ["receiptKey"] }),
431
+ catch: (e) => new Be({
432
+ receiptKey: String(r),
433
+ cause: e
434
+ })
435
+ });
436
+ if (a.outcome === "inserted") return {
437
+ ...n,
438
+ receipt: "recorded"
439
+ };
440
+ let o = Ve(a.row), s = Ve(i);
441
+ return Object.keys(o).some((e) => o[e] !== s[e]) ? yield* m.fail(new ze({
442
+ receiptKey: String(r),
443
+ recorded: o,
444
+ attempted: s
445
+ })) : {
446
+ ...Ue(a.row, n),
447
+ receipt: "replayed"
448
+ };
449
+ })), Ue = (e, t) => {
450
+ let n = Number(e.costMicroUsd) / 1e6;
451
+ return {
452
+ ...t,
453
+ inputTokens: Number(e.inputTokens),
454
+ outputTokens: Number(e.outputTokens),
455
+ totalCostUsd: n,
456
+ costSource: e.costSource ?? t.costSource
457
+ };
458
+ }, We = (e, t) => He(e, t).pipe(m.asVoid, m.catchAllCause((e) => m.logError("AI usage NOT booked as recorded — the call itself succeeded and was returned", e).pipe(m.annotateLogs({
459
+ scope: "voltro:ai:usage",
460
+ provider: t.provider,
461
+ model: t.model,
462
+ operation: t.operation,
463
+ ...z(t.usage) ? {
464
+ unit: t.usage.unit,
465
+ input: t.usage.input ?? null,
466
+ output: t.usage.output ?? null
467
+ } : {
468
+ inputTokens: t.usage.inputTokens ?? null,
469
+ outputTokens: t.usage.outputTokens ?? null
470
+ },
471
+ ...t.requestId === void 0 ? {} : {
472
+ requestId: t.requestId,
473
+ attempt: t.attempt ?? 0
474
+ },
475
+ ...t.actualCostUsd === void 0 ? {} : { actualCostUsd: t.actualCostUsd }
476
+ })))), Ge = (e, t = {}) => m.promise(async () => {
477
+ let n = [
478
+ ...t.tenantId === void 0 ? [] : [y("tenantId", t.tenantId)],
479
+ ...t.since === void 0 ? [] : [ie("calledAt", t.since)],
480
+ ...t.promptDigest === void 0 ? [] : [y("promptDigest", t.promptDigest)]
481
+ ], r = w(Le), i = n.length === 0 ? r : r.where(n.length === 1 ? n[0] : v(...n));
482
+ return (await e.query(i.descriptor)).reduce((e, t) => e + (Number(t.costMicroUsd) || 0), 0) / 1e6;
483
+ }), Ke = ee.exponential({
484
+ start: .001,
485
+ factor: 2,
486
+ count: 16
487
+ }), V = g.counter("voltro_ai_calls_total", { description: "Total AI provider calls (generate + stream)." }), qe = g.counter("voltro_ai_call_errors_total", { description: "AI provider calls that errored." }), H = g.histogram("voltro_ai_call_duration_seconds", Ke, "AI provider call duration in seconds."), Je = g.counter("voltro_ai_input_tokens_total", {
488
+ description: "Total prompt (input) tokens across AI calls.",
489
+ incremental: !0
490
+ }), Ye = g.counter("voltro_ai_output_tokens_total", {
491
+ description: "Total completion (output) tokens across AI calls.",
492
+ incremental: !0
493
+ }), Xe = g.counter("voltro_ai_cost_microusd_total", {
494
+ description: "Total estimated AI spend in micro-USD (USD × 1e6).",
495
+ incremental: !0
496
+ }), U = (e, t) => ({
497
+ provider: e.name,
498
+ model: e.model ?? e.name,
499
+ operation: t
500
+ }), W = (e, t, n) => e.pipe(m.tagMetrics("provider", t.provider), m.tagMetrics("model", t.model), m.tagMetrics("operation", t.operation), m.tagMetrics("status", n)), Ze = (e, t) => {
501
+ let n = t.inputTokens ?? 0, r = t.outputTokens ?? 0, i = Ie({
502
+ inputTokens: n,
503
+ outputTokens: r
504
+ }, { model: e.model }), a = Math.round(i.totalCostUsd * 1e6);
505
+ return m.all([
506
+ W(g.incrementBy(Je, n), e, "ok"),
507
+ W(g.incrementBy(Ye, r), e, "ok"),
508
+ W(g.incrementBy(Xe, a), e, "ok")
509
+ ], { discard: !0 });
510
+ }, G = (e, t, n) => m.gen(function* () {
511
+ let r = yield* m.clockWith((e) => e.currentTimeMillis);
512
+ return yield* n.pipe(m.tap((n) => Ze(e, t(n))), m.tap(() => W(g.increment(V), e, "ok").pipe(m.zipRight(m.clockWith((e) => e.currentTimeMillis).pipe(m.flatMap((t) => W(g.update(H, (t - r) / 1e3), e, "ok")))))), m.tapError(() => W(g.increment(V), e, "error").pipe(m.zipRight(W(g.increment(qe), e, "error")), m.zipRight(m.clockWith((e) => e.currentTimeMillis).pipe(m.flatMap((t) => W(g.update(H, (t - r) / 1e3), e, "error")))))), m.withSpan("voltro.ai.call", { attributes: {
513
+ "ai.provider": e.provider,
514
+ "ai.model": e.model,
515
+ "ai.operation": e.operation
516
+ } }));
517
+ }), Qe = (e, t) => {
518
+ let n = Date.now();
519
+ return t.pipe(ne.tap((t) => t._tag === "done" ? W(g.increment(V), e, "ok").pipe(m.zipRight(W(g.update(H, (Date.now() - n) / 1e3), e, "ok")), m.zipRight(Ze(e, t.usage ?? {}))) : t._tag === "error" ? W(g.increment(V), e, "error").pipe(m.zipRight(W(g.increment(qe), e, "error")), m.zipRight(W(g.update(H, (Date.now() - n) / 1e3), e, "error"))) : m.void), ne.withSpan("voltro.ai.call", { attributes: {
520
+ "ai.provider": e.provider,
521
+ "ai.model": e.model,
522
+ "ai.operation": e.operation
523
+ } }));
524
+ }, $e = (e) => {
525
+ let t = structuredClone(e), n = {
526
+ strict: !0,
527
+ strictTypes: !1,
528
+ strictTuples: !1,
529
+ strictRequired: !1,
530
+ allowUnionTypes: !0
531
+ }, r = t.$schema, i = r === "https://json-schema.org/draft/2020-12/schema" ? new le(n) : r === "https://json-schema.org/draft/2019-09/schema" ? new ce(n) : new se(n);
532
+ ue(i);
533
+ let a = i.compile(t);
534
+ if ("$async" in a && a.$async === !0) throw Error("asynchronous output schemas are not supported");
535
+ return c(t, { validate: (e) => a(e) ? {
536
+ success: !0,
537
+ value: e
538
+ } : {
539
+ success: !1,
540
+ error: /* @__PURE__ */ Error("model output does not satisfy the declared JSON Schema")
541
+ } });
542
+ }, et = _.Number.pipe(_.int(), _.nonNegative(), _.lessThanOrEqualTo(2 ** 53 - 1)), tt = _.Struct({
543
+ provider: _.String,
544
+ model: _.String,
545
+ usage: _.Struct({
546
+ inputTokens: _.optional(et),
547
+ outputTokens: _.optional(et),
548
+ totalTokens: _.optional(et),
549
+ completeness: _.Literal("complete", "partial", "unknown")
550
+ }),
551
+ cost: _.Union(_.Struct({
552
+ status: _.Literal("actual"),
553
+ source: _.Literal("gateway"),
554
+ usd: _.Number.pipe(_.finite(), _.nonNegative())
555
+ }), _.Struct({
556
+ status: _.Literal("unknown"),
557
+ source: _.Literal("unreported")
558
+ }))
559
+ }), nt = (e) => typeof e == "number" && Number.isSafeInteger(e) && e >= 0 ? e : void 0, K = (e, t, n, r) => {
560
+ let i = typeof n == "object" && n ? n : {}, a = nt("inputTokens" in i ? i.inputTokens : void 0), o = nt("outputTokens" in i ? i.outputTokens : void 0), s = nt("totalTokens" in i ? i.totalTokens : void 0), c = [
561
+ a,
562
+ o,
563
+ s
564
+ ].filter((e) => e !== void 0).length, l = Re(r);
565
+ return {
566
+ provider: e,
567
+ model: t,
568
+ usage: {
569
+ ...a === void 0 ? {} : { inputTokens: a },
570
+ ...o === void 0 ? {} : { outputTokens: o },
571
+ ...s === void 0 ? {} : { totalTokens: s },
572
+ completeness: c === 3 ? "complete" : c === 0 ? "unknown" : "partial"
573
+ },
574
+ cost: l === void 0 ? {
575
+ status: "unknown",
576
+ source: "unreported"
577
+ } : {
578
+ status: "actual",
579
+ source: "gateway",
580
+ usd: l
581
+ }
582
+ };
583
+ }, rt = (e, t) => {
584
+ let n = [];
585
+ return {
586
+ model: d({
587
+ model: t,
588
+ middleware: {
589
+ specificationVersion: "v4",
590
+ wrapGenerate: async ({ doGenerate: r }) => {
591
+ let i = await r(), a = i.usage.inputTokens.total, o = i.usage.outputTokens.total;
592
+ return n.push(K(e, t.modelId, {
593
+ inputTokens: a,
594
+ outputTokens: o,
595
+ totalTokens: a !== void 0 && o !== void 0 ? a + o : void 0
596
+ }, i.providerMetadata)), i;
597
+ }
598
+ }
599
+ }),
600
+ evidence: (r) => {
601
+ if (n.length === 0) return K(e, t.modelId, r);
602
+ let i = (e) => {
603
+ let t = 0;
604
+ for (let r of n) {
605
+ let n = r.usage[e];
606
+ if (n === void 0) return;
607
+ t += n;
608
+ }
609
+ return t;
610
+ }, a = 0;
611
+ for (let e of n) {
612
+ if (e.cost.status !== "actual") {
613
+ a = void 0;
614
+ break;
615
+ }
616
+ a += e.cost.usd;
617
+ }
618
+ return K(e, t.modelId, {
619
+ inputTokens: i("inputTokens"),
620
+ outputTokens: i("outputTokens"),
621
+ totalTokens: i("totalTokens")
622
+ }, a === void 0 ? void 0 : { gateway: { cost: a } });
623
+ }
624
+ };
625
+ }, q = class extends _.TaggedError()("AiError", {
626
+ reason: _.Literal("generation", "decode"),
627
+ message: _.String,
628
+ evidence: _.optional(tt)
629
+ }) {}, J = (e, t = {}) => {
630
+ let n = String(e?.message ?? e), r = it(e), i = new q({
631
+ reason: "generation",
632
+ message: `${t.prefix === void 0 ? "" : `${t.prefix}: `}${n}${r.length > 0 ? ` (${r.join(" <- ")})` : ""}`,
633
+ ...t.evidence === void 0 ? {} : { evidence: t.evidence }
634
+ });
635
+ return Object.defineProperty(i, "cause", {
636
+ value: e,
637
+ enumerable: !1,
638
+ configurable: !0,
639
+ writable: !0
640
+ }), i;
641
+ }, it = (e) => {
642
+ let t = [], n = e;
643
+ for (let e = 0; e < 8 && typeof n == "object" && n; e++) {
644
+ let e = n;
645
+ typeof e.code == "string" && e.code.length > 0 && !t.includes(e.code) && t.push(e.code), n = typeof e.lastError == "object" && e.lastError !== null ? e.lastError : e.cause;
646
+ }
647
+ return t;
648
+ }, at = (e, t, n) => {
649
+ let r = [e, ...t ?? []], i = (e) => n(r[e]).pipe(m.catchTag("AiError", (t) => t.reason === "generation" && e + 1 < r.length ? i(e + 1) : m.fail(t)));
650
+ return i(0);
651
+ }, ot = (e) => m.gen(function* () {
652
+ let r = e.messages === void 0 ? e.prompt === void 0 ? void 0 : { prompt: e.prompt } : { messages: [...e.messages] };
653
+ if (r === void 0 || e.prompt !== void 0 && e.messages !== void 0) return yield* m.fail(new q({
654
+ reason: "generation",
655
+ message: "generateText: supply exactly one of prompt or messages"
656
+ }));
657
+ let i = e.tools === void 0 ? void 0 : yield* m.runtime(), a = e.tools === void 0 || i === void 0 ? void 0 : k(e.tools, {
658
+ store: void 0,
659
+ ...e.toolContext,
660
+ ...e.abortSignal === void 0 ? {} : { abortSignal: e.abortSignal },
661
+ runtime: i
662
+ });
663
+ return yield* at(e.provider ?? n(), e.fallbacks, (n) => G(U(n, "generateText"), (e) => e.usage, m.tryPromise({
664
+ try: async () => {
665
+ let i = t(n), o = await s({
666
+ model: i,
667
+ ...r,
668
+ ...e.abortSignal === void 0 ? {} : { abortSignal: e.abortSignal },
669
+ ...a === void 0 ? {} : {
670
+ tools: a,
671
+ stopWhen: l(e.maxSteps ?? 8)
672
+ },
673
+ ...e.system === void 0 ? {} : { system: e.system },
674
+ ...e.maxTokens === void 0 ? {} : { maxOutputTokens: e.maxTokens },
675
+ ...e.temperature === void 0 ? {} : { temperature: e.temperature },
676
+ ...e.providerOptions === void 0 ? {} : { providerOptions: e.providerOptions }
677
+ }), c = a !== void 0 && o.totalUsage !== void 0 ? o.totalUsage : o.usage;
678
+ return {
679
+ text: o.text,
680
+ sources: o.sources,
681
+ usage: {
682
+ inputTokens: c.inputTokens,
683
+ outputTokens: c.outputTokens,
684
+ totalTokens: c.totalTokens
685
+ },
686
+ providerMetadata: o.providerMetadata
687
+ };
688
+ },
689
+ catch: (e) => J(e)
690
+ })));
691
+ }), st = (e, t) => m.gen(function* () {
692
+ let n = h.make(e);
693
+ if (n?.type !== "object") {
694
+ let e = n?.anyOf === void 0 ? `type:${JSON.stringify(n?.type ?? null)}` : "anyOf (e.g. Schema.Struct({}) or a union)";
695
+ return yield* m.fail(new q({
696
+ reason: "generation",
697
+ message: `${t}: the output schema must render as a top-level JSON object (type:"object"), but got ${e}. Use a Schema.Struct({ ... }) as the output schema — wrap arrays/scalars in a field (e.g. Schema.Struct({ items: Schema.Array(...) })).`
698
+ }));
699
+ }
700
+ return n;
701
+ }), ct = (e, t) => st(e, t), lt = (e) => at(e.provider ?? n(), e.fallbacks, (n) => G(U(n, "generateObject"), (e) => e.usage, m.gen(function* () {
702
+ let i = yield* m.try({
703
+ try: () => $e(e.jsonSchema),
704
+ catch: () => new q({
705
+ reason: "decode",
706
+ message: "generateObjectJson: invalid or unsupported output JSON Schema; no provider call was made"
707
+ })
708
+ }), a = rt(n.name, t(n)), s = a.model, c = yield* m.tryPromise({
709
+ try: () => o({
710
+ model: s,
711
+ schema: i,
712
+ prompt: e.prompt,
713
+ ...e.system === void 0 ? {} : { system: e.system },
714
+ ...e.maxTokens === void 0 ? {} : { maxOutputTokens: e.maxTokens },
715
+ ...e.temperature === void 0 ? {} : { temperature: e.temperature },
716
+ ...e.providerOptions === void 0 ? {} : { providerOptions: e.providerOptions }
717
+ }),
718
+ catch: (e) => r.isInstance(e) ? new q({
719
+ reason: "decode",
720
+ message: "model output failed JSON Schema validation",
721
+ evidence: a.evidence(e.usage)
722
+ }) : J(e, {
723
+ prefix: "structured provider call failed",
724
+ evidence: K(n.name, s.modelId, void 0)
725
+ })
726
+ });
727
+ return {
728
+ object: c.object,
729
+ evidence: K(n.name, s.modelId, c.usage, c.providerMetadata),
730
+ usage: {
731
+ inputTokens: c.usage.inputTokens,
732
+ outputTokens: c.usage.outputTokens,
733
+ totalTokens: c.usage.totalTokens
734
+ },
735
+ providerMetadata: c.providerMetadata
736
+ };
737
+ }))), ut = (e) => m.gen(function* () {
738
+ let t = yield* lt({
739
+ jsonSchema: yield* st(e.schema, "generateObject"),
740
+ prompt: e.prompt,
741
+ ...e.system === void 0 ? {} : { system: e.system },
742
+ ...e.provider === void 0 ? {} : { provider: e.provider },
743
+ ...e.fallbacks === void 0 ? {} : { fallbacks: e.fallbacks },
744
+ ...e.maxTokens === void 0 ? {} : { maxTokens: e.maxTokens },
745
+ ...e.temperature === void 0 ? {} : { temperature: e.temperature },
746
+ ...e.providerOptions === void 0 ? {} : { providerOptions: e.providerOptions }
747
+ }), n = yield* _.decodeUnknown(e.schema)(t.object).pipe(m.mapError(() => new q({
748
+ reason: "decode",
749
+ message: "model output failed schema decode",
750
+ evidence: t.evidence
751
+ })));
752
+ return {
753
+ ...t,
754
+ object: n
755
+ };
756
+ }), dt = (e) => m.gen(function* () {
757
+ let a = yield* m.runtime(), o = yield* st(e.schema, "generateObjectWithTools"), u = {
758
+ store: void 0,
759
+ ...e.toolContext,
760
+ ...e.abortSignal === void 0 ? {} : { abortSignal: e.abortSignal },
761
+ runtime: a
762
+ }, d = k(e.tools, u);
763
+ return yield* at(e.provider ?? n(), e.fallbacks, (n) => G(U(n, "generateObjectWithTools"), (e) => e.usage, m.gen(function* () {
764
+ let a = rt(n.name, t(n)), u = a.model, f = yield* m.tryPromise({
765
+ try: () => s({
766
+ model: u,
767
+ prompt: e.prompt,
768
+ tools: d,
769
+ ...e.abortSignal === void 0 ? {} : { abortSignal: e.abortSignal },
770
+ stopWhen: l(e.maxSteps ?? 8),
771
+ output: i.object({ schema: c(o) }),
772
+ ...e.system === void 0 ? {} : { system: e.system },
773
+ ...e.maxTokens === void 0 ? {} : { maxOutputTokens: e.maxTokens },
774
+ ...e.temperature === void 0 ? {} : { temperature: e.temperature },
775
+ ...e.providerOptions === void 0 ? {} : { providerOptions: e.providerOptions }
776
+ }),
777
+ catch: (e) => r.isInstance(e) ? new q({
778
+ reason: "decode",
779
+ message: "model output failed structured decode",
780
+ evidence: a.evidence(e.usage)
781
+ }) : J(e, {
782
+ prefix: "structured provider call failed",
783
+ evidence: K(n.name, u.modelId, void 0)
784
+ })
785
+ }), p = f.totalUsage, h = a.evidence(p), g = yield* m.try({
786
+ try: () => f.output,
787
+ catch: () => new q({
788
+ reason: "decode",
789
+ message: "model output failed structured decode",
790
+ evidence: h
791
+ })
792
+ });
793
+ return {
794
+ object: yield* _.decodeUnknown(e.schema)(g).pipe(m.mapError(() => new q({
795
+ reason: "decode",
796
+ message: "model output failed schema decode",
797
+ evidence: h
798
+ }))),
799
+ evidence: h,
800
+ usage: {
801
+ inputTokens: p.inputTokens,
802
+ outputTokens: p.outputTokens,
803
+ totalTokens: p.totalTokens
804
+ },
805
+ providerMetadata: f.providerMetadata
806
+ };
807
+ })));
808
+ }), ft = class extends f.Tag("@voltro/AiService")() {}, pt = {
809
+ generateText: (e) => ot(e),
810
+ generateObject: (e) => ut(e)
811
+ }, mt = async (e, t) => {
812
+ if ("bytes" in e) return {
813
+ audio: e.bytes,
814
+ mediaType: e.mediaType
815
+ };
816
+ if ("url" in e) {
817
+ let t = await fetch(e.url);
818
+ if (!t.ok) throw Error(`transcribe: GET ${e.url} answered ${t.status}.`);
819
+ let n = t.headers.get("content-type") ?? void 0;
820
+ return {
821
+ audio: new Uint8Array(await t.arrayBuffer()),
822
+ ...n === void 0 ? {} : { mediaType: n }
823
+ };
824
+ }
825
+ if (t === void 0) throw Error("transcribe: `source.storageRef` needs a `resolveRef` to turn the reference into bytes.\n → pass `resolveRef: (ref) => storage.read(ref)`. It is injected rather than imported so @voltro/ai does not depend on storage; the app owns tenancy and signing for that read.");
826
+ let { bytes: n, mediaType: r } = await t(e.storageRef);
827
+ return {
828
+ audio: n,
829
+ mediaType: r
830
+ };
831
+ }, ht = (e) => {
832
+ if (!Array.isArray(e) || e.length === 0) return;
833
+ let t = [];
834
+ for (let n of e) {
835
+ let e = typeof n.startSecond == "number" ? n.startSecond : typeof n.start == "number" ? n.start : void 0, r = typeof n.endSecond == "number" ? n.endSecond : typeof n.end == "number" ? n.end : void 0, i = typeof n.text == "string" ? n.text : void 0;
836
+ if (e === void 0 || r === void 0 || i === void 0) continue;
837
+ let a = typeof n.speaker == "string" ? n.speaker : void 0;
838
+ t.push({
839
+ start: e,
840
+ end: r,
841
+ text: i,
842
+ ...a === void 0 ? {} : { speaker: a }
843
+ });
844
+ }
845
+ return t.length > 0 ? t : void 0;
846
+ }, gt = (t) => {
847
+ let r = t.provider ?? n();
848
+ return G(U(r, "transcribe"), () => ({}), m.tryPromise({
849
+ try: async () => {
850
+ let { audio: n, mediaType: i } = await mt(t.source, t.resolveRef), o = await a({
851
+ model: e(r),
852
+ audio: n,
853
+ ...i === void 0 ? {} : { mediaType: i },
854
+ ...t.providerOptions === void 0 ? {} : { providerOptions: t.providerOptions }
855
+ }), s = t.timestamps === "none" ? void 0 : ht(o.segments);
856
+ return {
857
+ text: o.text,
858
+ ...o.language === void 0 ? {} : { language: o.language },
859
+ ...o.durationInSeconds === void 0 ? {} : { durationSec: o.durationInSeconds },
860
+ ...s === void 0 ? {} : { segments: s },
861
+ ...o.providerMetadata === void 0 ? {} : { providerMetadata: o.providerMetadata }
862
+ };
863
+ },
864
+ catch: (e) => J(e)
865
+ }));
866
+ }, _t = (e) => `sha256:${de("sha256").update(e).digest("hex").slice(0, 16)}`, vt = class extends _.TaggedError()("PromptRenderError", {
867
+ promptId: _.String,
868
+ missing: _.Array(_.String),
869
+ message: _.String
870
+ }) {}, yt = /\{\{\s*([A-Za-z0-9_.]+)\s*\}\}/g, bt = (e) => {
871
+ let t = /* @__PURE__ */ new Set();
872
+ for (let n of e.matchAll(yt)) {
873
+ let e = n[1];
874
+ e !== void 0 && t.add(e);
875
+ }
876
+ return [...t];
877
+ }, xt = (e, t) => _t(`${e.length}:${e}${(t ?? "").length}:${t ?? ""}`), St = (e) => {
878
+ let t = xt(e.template, e.system), n = bt(e.template);
879
+ return {
880
+ ...e,
881
+ digest: t,
882
+ variables: n,
883
+ render: (r = {}) => m.suspend(() => {
884
+ let i = n.filter((e) => r[e] === void 0);
885
+ if (i.length > 0) return m.fail(new vt({
886
+ promptId: e.id,
887
+ missing: i,
888
+ message: `prompt '${e.id}' needs ${i.map((e) => `{{${e}}}`).join(", ")}, which ${i.length === 1 ? "was" : "were"} not supplied.`
889
+ }));
890
+ let a = e.template.replace(yt, (e, t) => String(r[t]));
891
+ return m.succeed({
892
+ promptId: e.id,
893
+ digest: t,
894
+ ...e.label === void 0 ? {} : { label: e.label },
895
+ prompt: a,
896
+ ...e.system === void 0 ? {} : { system: e.system },
897
+ definition: e
898
+ });
899
+ })
900
+ };
901
+ }, Ct = (e) => typeof e == "object" && !!e && typeof e.prompt == "string" && typeof e.digest == "string" && typeof e.promptId == "string", Y = "_voltro_prompts", X = E(Y, {
902
+ id: x({ prefix: "prm" }),
903
+ promptId: D().maxLength(191),
904
+ digest: D().maxLength(191),
905
+ revision: S().default(1),
906
+ label: D().nullable(),
907
+ template: D().nullable(),
908
+ system: D().nullable(),
909
+ templateChars: S().default(0),
910
+ firstSeenAt: O().default("now"),
911
+ lastUsedAt: O().default("now")
912
+ }).unique("byPromptsVersion", ["promptId", "digest"]).index(["promptId"]), wt = 8760, Tt = () => {
913
+ T({
914
+ source: "framework",
915
+ table: Y,
916
+ timeColumn: "lastUsedAt",
917
+ ttlMs: oe(process.env.VOLTRO_AI_PROMPTS_TTL_HOURS, wt),
918
+ envVar: "VOLTRO_AI_PROMPTS_TTL_HOURS",
919
+ label: "ai prompt versions"
920
+ });
921
+ }, Z = (e) => ({
922
+ promptId: String(e.promptId),
923
+ digest: String(e.digest),
924
+ revision: Number(e.revision) || 1,
925
+ label: e.label ?? null,
926
+ template: e.template ?? null,
927
+ system: e.system ?? null,
928
+ firstSeenAt: e.firstSeenAt ?? null,
929
+ lastUsedAt: e.lastUsedAt ?? null
930
+ }), Et = (e, t) => m.gen(function* () {
931
+ Tt();
932
+ let n = t.digest ?? St(t).digest;
933
+ return yield* m.promise(async () => {
934
+ let r = (await e.query(w(X).where(v(y("promptId", t.id), y("digest", n))).descriptor))[0];
935
+ if (r !== void 0) {
936
+ let t = /* @__PURE__ */ new Date();
937
+ return await e.updateMany(Y, { lastUsedAt: t }, { where: y("id", String(r.id)) }), Z({
938
+ ...r,
939
+ lastUsedAt: t
940
+ });
941
+ }
942
+ let i = (await e.query(w(X).where(y("promptId", t.id)).descriptor)).reduce((e, t) => Math.max(e, Number(t.revision) || 0), 0) + 1, a = /* @__PURE__ */ new Date(), o = {
943
+ id: b({
944
+ kind: "typeid",
945
+ prefix: "prm"
946
+ }, Y),
947
+ promptId: t.id,
948
+ digest: n,
949
+ revision: i,
950
+ label: t.label ?? null,
951
+ template: t.template,
952
+ system: t.system ?? null,
953
+ templateChars: t.template.length,
954
+ firstSeenAt: a,
955
+ lastUsedAt: a
956
+ };
957
+ return Z(await e.insertIgnore(Y, o, { conflictColumns: ["promptId", "digest"] }) ?? o);
958
+ });
959
+ }), Dt = (e, t) => m.promise(async () => {
960
+ let n = (await e.query(w(X).where(y("digest", t)).descriptor))[0];
961
+ return n === void 0 ? null : Z(n);
962
+ }), Ot = (e, t) => m.promise(async () => [...await e.query(w(X).where(y("promptId", t)).orderBy("revision", "desc").descriptor)].sort((e, t) => (Number(t.revision) || 0) - (Number(e.revision) || 0)).map(Z)), kt = "_voltro_ai_inferences", At = E(kt, {
963
+ id: x({ prefix: "aiinf" }),
964
+ tenantId: D().nullable(),
965
+ executionId: D(),
966
+ workflowName: D(),
967
+ runId: D().nullable(),
968
+ signalName: D(),
969
+ stepName: D(),
970
+ status: D().oneOf([
971
+ "pending",
972
+ "running",
973
+ "succeeded",
974
+ "failed"
975
+ ]).default("pending"),
976
+ kind: D().oneOf([
977
+ "text",
978
+ "object",
979
+ "transcription",
980
+ "media"
981
+ ]).default("text"),
982
+ provider: D(),
983
+ model: D(),
984
+ prompt: D(),
985
+ system: D().nullable(),
986
+ promptId: D().nullable(),
987
+ promptDigest: D().nullable(),
988
+ promptRevision: S().nullable(),
989
+ maxTokens: S().nullable(),
990
+ providerOptions: C().nullable(),
991
+ jsonSchema: C().nullable(),
992
+ transcription: C().nullable(),
993
+ media: C().nullable(),
994
+ taskHandle: C().nullable(),
995
+ taskSubmittedAt: O().nullable(),
996
+ result: C().nullable(),
997
+ errorMessage: D().nullable(),
998
+ attempts: S().default(0),
999
+ fence: S().default(0),
1000
+ leaseUntil: O().nullable(),
1001
+ claimedBy: D().nullable(),
1002
+ enqueuedAt: O().default("now"),
1003
+ startedAt: O().nullable(),
1004
+ completedAt: O().nullable(),
1005
+ durationMs: S().nullable()
1006
+ }).index(["status", "enqueuedAt"]).index(["status", "leaseUntil"]).index(["executionId"]).index(["tenantId"]), jt = 3e5, Mt = 4, Q = (e, t) => {
1007
+ let n = typeof e == "number" ? e : Number(e);
1008
+ return Number.isFinite(n) ? Math.trunc(n) : t;
1009
+ }, $ = (e) => e == null ? null : String(e), Nt = (e) => {
1010
+ if (e instanceof Date) return e;
1011
+ if (typeof e == "string" || typeof e == "number") {
1012
+ let t = new Date(e);
1013
+ return Number.isNaN(t.getTime()) ? null : t;
1014
+ }
1015
+ return null;
1016
+ }, Pt = (e) => ({
1017
+ id: String(e.id),
1018
+ tenantId: $(e.tenantId),
1019
+ executionId: String(e.executionId),
1020
+ workflowName: String(e.workflowName),
1021
+ runId: $(e.runId),
1022
+ signalName: String(e.signalName),
1023
+ stepName: String(e.stepName),
1024
+ kind: e.kind === "object" ? "object" : e.kind === "transcription" ? "transcription" : e.kind === "media" ? "media" : "text",
1025
+ provider: String(e.provider),
1026
+ model: String(e.model),
1027
+ prompt: String(e.prompt ?? ""),
1028
+ system: $(e.system),
1029
+ promptId: $(e.promptId),
1030
+ promptDigest: $(e.promptDigest),
1031
+ promptRevision: e.promptRevision === null || e.promptRevision === void 0 ? null : Q(e.promptRevision, 0),
1032
+ maxTokens: e.maxTokens === null || e.maxTokens === void 0 ? null : Q(e.maxTokens, 0),
1033
+ providerOptions: e.providerOptions ?? null,
1034
+ jsonSchema: e.jsonSchema ?? null,
1035
+ transcription: e.transcription ?? null,
1036
+ media: e.media ?? null,
1037
+ taskHandle: typeof e.taskHandle == "object" ? e.taskHandle : null,
1038
+ taskSubmittedAt: Nt(e.taskSubmittedAt),
1039
+ attempts: Q(e.attempts, 0),
1040
+ fence: Q(e.fence, 0)
1041
+ }), Ft = (e) => {
1042
+ let t = e.attempts + 1;
1043
+ return t >= e.maxAttempts ? {
1044
+ kind: "give-up",
1045
+ attempts: t
1046
+ } : {
1047
+ kind: "retry",
1048
+ attempts: t,
1049
+ delayMs: e.retryAfterMs !== void 0 && e.retryAfterMs > 0 ? e.retryAfterMs : Math.min(e.baseDelayMs * 2 ** (t - 1), e.maxDelayMs)
1050
+ };
1051
+ }, It = (e) => `voltro.ai.infer:${e}`, Lt = (e, t) => `aiinf_${de("sha256").update(`${e}\u0000${t}`).digest("hex").slice(0, 40)}`;
1052
+ //#endregion
1053
+ export { M as $, tt as A, Ie as B, J as C, dt as D, lt as E, Be as F, Pe as G, z as H, ze as I, Me as J, He as K, je as L, Qe as M, G as N, ot as O, B as P, j as Q, Ge as R, ft as S, ut as T, Ne as U, Re as V, Fe as W, N as X, P as Y, A as Z, Ot as _, Ft as a, me as at, gt as b, Pt as c, vt as d, Se as et, St as f, xt as g, Dt as h, At as i, k as it, U as j, ct as k, wt as l, _t as m, Mt as n, Ae as nt, It as o, he as ot, Ct as p, We as q, jt as r, ke as rt, Lt as s, ge as st, kt as t, F as tt, Y as u, X as v, pt as w, q as x, Et as y, Le as z };