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