theorum 0.1.3 → 0.1.4
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/README.md +30 -9
- package/deno.json +57 -0
- package/deno.lock +469 -0
- package/{esm/mod.d.ts → mod.ts} +57 -15
- package/package.json +35 -44
- package/src/cli/commands/profile.ts +57 -0
- package/src/cli/commands/run.ts +66 -0
- package/src/cli/commands/test.ts +195 -0
- package/src/cli/index.ts +161 -0
- package/src/cli/matrix/fixtures.ts +96 -0
- package/src/cli/matrix/synthesizer.ts +240 -0
- package/src/guardrails/error.ts +142 -0
- package/src/guardrails/injection.ts +254 -0
- package/src/guardrails/mod.ts +40 -0
- package/src/guardrails/quota.ts +87 -0
- package/src/guardrails/sanitize.ts +165 -0
- package/src/guardrails/sensitive.ts +96 -0
- package/src/host/mint-trace.ts +54 -0
- package/{esm/src/host/mod.js → src/host/mod.ts} +11 -3
- package/src/host/reply.ts +32 -0
- package/src/kernel/engine/assert.ts +29 -0
- package/src/kernel/engine/boundary.ts +75 -0
- package/src/kernel/engine/delta.ts +440 -0
- package/src/kernel/engine/hash.ts +11 -0
- package/src/kernel/engine/record.ts +8 -0
- package/src/kernel/engine/repair.ts +56 -0
- package/src/kernel/engine/runner/gates.ts +338 -0
- package/src/kernel/engine/runner/mod.ts +135 -0
- package/src/kernel/engine/runner/state.ts +31 -0
- package/src/kernel/engine/runner/steps.ts +183 -0
- package/src/kernel/engine/runner/stream.ts +83 -0
- package/src/kernel/engine/runner/tokens.ts +47 -0
- package/src/kernel/engine/runner/tools.ts +266 -0
- package/{esm/src/kernel/engine/runner.d.ts → src/kernel/engine/runner.ts} +2 -1
- package/src/kernel/engine/tree.ts +18 -0
- package/src/kernel/mod.ts +39 -0
- package/src/kernel/registry/attachments.ts +195 -0
- package/src/kernel/registry/catalog.ts +181 -0
- package/src/kernel/registry/ingress.ts +223 -0
- package/src/kernel/registry/profiles.ts +165 -0
- package/src/kernel/registry/provider-request.ts +31 -0
- package/src/kernel/registry/resolve.ts +290 -0
- package/src/kernel/registry/schemas.ts +29 -0
- package/src/kernel/registry/tools.ts +45 -0
- package/{esm/src/kernel/registry/vault.d.ts → src/kernel/registry/vault.ts} +17 -2
- package/src/kernel/types.ts +576 -0
- package/{esm/src/observability/mod.js → src/observability/mod.ts} +11 -2
- package/src/observability/spans.ts +70 -0
- package/src/observability/trace-attach.ts +96 -0
- package/src/observability/trace-record.ts +254 -0
- package/src/observability/trace-usage.ts +36 -0
- package/src/observability/trace.ts +143 -0
- package/src/presets/google.ts +147 -0
- package/src/presets/mod.ts +24 -0
- package/src/providers/create-provider.ts +64 -0
- package/src/providers/gemini-tape.ts +59 -0
- package/src/providers/google-tap.ts +57 -0
- package/src/providers/interactions.ts +182 -0
- package/src/providers/keys.ts +182 -0
- package/{esm/src/providers/mod.js → src/providers/mod.ts} +4 -2
- package/{esm/src/providers/openrouter-mod.js → src/providers/openrouter-mod.ts} +7 -3
- package/src/providers/openrouter-payload.ts +232 -0
- package/src/providers/openrouter.ts +758 -0
- package/src/providers/pcm.ts +37 -0
- package/src/providers/provider.ts +206 -0
- package/src/providers/speech.ts +180 -0
- package/src/providers/sse.ts +59 -0
- package/esm/_dnt.polyfills.d.ts +0 -110
- package/esm/_dnt.polyfills.js +0 -144
- package/esm/_dnt.shims.d.ts +0 -5
- package/esm/_dnt.shims.js +0 -61
- package/esm/mod.js +0 -49
- package/esm/package.json +0 -3
- package/esm/src/cli/commands/profile.d.ts +0 -2
- package/esm/src/cli/commands/profile.js +0 -53
- package/esm/src/cli/commands/run.d.ts +0 -10
- package/esm/src/cli/commands/run.js +0 -55
- package/esm/src/cli/commands/test.d.ts +0 -15
- package/esm/src/cli/commands/test.js +0 -140
- package/esm/src/cli/index.d.ts +0 -4
- package/esm/src/cli/index.js +0 -148
- package/esm/src/cli/matrix/fixtures.d.ts +0 -13
- package/esm/src/cli/matrix/fixtures.js +0 -77
- package/esm/src/cli/matrix/synthesizer.d.ts +0 -29
- package/esm/src/cli/matrix/synthesizer.js +0 -187
- package/esm/src/guardrails/error.d.ts +0 -33
- package/esm/src/guardrails/error.js +0 -114
- package/esm/src/guardrails/injection.d.ts +0 -12
- package/esm/src/guardrails/injection.js +0 -220
- package/esm/src/guardrails/mod.d.ts +0 -14
- package/esm/src/guardrails/mod.js +0 -14
- package/esm/src/guardrails/sanitize.d.ts +0 -22
- package/esm/src/guardrails/sanitize.js +0 -133
- package/esm/src/guardrails/sensitive.d.ts +0 -12
- package/esm/src/guardrails/sensitive.js +0 -88
- package/esm/src/host/mint-trace.d.ts +0 -27
- package/esm/src/host/mint-trace.js +0 -33
- package/esm/src/host/mod.d.ts +0 -13
- package/esm/src/host/reply.d.ts +0 -14
- package/esm/src/host/reply.js +0 -27
- package/esm/src/kernel/engine/boundary.d.ts +0 -10
- package/esm/src/kernel/engine/boundary.js +0 -55
- package/esm/src/kernel/engine/delta.d.ts +0 -8
- package/esm/src/kernel/engine/delta.js +0 -389
- package/esm/src/kernel/engine/hash.d.ts +0 -1
- package/esm/src/kernel/engine/hash.js +0 -9
- package/esm/src/kernel/engine/record.d.ts +0 -2
- package/esm/src/kernel/engine/record.js +0 -7
- package/esm/src/kernel/engine/repair.d.ts +0 -7
- package/esm/src/kernel/engine/repair.js +0 -38
- package/esm/src/kernel/engine/runner/gates.d.ts +0 -4
- package/esm/src/kernel/engine/runner/gates.js +0 -206
- package/esm/src/kernel/engine/runner/mod.d.ts +0 -14
- package/esm/src/kernel/engine/runner/mod.js +0 -103
- package/esm/src/kernel/engine/runner/state.d.ts +0 -16
- package/esm/src/kernel/engine/runner/state.js +0 -8
- package/esm/src/kernel/engine/runner/steps.d.ts +0 -15
- package/esm/src/kernel/engine/runner/steps.js +0 -119
- package/esm/src/kernel/engine/runner/stream.d.ts +0 -11
- package/esm/src/kernel/engine/runner/stream.js +0 -65
- package/esm/src/kernel/engine/runner/tokens.d.ts +0 -3
- package/esm/src/kernel/engine/runner/tokens.js +0 -38
- package/esm/src/kernel/engine/runner/tools.d.ts +0 -13
- package/esm/src/kernel/engine/runner/tools.js +0 -197
- package/esm/src/kernel/engine/runner.js +0 -6
- package/esm/src/kernel/engine/tree.d.ts +0 -2
- package/esm/src/kernel/engine/tree.js +0 -17
- package/esm/src/kernel/mod.d.ts +0 -18
- package/esm/src/kernel/mod.js +0 -16
- package/esm/src/kernel/registry/attachments.d.ts +0 -16
- package/esm/src/kernel/registry/attachments.js +0 -156
- package/esm/src/kernel/registry/catalog.d.ts +0 -31
- package/esm/src/kernel/registry/catalog.js +0 -135
- package/esm/src/kernel/registry/ingress.d.ts +0 -13
- package/esm/src/kernel/registry/ingress.js +0 -163
- package/esm/src/kernel/registry/profiles.d.ts +0 -34
- package/esm/src/kernel/registry/profiles.js +0 -120
- package/esm/src/kernel/registry/provider-request.d.ts +0 -4
- package/esm/src/kernel/registry/provider-request.js +0 -25
- package/esm/src/kernel/registry/resolve.d.ts +0 -19
- package/esm/src/kernel/registry/resolve.js +0 -217
- package/esm/src/kernel/registry/schemas.d.ts +0 -14
- package/esm/src/kernel/registry/schemas.js +0 -23
- package/esm/src/kernel/registry/tools.d.ts +0 -12
- package/esm/src/kernel/registry/tools.js +0 -36
- package/esm/src/kernel/registry/vault.js +0 -18
- package/esm/src/kernel/types.d.ts +0 -521
- package/esm/src/kernel/types.js +0 -10
- package/esm/src/observability/mod.d.ts +0 -12
- package/esm/src/observability/spans.d.ts +0 -16
- package/esm/src/observability/spans.js +0 -56
- package/esm/src/observability/trace-attach.d.ts +0 -16
- package/esm/src/observability/trace-attach.js +0 -67
- package/esm/src/observability/trace-record.d.ts +0 -112
- package/esm/src/observability/trace-record.js +0 -140
- package/esm/src/observability/trace-usage.d.ts +0 -3
- package/esm/src/observability/trace-usage.js +0 -32
- package/esm/src/observability/trace.d.ts +0 -23
- package/esm/src/observability/trace.js +0 -121
- package/esm/src/presets/google.d.ts +0 -50
- package/esm/src/presets/google.js +0 -96
- package/esm/src/presets/mod.d.ts +0 -11
- package/esm/src/presets/mod.js +0 -10
- package/esm/src/providers/create-provider.d.ts +0 -29
- package/esm/src/providers/create-provider.js +0 -38
- package/esm/src/providers/gemini-tape.d.ts +0 -2
- package/esm/src/providers/gemini-tape.js +0 -46
- package/esm/src/providers/google-tap.d.ts +0 -3
- package/esm/src/providers/google-tap.js +0 -48
- package/esm/src/providers/interactions.d.ts +0 -5
- package/esm/src/providers/interactions.js +0 -152
- package/esm/src/providers/keys.d.ts +0 -19
- package/esm/src/providers/keys.js +0 -129
- package/esm/src/providers/mod.d.ts +0 -12
- package/esm/src/providers/openrouter-mod.d.ts +0 -13
- package/esm/src/providers/openrouter-payload.d.ts +0 -32
- package/esm/src/providers/openrouter-payload.js +0 -179
- package/esm/src/providers/openrouter.d.ts +0 -15
- package/esm/src/providers/openrouter.js +0 -589
- package/esm/src/providers/pcm.d.ts +0 -7
- package/esm/src/providers/pcm.js +0 -35
- package/esm/src/providers/provider.d.ts +0 -15
- package/esm/src/providers/provider.js +0 -166
- package/esm/src/providers/speech.d.ts +0 -23
- package/esm/src/providers/speech.js +0 -125
- package/esm/src/providers/sse.d.ts +0 -7
- package/esm/src/providers/sse.js +0 -53
|
@@ -1,589 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenRouter provider adapter powered by Vercel AI SDK Core.
|
|
3
|
-
*
|
|
4
|
-
* THEORUM keeps the public `ModelProvider` and `TurnEvent` contract; AI SDK
|
|
5
|
-
* owns the OpenRouter call, stream parsing, provider compatibility, and tool
|
|
6
|
-
* call normalization.
|
|
7
|
-
*
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
|
-
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
|
11
|
-
import { jsonSchema, streamText, tool, } from 'ai';
|
|
12
|
-
import { publicError } from '../guardrails/error.js';
|
|
13
|
-
import { tryStructured } from '../kernel/engine/delta.js';
|
|
14
|
-
import { getTool } from '../kernel/registry/catalog.js';
|
|
15
|
-
import { resolveOpenRouterModel, toOpenRouterPayload, } from './openrouter-payload.js';
|
|
16
|
-
import { takeSsePayloads } from './sse.js';
|
|
17
|
-
function trimApiKey(explicitKey) {
|
|
18
|
-
if (explicitKey?.trim()) {
|
|
19
|
-
return explicitKey.trim();
|
|
20
|
-
}
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
function createAccumulator() {
|
|
24
|
-
return {
|
|
25
|
-
text: '',
|
|
26
|
-
evidenceSeen: false,
|
|
27
|
-
emittedTokens: false,
|
|
28
|
-
errored: false,
|
|
29
|
-
toolInputs: new Map(),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
function mediaPart(part) {
|
|
33
|
-
if (part.type === 'text') {
|
|
34
|
-
return { type: 'text', text: part.text };
|
|
35
|
-
}
|
|
36
|
-
if (part.type === 'image') {
|
|
37
|
-
return {
|
|
38
|
-
type: 'image',
|
|
39
|
-
image: `data:${part.mimeType};base64,${part.data}`,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
return { type: 'file', mediaType: part.mimeType, data: part.data };
|
|
43
|
-
}
|
|
44
|
-
function contentFromParts(parts) {
|
|
45
|
-
if (parts.every((part) => part.type === 'text')) {
|
|
46
|
-
return parts
|
|
47
|
-
.map((part) => (part.type === 'text' ? part.text : ''))
|
|
48
|
-
.filter(Boolean)
|
|
49
|
-
.join('\n');
|
|
50
|
-
}
|
|
51
|
-
return parts.map(mediaPart);
|
|
52
|
-
}
|
|
53
|
-
function parseToolInput(raw) {
|
|
54
|
-
try {
|
|
55
|
-
return JSON.parse(raw);
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
return { _raw: raw };
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function stringDefault(value, fallback) {
|
|
62
|
-
return value === undefined ? fallback : value;
|
|
63
|
-
}
|
|
64
|
-
function optionalSingle(value) {
|
|
65
|
-
return value === undefined ? undefined : [value];
|
|
66
|
-
}
|
|
67
|
-
function fallbackToolCallId(name) {
|
|
68
|
-
return `call_${stringDefault(name, 'tool')}`;
|
|
69
|
-
}
|
|
70
|
-
function toolResultContent(msg) {
|
|
71
|
-
const toolName = stringDefault(msg.name, 'tool');
|
|
72
|
-
return {
|
|
73
|
-
role: 'tool',
|
|
74
|
-
content: [
|
|
75
|
-
{
|
|
76
|
-
type: 'tool-result',
|
|
77
|
-
toolCallId: stringDefault(msg.tool_call_id, fallbackToolCallId(msg.name)),
|
|
78
|
-
toolName,
|
|
79
|
-
output: { type: 'text', value: stringDefault(msg.content, '') },
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function assistantToolCallContent(msg) {
|
|
85
|
-
if (!msg.tool_calls || msg.tool_calls.length === 0) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
role: 'assistant',
|
|
90
|
-
content: msg.tool_calls.map((call) => ({
|
|
91
|
-
type: 'tool-call',
|
|
92
|
-
toolCallId: call.id,
|
|
93
|
-
toolName: call.function.name,
|
|
94
|
-
input: parseToolInput(call.function.arguments),
|
|
95
|
-
})),
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
function historyMessage(msg) {
|
|
99
|
-
if (msg.role === 'tool') {
|
|
100
|
-
return toolResultContent(msg);
|
|
101
|
-
}
|
|
102
|
-
return assistantToolCallContent(msg) || contentHistoryMessage(msg);
|
|
103
|
-
}
|
|
104
|
-
function contentFromOptionalParts(parts, text) {
|
|
105
|
-
if (!parts || parts.length === 0) {
|
|
106
|
-
return stringDefault(text, '');
|
|
107
|
-
}
|
|
108
|
-
return contentFromParts(parts);
|
|
109
|
-
}
|
|
110
|
-
function contentHistoryMessage(msg) {
|
|
111
|
-
const content = contentFromOptionalParts(msg.parts, msg.content);
|
|
112
|
-
return { role: msg.role, content };
|
|
113
|
-
}
|
|
114
|
-
function sourceValue(part, key) {
|
|
115
|
-
const source = part;
|
|
116
|
-
const value = source[key];
|
|
117
|
-
return typeof value === 'string' ? value : undefined;
|
|
118
|
-
}
|
|
119
|
-
function sourceUrl(part) {
|
|
120
|
-
return sourceValue(part, 'url');
|
|
121
|
-
}
|
|
122
|
-
function sourceTitle(part) {
|
|
123
|
-
return sourceValue(part, 'title') ?? sourceUrl(part);
|
|
124
|
-
}
|
|
125
|
-
function sourceList(title, url) {
|
|
126
|
-
if (title === undefined || url === undefined) {
|
|
127
|
-
return undefined;
|
|
128
|
-
}
|
|
129
|
-
return [{ title, uri: url, type: 'web' }];
|
|
130
|
-
}
|
|
131
|
-
function sourceEvent(part) {
|
|
132
|
-
const raw = part;
|
|
133
|
-
const url = sourceUrl(part);
|
|
134
|
-
const title = sourceTitle(part);
|
|
135
|
-
return {
|
|
136
|
-
type: 'evidence',
|
|
137
|
-
evidence: {
|
|
138
|
-
provider: 'openrouter',
|
|
139
|
-
raw,
|
|
140
|
-
citations: optionalSingle(url),
|
|
141
|
-
sources: sourceList(title, url),
|
|
142
|
-
},
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
function buildMessages(req) {
|
|
146
|
-
const messages = [];
|
|
147
|
-
for (const msg of req.history ?? []) {
|
|
148
|
-
const wired = historyMessage(msg);
|
|
149
|
-
if (wired) {
|
|
150
|
-
messages.push(wired);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if (req.input.length > 0) {
|
|
154
|
-
messages.push({ role: 'user', content: contentFromParts(req.input) });
|
|
155
|
-
}
|
|
156
|
-
return messages;
|
|
157
|
-
}
|
|
158
|
-
function schemaForTool(decl) {
|
|
159
|
-
return decl.parameters ?? { type: 'object', properties: {}, additionalProperties: true };
|
|
160
|
-
}
|
|
161
|
-
function buildTools(dynamicTools) {
|
|
162
|
-
if (!dynamicTools || dynamicTools.length === 0) {
|
|
163
|
-
return undefined;
|
|
164
|
-
}
|
|
165
|
-
const tools = {};
|
|
166
|
-
for (const decl of dynamicTools) {
|
|
167
|
-
tools[decl.name] = tool({
|
|
168
|
-
description: decl.description ?? '',
|
|
169
|
-
inputSchema: jsonSchema(schemaForTool(decl)),
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
return tools;
|
|
173
|
-
}
|
|
174
|
-
function openRouterPlugins(req) {
|
|
175
|
-
const plugins = req.builtins
|
|
176
|
-
.map((id) => getTool(id)?.openRouterPlugin)
|
|
177
|
-
.filter((id) => Boolean(id))
|
|
178
|
-
.map((id) => ({ id }));
|
|
179
|
-
return plugins.length > 0 ? plugins : undefined;
|
|
180
|
-
}
|
|
181
|
-
function openRouterSettings(req) {
|
|
182
|
-
const plugins = openRouterPlugins(req);
|
|
183
|
-
if (!plugins) {
|
|
184
|
-
return undefined;
|
|
185
|
-
}
|
|
186
|
-
return { plugins };
|
|
187
|
-
}
|
|
188
|
-
function tokensFromUsage(usage) {
|
|
189
|
-
const input = usage.inputTokens ?? 0;
|
|
190
|
-
const output = usage.outputTokens ?? 0;
|
|
191
|
-
const total = usage.totalTokens ?? input + output;
|
|
192
|
-
if (input === 0 && output === 0 && total === 0) {
|
|
193
|
-
return undefined;
|
|
194
|
-
}
|
|
195
|
-
return {
|
|
196
|
-
input,
|
|
197
|
-
output,
|
|
198
|
-
total,
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
function rawRecord(value) {
|
|
202
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
203
|
-
return value;
|
|
204
|
-
}
|
|
205
|
-
return undefined;
|
|
206
|
-
}
|
|
207
|
-
function stringArray(value) {
|
|
208
|
-
if (!Array.isArray(value)) {
|
|
209
|
-
return undefined;
|
|
210
|
-
}
|
|
211
|
-
const out = value.filter((item) => typeof item === 'string');
|
|
212
|
-
return out.length > 0 ? out : undefined;
|
|
213
|
-
}
|
|
214
|
-
function metadataRecord(raw, key) {
|
|
215
|
-
return rawRecord(raw[key]);
|
|
216
|
-
}
|
|
217
|
-
function citationCandidates(raw) {
|
|
218
|
-
const openrouter = metadataRecord(raw, 'openrouter') ?? {};
|
|
219
|
-
return [
|
|
220
|
-
raw.citations,
|
|
221
|
-
metadataRecord(raw, 'providerMetadata')?.citations,
|
|
222
|
-
metadataRecord(raw, 'provider_metadata')?.citations,
|
|
223
|
-
openrouter.citations,
|
|
224
|
-
metadataRecord(openrouter, 'providerMetadata')?.citations,
|
|
225
|
-
metadataRecord(openrouter, 'provider_metadata')?.citations,
|
|
226
|
-
];
|
|
227
|
-
}
|
|
228
|
-
function nestedCitations(raw) {
|
|
229
|
-
for (const candidate of citationCandidates(raw)) {
|
|
230
|
-
const citations = stringArray(candidate);
|
|
231
|
-
if (citations) {
|
|
232
|
-
return citations;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return undefined;
|
|
236
|
-
}
|
|
237
|
-
function metadataAnnotations(raw) {
|
|
238
|
-
const openrouter = metadataRecord(raw, 'openrouter');
|
|
239
|
-
if (Array.isArray(raw.annotations)) {
|
|
240
|
-
return raw.annotations;
|
|
241
|
-
}
|
|
242
|
-
if (Array.isArray(openrouter?.annotations)) {
|
|
243
|
-
return openrouter.annotations;
|
|
244
|
-
}
|
|
245
|
-
return undefined;
|
|
246
|
-
}
|
|
247
|
-
function evidenceFromMetadata(metadata, acc) {
|
|
248
|
-
const raw = rawRecord(metadata);
|
|
249
|
-
if (!raw || acc.evidenceSeen) {
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
|
-
const citations = nestedCitations(raw);
|
|
253
|
-
const annotations = metadataAnnotations(raw);
|
|
254
|
-
if (!citations && !annotations) {
|
|
255
|
-
return undefined;
|
|
256
|
-
}
|
|
257
|
-
acc.evidenceSeen = true;
|
|
258
|
-
return {
|
|
259
|
-
type: 'evidence',
|
|
260
|
-
evidence: { provider: 'openrouter', raw, citations, annotations },
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
function toolArguments(input) {
|
|
264
|
-
if (input && typeof input === 'object' && !Array.isArray(input)) {
|
|
265
|
-
return input;
|
|
266
|
-
}
|
|
267
|
-
if (input === undefined) {
|
|
268
|
-
return undefined;
|
|
269
|
-
}
|
|
270
|
-
return { value: input };
|
|
271
|
-
}
|
|
272
|
-
function isEmptyRecord(input) {
|
|
273
|
-
return Boolean(input) && Object.keys(input ?? {}).length === 0;
|
|
274
|
-
}
|
|
275
|
-
function toolCallArguments(part, acc) {
|
|
276
|
-
const fromInput = toolArguments(part.input);
|
|
277
|
-
const rawInput = acc.toolInputs.get(part.toolCallId);
|
|
278
|
-
if ((!fromInput || isEmptyRecord(fromInput)) && rawInput) {
|
|
279
|
-
return toolArguments(parseToolInput(rawInput));
|
|
280
|
-
}
|
|
281
|
-
return fromInput;
|
|
282
|
-
}
|
|
283
|
-
function toolResultData(output) {
|
|
284
|
-
return rawRecord(output);
|
|
285
|
-
}
|
|
286
|
-
function rawThoughtEvent(raw) {
|
|
287
|
-
const choices = raw.choices;
|
|
288
|
-
if (!Array.isArray(choices)) {
|
|
289
|
-
return undefined;
|
|
290
|
-
}
|
|
291
|
-
for (const choice of choices) {
|
|
292
|
-
const delta = rawRecord(rawRecord(choice)?.delta);
|
|
293
|
-
if (typeof delta?.thinking === 'string') {
|
|
294
|
-
return { type: 'thought', text: delta.thinking };
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return undefined;
|
|
298
|
-
}
|
|
299
|
-
function rawChoiceMessageEvidence(raw, acc) {
|
|
300
|
-
const choices = raw.choices;
|
|
301
|
-
if (!Array.isArray(choices)) {
|
|
302
|
-
return undefined;
|
|
303
|
-
}
|
|
304
|
-
for (const choice of choices) {
|
|
305
|
-
const message = rawRecord(rawRecord(choice)?.message);
|
|
306
|
-
if (!message) {
|
|
307
|
-
continue;
|
|
308
|
-
}
|
|
309
|
-
const evidence = evidenceFromMetadata(message, acc);
|
|
310
|
-
if (evidence) {
|
|
311
|
-
return evidence;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
return undefined;
|
|
315
|
-
}
|
|
316
|
-
function rawEvents(raw, acc) {
|
|
317
|
-
const record = rawRecord(raw);
|
|
318
|
-
if (!record) {
|
|
319
|
-
return [];
|
|
320
|
-
}
|
|
321
|
-
const events = [];
|
|
322
|
-
const thought = rawThoughtEvent(record);
|
|
323
|
-
if (thought) {
|
|
324
|
-
events.push(thought);
|
|
325
|
-
}
|
|
326
|
-
const evidence = evidenceFromMetadata(record, acc);
|
|
327
|
-
if (evidence) {
|
|
328
|
-
events.push(evidence);
|
|
329
|
-
}
|
|
330
|
-
const messageEvidence = rawChoiceMessageEvidence(record, acc);
|
|
331
|
-
if (messageEvidence) {
|
|
332
|
-
events.push(messageEvidence);
|
|
333
|
-
}
|
|
334
|
-
return events;
|
|
335
|
-
}
|
|
336
|
-
async function collectRawEvents(res) {
|
|
337
|
-
if (!res.body) {
|
|
338
|
-
return [];
|
|
339
|
-
}
|
|
340
|
-
const reader = res.body.getReader();
|
|
341
|
-
const decoder = new TextDecoder();
|
|
342
|
-
const events = [];
|
|
343
|
-
const acc = createAccumulator();
|
|
344
|
-
let buffer = '';
|
|
345
|
-
let pendingEvent = '';
|
|
346
|
-
while (true) {
|
|
347
|
-
const { done, value } = await reader.read();
|
|
348
|
-
if (done) {
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
buffer += decoder.decode(value, { stream: true });
|
|
352
|
-
const taken = takeSsePayloads(buffer, pendingEvent);
|
|
353
|
-
buffer = taken.rest;
|
|
354
|
-
pendingEvent = taken.pendingEvent;
|
|
355
|
-
for (const payload of taken.payloads) {
|
|
356
|
-
events.push(...rawEvents(payload, acc));
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
return events;
|
|
360
|
-
}
|
|
361
|
-
function captureFetch(config, setCapture) {
|
|
362
|
-
const fetchFn = config.fetch ?? fetch;
|
|
363
|
-
return async (input, init) => {
|
|
364
|
-
const res = await fetchFn(input, init);
|
|
365
|
-
setCapture(collectRawEvents(res.clone()).catch(() => []));
|
|
366
|
-
return res;
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
function toolCallEvent(part, acc) {
|
|
370
|
-
return {
|
|
371
|
-
type: 'tool',
|
|
372
|
-
tool: {
|
|
373
|
-
name: part.toolName,
|
|
374
|
-
arguments: toolCallArguments(part, acc),
|
|
375
|
-
id: part.toolCallId,
|
|
376
|
-
},
|
|
377
|
-
};
|
|
378
|
-
}
|
|
379
|
-
function toolResultEvent(part) {
|
|
380
|
-
return {
|
|
381
|
-
type: 'tool',
|
|
382
|
-
tool: {
|
|
383
|
-
name: part.toolName,
|
|
384
|
-
arguments: toolArguments(part.input),
|
|
385
|
-
result: {
|
|
386
|
-
status: 'ok',
|
|
387
|
-
data: toolResultData(part.output),
|
|
388
|
-
finding: typeof part.output === 'string' ? part.output : undefined,
|
|
389
|
-
},
|
|
390
|
-
id: part.toolCallId,
|
|
391
|
-
},
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
function tokenEvent(part) {
|
|
395
|
-
const tokens = tokensFromUsage(part.totalUsage);
|
|
396
|
-
return tokens ? { type: 'tokens', tokens } : undefined;
|
|
397
|
-
}
|
|
398
|
-
function providerMetadataEvent(part, acc) {
|
|
399
|
-
if (!('providerMetadata' in part)) {
|
|
400
|
-
return undefined;
|
|
401
|
-
}
|
|
402
|
-
return evidenceFromMetadata(part.providerMetadata, acc);
|
|
403
|
-
}
|
|
404
|
-
function appendToolInput(part, acc) {
|
|
405
|
-
if (part.type === 'tool-input-start') {
|
|
406
|
-
acc.toolInputs.set(part.id, '');
|
|
407
|
-
return true;
|
|
408
|
-
}
|
|
409
|
-
if (part.type === 'tool-input-delta') {
|
|
410
|
-
const current = acc.toolInputs.get(part.id) ?? '';
|
|
411
|
-
acc.toolInputs.set(part.id, current + part.delta);
|
|
412
|
-
return true;
|
|
413
|
-
}
|
|
414
|
-
return false;
|
|
415
|
-
}
|
|
416
|
-
function eventFromPart(part, acc) {
|
|
417
|
-
if (appendToolInput(part, acc)) {
|
|
418
|
-
return [];
|
|
419
|
-
}
|
|
420
|
-
const mapped = primaryEventFromPart(part, acc);
|
|
421
|
-
if (mapped) {
|
|
422
|
-
return [mapped];
|
|
423
|
-
}
|
|
424
|
-
const evidence = providerMetadataEvent(part, acc);
|
|
425
|
-
return evidence ? [evidence] : [];
|
|
426
|
-
}
|
|
427
|
-
function primaryEventFromPart(part, acc) {
|
|
428
|
-
switch (part.type) {
|
|
429
|
-
case 'text-delta':
|
|
430
|
-
acc.text += part.text;
|
|
431
|
-
return { type: 'text', text: part.text };
|
|
432
|
-
case 'reasoning-delta':
|
|
433
|
-
return { type: 'thought', text: part.text };
|
|
434
|
-
case 'tool-call':
|
|
435
|
-
return toolCallEvent(part, acc);
|
|
436
|
-
case 'tool-result':
|
|
437
|
-
return toolResultEvent(part);
|
|
438
|
-
case 'source':
|
|
439
|
-
return sourceEvent(part);
|
|
440
|
-
case 'finish':
|
|
441
|
-
return finishEvent(part, acc);
|
|
442
|
-
case 'error':
|
|
443
|
-
acc.errored = true;
|
|
444
|
-
return { type: 'error', error: publicError(part.error) };
|
|
445
|
-
default:
|
|
446
|
-
return undefined;
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
function finishEvent(part, acc) {
|
|
450
|
-
if (acc.emittedTokens) {
|
|
451
|
-
return undefined;
|
|
452
|
-
}
|
|
453
|
-
const event = tokenEvent(part);
|
|
454
|
-
if (event) {
|
|
455
|
-
acc.emittedTokens = true;
|
|
456
|
-
}
|
|
457
|
-
return event;
|
|
458
|
-
}
|
|
459
|
-
function emitRawEvents(rawCapture, acc) {
|
|
460
|
-
return (rawCapture ?? Promise.resolve([])).then((events) => events.filter((event) => {
|
|
461
|
-
if (event.type !== 'evidence') {
|
|
462
|
-
return true;
|
|
463
|
-
}
|
|
464
|
-
if (acc.evidenceSeen) {
|
|
465
|
-
return false;
|
|
466
|
-
}
|
|
467
|
-
acc.evidenceSeen = true;
|
|
468
|
-
return true;
|
|
469
|
-
}));
|
|
470
|
-
}
|
|
471
|
-
function createStreamContext(req, config, apiKey) {
|
|
472
|
-
let rawCapture;
|
|
473
|
-
const openrouter = createOpenRouter({
|
|
474
|
-
apiKey,
|
|
475
|
-
baseURL: config.baseUrl,
|
|
476
|
-
headers: openRouterHeaders(config),
|
|
477
|
-
fetch: captureFetch(config, (capture) => {
|
|
478
|
-
rawCapture = capture;
|
|
479
|
-
}),
|
|
480
|
-
compatibility: 'strict',
|
|
481
|
-
});
|
|
482
|
-
return {
|
|
483
|
-
openrouter,
|
|
484
|
-
modelName: resolveOpenRouterModel(req.model, config.modelMap, {
|
|
485
|
-
apiId: req.apiId,
|
|
486
|
-
openRouterId: req.openRouterId,
|
|
487
|
-
}),
|
|
488
|
-
rawCapture: () => rawCapture,
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
function streamTextOptions(req, context) {
|
|
492
|
-
return {
|
|
493
|
-
model: context.openrouter.chat(context.modelName, openRouterSettings(req)),
|
|
494
|
-
system: req.system,
|
|
495
|
-
messages: buildMessages(req),
|
|
496
|
-
allowSystemInMessages: true,
|
|
497
|
-
temperature: req.temperature,
|
|
498
|
-
maxOutputTokens: req.maxOutputTokens,
|
|
499
|
-
tools: buildTools(req.dynamicTools),
|
|
500
|
-
providerOptions: providerOptionsFor(req),
|
|
501
|
-
includeRawChunks: true,
|
|
502
|
-
onError: () => undefined,
|
|
503
|
-
};
|
|
504
|
-
}
|
|
505
|
-
async function* yieldAiSdkStream(req, acc, context) {
|
|
506
|
-
const result = streamText(streamTextOptions(req, context));
|
|
507
|
-
for await (const part of result.fullStream) {
|
|
508
|
-
if (part.type === 'raw') {
|
|
509
|
-
req.tapGemini?.(rawRecord(part.rawValue) ?? { rawValue: part.rawValue });
|
|
510
|
-
for (const event of rawEvents(part.rawValue, acc)) {
|
|
511
|
-
yield event;
|
|
512
|
-
}
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
for (const event of eventFromPart(part, acc)) {
|
|
516
|
-
yield event;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
async function* yieldCapturedRawEvents(context, acc) {
|
|
521
|
-
for (const event of await emitRawEvents(context.rawCapture(), acc)) {
|
|
522
|
-
yield event;
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
async function* yieldCapturedRawEventsUnchecked(context) {
|
|
526
|
-
for (const event of await (context.rawCapture() ?? Promise.resolve([]))) {
|
|
527
|
-
yield event;
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
function missingOpenRouterKey() {
|
|
531
|
-
return { type: 'error', error: publicError('missing OpenRouter API key') };
|
|
532
|
-
}
|
|
533
|
-
async function* streamOpenRouter(req, config) {
|
|
534
|
-
const apiKey = trimApiKey(config.apiKey);
|
|
535
|
-
if (!apiKey) {
|
|
536
|
-
yield missingOpenRouterKey();
|
|
537
|
-
return;
|
|
538
|
-
}
|
|
539
|
-
const acc = createAccumulator();
|
|
540
|
-
const context = createStreamContext(req, config, apiKey);
|
|
541
|
-
try {
|
|
542
|
-
yield* yieldAiSdkStream(req, acc, context);
|
|
543
|
-
yield* yieldCapturedRawEvents(context, acc);
|
|
544
|
-
yield* finalEvents(req, acc);
|
|
545
|
-
}
|
|
546
|
-
catch (err) {
|
|
547
|
-
yield* yieldCapturedRawEventsUnchecked(context);
|
|
548
|
-
yield { type: 'error', error: publicError(err) };
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
function* finalEvents(req, acc) {
|
|
552
|
-
if (acc.errored) {
|
|
553
|
-
return;
|
|
554
|
-
}
|
|
555
|
-
if (req.structured && acc.text) {
|
|
556
|
-
const structured = tryStructured(acc.text);
|
|
557
|
-
if (structured) {
|
|
558
|
-
yield structured;
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
yield { type: 'done' };
|
|
562
|
-
}
|
|
563
|
-
function providerOptionsFor(req) {
|
|
564
|
-
if (req.thinking === 'none') {
|
|
565
|
-
return undefined;
|
|
566
|
-
}
|
|
567
|
-
return {
|
|
568
|
-
openrouter: {
|
|
569
|
-
reasoning: { effort: req.thinking },
|
|
570
|
-
},
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
function openRouterHeaders(config) {
|
|
574
|
-
const headers = {};
|
|
575
|
-
if (config.siteUrl) {
|
|
576
|
-
headers['HTTP-Referer'] = config.siteUrl;
|
|
577
|
-
}
|
|
578
|
-
if (config.siteName) {
|
|
579
|
-
headers['X-Title'] = config.siteName;
|
|
580
|
-
}
|
|
581
|
-
return Object.keys(headers).length > 0 ? headers : undefined;
|
|
582
|
-
}
|
|
583
|
-
/** Create a `ModelProvider` backed by OpenRouter through AI SDK Core. */
|
|
584
|
-
function createOpenRouterProvider(config = {}) {
|
|
585
|
-
return {
|
|
586
|
-
complete: (req) => streamOpenRouter(req, config),
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
export { createOpenRouterProvider, resolveOpenRouterModel, toOpenRouterPayload };
|
package/esm/src/providers/pcm.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PCM → WAV helpers shared by speech transports.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
const SAMPLE_RATE = 24000;
|
|
7
|
-
function writeAscii(view, offset, str) {
|
|
8
|
-
for (let i = 0; i < str.length; i++)
|
|
9
|
-
view.setUint8(offset + i, str.charCodeAt(i));
|
|
10
|
-
}
|
|
11
|
-
/** Wrap raw PCM bytes in a RIFF/WAVE container. */
|
|
12
|
-
export function wrapPcmAsWav(pcm, sampleRate = SAMPLE_RATE) {
|
|
13
|
-
const numChannels = 1;
|
|
14
|
-
const bitsPerSample = 16;
|
|
15
|
-
const byteRate = (sampleRate * numChannels * bitsPerSample) / 8;
|
|
16
|
-
const blockAlign = (numChannels * bitsPerSample) / 8;
|
|
17
|
-
const dataSize = pcm.length;
|
|
18
|
-
const buf = new ArrayBuffer(44 + dataSize);
|
|
19
|
-
const view = new DataView(buf);
|
|
20
|
-
writeAscii(view, 0, 'RIFF');
|
|
21
|
-
view.setUint32(4, 36 + dataSize, true);
|
|
22
|
-
writeAscii(view, 8, 'WAVE');
|
|
23
|
-
writeAscii(view, 12, 'fmt ');
|
|
24
|
-
view.setUint32(16, 16, true);
|
|
25
|
-
view.setUint16(20, 1, true); // PCM
|
|
26
|
-
view.setUint16(22, numChannels, true);
|
|
27
|
-
view.setUint32(24, sampleRate, true);
|
|
28
|
-
view.setUint32(28, byteRate, true);
|
|
29
|
-
view.setUint16(32, blockAlign, true);
|
|
30
|
-
view.setUint16(34, bitsPerSample, true);
|
|
31
|
-
writeAscii(view, 36, 'data');
|
|
32
|
-
view.setUint32(40, dataSize, true);
|
|
33
|
-
new Uint8Array(buf, 44).set(pcm);
|
|
34
|
-
return new Uint8Array(buf);
|
|
35
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Google Interactions provider adapter.
|
|
3
|
-
*
|
|
4
|
-
* This adapter converts THEORUM's provider-neutral request into the Google
|
|
5
|
-
* Interactions wire format and streams normalized `TurnEvent` objects.
|
|
6
|
-
* Speech-role turns use `response_format: audio` + `speech_config` (same
|
|
7
|
-
* transport as chat/image).
|
|
8
|
-
*
|
|
9
|
-
* @module
|
|
10
|
-
*/
|
|
11
|
-
import type { ModelProvider } from '../kernel/types.js';
|
|
12
|
-
import { type GeminiTransport } from './keys.js';
|
|
13
|
-
/** Create a `ModelProvider` backed by Google Interactions streaming. */
|
|
14
|
-
declare function createInteractionsProvider(transport: GeminiTransport): ModelProvider;
|
|
15
|
-
export { createInteractionsProvider };
|