@voltro/ai 0.84.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 (61) hide show
  1. package/CHANGELOG.md +1215 -0
  2. package/THIRD-PARTY-NOTICES.md +5 -151
  3. package/dist/agent.d.ts +34 -41
  4. package/dist/agent.js +64 -2
  5. package/dist/agentConstants.js +4 -0
  6. package/dist/agentExecutor.js +51 -0
  7. package/dist/api.js +199 -0
  8. package/dist/appTools.js +80 -0
  9. package/dist/budget.js +201 -0
  10. package/dist/callEvidence.js +51 -0
  11. package/dist/copilot.js +126 -0
  12. package/dist/cost.js +242 -0
  13. package/dist/embed.js +41 -0
  14. package/dist/embeddingProvider.js +51 -0
  15. package/dist/eval.js +130 -0
  16. package/dist/events.d.ts +171 -168
  17. package/dist/events.js +81 -2
  18. package/dist/executableModalities.js +13 -0
  19. package/dist/gateway.js +58 -0
  20. package/dist/gatewayCatalog.js +47 -0
  21. package/dist/gatewayMedia.js +88 -0
  22. package/dist/index.d.ts +328 -326
  23. package/dist/index.js +42 -2581
  24. package/dist/inferenceDispatch.js +493 -0
  25. package/dist/inferenceQueue.js +96 -0
  26. package/dist/jsonOutputValidation.js +27 -0
  27. package/dist/mcpClient.js +332 -0
  28. package/dist/mcpTools.js +80 -0
  29. package/dist/media.js +182 -0
  30. package/dist/mediaBytes.js +19 -0
  31. package/dist/mediaCall.js +13 -0
  32. package/dist/mediaTaskProvider.js +16 -0
  33. package/dist/middleware.js +32 -0
  34. package/dist/observe.js +52 -0
  35. package/dist/prompts.js +103 -0
  36. package/dist/provider.js +303 -0
  37. package/dist/realtimeEvent.js +97 -0
  38. package/dist/realtimeSession.js +154 -0
  39. package/dist/rerank.js +61 -0
  40. package/dist/resumableStream.js +321 -0
  41. package/dist/retrieveReranked.js +16 -0
  42. package/dist/runAndPersist.js +148 -0
  43. package/dist/semanticCache.js +66 -0
  44. package/dist/speechProvider.js +16 -0
  45. package/dist/streamRegistry.js +14 -0
  46. package/dist/streamText.js +170 -0
  47. package/dist/streamTranscribe.js +74 -0
  48. package/dist/streamWakeups.js +44 -0
  49. package/dist/structuredEvidence.js +48 -0
  50. package/dist/test.js +1 -1
  51. package/dist/threads.js +92 -0
  52. package/dist/tools.js +68 -0
  53. package/dist/transcribe.js +64 -0
  54. package/dist/transcriptionEvent.js +46 -0
  55. package/dist/workflow.d.ts +12 -10
  56. package/dist/workflow.js +117 -112
  57. package/package.json +6 -6
  58. package/dist/agentDescriptor-DuxvWGDi.js +0 -63
  59. package/dist/agentEvent-BuXA7sRt.js +0 -152
  60. package/dist/inferenceQueue-BmtEm3YI.js +0 -1061
  61. 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 };
@@ -1,7 +1,7 @@
1
+ import { Context } from 'effect';
1
2
  import { DataStore } from '@voltro/database';
2
3
  import { Effect } from 'effect';
3
4
  import { PluginMediaPersistMetadata } from '@voltro/protocol';
4
- import { Runtime } from 'effect';
5
5
  import { Schema } from 'effect';
6
6
  import { StepRetryPolicy } from '@voltro/workflow';
7
7
 
@@ -39,7 +39,7 @@ declare type AiJsonValue = null | boolean | number | string | {
39
39
  export declare const aiObjectStep: <A, I>(options: AiObjectStepOptions<A, I>) => Effect.Effect<A, unknown>;
40
40
 
41
41
  export declare interface AiObjectStepOptions<A, I> extends AiStepBaseOptions {
42
- readonly schema: Schema.Schema<A, I>;
42
+ readonly schema: Schema.Codec<A, I>;
43
43
  }
44
44
 
45
45
  export declare class AiOffloadError extends Error {
@@ -209,13 +209,15 @@ declare type AnthropicModel = 'claude-opus-4-8' | 'claude-sonnet-4-6' | 'claude-
209
209
  declare interface AnyTool {
210
210
  readonly name: string;
211
211
  readonly description: string;
212
- readonly input: Schema.Schema.Any;
212
+ readonly input: Schema.Top;
213
213
  /** See `ToolDef.inputJsonSchema` — a foreign parameter schema shown to the
214
214
  * model in place of a rendered `input`. */
215
215
  readonly inputJsonSchema?: Record<string, unknown>;
216
- readonly output?: Schema.Schema.Any;
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
 
@@ -547,18 +549,18 @@ export declare const resolveStepPrompt: (options: Pick<AiStepBaseOptions, "promp
547
549
  * CLI discovery path passes the real `AppContext`, which is a superset.
548
550
  *
549
551
  * `runtime` is the caller's ambient Effect `Runtime`. When present, tool
550
- * bodies are run through it (`Runtime.runPromise(runtime)(eff)`) instead of
552
+ * bodies are run through it (`Effect.runPromiseWith(runtime)(eff)`) instead of
551
553
  * bare `Effect.runPromise`, so a body may `yield*` any service the caller's
552
554
  * runtime carries — `JiraService`, the data store layer, `HttpClient`, … —
553
555
  * rather than being limited to `R = never`. The agent loop
554
- * (`streamText`/`runAssistant`) captures `yield* Effect.runtime()` and threads
556
+ * (`streamText`/`runAssistant`) captures `yield* Effect.context<never>()` and threads
555
557
  * it here; without a runtime, behaviour is unchanged. */
556
558
  declare interface ToolContext {
557
559
  readonly store: unknown;
558
560
  readonly request?: {
559
561
  readonly subject?: unknown;
560
562
  };
561
- readonly runtime?: Runtime.Runtime<unknown>;
563
+ readonly runtime?: Context.Context<never>;
562
564
  /** SDK tool-call identity for this execution, not a durable application idempotency key. */
563
565
  readonly invocationId?: string;
564
566
  /** Cancellation from either the caller's turn or SDK invocation; Promise handlers must pass it to their I/O. */
@@ -628,9 +630,9 @@ declare type TranscriptionSource =
628
630
  /** What a `transcribeStep` journals. Structural, because a durable step's
629
631
  * success schema is what a replay decodes through — see `AiStepText`. */
630
632
  export declare const TranscriptionStepResult: Schema.Struct<{
631
- text: typeof Schema.String;
632
- language: Schema.optional<typeof Schema.String>;
633
- durationSec: Schema.optional<typeof Schema.Number>;
633
+ readonly text: Schema.String;
634
+ readonly language: Schema.optional<Schema.String>;
635
+ readonly durationSec: Schema.optional<Schema.Number>;
634
636
  }>;
635
637
 
636
638
  /** How much timestamp detail to ask for. Providers charge for it. */
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-BmtEm3YI.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,26 +47,26 @@ 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
- }).pipe(h.asVoid, h.catchAllCause(() => h.void));
69
+ }).pipe(h.asVoid, h.catchCause(() => h.void));
65
70
  }, N = g.Struct({
66
71
  text: g.String,
67
72
  inputTokens: g.NullOr(g.Number),
@@ -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.catchAll((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.zipRight(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.zipRight(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 }
@@ -261,46 +266,46 @@ var T = {
261
266
  modality: t.modality,
262
267
  ...O(r.text, void 0, t.recordPrompt ?? "digest", r.rendered)
263
268
  };
264
- return ((e) => t.budget === void 0 ? e : h.zipRight(B(t), e))(R({
269
+ return ((e) => t.budget === void 0 ? e : h.andThen(B(t), e))(R({
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.zipRight(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.decodeUnknown(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.84.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.84.0",
59
- "@voltro/database": "0.84.0",
60
- "@voltro/protocol": "0.84.0",
61
- "@voltro/workflow": "0.84.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"
@@ -67,7 +67,7 @@
67
67
  "@ai-sdk/gateway": "^4.0.74",
68
68
  "@ai-sdk/provider": "^4.0.10",
69
69
  "ai": "^7.0.92",
70
- "effect": "^3.22.2"
70
+ "effect": "4.0.1"
71
71
  },
72
72
  "publishConfig": {
73
73
  "access": "public"