@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.
- package/CHANGELOG.md +1215 -0
- package/THIRD-PARTY-NOTICES.md +5 -151
- package/dist/agent.d.ts +34 -41
- package/dist/agent.js +64 -2
- package/dist/agentConstants.js +4 -0
- package/dist/agentExecutor.js +51 -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 +51 -0
- package/dist/eval.js +130 -0
- package/dist/events.d.ts +171 -168
- 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 +328 -326
- package/dist/index.js +42 -2581
- 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 +303 -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 +148 -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 +12 -10
- package/dist/workflow.js +117 -112
- package/package.json +6 -6
- package/dist/agentDescriptor-DuxvWGDi.js +0 -63
- package/dist/agentEvent-BuXA7sRt.js +0 -152
- package/dist/inferenceQueue-BmtEm3YI.js +0 -1061
- package/dist/provider-BnemgE4D.js +0 -409
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { providerFromEnv as e } from "./provider.js";
|
|
2
|
+
import { recordAiUsageBestEffort as t } from "./cost.js";
|
|
3
|
+
import { streamText as n } from "./streamText.js";
|
|
4
|
+
import { AGENT_MESSAGES_TABLE as r, AGENT_THREADS_TABLE as i } from "./agentConstants.js";
|
|
5
|
+
import { Effect as a, Stream as o } from "effect";
|
|
6
|
+
//#region src/runAndPersist.ts
|
|
7
|
+
var s = (e) => [...e].sort((e, t) => e.order - t.order || e.stepOrder - t.stepOrder).filter((e) => !e.streaming && e.content.length > 0 && (e.role === "user" || e.role === "assistant")).map((e) => e.role === "user" ? {
|
|
8
|
+
role: "user",
|
|
9
|
+
content: e.content
|
|
10
|
+
} : {
|
|
11
|
+
role: "assistant",
|
|
12
|
+
content: e.content
|
|
13
|
+
}), c = (e, t) => a.promise(async () => {
|
|
14
|
+
let n = await e.insert(r, {
|
|
15
|
+
threadId: t.threadId,
|
|
16
|
+
tenantId: t.tenantId ?? null,
|
|
17
|
+
role: "assistant",
|
|
18
|
+
content: "",
|
|
19
|
+
streaming: !0,
|
|
20
|
+
order: t.order,
|
|
21
|
+
stepOrder: 0,
|
|
22
|
+
parts: [],
|
|
23
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
24
|
+
});
|
|
25
|
+
return await e.update(i, t.threadId, { updatedAt: /* @__PURE__ */ new Date() }).catch(() => null), n.id;
|
|
26
|
+
}), l = (e, t, n) => a.promise(async () => {
|
|
27
|
+
await e.update(r, t, {
|
|
28
|
+
parts: n,
|
|
29
|
+
content: u(n)
|
|
30
|
+
});
|
|
31
|
+
}), u = (e) => e.filter((e) => e.type === "text").map((e) => e.text).join(""), d = (i, s) => a.gen(function* () {
|
|
32
|
+
let d = yield* c(i, {
|
|
33
|
+
threadId: s.threadId,
|
|
34
|
+
tenantId: s.tenantId ?? null,
|
|
35
|
+
order: s.order
|
|
36
|
+
}), f = "", p = "", m = /* @__PURE__ */ new Map(), h = [], g = [], _ = [], v = 0, y = null, b, x = s.throttleMs ?? 100, S = () => {
|
|
37
|
+
let e = [];
|
|
38
|
+
f.length > 0 && e.push({
|
|
39
|
+
type: "reasoning",
|
|
40
|
+
text: f
|
|
41
|
+
}), p.length > 0 && e.push({
|
|
42
|
+
type: "text",
|
|
43
|
+
text: p
|
|
44
|
+
});
|
|
45
|
+
for (let t of m.values()) e.push(t);
|
|
46
|
+
for (let t of h) e.push(t);
|
|
47
|
+
for (let t of g) e.push(t);
|
|
48
|
+
for (let t of _) e.push(t);
|
|
49
|
+
return e;
|
|
50
|
+
}, C = (e) => {
|
|
51
|
+
let t = Date.now();
|
|
52
|
+
return !e && t - v < x ? a.void : (v = t, l(i, d, S()));
|
|
53
|
+
};
|
|
54
|
+
yield* n({
|
|
55
|
+
prompt: s.prompt,
|
|
56
|
+
...s.messages === void 0 ? {} : { messages: s.messages },
|
|
57
|
+
...s.system === void 0 ? {} : { system: s.system },
|
|
58
|
+
...s.tools === void 0 ? {} : { tools: s.tools },
|
|
59
|
+
...s.provider === void 0 ? {} : { provider: s.provider },
|
|
60
|
+
...s.maxSteps === void 0 ? {} : { maxSteps: s.maxSteps },
|
|
61
|
+
...s.toolContext === void 0 ? {} : { toolContext: s.toolContext },
|
|
62
|
+
...s.providerOptions === void 0 ? {} : { providerOptions: s.providerOptions }
|
|
63
|
+
}).pipe(o.runForEach((e) => a.gen(function* () {
|
|
64
|
+
switch (e._tag) {
|
|
65
|
+
case "token":
|
|
66
|
+
p += e.text, yield* C(!1);
|
|
67
|
+
break;
|
|
68
|
+
case "toolCall":
|
|
69
|
+
m.set(e.id, {
|
|
70
|
+
type: "tool",
|
|
71
|
+
toolCallId: e.id,
|
|
72
|
+
toolName: e.name,
|
|
73
|
+
state: "input-available",
|
|
74
|
+
input: e.input,
|
|
75
|
+
...e.execution === void 0 ? {} : { execution: e.execution }
|
|
76
|
+
}), yield* C(!0);
|
|
77
|
+
break;
|
|
78
|
+
case "toolResult": {
|
|
79
|
+
let t = m.get(e.id);
|
|
80
|
+
m.set(e.id, {
|
|
81
|
+
type: "tool",
|
|
82
|
+
toolCallId: e.id,
|
|
83
|
+
toolName: e.name,
|
|
84
|
+
state: e.error ? "output-error" : "output-available",
|
|
85
|
+
input: t?.input,
|
|
86
|
+
output: e.output,
|
|
87
|
+
...e.error ? { errorText: e.error } : {}
|
|
88
|
+
}), yield* C(!0);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
case "reasoning":
|
|
92
|
+
f += e.text, yield* C(!1);
|
|
93
|
+
break;
|
|
94
|
+
case "source": {
|
|
95
|
+
let { _tag: t, ...n } = e;
|
|
96
|
+
h.push({
|
|
97
|
+
type: t,
|
|
98
|
+
...n
|
|
99
|
+
}), yield* C(!0);
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case "file": {
|
|
103
|
+
let { _tag: t, ...n } = e;
|
|
104
|
+
g.push({
|
|
105
|
+
type: t,
|
|
106
|
+
...n
|
|
107
|
+
}), yield* C(!0);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
case "stepMetadata": {
|
|
111
|
+
let { _tag: t, ...n } = e;
|
|
112
|
+
_.push({
|
|
113
|
+
type: t,
|
|
114
|
+
...n
|
|
115
|
+
}), yield* C(!0);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case "error":
|
|
119
|
+
y = e.message;
|
|
120
|
+
break;
|
|
121
|
+
case "done": b = e.usage;
|
|
122
|
+
}
|
|
123
|
+
})));
|
|
124
|
+
let w = S();
|
|
125
|
+
if (yield* a.promise(() => i.update(r, d, {
|
|
126
|
+
parts: w,
|
|
127
|
+
content: u(w),
|
|
128
|
+
streaming: !1
|
|
129
|
+
})), s.recordUsage !== !1 && b !== void 0) {
|
|
130
|
+
let n = s.provider ?? e();
|
|
131
|
+
yield* t(i, {
|
|
132
|
+
tenantId: s.tenantId ?? null,
|
|
133
|
+
provider: n.name,
|
|
134
|
+
model: n.model ?? "unknown",
|
|
135
|
+
operation: "agent.turn",
|
|
136
|
+
agent: s.agent ?? null,
|
|
137
|
+
requestId: d,
|
|
138
|
+
usage: {
|
|
139
|
+
inputTokens: b.inputTokens,
|
|
140
|
+
outputTokens: b.outputTokens,
|
|
141
|
+
...b.totalTokens === void 0 ? {} : { totalTokens: b.totalTokens }
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return y ? yield* a.fail(Error(y)) : u(w);
|
|
146
|
+
});
|
|
147
|
+
//#endregion
|
|
148
|
+
export { c as appendStreamingMessage, s as historyToModelMessages, l as patchStreamingMessage, d as runAssistant };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { generateObject as e, generateText as t } from "./api.js";
|
|
2
|
+
import { embed as n } from "./embed.js";
|
|
3
|
+
import { Effect as r, Option as i } from "effect";
|
|
4
|
+
import { rowDep as a, tableDep as o } from "@voltro/cache";
|
|
5
|
+
//#region src/semanticCache.ts
|
|
6
|
+
var s = {
|
|
7
|
+
inputTokens: 0,
|
|
8
|
+
outputTokens: 0,
|
|
9
|
+
totalTokens: 0
|
|
10
|
+
}, c = .95, l = (e, t) => t === void 0 ? e : `${t}\n\n${e}`, u = (e, t, n) => e.lookup(t, { threshold: n }).pipe(r.catchTag("CacheError", () => r.succeed(i.none()))), d = (e, t, n, i) => e.put(t, n, {
|
|
11
|
+
deps: i.deps,
|
|
12
|
+
...i.ttlMs === void 0 ? {} : { ttlMs: i.ttlMs }
|
|
13
|
+
}).pipe(r.catchTag("CacheError", () => r.void)), f = (e, a, o) => r.gen(function* () {
|
|
14
|
+
if (e.messages !== void 0 || e.prompt === void 0) {
|
|
15
|
+
let n = yield* t(e);
|
|
16
|
+
return {
|
|
17
|
+
value: n.text,
|
|
18
|
+
cached: !1,
|
|
19
|
+
usage: n.usage
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
let r = o.embed ?? n, f = a.threshold ?? c, p = yield* r(l(e.prompt, e.system)), m = yield* u(o.cache, p, f);
|
|
23
|
+
if (i.isSome(m)) return {
|
|
24
|
+
value: m.value,
|
|
25
|
+
cached: !0,
|
|
26
|
+
usage: s
|
|
27
|
+
};
|
|
28
|
+
let h = yield* t(e);
|
|
29
|
+
return yield* d(o.cache, p, h.text, a), {
|
|
30
|
+
value: h.text,
|
|
31
|
+
cached: !1,
|
|
32
|
+
usage: h.usage
|
|
33
|
+
};
|
|
34
|
+
}), p = (t, a, o) => r.gen(function* () {
|
|
35
|
+
let r = o.embed ?? n, f = a.threshold ?? c, p = yield* r(l(t.prompt, t.system)), m = yield* u(o.cache, p, f);
|
|
36
|
+
if (i.isSome(m)) return {
|
|
37
|
+
value: m.value,
|
|
38
|
+
cached: !0,
|
|
39
|
+
usage: s
|
|
40
|
+
};
|
|
41
|
+
let h = yield* e(t);
|
|
42
|
+
return yield* d(o.cache, p, h.object, a), {
|
|
43
|
+
value: h.object,
|
|
44
|
+
cached: !1,
|
|
45
|
+
usage: h.usage
|
|
46
|
+
};
|
|
47
|
+
}), m = (e) => {
|
|
48
|
+
let t = /* @__PURE__ */ new Set(), n = async (n) => {
|
|
49
|
+
let r = await e.query(n);
|
|
50
|
+
t.add(o(n.table));
|
|
51
|
+
for (let e of r) {
|
|
52
|
+
let r = e.id;
|
|
53
|
+
r != null && t.add(a(n.table, String(r)));
|
|
54
|
+
}
|
|
55
|
+
return r;
|
|
56
|
+
};
|
|
57
|
+
return {
|
|
58
|
+
store: new Proxy(e, { get(e, t, r) {
|
|
59
|
+
return t === "query" ? n : Reflect.get(e, t, r);
|
|
60
|
+
} }),
|
|
61
|
+
deps: () => [...t],
|
|
62
|
+
reset: () => t.clear()
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
//#endregion
|
|
66
|
+
export { m as recordReads, p as semanticGenerateObject, f as semanticGenerateText };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//#region src/speechProvider.ts
|
|
2
|
+
var e = Symbol.for("@voltro/ai/speechProviders"), t = globalThis, n = () => t[e] ?? (t[e] = /* @__PURE__ */ new Map()), r = [
|
|
3
|
+
"mock",
|
|
4
|
+
"openai",
|
|
5
|
+
"gateway",
|
|
6
|
+
"anthropic"
|
|
7
|
+
], i = (e, t, i = {}) => {
|
|
8
|
+
if (r.includes(e) && i.replaceBuiltin !== !0) throw Error(`registerSpeechProvider: '${e}' is a built-in provider name.\n Shadowing one by accident would make the same config mean different things depending on which module loaded first.
|
|
9
|
+
→ if you meant it, say so: registerSpeechProvider('${e}', provider, { replaceBuiltin: true }). That is the right call when the name is not yours to choose — a gateway model id's provider segment, say, that your stored rows already carry.
|
|
10
|
+
→ otherwise pick another name.`);
|
|
11
|
+
n().set(e, t);
|
|
12
|
+
}, a = (e) => r.includes(e) && n().has(e), o = (e) => n().get(e), s = () => [...n().keys()].sort(), c = () => {
|
|
13
|
+
n().clear();
|
|
14
|
+
};
|
|
15
|
+
//#endregion
|
|
16
|
+
export { r as BUILTIN_SPEECH_PROVIDERS, c as clearSpeechProviders, i as registerSpeechProvider, s as registeredSpeechProviders, a as replacesBuiltinSpeechProvider, o as speechProvider };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/streamRegistry.ts
|
|
2
|
+
var e = /* @__PURE__ */ new Map(), t = (t) => {
|
|
3
|
+
let n = e.get(t);
|
|
4
|
+
if (n) return n;
|
|
5
|
+
let r = new AbortController();
|
|
6
|
+
return e.set(t, r), r;
|
|
7
|
+
}, n = (t) => {
|
|
8
|
+
let n = e.get(t);
|
|
9
|
+
return n ? (e.delete(t), n.abort(), !0) : !1;
|
|
10
|
+
}, r = (t) => e.has(t), i = (t) => {
|
|
11
|
+
e.delete(t);
|
|
12
|
+
}, a = () => e.size;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { a as activeStreamCount, n as cancelStream, r as isStreamActive, t as registerStream, i as unregisterStream };
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { providerFromEnv as e, resolveModel as t } from "./provider.js";
|
|
2
|
+
import { buildSdkTools as n } from "./tools.js";
|
|
3
|
+
import { aiCallAttributes as r, observeStream as i } from "./observe.js";
|
|
4
|
+
import { registerStream as a, unregisterStream as o } from "./streamRegistry.js";
|
|
5
|
+
import { smoothStream as s, stepCountIs as c, streamText as l } from "ai";
|
|
6
|
+
import { Duration as u, Effect as d, Stream as f } from "effect";
|
|
7
|
+
//#region src/streamText.ts
|
|
8
|
+
var p = (e) => {
|
|
9
|
+
let t = e?.name, n = String(e?.message ?? e ?? "");
|
|
10
|
+
return t === "AbortError" || t === "TimeoutError" || /\babort(ed)?\b/i.test(n);
|
|
11
|
+
}, m = (e, t) => e === null ? Promise.resolve() : t.aborted ? Promise.reject(t.reason ?? new DOMException("stream aborted", "AbortError")) : new Promise((n, r) => {
|
|
12
|
+
let i = setTimeout(() => {
|
|
13
|
+
t.removeEventListener("abort", a), n();
|
|
14
|
+
}, e), a = () => {
|
|
15
|
+
clearTimeout(i), t.removeEventListener("abort", a), r(t.reason ?? new DOMException("stream aborted", "AbortError"));
|
|
16
|
+
};
|
|
17
|
+
t.addEventListener("abort", a, { once: !0 });
|
|
18
|
+
}), h = (e, t) => () => {
|
|
19
|
+
let n;
|
|
20
|
+
return new TransformStream({ async transform(r, i) {
|
|
21
|
+
r.type !== "text-delta" && r.type !== "reasoning-delta" ? (n = void 0, i.enqueue(r)) : (n?.type === r.type && n.id === r.id && await m(e, t), i.enqueue(r), n = {
|
|
22
|
+
type: r.type,
|
|
23
|
+
id: r.id
|
|
24
|
+
});
|
|
25
|
+
} });
|
|
26
|
+
}, g = (e, t) => {
|
|
27
|
+
switch (e?.type) {
|
|
28
|
+
case "text-delta": return {
|
|
29
|
+
_tag: "token",
|
|
30
|
+
text: e.text ?? e.delta ?? ""
|
|
31
|
+
};
|
|
32
|
+
case "reasoning-delta":
|
|
33
|
+
case "reasoning": return {
|
|
34
|
+
_tag: "reasoning",
|
|
35
|
+
text: e.text ?? e.delta ?? ""
|
|
36
|
+
};
|
|
37
|
+
case "tool-call": return {
|
|
38
|
+
_tag: "toolCall",
|
|
39
|
+
id: e.toolCallId ?? "",
|
|
40
|
+
name: e.toolName ?? "",
|
|
41
|
+
input: e.input
|
|
42
|
+
};
|
|
43
|
+
case "tool-result": return {
|
|
44
|
+
_tag: "toolResult",
|
|
45
|
+
id: e.toolCallId ?? "",
|
|
46
|
+
name: e.toolName ?? "",
|
|
47
|
+
output: e.output
|
|
48
|
+
};
|
|
49
|
+
case "tool-error": return {
|
|
50
|
+
_tag: "toolResult",
|
|
51
|
+
id: e.toolCallId ?? "",
|
|
52
|
+
name: e.toolName ?? "",
|
|
53
|
+
error: String(e.error?.message ?? e.error ?? "tool error")
|
|
54
|
+
};
|
|
55
|
+
case "source": return {
|
|
56
|
+
_tag: "source",
|
|
57
|
+
sourceType: e.sourceType === "document" ? "document" : "url",
|
|
58
|
+
id: e.id ?? "",
|
|
59
|
+
...e.url === void 0 ? {} : { url: e.url },
|
|
60
|
+
...e.title === void 0 ? {} : { title: e.title },
|
|
61
|
+
...e.mediaType === void 0 ? {} : { mediaType: e.mediaType },
|
|
62
|
+
...e.filename === void 0 ? {} : { filename: e.filename },
|
|
63
|
+
...e.providerMetadata === void 0 ? {} : { providerMetadata: e.providerMetadata }
|
|
64
|
+
};
|
|
65
|
+
case "file": return e.file ? {
|
|
66
|
+
_tag: "file",
|
|
67
|
+
mediaType: e.file.mediaType,
|
|
68
|
+
data: e.file.base64,
|
|
69
|
+
...e.providerMetadata === void 0 ? {} : { providerMetadata: e.providerMetadata }
|
|
70
|
+
} : null;
|
|
71
|
+
case "finish-step": return e.providerMetadata === void 0 ? null : {
|
|
72
|
+
_tag: "stepMetadata",
|
|
73
|
+
step: t,
|
|
74
|
+
providerMetadata: e.providerMetadata
|
|
75
|
+
};
|
|
76
|
+
case "abort": return {
|
|
77
|
+
_tag: "error",
|
|
78
|
+
code: "cancelled",
|
|
79
|
+
message: "stream aborted",
|
|
80
|
+
retryable: !1
|
|
81
|
+
};
|
|
82
|
+
case "finish": return {
|
|
83
|
+
_tag: "done",
|
|
84
|
+
finishReason: String(e.finishReason ?? "stop"),
|
|
85
|
+
usage: {
|
|
86
|
+
inputTokens: e.totalUsage?.inputTokens,
|
|
87
|
+
outputTokens: e.totalUsage?.outputTokens,
|
|
88
|
+
totalTokens: e.totalUsage?.totalTokens
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
case "error": return {
|
|
92
|
+
_tag: "error",
|
|
93
|
+
code: "provider",
|
|
94
|
+
message: String(e.error),
|
|
95
|
+
retryable: !0
|
|
96
|
+
};
|
|
97
|
+
default: return null;
|
|
98
|
+
}
|
|
99
|
+
}, _ = (u) => f.unwrap(d.gen(function* () {
|
|
100
|
+
let m = yield* d.context(), _ = u.provider ?? e(), v = t(_), y = u.tools ? {
|
|
101
|
+
store: void 0,
|
|
102
|
+
...u.toolContext,
|
|
103
|
+
runtime: m
|
|
104
|
+
} : u.toolContext, b = u.tools ? n(u.tools, y) : void 0, x = new Set(Object.entries(b ?? {}).filter(([, e]) => e.execute === void 0).map(([e]) => e)), S = u.streamId === void 0 ? new AbortController() : a(u.streamId);
|
|
105
|
+
u.signal !== void 0 && (u.signal.aborted ? S.abort() : u.signal.addEventListener("abort", () => S.abort(), { once: !0 }));
|
|
106
|
+
let C = S.signal, w = u.smooth === !1 ? void 0 : u.smooth, T = l({
|
|
107
|
+
model: v,
|
|
108
|
+
...u.messages === void 0 ? { prompt: u.prompt } : { messages: [...u.messages] },
|
|
109
|
+
...u.system === void 0 ? {} : { system: u.system },
|
|
110
|
+
...u.maxTokens === void 0 ? {} : { maxOutputTokens: u.maxTokens },
|
|
111
|
+
...u.temperature === void 0 ? {} : { temperature: u.temperature },
|
|
112
|
+
...u.providerOptions === void 0 ? {} : { providerOptions: u.providerOptions },
|
|
113
|
+
...u.maxRetries === void 0 ? {} : { maxRetries: u.maxRetries },
|
|
114
|
+
abortSignal: C,
|
|
115
|
+
...w === void 0 ? {} : { experimental_transform: [s({
|
|
116
|
+
...w.chunking === void 0 ? {} : { chunking: w.chunking },
|
|
117
|
+
delayInMs: null
|
|
118
|
+
}), h(w.delayMs === void 0 ? 10 : w.delayMs, C)] },
|
|
119
|
+
...b ? {
|
|
120
|
+
tools: b,
|
|
121
|
+
stopWhen: c(u.maxSteps ?? 8)
|
|
122
|
+
} : {}
|
|
123
|
+
}), E = 0;
|
|
124
|
+
return i(r(_, "streamText"), f.fromAsyncIterable(T.fullStream, (e) => e).pipe(f.map((e) => {
|
|
125
|
+
let t = g(e, E), n = t?._tag === "toolCall" && x.has(t.name) ? {
|
|
126
|
+
...t,
|
|
127
|
+
execution: "client"
|
|
128
|
+
} : t;
|
|
129
|
+
return e.type === "finish-step" && (E += 1), n;
|
|
130
|
+
}), f.filter((e) => e !== null), f.catch((e) => {
|
|
131
|
+
let t = C.aborted || p(e);
|
|
132
|
+
return f.make({
|
|
133
|
+
_tag: "error",
|
|
134
|
+
code: t ? "cancelled" : "provider",
|
|
135
|
+
message: t ? "stream aborted" : String(e),
|
|
136
|
+
retryable: !t
|
|
137
|
+
});
|
|
138
|
+
}), f.ensuring(d.sync(() => {
|
|
139
|
+
S.abort(), u.streamId !== void 0 && o(u.streamId);
|
|
140
|
+
}))));
|
|
141
|
+
})), v = (e) => e._tag === "token" || e._tag === "reasoning" || e._tag === "toolCall" || e._tag === "toolResult" || e._tag === "source" || e._tag === "file" || e._tag === "message" || e._tag === "stepMetadata", y = (e) => e._tag === "done" || e._tag === "error", b = (e, t = {}) => {
|
|
142
|
+
let n = Math.max(1, t.maxAttempts ?? 3), r = t.backoffMs ?? 250, i = t.maxBackoffMs ?? 5e3, a = [e.provider, ...e.fallbacks ?? []], o = (t, s) => {
|
|
143
|
+
let c = !1, l = a[t];
|
|
144
|
+
return _(l === void 0 ? e : {
|
|
145
|
+
...e,
|
|
146
|
+
provider: l
|
|
147
|
+
}).pipe(f.takeUntil(y), f.flatMap((e) => {
|
|
148
|
+
if (e._tag === "error" && e.retryable && !c) {
|
|
149
|
+
if (s + 1 < n) {
|
|
150
|
+
let e = Math.min(i, r * 2 ** s);
|
|
151
|
+
return f.unwrap(d.as(d.sleep(u.millis(e)), o(t, s + 1)));
|
|
152
|
+
}
|
|
153
|
+
if (t + 1 < a.length) return o(t + 1, 0);
|
|
154
|
+
}
|
|
155
|
+
return v(e) && (c = !0), f.make(e);
|
|
156
|
+
}, { concurrency: 1 }));
|
|
157
|
+
};
|
|
158
|
+
return o(0, 0);
|
|
159
|
+
}, x = (e) => {
|
|
160
|
+
let t = [e.provider, ...e.fallbacks ?? []], n = (r) => {
|
|
161
|
+
let i = !1, a = t[r];
|
|
162
|
+
return _(a === void 0 ? e : {
|
|
163
|
+
...e,
|
|
164
|
+
provider: a
|
|
165
|
+
}).pipe(f.takeUntil(y), f.flatMap((e) => e._tag === "error" && e.retryable && !i && r + 1 < t.length ? n(r + 1) : (v(e) && (i = !0), f.make(e)), { concurrency: 1 }));
|
|
166
|
+
};
|
|
167
|
+
return n(0);
|
|
168
|
+
};
|
|
169
|
+
//#endregion
|
|
170
|
+
export { _ as streamText, x as streamTextWithFallback, b as streamTextWithRetry };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { providerFromEnv as e, resolveTranscriptionModel as t } from "./provider.js";
|
|
2
|
+
import { TranscriptionStreamError as n, TranscriptionStreamEvent as r } from "./transcriptionEvent.js";
|
|
3
|
+
import { experimental_streamTranscribe as i } from "ai";
|
|
4
|
+
import { Effect as a, Schema as o, Stream as s } from "effect";
|
|
5
|
+
//#region src/streamTranscribe.ts
|
|
6
|
+
var c = (c) => s.unwrap(a.gen(function* () {
|
|
7
|
+
let l = yield* a.acquireRelease(a.sync(() => new AbortController()), (e) => a.promise(async () => {
|
|
8
|
+
e.abort(), c.audio.locked || await c.audio.cancel().catch(() => {});
|
|
9
|
+
})), u = c.signal === void 0 ? l.signal : AbortSignal.any([l.signal, c.signal]), d = (e) => {
|
|
10
|
+
let t = new n({
|
|
11
|
+
reason: u.aborted ? "cancelled" : "provider",
|
|
12
|
+
message: u.aborted ? "Transcription cancelled." : "Streaming transcription failed."
|
|
13
|
+
});
|
|
14
|
+
return Object.defineProperty(t, "cause", {
|
|
15
|
+
value: e,
|
|
16
|
+
enumerable: !1
|
|
17
|
+
}), t;
|
|
18
|
+
};
|
|
19
|
+
if (u.aborted) return s.fail(d(u.reason));
|
|
20
|
+
let f = c.inputAudioFormat;
|
|
21
|
+
if (![
|
|
22
|
+
"audio/pcm",
|
|
23
|
+
"audio/pcmu",
|
|
24
|
+
"audio/pcma"
|
|
25
|
+
].includes(f.type) || f.type === "audio/pcm" && f.rate === void 0 || f.rate !== void 0 && (!Number.isSafeInteger(f.rate) || f.rate <= 0)) return s.fail(new n({
|
|
26
|
+
reason: "input",
|
|
27
|
+
message: "streamTranscribe requires raw PCM (with a positive integer rate), PCMU or PCMA audio; decode container files first."
|
|
28
|
+
}));
|
|
29
|
+
let p = yield* a.try({
|
|
30
|
+
try: () => t(c.provider ?? e()),
|
|
31
|
+
catch: d
|
|
32
|
+
});
|
|
33
|
+
if (p.doStream === void 0) return s.fail(new n({
|
|
34
|
+
reason: "unsupported",
|
|
35
|
+
message: "The selected transcription provider/model does not support streaming."
|
|
36
|
+
}));
|
|
37
|
+
let m = yield* a.try({
|
|
38
|
+
try: () => i({
|
|
39
|
+
model: p,
|
|
40
|
+
audio: c.audio,
|
|
41
|
+
inputAudioFormat: f,
|
|
42
|
+
...c.providerOptions === void 0 ? {} : { providerOptions: c.providerOptions },
|
|
43
|
+
abortSignal: u
|
|
44
|
+
}),
|
|
45
|
+
catch: d
|
|
46
|
+
}), h = s.fromReadableStream({
|
|
47
|
+
evaluate: () => m.fullStream,
|
|
48
|
+
onError: d
|
|
49
|
+
}).pipe(s.filter((e) => e.type !== "raw"), s.mapEffect((e) => e.type === "error" ? a.fail(d(e.error)) : o.decodeUnknownEffect(r)(e).pipe(a.mapError(d)))), g = s.fromEffect(a.tryPromise({
|
|
50
|
+
try: async () => {
|
|
51
|
+
let [e, t, n, i] = await Promise.all([
|
|
52
|
+
m.text,
|
|
53
|
+
m.segments,
|
|
54
|
+
m.language,
|
|
55
|
+
m.durationInSeconds
|
|
56
|
+
]);
|
|
57
|
+
return o.decodeUnknownSync(r)({
|
|
58
|
+
type: "finish",
|
|
59
|
+
text: e,
|
|
60
|
+
segments: t.map((e) => ({
|
|
61
|
+
text: e.text,
|
|
62
|
+
start: e.startSecond,
|
|
63
|
+
end: e.endSecond
|
|
64
|
+
})),
|
|
65
|
+
...n === void 0 ? {} : { language: n },
|
|
66
|
+
...i === void 0 ? {} : { durationSec: i }
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
catch: d
|
|
70
|
+
}));
|
|
71
|
+
return s.concat(h, g);
|
|
72
|
+
}));
|
|
73
|
+
//#endregion
|
|
74
|
+
export { n as TranscriptionStreamError, r as TranscriptionStreamEvent, c as streamTranscribe };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Effect as e } from "effect";
|
|
2
|
+
//#region src/streamWakeups.ts
|
|
3
|
+
var t = /* @__PURE__ */ new WeakMap(), n = (e, n) => (t.get(e)?.get(n)?.readers ?? 0) > 0, r = (n, r) => e.acquireRelease(e.sync(() => {
|
|
4
|
+
let e = t.get(n);
|
|
5
|
+
e === void 0 && (e = /* @__PURE__ */ new Map(), t.set(n, e));
|
|
6
|
+
let i = e.get(r);
|
|
7
|
+
return i === void 0 && (i = {
|
|
8
|
+
version: 0,
|
|
9
|
+
readers: 0,
|
|
10
|
+
waiters: /* @__PURE__ */ new Set()
|
|
11
|
+
}, e.set(r, i)), i.readers++, i;
|
|
12
|
+
}), (i) => e.sync(() => {
|
|
13
|
+
if (i.readers--, i.readers === 0) {
|
|
14
|
+
let e = t.get(n);
|
|
15
|
+
e?.delete(r), e?.size === 0 && t.delete(n);
|
|
16
|
+
}
|
|
17
|
+
})), i = (t, n) => e.callback((r) => {
|
|
18
|
+
if (t.version !== n) {
|
|
19
|
+
r(e.void);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
let i = () => {
|
|
23
|
+
t.waiters.delete(i), r(e.void);
|
|
24
|
+
};
|
|
25
|
+
return t.waiters.add(i), e.sync(() => {
|
|
26
|
+
t.waiters.delete(i);
|
|
27
|
+
});
|
|
28
|
+
}), a = (n) => {
|
|
29
|
+
let r = (e) => {
|
|
30
|
+
let n = t.get(i)?.get(e);
|
|
31
|
+
if (n === void 0) return;
|
|
32
|
+
n.version++;
|
|
33
|
+
let r = [...n.waiters];
|
|
34
|
+
for (let e of r) n.waiters.has(e) && e();
|
|
35
|
+
}, i = {
|
|
36
|
+
...n,
|
|
37
|
+
append: (t, i) => n.append(t, i).pipe(e.tap(() => e.sync(() => r(t)))),
|
|
38
|
+
...n.appendMany === void 0 ? {} : { appendMany: (t, i) => n.appendMany(t, i).pipe(e.tap(() => e.sync(() => r(t)))) },
|
|
39
|
+
markDone: (t) => n.markDone(t).pipe(e.tap(() => e.sync(() => r(t))))
|
|
40
|
+
};
|
|
41
|
+
return i;
|
|
42
|
+
};
|
|
43
|
+
//#endregion
|
|
44
|
+
export { i as awaitStreamChange, n as hasStreamReaders, r as watchStream, a as withStreamWakeups };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { normalizeAiCallEvidence as e } from "./callEvidence.js";
|
|
2
|
+
import { wrapLanguageModel as t } from "ai";
|
|
3
|
+
//#region src/structuredEvidence.ts
|
|
4
|
+
var n = (n, r) => {
|
|
5
|
+
let i = [];
|
|
6
|
+
return {
|
|
7
|
+
model: t({
|
|
8
|
+
model: r,
|
|
9
|
+
middleware: {
|
|
10
|
+
specificationVersion: "v4",
|
|
11
|
+
wrapGenerate: async ({ doGenerate: t }) => {
|
|
12
|
+
let a = await t(), o = a.usage.inputTokens.total, s = a.usage.outputTokens.total;
|
|
13
|
+
return i.push(e(n, r.modelId, {
|
|
14
|
+
inputTokens: o,
|
|
15
|
+
outputTokens: s,
|
|
16
|
+
totalTokens: o !== void 0 && s !== void 0 ? o + s : void 0
|
|
17
|
+
}, a.providerMetadata)), a;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}),
|
|
21
|
+
evidence: (t) => {
|
|
22
|
+
if (i.length === 0) return e(n, r.modelId, t);
|
|
23
|
+
let a = (e) => {
|
|
24
|
+
let t = 0;
|
|
25
|
+
for (let n of i) {
|
|
26
|
+
let r = n.usage[e];
|
|
27
|
+
if (r === void 0) return;
|
|
28
|
+
t += r;
|
|
29
|
+
}
|
|
30
|
+
return t;
|
|
31
|
+
}, o = 0;
|
|
32
|
+
for (let e of i) {
|
|
33
|
+
if (e.cost.status !== "actual") {
|
|
34
|
+
o = void 0;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
o += e.cost.usd;
|
|
38
|
+
}
|
|
39
|
+
return e(n, r.modelId, {
|
|
40
|
+
inputTokens: a("inputTokens"),
|
|
41
|
+
outputTokens: a("outputTokens"),
|
|
42
|
+
totalTokens: a("totalTokens")
|
|
43
|
+
}, o === void 0 ? void 0 : { gateway: { cost: o } });
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
//#endregion
|
|
48
|
+
export { n as captureStructuredEvidence };
|
package/dist/test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MockScript as e, setProviderOverride as t } from "./provider.js";
|
|
2
2
|
//#region src/test/index.ts
|
|
3
3
|
var n = (e) => e.turns && e.turns.length > 0 ? e.turns : e.stream && e.stream.length > 0 ? [{ text: e.stream.join("") }] : e.generate ? [{ text: e.generate.text }] : [{ text: "" }], r = (t) => {
|
|
4
4
|
let r = new e(n(t));
|
package/dist/threads.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { AGENT_MESSAGES_TABLE as e, AGENT_THREADS_TABLE as t } from "./agentConstants.js";
|
|
2
|
+
import { AgentThreadAccessDenied as n } from "./agent.js";
|
|
3
|
+
import { Effect as r } from "effect";
|
|
4
|
+
import { boolean as i, id as a, integer as o, json as s, table as c, text as l, timestamp as u } from "@voltro/database";
|
|
5
|
+
//#region src/threads.ts
|
|
6
|
+
var d = c(t, {
|
|
7
|
+
id: a({ prefix: "thread" }),
|
|
8
|
+
tenantId: l().nullable(),
|
|
9
|
+
subjectId: l().nullable(),
|
|
10
|
+
title: l().nullable(),
|
|
11
|
+
createdAt: u(),
|
|
12
|
+
updatedAt: u()
|
|
13
|
+
}).renamedFrom("agent_threads").index(["tenantId"]), f = c(e, {
|
|
14
|
+
id: a({ prefix: "msg" }),
|
|
15
|
+
threadId: l(),
|
|
16
|
+
tenantId: l().nullable(),
|
|
17
|
+
role: l(),
|
|
18
|
+
content: l(),
|
|
19
|
+
streaming: i(),
|
|
20
|
+
order: o(),
|
|
21
|
+
stepOrder: o(),
|
|
22
|
+
parts: s(),
|
|
23
|
+
createdAt: u()
|
|
24
|
+
}).renamedFrom("agent_messages").index(["threadId"]), p = (e, n = {}) => r.promise(async () => {
|
|
25
|
+
let r = /* @__PURE__ */ new Date();
|
|
26
|
+
return await e.insert(t, {
|
|
27
|
+
tenantId: n.tenantId ?? null,
|
|
28
|
+
subjectId: n.subjectId ?? null,
|
|
29
|
+
title: n.title ?? null,
|
|
30
|
+
createdAt: r,
|
|
31
|
+
updatedAt: r
|
|
32
|
+
});
|
|
33
|
+
}), m = (e, i) => r.gen(function* () {
|
|
34
|
+
let a = yield* _(e, i.threadId);
|
|
35
|
+
if (a === null) {
|
|
36
|
+
let n = /* @__PURE__ */ new Date();
|
|
37
|
+
return yield* r.promise(() => e.insert(t, {
|
|
38
|
+
id: i.threadId,
|
|
39
|
+
tenantId: i.tenantId ?? null,
|
|
40
|
+
subjectId: i.subjectId,
|
|
41
|
+
title: null,
|
|
42
|
+
createdAt: n,
|
|
43
|
+
updatedAt: n
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
return a.subjectId !== null && a.subjectId !== i.subjectId ? yield* r.fail(new n({ threadId: i.threadId })) : a;
|
|
47
|
+
}), h = (n, i) => r.promise(async () => {
|
|
48
|
+
let r = i.parts ?? (i.content ? [{
|
|
49
|
+
type: "text",
|
|
50
|
+
text: i.content
|
|
51
|
+
}] : []), a = await n.insert(e, {
|
|
52
|
+
threadId: i.threadId,
|
|
53
|
+
tenantId: i.tenantId ?? null,
|
|
54
|
+
role: i.role,
|
|
55
|
+
content: i.content,
|
|
56
|
+
streaming: i.streaming ?? !1,
|
|
57
|
+
order: i.order ?? 0,
|
|
58
|
+
stepOrder: i.stepOrder ?? 0,
|
|
59
|
+
parts: r,
|
|
60
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
61
|
+
});
|
|
62
|
+
return await n.update(t, i.threadId, { updatedAt: /* @__PURE__ */ new Date() }).catch(() => null), a;
|
|
63
|
+
}), g = (t, n) => r.promise(async () => await t.query({
|
|
64
|
+
table: e,
|
|
65
|
+
predicate: {
|
|
66
|
+
_tag: "leaf",
|
|
67
|
+
column: "threadId",
|
|
68
|
+
op: "eq",
|
|
69
|
+
value: n
|
|
70
|
+
},
|
|
71
|
+
order: [{
|
|
72
|
+
column: "createdAt",
|
|
73
|
+
direction: "asc"
|
|
74
|
+
}],
|
|
75
|
+
take: void 0,
|
|
76
|
+
skip: void 0,
|
|
77
|
+
projection: void 0
|
|
78
|
+
})), _ = (e, t) => r.promise(async () => (await e.query({
|
|
79
|
+
table: "_voltro_agent_threads",
|
|
80
|
+
predicate: {
|
|
81
|
+
_tag: "leaf",
|
|
82
|
+
column: "id",
|
|
83
|
+
op: "eq",
|
|
84
|
+
value: t
|
|
85
|
+
},
|
|
86
|
+
order: [],
|
|
87
|
+
take: 1,
|
|
88
|
+
skip: void 0,
|
|
89
|
+
projection: void 0
|
|
90
|
+
}))[0] ?? null);
|
|
91
|
+
//#endregion
|
|
92
|
+
export { e as AGENT_MESSAGES_TABLE, t as AGENT_THREADS_TABLE, f as agentMessagesTable, d as agentThreadsTable, h as appendMessage, p as createThread, m as ensureThreadOwned, g as getMessages, _ as getThread };
|