@voltro/ai 0.85.0 → 0.86.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +666 -0
  2. package/THIRD-PARTY-NOTICES.md +5 -33
  3. package/dist/agent.js +64 -2
  4. package/dist/agentConstants.js +4 -0
  5. package/dist/agentExecutor.js +51 -0
  6. package/dist/api.js +199 -0
  7. package/dist/appTools.js +80 -0
  8. package/dist/budget.js +201 -0
  9. package/dist/callEvidence.js +51 -0
  10. package/dist/copilot.js +126 -0
  11. package/dist/cost.js +242 -0
  12. package/dist/embed.js +41 -0
  13. package/dist/embeddingProvider.js +51 -0
  14. package/dist/eval.js +130 -0
  15. package/dist/events.d.ts +4 -0
  16. package/dist/events.js +81 -2
  17. package/dist/executableModalities.js +13 -0
  18. package/dist/gateway.js +58 -0
  19. package/dist/gatewayCatalog.js +47 -0
  20. package/dist/gatewayMedia.js +88 -0
  21. package/dist/index.d.ts +11 -0
  22. package/dist/index.js +42 -2750
  23. package/dist/inferenceDispatch.js +493 -0
  24. package/dist/inferenceQueue.js +96 -0
  25. package/dist/jsonOutputValidation.js +27 -0
  26. package/dist/mcpClient.js +332 -0
  27. package/dist/mcpTools.js +80 -0
  28. package/dist/media.js +182 -0
  29. package/dist/mediaBytes.js +19 -0
  30. package/dist/mediaCall.js +13 -0
  31. package/dist/mediaTaskProvider.js +16 -0
  32. package/dist/middleware.js +32 -0
  33. package/dist/observe.js +52 -0
  34. package/dist/prompts.js +103 -0
  35. package/dist/provider.js +303 -0
  36. package/dist/realtimeEvent.js +97 -0
  37. package/dist/realtimeSession.js +154 -0
  38. package/dist/rerank.js +61 -0
  39. package/dist/resumableStream.js +321 -0
  40. package/dist/retrieveReranked.js +16 -0
  41. package/dist/runAndPersist.js +148 -0
  42. package/dist/semanticCache.js +66 -0
  43. package/dist/speechProvider.js +16 -0
  44. package/dist/streamRegistry.js +14 -0
  45. package/dist/streamText.js +170 -0
  46. package/dist/streamTranscribe.js +74 -0
  47. package/dist/streamWakeups.js +44 -0
  48. package/dist/structuredEvidence.js +48 -0
  49. package/dist/test.js +1 -1
  50. package/dist/threads.js +92 -0
  51. package/dist/tools.js +68 -0
  52. package/dist/transcribe.js +64 -0
  53. package/dist/transcriptionEvent.js +46 -0
  54. package/dist/workflow.d.ts +2 -0
  55. package/dist/workflow.js +115 -110
  56. package/package.json +5 -5
  57. package/dist/agentDescriptor-DhoiXVqO.js +0 -63
  58. package/dist/agentEvent-Bl4egdM5.js +0 -211
  59. package/dist/inferenceQueue-DcEulZep.js +0 -1077
  60. package/dist/provider-BnemgE4D.js +0 -409
package/dist/tools.js ADDED
@@ -0,0 +1,68 @@
1
+ import { jsonSchema as e, tool as t } from "ai";
2
+ import { Context as n, Effect as r, Schema as i } from "effect";
3
+ import { jsonSchemaOf as a } from "@voltro/protocol";
4
+ //#region src/tools.ts
5
+ var o = (e, t) => e(t), s = Symbol.for("@voltro/ai/Tool"), c = (e) => ({
6
+ ...e,
7
+ [s]: !0
8
+ }), l = (e) => typeof e == "object" && !!e && e[s] === !0, u = (e) => {
9
+ let t = e.default;
10
+ if (typeof t != "function") return 0;
11
+ let n = 0;
12
+ for (let r of Object.values(e)) l(r) && r.execution !== "client" && r.execute === void 0 && r.handler === void 0 && (r.handler = t, n += 1);
13
+ return n;
14
+ }, d = (e, t, i) => {
15
+ let a = t ?? n.empty();
16
+ return r.runPromiseWith(a)(e, i === void 0 ? {} : { signal: i });
17
+ }, f = (e, t, n) => n ? e.pipe(r.timeoutOrElse({
18
+ duration: `${n} millis`,
19
+ orElse: () => r.fail(/* @__PURE__ */ Error(`tool '${t}' timed out`))
20
+ })) : e, p = (e, t, n) => {
21
+ if (e.execute) return d(f(o(e.execute, t), e.name, e.timeoutMs), n.runtime, n.abortSignal);
22
+ if (e.handler) {
23
+ let i = e.handler, a = i(t, n);
24
+ return r.isEffect(a) ? d(f(a, e.name, e.timeoutMs), n.runtime, n.abortSignal) : a;
25
+ }
26
+ return Promise.reject(/* @__PURE__ */ Error(`tool '${e.name}' has neither execute nor handler`));
27
+ }, m = (e) => {
28
+ let t = a(e);
29
+ return t && t.type === "object" ? t : {
30
+ type: "object",
31
+ properties: {},
32
+ additionalProperties: !1
33
+ };
34
+ }, h = (e) => {
35
+ let t = e.inputJsonSchema;
36
+ return t === void 0 ? m(e.input) : t.type === "object" ? t : {
37
+ type: "object",
38
+ properties: {},
39
+ additionalProperties: !0
40
+ };
41
+ }, g = (n, a = { store: void 0 }) => {
42
+ let o = {};
43
+ for (let [s, c] of Object.entries(n)) {
44
+ if (c.execution === "client" && (c.execute !== void 0 || c.handler !== void 0)) throw Error(`client tool '${c.name || s}' cannot declare execute or handler`);
45
+ c.execution === "client" ? o[c.name || s] = t({
46
+ description: c.description,
47
+ inputSchema: e(h(c))
48
+ }) : o[c.name || s] = t({
49
+ description: c.description,
50
+ inputSchema: e(h(c)),
51
+ execute: async (e, t) => {
52
+ let n = a.abortSignal, o = t?.abortSignal, s = n !== void 0 && o !== void 0 && n !== o ? AbortSignal.any([n, o]) : o ?? n;
53
+ s?.throwIfAborted();
54
+ let l = {
55
+ ...a,
56
+ ...t?.toolCallId === void 0 ? {} : { invocationId: t.toolCallId },
57
+ ...s === void 0 ? {} : { abortSignal: s }
58
+ }, u = await r.runPromise(i.decodeUnknownEffect(c.input)(e));
59
+ s?.throwIfAborted();
60
+ let d = await p(c, u, l);
61
+ return c.output ? r.runPromise(i.decodeUnknownEffect(c.output)(d)) : d;
62
+ }
63
+ });
64
+ }
65
+ return o;
66
+ };
67
+ //#endregion
68
+ export { g as buildSdkTools, c as defineTool, l as isTool, u as resolveToolModuleHandlers };
@@ -0,0 +1,64 @@
1
+ import { providerFromEnv as e, resolveTranscriptionModel as t } from "./provider.js";
2
+ import { aiCallAttributes as n, withAiCallSpan as r } from "./observe.js";
3
+ import { aiGenerationError as i } from "./api.js";
4
+ import { experimental_transcribe as a } from "ai";
5
+ import { Effect as o } from "effect";
6
+ //#region src/transcribe.ts
7
+ var s = async (e, t) => {
8
+ if ("bytes" in e) return {
9
+ audio: e.bytes,
10
+ mediaType: e.mediaType
11
+ };
12
+ if ("url" in e) {
13
+ let t = await fetch(e.url);
14
+ if (!t.ok) throw Error(`transcribe: GET ${e.url} answered ${t.status}.`);
15
+ let n = t.headers.get("content-type") ?? void 0;
16
+ return {
17
+ audio: new Uint8Array(await t.arrayBuffer()),
18
+ ...n === void 0 ? {} : { mediaType: n }
19
+ };
20
+ }
21
+ if (t === void 0) throw Error("transcribe: `source.storageRef` needs a `resolveRef` to turn the reference into bytes.\n → pass `resolveRef: (ref) => storage.read(ref)`. It is injected rather than imported so @voltro/ai does not depend on storage; the app owns tenancy and signing for that read.");
22
+ let { bytes: n, mediaType: r } = await t(e.storageRef);
23
+ return {
24
+ audio: n,
25
+ mediaType: r
26
+ };
27
+ }, c = (e) => {
28
+ if (!Array.isArray(e) || e.length === 0) return;
29
+ let t = [];
30
+ for (let n of e) {
31
+ let e = typeof n.startSecond == "number" ? n.startSecond : typeof n.start == "number" ? n.start : void 0, r = typeof n.endSecond == "number" ? n.endSecond : typeof n.end == "number" ? n.end : void 0, i = typeof n.text == "string" ? n.text : void 0;
32
+ if (e === void 0 || r === void 0 || i === void 0) continue;
33
+ let a = typeof n.speaker == "string" ? n.speaker : void 0;
34
+ t.push({
35
+ start: e,
36
+ end: r,
37
+ text: i,
38
+ ...a === void 0 ? {} : { speaker: a }
39
+ });
40
+ }
41
+ return t.length > 0 ? t : void 0;
42
+ }, l = (l) => {
43
+ let u = l.provider ?? e();
44
+ return r(n(u, "transcribe"), () => ({}), o.tryPromise({
45
+ try: async () => {
46
+ let { audio: e, mediaType: n } = await s(l.source, l.resolveRef), r = await a({
47
+ model: t(u),
48
+ audio: e,
49
+ ...n === void 0 ? {} : { mediaType: n },
50
+ ...l.providerOptions === void 0 ? {} : { providerOptions: l.providerOptions }
51
+ }), i = l.timestamps === "none" ? void 0 : c(r.segments);
52
+ return {
53
+ text: r.text,
54
+ ...r.language === void 0 ? {} : { language: r.language },
55
+ ...r.durationInSeconds === void 0 ? {} : { durationSec: r.durationInSeconds },
56
+ ...i === void 0 ? {} : { segments: i },
57
+ ...r.providerMetadata === void 0 ? {} : { providerMetadata: r.providerMetadata }
58
+ };
59
+ },
60
+ catch: (e) => i(e)
61
+ }));
62
+ };
63
+ //#endregion
64
+ export { l as transcribe };
@@ -0,0 +1,46 @@
1
+ import { Schema as e } from "effect";
2
+ //#region src/transcriptionEvent.ts
3
+ var t = class extends e.TaggedError()("TranscriptionStreamError", {
4
+ reason: e.Literals([
5
+ "input",
6
+ "unsupported",
7
+ "provider",
8
+ "cancelled"
9
+ ]),
10
+ message: e.String
11
+ }) {}, n = e.Struct({
12
+ text: e.String,
13
+ start: e.Number,
14
+ end: e.Number
15
+ }), r = { id: e.optional(e.String) }, i = e.Union([
16
+ e.Struct({
17
+ type: e.Literal("transcript-delta"),
18
+ ...r,
19
+ delta: e.String
20
+ }),
21
+ e.Struct({
22
+ type: e.Literal("transcript-partial"),
23
+ ...r,
24
+ text: e.String,
25
+ startSecond: e.optional(e.Number),
26
+ durationInSeconds: e.optional(e.Number),
27
+ channelIndex: e.optional(e.Number)
28
+ }),
29
+ e.Struct({
30
+ type: e.Literal("transcript-final"),
31
+ ...r,
32
+ text: e.String,
33
+ startSecond: e.optional(e.Number),
34
+ endSecond: e.optional(e.Number),
35
+ channelIndex: e.optional(e.Number)
36
+ }),
37
+ e.Struct({
38
+ type: e.Literal("finish"),
39
+ text: e.String,
40
+ segments: e.Array(n),
41
+ language: e.optional(e.String),
42
+ durationSec: e.optional(e.Number)
43
+ })
44
+ ]);
45
+ //#endregion
46
+ export { t as TranscriptionStreamError, i as TranscriptionStreamEvent };
@@ -216,6 +216,8 @@ declare interface AnyTool {
216
216
  readonly output?: Schema.Top;
217
217
  readonly execute?: (input: never) => Effect.Effect<unknown, never, unknown>;
218
218
  readonly handler?: ToolHandler<never, unknown>;
219
+ /** Client tools return a pending call to the caller; never run on the server. */
220
+ readonly execution?: 'server' | 'client';
219
221
  readonly timeoutMs?: number;
220
222
  }
221
223
 
package/dist/workflow.js CHANGED
@@ -1,5 +1,10 @@
1
- import { r as e } from "./provider-BnemgE4D.js";
2
- import { D as t, O as n, T as r, V as i, b as a, k as o, m as s, o as c, p as l, q as u, rt as d, s as f, t as p, y as m } from "./inferenceQueue-DcEulZep.js";
1
+ import { providerFromEnv as e } from "./provider.js";
2
+ import { requireAiBudget as t } from "./budget.js";
3
+ import { gatewayCostUsd as n, recordAiUsageBestEffort as r } from "./cost.js";
4
+ import { generateObject as i, generateObjectWithTools as a, generateText as o, outputJsonSchema as s } from "./api.js";
5
+ import { transcribe as c } from "./transcribe.js";
6
+ import { isRenderedPrompt as l, promptDigest as u, recordPromptVersion as d } from "./prompts.js";
7
+ import { AI_INFERENCES_TABLE as f, inferenceSignalName as p, offloadedInferenceId as m } from "./inferenceQueue.js";
3
8
  import { Effect as h, Schema as g } from "effect";
4
9
  import { eq as _ } from "@voltro/database";
5
10
  import { BudgetHoldExpired as v, CurrentWorkflowExecutionId as y, SuspensionUnavailable as b, WorkflowCannotPark as x, awaitSignalSuspending as S, step as C, suspendForBudget as w } from "@voltro/workflow";
@@ -24,10 +29,10 @@ var T = {
24
29
  ...t === void 0 ? {} : { system: t }
25
30
  } : {
26
31
  ...i,
27
- promptDigest: s(e),
32
+ promptDigest: u(e),
28
33
  promptChars: e.length,
29
34
  ...t === void 0 ? {} : {
30
- systemDigest: s(t),
35
+ systemDigest: u(t),
31
36
  systemChars: t.length
32
37
  }
33
38
  };
@@ -42,23 +47,23 @@ var T = {
42
47
  }, A = (e) => ({
43
48
  provider: String(e.name),
44
49
  model: String(e.model ?? "unknown")
45
- }), j = (e, t, n, r, a) => {
46
- let o = e.store;
47
- if (o === void 0) return h.void;
48
- let { provider: s, model: c } = A(t), l = i(r.providerMetadata);
49
- return u(o, {
50
- provider: s,
51
- model: c,
52
- operation: n,
50
+ }), j = (e, t, i, a, o) => {
51
+ let s = e.store;
52
+ if (s === void 0) return h.void;
53
+ let { provider: c, model: l } = A(t), u = n(a.providerMetadata);
54
+ return r(s, {
55
+ provider: c,
56
+ model: l,
57
+ operation: i,
53
58
  agent: e.name,
54
- usage: r.usage,
59
+ usage: a.usage,
55
60
  ...e.tenantId === void 0 ? {} : { tenantId: e.tenantId },
56
- ...l === void 0 ? {} : { actualCostUsd: l },
57
- ...a === void 0 ? {} : { prompt: a }
61
+ ...u === void 0 ? {} : { actualCostUsd: u },
62
+ ...o === void 0 ? {} : { prompt: o }
58
63
  });
59
64
  }, M = (e, t) => {
60
65
  let n = e.store;
61
- return n === void 0 || t === void 0 ? h.void : m(n, {
66
+ return n === void 0 || t === void 0 ? h.void : d(n, {
62
67
  ...t.definition,
63
68
  digest: t.digest
64
69
  }).pipe(h.asVoid, h.catchCause(() => h.void));
@@ -80,28 +85,28 @@ var T = {
80
85
  }, L = (e, t, n, r, i, a, o) => h.gen(function* () {
81
86
  let s = e.store;
82
87
  if (s === void 0) return yield* h.die(new I(e.name));
83
- let l = yield* y;
84
- if (l === void 0) return yield* h.die(/* @__PURE__ */ Error(`aiStep('${e.name}'): offload: true is only valid inside a workflow body — there is no execution to suspend here.`));
85
- let { provider: u, model: d } = A(t), m = f(l, e.name), g = yield* h.promise(() => s.query({
88
+ let c = yield* y;
89
+ if (c === void 0) return yield* h.die(/* @__PURE__ */ Error(`aiStep('${e.name}'): offload: true is only valid inside a workflow body — there is no execution to suspend here.`));
90
+ let { provider: l, model: u } = A(t), d = m(c, e.name), g = yield* h.promise(() => s.query({
86
91
  table: "_voltro_workflow_runs",
87
- predicate: _("executionId", l),
92
+ predicate: _("executionId", c),
88
93
  order: [],
89
94
  take: 1,
90
95
  skip: void 0,
91
96
  projection: void 0
92
97
  })), v = String(g[0]?.tag ?? ""), b = g[0]?.id, x = /* @__PURE__ */ new Date();
93
- return yield* h.promise(() => s.insertIgnore(p, {
94
- id: m,
98
+ return yield* h.promise(() => s.insertIgnore(f, {
99
+ id: d,
95
100
  tenantId: e.tenantId ?? null,
96
- executionId: l,
101
+ executionId: c,
97
102
  workflowName: v,
98
103
  runId: typeof b == "string" ? b : null,
99
- signalName: c(m),
104
+ signalName: p(d),
100
105
  stepName: e.name,
101
106
  status: "pending",
102
107
  kind: n,
103
- provider: u,
104
- model: d,
108
+ provider: l,
109
+ model: u,
105
110
  prompt: i.text,
106
111
  system: i.system ?? null,
107
112
  promptId: i.rendered?.promptId ?? null,
@@ -116,61 +121,61 @@ var T = {
116
121
  fence: 0,
117
122
  queuedAt: x,
118
123
  enqueuedAt: x
119
- }, { conflictColumns: ["id"] })), m;
124
+ }, { conflictColumns: ["id"] })), d;
120
125
  }), R = (e, t, n, r, i, a, o, s) => h.gen(function* () {
121
- let l = yield* b;
122
- if (l !== void 0) return yield* h.die(new x(`the offloaded call '${e.name}'`, l));
123
- let u = yield* C({
126
+ let c = yield* b;
127
+ if (c !== void 0) return yield* h.die(new x(`the offloaded call '${e.name}'`, c));
128
+ let l = yield* C({
124
129
  name: `${e.name}:enqueue`,
125
130
  success: g.String,
126
131
  input: i,
127
132
  execute: L(e, t, n, r, a, o, s)
128
133
  });
129
134
  yield* M(e, a.rendered);
130
- let d = yield* S({ store: e.store }, {
131
- name: c(u),
135
+ let u = yield* S({ store: e.store }, {
136
+ name: p(l),
132
137
  schema: g.Unknown,
133
138
  timeoutMs: e.offloadTimeoutMs ?? 36e5
134
139
  });
135
- return P(d) ? yield* h.die(new F(e.name, d.message, d.attempts, d.outcome === "unknown" ? "unknown" : "failed")) : d;
140
+ return P(u) ? yield* h.die(new F(e.name, u.message, u.attempts, u.outcome === "unknown" ? "unknown" : "failed")) : u;
136
141
  }), z = class extends Error {
137
142
  constructor(e) {
138
143
  super(`aiStep('${e}'): budget needs \`store\` — the reservation counter and the hold both live in tables. Pass ctx.store.`), this.name = "AiBudgetMisuseError";
139
144
  }
140
145
  }, B = (e) => h.gen(function* () {
141
- let t = e.budget;
142
- if (t === void 0) return;
143
- let n = e.store;
144
- if (n === void 0) return yield* h.die(new z(e.name));
145
- let r = e.tenantId ?? null, i = t.name ?? "ai-usd", a = yield* y, o = () => d(n, {
146
- tenantId: r,
147
- limitUsd: t.limitUsd,
146
+ let n = e.budget;
147
+ if (n === void 0) return;
148
+ let r = e.store;
149
+ if (r === void 0) return yield* h.die(new z(e.name));
150
+ let i = e.tenantId ?? null, a = n.name ?? "ai-usd", o = yield* y, s = () => t(r, {
151
+ tenantId: i,
152
+ limitUsd: n.limitUsd,
148
153
  addUsd: 0,
149
- ...t.since === void 0 ? {} : { since: t.since }
150
- }).pipe(h.as(null), h.catchTag("AiBudgetExceeded", (e) => h.succeed(e))), s = () => t.estimateUsd === void 0 ? h.void : d(n, {
151
- tenantId: r,
152
- limitUsd: t.limitUsd,
153
- addUsd: t.estimateUsd,
154
- ...a === void 0 ? {} : { reservationId: f(a, JSON.stringify([
154
+ ...n.since === void 0 ? {} : { since: n.since }
155
+ }).pipe(h.as(null), h.catchTag("AiBudgetExceeded", (e) => h.succeed(e))), c = () => n.estimateUsd === void 0 ? h.void : t(r, {
156
+ tenantId: i,
157
+ limitUsd: n.limitUsd,
158
+ addUsd: n.estimateUsd,
159
+ ...o === void 0 ? {} : { reservationId: m(o, JSON.stringify([
155
160
  "budget",
156
- i,
161
+ a,
157
162
  e.name
158
163
  ])) },
159
- ...t.since === void 0 ? {} : { since: t.since }
160
- }).pipe(h.asVoid), c = yield* t.estimateUsd !== void 0 && t.estimateUsd !== 0 ? s().pipe(h.as(null), h.catchTag("AiBudgetExceeded", (e) => h.succeed(e))) : o();
161
- if (c !== null) return (t.onExceeded ?? "fail") !== "suspend" || a === void 0 ? yield* h.fail(c) : (yield* w({
162
- store: n,
163
- budget: i,
164
- tenantId: r,
165
- executionId: a,
166
- workflowName: yield* V(n, a),
164
+ ...n.since === void 0 ? {} : { since: n.since }
165
+ }).pipe(h.asVoid), l = yield* n.estimateUsd !== void 0 && n.estimateUsd !== 0 ? c().pipe(h.as(null), h.catchTag("AiBudgetExceeded", (e) => h.succeed(e))) : s();
166
+ if (l !== null) return (n.onExceeded ?? "fail") !== "suspend" || o === void 0 ? yield* h.fail(l) : (yield* w({
167
+ store: r,
168
+ budget: a,
169
+ tenantId: i,
170
+ executionId: o,
171
+ workflowName: yield* V(r, o),
167
172
  stepName: e.name,
168
- spentMicroUsd: Math.round(c.spentUsd * 1e6),
169
- limitMicroUsd: Math.round(t.limitUsd * 1e6),
170
- hasHeadroom: o().pipe(h.map((e) => e === null)),
171
- ...t.holdTimeoutMs === void 0 ? {} : { timeoutMs: t.holdTimeoutMs },
172
- ...t.recheckEveryMs === void 0 ? {} : { recheckEveryMs: t.recheckEveryMs }
173
- }).pipe(h.catch((e) => e instanceof v ? h.die(e) : h.fail(e))), yield* s());
173
+ spentMicroUsd: Math.round(l.spentUsd * 1e6),
174
+ limitMicroUsd: Math.round(n.limitUsd * 1e6),
175
+ hasHeadroom: s().pipe(h.map((e) => e === null)),
176
+ ...n.holdTimeoutMs === void 0 ? {} : { timeoutMs: n.holdTimeoutMs },
177
+ ...n.recheckEveryMs === void 0 ? {} : { recheckEveryMs: n.recheckEveryMs }
178
+ }).pipe(h.catch((e) => e instanceof v ? h.die(e) : h.fail(e))), yield* c());
174
179
  }), V = (e, t) => h.promise(async () => {
175
180
  let n = await e.query({
176
181
  table: "_voltro_workflow_runs",
@@ -182,28 +187,28 @@ var T = {
182
187
  });
183
188
  return String(n[0]?.tag ?? "");
184
189
  }), H = (t) => {
185
- let r = t.provider ?? e(), i = k(t), a = {
186
- ...A(r),
190
+ let n = t.provider ?? e(), r = k(t), i = {
191
+ ...A(n),
187
192
  operation: "generateText",
188
193
  offloaded: t.offload === !0,
189
- ...O(i.text, i.system, t.recordPrompt ?? "digest", i.rendered)
190
- }, o = (e) => t.budget === void 0 ? e : h.andThen(B(t), e);
191
- return t.offload === !0 ? o(R(t, r, "text", null, a, i)) : o(C({
194
+ ...O(r.text, r.system, t.recordPrompt ?? "digest", r.rendered)
195
+ }, a = (e) => t.budget === void 0 ? e : h.andThen(B(t), e);
196
+ return t.offload === !0 ? a(R(t, n, "text", null, i, r)) : a(C({
192
197
  name: t.name,
193
198
  success: N,
194
- input: a,
199
+ input: i,
195
200
  retry: t.retry ?? T,
196
- execute: n({
197
- prompt: i.text,
198
- provider: r,
199
- ...i.system === void 0 ? {} : { system: i.system },
201
+ execute: o({
202
+ prompt: r.text,
203
+ provider: n,
204
+ ...r.system === void 0 ? {} : { system: r.system },
200
205
  ...t.fallbacks === void 0 ? {} : { fallbacks: t.fallbacks },
201
206
  ...t.maxTokens === void 0 ? {} : { maxTokens: t.maxTokens },
202
207
  ...t.providerOptions === void 0 ? {} : { providerOptions: t.providerOptions },
203
208
  ...t.tools === void 0 ? {} : { tools: t.tools },
204
209
  ...t.maxSteps === void 0 ? {} : { maxSteps: t.maxSteps },
205
210
  ...t.toolContext === void 0 ? {} : { toolContext: t.toolContext }
206
- }).pipe(h.tap((e) => j(t, r, "generateText", e, i.rendered)), h.tap(() => M(t, i.rendered)), h.map((e) => ({
211
+ }).pipe(h.tap((e) => j(t, n, "generateText", e, r.rendered)), h.tap(() => M(t, r.rendered)), h.map((e) => ({
207
212
  text: e.text,
208
213
  inputTokens: e.usage.inputTokens ?? null,
209
214
  outputTokens: e.usage.outputTokens ?? null,
@@ -225,17 +230,17 @@ var T = {
225
230
  ...A(n),
226
231
  operation: "transcribe",
227
232
  offloaded: t.offload === !0
228
- }, o = (e) => t.budget === void 0 ? e : h.andThen(B(t), e);
229
- return t.offload === !0 ? o(R(t, n, "transcription", null, i, {
233
+ }, a = (e) => t.budget === void 0 ? e : h.andThen(B(t), e);
234
+ return t.offload === !0 ? a(R(t, n, "transcription", null, i, {
230
235
  text: "",
231
236
  system: void 0,
232
237
  rendered: void 0
233
- }, r)) : o(C({
238
+ }, r)) : a(C({
234
239
  name: t.name,
235
240
  success: U,
236
241
  input: i,
237
242
  retry: t.retry ?? T,
238
- execute: a({
243
+ execute: c({
239
244
  ...r,
240
245
  provider: n,
241
246
  ...t.resolveRef === void 0 ? {} : { resolveRef: t.resolveRef }
@@ -265,42 +270,42 @@ var T = {
265
270
  ...t,
266
271
  offload: !0
267
272
  }, n, "media", null, a, r, void 0, i));
268
- }, K = (n) => {
269
- let i = n.provider ?? e(), a = k(n), s = {
270
- ...A(i),
273
+ }, K = (t) => {
274
+ let n = t.provider ?? e(), r = k(t), o = {
275
+ ...A(n),
271
276
  operation: "generateObject",
272
- offloaded: n.offload === !0,
273
- ...O(a.text, a.system, n.recordPrompt ?? "digest", a.rendered)
274
- }, c = (e) => n.budget === void 0 ? e : h.andThen(B(n), e);
275
- return n.offload === !0 ? c(h.gen(function* () {
276
- let e = yield* o(n.schema, "aiObjectStep"), t = yield* R(n, i, "object", e, s, a);
277
- return yield* g.decodeUnknownEffect(n.schema)(t);
277
+ offloaded: t.offload === !0,
278
+ ...O(r.text, r.system, t.recordPrompt ?? "digest", r.rendered)
279
+ }, c = (e) => t.budget === void 0 ? e : h.andThen(B(t), e);
280
+ return t.offload === !0 ? c(h.gen(function* () {
281
+ let e = yield* s(t.schema, "aiObjectStep"), i = yield* R(t, n, "object", e, o, r);
282
+ return yield* g.decodeUnknownEffect(t.schema)(i);
278
283
  })) : c(C({
279
- name: n.name,
280
- success: n.schema,
281
- input: s,
282
- retry: n.retry ?? T,
283
- execute: (n.tools === void 0 ? r({
284
- prompt: a.text,
285
- schema: n.schema,
286
- provider: i,
287
- ...a.system === void 0 ? {} : { system: a.system },
288
- ...n.fallbacks === void 0 ? {} : { fallbacks: n.fallbacks },
289
- ...n.maxTokens === void 0 ? {} : { maxTokens: n.maxTokens },
290
- ...n.providerOptions === void 0 ? {} : { providerOptions: n.providerOptions }
291
- }) : t({
292
- prompt: a.text,
293
- schema: n.schema,
294
- provider: i,
295
- tools: n.tools,
296
- ...n.maxSteps === void 0 ? {} : { maxSteps: n.maxSteps },
297
- ...n.toolContext === void 0 ? {} : { toolContext: n.toolContext },
298
- ...a.system === void 0 ? {} : { system: a.system },
299
- ...n.fallbacks === void 0 ? {} : { fallbacks: n.fallbacks },
300
- ...n.maxTokens === void 0 ? {} : { maxTokens: n.maxTokens },
301
- ...n.providerOptions === void 0 ? {} : { providerOptions: n.providerOptions }
302
- })).pipe(h.tap((e) => j(n, i, "generateObject", e, a.rendered)), h.tap(() => M(n, a.rendered)), h.map((e) => e.object))
284
+ name: t.name,
285
+ success: t.schema,
286
+ input: o,
287
+ retry: t.retry ?? T,
288
+ execute: (t.tools === void 0 ? i({
289
+ prompt: r.text,
290
+ schema: t.schema,
291
+ provider: n,
292
+ ...r.system === void 0 ? {} : { system: r.system },
293
+ ...t.fallbacks === void 0 ? {} : { fallbacks: t.fallbacks },
294
+ ...t.maxTokens === void 0 ? {} : { maxTokens: t.maxTokens },
295
+ ...t.providerOptions === void 0 ? {} : { providerOptions: t.providerOptions }
296
+ }) : a({
297
+ prompt: r.text,
298
+ schema: t.schema,
299
+ provider: n,
300
+ tools: t.tools,
301
+ ...t.maxSteps === void 0 ? {} : { maxSteps: t.maxSteps },
302
+ ...t.toolContext === void 0 ? {} : { toolContext: t.toolContext },
303
+ ...r.system === void 0 ? {} : { system: r.system },
304
+ ...t.fallbacks === void 0 ? {} : { fallbacks: t.fallbacks },
305
+ ...t.maxTokens === void 0 ? {} : { maxTokens: t.maxTokens },
306
+ ...t.providerOptions === void 0 ? {} : { providerOptions: t.providerOptions }
307
+ })).pipe(h.tap((e) => j(t, n, "generateObject", e, r.rendered)), h.tap(() => M(t, r.rendered)), h.map((e) => e.object))
303
308
  }));
304
309
  };
305
310
  //#endregion
306
- export { T as AI_STEP_RETRY, z as AiBudgetMisuseError, F as AiOffloadError, I as AiOffloadMisuseError, D as DEFAULT_AI_BUDGET_NAME, E as DEFAULT_OFFLOAD_TIMEOUT_MS, U as TranscriptionStepResult, K as aiObjectStep, H as aiStep, G as mediaStep, s as promptDigest, O as promptRecordFor, k as resolveStepPrompt, W as transcribeStep };
311
+ export { T as AI_STEP_RETRY, z as AiBudgetMisuseError, F as AiOffloadError, I as AiOffloadMisuseError, D as DEFAULT_AI_BUDGET_NAME, E as DEFAULT_OFFLOAD_TIMEOUT_MS, U as TranscriptionStepResult, K as aiObjectStep, H as aiStep, G as mediaStep, u as promptDigest, O as promptRecordFor, k as resolveStepPrompt, W as transcribeStep };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/ai",
3
- "version": "0.85.0",
3
+ "version": "0.86.0",
4
4
  "description": "Effect-native AI primitives — generateText / generateObject / streamText, tools, agents, media generation, cost tracking + budgets, and provider fallback.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -55,10 +55,10 @@
55
55
  "dependencies": {
56
56
  "@ai-sdk/anthropic": "^4.0.56",
57
57
  "@ai-sdk/openai": "^4.0.69",
58
- "@voltro/cache": "0.85.0",
59
- "@voltro/database": "0.85.0",
60
- "@voltro/protocol": "0.85.0",
61
- "@voltro/workflow": "0.85.0",
58
+ "@voltro/cache": "0.86.0",
59
+ "@voltro/database": "0.86.0",
60
+ "@voltro/protocol": "0.86.0",
61
+ "@voltro/workflow": "0.86.0",
62
62
  "ajv": "^8.20.0",
63
63
  "ajv-formats": "^3.0.1",
64
64
  "ws": "^8.21.3"
@@ -1,63 +0,0 @@
1
- import { Schema as e } from "effect";
2
- import { defineAction as t, defineQuery as n } from "@voltro/protocol";
3
- //#region src/agentConstants.ts
4
- var r = "_voltro_agent_threads", i = "_voltro_agent_messages", a = e.Struct({ prompt: e.String }), o = "@voltro/ai/AgentDescriptor", s = class extends e.TaggedError()("AgentThreadAccessDenied", { threadId: e.String }) {
5
- get message() {
6
- return `agent thread '${this.threadId}' belongs to another subject`;
7
- }
8
- }, c = (e) => {
9
- if (e.guards !== void 0 && e.guards.length === 0) throw Error(`defineAgent("${e.name}"): \`guards: []\` is empty, so it enforces nothing —\n but it reads at the call site as if the agent were protected. Omit the field
10
- and decide with \`openAccess\`, or list the scopes that may talk to it.`);
11
- if (e.openAccess !== void 0 && e.guards !== void 0 && e.guards.length > 0) throw Error(`defineAgent("${e.name}"): \`openAccess\` and \`guards\` are two different access\n decisions, so declaring both says the agent is protected AND open. Keep the
12
- guards if a caller must hold a scope; drop them if anyone may talk to it.`);
13
- return {
14
- _brand: o,
15
- name: e.name,
16
- ...e.input === void 0 ? {} : { input: e.input },
17
- ...e.guards === void 0 ? {} : { guards: e.guards },
18
- ...e.openAccess === void 0 ? {} : { openAccess: e.openAccess }
19
- };
20
- }, l = (e) => typeof e == "object" && !!e && e._brand === o, u = (e) => e.input ?? a, d = e.StructWithRest(e.Struct({ type: e.String }), [e.Record(e.String, e.Unknown)]), f = e.Struct({
21
- id: e.String,
22
- threadId: e.String,
23
- role: e.String,
24
- content: e.String,
25
- streaming: e.Boolean,
26
- order: e.Number,
27
- stepOrder: e.Number,
28
- parts: e.Array(d)
29
- }), p = (t) => {
30
- let n = u(t), r = e.Struct({
31
- threadId: e.String,
32
- order: e.Number
33
- });
34
- try {
35
- return e.Struct({
36
- ...n.fields,
37
- ...r.fields
38
- });
39
- } catch {
40
- return r;
41
- }
42
- }, m = (r) => {
43
- let a = {};
44
- return r.openAccess === void 0 ? r.guards !== void 0 && (a.guards = r.guards) : a.openAccess = r.openAccess, {
45
- send: t({
46
- name: `${r.name}.send`,
47
- input: p(r),
48
- output: e.Struct({ text: e.String }),
49
- error: s,
50
- ...a
51
- }),
52
- messages: n({
53
- name: `${r.name}.messages`,
54
- input: e.Struct({ threadId: e.String }),
55
- output: e.Array(f),
56
- source: i,
57
- error: s,
58
- ...a
59
- })
60
- };
61
- };
62
- //#endregion
63
- export { c as a, r as c, m as i, u as n, l as o, f as r, i as s, s as t };