@voltro/ai 0.85.0 → 0.87.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.
- package/CHANGELOG.md +5987 -0
- package/THIRD-PARTY-NOTICES.md +4723 -519
- package/dist/agent.js +64 -2
- package/dist/agentConstants.js +4 -0
- package/dist/agentExecutor.js +55 -0
- package/dist/aiSettings.js +11 -0
- package/dist/api.js +199 -0
- package/dist/appTools.js +80 -0
- package/dist/budget.js +201 -0
- package/dist/callEvidence.js +51 -0
- package/dist/copilot.js +126 -0
- package/dist/cost.js +242 -0
- package/dist/embed.js +41 -0
- package/dist/embeddingProvider.js +69 -0
- package/dist/eval.js +130 -0
- package/dist/events.d.ts +4 -0
- package/dist/events.js +81 -2
- package/dist/executableModalities.js +13 -0
- package/dist/gateway.js +58 -0
- package/dist/gatewayCatalog.js +47 -0
- package/dist/gatewayMedia.js +88 -0
- package/dist/index.d.ts +60 -2
- package/dist/index.js +42 -2750
- package/dist/inferenceDispatch.js +493 -0
- package/dist/inferenceQueue.js +96 -0
- package/dist/jsonOutputValidation.js +27 -0
- package/dist/mcpClient.js +332 -0
- package/dist/mcpTools.js +80 -0
- package/dist/media.js +182 -0
- package/dist/mediaBytes.js +19 -0
- package/dist/mediaCall.js +13 -0
- package/dist/mediaTaskProvider.js +16 -0
- package/dist/middleware.js +32 -0
- package/dist/observe.js +52 -0
- package/dist/prompts.js +103 -0
- package/dist/provider.js +319 -0
- package/dist/realtimeEvent.js +97 -0
- package/dist/realtimeSession.js +154 -0
- package/dist/rerank.js +61 -0
- package/dist/resumableStream.js +321 -0
- package/dist/retrieveReranked.js +16 -0
- package/dist/runAndPersist.js +147 -0
- package/dist/semanticCache.js +66 -0
- package/dist/speechProvider.js +16 -0
- package/dist/streamRegistry.js +14 -0
- package/dist/streamText.js +170 -0
- package/dist/streamTranscribe.js +74 -0
- package/dist/streamWakeups.js +44 -0
- package/dist/structuredEvidence.js +48 -0
- package/dist/test.js +1 -1
- package/dist/threads.js +92 -0
- package/dist/tools.js +68 -0
- package/dist/transcribe.js +64 -0
- package/dist/transcriptionEvent.js +46 -0
- package/dist/workflow.d.ts +2 -0
- package/dist/workflow.js +115 -110
- package/package.json +6 -5
- package/dist/agentDescriptor-DhoiXVqO.js +0 -63
- package/dist/agentEvent-Bl4egdM5.js +0 -211
- package/dist/inferenceQueue-DcEulZep.js +0 -1077
- 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 };
|
package/dist/workflow.d.ts
CHANGED
|
@@ -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 {
|
|
2
|
-
import {
|
|
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:
|
|
32
|
+
promptDigest: u(e),
|
|
28
33
|
promptChars: e.length,
|
|
29
34
|
...t === void 0 ? {} : {
|
|
30
|
-
systemDigest:
|
|
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,
|
|
46
|
-
let
|
|
47
|
-
if (
|
|
48
|
-
let { provider:
|
|
49
|
-
return
|
|
50
|
-
provider:
|
|
51
|
-
model:
|
|
52
|
-
operation:
|
|
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:
|
|
59
|
+
usage: a.usage,
|
|
55
60
|
...e.tenantId === void 0 ? {} : { tenantId: e.tenantId },
|
|
56
|
-
...
|
|
57
|
-
...
|
|
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 :
|
|
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
|
|
84
|
-
if (
|
|
85
|
-
let { provider:
|
|
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",
|
|
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(
|
|
94
|
-
id:
|
|
98
|
+
return yield* h.promise(() => s.insertIgnore(f, {
|
|
99
|
+
id: d,
|
|
95
100
|
tenantId: e.tenantId ?? null,
|
|
96
|
-
executionId:
|
|
101
|
+
executionId: c,
|
|
97
102
|
workflowName: v,
|
|
98
103
|
runId: typeof b == "string" ? b : null,
|
|
99
|
-
signalName:
|
|
104
|
+
signalName: p(d),
|
|
100
105
|
stepName: e.name,
|
|
101
106
|
status: "pending",
|
|
102
107
|
kind: n,
|
|
103
|
-
provider:
|
|
104
|
-
model:
|
|
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"] })),
|
|
124
|
+
}, { conflictColumns: ["id"] })), d;
|
|
120
125
|
}), R = (e, t, n, r, i, a, o, s) => h.gen(function* () {
|
|
121
|
-
let
|
|
122
|
-
if (
|
|
123
|
-
let
|
|
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
|
|
131
|
-
name:
|
|
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(
|
|
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
|
|
142
|
-
if (
|
|
143
|
-
let
|
|
144
|
-
if (
|
|
145
|
-
let
|
|
146
|
-
tenantId:
|
|
147
|
-
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
|
-
...
|
|
150
|
-
}).pipe(h.as(null), h.catchTag("AiBudgetExceeded", (e) => h.succeed(e))),
|
|
151
|
-
tenantId:
|
|
152
|
-
limitUsd:
|
|
153
|
-
addUsd:
|
|
154
|
-
...
|
|
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
|
-
|
|
161
|
+
a,
|
|
157
162
|
e.name
|
|
158
163
|
])) },
|
|
159
|
-
...
|
|
160
|
-
}).pipe(h.asVoid),
|
|
161
|
-
if (
|
|
162
|
-
store:
|
|
163
|
-
budget:
|
|
164
|
-
tenantId:
|
|
165
|
-
executionId:
|
|
166
|
-
workflowName: yield* V(
|
|
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(
|
|
169
|
-
limitMicroUsd: Math.round(
|
|
170
|
-
hasHeadroom:
|
|
171
|
-
...
|
|
172
|
-
...
|
|
173
|
-
}).pipe(h.catch((e) => e instanceof v ? h.die(e) : h.fail(e))), yield*
|
|
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
|
|
186
|
-
...A(
|
|
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(
|
|
190
|
-
},
|
|
191
|
-
return t.offload === !0 ?
|
|
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:
|
|
199
|
+
input: i,
|
|
195
200
|
retry: t.retry ?? T,
|
|
196
|
-
execute:
|
|
197
|
-
prompt:
|
|
198
|
-
provider:
|
|
199
|
-
...
|
|
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,
|
|
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
|
-
},
|
|
229
|
-
return t.offload === !0 ?
|
|
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)) :
|
|
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:
|
|
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 = (
|
|
269
|
-
let
|
|
270
|
-
...A(
|
|
273
|
+
}, K = (t) => {
|
|
274
|
+
let n = t.provider ?? e(), r = k(t), o = {
|
|
275
|
+
...A(n),
|
|
271
276
|
operation: "generateObject",
|
|
272
|
-
offloaded:
|
|
273
|
-
...O(
|
|
274
|
-
}, c = (e) =>
|
|
275
|
-
return
|
|
276
|
-
let e = yield*
|
|
277
|
-
return yield* g.decodeUnknownEffect(
|
|
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:
|
|
280
|
-
success:
|
|
281
|
-
input:
|
|
282
|
-
retry:
|
|
283
|
-
execute: (
|
|
284
|
-
prompt:
|
|
285
|
-
schema:
|
|
286
|
-
provider:
|
|
287
|
-
...
|
|
288
|
-
...
|
|
289
|
-
...
|
|
290
|
-
...
|
|
291
|
-
}) :
|
|
292
|
-
prompt:
|
|
293
|
-
schema:
|
|
294
|
-
provider:
|
|
295
|
-
tools:
|
|
296
|
-
...
|
|
297
|
-
...
|
|
298
|
-
...
|
|
299
|
-
...
|
|
300
|
-
...
|
|
301
|
-
...
|
|
302
|
-
})).pipe(h.tap((e) => j(
|
|
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,
|
|
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.
|
|
3
|
+
"version": "0.87.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,11 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@ai-sdk/anthropic": "^4.0.56",
|
|
57
57
|
"@ai-sdk/openai": "^4.0.69",
|
|
58
|
-
"@voltro/cache": "0.
|
|
59
|
-
"@voltro/database": "0.
|
|
60
|
-
"@voltro/
|
|
61
|
-
"@voltro/
|
|
58
|
+
"@voltro/cache": "0.87.0",
|
|
59
|
+
"@voltro/database": "0.87.0",
|
|
60
|
+
"@voltro/env": "0.87.0",
|
|
61
|
+
"@voltro/protocol": "0.87.0",
|
|
62
|
+
"@voltro/workflow": "0.87.0",
|
|
62
63
|
"ajv": "^8.20.0",
|
|
63
64
|
"ajv-formats": "^3.0.1",
|
|
64
65
|
"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 };
|