noumen 0.6.0 → 0.8.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/README.md +237 -93
- package/dist/a2a/index.d.ts +5 -7
- package/dist/a2a/index.js +3 -4
- package/dist/a2a/index.js.map +1 -1
- package/dist/acp/index.d.ts +5 -7
- package/dist/acp/index.js +0 -1
- package/dist/acp/index.js.map +1 -1
- package/dist/{agent-DWE4_P5X.d.ts → agent-D0gl-qYi.d.ts} +89 -34
- package/dist/{chunk-6MMYCGJQ.js → chunk-5HY4IYNT.js} +1529 -2321
- package/dist/chunk-5HY4IYNT.js.map +1 -0
- package/dist/chunk-BC5BLWBC.js +21 -0
- package/dist/chunk-BC5BLWBC.js.map +1 -0
- package/dist/{chunk-XZN4QZLK.js → chunk-CX4BL6PC.js} +25 -15
- package/dist/chunk-CX4BL6PC.js.map +1 -0
- package/dist/{chunk-5GEX6ZSB.js → chunk-HQISH4D7.js} +60 -1
- package/dist/chunk-HQISH4D7.js.map +1 -0
- package/dist/{chunk-Y45R3PQL.js → chunk-NUCJXOUV.js} +32 -18
- package/dist/{chunk-Y45R3PQL.js.map → chunk-NUCJXOUV.js.map} +1 -1
- package/dist/chunk-OPFFLQZL.js +40 -0
- package/dist/chunk-OPFFLQZL.js.map +1 -0
- package/dist/chunk-PDEAJ272.js +660 -0
- package/dist/chunk-PDEAJ272.js.map +1 -0
- package/dist/chunk-PKHLGGEC.js +115 -0
- package/dist/chunk-PKHLGGEC.js.map +1 -0
- package/dist/chunk-XQTNXRE7.js +176 -0
- package/dist/chunk-XQTNXRE7.js.map +1 -0
- package/dist/chunk-XZPAA5TO.js +817 -0
- package/dist/chunk-XZPAA5TO.js.map +1 -0
- package/dist/cli/index.js +77 -42
- package/dist/cli/index.js.map +1 -1
- package/dist/client/index.d.ts +1 -2
- package/dist/client/index.js +0 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client-JJFLE6RT.js +9 -0
- package/dist/{computer-BPdxSo6X.d.ts → computer-DzMR92tK.d.ts} +1 -1
- package/dist/docker.d.ts +2 -2
- package/dist/docker.js +0 -1
- package/dist/docker.js.map +1 -1
- package/dist/e2b.d.ts +2 -2
- package/dist/e2b.js +0 -1
- package/dist/e2b.js.map +1 -1
- package/dist/freestyle.d.ts +2 -2
- package/dist/freestyle.js +0 -1
- package/dist/freestyle.js.map +1 -1
- package/dist/{headless-FFU2DESQ.js → headless-25DU4MJQ.js} +1 -3
- package/dist/{headless-FFU2DESQ.js.map → headless-25DU4MJQ.js.map} +1 -1
- package/dist/{history-snip-64GYP4ZL.js → history-snip-HAWNAYKY.js} +1 -2
- package/dist/index.d.ts +351 -72
- package/dist/index.js +54 -55
- package/dist/jsonrpc/index.js +0 -1
- package/dist/local.d.ts +168 -0
- package/dist/local.js +40 -0
- package/dist/local.js.map +1 -0
- package/dist/lsp/index.d.ts +4 -5
- package/dist/lsp/index.js +0 -1
- package/dist/{lsp-PS3BWIHC.js → lsp-3APWNKB2.js} +1 -2
- package/dist/{manager-DLXK63XC.js → manager-Z5EQ7YYV.js} +1 -2
- package/dist/mcp/index.d.ts +16 -8
- package/dist/mcp/index.js +5 -6
- package/dist/mcp/index.js.map +1 -1
- package/dist/{mcp-auth-AEI2R4ZC.js → mcp-auth-NOIQPF7W.js} +1 -2
- package/dist/{provider-factory-TUHU3DIG.js → provider-factory-KNBSHXJ6.js} +3 -3
- package/dist/{render-GRN4ZSSW.js → render-4VEODRK7.js} +1 -2
- package/dist/{resolve-6KUZNEYW.js → resolve-AGQZFMKD.js} +3 -3
- package/dist/sandbox-DAqQo0Tj.d.ts +49 -0
- package/dist/sandbox-index-ODNREIFA.js +32 -0
- package/dist/sandbox-index-ODNREIFA.js.map +1 -0
- package/dist/server/index.d.ts +18 -7
- package/dist/server/index.js +9 -5
- package/dist/server/index.js.map +1 -1
- package/dist/{server-BzNGKTP6.d.ts → server-DFXdlqyX.d.ts} +1 -1
- package/dist/{spinner-OJNR6NFO.js → spinner-72JEISPK.js} +1 -2
- package/dist/sprites.d.ts +2 -2
- package/dist/sprites.js +0 -1
- package/dist/sprites.js.map +1 -1
- package/dist/ssh.d.ts +2 -2
- package/dist/ssh.js +0 -1
- package/dist/ssh.js.map +1 -1
- package/dist/{types-DhXwOQwD.d.ts → types-BX4ALqoN.d.ts} +76 -4
- package/dist/{types-kiGBF35b.d.ts → types-DLZNyF5t.d.ts} +125 -1
- package/dist/unsandboxed.d.ts +59 -0
- package/dist/unsandboxed.js +32 -0
- package/dist/unsandboxed.js.map +1 -0
- package/dist/{uuid-RVN2T26F.js → uuid-CVTNAPEB.js} +1 -2
- package/dist/{zod-7YXKWYMC.js → zod-VKURGPRT.js} +1 -2
- package/package.json +35 -50
- package/dist/cache-BlBwXXPS.d.ts +0 -38
- package/dist/chunk-5GEX6ZSB.js.map +0 -1
- package/dist/chunk-6MMYCGJQ.js.map +0 -1
- package/dist/chunk-7IQCQI2G.js +0 -94
- package/dist/chunk-7IQCQI2G.js.map +0 -1
- package/dist/chunk-CCM2AXZG.js +0 -16
- package/dist/chunk-CCM2AXZG.js.map +0 -1
- package/dist/chunk-DGUM43GV.js +0 -11
- package/dist/chunk-HEQQQGK5.js +0 -131
- package/dist/chunk-HEQQQGK5.js.map +0 -1
- package/dist/chunk-I3JTUFPK.js +0 -171
- package/dist/chunk-I3JTUFPK.js.map +0 -1
- package/dist/chunk-XZN4QZLK.js.map +0 -1
- package/dist/chunk-ZXSDKBYB.js +0 -474
- package/dist/chunk-ZXSDKBYB.js.map +0 -1
- package/dist/client-CRRO2376.js +0 -10
- package/dist/providers/anthropic.d.ts +0 -19
- package/dist/providers/anthropic.js +0 -36
- package/dist/providers/anthropic.js.map +0 -1
- package/dist/providers/bedrock.d.ts +0 -39
- package/dist/providers/bedrock.js +0 -56
- package/dist/providers/bedrock.js.map +0 -1
- package/dist/providers/gemini.d.ts +0 -17
- package/dist/providers/gemini.js +0 -262
- package/dist/providers/gemini.js.map +0 -1
- package/dist/providers/ollama.d.ts +0 -13
- package/dist/providers/ollama.js +0 -20
- package/dist/providers/ollama.js.map +0 -1
- package/dist/providers/openai.d.ts +0 -21
- package/dist/providers/openai.js +0 -9
- package/dist/providers/openrouter.d.ts +0 -16
- package/dist/providers/openrouter.js +0 -24
- package/dist/providers/openrouter.js.map +0 -1
- package/dist/providers/vertex.d.ts +0 -42
- package/dist/providers/vertex.js +0 -68
- package/dist/providers/vertex.js.map +0 -1
- package/dist/sandbox-9qeMTNrD.d.ts +0 -126
- package/dist/types-CD0rUKKT.d.ts +0 -109
- package/dist/uuid-RVN2T26F.js.map +0 -1
- package/dist/zod-7YXKWYMC.js.map +0 -1
- /package/dist/{chunk-DGUM43GV.js.map → client-JJFLE6RT.js.map} +0 -0
- /package/dist/{client-CRRO2376.js.map → history-snip-HAWNAYKY.js.map} +0 -0
- /package/dist/{history-snip-64GYP4ZL.js.map → lsp-3APWNKB2.js.map} +0 -0
- /package/dist/{lsp-PS3BWIHC.js.map → manager-Z5EQ7YYV.js.map} +0 -0
- /package/dist/{manager-DLXK63XC.js.map → mcp-auth-NOIQPF7W.js.map} +0 -0
- /package/dist/{mcp-auth-AEI2R4ZC.js.map → provider-factory-KNBSHXJ6.js.map} +0 -0
- /package/dist/{provider-factory-TUHU3DIG.js.map → render-4VEODRK7.js.map} +0 -0
- /package/dist/{providers/openai.js.map → resolve-AGQZFMKD.js.map} +0 -0
- /package/dist/{render-GRN4ZSSW.js.map → spinner-72JEISPK.js.map} +0 -0
- /package/dist/{resolve-6KUZNEYW.js.map → uuid-CVTNAPEB.js.map} +0 -0
- /package/dist/{spinner-OJNR6NFO.js.map → zod-VKURGPRT.js.map} +0 -0
|
@@ -0,0 +1,817 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChatStreamError,
|
|
3
|
+
getMessageCacheBreakpointIndex
|
|
4
|
+
} from "./chunk-OPFFLQZL.js";
|
|
5
|
+
|
|
6
|
+
// src/providers/ai-sdk/errors.ts
|
|
7
|
+
function isApiCallErrorLike(err) {
|
|
8
|
+
if (!err || typeof err !== "object") return false;
|
|
9
|
+
const name = err.name;
|
|
10
|
+
if (name !== "AI_APICallError" && name !== "APICallError") return false;
|
|
11
|
+
return typeof err.message === "string";
|
|
12
|
+
}
|
|
13
|
+
function mapApiCallError(err) {
|
|
14
|
+
if (err instanceof ChatStreamError) return err;
|
|
15
|
+
if (isApiCallErrorLike(err)) {
|
|
16
|
+
return new ChatStreamError(err.message, {
|
|
17
|
+
status: err.statusCode,
|
|
18
|
+
retryAfter: err.responseHeaders?.["retry-after"],
|
|
19
|
+
cause: err
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
23
|
+
return new ChatStreamError(message, { cause: err });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/providers/ai-sdk/compat/schema.ts
|
|
27
|
+
var PERMISSIVE_TYPES = [
|
|
28
|
+
"string",
|
|
29
|
+
"number",
|
|
30
|
+
"integer",
|
|
31
|
+
"boolean",
|
|
32
|
+
"object",
|
|
33
|
+
"null"
|
|
34
|
+
];
|
|
35
|
+
function fixTypelessProperties(schema) {
|
|
36
|
+
if (typeof schema !== "object" || schema === null) return schema;
|
|
37
|
+
const result = { ...schema };
|
|
38
|
+
if (result.properties && typeof result.properties === "object" && !Array.isArray(result.properties)) {
|
|
39
|
+
result.properties = Object.fromEntries(
|
|
40
|
+
Object.entries(result.properties).map(([key, value]) => {
|
|
41
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
42
|
+
return [key, value];
|
|
43
|
+
}
|
|
44
|
+
const propSchema = value;
|
|
45
|
+
const hasType = "type" in propSchema;
|
|
46
|
+
const hasRef = "$ref" in propSchema;
|
|
47
|
+
const hasAnyOf = "anyOf" in propSchema;
|
|
48
|
+
const hasOneOf = "oneOf" in propSchema;
|
|
49
|
+
const hasAllOf = "allOf" in propSchema;
|
|
50
|
+
if (!hasType && !hasRef && !hasAnyOf && !hasOneOf && !hasAllOf) {
|
|
51
|
+
const { items: _items, ...rest } = propSchema;
|
|
52
|
+
return [key, { ...rest, type: [...PERMISSIVE_TYPES] }];
|
|
53
|
+
}
|
|
54
|
+
return [key, fixTypelessProperties(propSchema)];
|
|
55
|
+
})
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
if (result.items) {
|
|
59
|
+
if (Array.isArray(result.items)) {
|
|
60
|
+
result.items = result.items.map(
|
|
61
|
+
(item) => fixTypelessProperties(item)
|
|
62
|
+
);
|
|
63
|
+
} else if (typeof result.items === "object") {
|
|
64
|
+
result.items = fixTypelessProperties(result.items);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/providers/ai-sdk/request.ts
|
|
71
|
+
function translateRequest(params, opts) {
|
|
72
|
+
const { providerFamily } = opts;
|
|
73
|
+
const useAnthropicCache = providerFamily === "anthropic" && opts.cacheConfig?.enabled === true;
|
|
74
|
+
const prompt = buildPrompt(params, {
|
|
75
|
+
providerFamily,
|
|
76
|
+
cacheConfig: useAnthropicCache ? opts.cacheConfig : void 0,
|
|
77
|
+
skipCacheWrite: params.skipCacheWrite
|
|
78
|
+
});
|
|
79
|
+
const tools = buildTools(params.tools, {
|
|
80
|
+
providerFamily,
|
|
81
|
+
cacheConfig: useAnthropicCache ? opts.cacheConfig : void 0
|
|
82
|
+
});
|
|
83
|
+
const call = {
|
|
84
|
+
prompt,
|
|
85
|
+
maxOutputTokens: params.max_tokens
|
|
86
|
+
};
|
|
87
|
+
if (params.signal) call.abortSignal = params.signal;
|
|
88
|
+
if (tools && tools.length > 0) call.tools = tools;
|
|
89
|
+
const thinkingEnabled = params.thinking?.type === "enabled" && params.thinking.budgetTokens > 0;
|
|
90
|
+
if (providerFamily === "anthropic") {
|
|
91
|
+
if (!thinkingEnabled && params.temperature !== void 0) {
|
|
92
|
+
call.temperature = params.temperature;
|
|
93
|
+
}
|
|
94
|
+
} else if (params.temperature !== void 0) {
|
|
95
|
+
call.temperature = params.temperature;
|
|
96
|
+
}
|
|
97
|
+
if (params.outputFormat?.type === "json_schema") {
|
|
98
|
+
call.responseFormat = {
|
|
99
|
+
type: "json",
|
|
100
|
+
schema: params.outputFormat.schema,
|
|
101
|
+
name: params.outputFormat.name
|
|
102
|
+
};
|
|
103
|
+
} else if (params.outputFormat?.type === "json_object") {
|
|
104
|
+
call.responseFormat = { type: "json" };
|
|
105
|
+
}
|
|
106
|
+
const providerOptions = buildProviderOptions(params, providerFamily);
|
|
107
|
+
if (providerOptions) call.providerOptions = providerOptions;
|
|
108
|
+
return call;
|
|
109
|
+
}
|
|
110
|
+
function buildProviderOptions(params, family) {
|
|
111
|
+
const thinking = params.thinking;
|
|
112
|
+
const thinkingEnabled = thinking?.type === "enabled" && thinking.budgetTokens > 0;
|
|
113
|
+
switch (family) {
|
|
114
|
+
case "anthropic": {
|
|
115
|
+
if (!thinkingEnabled) {
|
|
116
|
+
return void 0;
|
|
117
|
+
}
|
|
118
|
+
const { budgetTokens } = thinking;
|
|
119
|
+
const maxOutput = params.max_tokens;
|
|
120
|
+
const clampedBudget = typeof maxOutput === "number" && maxOutput > 0 ? Math.min(budgetTokens, maxOutput - 1) : budgetTokens;
|
|
121
|
+
return {
|
|
122
|
+
anthropic: {
|
|
123
|
+
thinking: {
|
|
124
|
+
type: "enabled",
|
|
125
|
+
budgetTokens: clampedBudget
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
case "openai": {
|
|
131
|
+
const effort = params.reasoningEffort ?? (thinkingEnabled ? "high" : thinking?.type === "disabled" ? "minimal" : void 0);
|
|
132
|
+
if (!effort) return void 0;
|
|
133
|
+
return { openai: { reasoningEffort: effort } };
|
|
134
|
+
}
|
|
135
|
+
case "google": {
|
|
136
|
+
if (thinkingEnabled) {
|
|
137
|
+
const { budgetTokens } = thinking;
|
|
138
|
+
return { google: { thinkingConfig: { thinkingBudget: budgetTokens } } };
|
|
139
|
+
}
|
|
140
|
+
if (thinking?.type === "disabled") {
|
|
141
|
+
return { google: { thinkingConfig: { thinkingBudget: 0 } } };
|
|
142
|
+
}
|
|
143
|
+
return void 0;
|
|
144
|
+
}
|
|
145
|
+
default:
|
|
146
|
+
return void 0;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function buildPrompt(params, opts) {
|
|
150
|
+
const result = [];
|
|
151
|
+
const convo = params.messages.filter((m) => m.role !== "system");
|
|
152
|
+
const cacheEnabled = opts.cacheConfig?.enabled === true;
|
|
153
|
+
const cacheBreakpoint = cacheEnabled ? getMessageCacheBreakpointIndex(convo, opts.skipCacheWrite) : -1;
|
|
154
|
+
if (params.system) {
|
|
155
|
+
const sys = { role: "system", content: params.system };
|
|
156
|
+
if (cacheEnabled) {
|
|
157
|
+
sys.providerOptions = {
|
|
158
|
+
anthropic: { cacheControl: buildCacheControl(opts.cacheConfig) }
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
result.push(sys);
|
|
162
|
+
}
|
|
163
|
+
for (let i = 0; i < convo.length; i++) {
|
|
164
|
+
const msg = convo[i];
|
|
165
|
+
const addCache = cacheEnabled && i === cacheBreakpoint;
|
|
166
|
+
if (msg.role === "user") {
|
|
167
|
+
result.push(convertUserMessage(msg, addCache ? opts.cacheConfig : void 0));
|
|
168
|
+
} else if (msg.role === "assistant") {
|
|
169
|
+
result.push(
|
|
170
|
+
convertAssistantMessage(msg, {
|
|
171
|
+
addCache,
|
|
172
|
+
cacheConfig: opts.cacheConfig,
|
|
173
|
+
providerFamily: opts.providerFamily
|
|
174
|
+
})
|
|
175
|
+
);
|
|
176
|
+
} else if (msg.role === "tool") {
|
|
177
|
+
result.push(
|
|
178
|
+
convertToolMessage(msg, addCache ? opts.cacheConfig : void 0)
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
function convertUserMessage(msg, cacheConfig) {
|
|
185
|
+
const parts = Array.isArray(msg.content) ? contentPartsToAiSdk(msg.content) : [{ type: "text", text: msg.content }];
|
|
186
|
+
if (cacheConfig?.enabled && parts.length > 0) {
|
|
187
|
+
const last = parts[parts.length - 1];
|
|
188
|
+
last.providerOptions = {
|
|
189
|
+
...last.providerOptions ?? {},
|
|
190
|
+
anthropic: { cacheControl: buildCacheControl(cacheConfig) }
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
return { role: "user", content: parts };
|
|
194
|
+
}
|
|
195
|
+
function convertAssistantMessage(msg, opts) {
|
|
196
|
+
const content = [];
|
|
197
|
+
if (msg.thinking_content && opts.providerFamily === "anthropic") {
|
|
198
|
+
const reasoning = {
|
|
199
|
+
type: "reasoning",
|
|
200
|
+
text: msg.thinking_content
|
|
201
|
+
};
|
|
202
|
+
if (msg.thinking_signature) {
|
|
203
|
+
reasoning.providerOptions = {
|
|
204
|
+
anthropic: { signature: msg.thinking_signature }
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
content.push(reasoning);
|
|
208
|
+
}
|
|
209
|
+
if (msg.redacted_thinking_data && opts.providerFamily === "anthropic") {
|
|
210
|
+
content.push({
|
|
211
|
+
type: "reasoning",
|
|
212
|
+
text: "",
|
|
213
|
+
providerOptions: {
|
|
214
|
+
anthropic: { redactedData: msg.redacted_thinking_data }
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (typeof msg.content === "string" && msg.content !== "") {
|
|
219
|
+
content.push({ type: "text", text: msg.content });
|
|
220
|
+
} else if (msg.content != null && typeof msg.content !== "string" && Array.isArray(msg.content)) {
|
|
221
|
+
for (const part of msg.content) {
|
|
222
|
+
if (part.type === "text") content.push({ type: "text", text: part.text });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (msg.tool_calls) {
|
|
226
|
+
for (const tc of msg.tool_calls) {
|
|
227
|
+
let input = {};
|
|
228
|
+
if (tc.function.arguments) {
|
|
229
|
+
try {
|
|
230
|
+
input = JSON.parse(tc.function.arguments);
|
|
231
|
+
} catch {
|
|
232
|
+
input = {};
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
content.push({
|
|
236
|
+
type: "tool-call",
|
|
237
|
+
toolCallId: tc.id,
|
|
238
|
+
toolName: tc.function.name,
|
|
239
|
+
input
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (content.length === 0) {
|
|
244
|
+
content.push({ type: "text", text: "" });
|
|
245
|
+
}
|
|
246
|
+
if (opts.addCache && opts.cacheConfig?.enabled) {
|
|
247
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
248
|
+
const block = content[i];
|
|
249
|
+
if (block.type === "reasoning") continue;
|
|
250
|
+
block.providerOptions = {
|
|
251
|
+
...block.providerOptions ?? {},
|
|
252
|
+
anthropic: { cacheControl: buildCacheControl(opts.cacheConfig) }
|
|
253
|
+
};
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return { role: "assistant", content };
|
|
258
|
+
}
|
|
259
|
+
function convertToolMessage(msg, cacheConfig) {
|
|
260
|
+
const output = Array.isArray(msg.content) ? toolContentToOutput(msg.content, msg.isError) : msg.isError ? { type: "error-text", value: msg.content } : { type: "text", value: msg.content };
|
|
261
|
+
const part = {
|
|
262
|
+
type: "tool-result",
|
|
263
|
+
toolCallId: msg.tool_call_id,
|
|
264
|
+
toolName: "tool",
|
|
265
|
+
output
|
|
266
|
+
};
|
|
267
|
+
if (cacheConfig?.enabled) {
|
|
268
|
+
part.providerOptions = {
|
|
269
|
+
anthropic: { cacheControl: buildCacheControl(cacheConfig) }
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
return { role: "tool", content: [part] };
|
|
273
|
+
}
|
|
274
|
+
function contentPartsToAiSdk(parts) {
|
|
275
|
+
return parts.map((part) => {
|
|
276
|
+
if (part.type === "text") {
|
|
277
|
+
return { type: "text", text: part.text };
|
|
278
|
+
}
|
|
279
|
+
if (part.type === "image") {
|
|
280
|
+
return {
|
|
281
|
+
type: "file",
|
|
282
|
+
mediaType: part.media_type,
|
|
283
|
+
data: part.data
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
type: "file",
|
|
288
|
+
mediaType: "image/*",
|
|
289
|
+
data: new URL(part.url)
|
|
290
|
+
};
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
function toolContentToOutput(parts, isError) {
|
|
294
|
+
const contentValue = parts.map((p) => {
|
|
295
|
+
if (p.type === "text") return { type: "text", text: p.text };
|
|
296
|
+
if (p.type === "image") {
|
|
297
|
+
return { type: "image-data", data: p.data, mediaType: p.media_type };
|
|
298
|
+
}
|
|
299
|
+
return { type: "image-url", url: p.url };
|
|
300
|
+
});
|
|
301
|
+
if (isError) {
|
|
302
|
+
const textOnly = contentValue.filter((v) => v.type === "text").map((v) => v.text).join("\n");
|
|
303
|
+
return { type: "error-text", value: textOnly };
|
|
304
|
+
}
|
|
305
|
+
return { type: "content", value: contentValue };
|
|
306
|
+
}
|
|
307
|
+
function buildTools(tools, opts) {
|
|
308
|
+
if (!tools || tools.length === 0) return void 0;
|
|
309
|
+
const cacheEnabled = opts.providerFamily === "anthropic" && opts.cacheConfig?.enabled === true;
|
|
310
|
+
return tools.map((t, idx) => {
|
|
311
|
+
const schema = fixTypelessProperties(
|
|
312
|
+
t.function.parameters
|
|
313
|
+
);
|
|
314
|
+
const tool = {
|
|
315
|
+
type: "function",
|
|
316
|
+
name: t.function.name,
|
|
317
|
+
description: t.function.description,
|
|
318
|
+
inputSchema: schema
|
|
319
|
+
};
|
|
320
|
+
if (cacheEnabled && idx === tools.length - 1) {
|
|
321
|
+
tool.providerOptions = {
|
|
322
|
+
anthropic: { cacheControl: buildCacheControl(opts.cacheConfig) }
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
return tool;
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
function buildCacheControl(config) {
|
|
329
|
+
const cc = { type: "ephemeral" };
|
|
330
|
+
if (config.ttl) cc.ttl = config.ttl;
|
|
331
|
+
if (config.scope) cc.scope = config.scope;
|
|
332
|
+
return cc;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// src/providers/ai-sdk/compat/json-repair.ts
|
|
336
|
+
function sanitizeToolCallInput(input) {
|
|
337
|
+
try {
|
|
338
|
+
JSON.parse(input);
|
|
339
|
+
return input;
|
|
340
|
+
} catch {
|
|
341
|
+
return input.replace(/[\s]*<\|[^|]*\|>[\s]*/g, "").trim();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
function tryRepairJson(input) {
|
|
345
|
+
let repaired = input.trim();
|
|
346
|
+
repaired = repaired.replace(
|
|
347
|
+
/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)"/g,
|
|
348
|
+
(match, prefix, name) => {
|
|
349
|
+
if (prefix.trimEnd().endsWith('"')) return match;
|
|
350
|
+
return `${prefix}"${name}"`;
|
|
351
|
+
}
|
|
352
|
+
);
|
|
353
|
+
repaired = repaired.replace(
|
|
354
|
+
/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g,
|
|
355
|
+
'$1"$2":'
|
|
356
|
+
);
|
|
357
|
+
repaired = repaired.replace(/'/g, '"');
|
|
358
|
+
repaired = repaired.replace(/,(\s*[}\]])/g, "$1");
|
|
359
|
+
repaired = repaired.replace(
|
|
360
|
+
/:\s*(\d{4}-\d{2}-\d{2}(?:T[\d:]+)?)\s*([,}])/g,
|
|
361
|
+
': "$1"$2'
|
|
362
|
+
);
|
|
363
|
+
try {
|
|
364
|
+
return JSON.parse(repaired);
|
|
365
|
+
} catch {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function parseToolCallJson(input) {
|
|
370
|
+
if (!input) return void 0;
|
|
371
|
+
const sanitized = sanitizeToolCallInput(input);
|
|
372
|
+
if (!sanitized) return void 0;
|
|
373
|
+
try {
|
|
374
|
+
return JSON.parse(sanitized);
|
|
375
|
+
} catch {
|
|
376
|
+
return tryRepairJson(sanitized);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// src/providers/ai-sdk/stream.ts
|
|
381
|
+
async function* translateStream(stream, model, signal) {
|
|
382
|
+
const reader = stream.getReader();
|
|
383
|
+
const state = createState();
|
|
384
|
+
try {
|
|
385
|
+
while (true) {
|
|
386
|
+
if (signal?.aborted) {
|
|
387
|
+
try {
|
|
388
|
+
await reader.cancel();
|
|
389
|
+
} catch {
|
|
390
|
+
}
|
|
391
|
+
throw new ChatStreamError("aborted", { cause: signal.reason });
|
|
392
|
+
}
|
|
393
|
+
const { done, value: part } = await reader.read();
|
|
394
|
+
if (done) break;
|
|
395
|
+
for (const chunk of processStreamPart(part, state, model)) {
|
|
396
|
+
yield chunk;
|
|
397
|
+
}
|
|
398
|
+
if (state.terminated) break;
|
|
399
|
+
}
|
|
400
|
+
} catch (err) {
|
|
401
|
+
if (err instanceof ChatStreamError) throw err;
|
|
402
|
+
throw mapApiCallError(err);
|
|
403
|
+
} finally {
|
|
404
|
+
try {
|
|
405
|
+
reader.releaseLock();
|
|
406
|
+
} catch {
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
function createState() {
|
|
411
|
+
return {
|
|
412
|
+
chunkIndex: 0,
|
|
413
|
+
toolIndexMap: /* @__PURE__ */ new Map(),
|
|
414
|
+
toolNames: /* @__PURE__ */ new Map(),
|
|
415
|
+
nextToolIndex: 0,
|
|
416
|
+
terminated: false
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
function processStreamPart(part, state, model) {
|
|
420
|
+
if (!part || typeof part !== "object") return [];
|
|
421
|
+
const chunkId = `chatcmpl-${state.chunkIndex++}`;
|
|
422
|
+
switch (part.type) {
|
|
423
|
+
case "text-delta": {
|
|
424
|
+
const delta = part.delta;
|
|
425
|
+
if (!delta) return [];
|
|
426
|
+
return [makeChunk(chunkId, model, { content: delta })];
|
|
427
|
+
}
|
|
428
|
+
case "reasoning-delta": {
|
|
429
|
+
const delta = part.delta;
|
|
430
|
+
if (!delta) return [];
|
|
431
|
+
return [makeChunk(chunkId, model, { thinking_content: delta })];
|
|
432
|
+
}
|
|
433
|
+
case "reasoning-end": {
|
|
434
|
+
const meta = part.providerMetadata;
|
|
435
|
+
const anthropicMeta = meta?.anthropic;
|
|
436
|
+
if (!anthropicMeta) return [];
|
|
437
|
+
const delta = {};
|
|
438
|
+
if (typeof anthropicMeta.signature === "string") {
|
|
439
|
+
delta.thinking_signature = anthropicMeta.signature;
|
|
440
|
+
}
|
|
441
|
+
if (typeof anthropicMeta.redactedData === "string") {
|
|
442
|
+
delta.redacted_thinking_data = anthropicMeta.redactedData;
|
|
443
|
+
}
|
|
444
|
+
if (Object.keys(delta).length === 0) return [];
|
|
445
|
+
return [makeChunk(chunkId, model, delta)];
|
|
446
|
+
}
|
|
447
|
+
case "tool-input-start": {
|
|
448
|
+
const p = part;
|
|
449
|
+
if (!p.id || !p.toolName) return [];
|
|
450
|
+
if (state.toolIndexMap.has(p.id)) return [];
|
|
451
|
+
const idx = state.nextToolIndex++;
|
|
452
|
+
state.toolIndexMap.set(p.id, idx);
|
|
453
|
+
state.toolNames.set(p.id, p.toolName);
|
|
454
|
+
return [
|
|
455
|
+
makeChunk(chunkId, model, {
|
|
456
|
+
tool_calls: [
|
|
457
|
+
{
|
|
458
|
+
index: idx,
|
|
459
|
+
id: p.id,
|
|
460
|
+
type: "function",
|
|
461
|
+
function: { name: p.toolName, arguments: "" }
|
|
462
|
+
}
|
|
463
|
+
]
|
|
464
|
+
})
|
|
465
|
+
];
|
|
466
|
+
}
|
|
467
|
+
case "tool-input-delta": {
|
|
468
|
+
const p = part;
|
|
469
|
+
if (!p.delta) return [];
|
|
470
|
+
let idx = state.toolIndexMap.get(p.id);
|
|
471
|
+
if (idx === void 0) {
|
|
472
|
+
idx = state.nextToolIndex++;
|
|
473
|
+
state.toolIndexMap.set(p.id, idx);
|
|
474
|
+
}
|
|
475
|
+
return [
|
|
476
|
+
makeChunk(chunkId, model, {
|
|
477
|
+
tool_calls: [
|
|
478
|
+
{
|
|
479
|
+
index: idx,
|
|
480
|
+
function: { arguments: p.delta }
|
|
481
|
+
}
|
|
482
|
+
]
|
|
483
|
+
})
|
|
484
|
+
];
|
|
485
|
+
}
|
|
486
|
+
case "tool-call": {
|
|
487
|
+
const p = part;
|
|
488
|
+
if (state.toolIndexMap.has(p.toolCallId)) {
|
|
489
|
+
return [];
|
|
490
|
+
}
|
|
491
|
+
const idx = state.nextToolIndex++;
|
|
492
|
+
state.toolIndexMap.set(p.toolCallId, idx);
|
|
493
|
+
state.toolNames.set(p.toolCallId, p.toolName);
|
|
494
|
+
const parsed = parseToolCallJson(p.input);
|
|
495
|
+
const argsString = parsed === null || parsed === void 0 ? p.input ?? "" : JSON.stringify(parsed);
|
|
496
|
+
return [
|
|
497
|
+
makeChunk(chunkId, model, {
|
|
498
|
+
tool_calls: [
|
|
499
|
+
{
|
|
500
|
+
index: idx,
|
|
501
|
+
id: p.toolCallId,
|
|
502
|
+
type: "function",
|
|
503
|
+
function: { name: p.toolName, arguments: argsString }
|
|
504
|
+
}
|
|
505
|
+
]
|
|
506
|
+
})
|
|
507
|
+
];
|
|
508
|
+
}
|
|
509
|
+
case "finish": {
|
|
510
|
+
state.terminated = true;
|
|
511
|
+
const p = part;
|
|
512
|
+
const finishReason = mapFinishReason(
|
|
513
|
+
p.finishReason,
|
|
514
|
+
state.toolIndexMap.size > 0
|
|
515
|
+
);
|
|
516
|
+
const usage = mapUsage(p.usage, p.providerMetadata);
|
|
517
|
+
return [
|
|
518
|
+
{
|
|
519
|
+
id: chunkId,
|
|
520
|
+
model,
|
|
521
|
+
choices: [
|
|
522
|
+
{
|
|
523
|
+
index: 0,
|
|
524
|
+
delta: {},
|
|
525
|
+
finish_reason: finishReason
|
|
526
|
+
}
|
|
527
|
+
],
|
|
528
|
+
usage
|
|
529
|
+
}
|
|
530
|
+
];
|
|
531
|
+
}
|
|
532
|
+
case "error": {
|
|
533
|
+
state.terminated = true;
|
|
534
|
+
throw mapApiCallError(part.error);
|
|
535
|
+
}
|
|
536
|
+
// No-op events we simply drop. These still advance chunkIndex for
|
|
537
|
+
// deterministic ids, matching mastra's approach.
|
|
538
|
+
case "stream-start":
|
|
539
|
+
case "response-metadata":
|
|
540
|
+
case "text-start":
|
|
541
|
+
case "text-end":
|
|
542
|
+
case "reasoning-start":
|
|
543
|
+
case "tool-input-end":
|
|
544
|
+
case "tool-result":
|
|
545
|
+
case "tool-approval-request":
|
|
546
|
+
case "file":
|
|
547
|
+
case "source":
|
|
548
|
+
case "raw":
|
|
549
|
+
return [];
|
|
550
|
+
default:
|
|
551
|
+
return [];
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
function mapFinishReason(reason, hasToolCalls) {
|
|
555
|
+
const unified = typeof reason === "object" && reason !== null && "unified" in reason ? reason.unified : reason ?? "other";
|
|
556
|
+
switch (unified) {
|
|
557
|
+
case "stop":
|
|
558
|
+
return hasToolCalls ? "tool_calls" : "stop";
|
|
559
|
+
case "length":
|
|
560
|
+
return "length";
|
|
561
|
+
case "content-filter":
|
|
562
|
+
return "content_filter";
|
|
563
|
+
case "tool-calls":
|
|
564
|
+
return "tool_calls";
|
|
565
|
+
case "error":
|
|
566
|
+
return "error";
|
|
567
|
+
case "other":
|
|
568
|
+
case "unknown":
|
|
569
|
+
default:
|
|
570
|
+
return hasToolCalls ? "tool_calls" : "stop";
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
function mapUsage(usage, providerMetadata) {
|
|
574
|
+
if (!usage) return void 0;
|
|
575
|
+
let prompt = 0;
|
|
576
|
+
let completion = 0;
|
|
577
|
+
let cacheRead;
|
|
578
|
+
let cacheCreation;
|
|
579
|
+
let thinking;
|
|
580
|
+
const nested = typeof usage.inputTokens === "object";
|
|
581
|
+
if (nested) {
|
|
582
|
+
const u = usage;
|
|
583
|
+
prompt = u.inputTokens.total ?? 0;
|
|
584
|
+
completion = u.outputTokens.total ?? 0;
|
|
585
|
+
cacheRead = u.inputTokens.cacheRead;
|
|
586
|
+
cacheCreation = u.inputTokens.cacheWrite;
|
|
587
|
+
thinking = u.outputTokens.reasoning;
|
|
588
|
+
} else {
|
|
589
|
+
const u = usage;
|
|
590
|
+
prompt = u.inputTokens ?? 0;
|
|
591
|
+
completion = u.outputTokens ?? 0;
|
|
592
|
+
thinking = u.reasoningTokens;
|
|
593
|
+
cacheRead = u.cachedInputTokens;
|
|
594
|
+
}
|
|
595
|
+
if (providerMetadata) {
|
|
596
|
+
const anth = providerMetadata.anthropic;
|
|
597
|
+
if (anth) {
|
|
598
|
+
if (cacheRead === void 0 && typeof anth.cacheReadInputTokens === "number") {
|
|
599
|
+
cacheRead = anth.cacheReadInputTokens;
|
|
600
|
+
}
|
|
601
|
+
if (cacheCreation === void 0 && typeof anth.cacheCreationInputTokens === "number") {
|
|
602
|
+
cacheCreation = anth.cacheCreationInputTokens;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
const openai = providerMetadata.openai;
|
|
606
|
+
if (openai && cacheRead === void 0 && typeof openai.cachedPromptTokens === "number") {
|
|
607
|
+
cacheRead = openai.cachedPromptTokens;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
return {
|
|
611
|
+
prompt_tokens: prompt,
|
|
612
|
+
completion_tokens: completion,
|
|
613
|
+
total_tokens: prompt + completion,
|
|
614
|
+
cache_read_tokens: cacheRead,
|
|
615
|
+
cache_creation_tokens: cacheCreation,
|
|
616
|
+
thinking_tokens: thinking
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
function makeChunk(id, model, delta) {
|
|
620
|
+
return {
|
|
621
|
+
id,
|
|
622
|
+
model,
|
|
623
|
+
choices: [
|
|
624
|
+
{
|
|
625
|
+
index: 0,
|
|
626
|
+
delta,
|
|
627
|
+
finish_reason: null
|
|
628
|
+
}
|
|
629
|
+
]
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// src/providers/ai-sdk/provider-family.ts
|
|
634
|
+
function inferProviderFamily(providerString) {
|
|
635
|
+
const p = providerString.toLowerCase();
|
|
636
|
+
if (p.includes("anthropic")) return "anthropic";
|
|
637
|
+
if (p.startsWith("amazon-bedrock") || p.startsWith("bedrock")) {
|
|
638
|
+
return "anthropic";
|
|
639
|
+
}
|
|
640
|
+
if (p.startsWith("google.") || p === "google" || p.startsWith("google-generative-ai")) {
|
|
641
|
+
return "google";
|
|
642
|
+
}
|
|
643
|
+
if (p.startsWith("openai") || p.startsWith("openrouter") || p.startsWith("ollama") || p.endsWith(".chat") || p.endsWith(".responses")) {
|
|
644
|
+
return "openai";
|
|
645
|
+
}
|
|
646
|
+
return "unknown";
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// src/providers/ai-sdk/provider.ts
|
|
650
|
+
var AiSdkProvider = class {
|
|
651
|
+
defaultModel;
|
|
652
|
+
providerFamily;
|
|
653
|
+
model;
|
|
654
|
+
cacheConfig;
|
|
655
|
+
constructor(opts) {
|
|
656
|
+
this.model = opts.model;
|
|
657
|
+
this.defaultModel = opts.defaultModel ?? opts.model.modelId;
|
|
658
|
+
this.providerFamily = opts.providerFamily ?? inferProviderFamily(opts.model.provider);
|
|
659
|
+
this.cacheConfig = opts.cacheConfig;
|
|
660
|
+
}
|
|
661
|
+
async *chat(params) {
|
|
662
|
+
const call = translateRequest(params, {
|
|
663
|
+
providerFamily: this.providerFamily,
|
|
664
|
+
cacheConfig: this.cacheConfig
|
|
665
|
+
});
|
|
666
|
+
let result;
|
|
667
|
+
try {
|
|
668
|
+
result = await this.model.doStream(call);
|
|
669
|
+
} catch (err) {
|
|
670
|
+
throw mapApiCallError(err);
|
|
671
|
+
}
|
|
672
|
+
const modelId = params.model ?? this.defaultModel;
|
|
673
|
+
yield* translateStream(result.stream, modelId, params.signal);
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
// src/providers/resolve.ts
|
|
678
|
+
var ENV_KEY_MAP = {
|
|
679
|
+
openai: "OPENAI_API_KEY",
|
|
680
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
681
|
+
gemini: "GEMINI_API_KEY",
|
|
682
|
+
openrouter: "OPENROUTER_API_KEY"
|
|
683
|
+
};
|
|
684
|
+
var DEFAULT_MODELS = {
|
|
685
|
+
openai: "gpt-5.4",
|
|
686
|
+
anthropic: "claude-opus-4.6",
|
|
687
|
+
gemini: "gemini-2.5-flash",
|
|
688
|
+
openrouter: "anthropic/claude-opus-4.6",
|
|
689
|
+
bedrock: "us.anthropic.claude-opus-4.6-v1:0",
|
|
690
|
+
vertex: "claude-opus-4.6",
|
|
691
|
+
ollama: "qwen2.5-coder:32b"
|
|
692
|
+
};
|
|
693
|
+
var SUPPORTED_PROVIDERS = Object.keys(DEFAULT_MODELS);
|
|
694
|
+
function getProviderEnvKey(name) {
|
|
695
|
+
const envVar = ENV_KEY_MAP[name];
|
|
696
|
+
return envVar ? process.env[envVar] : void 0;
|
|
697
|
+
}
|
|
698
|
+
function cannotFindVendor(provider, pkg, err) {
|
|
699
|
+
const hint = err instanceof Error && err.message.includes("Cannot find") ? ` Install it with \`pnpm add ${pkg}\`.` : "";
|
|
700
|
+
throw new Error(
|
|
701
|
+
`noumen provider "${provider}" requires the "${pkg}" package.${hint}`,
|
|
702
|
+
{ cause: err }
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
async function loadModule(provider, pkg) {
|
|
706
|
+
try {
|
|
707
|
+
return await import(pkg);
|
|
708
|
+
} catch (err) {
|
|
709
|
+
cannotFindVendor(provider, pkg, err);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
async function resolveProvider(input, opts) {
|
|
713
|
+
if (typeof input !== "string") return input;
|
|
714
|
+
const name = input;
|
|
715
|
+
if (!SUPPORTED_PROVIDERS.includes(name)) {
|
|
716
|
+
throw new Error(
|
|
717
|
+
`Unknown provider "${name}". Supported: ${SUPPORTED_PROVIDERS.join(", ")}`
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
const apiKey = opts?.apiKey ?? getProviderEnvKey(name) ?? process.env.NOUMEN_API_KEY;
|
|
721
|
+
const modelId = opts?.model ?? DEFAULT_MODELS[name];
|
|
722
|
+
switch (name) {
|
|
723
|
+
case "openai": {
|
|
724
|
+
if (!apiKey) {
|
|
725
|
+
throw new Error("OpenAI requires an API key. Set OPENAI_API_KEY or pass apiKey.");
|
|
726
|
+
}
|
|
727
|
+
const mod = await loadModule(name, "@ai-sdk/openai");
|
|
728
|
+
const openai = mod.createOpenAI({ apiKey, baseURL: opts?.baseURL });
|
|
729
|
+
return new AiSdkProvider({ model: openai.chat(modelId) });
|
|
730
|
+
}
|
|
731
|
+
case "anthropic": {
|
|
732
|
+
if (!apiKey) {
|
|
733
|
+
throw new Error("Anthropic requires an API key. Set ANTHROPIC_API_KEY or pass apiKey.");
|
|
734
|
+
}
|
|
735
|
+
const mod = await loadModule(name, "@ai-sdk/anthropic");
|
|
736
|
+
const anthropic = mod.createAnthropic({ apiKey, baseURL: opts?.baseURL });
|
|
737
|
+
return new AiSdkProvider({
|
|
738
|
+
model: anthropic(modelId),
|
|
739
|
+
providerFamily: "anthropic",
|
|
740
|
+
cacheConfig: { enabled: true }
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
case "gemini": {
|
|
744
|
+
if (!apiKey) {
|
|
745
|
+
throw new Error("Gemini requires an API key. Set GEMINI_API_KEY or pass apiKey.");
|
|
746
|
+
}
|
|
747
|
+
const mod = await loadModule(name, "@ai-sdk/google");
|
|
748
|
+
const google = mod.createGoogleGenerativeAI({ apiKey, baseURL: opts?.baseURL });
|
|
749
|
+
return new AiSdkProvider({ model: google(modelId), providerFamily: "google" });
|
|
750
|
+
}
|
|
751
|
+
case "openrouter": {
|
|
752
|
+
if (!apiKey) {
|
|
753
|
+
throw new Error("OpenRouter requires an API key. Set OPENROUTER_API_KEY or pass apiKey.");
|
|
754
|
+
}
|
|
755
|
+
const mod = await loadModule(name, "@openrouter/ai-sdk-provider");
|
|
756
|
+
const openrouter = mod.createOpenRouter({ apiKey });
|
|
757
|
+
return new AiSdkProvider({ model: openrouter.chat(modelId) });
|
|
758
|
+
}
|
|
759
|
+
case "bedrock": {
|
|
760
|
+
const mod = await loadModule(name, "@ai-sdk/amazon-bedrock");
|
|
761
|
+
const bedrock = mod.createAmazonBedrock({
|
|
762
|
+
region: process.env.AWS_REGION,
|
|
763
|
+
baseURL: opts?.baseURL
|
|
764
|
+
});
|
|
765
|
+
return new AiSdkProvider({ model: bedrock(modelId), providerFamily: "anthropic" });
|
|
766
|
+
}
|
|
767
|
+
case "vertex": {
|
|
768
|
+
const mod = await loadModule(name, "@ai-sdk/google-vertex");
|
|
769
|
+
const vertex = mod.createVertex({
|
|
770
|
+
project: process.env.GCLOUD_PROJECT ?? process.env.GOOGLE_CLOUD_PROJECT,
|
|
771
|
+
location: process.env.GOOGLE_CLOUD_LOCATION ?? "us-central1",
|
|
772
|
+
baseURL: opts?.baseURL
|
|
773
|
+
});
|
|
774
|
+
const isClaude = modelId.toLowerCase().includes("claude");
|
|
775
|
+
const model = isClaude ? vertex.anthropic(modelId) : vertex(modelId);
|
|
776
|
+
return new AiSdkProvider({
|
|
777
|
+
model,
|
|
778
|
+
providerFamily: isClaude ? "anthropic" : "google"
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
case "ollama": {
|
|
782
|
+
const mod = await loadModule(name, "ollama-ai-provider-v2");
|
|
783
|
+
const base = opts?.baseURL ?? (process.env.OLLAMA_HOST ? `${process.env.OLLAMA_HOST.replace(/\/+$/, "")}/api` : void 0);
|
|
784
|
+
const ollama = mod.createOllama(base ? { baseURL: base } : {});
|
|
785
|
+
return new AiSdkProvider({ model: ollama(modelId) });
|
|
786
|
+
}
|
|
787
|
+
default:
|
|
788
|
+
throw new Error(`Unhandled provider: ${name}`);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
async function detectProvider() {
|
|
792
|
+
if (process.env.ANTHROPIC_API_KEY) return "anthropic";
|
|
793
|
+
if (process.env.OPENAI_API_KEY) return "openai";
|
|
794
|
+
if (process.env.GEMINI_API_KEY) return "gemini";
|
|
795
|
+
if (process.env.OPENROUTER_API_KEY) return "openrouter";
|
|
796
|
+
if (process.env.AWS_ACCESS_KEY_ID || process.env.AWS_PROFILE) return "bedrock";
|
|
797
|
+
if (process.env.GOOGLE_APPLICATION_CREDENTIALS || process.env.GCLOUD_PROJECT) return "vertex";
|
|
798
|
+
if (process.env.OLLAMA_HOST) return "ollama";
|
|
799
|
+
try {
|
|
800
|
+
const host = process.env.OLLAMA_HOST ?? "http://localhost:11434";
|
|
801
|
+
const res = await fetch(`${host.replace(/\/+$/, "")}/api/tags`, {
|
|
802
|
+
signal: AbortSignal.timeout(500)
|
|
803
|
+
});
|
|
804
|
+
if (res.ok) return "ollama";
|
|
805
|
+
} catch {
|
|
806
|
+
}
|
|
807
|
+
return void 0;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
export {
|
|
811
|
+
AiSdkProvider,
|
|
812
|
+
DEFAULT_MODELS,
|
|
813
|
+
SUPPORTED_PROVIDERS,
|
|
814
|
+
resolveProvider,
|
|
815
|
+
detectProvider
|
|
816
|
+
};
|
|
817
|
+
//# sourceMappingURL=chunk-XZPAA5TO.js.map
|