@gedatou/cadenza-ai 0.7.1
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 +71 -0
- package/dist/anthropic-DdrANeO1.mjs +236 -0
- package/dist/bedrock-534H9yfk.mjs +75 -0
- package/dist/catalog-CvvS2JaW.mjs +32 -0
- package/dist/deepseek-C1b74T2F.mjs +55 -0
- package/dist/gemini-DcJ5Kr3h.mjs +229 -0
- package/dist/grok-CffQuBd6.mjs +77 -0
- package/dist/groq-Ba6TTYLp.mjs +98 -0
- package/dist/index.d.mts +1056 -0
- package/dist/index.mjs +2809 -0
- package/dist/llmgateway-Pt5CS6aQ.mjs +211 -0
- package/dist/mistral-BGMwwbU9.mjs +107 -0
- package/dist/mock/index.d.mts +168 -0
- package/dist/mock/index.mjs +467 -0
- package/dist/ollama-BBJs-3mK.mjs +80 -0
- package/dist/openai--FIeahIH.mjs +153 -0
- package/dist/openrouter-q-lx-2Cb.mjs +167 -0
- package/dist/preset-CEyIPxfS.mjs +157 -0
- package/dist/preset-DRT0T14q.d.mts +19 -0
- package/dist/providers/anthropic.d.mts +6 -0
- package/dist/providers/anthropic.mjs +11 -0
- package/dist/providers/bedrock.d.mts +6 -0
- package/dist/providers/bedrock.mjs +11 -0
- package/dist/providers/byteplus.d.mts +6 -0
- package/dist/providers/byteplus.mjs +21 -0
- package/dist/providers/deepseek.d.mts +35 -0
- package/dist/providers/deepseek.mjs +283 -0
- package/dist/providers/gemini.d.mts +6 -0
- package/dist/providers/gemini.mjs +11 -0
- package/dist/providers/grok.d.mts +6 -0
- package/dist/providers/grok.mjs +11 -0
- package/dist/providers/groq.d.mts +6 -0
- package/dist/providers/groq.mjs +11 -0
- package/dist/providers/llmgateway.d.mts +6 -0
- package/dist/providers/llmgateway.mjs +11 -0
- package/dist/providers/mistral.d.mts +6 -0
- package/dist/providers/mistral.mjs +11 -0
- package/dist/providers/ollama.d.mts +9 -0
- package/dist/providers/ollama.mjs +28 -0
- package/dist/providers/openai-compatible.d.mts +32 -0
- package/dist/providers/openai-compatible.mjs +45 -0
- package/dist/providers/openai.d.mts +6 -0
- package/dist/providers/openai.mjs +11 -0
- package/dist/providers/openrouter.d.mts +6 -0
- package/dist/providers/openrouter.mjs +11 -0
- package/dist/providers/vercel-gateway.d.mts +6 -0
- package/dist/providers/vercel-gateway.mjs +11 -0
- package/dist/providers/vertex.d.mts +6 -0
- package/dist/providers/vertex.mjs +11 -0
- package/dist/server/index.d.mts +173 -0
- package/dist/server/index.mjs +440 -0
- package/dist/thinking-CH2uL1dr.mjs +26 -0
- package/dist/types-56Hn7Qq2.d.mts +46 -0
- package/dist/vercel-gateway-DW3Z0Os1.mjs +109 -0
- package/dist/vertex-hg4Dt54O.mjs +20 -0
- package/package.json +114 -0
- package/styles.css +3 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { t as deepseek$1 } from "../deepseek-C1b74T2F.mjs";
|
|
2
|
+
import { i as deepseekResponsesThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { openaiCompatiblePreset } from "./openai-compatible.mjs";
|
|
4
|
+
import { EventType } from "@tanstack/ai";
|
|
5
|
+
import { OpenAICompatibleResponsesAdapter, openaiCompatibleText } from "@tanstack/ai-openai/compatible";
|
|
6
|
+
import { convertToolsToProviderFormat, webSearchTool } from "@tanstack/ai-openai/tools";
|
|
7
|
+
//#region src/providers/deepseek.ts
|
|
8
|
+
const BASE_URL = "https://api.deepseek.com";
|
|
9
|
+
/** What the built-in search reports as. `sourcesOf` keys on a provider-executed call whose name matches `/search/i`. */
|
|
10
|
+
const SEARCH_TOOL = "web_search";
|
|
11
|
+
/**
|
|
12
|
+
* A `web_search_call` output item wearing the `function_call` shape.
|
|
13
|
+
*
|
|
14
|
+
* The base adapter's stream handler only knows `function_call` items, so every
|
|
15
|
+
* other kind — DeepSeek's server-side searches included — is dropped: no events,
|
|
16
|
+
* no content, no trace. Dropping them is not merely lossy. The client's stream
|
|
17
|
+
* processor keeps one text buffer per *message* and only clears it on
|
|
18
|
+
* `TOOL_CALL_START`, while it starts a *new* text part whenever some other part
|
|
19
|
+
* type lands in between. DeepSeek's search auto-continues up to 10 rounds inside
|
|
20
|
+
* one response — reasoning, text, search, reasoning, text — so with the searches
|
|
21
|
+
* invisible the reasoning splits the parts while nothing resets the buffer, and
|
|
22
|
+
* every text block repeats all the earlier ones.
|
|
23
|
+
*
|
|
24
|
+
* Reporting the search as a tool call is therefore both the honest mapping and
|
|
25
|
+
* the fix: it is what `@ai-sdk/openai` does with the same wire items, it gives
|
|
26
|
+
* the run its segment boundaries back, and it puts the searches on screen.
|
|
27
|
+
*/
|
|
28
|
+
function asFunctionCall(event) {
|
|
29
|
+
const item = event.item;
|
|
30
|
+
if (item?.type !== "web_search_call" || item.id === void 0) return event;
|
|
31
|
+
return {
|
|
32
|
+
...event,
|
|
33
|
+
item: {
|
|
34
|
+
type: "function_call",
|
|
35
|
+
id: item.id,
|
|
36
|
+
call_id: item.id,
|
|
37
|
+
name: SEARCH_TOOL,
|
|
38
|
+
arguments: JSON.stringify(item.action ?? {})
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
async function* rewriteSearchCalls(stream) {
|
|
43
|
+
for await (const event of stream) {
|
|
44
|
+
const raw = event;
|
|
45
|
+
yield raw.type === "response.output_item.added" || raw.type === "response.output_item.done" ? asFunctionCall(raw) : raw;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function isAsyncIterable(value) {
|
|
49
|
+
return typeof value === "object" && value !== null && Symbol.asyncIterator in value;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The same client with `responses.create` teed through the rewrite — the base
|
|
53
|
+
* reaches for nothing else on it. `Object.create` rather than a spread: these are
|
|
54
|
+
* SDK class instances, so their methods live on the prototype.
|
|
55
|
+
*/
|
|
56
|
+
function withSearchCalls(client) {
|
|
57
|
+
const inner = client.responses;
|
|
58
|
+
const create = async (...args) => {
|
|
59
|
+
const result = await inner.create(...args);
|
|
60
|
+
return isAsyncIterable(result) ? rewriteSearchCalls(result) : result;
|
|
61
|
+
};
|
|
62
|
+
const responses = Object.create(inner, { create: { value: create } });
|
|
63
|
+
return Object.create(client, { responses: { value: responses } });
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The built-in searches in a history, keyed by the call id they were rewritten
|
|
67
|
+
* under, each already shaped back into the `web_search_call` DeepSeek issued.
|
|
68
|
+
*
|
|
69
|
+
* Both conditions have to hold — `metadata.providerExecuted` *and* the name.
|
|
70
|
+
* The metadata alone would restore any future provider-executed tool as a
|
|
71
|
+
* search; the name alone would catch a consumer's own function called
|
|
72
|
+
* `web_search`, which carries no such metadata. (`TranscriptParts` keys on the
|
|
73
|
+
* metadata alone, because there the question is only "did we run it".)
|
|
74
|
+
*/
|
|
75
|
+
function restorableSearches(messages) {
|
|
76
|
+
const searches = /* @__PURE__ */ new Map();
|
|
77
|
+
for (const message of messages) {
|
|
78
|
+
if (message.role !== "assistant") continue;
|
|
79
|
+
for (const toolCall of message.toolCalls ?? []) {
|
|
80
|
+
const metadata = toolCall.metadata;
|
|
81
|
+
if (metadata?.providerExecuted !== true || toolCall.function.name !== SEARCH_TOOL) continue;
|
|
82
|
+
const raw = toolCall.function.arguments;
|
|
83
|
+
let action;
|
|
84
|
+
try {
|
|
85
|
+
action = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
86
|
+
} catch {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (typeof action !== "object" || action === null) continue;
|
|
90
|
+
searches.set(toolCall.id, {
|
|
91
|
+
type: "web_search_call",
|
|
92
|
+
id: metadata.itemId ?? toolCall.id,
|
|
93
|
+
action,
|
|
94
|
+
status: "completed"
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return searches;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The compatible Responses adapter with one fix: its base converts *every* tool
|
|
102
|
+
* with `convertToolsToResponsesFormat`, which forces `{ type: 'function' }` and
|
|
103
|
+
* so degrades a provider tool into a schema-less function call nothing can
|
|
104
|
+
* execute. Routing through `convertToolsToProviderFormat` — which dispatches on
|
|
105
|
+
* the tool's private `metadata.__kind` — is exactly what `OpenAITextAdapter`
|
|
106
|
+
* does for the same reason, and is what lets `deepseekWebSearch()` reach the
|
|
107
|
+
* wire as `{ type: 'web_search' }`.
|
|
108
|
+
*
|
|
109
|
+
* Module-private: its declaration would need the openai SDK's types, which this
|
|
110
|
+
* package cannot name; `deepseek.create()` is the way to one.
|
|
111
|
+
*/
|
|
112
|
+
var DeepSeekResponsesAdapter = class extends OpenAICompatibleResponsesAdapter {
|
|
113
|
+
constructor(client, model) {
|
|
114
|
+
super(client, model, "deepseek");
|
|
115
|
+
let wrapped = withSearchCalls(client);
|
|
116
|
+
Object.defineProperty(this, "client", {
|
|
117
|
+
configurable: true,
|
|
118
|
+
get: () => wrapped,
|
|
119
|
+
set: (next) => {
|
|
120
|
+
wrapped = withSearchCalls(next);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Mark the rewritten search calls provider-executed. Without it the agent loop
|
|
126
|
+
* would count them as pending client work forever (`isProviderExecutedToolCall`
|
|
127
|
+
* gates that in `@tanstack/ai`), and the tool card would spin: the processor
|
|
128
|
+
* treats a provider-executed call as already complete.
|
|
129
|
+
*/
|
|
130
|
+
async *chatStream(options) {
|
|
131
|
+
const searches = /* @__PURE__ */ new Set();
|
|
132
|
+
for await (const chunk of super.chatStream(options)) {
|
|
133
|
+
const event = chunk;
|
|
134
|
+
if (event.type === EventType.TOOL_CALL_START && event.toolName === SEARCH_TOOL && event.toolCallId !== void 0) {
|
|
135
|
+
searches.add(event.toolCallId);
|
|
136
|
+
yield {
|
|
137
|
+
...chunk,
|
|
138
|
+
metadata: {
|
|
139
|
+
...event.metadata,
|
|
140
|
+
providerExecuted: true
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
yield chunk;
|
|
146
|
+
if (event.type !== EventType.TOOL_CALL_END || event.toolCallId === void 0 || !searches.delete(event.toolCallId)) continue;
|
|
147
|
+
yield {
|
|
148
|
+
type: EventType.TOOL_CALL_RESULT,
|
|
149
|
+
toolCallId: event.toolCallId,
|
|
150
|
+
toolCallName: SEARCH_TOOL,
|
|
151
|
+
messageId: `${event.toolCallId}-result`,
|
|
152
|
+
role: "tool",
|
|
153
|
+
content: JSON.stringify(event.input ?? {}),
|
|
154
|
+
timestamp: Date.now()
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Rebuild one assistant turn the way DeepSeek wants to read it back.
|
|
160
|
+
*
|
|
161
|
+
* Two things have to be true at once, both measured against the live API on
|
|
162
|
+
* 2026-08-30 rather than reasoned about:
|
|
163
|
+
*
|
|
164
|
+
* 1. **Every `function_call` must sit next to its `function_call_output`.**
|
|
165
|
+
* The base emits an assistant message as `[...function_call, message]`
|
|
166
|
+
* while the outputs arrive as the *next* messages, so a turn that called a
|
|
167
|
+
* tool and then answered replays as `function_call → message →
|
|
168
|
+
* function_call_output`. DeepSeek documents `function_call` as "merged into
|
|
169
|
+
* the adjacent assistant message": the call is folded into the message
|
|
170
|
+
* behind it, that turn closes, and the output left over pairs with nothing
|
|
171
|
+
* — `400 No tool output found for tool call <call_id>` on the user's next
|
|
172
|
+
* question, every time the previous one used a tool. A `web_search_call`
|
|
173
|
+
* between the two breaks it in exactly the same way.
|
|
174
|
+
* 2. **A built-in search must go back as the `web_search_call` it was.** We
|
|
175
|
+
* rewrite those items into `function_call`s on the way in, because that is
|
|
176
|
+
* the only signal that keeps the client's text segments apart (see
|
|
177
|
+
* `asFunctionCall`) — but the rewrite must not reach the wire. DeepSeek
|
|
178
|
+
* "automatically restores the search results" for a `web_search_call`
|
|
179
|
+
* passed back as-is; hand it the rewritten `function_call` instead and the
|
|
180
|
+
* results are gone, so the model searches again on every follow-up.
|
|
181
|
+
*
|
|
182
|
+
* Hence the order `[assistant message, calls, outputs, searches]`. The search
|
|
183
|
+
* items carry no output of their own, so their own `function_call_output` is
|
|
184
|
+
* dropped. A search whose action no longer parses simply stays a plain
|
|
185
|
+
* function call: accepted too, only costing the re-search.
|
|
186
|
+
*/
|
|
187
|
+
convertMessagesToInput(messages) {
|
|
188
|
+
const searches = restorableSearches(messages);
|
|
189
|
+
const input = super.convertMessagesToInput(messages);
|
|
190
|
+
const output = [];
|
|
191
|
+
for (let i = 0; i < input.length;) {
|
|
192
|
+
if (input[i].type !== "function_call") {
|
|
193
|
+
output.push(input[i]);
|
|
194
|
+
i += 1;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const calls = [];
|
|
198
|
+
const restored = [];
|
|
199
|
+
let end = i;
|
|
200
|
+
while (end < input.length && input[end].type === "function_call") {
|
|
201
|
+
const search = searches.get(String(input[end].call_id));
|
|
202
|
+
if (search === void 0) calls.push(input[end]);
|
|
203
|
+
else restored.push(search);
|
|
204
|
+
end += 1;
|
|
205
|
+
}
|
|
206
|
+
const next = input[end];
|
|
207
|
+
const message = next?.type === "message" && next.role === "assistant" ? next : void 0;
|
|
208
|
+
if (message !== void 0) end += 1;
|
|
209
|
+
const outputs = [];
|
|
210
|
+
while (end < input.length && input[end].type === "function_call_output") {
|
|
211
|
+
if (!searches.has(String(input[end].call_id))) outputs.push(input[end]);
|
|
212
|
+
end += 1;
|
|
213
|
+
}
|
|
214
|
+
if (message !== void 0) output.push(message);
|
|
215
|
+
output.push(...calls, ...outputs, ...restored);
|
|
216
|
+
i = end;
|
|
217
|
+
}
|
|
218
|
+
return output;
|
|
219
|
+
}
|
|
220
|
+
mapOptionsToRequest(options) {
|
|
221
|
+
const { tools: _dropped, ...request } = super.mapOptionsToRequest({
|
|
222
|
+
...options,
|
|
223
|
+
tools: void 0
|
|
224
|
+
});
|
|
225
|
+
const tools = options.tools ? convertToolsToProviderFormat(options.tools) : void 0;
|
|
226
|
+
return tools !== void 0 && tools.length > 0 ? {
|
|
227
|
+
...request,
|
|
228
|
+
tools
|
|
229
|
+
} : request;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
/**
|
|
233
|
+
* DeepSeek's server-side web search: the model searches, opens and reads pages
|
|
234
|
+
* itself (auto-continuing up to 10 rounds) before answering, and nothing is
|
|
235
|
+
* executed on our side. Only the Responses endpoint has it — Chat Completions
|
|
236
|
+
* still documents `function` as the one tool type.
|
|
237
|
+
*
|
|
238
|
+
* The wire shape is OpenAI's, so this is that factory; DeepSeek ignores the
|
|
239
|
+
* extra `search_context_size` / `user_location` fields it can carry.
|
|
240
|
+
*
|
|
241
|
+
* Hand it to `createChatHandler` through the *function* form of `tools`, so it
|
|
242
|
+
* only ever reaches DeepSeek:
|
|
243
|
+
*
|
|
244
|
+
* ```ts
|
|
245
|
+
* tools: sel => sel.preset.id === 'deepseek' ? [deepseekWebSearch()] : []
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
function deepseekWebSearch() {
|
|
249
|
+
return webSearchTool({ type: "web_search" });
|
|
250
|
+
}
|
|
251
|
+
const compatible = openaiCompatiblePreset({
|
|
252
|
+
id: deepseek$1.id,
|
|
253
|
+
label: deepseek$1.label,
|
|
254
|
+
baseURL: BASE_URL,
|
|
255
|
+
env: "DEEPSEEK_API_KEY",
|
|
256
|
+
models: deepseek$1.models,
|
|
257
|
+
api: "responses",
|
|
258
|
+
thinking: deepseekResponsesThinking
|
|
259
|
+
});
|
|
260
|
+
/**
|
|
261
|
+
* DeepSeek speaks three protocols under one host and they are not equal: only
|
|
262
|
+
* `/responses` carries the built-in `web_search` tool, and only there does
|
|
263
|
+
* thinking arrive as the standard `response.reasoning_text.delta` (which the
|
|
264
|
+
* base adapter already parses) instead of Chat Completions'
|
|
265
|
+
* `delta.reasoning_content` (which it ignores, and which forced a hand-written
|
|
266
|
+
* subclass plus `reasoning_content` echo on every assistant turn). So the
|
|
267
|
+
* preset is the compatible one over `/responses`, with the adapter swapped for
|
|
268
|
+
* the tool-converter fix above. The `openai` client is borrowed from the
|
|
269
|
+
* compatible factory: this package cannot resolve the SDK itself.
|
|
270
|
+
*/
|
|
271
|
+
const deepseek = definePreset({
|
|
272
|
+
...compatible,
|
|
273
|
+
create: (model, key) => {
|
|
274
|
+
return new DeepSeekResponsesAdapter(openaiCompatibleText(model, {
|
|
275
|
+
baseURL: BASE_URL,
|
|
276
|
+
apiKey: key ?? "",
|
|
277
|
+
name: "deepseek",
|
|
278
|
+
api: "responses"
|
|
279
|
+
}).client, model);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
//#endregion
|
|
283
|
+
export { deepseek, deepseekWebSearch };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as gemini$1 } from "../gemini-DcJ5Kr3h.mjs";
|
|
2
|
+
import { o as geminiThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createGeminiChat } from "@tanstack/ai-gemini";
|
|
4
|
+
//#region src/providers/gemini.ts
|
|
5
|
+
const gemini = definePreset({
|
|
6
|
+
...gemini$1,
|
|
7
|
+
create: (model, key) => createGeminiChat(model, key ?? ""),
|
|
8
|
+
thinking: geminiThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { gemini };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as grok$1 } from "../grok-CffQuBd6.mjs";
|
|
2
|
+
import { s as grokThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createGrokText } from "@tanstack/ai-grok";
|
|
4
|
+
//#region src/providers/grok.ts
|
|
5
|
+
const grok = definePreset({
|
|
6
|
+
...grok$1,
|
|
7
|
+
create: (model, key) => createGrokText(model, key ?? ""),
|
|
8
|
+
thinking: grokThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { grok };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as groq$1 } from "../groq-Ba6TTYLp.mjs";
|
|
2
|
+
import { c as groqThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createGroqText } from "@tanstack/ai-groq";
|
|
4
|
+
//#region src/providers/groq.ts
|
|
5
|
+
const groq = definePreset({
|
|
6
|
+
...groq$1,
|
|
7
|
+
create: (model, key) => createGroqText(model, key ?? ""),
|
|
8
|
+
thinking: groqThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { groq };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as llmgateway$1 } from "../llmgateway-Pt5CS6aQ.mjs";
|
|
2
|
+
import { l as llmgatewayThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createLLMGatewayText } from "@tanstack/ai-llmgateway";
|
|
4
|
+
//#region src/providers/llmgateway.ts
|
|
5
|
+
const llmgateway = definePreset({
|
|
6
|
+
...llmgateway$1,
|
|
7
|
+
create: (model, key) => createLLMGatewayText(model, key ?? ""),
|
|
8
|
+
thinking: llmgatewayThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { llmgateway };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as mistral$1 } from "../mistral-BGMwwbU9.mjs";
|
|
2
|
+
import { t as definePreset, u as noThinking } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createMistralText } from "@tanstack/ai-mistral";
|
|
4
|
+
//#region src/providers/mistral.ts
|
|
5
|
+
const mistral = definePreset({
|
|
6
|
+
...mistral$1,
|
|
7
|
+
create: (model, key) => createMistralText(model, key ?? ""),
|
|
8
|
+
thinking: noThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { mistral };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { r as Model } from "../types-56Hn7Qq2.mjs";
|
|
2
|
+
import { t as ProviderPreset } from "../preset-DRT0T14q.mjs";
|
|
3
|
+
import "../server/index.mjs";
|
|
4
|
+
//#region src/providers/ollama.d.ts
|
|
5
|
+
/** `GET {host}/api/tags` → one `Model` per installed tag; catalog metadata wins when the tag is known. */
|
|
6
|
+
declare function discoverOllamaModels(host: string): Promise<Model[]>;
|
|
7
|
+
declare const ollama: ProviderPreset;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { discoverOllamaModels, ollama };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { t as ollama$1 } from "../ollama-BBJs-3mK.mjs";
|
|
2
|
+
import { d as ollamaThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createOllamaChat, ollamaText } from "@tanstack/ai-ollama";
|
|
4
|
+
//#region src/providers/ollama.ts
|
|
5
|
+
function defaultHost() {
|
|
6
|
+
const host = process.env.OLLAMA_HOST;
|
|
7
|
+
return host !== void 0 && host !== "" ? host : "http://localhost:11434";
|
|
8
|
+
}
|
|
9
|
+
/** `GET {host}/api/tags` → one `Model` per installed tag; catalog metadata wins when the tag is known. */
|
|
10
|
+
async function discoverOllamaModels(host) {
|
|
11
|
+
const res = await fetch(`${host.replace(/\/$/, "")}/api/tags`);
|
|
12
|
+
if (!res.ok) throw new Error(`Ollama ${host} answered ${res.status}`);
|
|
13
|
+
return ((await res.json()).models ?? []).map(({ name }) => ollama$1.models.find((m) => m.id === name) ?? {
|
|
14
|
+
id: name,
|
|
15
|
+
name,
|
|
16
|
+
provider: "ollama",
|
|
17
|
+
input: ["text"],
|
|
18
|
+
reasoning: false
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
const ollama = definePreset({
|
|
22
|
+
...ollama$1,
|
|
23
|
+
create: (model, key) => key !== null ? createOllamaChat(model, key) : ollamaText(model),
|
|
24
|
+
thinking: ollamaThinking,
|
|
25
|
+
discoverModels: (key) => discoverOllamaModels(key ?? defaultHost())
|
|
26
|
+
});
|
|
27
|
+
//#endregion
|
|
28
|
+
export { discoverOllamaModels, ollama };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { r as Model } from "../types-56Hn7Qq2.mjs";
|
|
2
|
+
import { t as ProviderPreset } from "../preset-DRT0T14q.mjs";
|
|
3
|
+
import { CompatibleApi } from "@tanstack/ai-openai/compatible";
|
|
4
|
+
//#region src/providers/openai-compatible.d.ts
|
|
5
|
+
interface OpenAICompatibleConfig {
|
|
6
|
+
/** BYOK slug (`x-byok-<id>`), `/^[a-z][a-z0-9-]{0,63}$/`. */
|
|
7
|
+
id: string;
|
|
8
|
+
label: string;
|
|
9
|
+
baseURL: string;
|
|
10
|
+
/** Env names `getByokKey` may fall back to, in order. */
|
|
11
|
+
env?: string | readonly string[];
|
|
12
|
+
models: readonly Model[];
|
|
13
|
+
/**
|
|
14
|
+
* Which OpenAI protocol the endpoint speaks. Default `'chat-completions'`
|
|
15
|
+
* (`{baseURL}/chat/completions`); `'responses'` targets `{baseURL}/responses`,
|
|
16
|
+
* which a few compatible vendors implement — and where their built-in tools
|
|
17
|
+
* (DeepSeek's `web_search`) and native reasoning events live.
|
|
18
|
+
*/
|
|
19
|
+
api?: CompatibleApi;
|
|
20
|
+
/** Defaults to `openaiCompatibleThinking` (`reasoning_effort` for reasoning models). */
|
|
21
|
+
thinking?: ProviderPreset['thinking'];
|
|
22
|
+
/** Adapter name shown in TanStack AI's events / debug output; defaults to `id`. */
|
|
23
|
+
name?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The one entry point for a consumer-defined provider: any endpoint speaking the
|
|
27
|
+
* OpenAI Chat Completions / Responses protocol. The catalog half (`Provider`)
|
|
28
|
+
* is the same object minus `create` / `thinking`, so hand it to `withProvider` too.
|
|
29
|
+
*/
|
|
30
|
+
declare function openaiCompatiblePreset(config: OpenAICompatibleConfig): ProviderPreset;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { OpenAICompatibleConfig, openaiCompatiblePreset };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { f as openaiCompatibleThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
2
|
+
import { defineByokProvider } from "@tanstack/ai/byok";
|
|
3
|
+
import { openaiCompatibleText } from "@tanstack/ai-openai/compatible";
|
|
4
|
+
//#region src/providers/openai-compatible.ts
|
|
5
|
+
/** `GET {baseURL}/models` (Bearer key) → `data[].id`; catalog metadata wins when the id is known. */
|
|
6
|
+
async function discoverCompatibleModels(config, key) {
|
|
7
|
+
const res = await fetch(`${config.baseURL.replace(/\/$/, "")}/models`, { headers: key !== null ? { authorization: `Bearer ${key}` } : {} });
|
|
8
|
+
if (!res.ok) throw new Error(`${config.label} answered ${res.status}`);
|
|
9
|
+
return ((await res.json()).data ?? []).map(({ id }) => config.models.find((m) => m.id === id) ?? {
|
|
10
|
+
id,
|
|
11
|
+
name: id,
|
|
12
|
+
provider: config.id,
|
|
13
|
+
input: ["text"],
|
|
14
|
+
reasoning: false
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The one entry point for a consumer-defined provider: any endpoint speaking the
|
|
19
|
+
* OpenAI Chat Completions / Responses protocol. The catalog half (`Provider`)
|
|
20
|
+
* is the same object minus `create` / `thinking`, so hand it to `withProvider` too.
|
|
21
|
+
*/
|
|
22
|
+
function openaiCompatiblePreset(config) {
|
|
23
|
+
return definePreset({
|
|
24
|
+
id: config.id,
|
|
25
|
+
label: config.label,
|
|
26
|
+
byok: defineByokProvider({
|
|
27
|
+
id: config.id,
|
|
28
|
+
label: config.label,
|
|
29
|
+
env: config.env
|
|
30
|
+
}),
|
|
31
|
+
keyRequired: true,
|
|
32
|
+
runtime: "node",
|
|
33
|
+
models: config.models,
|
|
34
|
+
create: (model, key) => openaiCompatibleText(model, {
|
|
35
|
+
baseURL: config.baseURL,
|
|
36
|
+
apiKey: key ?? "",
|
|
37
|
+
name: config.name ?? config.id,
|
|
38
|
+
api: config.api
|
|
39
|
+
}),
|
|
40
|
+
thinking: config.thinking ?? openaiCompatibleThinking,
|
|
41
|
+
discoverModels: (key) => discoverCompatibleModels(config, key)
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { openaiCompatiblePreset };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as openai$1 } from "../openai--FIeahIH.mjs";
|
|
2
|
+
import { p as openaiThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createOpenaiChat } from "@tanstack/ai-openai";
|
|
4
|
+
//#region src/providers/openai.ts
|
|
5
|
+
const openai = definePreset({
|
|
6
|
+
...openai$1,
|
|
7
|
+
create: (model, key) => createOpenaiChat(model, key ?? ""),
|
|
8
|
+
thinking: openaiThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { openai };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as openrouter$1 } from "../openrouter-q-lx-2Cb.mjs";
|
|
2
|
+
import { m as openrouterThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createOpenRouterText } from "@tanstack/ai-openrouter";
|
|
4
|
+
//#region src/providers/openrouter.ts
|
|
5
|
+
const openrouter = definePreset({
|
|
6
|
+
...openrouter$1,
|
|
7
|
+
create: (model, key) => createOpenRouterText(model, key ?? ""),
|
|
8
|
+
thinking: openrouterThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { openrouter };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as vercelGateway$1 } from "../vercel-gateway-DW3Z0Os1.mjs";
|
|
2
|
+
import { g as vercelGatewayThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { createVercelGatewayText } from "@tanstack/ai-vercel-gateway";
|
|
4
|
+
//#region src/providers/vercel-gateway.ts
|
|
5
|
+
const vercelGateway = definePreset({
|
|
6
|
+
...vercelGateway$1,
|
|
7
|
+
create: (model, key) => createVercelGatewayText(model, key ?? "", { api: "chat" }),
|
|
8
|
+
thinking: vercelGatewayThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { vercelGateway };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as vertex$1 } from "../vertex-hg4Dt54O.mjs";
|
|
2
|
+
import { o as geminiThinking, t as definePreset } from "../preset-CEyIPxfS.mjs";
|
|
3
|
+
import { vertexText } from "@tanstack/ai-vertex";
|
|
4
|
+
//#region src/providers/vertex.ts
|
|
5
|
+
const vertex = definePreset({
|
|
6
|
+
...vertex$1,
|
|
7
|
+
create: (model, key) => vertexText(model, key !== null ? { apiKey: key } : void 0),
|
|
8
|
+
thinking: geminiThinking
|
|
9
|
+
});
|
|
10
|
+
//#endregion
|
|
11
|
+
export { vertex };
|