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