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