@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.
@@ -0,0 +1,632 @@
1
+ import { a as e, r as t, s as n } from "./provider-BOgeCRkg.js";
2
+ import { Output as r, experimental_transcribe as i, generateObject as a, generateText as o, jsonSchema as s, stepCountIs as c, tool as l } from "ai";
3
+ import { Context as u, Effect as d, JSONSchema as ee, Metric as f, MetricBoundaries as te, Runtime as p, Schema as m, Stream as ne } from "effect";
4
+ import { and as h, eq as g, generateId as re, gte as ie, id as _, integer as v, json as y, queryFor as b, registerRetention as x, retentionTtlMsFromEnv as S, table as C, text as w, timestamp as T } from "@voltro/database";
5
+ import { createHash as E } from "node:crypto";
6
+ //#region src/tools.ts
7
+ var ae = (e, t) => e(t), D = Symbol.for("@voltro/ai/Tool"), oe = (e) => ({
8
+ ...e,
9
+ [D]: !0
10
+ }), O = (e) => typeof e == "object" && !!e && e[D] === !0, se = (e) => {
11
+ let t = e.default;
12
+ if (typeof t != "function") return 0;
13
+ let n = 0;
14
+ for (let r of Object.values(e)) O(r) && r.execute === void 0 && r.handler === void 0 && (r.handler = t, n += 1);
15
+ return n;
16
+ }, k = (e, t) => {
17
+ let n = t ?? p.defaultRuntime;
18
+ return p.runPromise(n)(e);
19
+ }, A = (e, t, n) => n ? e.pipe(d.timeoutFail({
20
+ duration: `${n} millis`,
21
+ onTimeout: () => /* @__PURE__ */ Error(`tool '${t}' timed out`)
22
+ })) : e, ce = (e, t, n) => {
23
+ if (e.execute) return k(A(ae(e.execute, t), e.name, e.timeoutMs), n.runtime);
24
+ if (e.handler) {
25
+ let r = e.handler, i = r(t, n);
26
+ return d.isEffect(i) ? k(A(i, e.name, e.timeoutMs), n.runtime) : i;
27
+ }
28
+ return Promise.reject(/* @__PURE__ */ Error(`tool '${e.name}' has neither execute nor handler`));
29
+ }, le = (e) => {
30
+ let t = ee.make(e);
31
+ return t && t.type === "object" ? t : {
32
+ type: "object",
33
+ properties: {},
34
+ additionalProperties: !1
35
+ };
36
+ }, ue = (e) => {
37
+ let t = e.inputJsonSchema;
38
+ return t === void 0 ? le(e.input) : t.type === "object" ? t : {
39
+ type: "object",
40
+ properties: {},
41
+ additionalProperties: !0
42
+ };
43
+ }, j = (e, t = { store: void 0 }) => {
44
+ let n = {};
45
+ for (let [r, i] of Object.entries(e)) n[i.name || r] = l({
46
+ description: i.description,
47
+ inputSchema: s(ue(i)),
48
+ execute: async (e) => {
49
+ let n = await d.runPromise(m.decodeUnknown(i.input)(e)), r = await ce(i, n, t);
50
+ return i.output ? d.runPromise(m.decodeUnknown(i.output)(r)) : r;
51
+ }
52
+ });
53
+ return n;
54
+ }, de = {
55
+ "claude-opus-4-8": {
56
+ inputPer1M: 15,
57
+ outputPer1M: 75
58
+ },
59
+ "claude-opus-4-6": {
60
+ inputPer1M: 15,
61
+ outputPer1M: 75
62
+ },
63
+ "claude-sonnet-4-6": {
64
+ inputPer1M: 3,
65
+ outputPer1M: 15
66
+ },
67
+ "claude-haiku-4-5": {
68
+ inputPer1M: 1,
69
+ outputPer1M: 5
70
+ },
71
+ "claude-haiku-4-5-20251001": {
72
+ inputPer1M: 1,
73
+ outputPer1M: 5
74
+ },
75
+ "gpt-5.5": {
76
+ inputPer1M: 5,
77
+ outputPer1M: 30
78
+ },
79
+ "gpt-4o": {
80
+ inputPer1M: 2.5,
81
+ outputPer1M: 10
82
+ },
83
+ "gpt-4o-mini": {
84
+ inputPer1M: .15,
85
+ outputPer1M: .6
86
+ },
87
+ "gemini-2.5-pro": {
88
+ inputPer1M: 1.25,
89
+ outputPer1M: 10
90
+ },
91
+ "gemini-2.5-flash": {
92
+ inputPer1M: .3,
93
+ outputPer1M: 2.5
94
+ },
95
+ "gemini-2.0-flash": {
96
+ inputPer1M: .1,
97
+ outputPer1M: .4
98
+ }
99
+ }, M = {}, fe = (e) => {
100
+ let t = M;
101
+ return M = { ...e }, t;
102
+ }, pe = () => ({
103
+ ...de,
104
+ ...M
105
+ }), me = (e) => {
106
+ let t = pe();
107
+ if (t[e] !== void 0) return t[e];
108
+ let n = e.indexOf("/");
109
+ if (n > 0) {
110
+ let r = e.slice(n + 1);
111
+ if (t[r] !== void 0) return t[r];
112
+ }
113
+ }, N = (e, t) => {
114
+ let n = e.inputTokens ?? 0, r = e.outputTokens ?? 0;
115
+ if (t.actualCostUsd !== void 0) {
116
+ let e = n + r, i = e > 0 ? n / e : 0;
117
+ return {
118
+ inputTokens: n,
119
+ outputTokens: r,
120
+ inputCostUsd: t.actualCostUsd * i,
121
+ outputCostUsd: t.actualCostUsd * (1 - i),
122
+ totalCostUsd: t.actualCostUsd,
123
+ costSource: "gateway"
124
+ };
125
+ }
126
+ let i = t.price ?? me(t.model) ?? {
127
+ inputPer1M: 0,
128
+ outputPer1M: 0
129
+ }, a = n / 1e6 * i.inputPer1M, o = r / 1e6 * i.outputPer1M;
130
+ return {
131
+ inputTokens: n,
132
+ outputTokens: r,
133
+ inputCostUsd: a,
134
+ outputCostUsd: o,
135
+ totalCostUsd: a + o,
136
+ costSource: "estimated"
137
+ };
138
+ }, P = "_voltro_ai_usage", he = C(P, {
139
+ id: _({ prefix: "aiu" }),
140
+ tenantId: w().nullable(),
141
+ provider: w(),
142
+ model: w(),
143
+ operation: w(),
144
+ agent: w().nullable(),
145
+ inputTokens: v().default(0),
146
+ outputTokens: v().default(0),
147
+ costMicroUsd: v().default(0),
148
+ costSource: w().default("estimated"),
149
+ promptId: w().nullable(),
150
+ promptDigest: w().nullable(),
151
+ promptRevision: v().nullable(),
152
+ calledAt: T().default("now")
153
+ }).index(["tenantId"]).index(["promptDigest"]), ge = (e) => {
154
+ let t = e?.gateway?.cost, n = typeof t == "number" ? t : typeof t == "string" ? Number(t) : NaN;
155
+ return Number.isFinite(n) ? n : void 0;
156
+ }, _e = (e, t) => (x({
157
+ source: "plugin",
158
+ table: P,
159
+ timeColumn: "calledAt",
160
+ ttlMs: S(process.env.VOLTRO_AI_USAGE_TTL_HOURS, 8760)
161
+ }), d.promise(async () => {
162
+ let n = N(t.usage, {
163
+ model: t.model,
164
+ ...t.price === void 0 ? {} : { price: t.price },
165
+ ...t.actualCostUsd === void 0 ? {} : { actualCostUsd: t.actualCostUsd }
166
+ });
167
+ return await e.insert(P, {
168
+ tenantId: t.tenantId ?? null,
169
+ provider: t.provider,
170
+ model: t.model,
171
+ operation: t.operation,
172
+ agent: t.agent ?? null,
173
+ inputTokens: n.inputTokens,
174
+ outputTokens: n.outputTokens,
175
+ costMicroUsd: Math.round(n.totalCostUsd * 1e6),
176
+ costSource: n.costSource,
177
+ promptId: t.prompt?.promptId ?? null,
178
+ promptDigest: t.prompt?.digest ?? null,
179
+ promptRevision: t.prompt?.revision ?? null,
180
+ calledAt: t.calledAt ?? /* @__PURE__ */ new Date()
181
+ }), n;
182
+ })), ve = (e, t = {}) => d.promise(async () => {
183
+ let n = [
184
+ ...t.tenantId === void 0 ? [] : [g("tenantId", t.tenantId)],
185
+ ...t.since === void 0 ? [] : [ie("calledAt", t.since)],
186
+ ...t.promptDigest === void 0 ? [] : [g("promptDigest", t.promptDigest)]
187
+ ], r = b(he), i = n.length === 0 ? r : r.where(n.length === 1 ? n[0] : h(...n));
188
+ return (await e.query(i.descriptor)).reduce((e, t) => e + (Number(t.costMicroUsd) || 0), 0) / 1e6;
189
+ }), ye = class extends m.TaggedError()("AiBudgetExceeded", {
190
+ tenantId: m.NullOr(m.String),
191
+ limitUsd: m.Number,
192
+ spentUsd: m.Number,
193
+ attemptedUsd: m.Number
194
+ }) {}, F = "_voltro_ai_budget", I = C(F, {
195
+ id: _({ prefix: "aib" }),
196
+ bucket: w().maxLength(191),
197
+ tenantId: w().nullable(),
198
+ reservedMicroUsd: v().default(0),
199
+ updatedAt: T().default("now")
200
+ }).unique("byAiBudgetBucket", ["bucket"]), be = (e, t) => `${e ?? "global"}::${t === void 0 ? "all" : String(t.getTime())}`, L = 32, xe = (e, t) => d.gen(function* () {
201
+ x({
202
+ source: "plugin",
203
+ table: F,
204
+ timeColumn: "updatedAt",
205
+ ttlMs: S(process.env.VOLTRO_AI_USAGE_TTL_HOURS, 8760)
206
+ });
207
+ let n = t.addUsd ?? 0, r = Math.round(n * 1e6), i = Math.round(t.limitUsd * 1e6), a = be(t.tenantId, t.since), o = t.tenantId ?? null, s = (e) => new ye({
208
+ tenantId: o,
209
+ limitUsd: t.limitUsd,
210
+ spentUsd: e / 1e6,
211
+ attemptedUsd: n
212
+ }), c = yield* d.promise(async () => {
213
+ for (let t = 0; t < L; t++) {
214
+ t > 0 && await new Promise((e) => setTimeout(e, t));
215
+ let n = (await e.query(b(I).where(g("bucket", a)).descriptor))[0], s = n && Number(n.reservedMicroUsd) || 0;
216
+ if (s + r > i) return {
217
+ ok: !1,
218
+ reservedMicro: s
219
+ };
220
+ if (r === 0) return { ok: !0 };
221
+ if (n) {
222
+ if (await e.updateMany("_voltro_ai_budget", {
223
+ reservedMicroUsd: s + r,
224
+ updatedAt: /* @__PURE__ */ new Date()
225
+ }, { where: h(g("id", String(n.id)), g("reservedMicroUsd", s)) }) === 1) return { ok: !0 };
226
+ } else {
227
+ let t = re({
228
+ kind: "typeid",
229
+ prefix: "aib"
230
+ }, F), n = await e.insertIgnore(F, {
231
+ id: t,
232
+ bucket: a,
233
+ tenantId: o,
234
+ reservedMicroUsd: r,
235
+ updatedAt: /* @__PURE__ */ new Date()
236
+ }, { conflictColumns: ["bucket"] });
237
+ if (String(n.id) === t) return { ok: !0 };
238
+ }
239
+ }
240
+ throw Error(`requireAiBudget: contention on bucket '${a}' exceeded ${L} attempts`);
241
+ });
242
+ if (!c.ok) return yield* d.fail(s(c.reservedMicro));
243
+ }), Se = te.exponential({
244
+ start: .001,
245
+ factor: 2,
246
+ count: 16
247
+ }), R = f.counter("voltro_ai_calls_total", { description: "Total AI provider calls (generate + stream)." }), z = f.counter("voltro_ai_call_errors_total", { description: "AI provider calls that errored." }), B = f.histogram("voltro_ai_call_duration_seconds", Se, "AI provider call duration in seconds."), Ce = f.counter("voltro_ai_input_tokens_total", {
248
+ description: "Total prompt (input) tokens across AI calls.",
249
+ incremental: !0
250
+ }), we = f.counter("voltro_ai_output_tokens_total", {
251
+ description: "Total completion (output) tokens across AI calls.",
252
+ incremental: !0
253
+ }), Te = f.counter("voltro_ai_cost_microusd_total", {
254
+ description: "Total estimated AI spend in micro-USD (USD × 1e6).",
255
+ incremental: !0
256
+ }), V = (e, t) => ({
257
+ provider: e.name,
258
+ model: e.model ?? e.name,
259
+ operation: t
260
+ }), H = (e, t, n) => e.pipe(d.tagMetrics("provider", t.provider), d.tagMetrics("model", t.model), d.tagMetrics("operation", t.operation), d.tagMetrics("status", n)), U = (e, t) => {
261
+ let n = t.inputTokens ?? 0, r = t.outputTokens ?? 0, i = N({
262
+ inputTokens: n,
263
+ outputTokens: r
264
+ }, { model: e.model }), a = Math.round(i.totalCostUsd * 1e6);
265
+ return d.all([
266
+ H(f.incrementBy(Ce, n), e, "ok"),
267
+ H(f.incrementBy(we, r), e, "ok"),
268
+ H(f.incrementBy(Te, a), e, "ok")
269
+ ], { discard: !0 });
270
+ }, W = (e, t, n) => d.gen(function* () {
271
+ let r = yield* d.clockWith((e) => e.currentTimeMillis);
272
+ return yield* n.pipe(d.tap((n) => U(e, t(n))), d.tap(() => H(f.increment(R), e, "ok").pipe(d.zipRight(d.clockWith((e) => e.currentTimeMillis).pipe(d.flatMap((t) => H(f.update(B, (t - r) / 1e3), e, "ok")))))), d.tapError(() => H(f.increment(R), e, "error").pipe(d.zipRight(H(f.increment(z), e, "error")), d.zipRight(d.clockWith((e) => e.currentTimeMillis).pipe(d.flatMap((t) => H(f.update(B, (t - r) / 1e3), e, "error")))))), d.withSpan("voltro.ai.call", { attributes: {
273
+ "ai.provider": e.provider,
274
+ "ai.model": e.model,
275
+ "ai.operation": e.operation
276
+ } }));
277
+ }), Ee = (e, t) => {
278
+ let n = Date.now();
279
+ return t.pipe(ne.tap((t) => t._tag === "done" ? H(f.increment(R), e, "ok").pipe(d.zipRight(H(f.update(B, (Date.now() - n) / 1e3), e, "ok")), d.zipRight(U(e, t.usage ?? {}))) : t._tag === "error" ? H(f.increment(R), e, "error").pipe(d.zipRight(H(f.increment(z), e, "error")), d.zipRight(H(f.update(B, (Date.now() - n) / 1e3), e, "error"))) : d.void), ne.withSpan("voltro.ai.call", { attributes: {
280
+ "ai.provider": e.provider,
281
+ "ai.model": e.model,
282
+ "ai.operation": e.operation
283
+ } }));
284
+ }, G = class extends m.TaggedError()("AiError", {
285
+ reason: m.Literal("generation", "decode"),
286
+ message: m.String
287
+ }) {}, K = (e, t, n) => {
288
+ let r = [e, ...t ?? []], i = (e) => n(r[e]).pipe(d.catchTag("AiError", (t) => t.reason === "generation" && e + 1 < r.length ? i(e + 1) : d.fail(t)));
289
+ return i(0);
290
+ }, De = (n) => K(n.provider ?? t(), n.fallbacks, (t) => W(V(t, "generateText"), (e) => e.usage, d.tryPromise({
291
+ try: async () => {
292
+ let r = e(t), i = await o({
293
+ model: r,
294
+ prompt: n.prompt,
295
+ ...n.system === void 0 ? {} : { system: n.system },
296
+ ...n.maxTokens === void 0 ? {} : { maxOutputTokens: n.maxTokens },
297
+ ...n.providerOptions === void 0 ? {} : { providerOptions: n.providerOptions }
298
+ });
299
+ return {
300
+ text: i.text,
301
+ usage: {
302
+ inputTokens: i.usage.inputTokens,
303
+ outputTokens: i.usage.outputTokens,
304
+ totalTokens: i.usage.totalTokens
305
+ },
306
+ providerMetadata: i.providerMetadata
307
+ };
308
+ },
309
+ catch: (e) => new G({
310
+ reason: "generation",
311
+ message: String(e?.message ?? e)
312
+ })
313
+ }))), q = (e, t) => d.gen(function* () {
314
+ let n = ee.make(e);
315
+ if (n?.type !== "object") {
316
+ let e = n?.anyOf === void 0 ? `type:${JSON.stringify(n?.type ?? null)}` : "anyOf (e.g. Schema.Struct({}) or a union)";
317
+ return yield* d.fail(new G({
318
+ reason: "generation",
319
+ 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(...) })).`
320
+ }));
321
+ }
322
+ return n;
323
+ }), Oe = (e, t) => q(e, t), ke = (n) => K(n.provider ?? t(), n.fallbacks, (t) => W(V(t, "generateObject"), (e) => e.usage, d.gen(function* () {
324
+ let r = e(t), i = yield* d.tryPromise({
325
+ try: () => a({
326
+ model: r,
327
+ schema: s(n.jsonSchema),
328
+ prompt: n.prompt,
329
+ ...n.system === void 0 ? {} : { system: n.system },
330
+ ...n.maxTokens === void 0 ? {} : { maxOutputTokens: n.maxTokens },
331
+ ...n.providerOptions === void 0 ? {} : { providerOptions: n.providerOptions }
332
+ }),
333
+ catch: (e) => new G({
334
+ reason: "generation",
335
+ message: String(e?.message ?? e)
336
+ })
337
+ });
338
+ return {
339
+ object: i.object,
340
+ usage: {
341
+ inputTokens: i.usage.inputTokens,
342
+ outputTokens: i.usage.outputTokens,
343
+ totalTokens: i.usage.totalTokens
344
+ },
345
+ providerMetadata: i.providerMetadata
346
+ };
347
+ }))), Ae = (e) => d.gen(function* () {
348
+ let t = yield* ke({
349
+ jsonSchema: yield* q(e.schema, "generateObject"),
350
+ prompt: e.prompt,
351
+ ...e.system === void 0 ? {} : { system: e.system },
352
+ ...e.provider === void 0 ? {} : { provider: e.provider },
353
+ ...e.fallbacks === void 0 ? {} : { fallbacks: e.fallbacks },
354
+ ...e.maxTokens === void 0 ? {} : { maxTokens: e.maxTokens },
355
+ ...e.providerOptions === void 0 ? {} : { providerOptions: e.providerOptions }
356
+ }), n = yield* m.decodeUnknown(e.schema)(t.object).pipe(d.mapError((e) => new G({
357
+ reason: "decode",
358
+ message: `model output failed schema decode: ${String(e)}`
359
+ })));
360
+ return {
361
+ ...t,
362
+ object: n
363
+ };
364
+ }), je = (n) => d.gen(function* () {
365
+ let i = yield* d.runtime(), a = yield* q(n.schema, "generateObjectWithTools"), l = {
366
+ store: void 0,
367
+ ...n.toolContext,
368
+ runtime: i
369
+ }, u = j(n.tools, l);
370
+ return yield* K(n.provider ?? t(), n.fallbacks, (t) => W(V(t, "generateObjectWithTools"), (e) => e.usage, d.gen(function* () {
371
+ let i = e(t), l = yield* d.tryPromise({
372
+ try: () => o({
373
+ model: i,
374
+ prompt: n.prompt,
375
+ tools: u,
376
+ stopWhen: c(n.maxSteps ?? 8),
377
+ output: r.object({ schema: s(a) }),
378
+ ...n.system === void 0 ? {} : { system: n.system },
379
+ ...n.maxTokens === void 0 ? {} : { maxOutputTokens: n.maxTokens },
380
+ ...n.providerOptions === void 0 ? {} : { providerOptions: n.providerOptions }
381
+ }),
382
+ catch: (e) => new G({
383
+ reason: "generation",
384
+ message: String(e?.message ?? e)
385
+ })
386
+ });
387
+ return {
388
+ object: yield* m.decodeUnknown(n.schema)(l.output).pipe(d.mapError((e) => new G({
389
+ reason: "decode",
390
+ message: `model output failed schema decode: ${String(e)}`
391
+ }))),
392
+ usage: {
393
+ inputTokens: l.usage.inputTokens,
394
+ outputTokens: l.usage.outputTokens,
395
+ totalTokens: l.usage.totalTokens
396
+ },
397
+ providerMetadata: l.providerMetadata
398
+ };
399
+ })));
400
+ }), Me = class extends u.Tag("@voltro/AiService")() {}, Ne = {
401
+ generateText: (e) => De(e),
402
+ generateObject: (e) => Ae(e)
403
+ }, Pe = async (e, t) => {
404
+ if ("bytes" in e) return {
405
+ audio: e.bytes,
406
+ mediaType: e.mediaType
407
+ };
408
+ if ("url" in e) {
409
+ let t = await fetch(e.url);
410
+ if (!t.ok) throw Error(`transcribe: GET ${e.url} answered ${t.status}.`);
411
+ let n = t.headers.get("content-type") ?? void 0;
412
+ return {
413
+ audio: new Uint8Array(await t.arrayBuffer()),
414
+ ...n === void 0 ? {} : { mediaType: n }
415
+ };
416
+ }
417
+ 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.");
418
+ let { bytes: n, mediaType: r } = await t(e.storageRef);
419
+ return {
420
+ audio: n,
421
+ mediaType: r
422
+ };
423
+ }, Fe = (e) => {
424
+ if (!Array.isArray(e) || e.length === 0) return;
425
+ let t = [];
426
+ for (let n of e) {
427
+ 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;
428
+ if (e === void 0 || r === void 0 || i === void 0) continue;
429
+ let a = typeof n.speaker == "string" ? n.speaker : void 0;
430
+ t.push({
431
+ start: e,
432
+ end: r,
433
+ text: i,
434
+ ...a === void 0 ? {} : { speaker: a }
435
+ });
436
+ }
437
+ return t.length > 0 ? t : void 0;
438
+ }, Ie = (e) => {
439
+ let r = e.provider ?? t();
440
+ return W(V(r, "transcribe"), () => ({}), d.tryPromise({
441
+ try: async () => {
442
+ let { audio: t, mediaType: a } = await Pe(e.source, e.resolveRef), o = await i({
443
+ model: n(r),
444
+ audio: t,
445
+ ...a === void 0 ? {} : { mediaType: a },
446
+ ...e.providerOptions === void 0 ? {} : { providerOptions: e.providerOptions }
447
+ }), s = e.timestamps === "none" ? void 0 : Fe(o.segments);
448
+ return {
449
+ text: o.text,
450
+ ...o.language === void 0 ? {} : { language: o.language },
451
+ ...o.durationInSeconds === void 0 ? {} : { durationSec: o.durationInSeconds },
452
+ ...s === void 0 ? {} : { segments: s },
453
+ ...o.providerMetadata === void 0 ? {} : { providerMetadata: o.providerMetadata }
454
+ };
455
+ },
456
+ catch: (e) => new G({
457
+ reason: "generation",
458
+ message: String(e?.message ?? e)
459
+ })
460
+ }));
461
+ }, Le = (e) => `sha256:${E("sha256").update(e).digest("hex").slice(0, 16)}`, Re = class extends m.TaggedError()("PromptRenderError", {
462
+ promptId: m.String,
463
+ missing: m.Array(m.String),
464
+ message: m.String
465
+ }) {}, J = /\{\{\s*([A-Za-z0-9_.]+)\s*\}\}/g, ze = (e) => {
466
+ let t = /* @__PURE__ */ new Set();
467
+ for (let n of e.matchAll(J)) {
468
+ let e = n[1];
469
+ e !== void 0 && t.add(e);
470
+ }
471
+ return [...t];
472
+ }, Be = (e, t) => Le(`${e.length}:${e}${(t ?? "").length}:${t ?? ""}`), Ve = (e) => {
473
+ let t = Be(e.template, e.system), n = ze(e.template);
474
+ return {
475
+ ...e,
476
+ digest: t,
477
+ variables: n,
478
+ render: (r = {}) => d.suspend(() => {
479
+ let i = n.filter((e) => r[e] === void 0);
480
+ if (i.length > 0) return d.fail(new Re({
481
+ promptId: e.id,
482
+ missing: i,
483
+ message: `prompt '${e.id}' needs ${i.map((e) => `{{${e}}}`).join(", ")}, which ${i.length === 1 ? "was" : "were"} not supplied.`
484
+ }));
485
+ let a = e.template.replace(J, (e, t) => String(r[t]));
486
+ return d.succeed({
487
+ promptId: e.id,
488
+ digest: t,
489
+ ...e.label === void 0 ? {} : { label: e.label },
490
+ prompt: a,
491
+ ...e.system === void 0 ? {} : { system: e.system },
492
+ definition: e
493
+ });
494
+ })
495
+ };
496
+ }, He = (e) => typeof e == "object" && !!e && typeof e.prompt == "string" && typeof e.digest == "string" && typeof e.promptId == "string", Y = "_voltro_prompts", X = C(Y, {
497
+ id: _({ prefix: "prm" }),
498
+ promptId: w().maxLength(191),
499
+ digest: w().maxLength(191),
500
+ revision: v().default(1),
501
+ label: w().nullable(),
502
+ template: w().nullable(),
503
+ system: w().nullable(),
504
+ templateChars: v().default(0),
505
+ firstSeenAt: T().default("now"),
506
+ lastUsedAt: T().default("now")
507
+ }).unique("byPromptsVersion", ["promptId", "digest"]).index(["promptId"]), Ue = 8760, We = () => {
508
+ x({
509
+ source: "framework",
510
+ table: Y,
511
+ timeColumn: "lastUsedAt",
512
+ ttlMs: S(process.env.VOLTRO_AI_PROMPTS_TTL_HOURS, Ue),
513
+ envVar: "VOLTRO_AI_PROMPTS_TTL_HOURS",
514
+ label: "ai prompt versions"
515
+ });
516
+ }, Z = (e) => ({
517
+ promptId: String(e.promptId),
518
+ digest: String(e.digest),
519
+ revision: Number(e.revision) || 1,
520
+ label: e.label ?? null,
521
+ template: e.template ?? null,
522
+ system: e.system ?? null,
523
+ firstSeenAt: e.firstSeenAt ?? null,
524
+ lastUsedAt: e.lastUsedAt ?? null
525
+ }), Ge = (e, t) => d.gen(function* () {
526
+ We();
527
+ let n = t.digest ?? Ve(t).digest;
528
+ return yield* d.promise(async () => {
529
+ let r = (await e.query(b(X).where(h(g("promptId", t.id), g("digest", n))).descriptor))[0];
530
+ if (r !== void 0) {
531
+ let t = /* @__PURE__ */ new Date();
532
+ return await e.updateMany(Y, { lastUsedAt: t }, { where: g("id", String(r.id)) }), Z({
533
+ ...r,
534
+ lastUsedAt: t
535
+ });
536
+ }
537
+ let i = (await e.query(b(X).where(g("promptId", t.id)).descriptor)).reduce((e, t) => Math.max(e, Number(t.revision) || 0), 0) + 1, a = /* @__PURE__ */ new Date(), o = {
538
+ id: re({
539
+ kind: "typeid",
540
+ prefix: "prm"
541
+ }, Y),
542
+ promptId: t.id,
543
+ digest: n,
544
+ revision: i,
545
+ label: t.label ?? null,
546
+ template: t.template,
547
+ system: t.system ?? null,
548
+ templateChars: t.template.length,
549
+ firstSeenAt: a,
550
+ lastUsedAt: a
551
+ };
552
+ return Z(await e.insertIgnore(Y, o, { conflictColumns: ["promptId", "digest"] }) ?? o);
553
+ });
554
+ }), Ke = (e, t) => d.promise(async () => {
555
+ let n = (await e.query(b(X).where(g("digest", t)).descriptor))[0];
556
+ return n === void 0 ? null : Z(n);
557
+ }), qe = (e, t) => d.promise(async () => [...await e.query(b(X).where(g("promptId", t)).orderBy("revision", "desc").descriptor)].sort((e, t) => (Number(t.revision) || 0) - (Number(e.revision) || 0)).map(Z)), Je = "_voltro_ai_inferences", Ye = C(Je, {
558
+ id: _({ prefix: "aiinf" }),
559
+ tenantId: w().nullable(),
560
+ executionId: w(),
561
+ workflowName: w(),
562
+ runId: w().nullable(),
563
+ signalName: w(),
564
+ stepName: w(),
565
+ status: w().oneOf([
566
+ "pending",
567
+ "running",
568
+ "succeeded",
569
+ "failed"
570
+ ]).default("pending"),
571
+ kind: w().oneOf([
572
+ "text",
573
+ "object",
574
+ "transcription"
575
+ ]).default("text"),
576
+ provider: w(),
577
+ model: w(),
578
+ prompt: w(),
579
+ system: w().nullable(),
580
+ promptId: w().nullable(),
581
+ promptDigest: w().nullable(),
582
+ promptRevision: v().nullable(),
583
+ maxTokens: v().nullable(),
584
+ providerOptions: y().nullable(),
585
+ jsonSchema: y().nullable(),
586
+ transcription: y().nullable(),
587
+ result: y().nullable(),
588
+ errorMessage: w().nullable(),
589
+ attempts: v().default(0),
590
+ leaseUntil: T().nullable(),
591
+ claimedBy: w().nullable(),
592
+ enqueuedAt: T().default("now"),
593
+ startedAt: T().nullable(),
594
+ completedAt: T().nullable(),
595
+ durationMs: v().nullable()
596
+ }).index(["status", "enqueuedAt"]).index(["status", "leaseUntil"]).index(["executionId"]).index(["tenantId"]), Xe = 3e5, Ze = 4, Q = (e, t) => {
597
+ let n = typeof e == "number" ? e : Number(e);
598
+ return Number.isFinite(n) ? Math.trunc(n) : t;
599
+ }, $ = (e) => e == null ? null : String(e), Qe = (e) => ({
600
+ id: String(e.id),
601
+ tenantId: $(e.tenantId),
602
+ executionId: String(e.executionId),
603
+ workflowName: String(e.workflowName),
604
+ runId: $(e.runId),
605
+ signalName: String(e.signalName),
606
+ stepName: String(e.stepName),
607
+ kind: e.kind === "object" ? "object" : e.kind === "transcription" ? "transcription" : "text",
608
+ provider: String(e.provider),
609
+ model: String(e.model),
610
+ prompt: String(e.prompt ?? ""),
611
+ system: $(e.system),
612
+ promptId: $(e.promptId),
613
+ promptDigest: $(e.promptDigest),
614
+ promptRevision: e.promptRevision === null || e.promptRevision === void 0 ? null : Q(e.promptRevision, 0),
615
+ maxTokens: e.maxTokens === null || e.maxTokens === void 0 ? null : Q(e.maxTokens, 0),
616
+ providerOptions: e.providerOptions ?? null,
617
+ jsonSchema: e.jsonSchema ?? null,
618
+ transcription: e.transcription ?? null,
619
+ attempts: Q(e.attempts, 0)
620
+ }), $e = (e) => {
621
+ let t = e.attempts + 1;
622
+ return t >= e.maxAttempts ? {
623
+ kind: "give-up",
624
+ attempts: t
625
+ } : {
626
+ kind: "retry",
627
+ attempts: t,
628
+ delayMs: e.retryAfterMs !== void 0 && e.retryAfterMs > 0 ? e.retryAfterMs : Math.min(e.baseDelayMs * 2 ** (t - 1), e.maxDelayMs)
629
+ };
630
+ }, et = (e) => `voltro.ai.infer:${e}`, tt = (e, t) => `aiinf_${E("sha256").update(`${e}\u0000${t}`).digest("hex").slice(0, 40)}`;
631
+ //#endregion
632
+ export { Ee as A, ge as B, Ne as C, De as D, je as E, de as F, fe as G, me as H, I, O as J, j as K, ve as L, F as M, P as N, Oe as O, ye as P, he as R, Me as S, ke as T, _e as U, pe as V, xe as W, se as Y, qe as _, $e as a, Ie as b, Qe as c, Re as d, Ve as f, Be as g, Ke as h, Ye as i, W as j, V as k, Ue as l, Le as m, Ze as n, et as o, He as p, oe as q, Xe as r, tt as s, Je as t, Y as u, X as v, Ae as w, G as x, Ge as y, N as z };