ai-sdk-ollama 0.2.0 โ 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -1
- package/README.md +102 -3
- package/dist/index.cjs +114 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +114 -25
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- **Reasoning Support**: Added support for reasoning (chain-of-thought) output
|
|
8
|
+
- ๐ง **Reasoning Content**: Models that support reasoning can now output their thinking process
|
|
9
|
+
- ๐ **Content Types**: Support for `LanguageModelV2Reasoning` content type in both non-streaming and streaming responses
|
|
10
|
+
- ๐ **Streaming Support**: Full streaming support with `reasoning-start`, `reasoning-delta`, and `reasoning-end` events
|
|
11
|
+
- โ๏ธ **Configurable**: Enable reasoning with `{ reasoning: true }` setting
|
|
12
|
+
- ๐งช **Comprehensive Testing**: Added unit tests for reasoning functionality
|
|
13
|
+
- ๐ **Documentation**: Updated README and examples with reasoning usage
|
|
14
|
+
- ๐ฏ **Backward Compatible**: Reasoning is disabled by default, existing code continues to work
|
|
15
|
+
|
|
16
|
+
### Technical Improvements
|
|
17
|
+
|
|
18
|
+
- Added `reasoning` setting to `OllamaChatSettings` interface
|
|
19
|
+
- Enhanced `doGenerate` method to handle `thinking` field from Ollama responses
|
|
20
|
+
- Enhanced `doStream` method to emit reasoning stream parts
|
|
21
|
+
- Added reasoning support to content conversion logic
|
|
22
|
+
- Updated type definitions to include reasoning content types
|
|
23
|
+
|
|
24
|
+
## 0.3.0
|
|
25
|
+
|
|
26
|
+
### Minor Changes
|
|
27
|
+
|
|
28
|
+
- **Auto-Structured Outputs**: Enhanced structured outputs with intelligent auto-detection
|
|
29
|
+
- ๐ฏ **Smart Auto-Detection**: Automatically enables structured outputs when JSON schema is provided
|
|
30
|
+
- ๐ง **Backward Compatibility**: Explicit `structuredOutputs: true/false` settings are still respected
|
|
31
|
+
- โ ๏ธ **User-Friendly Warnings**: Clear warnings when auto-enabling structured outputs
|
|
32
|
+
- ๐ **Enhanced Documentation**: Updated examples and README with auto-detection guidance
|
|
33
|
+
- ๐งช **Comprehensive Testing**: Added integration tests for auto-detection scenarios
|
|
34
|
+
- ๐ ๏ธ **Improved Developer Experience**: No need to manually set `structuredOutputs: true` for object generation
|
|
35
|
+
|
|
36
|
+
### Technical Improvements
|
|
37
|
+
|
|
38
|
+
- Enhanced `shouldEnableStructuredOutputs()` method for intelligent auto-detection
|
|
39
|
+
- Improved schema validation and error handling
|
|
40
|
+
- Updated README with auto-detection examples and best practices
|
|
41
|
+
- Added comprehensive integration tests for edge cases
|
|
42
|
+
- Streamlined configuration for common use cases
|
|
43
|
+
|
|
3
44
|
## 0.2.0
|
|
4
45
|
|
|
5
46
|
### Minor Changes
|
|
@@ -79,7 +120,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
79
120
|
|
|
80
121
|
### Supported Models
|
|
81
122
|
|
|
82
|
-
- **Chat Models**: llama3.2,
|
|
123
|
+
- **Chat Models**: llama3.2, mistral, phi4-mini, qwen2.5, codellama, and all Ollama chat models
|
|
83
124
|
- **Vision Models**: llava, bakllava, llama3.2-vision, minicpm-v
|
|
84
125
|
- **Embedding Models**: nomic-embed-text, all-minilm, mxbai-embed-large, and all Ollama embedding models
|
|
85
126
|
|
package/README.md
CHANGED
|
@@ -19,12 +19,14 @@ A Vercel AI SDK v5+ provider for Ollama built on the official `ollama` package.
|
|
|
19
19
|
- [Cross Provider Compatibility](#cross-provider-compatibility)
|
|
20
20
|
- [Native Ollama Power](#native-ollama-power)
|
|
21
21
|
- [Tool Calling Support](#tool-calling-support)
|
|
22
|
-
- [
|
|
22
|
+
- [Simple and Predictable](#simple-and-predictable)
|
|
23
23
|
- [Advanced Features](#advanced-features)
|
|
24
24
|
- [Custom Ollama Instance](#custom-ollama-instance)
|
|
25
25
|
- [Structured Output](#structured-output)
|
|
26
|
+
- [Auto-Detection of Structured Outputs](#auto-detection-of-structured-outputs)
|
|
26
27
|
- [Common Issues](#common-issues)
|
|
27
28
|
- [Supported Models](#supported-models)
|
|
29
|
+
- [Testing](#testing)
|
|
28
30
|
- [Learn More](#learn-more)
|
|
29
31
|
- [License](#license)
|
|
30
32
|
|
|
@@ -223,8 +225,9 @@ const { text } = await generateText({
|
|
|
223
225
|
import { generateObject } from 'ai';
|
|
224
226
|
import { z } from 'zod';
|
|
225
227
|
|
|
228
|
+
// Auto-detection: structuredOutputs is automatically enabled for object generation
|
|
226
229
|
const { object } = await generateObject({
|
|
227
|
-
model: ollama('llama3.2',
|
|
230
|
+
model: ollama('llama3.2'), // No need to set structuredOutputs: true
|
|
228
231
|
schema: z.object({
|
|
229
232
|
name: z.string(),
|
|
230
233
|
age: z.number(),
|
|
@@ -235,8 +238,84 @@ const { object } = await generateObject({
|
|
|
235
238
|
|
|
236
239
|
console.log(object);
|
|
237
240
|
// { name: "Alice", age: 28, interests: ["reading", "hiking"] }
|
|
241
|
+
|
|
242
|
+
// Explicit setting still works
|
|
243
|
+
const { object: explicitObject } = await generateObject({
|
|
244
|
+
model: ollama('llama3.2', { structuredOutputs: true }), // Explicit
|
|
245
|
+
schema: z.object({
|
|
246
|
+
name: z.string(),
|
|
247
|
+
age: z.number(),
|
|
248
|
+
}),
|
|
249
|
+
prompt: 'Generate a person',
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Auto-Detection of Structured Outputs
|
|
254
|
+
|
|
255
|
+
The provider automatically detects when structured outputs are needed:
|
|
256
|
+
|
|
257
|
+
- **Object Generation**: `generateObject` and `streamObject` automatically enable `structuredOutputs: true`
|
|
258
|
+
- **Text Generation**: `generateText` and `streamText` require explicit `structuredOutputs: true` for JSON output
|
|
259
|
+
- **Backward Compatibility**: Explicit settings are respected, with warnings when overridden
|
|
260
|
+
- **No Breaking Changes**: Existing code continues to work as expected
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// This works without explicit structuredOutputs: true
|
|
264
|
+
const { object } = await generateObject({
|
|
265
|
+
model: ollama('llama3.2'),
|
|
266
|
+
schema: z.object({ name: z.string() }),
|
|
267
|
+
prompt: 'Generate a name',
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// This still requires explicit setting for JSON output
|
|
271
|
+
const { text } = await generateText({
|
|
272
|
+
model: ollama('llama3.2', { structuredOutputs: true }),
|
|
273
|
+
prompt: 'Generate JSON with a message field',
|
|
274
|
+
});
|
|
238
275
|
```
|
|
239
276
|
|
|
277
|
+
### Reasoning Support
|
|
278
|
+
|
|
279
|
+
Some models like DeepSeek-R1 support reasoning (chain-of-thought) output. Enable this feature to see the model's thinking process:
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
// Enable reasoning for models that support it (e.g., deepseek-r1:7b)
|
|
283
|
+
const model = ollama('deepseek-r1:7b', { reasoning: true });
|
|
284
|
+
|
|
285
|
+
// Generate text with reasoning
|
|
286
|
+
const { text } = await generateText({
|
|
287
|
+
model,
|
|
288
|
+
prompt:
|
|
289
|
+
'Solve: If I have 3 boxes, each with 4 smaller boxes, and each smaller box has 5 items, how many items total?',
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
console.log('Answer:', text);
|
|
293
|
+
// DeepSeek-R1 includes reasoning in the output with <think> tags:
|
|
294
|
+
// <think>
|
|
295
|
+
// First, I'll calculate the number of smaller boxes: 3 ร 4 = 12
|
|
296
|
+
// Then, the total items: 12 ร 5 = 60
|
|
297
|
+
// </think>
|
|
298
|
+
// You have 60 items in total.
|
|
299
|
+
|
|
300
|
+
// Compare with reasoning disabled
|
|
301
|
+
const modelNoReasoning = ollama('deepseek-r1:7b', { reasoning: false });
|
|
302
|
+
const { text: noReasoningText } = await generateText({
|
|
303
|
+
model: modelNoReasoning,
|
|
304
|
+
prompt: 'Calculate 3 ร 4 ร 5',
|
|
305
|
+
});
|
|
306
|
+
// Output: 60 (without showing the thinking process)
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
**Recommended Reasoning Models**:
|
|
310
|
+
|
|
311
|
+
- `deepseek-r1:7b` - Balanced performance and reasoning capability (5GB)
|
|
312
|
+
- `deepseek-r1:1.5b` - Lightweight option (2.5GB)
|
|
313
|
+
- `deepseek-r1:8b` - Llama-based distilled version (5.5GB)
|
|
314
|
+
|
|
315
|
+
Install with: `ollama pull deepseek-r1:7b`
|
|
316
|
+
|
|
317
|
+
**Note**: The reasoning feature is model-dependent. Models without reasoning support will work normally without showing thinking process.
|
|
318
|
+
|
|
240
319
|
## Common Issues
|
|
241
320
|
|
|
242
321
|
- **Make sure Ollama is running** - Run `ollama serve` before using the provider
|
|
@@ -250,9 +329,29 @@ console.log(object);
|
|
|
250
329
|
|
|
251
330
|
Works with any model in your Ollama installation:
|
|
252
331
|
|
|
253
|
-
- **Chat**: `llama3.2`, `
|
|
332
|
+
- **Chat**: `llama3.2`, `mistral`, `phi4-mini`, `qwen2.5`, `codellama`
|
|
254
333
|
- **Vision**: `llava`, `bakllava`, `llama3.2-vision`, `minicpm-v`
|
|
255
334
|
- **Embeddings**: `nomic-embed-text`, `all-minilm`, `mxbai-embed-large`
|
|
335
|
+
- **Reasoning**: `deepseek-r1:7b`, `deepseek-r1:1.5b`, `deepseek-r1:8b`
|
|
336
|
+
|
|
337
|
+
## Testing
|
|
338
|
+
|
|
339
|
+
The project includes unit and integration tests:
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
# Run unit tests only (fast, no external dependencies)
|
|
343
|
+
npm test
|
|
344
|
+
|
|
345
|
+
# Run all tests (unit + integration)
|
|
346
|
+
npm run test:all
|
|
347
|
+
|
|
348
|
+
# Run integration tests only (requires Ollama running)
|
|
349
|
+
npm run test:integration
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
> **Note**: Integration tests may occasionally fail due to the non-deterministic nature of AI model outputs. This is expected behavior - the tests use loose assertions to account for LLM output variability. Some tests may also skip if required models aren't available locally.
|
|
353
|
+
|
|
354
|
+
For detailed testing information, see [Integration Tests Documentation](./src/integration-tests/README.md).
|
|
256
355
|
|
|
257
356
|
## Learn More
|
|
258
357
|
|
package/dist/index.cjs
CHANGED
|
@@ -54,27 +54,43 @@ function convertToOllamaChatMessages(prompt) {
|
|
|
54
54
|
const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
55
55
|
const imageParts = message.content.filter(
|
|
56
56
|
(part) => part.type === "file"
|
|
57
|
-
).filter((part) =>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
).filter((part) => {
|
|
58
|
+
return part.mediaType?.startsWith("image/") || false;
|
|
59
|
+
}).map((part) => {
|
|
60
|
+
const imageData = part.data;
|
|
61
|
+
if (imageData instanceof URL) {
|
|
62
|
+
if (imageData.protocol === "data:") {
|
|
63
|
+
const base64Match = imageData.href.match(
|
|
64
|
+
/data:[^;]+;base64,(.+)/
|
|
65
|
+
);
|
|
63
66
|
if (base64Match) {
|
|
64
67
|
return base64Match[1];
|
|
65
68
|
}
|
|
69
|
+
return imageData.href;
|
|
66
70
|
}
|
|
67
|
-
return
|
|
68
|
-
} else if (
|
|
69
|
-
|
|
71
|
+
return imageData.href;
|
|
72
|
+
} else if (typeof imageData === "string") {
|
|
73
|
+
if (imageData.startsWith("data:")) {
|
|
74
|
+
const base64Match = imageData.match(/data:[^;]+;base64,(.+)/);
|
|
75
|
+
if (base64Match) {
|
|
76
|
+
return base64Match[1];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return imageData;
|
|
80
|
+
} else if (imageData instanceof Uint8Array) {
|
|
81
|
+
return Buffer.from(imageData).toString("base64");
|
|
70
82
|
} else {
|
|
71
|
-
|
|
83
|
+
console.warn(
|
|
84
|
+
`Unsupported image data type: ${typeof imageData}`
|
|
85
|
+
);
|
|
86
|
+
return null;
|
|
72
87
|
}
|
|
73
|
-
});
|
|
88
|
+
}).filter((img) => img !== null);
|
|
74
89
|
messages.push({
|
|
75
90
|
role: "user",
|
|
76
|
-
content: textParts,
|
|
77
|
-
|
|
91
|
+
content: textParts || "",
|
|
92
|
+
// Ensure content is never undefined
|
|
93
|
+
images: imageParts.length > 0 ? imageParts : void 0
|
|
78
94
|
});
|
|
79
95
|
}
|
|
80
96
|
break;
|
|
@@ -84,7 +100,9 @@ function convertToOllamaChatMessages(prompt) {
|
|
|
84
100
|
if (typeof message.content === "string") {
|
|
85
101
|
content = message.content;
|
|
86
102
|
} else {
|
|
87
|
-
|
|
103
|
+
const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("");
|
|
104
|
+
const reasoningParts = message.content.filter((part) => part.type === "reasoning").map((part) => part.text).join("\n");
|
|
105
|
+
content = [textParts, reasoningParts].filter(Boolean).join("\n");
|
|
88
106
|
const toolCalls = message.content.filter(
|
|
89
107
|
(part) => part.type === "tool-call"
|
|
90
108
|
);
|
|
@@ -98,20 +116,38 @@ ${toolCallText}` : toolCallText;
|
|
|
98
116
|
}
|
|
99
117
|
messages.push({
|
|
100
118
|
role: "assistant",
|
|
101
|
-
content
|
|
119
|
+
content: content || ""
|
|
120
|
+
// Ensure content is never undefined
|
|
102
121
|
});
|
|
103
122
|
break;
|
|
104
123
|
}
|
|
105
124
|
case "tool": {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
125
|
+
if (typeof message.content === "string") {
|
|
126
|
+
messages.push({
|
|
127
|
+
role: "user",
|
|
128
|
+
// Ollama doesn't have native tool role, so we use user
|
|
129
|
+
content: `[Tool Result]: ${message.content}`
|
|
130
|
+
});
|
|
131
|
+
} else {
|
|
132
|
+
const toolResultParts = message.content.filter((part) => part.type === "tool-result").map((part) => {
|
|
133
|
+
if (part.output.type === "text") {
|
|
134
|
+
return part.output.value;
|
|
135
|
+
} else if (part.output.type === "json") {
|
|
136
|
+
return JSON.stringify(part.output.value);
|
|
137
|
+
}
|
|
138
|
+
return String(part.output.value);
|
|
139
|
+
}).join("\n");
|
|
140
|
+
messages.push({
|
|
141
|
+
role: "user",
|
|
142
|
+
content: `[Tool Result]: ${toolResultParts || ""}`
|
|
143
|
+
});
|
|
144
|
+
}
|
|
110
145
|
break;
|
|
111
146
|
}
|
|
112
147
|
default: {
|
|
148
|
+
const role = message.role;
|
|
113
149
|
throw new Error(
|
|
114
|
-
`Unsupported message role: ${
|
|
150
|
+
`Unsupported message role: ${role}. Supported roles are: system, user, assistant, tool`
|
|
115
151
|
);
|
|
116
152
|
}
|
|
117
153
|
}
|
|
@@ -163,19 +199,50 @@ var OllamaChatLanguageModel = class {
|
|
|
163
199
|
}
|
|
164
200
|
specificationVersion = "v2";
|
|
165
201
|
defaultObjectGenerationMode = "json";
|
|
166
|
-
supportsImages =
|
|
202
|
+
supportsImages = true;
|
|
203
|
+
// โ
Ollama supports images (URLs, files, base64)
|
|
167
204
|
supportsVideoURLs = false;
|
|
205
|
+
// โ Not supported by Ollama API
|
|
168
206
|
supportsAudioURLs = false;
|
|
207
|
+
// โ Not supported by Ollama API
|
|
169
208
|
supportsVideoFile = false;
|
|
209
|
+
// โ Not supported by Ollama API
|
|
170
210
|
supportsAudioFile = false;
|
|
211
|
+
// โ Not supported by Ollama API
|
|
171
212
|
supportsImageFile = true;
|
|
172
|
-
|
|
213
|
+
// โ
Already correct
|
|
214
|
+
supportedUrls = {
|
|
215
|
+
// Support common image URL patterns
|
|
216
|
+
image: [
|
|
217
|
+
/^https?:\/\/.*\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?.*)?$/i,
|
|
218
|
+
/^data:image\/[^;]+;base64,/i
|
|
219
|
+
// Data URLs
|
|
220
|
+
]
|
|
221
|
+
};
|
|
173
222
|
get provider() {
|
|
174
223
|
return this.config.provider;
|
|
175
224
|
}
|
|
176
225
|
get supportsStructuredOutputs() {
|
|
177
226
|
return this.settings.structuredOutputs ?? false;
|
|
178
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Check if structured outputs should be enabled based on the call options
|
|
230
|
+
* This is used internally to auto-detect when structured outputs are needed
|
|
231
|
+
*/
|
|
232
|
+
shouldEnableStructuredOutputs(options) {
|
|
233
|
+
if (options.responseFormat?.type === "json" && options.responseFormat.schema) {
|
|
234
|
+
if (this.settings.structuredOutputs === false) {
|
|
235
|
+
console.warn(
|
|
236
|
+
"Ollama: structuredOutputs was set to false but auto-enabled for object generation. This ensures generateObject and streamObject work correctly."
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
if (this.settings.structuredOutputs !== void 0) {
|
|
242
|
+
return this.settings.structuredOutputs;
|
|
243
|
+
}
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
179
246
|
getCallOptions(options) {
|
|
180
247
|
const {
|
|
181
248
|
prompt,
|
|
@@ -191,7 +258,8 @@ var OllamaChatLanguageModel = class {
|
|
|
191
258
|
tools
|
|
192
259
|
} = options;
|
|
193
260
|
const warnings = [];
|
|
194
|
-
|
|
261
|
+
const needsStructuredOutputs = this.shouldEnableStructuredOutputs(options);
|
|
262
|
+
if (responseFormat?.type === "json" && responseFormat.schema && !needsStructuredOutputs) {
|
|
195
263
|
throw new Error(
|
|
196
264
|
"JSON schema is only supported when structuredOutputs is enabled"
|
|
197
265
|
);
|
|
@@ -262,7 +330,7 @@ var OllamaChatLanguageModel = class {
|
|
|
262
330
|
}
|
|
263
331
|
let format;
|
|
264
332
|
if (responseFormat?.type === "json") {
|
|
265
|
-
format = "json";
|
|
333
|
+
format = responseFormat.schema && needsStructuredOutputs ? responseFormat.schema : "json";
|
|
266
334
|
}
|
|
267
335
|
const messages = convertToOllamaChatMessages(prompt);
|
|
268
336
|
return {
|
|
@@ -292,7 +360,11 @@ var OllamaChatLanguageModel = class {
|
|
|
292
360
|
});
|
|
293
361
|
const text = response.message.content;
|
|
294
362
|
const toolCalls = response.message.tool_calls;
|
|
363
|
+
const thinking = response.message.thinking;
|
|
295
364
|
const content = [];
|
|
365
|
+
if (thinking && this.settings.reasoning) {
|
|
366
|
+
content.push({ type: "reasoning", text: thinking });
|
|
367
|
+
}
|
|
296
368
|
if (text) {
|
|
297
369
|
content.push({ type: "text", text });
|
|
298
370
|
}
|
|
@@ -372,6 +444,7 @@ var OllamaChatLanguageModel = class {
|
|
|
372
444
|
totalTokens: 0
|
|
373
445
|
};
|
|
374
446
|
let finishReason = "unknown";
|
|
447
|
+
const reasoningEnabled = this.settings.reasoning;
|
|
375
448
|
const transformStream = new TransformStream({
|
|
376
449
|
async transform(chunk, controller) {
|
|
377
450
|
if (!chunk || typeof chunk !== "object") {
|
|
@@ -392,6 +465,21 @@ var OllamaChatLanguageModel = class {
|
|
|
392
465
|
usage
|
|
393
466
|
});
|
|
394
467
|
} else {
|
|
468
|
+
if (chunk.message.thinking && reasoningEnabled) {
|
|
469
|
+
controller.enqueue({
|
|
470
|
+
type: "reasoning-start",
|
|
471
|
+
id: crypto.randomUUID()
|
|
472
|
+
});
|
|
473
|
+
controller.enqueue({
|
|
474
|
+
type: "reasoning-delta",
|
|
475
|
+
id: crypto.randomUUID(),
|
|
476
|
+
delta: chunk.message.thinking
|
|
477
|
+
});
|
|
478
|
+
controller.enqueue({
|
|
479
|
+
type: "reasoning-end",
|
|
480
|
+
id: crypto.randomUUID()
|
|
481
|
+
});
|
|
482
|
+
}
|
|
395
483
|
if (chunk.message.tool_calls && chunk.message.tool_calls.length > 0) {
|
|
396
484
|
for (const toolCall of chunk.message.tool_calls) {
|
|
397
485
|
const toolInput = toolCall.function.arguments || {};
|
|
@@ -403,7 +491,8 @@ var OllamaChatLanguageModel = class {
|
|
|
403
491
|
input: JSON.stringify(toolInput)
|
|
404
492
|
});
|
|
405
493
|
}
|
|
406
|
-
}
|
|
494
|
+
}
|
|
495
|
+
if (chunk.message.content && typeof chunk.message.content === "string" && chunk.message.content.length > 0) {
|
|
407
496
|
controller.enqueue({
|
|
408
497
|
type: "text-delta",
|
|
409
498
|
id: crypto.randomUUID(),
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider.ts","../src/utils/convert-to-ollama-messages.ts","../src/utils/map-ollama-finish-reason.ts","../src/utils/ollama-error.ts","../src/models/chat-language-model.ts","../src/models/embedding-model.ts"],"sourcesContent":["export {\n createOllama,\n ollama,\n type OllamaProvider,\n type OllamaProviderSettings,\n type OllamaChatSettings,\n type OllamaEmbeddingSettings,\n type OllamaProviderOptions,\n type OllamaChatProviderOptions,\n type OllamaEmbeddingProviderOptions,\n} from './provider';\n\nexport { OllamaChatLanguageModel } from './models/chat-language-model';\nexport type { OllamaChatConfig } from './models/chat-language-model';\nexport { OllamaEmbeddingModel } from './models/embedding-model';\nexport type { OllamaEmbeddingConfig } from './models/embedding-model';\nexport { OllamaError } from './utils/ollama-error';\nexport type { OllamaErrorData } from './utils/ollama-error';\n\n","import {\n LanguageModelV2,\n EmbeddingModelV2,\n ProviderV2,\n NoSuchModelError,\n} from '@ai-sdk/provider';\nimport { Ollama } from 'ollama';\nimport { OllamaChatLanguageModel } from './models/chat-language-model';\nimport { OllamaEmbeddingModel } from './models/embedding-model';\n\nexport interface OllamaProviderSettings {\n /**\n * Base URL for the Ollama API (defaults to http://127.0.0.1:11434)\n */\n baseURL?: string;\n\n /**\n * Custom headers for API requests\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\nexport interface OllamaProvider extends ProviderV2 {\n /**\n * Create a language model instance\n */\n (modelId: string, settings?: OllamaChatSettings): LanguageModelV2;\n\n /**\n * Create a language model instance with the `chat` method\n */\n chat(modelId: string, settings?: OllamaChatSettings): LanguageModelV2;\n\n /**\n * Create a language model instance with the `languageModel` method\n */\n languageModel(\n modelId: string,\n settings?: OllamaChatSettings,\n ): LanguageModelV2;\n\n /**\n * Create an embedding model instance\n */\n embedding(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n\n /**\n * Create an embedding model instance with the `textEmbedding` method\n */\n textEmbedding(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n\n /**\n * Create an embedding model instance with the `textEmbeddingModel` method\n */\n textEmbeddingModel(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n}\n\nexport interface OllamaChatSettings {\n /**\n * Enable structured output mode\n */\n structuredOutputs?: boolean;\n\n /**\n * Additional model parameters\n */\n options?: {\n num_ctx?: number;\n num_predict?: number;\n temperature?: number;\n top_k?: number;\n top_p?: number;\n min_p?: number;\n seed?: number;\n stop?: string[];\n num_keep?: number;\n typical_p?: number;\n repeat_last_n?: number;\n repeat_penalty?: number;\n presence_penalty?: number;\n frequency_penalty?: number;\n mirostat?: number;\n mirostat_tau?: number;\n mirostat_eta?: number;\n penalize_newline?: boolean;\n numa?: boolean;\n num_thread?: number;\n num_gpu?: number;\n main_gpu?: number;\n low_vram?: boolean;\n f16_kv?: boolean;\n vocab_only?: boolean;\n use_mmap?: boolean;\n use_mlock?: boolean;\n };\n}\n\nexport interface OllamaEmbeddingSettings {\n /**\n * Additional embedding parameters\n */\n options?: {\n num_thread?: number;\n };\n}\n\n/**\n * Options for configuring Ollama provider calls\n */\nexport interface OllamaProviderOptions {\n /**\n * Additional headers to include in requests\n */\n headers?: Record<string, string>;\n}\n\n/**\n * Options for configuring Ollama chat model calls\n */\nexport interface OllamaChatProviderOptions extends OllamaProviderOptions {\n /**\n * Enable structured output mode for object generation\n */\n structuredOutputs?: boolean;\n}\n\n/**\n * Options for configuring Ollama embedding model calls\n */\nexport interface OllamaEmbeddingProviderOptions extends OllamaProviderOptions {\n /**\n * Maximum number of embeddings to process in a single call\n */\n maxEmbeddingsPerCall?: number;\n}\n\n/**\n * Create an Ollama provider instance\n */\nexport function createOllama(\n options: OllamaProviderSettings = {},\n): OllamaProvider {\n const client = new Ollama({\n host: options.baseURL,\n fetch: options.fetch,\n headers: options.headers,\n });\n\n const createChatModel = (\n modelId: string,\n settings: OllamaChatSettings = {},\n ) => {\n return new OllamaChatLanguageModel(modelId, settings, {\n client,\n provider: 'ollama',\n });\n };\n\n const createEmbeddingModel = (\n modelId: string,\n settings: OllamaEmbeddingSettings = {},\n ) => {\n return new OllamaEmbeddingModel(modelId, settings, {\n client,\n provider: 'ollama',\n });\n };\n\n const provider = function (modelId: string, settings?: OllamaChatSettings) {\n if (new.target) {\n throw new Error(\n 'The Ollama provider cannot be called with the new keyword.',\n );\n }\n return createChatModel(modelId, settings);\n };\n\n provider.chat = createChatModel;\n provider.languageModel = createChatModel;\n provider.embedding = createEmbeddingModel;\n provider.textEmbedding = createEmbeddingModel;\n provider.textEmbeddingModel = createEmbeddingModel;\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'imageModel',\n message: 'Image generation is not supported by Ollama',\n });\n };\n\n return provider as OllamaProvider;\n}\n\n/**\n * Default Ollama provider instance\n */\nexport const ollama = createOllama();\n","import { LanguageModelV2Prompt } from '@ai-sdk/provider';\nimport { Message as OllamaMessage } from 'ollama';\n\nexport function convertToOllamaChatMessages(\n prompt: LanguageModelV2Prompt,\n): OllamaMessage[] {\n const messages: OllamaMessage[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case 'system': {\n messages.push({\n role: 'system',\n content: message.content,\n });\n break;\n }\n\n case 'user': {\n if (typeof message.content === 'string') {\n messages.push({\n role: 'user',\n content: message.content,\n });\n } else {\n // Handle multi-part content\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('\\n');\n\n const imageParts = message.content\n .filter(\n (part): part is Extract<typeof part, { type: 'file' }> =>\n part.type === 'file',\n )\n .filter((part) => part.mediaType.startsWith('image/'))\n .map((part) => {\n if (part.data instanceof URL) {\n return part.data.href;\n } else if (typeof part.data === 'string') {\n // If it's already a data URL, extract just the base64 part\n if (part.data.startsWith('data:')) {\n const base64Match = part.data.match(/data:[^;]+;base64,(.+)/);\n if (base64Match) {\n return base64Match[1]; // Return just the base64 part\n }\n }\n return part.data;\n } else if (part.data instanceof Uint8Array) {\n // Handle Uint8Array by converting to base64 (without data URL prefix)\n return Buffer.from(part.data).toString('base64');\n } else {\n // Fallback for other types\n return String(part.data);\n }\n });\n\n messages.push({\n role: 'user',\n content: textParts,\n images:\n imageParts.length > 0\n ? imageParts.filter((img): img is string => img !== undefined)\n : undefined,\n });\n }\n break;\n }\n\n case 'assistant': {\n let content = '';\n\n if (typeof message.content === 'string') {\n content = message.content;\n } else {\n // Combine text parts\n content = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('');\n\n // Handle tool calls if present\n const toolCalls = message.content.filter(\n (part) => part.type === 'tool-call',\n );\n if (toolCalls.length > 0) {\n // For now, we'll append tool calls as text since Ollama doesn't have native support\n const toolCallText = toolCalls\n .map((tc) => `[Tool Call: ${tc.toolName}]`)\n .join('\\n');\n if (toolCallText) {\n content = content ? `${content}\\n${toolCallText}` : toolCallText;\n }\n }\n }\n\n messages.push({\n role: 'assistant',\n content,\n });\n break;\n }\n\n case 'tool': {\n // Ollama doesn't have native tool result support, so we'll add it as a user message\n messages.push({\n role: 'user',\n content: `[Tool Result]`,\n });\n break;\n }\n\n default: {\n // Handle unknown message roles\n throw new Error(\n `Unsupported message role: ${(message as { role: string }).role}`,\n );\n }\n }\n }\n\n return messages;\n}\n","import { LanguageModelV2FinishReason } from '@ai-sdk/provider';\n\nexport function mapOllamaFinishReason(\n reason?: string | null,\n): LanguageModelV2FinishReason {\n if (!reason) return 'unknown';\n\n switch (reason) {\n case 'stop': {\n return 'stop';\n }\n case 'length': {\n return 'length';\n }\n default: {\n return 'unknown';\n }\n }\n}\n","export interface OllamaErrorData {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport class OllamaError extends Error {\n readonly cause?: unknown;\n readonly data?: OllamaErrorData;\n\n constructor({\n message,\n cause,\n data,\n }: {\n message: string;\n cause?: unknown;\n data?: OllamaErrorData;\n }) {\n super(message);\n this.name = 'OllamaError';\n this.cause = cause;\n this.data = data;\n }\n\n static isOllamaError(error: unknown): error is OllamaError {\n return error instanceof OllamaError;\n }\n}\n","import {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2FinishReason,\n LanguageModelV2StreamPart,\n LanguageModelV2Usage,\n LanguageModelV2Content,\n JSONValue,\n} from '@ai-sdk/provider';\nimport { Ollama, Message as OllamaMessage, ChatResponse, Tool } from 'ollama';\nimport { OllamaChatSettings } from '../provider';\nimport { convertToOllamaChatMessages } from '../utils/convert-to-ollama-messages';\nimport { mapOllamaFinishReason } from '../utils/map-ollama-finish-reason';\nimport { OllamaError } from '../utils/ollama-error';\n\nexport interface OllamaChatConfig {\n client: Ollama;\n provider: string;\n}\n\nexport class OllamaChatLanguageModel implements LanguageModelV2 {\n readonly specificationVersion = 'v2' as const;\n readonly defaultObjectGenerationMode = 'json';\n readonly supportsImages = false;\n readonly supportsVideoURLs = false;\n readonly supportsAudioURLs = false;\n readonly supportsVideoFile = false;\n readonly supportsAudioFile = false;\n readonly supportsImageFile = true;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n constructor(\n public readonly modelId: string,\n public readonly settings: OllamaChatSettings,\n private readonly config: OllamaChatConfig,\n ) {}\n\n get provider(): string {\n return this.config.provider;\n }\n\n get supportsStructuredOutputs(): boolean {\n return this.settings.structuredOutputs ?? false;\n }\n\n private getCallOptions(options: LanguageModelV2CallOptions): {\n messages: OllamaMessage[];\n options: Record<string, unknown>;\n format?: string;\n tools?: Tool[];\n warnings: LanguageModelV2CallWarning[];\n } {\n const {\n prompt,\n temperature,\n maxOutputTokens,\n topP,\n topK,\n frequencyPenalty,\n presencePenalty,\n stopSequences,\n seed,\n responseFormat,\n tools,\n } = options;\n\n const warnings: LanguageModelV2CallWarning[] = [];\n\n // Check for unsupported features and throw errors\n if (\n responseFormat?.type === 'json' &&\n responseFormat.schema &&\n !this.supportsStructuredOutputs\n ) {\n throw new Error(\n 'JSON schema is only supported when structuredOutputs is enabled',\n );\n }\n\n // Convert AI SDK tools to Ollama format (error already thrown if unsupported)\n const ollamaTools: Tool[] | undefined = tools\n ? tools.map((tool): Tool => {\n if (tool.type === 'function') {\n // The inputSchema from AI SDK should already be a JSON schema\n // when tools are passed to providers\n let jsonSchema: Record<string, unknown>;\n\n // Check if we have a Zod schema (has parse method) or a JSON schema\n if (tool.inputSchema && typeof tool.inputSchema === 'object') {\n if (\n 'parse' in tool.inputSchema &&\n typeof tool.inputSchema.parse === 'function'\n ) {\n // It's a Zod schema - we need to convert it\n // For now, we'll use a basic fallback since zod-to-json-schema has version issues\n console.warn(\n `Tool ${tool.name} is using a Zod schema directly. Schema conversion may not work properly due to Zod version mismatch.`,\n );\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n } else if (\n 'properties' in tool.inputSchema ||\n 'type' in tool.inputSchema\n ) {\n // It looks like a JSON schema already\n jsonSchema = tool.inputSchema as Record<string, unknown>;\n } else {\n // Unknown schema format\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n }\n } else {\n // No schema provided\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n }\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: jsonSchema,\n },\n };\n }\n // Provider-defined tools not supported by Ollama\n throw new Error(\n `Provider-defined tools are not supported by Ollama. Use function tools instead.`,\n );\n })\n : undefined;\n\n // Build options with correct precedence:\n // 1. AI SDK call parameters (mapped to Ollama equivalents)\n // 2. Model settings (Ollama options) override AI SDK parameters when both are specified\n const ollamaOptions: Record<string, unknown> = {\n // Start with AI SDK parameters mapped to Ollama names\n ...(temperature !== undefined && { temperature }),\n ...(maxOutputTokens !== undefined && { num_predict: maxOutputTokens }),\n ...(topP !== undefined && { top_p: topP }),\n ...(topK !== undefined && { top_k: topK }),\n ...(frequencyPenalty !== undefined && {\n frequency_penalty: frequencyPenalty,\n }),\n ...(presencePenalty !== undefined && {\n presence_penalty: presencePenalty,\n }),\n ...(stopSequences !== undefined && { stop: stopSequences }),\n ...(seed !== undefined && { seed }),\n // Ollama model options override AI SDK parameters\n ...this.settings.options,\n };\n\n // Remove undefined values\n for (const key of Object.keys(ollamaOptions)) {\n if (ollamaOptions[key] === undefined) {\n delete ollamaOptions[key];\n }\n }\n\n let format: string | undefined;\n if (responseFormat?.type === 'json') {\n format = 'json';\n }\n\n const messages = convertToOllamaChatMessages(prompt);\n\n return {\n messages,\n options: ollamaOptions,\n format,\n tools: ollamaTools,\n warnings,\n };\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n providerMetadata?: Record<string, Record<string, JSONValue>>;\n request?: { body: string };\n response?: { id?: string; timestamp?: Date; modelId?: string };\n warnings: LanguageModelV2CallWarning[];\n }> {\n const {\n messages,\n options: ollamaOptions,\n format,\n tools,\n warnings,\n } = this.getCallOptions(options);\n\n try {\n const response = (await this.config.client.chat({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n stream: false,\n })) as ChatResponse;\n\n const text = response.message.content;\n const toolCalls = response.message.tool_calls;\n\n // Convert content based on whether we have tool calls\n const content: LanguageModelV2Content[] = [];\n\n if (text) {\n content.push({ type: 'text', text });\n }\n\n if (toolCalls && toolCalls.length > 0) {\n for (const toolCall of toolCalls) {\n const toolInput = toolCall.function.arguments || {};\n\n content.push({\n type: 'tool-call',\n toolCallId: crypto.randomUUID(), // Ollama doesn't provide IDs\n toolName: toolCall.function.name,\n input: JSON.stringify(toolInput),\n });\n }\n }\n\n return {\n content,\n finishReason: mapOllamaFinishReason(\n response.done_reason,\n ) as LanguageModelV2FinishReason,\n usage: {\n inputTokens: response.prompt_eval_count || 0,\n outputTokens: response.eval_count || 0,\n totalTokens:\n (response.prompt_eval_count || 0) + (response.eval_count || 0),\n },\n providerMetadata: {\n ollama: {\n model: response.model,\n created_at: response.created_at\n ? new Date(response.created_at).toISOString()\n : undefined,\n total_duration: response.total_duration,\n load_duration: response.load_duration,\n eval_duration: response.eval_duration,\n } as Record<string, JSONValue>,\n },\n request: {\n body: JSON.stringify({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n }),\n },\n response: {\n timestamp: new Date(),\n modelId: this.modelId,\n },\n warnings,\n };\n } catch (error) {\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n rawCall: {\n rawPrompt: unknown;\n rawSettings: Record<string, unknown>;\n };\n warnings?: LanguageModelV2CallWarning[];\n }> {\n const {\n messages,\n options: ollamaOptions,\n format,\n tools,\n warnings,\n } = this.getCallOptions(options);\n\n try {\n const stream = await this.config.client.chat({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n stream: true,\n });\n\n let usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n\n const transformStream = new TransformStream<\n ChatResponse,\n LanguageModelV2StreamPart\n >({\n async transform(chunk: ChatResponse, controller) {\n // Validate chunk\n if (!chunk || typeof chunk !== 'object') {\n return; // Skip invalid chunks\n }\n\n // Regular chunk with content\n if (chunk.done) {\n // Final chunk with metadata\n usage = {\n inputTokens: chunk.prompt_eval_count || 0,\n outputTokens: chunk.eval_count || 0,\n totalTokens:\n (chunk.prompt_eval_count || 0) + (chunk.eval_count || 0),\n };\n finishReason = mapOllamaFinishReason(\n chunk.done_reason,\n ) as LanguageModelV2FinishReason;\n\n controller.enqueue({\n type: 'finish',\n finishReason,\n usage,\n });\n } else {\n // Handle tool calls in streaming\n if (\n chunk.message.tool_calls &&\n chunk.message.tool_calls.length > 0\n ) {\n for (const toolCall of chunk.message.tool_calls) {\n const toolInput = toolCall.function.arguments || {};\n\n controller.enqueue({\n type: 'tool-call',\n toolCallId: crypto.randomUUID(), // Ollama doesn't provide IDs\n toolName: toolCall.function.name,\n input: JSON.stringify(toolInput),\n });\n }\n } else if (\n chunk.message.content &&\n typeof chunk.message.content === 'string'\n ) {\n controller.enqueue({\n type: 'text-delta',\n id: crypto.randomUUID(), // Generate unique ID for each text chunk\n delta: chunk.message.content,\n });\n }\n }\n },\n });\n\n // Create a readable stream from the async generator\n const readableStream = new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Ensure chunk is valid before enqueuing\n if (chunk && typeof chunk === 'object') {\n controller.enqueue(chunk);\n }\n }\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n\n return {\n stream: readableStream.pipeThrough(transformStream),\n rawCall: {\n rawPrompt: messages,\n rawSettings: {\n model: this.modelId,\n options: ollamaOptions,\n format,\n tools,\n },\n },\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (error) {\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n}\n","import { EmbeddingModelV2, EmbeddingModelV2Embedding } from '@ai-sdk/provider';\nimport { Ollama } from 'ollama';\nimport { OllamaEmbeddingSettings } from '../provider';\nimport { OllamaError } from '../utils/ollama-error';\n\nexport interface OllamaEmbeddingConfig {\n client: Ollama;\n provider: string;\n}\n\nexport class OllamaEmbeddingModel implements EmbeddingModelV2<string> {\n readonly specificationVersion = 'v2' as const;\n readonly modelId: string;\n readonly maxEmbeddingsPerCall = 2048;\n readonly supportsParallelCalls = true;\n\n constructor(\n modelId: string,\n private readonly settings: OllamaEmbeddingSettings,\n private readonly config: OllamaEmbeddingConfig,\n ) {\n this.modelId = modelId;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n async doEmbed(params: {\n values: string[];\n abortSignal?: AbortSignal;\n }): Promise<{\n embeddings: EmbeddingModelV2Embedding[];\n }> {\n const { values, abortSignal } = params;\n if (values.length > this.maxEmbeddingsPerCall) {\n throw new OllamaError({\n message: `Too many values to embed. Maximum: ${this.maxEmbeddingsPerCall}, Received: ${values.length}`,\n });\n }\n\n // Handle empty array case\n if (values.length === 0) {\n return { embeddings: [] };\n }\n\n try {\n const embeddings: EmbeddingModelV2Embedding[] = [];\n\n // Ollama's embed API currently only supports single prompts\n // So we need to make multiple requests\n for (const value of values) {\n // Skip undefined values (AI SDK interface issue workaround)\n if (value === undefined || value === null) {\n continue;\n }\n\n const response = await this.config.client.embed({\n model: this.modelId,\n input: value,\n options: this.settings.options,\n });\n\n if (!response.embeddings) {\n throw new OllamaError({\n message: `No embeddings field in response`,\n });\n }\n\n if (response.embeddings.length === 0) {\n throw new OllamaError({\n message: `Empty embeddings array returned`,\n });\n }\n\n embeddings.push(response.embeddings[0] as number[]);\n\n // Check if we should abort\n if (abortSignal?.aborted) {\n throw new Error('Embedding generation aborted');\n }\n }\n\n if (embeddings.length === 0) {\n throw new OllamaError({\n message: `No valid values provided for embedding (all were undefined/null)`,\n });\n }\n\n return {\n embeddings,\n };\n } catch (error) {\n if (error instanceof OllamaError) {\n throw error;\n }\n\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.ts","../src/utils/convert-to-ollama-messages.ts","../src/utils/map-ollama-finish-reason.ts","../src/utils/ollama-error.ts","../src/models/chat-language-model.ts","../src/models/embedding-model.ts"],"sourcesContent":["export {\n createOllama,\n ollama,\n type OllamaProvider,\n type OllamaProviderSettings,\n type OllamaChatSettings,\n type OllamaEmbeddingSettings,\n type OllamaProviderOptions,\n type OllamaChatProviderOptions,\n type OllamaEmbeddingProviderOptions,\n} from './provider';\n\nexport { OllamaChatLanguageModel } from './models/chat-language-model';\nexport type { OllamaChatConfig } from './models/chat-language-model';\nexport { OllamaEmbeddingModel } from './models/embedding-model';\nexport type { OllamaEmbeddingConfig } from './models/embedding-model';\nexport { OllamaError } from './utils/ollama-error';\nexport type { OllamaErrorData } from './utils/ollama-error';\n","import {\n LanguageModelV2,\n EmbeddingModelV2,\n ProviderV2,\n NoSuchModelError,\n} from '@ai-sdk/provider';\nimport { Ollama } from 'ollama';\nimport { OllamaChatLanguageModel } from './models/chat-language-model';\nimport { OllamaEmbeddingModel } from './models/embedding-model';\n\nexport interface OllamaProviderSettings {\n /**\n * Base URL for the Ollama API (defaults to http://127.0.0.1:11434)\n */\n baseURL?: string;\n\n /**\n * Custom headers for API requests\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\nexport interface OllamaProvider extends ProviderV2 {\n /**\n * Create a language model instance\n */\n (modelId: string, settings?: OllamaChatSettings): LanguageModelV2;\n\n /**\n * Create a language model instance with the `chat` method\n */\n chat(modelId: string, settings?: OllamaChatSettings): LanguageModelV2;\n\n /**\n * Create a language model instance with the `languageModel` method\n */\n languageModel(\n modelId: string,\n settings?: OllamaChatSettings,\n ): LanguageModelV2;\n\n /**\n * Create an embedding model instance\n */\n embedding(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n\n /**\n * Create an embedding model instance with the `textEmbedding` method\n */\n textEmbedding(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n\n /**\n * Create an embedding model instance with the `textEmbeddingModel` method\n */\n textEmbeddingModel(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n}\n\nexport interface OllamaChatSettings {\n /**\n * Enable structured output mode\n */\n structuredOutputs?: boolean;\n\n /**\n * Enable reasoning support for models that support it\n */\n reasoning?: boolean;\n\n /**\n * Additional model parameters\n */\n options?: {\n num_ctx?: number;\n num_predict?: number;\n temperature?: number;\n top_k?: number;\n top_p?: number;\n min_p?: number;\n seed?: number;\n stop?: string[];\n num_keep?: number;\n typical_p?: number;\n repeat_last_n?: number;\n repeat_penalty?: number;\n presence_penalty?: number;\n frequency_penalty?: number;\n mirostat?: number;\n mirostat_tau?: number;\n mirostat_eta?: number;\n penalize_newline?: boolean;\n numa?: boolean;\n num_thread?: number;\n num_gpu?: number;\n main_gpu?: number;\n low_vram?: boolean;\n f16_kv?: boolean;\n vocab_only?: boolean;\n use_mmap?: boolean;\n use_mlock?: boolean;\n };\n}\n\nexport interface OllamaEmbeddingSettings {\n /**\n * Additional embedding parameters\n */\n options?: {\n num_thread?: number;\n };\n}\n\n/**\n * Options for configuring Ollama provider calls\n */\nexport interface OllamaProviderOptions {\n /**\n * Additional headers to include in requests\n */\n headers?: Record<string, string>;\n}\n\n/**\n * Options for configuring Ollama chat model calls\n */\nexport interface OllamaChatProviderOptions extends OllamaProviderOptions {\n /**\n * Enable structured output mode for object generation\n */\n structuredOutputs?: boolean;\n}\n\n/**\n * Options for configuring Ollama embedding model calls\n */\nexport interface OllamaEmbeddingProviderOptions extends OllamaProviderOptions {\n /**\n * Maximum number of embeddings to process in a single call\n */\n maxEmbeddingsPerCall?: number;\n}\n\n/**\n * Create an Ollama provider instance\n */\nexport function createOllama(\n options: OllamaProviderSettings = {},\n): OllamaProvider {\n const client = new Ollama({\n host: options.baseURL,\n fetch: options.fetch,\n headers: options.headers,\n });\n\n const createChatModel = (\n modelId: string,\n settings: OllamaChatSettings = {},\n ) => {\n return new OllamaChatLanguageModel(modelId, settings, {\n client,\n provider: 'ollama',\n });\n };\n\n const createEmbeddingModel = (\n modelId: string,\n settings: OllamaEmbeddingSettings = {},\n ) => {\n return new OllamaEmbeddingModel(modelId, settings, {\n client,\n provider: 'ollama',\n });\n };\n\n const provider = function (modelId: string, settings?: OllamaChatSettings) {\n if (new.target) {\n throw new Error(\n 'The Ollama provider cannot be called with the new keyword.',\n );\n }\n return createChatModel(modelId, settings);\n };\n\n provider.chat = createChatModel;\n provider.languageModel = createChatModel;\n provider.embedding = createEmbeddingModel;\n provider.textEmbedding = createEmbeddingModel;\n provider.textEmbeddingModel = createEmbeddingModel;\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'imageModel',\n message: 'Image generation is not supported by Ollama',\n });\n };\n\n return provider as OllamaProvider;\n}\n\n/**\n * Default Ollama provider instance\n */\nexport const ollama = createOllama();\n","import { LanguageModelV2Prompt } from '@ai-sdk/provider';\nimport { Message as OllamaMessage } from 'ollama';\n\n/**\n * Enhanced message conversion that supports all Ollama capabilities\n * and handles edge cases better than the referenced implementation\n */\nexport function convertToOllamaChatMessages(\n prompt: LanguageModelV2Prompt,\n): OllamaMessage[] {\n const messages: OllamaMessage[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case 'system': {\n messages.push({\n role: 'system',\n content: message.content,\n });\n break;\n }\n\n case 'user': {\n if (typeof message.content === 'string') {\n messages.push({\n role: 'user',\n content: message.content,\n });\n } else {\n // Handle multi-part content with enhanced image support\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('\\n');\n\n const imageParts = message.content\n .filter(\n (part): part is Extract<typeof part, { type: 'file' }> =>\n part.type === 'file',\n )\n .filter((part) => {\n // Support image files only\n return part.mediaType?.startsWith('image/') || false;\n })\n .map((part) => {\n const imageData = part.data;\n\n if (imageData instanceof URL) {\n // Handle image URLs - extract base64 from data URLs or use URL directly\n if (imageData.protocol === 'data:') {\n const base64Match = imageData.href.match(\n /data:[^;]+;base64,(.+)/,\n );\n if (base64Match) {\n return base64Match[1]; // Return just the base64 part\n }\n // If no base64 match, return the full data URL\n return imageData.href;\n }\n // For HTTP URLs, return as-is (Ollama will handle them)\n return imageData.href;\n } else if (typeof imageData === 'string') {\n // Handle base64 strings\n if (imageData.startsWith('data:')) {\n const base64Match = imageData.match(/data:[^;]+;base64,(.+)/);\n if (base64Match) {\n return base64Match[1]; // Return just the base64 part\n }\n }\n return imageData;\n } else if (imageData instanceof Uint8Array) {\n // Handle Uint8Array by converting to base64\n return Buffer.from(imageData).toString('base64');\n } else {\n // Fallback for other types\n console.warn(\n `Unsupported image data type: ${typeof imageData}`,\n );\n return null;\n }\n })\n .filter((img): img is string => img !== null);\n\n messages.push({\n role: 'user',\n content: textParts || '', // Ensure content is never undefined\n images: imageParts.length > 0 ? imageParts : undefined,\n });\n }\n break;\n }\n\n case 'assistant': {\n let content = '';\n\n if (typeof message.content === 'string') {\n content = message.content;\n } else {\n // Enhanced content handling with better tool call support\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('');\n\n const reasoningParts = message.content\n .filter((part) => part.type === 'reasoning')\n .map((part) => part.text)\n .join('\\n');\n\n // Combine text and reasoning\n content = [textParts, reasoningParts].filter(Boolean).join('\\n');\n\n // Handle tool calls if present\n const toolCalls = message.content.filter(\n (part) => part.type === 'tool-call',\n );\n if (toolCalls.length > 0) {\n // For now, we'll append tool calls as text since Ollama doesn't have native support\n const toolCallText = toolCalls\n .map((tc) => `[Tool Call: ${tc.toolName}]`)\n .join('\\n');\n if (toolCallText) {\n content = content ? `${content}\\n${toolCallText}` : toolCallText;\n }\n }\n }\n\n messages.push({\n role: 'assistant',\n content: content || '', // Ensure content is never undefined\n });\n break;\n }\n\n case 'tool': {\n // Enhanced tool result handling\n if (typeof message.content === 'string') {\n messages.push({\n role: 'user', // Ollama doesn't have native tool role, so we use user\n content: `[Tool Result]: ${message.content}`,\n });\n } else {\n // Handle multi-part tool results\n const toolResultParts = message.content\n .filter((part) => part.type === 'tool-result')\n .map((part) => {\n if (part.output.type === 'text') {\n return part.output.value;\n } else if (part.output.type === 'json') {\n return JSON.stringify(part.output.value);\n }\n return String(part.output.value);\n })\n .join('\\n');\n\n messages.push({\n role: 'user',\n content: `[Tool Result]: ${toolResultParts || ''}`,\n });\n }\n break;\n }\n\n default: {\n // Enhanced error handling with more descriptive messages\n const role = (message as { role: string }).role;\n throw new Error(\n `Unsupported message role: ${role}. Supported roles are: system, user, assistant, tool`,\n );\n }\n }\n }\n\n return messages;\n}\n","import { LanguageModelV2FinishReason } from '@ai-sdk/provider';\n\nexport function mapOllamaFinishReason(\n reason?: string | null,\n): LanguageModelV2FinishReason {\n if (!reason) return 'unknown';\n\n switch (reason) {\n case 'stop': {\n return 'stop';\n }\n case 'length': {\n return 'length';\n }\n default: {\n return 'unknown';\n }\n }\n}\n","export interface OllamaErrorData {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport class OllamaError extends Error {\n readonly cause?: unknown;\n readonly data?: OllamaErrorData;\n\n constructor({\n message,\n cause,\n data,\n }: {\n message: string;\n cause?: unknown;\n data?: OllamaErrorData;\n }) {\n super(message);\n this.name = 'OllamaError';\n this.cause = cause;\n this.data = data;\n }\n\n static isOllamaError(error: unknown): error is OllamaError {\n return error instanceof OllamaError;\n }\n}\n","import {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2FinishReason,\n LanguageModelV2StreamPart,\n LanguageModelV2Usage,\n LanguageModelV2Content,\n JSONValue,\n} from '@ai-sdk/provider';\nimport { Ollama, Message as OllamaMessage, ChatResponse, Tool } from 'ollama';\nimport { OllamaChatSettings } from '../provider';\nimport { convertToOllamaChatMessages } from '../utils/convert-to-ollama-messages';\nimport { mapOllamaFinishReason } from '../utils/map-ollama-finish-reason';\nimport { OllamaError } from '../utils/ollama-error';\n\nexport interface OllamaChatConfig {\n client: Ollama;\n provider: string;\n}\n\nexport class OllamaChatLanguageModel implements LanguageModelV2 {\n readonly specificationVersion = 'v2' as const;\n readonly defaultObjectGenerationMode = 'json';\n readonly supportsImages = true; // โ
Ollama supports images (URLs, files, base64)\n readonly supportsVideoURLs = false; // โ Not supported by Ollama API\n readonly supportsAudioURLs = false; // โ Not supported by Ollama API\n readonly supportsVideoFile = false; // โ Not supported by Ollama API\n readonly supportsAudioFile = false; // โ Not supported by Ollama API\n readonly supportsImageFile = true; // โ
Already correct\n readonly supportedUrls: Record<string, RegExp[]> = {\n // Support common image URL patterns\n image: [\n /^https?:\\/\\/.*\\.(jpg|jpeg|png|gif|webp|bmp|svg)(\\?.*)?$/i,\n /^data:image\\/[^;]+;base64,/i, // Data URLs\n ],\n };\n\n constructor(\n public readonly modelId: string,\n public readonly settings: OllamaChatSettings,\n private readonly config: OllamaChatConfig,\n ) {}\n\n get provider(): string {\n return this.config.provider;\n }\n\n get supportsStructuredOutputs(): boolean {\n // Auto-detect structured outputs when JSON schema is provided\n // This allows generateObject and streamObject to work without explicit structuredOutputs: true\n return this.settings.structuredOutputs ?? false;\n }\n\n /**\n * Check if structured outputs should be enabled based on the call options\n * This is used internally to auto-detect when structured outputs are needed\n */\n private shouldEnableStructuredOutputs(\n options: LanguageModelV2CallOptions,\n ): boolean {\n // Auto-detect: if we have a JSON schema, we need structured outputs\n // This overrides explicit settings to ensure object generation works\n if (\n options.responseFormat?.type === 'json' &&\n options.responseFormat.schema\n ) {\n // Warn if structuredOutputs was explicitly set to false but we're auto-enabling it\n if (this.settings.structuredOutputs === false) {\n console.warn(\n 'Ollama: structuredOutputs was set to false but auto-enabled for object generation. ' +\n 'This ensures generateObject and streamObject work correctly.',\n );\n }\n return true;\n }\n\n // If explicitly set, use that value (for text generation)\n if (this.settings.structuredOutputs !== undefined) {\n return this.settings.structuredOutputs;\n }\n\n // Default to false for regular text generation\n return false;\n }\n\n private getCallOptions(options: LanguageModelV2CallOptions): {\n messages: OllamaMessage[];\n options: Record<string, unknown>;\n format?: string | Record<string, unknown>;\n tools?: Tool[];\n warnings: LanguageModelV2CallWarning[];\n } {\n const {\n prompt,\n temperature,\n maxOutputTokens,\n topP,\n topK,\n frequencyPenalty,\n presencePenalty,\n stopSequences,\n seed,\n responseFormat,\n tools,\n } = options;\n\n const warnings: LanguageModelV2CallWarning[] = [];\n\n // Auto-detect structured outputs when JSON schema is provided\n const needsStructuredOutputs = this.shouldEnableStructuredOutputs(options);\n\n // Check for unsupported features and throw errors\n if (\n responseFormat?.type === 'json' &&\n responseFormat.schema &&\n !needsStructuredOutputs\n ) {\n throw new Error(\n 'JSON schema is only supported when structuredOutputs is enabled',\n );\n }\n\n // Convert AI SDK tools to Ollama format (error already thrown if unsupported)\n const ollamaTools: Tool[] | undefined = tools\n ? tools.map((tool): Tool => {\n if (tool.type === 'function') {\n // The inputSchema from AI SDK should already be a JSON schema\n // when tools are passed to providers\n let jsonSchema: Record<string, unknown>;\n\n // Check if we have a Zod schema (has parse method) or a JSON schema\n if (tool.inputSchema && typeof tool.inputSchema === 'object') {\n if (\n 'parse' in tool.inputSchema &&\n typeof tool.inputSchema.parse === 'function'\n ) {\n // It's a Zod schema - we need to convert it\n // For now, we'll use a basic fallback since zod-to-json-schema has version issues\n console.warn(\n `Tool ${tool.name} is using a Zod schema directly. Schema conversion may not work properly due to Zod version mismatch.`,\n );\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n } else if (\n 'properties' in tool.inputSchema ||\n 'type' in tool.inputSchema\n ) {\n // It looks like a JSON schema already\n jsonSchema = tool.inputSchema as Record<string, unknown>;\n } else {\n // Unknown schema format\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n }\n } else {\n // No schema provided\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n }\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: jsonSchema,\n },\n };\n }\n // Provider-defined tools not supported by Ollama\n throw new Error(\n `Provider-defined tools are not supported by Ollama. Use function tools instead.`,\n );\n })\n : undefined;\n\n // Build options with correct precedence:\n // 1. AI SDK call parameters (mapped to Ollama equivalents)\n // 2. Model settings (Ollama options) override AI SDK parameters when both are specified\n const ollamaOptions: Record<string, unknown> = {\n // Start with AI SDK parameters mapped to Ollama names\n ...(temperature !== undefined && { temperature }),\n ...(maxOutputTokens !== undefined && { num_predict: maxOutputTokens }),\n ...(topP !== undefined && { top_p: topP }),\n ...(topK !== undefined && { top_k: topK }),\n ...(frequencyPenalty !== undefined && {\n frequency_penalty: frequencyPenalty,\n }),\n ...(presencePenalty !== undefined && {\n presence_penalty: presencePenalty,\n }),\n ...(stopSequences !== undefined && { stop: stopSequences }),\n ...(seed !== undefined && { seed }),\n // Ollama model options override AI SDK parameters\n ...this.settings.options,\n };\n\n // Remove undefined values\n for (const key of Object.keys(ollamaOptions)) {\n if (ollamaOptions[key] === undefined) {\n delete ollamaOptions[key];\n }\n }\n\n let format: string | Record<string, unknown> | undefined;\n if (responseFormat?.type === 'json') {\n format =\n responseFormat.schema && needsStructuredOutputs\n ? (responseFormat.schema as Record<string, unknown>)\n : 'json';\n }\n\n const messages = convertToOllamaChatMessages(prompt);\n\n return {\n messages,\n options: ollamaOptions,\n format,\n tools: ollamaTools,\n warnings,\n };\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n providerMetadata?: Record<string, Record<string, JSONValue>>;\n request?: { body: string };\n response?: { id?: string; timestamp?: Date; modelId?: string };\n warnings: LanguageModelV2CallWarning[];\n }> {\n const {\n messages,\n options: ollamaOptions,\n format,\n tools,\n warnings,\n } = this.getCallOptions(options);\n\n try {\n const response = (await this.config.client.chat({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n stream: false,\n })) as ChatResponse;\n\n const text = response.message.content;\n const toolCalls = response.message.tool_calls;\n const thinking = response.message.thinking;\n\n // Convert content based on whether we have tool calls, reasoning, or text\n const content: LanguageModelV2Content[] = [];\n\n // Add reasoning content if present and enabled\n if (thinking && this.settings.reasoning) {\n content.push({ type: 'reasoning', text: thinking });\n }\n\n // Add text content if present\n if (text) {\n content.push({ type: 'text', text });\n }\n\n // Add tool calls if present\n if (toolCalls && toolCalls.length > 0) {\n for (const toolCall of toolCalls) {\n const toolInput = toolCall.function.arguments || {};\n\n content.push({\n type: 'tool-call',\n toolCallId: crypto.randomUUID(), // Ollama doesn't provide IDs\n toolName: toolCall.function.name,\n input: JSON.stringify(toolInput),\n });\n }\n }\n\n return {\n content,\n finishReason: mapOllamaFinishReason(\n response.done_reason,\n ) as LanguageModelV2FinishReason,\n usage: {\n inputTokens: response.prompt_eval_count || 0,\n outputTokens: response.eval_count || 0,\n totalTokens:\n (response.prompt_eval_count || 0) + (response.eval_count || 0),\n },\n providerMetadata: {\n ollama: {\n model: response.model,\n created_at: response.created_at\n ? new Date(response.created_at).toISOString()\n : undefined,\n total_duration: response.total_duration,\n load_duration: response.load_duration,\n eval_duration: response.eval_duration,\n } as Record<string, JSONValue>,\n },\n request: {\n body: JSON.stringify({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n }),\n },\n response: {\n timestamp: new Date(),\n modelId: this.modelId,\n },\n warnings,\n };\n } catch (error) {\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n rawCall: {\n rawPrompt: unknown;\n rawSettings: Record<string, unknown>;\n };\n warnings?: LanguageModelV2CallWarning[];\n }> {\n const {\n messages,\n options: ollamaOptions,\n format,\n tools,\n warnings,\n } = this.getCallOptions(options);\n\n try {\n const stream = await this.config.client.chat({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n stream: true,\n });\n\n let usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n\n // Capture settings for use in transform function\n const reasoningEnabled = this.settings.reasoning;\n\n const transformStream = new TransformStream<\n ChatResponse,\n LanguageModelV2StreamPart\n >({\n async transform(chunk: ChatResponse, controller) {\n // Validate chunk\n if (!chunk || typeof chunk !== 'object') {\n return; // Skip invalid chunks\n }\n\n // Regular chunk with content\n if (chunk.done) {\n // Final chunk with metadata\n usage = {\n inputTokens: chunk.prompt_eval_count || 0,\n outputTokens: chunk.eval_count || 0,\n totalTokens:\n (chunk.prompt_eval_count || 0) + (chunk.eval_count || 0),\n };\n finishReason = mapOllamaFinishReason(\n chunk.done_reason,\n ) as LanguageModelV2FinishReason;\n\n controller.enqueue({\n type: 'finish',\n finishReason,\n usage,\n });\n } else {\n // Handle reasoning in streaming\n if (chunk.message.thinking && reasoningEnabled) {\n // For reasoning, we'll emit it as a single reasoning content\n // since Ollama doesn't stream reasoning in chunks\n controller.enqueue({\n type: 'reasoning-start',\n id: crypto.randomUUID(),\n });\n\n controller.enqueue({\n type: 'reasoning-delta',\n id: crypto.randomUUID(),\n delta: chunk.message.thinking,\n });\n\n controller.enqueue({\n type: 'reasoning-end',\n id: crypto.randomUUID(),\n });\n }\n\n // Handle tool calls in streaming\n if (\n chunk.message.tool_calls &&\n chunk.message.tool_calls.length > 0\n ) {\n for (const toolCall of chunk.message.tool_calls) {\n const toolInput = toolCall.function.arguments || {};\n\n controller.enqueue({\n type: 'tool-call',\n toolCallId: crypto.randomUUID(), // Ollama doesn't provide IDs\n toolName: toolCall.function.name,\n input: JSON.stringify(toolInput),\n });\n }\n }\n\n // Handle text content in streaming (always emit if present)\n if (\n chunk.message.content &&\n typeof chunk.message.content === 'string' &&\n chunk.message.content.length > 0\n ) {\n controller.enqueue({\n type: 'text-delta',\n id: crypto.randomUUID(), // Generate unique ID for each text chunk\n delta: chunk.message.content,\n });\n }\n }\n },\n });\n\n // Create a readable stream from the async generator\n const readableStream = new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Ensure chunk is valid before enqueuing\n if (chunk && typeof chunk === 'object') {\n controller.enqueue(chunk);\n }\n }\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n\n return {\n stream: readableStream.pipeThrough(transformStream),\n rawCall: {\n rawPrompt: messages,\n rawSettings: {\n model: this.modelId,\n options: ollamaOptions,\n format,\n tools,\n },\n },\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (error) {\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n}\n","import { EmbeddingModelV2, EmbeddingModelV2Embedding } from '@ai-sdk/provider';\nimport { Ollama } from 'ollama';\nimport { OllamaEmbeddingSettings } from '../provider';\nimport { OllamaError } from '../utils/ollama-error';\n\nexport interface OllamaEmbeddingConfig {\n client: Ollama;\n provider: string;\n}\n\nexport class OllamaEmbeddingModel implements EmbeddingModelV2<string> {\n readonly specificationVersion = 'v2' as const;\n readonly modelId: string;\n readonly maxEmbeddingsPerCall = 2048;\n readonly supportsParallelCalls = true;\n\n constructor(\n modelId: string,\n private readonly settings: OllamaEmbeddingSettings,\n private readonly config: OllamaEmbeddingConfig,\n ) {\n this.modelId = modelId;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n async doEmbed(params: {\n values: string[];\n abortSignal?: AbortSignal;\n }): Promise<{\n embeddings: EmbeddingModelV2Embedding[];\n }> {\n const { values, abortSignal } = params;\n if (values.length > this.maxEmbeddingsPerCall) {\n throw new OllamaError({\n message: `Too many values to embed. Maximum: ${this.maxEmbeddingsPerCall}, Received: ${values.length}`,\n });\n }\n\n // Handle empty array case\n if (values.length === 0) {\n return { embeddings: [] };\n }\n\n try {\n const embeddings: EmbeddingModelV2Embedding[] = [];\n\n // Ollama's embed API currently only supports single prompts\n // So we need to make multiple requests\n for (const value of values) {\n // Skip undefined values (AI SDK interface issue workaround)\n if (value === undefined || value === null) {\n continue;\n }\n\n const response = await this.config.client.embed({\n model: this.modelId,\n input: value,\n options: this.settings.options,\n });\n\n if (!response.embeddings) {\n throw new OllamaError({\n message: `No embeddings field in response`,\n });\n }\n\n if (response.embeddings.length === 0) {\n throw new OllamaError({\n message: `Empty embeddings array returned`,\n });\n }\n\n embeddings.push(response.embeddings[0] as number[]);\n\n // Check if we should abort\n if (abortSignal?.aborted) {\n throw new Error('Embedding generation aborted');\n }\n }\n\n if (embeddings.length === 0) {\n throw new OllamaError({\n message: `No valid values provided for embedding (all were undefined/null)`,\n });\n }\n\n return {\n embeddings,\n };\n } catch (error) {\n if (error instanceof OllamaError) {\n throw error;\n }\n\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -46,6 +46,10 @@ interface OllamaChatSettings {
|
|
|
46
46
|
* Enable structured output mode
|
|
47
47
|
*/
|
|
48
48
|
structuredOutputs?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Enable reasoning support for models that support it
|
|
51
|
+
*/
|
|
52
|
+
reasoning?: boolean;
|
|
49
53
|
/**
|
|
50
54
|
* Additional model parameters
|
|
51
55
|
*/
|
|
@@ -133,7 +137,7 @@ declare class OllamaChatLanguageModel implements LanguageModelV2 {
|
|
|
133
137
|
private readonly config;
|
|
134
138
|
readonly specificationVersion: "v2";
|
|
135
139
|
readonly defaultObjectGenerationMode = "json";
|
|
136
|
-
readonly supportsImages =
|
|
140
|
+
readonly supportsImages = true;
|
|
137
141
|
readonly supportsVideoURLs = false;
|
|
138
142
|
readonly supportsAudioURLs = false;
|
|
139
143
|
readonly supportsVideoFile = false;
|
|
@@ -143,6 +147,11 @@ declare class OllamaChatLanguageModel implements LanguageModelV2 {
|
|
|
143
147
|
constructor(modelId: string, settings: OllamaChatSettings, config: OllamaChatConfig);
|
|
144
148
|
get provider(): string;
|
|
145
149
|
get supportsStructuredOutputs(): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Check if structured outputs should be enabled based on the call options
|
|
152
|
+
* This is used internally to auto-detect when structured outputs are needed
|
|
153
|
+
*/
|
|
154
|
+
private shouldEnableStructuredOutputs;
|
|
146
155
|
private getCallOptions;
|
|
147
156
|
doGenerate(options: LanguageModelV2CallOptions): Promise<{
|
|
148
157
|
content: LanguageModelV2Content[];
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,10 @@ interface OllamaChatSettings {
|
|
|
46
46
|
* Enable structured output mode
|
|
47
47
|
*/
|
|
48
48
|
structuredOutputs?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Enable reasoning support for models that support it
|
|
51
|
+
*/
|
|
52
|
+
reasoning?: boolean;
|
|
49
53
|
/**
|
|
50
54
|
* Additional model parameters
|
|
51
55
|
*/
|
|
@@ -133,7 +137,7 @@ declare class OllamaChatLanguageModel implements LanguageModelV2 {
|
|
|
133
137
|
private readonly config;
|
|
134
138
|
readonly specificationVersion: "v2";
|
|
135
139
|
readonly defaultObjectGenerationMode = "json";
|
|
136
|
-
readonly supportsImages =
|
|
140
|
+
readonly supportsImages = true;
|
|
137
141
|
readonly supportsVideoURLs = false;
|
|
138
142
|
readonly supportsAudioURLs = false;
|
|
139
143
|
readonly supportsVideoFile = false;
|
|
@@ -143,6 +147,11 @@ declare class OllamaChatLanguageModel implements LanguageModelV2 {
|
|
|
143
147
|
constructor(modelId: string, settings: OllamaChatSettings, config: OllamaChatConfig);
|
|
144
148
|
get provider(): string;
|
|
145
149
|
get supportsStructuredOutputs(): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Check if structured outputs should be enabled based on the call options
|
|
152
|
+
* This is used internally to auto-detect when structured outputs are needed
|
|
153
|
+
*/
|
|
154
|
+
private shouldEnableStructuredOutputs;
|
|
146
155
|
private getCallOptions;
|
|
147
156
|
doGenerate(options: LanguageModelV2CallOptions): Promise<{
|
|
148
157
|
content: LanguageModelV2Content[];
|
package/dist/index.js
CHANGED
|
@@ -26,27 +26,43 @@ function convertToOllamaChatMessages(prompt) {
|
|
|
26
26
|
const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("\n");
|
|
27
27
|
const imageParts = message.content.filter(
|
|
28
28
|
(part) => part.type === "file"
|
|
29
|
-
).filter((part) =>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
).filter((part) => {
|
|
30
|
+
return part.mediaType?.startsWith("image/") || false;
|
|
31
|
+
}).map((part) => {
|
|
32
|
+
const imageData = part.data;
|
|
33
|
+
if (imageData instanceof URL) {
|
|
34
|
+
if (imageData.protocol === "data:") {
|
|
35
|
+
const base64Match = imageData.href.match(
|
|
36
|
+
/data:[^;]+;base64,(.+)/
|
|
37
|
+
);
|
|
35
38
|
if (base64Match) {
|
|
36
39
|
return base64Match[1];
|
|
37
40
|
}
|
|
41
|
+
return imageData.href;
|
|
38
42
|
}
|
|
39
|
-
return
|
|
40
|
-
} else if (
|
|
41
|
-
|
|
43
|
+
return imageData.href;
|
|
44
|
+
} else if (typeof imageData === "string") {
|
|
45
|
+
if (imageData.startsWith("data:")) {
|
|
46
|
+
const base64Match = imageData.match(/data:[^;]+;base64,(.+)/);
|
|
47
|
+
if (base64Match) {
|
|
48
|
+
return base64Match[1];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return imageData;
|
|
52
|
+
} else if (imageData instanceof Uint8Array) {
|
|
53
|
+
return Buffer.from(imageData).toString("base64");
|
|
42
54
|
} else {
|
|
43
|
-
|
|
55
|
+
console.warn(
|
|
56
|
+
`Unsupported image data type: ${typeof imageData}`
|
|
57
|
+
);
|
|
58
|
+
return null;
|
|
44
59
|
}
|
|
45
|
-
});
|
|
60
|
+
}).filter((img) => img !== null);
|
|
46
61
|
messages.push({
|
|
47
62
|
role: "user",
|
|
48
|
-
content: textParts,
|
|
49
|
-
|
|
63
|
+
content: textParts || "",
|
|
64
|
+
// Ensure content is never undefined
|
|
65
|
+
images: imageParts.length > 0 ? imageParts : void 0
|
|
50
66
|
});
|
|
51
67
|
}
|
|
52
68
|
break;
|
|
@@ -56,7 +72,9 @@ function convertToOllamaChatMessages(prompt) {
|
|
|
56
72
|
if (typeof message.content === "string") {
|
|
57
73
|
content = message.content;
|
|
58
74
|
} else {
|
|
59
|
-
|
|
75
|
+
const textParts = message.content.filter((part) => part.type === "text").map((part) => part.text).join("");
|
|
76
|
+
const reasoningParts = message.content.filter((part) => part.type === "reasoning").map((part) => part.text).join("\n");
|
|
77
|
+
content = [textParts, reasoningParts].filter(Boolean).join("\n");
|
|
60
78
|
const toolCalls = message.content.filter(
|
|
61
79
|
(part) => part.type === "tool-call"
|
|
62
80
|
);
|
|
@@ -70,20 +88,38 @@ ${toolCallText}` : toolCallText;
|
|
|
70
88
|
}
|
|
71
89
|
messages.push({
|
|
72
90
|
role: "assistant",
|
|
73
|
-
content
|
|
91
|
+
content: content || ""
|
|
92
|
+
// Ensure content is never undefined
|
|
74
93
|
});
|
|
75
94
|
break;
|
|
76
95
|
}
|
|
77
96
|
case "tool": {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
97
|
+
if (typeof message.content === "string") {
|
|
98
|
+
messages.push({
|
|
99
|
+
role: "user",
|
|
100
|
+
// Ollama doesn't have native tool role, so we use user
|
|
101
|
+
content: `[Tool Result]: ${message.content}`
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
const toolResultParts = message.content.filter((part) => part.type === "tool-result").map((part) => {
|
|
105
|
+
if (part.output.type === "text") {
|
|
106
|
+
return part.output.value;
|
|
107
|
+
} else if (part.output.type === "json") {
|
|
108
|
+
return JSON.stringify(part.output.value);
|
|
109
|
+
}
|
|
110
|
+
return String(part.output.value);
|
|
111
|
+
}).join("\n");
|
|
112
|
+
messages.push({
|
|
113
|
+
role: "user",
|
|
114
|
+
content: `[Tool Result]: ${toolResultParts || ""}`
|
|
115
|
+
});
|
|
116
|
+
}
|
|
82
117
|
break;
|
|
83
118
|
}
|
|
84
119
|
default: {
|
|
120
|
+
const role = message.role;
|
|
85
121
|
throw new Error(
|
|
86
|
-
`Unsupported message role: ${
|
|
122
|
+
`Unsupported message role: ${role}. Supported roles are: system, user, assistant, tool`
|
|
87
123
|
);
|
|
88
124
|
}
|
|
89
125
|
}
|
|
@@ -135,19 +171,50 @@ var OllamaChatLanguageModel = class {
|
|
|
135
171
|
}
|
|
136
172
|
specificationVersion = "v2";
|
|
137
173
|
defaultObjectGenerationMode = "json";
|
|
138
|
-
supportsImages =
|
|
174
|
+
supportsImages = true;
|
|
175
|
+
// โ
Ollama supports images (URLs, files, base64)
|
|
139
176
|
supportsVideoURLs = false;
|
|
177
|
+
// โ Not supported by Ollama API
|
|
140
178
|
supportsAudioURLs = false;
|
|
179
|
+
// โ Not supported by Ollama API
|
|
141
180
|
supportsVideoFile = false;
|
|
181
|
+
// โ Not supported by Ollama API
|
|
142
182
|
supportsAudioFile = false;
|
|
183
|
+
// โ Not supported by Ollama API
|
|
143
184
|
supportsImageFile = true;
|
|
144
|
-
|
|
185
|
+
// โ
Already correct
|
|
186
|
+
supportedUrls = {
|
|
187
|
+
// Support common image URL patterns
|
|
188
|
+
image: [
|
|
189
|
+
/^https?:\/\/.*\.(jpg|jpeg|png|gif|webp|bmp|svg)(\?.*)?$/i,
|
|
190
|
+
/^data:image\/[^;]+;base64,/i
|
|
191
|
+
// Data URLs
|
|
192
|
+
]
|
|
193
|
+
};
|
|
145
194
|
get provider() {
|
|
146
195
|
return this.config.provider;
|
|
147
196
|
}
|
|
148
197
|
get supportsStructuredOutputs() {
|
|
149
198
|
return this.settings.structuredOutputs ?? false;
|
|
150
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if structured outputs should be enabled based on the call options
|
|
202
|
+
* This is used internally to auto-detect when structured outputs are needed
|
|
203
|
+
*/
|
|
204
|
+
shouldEnableStructuredOutputs(options) {
|
|
205
|
+
if (options.responseFormat?.type === "json" && options.responseFormat.schema) {
|
|
206
|
+
if (this.settings.structuredOutputs === false) {
|
|
207
|
+
console.warn(
|
|
208
|
+
"Ollama: structuredOutputs was set to false but auto-enabled for object generation. This ensures generateObject and streamObject work correctly."
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
if (this.settings.structuredOutputs !== void 0) {
|
|
214
|
+
return this.settings.structuredOutputs;
|
|
215
|
+
}
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
151
218
|
getCallOptions(options) {
|
|
152
219
|
const {
|
|
153
220
|
prompt,
|
|
@@ -163,7 +230,8 @@ var OllamaChatLanguageModel = class {
|
|
|
163
230
|
tools
|
|
164
231
|
} = options;
|
|
165
232
|
const warnings = [];
|
|
166
|
-
|
|
233
|
+
const needsStructuredOutputs = this.shouldEnableStructuredOutputs(options);
|
|
234
|
+
if (responseFormat?.type === "json" && responseFormat.schema && !needsStructuredOutputs) {
|
|
167
235
|
throw new Error(
|
|
168
236
|
"JSON schema is only supported when structuredOutputs is enabled"
|
|
169
237
|
);
|
|
@@ -234,7 +302,7 @@ var OllamaChatLanguageModel = class {
|
|
|
234
302
|
}
|
|
235
303
|
let format;
|
|
236
304
|
if (responseFormat?.type === "json") {
|
|
237
|
-
format = "json";
|
|
305
|
+
format = responseFormat.schema && needsStructuredOutputs ? responseFormat.schema : "json";
|
|
238
306
|
}
|
|
239
307
|
const messages = convertToOllamaChatMessages(prompt);
|
|
240
308
|
return {
|
|
@@ -264,7 +332,11 @@ var OllamaChatLanguageModel = class {
|
|
|
264
332
|
});
|
|
265
333
|
const text = response.message.content;
|
|
266
334
|
const toolCalls = response.message.tool_calls;
|
|
335
|
+
const thinking = response.message.thinking;
|
|
267
336
|
const content = [];
|
|
337
|
+
if (thinking && this.settings.reasoning) {
|
|
338
|
+
content.push({ type: "reasoning", text: thinking });
|
|
339
|
+
}
|
|
268
340
|
if (text) {
|
|
269
341
|
content.push({ type: "text", text });
|
|
270
342
|
}
|
|
@@ -344,6 +416,7 @@ var OllamaChatLanguageModel = class {
|
|
|
344
416
|
totalTokens: 0
|
|
345
417
|
};
|
|
346
418
|
let finishReason = "unknown";
|
|
419
|
+
const reasoningEnabled = this.settings.reasoning;
|
|
347
420
|
const transformStream = new TransformStream({
|
|
348
421
|
async transform(chunk, controller) {
|
|
349
422
|
if (!chunk || typeof chunk !== "object") {
|
|
@@ -364,6 +437,21 @@ var OllamaChatLanguageModel = class {
|
|
|
364
437
|
usage
|
|
365
438
|
});
|
|
366
439
|
} else {
|
|
440
|
+
if (chunk.message.thinking && reasoningEnabled) {
|
|
441
|
+
controller.enqueue({
|
|
442
|
+
type: "reasoning-start",
|
|
443
|
+
id: crypto.randomUUID()
|
|
444
|
+
});
|
|
445
|
+
controller.enqueue({
|
|
446
|
+
type: "reasoning-delta",
|
|
447
|
+
id: crypto.randomUUID(),
|
|
448
|
+
delta: chunk.message.thinking
|
|
449
|
+
});
|
|
450
|
+
controller.enqueue({
|
|
451
|
+
type: "reasoning-end",
|
|
452
|
+
id: crypto.randomUUID()
|
|
453
|
+
});
|
|
454
|
+
}
|
|
367
455
|
if (chunk.message.tool_calls && chunk.message.tool_calls.length > 0) {
|
|
368
456
|
for (const toolCall of chunk.message.tool_calls) {
|
|
369
457
|
const toolInput = toolCall.function.arguments || {};
|
|
@@ -375,7 +463,8 @@ var OllamaChatLanguageModel = class {
|
|
|
375
463
|
input: JSON.stringify(toolInput)
|
|
376
464
|
});
|
|
377
465
|
}
|
|
378
|
-
}
|
|
466
|
+
}
|
|
467
|
+
if (chunk.message.content && typeof chunk.message.content === "string" && chunk.message.content.length > 0) {
|
|
379
468
|
controller.enqueue({
|
|
380
469
|
type: "text-delta",
|
|
381
470
|
id: crypto.randomUUID(),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.ts","../src/utils/convert-to-ollama-messages.ts","../src/utils/map-ollama-finish-reason.ts","../src/utils/ollama-error.ts","../src/models/chat-language-model.ts","../src/models/embedding-model.ts"],"sourcesContent":["import {\n LanguageModelV2,\n EmbeddingModelV2,\n ProviderV2,\n NoSuchModelError,\n} from '@ai-sdk/provider';\nimport { Ollama } from 'ollama';\nimport { OllamaChatLanguageModel } from './models/chat-language-model';\nimport { OllamaEmbeddingModel } from './models/embedding-model';\n\nexport interface OllamaProviderSettings {\n /**\n * Base URL for the Ollama API (defaults to http://127.0.0.1:11434)\n */\n baseURL?: string;\n\n /**\n * Custom headers for API requests\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\nexport interface OllamaProvider extends ProviderV2 {\n /**\n * Create a language model instance\n */\n (modelId: string, settings?: OllamaChatSettings): LanguageModelV2;\n\n /**\n * Create a language model instance with the `chat` method\n */\n chat(modelId: string, settings?: OllamaChatSettings): LanguageModelV2;\n\n /**\n * Create a language model instance with the `languageModel` method\n */\n languageModel(\n modelId: string,\n settings?: OllamaChatSettings,\n ): LanguageModelV2;\n\n /**\n * Create an embedding model instance\n */\n embedding(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n\n /**\n * Create an embedding model instance with the `textEmbedding` method\n */\n textEmbedding(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n\n /**\n * Create an embedding model instance with the `textEmbeddingModel` method\n */\n textEmbeddingModel(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n}\n\nexport interface OllamaChatSettings {\n /**\n * Enable structured output mode\n */\n structuredOutputs?: boolean;\n\n /**\n * Additional model parameters\n */\n options?: {\n num_ctx?: number;\n num_predict?: number;\n temperature?: number;\n top_k?: number;\n top_p?: number;\n min_p?: number;\n seed?: number;\n stop?: string[];\n num_keep?: number;\n typical_p?: number;\n repeat_last_n?: number;\n repeat_penalty?: number;\n presence_penalty?: number;\n frequency_penalty?: number;\n mirostat?: number;\n mirostat_tau?: number;\n mirostat_eta?: number;\n penalize_newline?: boolean;\n numa?: boolean;\n num_thread?: number;\n num_gpu?: number;\n main_gpu?: number;\n low_vram?: boolean;\n f16_kv?: boolean;\n vocab_only?: boolean;\n use_mmap?: boolean;\n use_mlock?: boolean;\n };\n}\n\nexport interface OllamaEmbeddingSettings {\n /**\n * Additional embedding parameters\n */\n options?: {\n num_thread?: number;\n };\n}\n\n/**\n * Options for configuring Ollama provider calls\n */\nexport interface OllamaProviderOptions {\n /**\n * Additional headers to include in requests\n */\n headers?: Record<string, string>;\n}\n\n/**\n * Options for configuring Ollama chat model calls\n */\nexport interface OllamaChatProviderOptions extends OllamaProviderOptions {\n /**\n * Enable structured output mode for object generation\n */\n structuredOutputs?: boolean;\n}\n\n/**\n * Options for configuring Ollama embedding model calls\n */\nexport interface OllamaEmbeddingProviderOptions extends OllamaProviderOptions {\n /**\n * Maximum number of embeddings to process in a single call\n */\n maxEmbeddingsPerCall?: number;\n}\n\n/**\n * Create an Ollama provider instance\n */\nexport function createOllama(\n options: OllamaProviderSettings = {},\n): OllamaProvider {\n const client = new Ollama({\n host: options.baseURL,\n fetch: options.fetch,\n headers: options.headers,\n });\n\n const createChatModel = (\n modelId: string,\n settings: OllamaChatSettings = {},\n ) => {\n return new OllamaChatLanguageModel(modelId, settings, {\n client,\n provider: 'ollama',\n });\n };\n\n const createEmbeddingModel = (\n modelId: string,\n settings: OllamaEmbeddingSettings = {},\n ) => {\n return new OllamaEmbeddingModel(modelId, settings, {\n client,\n provider: 'ollama',\n });\n };\n\n const provider = function (modelId: string, settings?: OllamaChatSettings) {\n if (new.target) {\n throw new Error(\n 'The Ollama provider cannot be called with the new keyword.',\n );\n }\n return createChatModel(modelId, settings);\n };\n\n provider.chat = createChatModel;\n provider.languageModel = createChatModel;\n provider.embedding = createEmbeddingModel;\n provider.textEmbedding = createEmbeddingModel;\n provider.textEmbeddingModel = createEmbeddingModel;\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'imageModel',\n message: 'Image generation is not supported by Ollama',\n });\n };\n\n return provider as OllamaProvider;\n}\n\n/**\n * Default Ollama provider instance\n */\nexport const ollama = createOllama();\n","import { LanguageModelV2Prompt } from '@ai-sdk/provider';\nimport { Message as OllamaMessage } from 'ollama';\n\nexport function convertToOllamaChatMessages(\n prompt: LanguageModelV2Prompt,\n): OllamaMessage[] {\n const messages: OllamaMessage[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case 'system': {\n messages.push({\n role: 'system',\n content: message.content,\n });\n break;\n }\n\n case 'user': {\n if (typeof message.content === 'string') {\n messages.push({\n role: 'user',\n content: message.content,\n });\n } else {\n // Handle multi-part content\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('\\n');\n\n const imageParts = message.content\n .filter(\n (part): part is Extract<typeof part, { type: 'file' }> =>\n part.type === 'file',\n )\n .filter((part) => part.mediaType.startsWith('image/'))\n .map((part) => {\n if (part.data instanceof URL) {\n return part.data.href;\n } else if (typeof part.data === 'string') {\n // If it's already a data URL, extract just the base64 part\n if (part.data.startsWith('data:')) {\n const base64Match = part.data.match(/data:[^;]+;base64,(.+)/);\n if (base64Match) {\n return base64Match[1]; // Return just the base64 part\n }\n }\n return part.data;\n } else if (part.data instanceof Uint8Array) {\n // Handle Uint8Array by converting to base64 (without data URL prefix)\n return Buffer.from(part.data).toString('base64');\n } else {\n // Fallback for other types\n return String(part.data);\n }\n });\n\n messages.push({\n role: 'user',\n content: textParts,\n images:\n imageParts.length > 0\n ? imageParts.filter((img): img is string => img !== undefined)\n : undefined,\n });\n }\n break;\n }\n\n case 'assistant': {\n let content = '';\n\n if (typeof message.content === 'string') {\n content = message.content;\n } else {\n // Combine text parts\n content = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('');\n\n // Handle tool calls if present\n const toolCalls = message.content.filter(\n (part) => part.type === 'tool-call',\n );\n if (toolCalls.length > 0) {\n // For now, we'll append tool calls as text since Ollama doesn't have native support\n const toolCallText = toolCalls\n .map((tc) => `[Tool Call: ${tc.toolName}]`)\n .join('\\n');\n if (toolCallText) {\n content = content ? `${content}\\n${toolCallText}` : toolCallText;\n }\n }\n }\n\n messages.push({\n role: 'assistant',\n content,\n });\n break;\n }\n\n case 'tool': {\n // Ollama doesn't have native tool result support, so we'll add it as a user message\n messages.push({\n role: 'user',\n content: `[Tool Result]`,\n });\n break;\n }\n\n default: {\n // Handle unknown message roles\n throw new Error(\n `Unsupported message role: ${(message as { role: string }).role}`,\n );\n }\n }\n }\n\n return messages;\n}\n","import { LanguageModelV2FinishReason } from '@ai-sdk/provider';\n\nexport function mapOllamaFinishReason(\n reason?: string | null,\n): LanguageModelV2FinishReason {\n if (!reason) return 'unknown';\n\n switch (reason) {\n case 'stop': {\n return 'stop';\n }\n case 'length': {\n return 'length';\n }\n default: {\n return 'unknown';\n }\n }\n}\n","export interface OllamaErrorData {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport class OllamaError extends Error {\n readonly cause?: unknown;\n readonly data?: OllamaErrorData;\n\n constructor({\n message,\n cause,\n data,\n }: {\n message: string;\n cause?: unknown;\n data?: OllamaErrorData;\n }) {\n super(message);\n this.name = 'OllamaError';\n this.cause = cause;\n this.data = data;\n }\n\n static isOllamaError(error: unknown): error is OllamaError {\n return error instanceof OllamaError;\n }\n}\n","import {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2FinishReason,\n LanguageModelV2StreamPart,\n LanguageModelV2Usage,\n LanguageModelV2Content,\n JSONValue,\n} from '@ai-sdk/provider';\nimport { Ollama, Message as OllamaMessage, ChatResponse, Tool } from 'ollama';\nimport { OllamaChatSettings } from '../provider';\nimport { convertToOllamaChatMessages } from '../utils/convert-to-ollama-messages';\nimport { mapOllamaFinishReason } from '../utils/map-ollama-finish-reason';\nimport { OllamaError } from '../utils/ollama-error';\n\nexport interface OllamaChatConfig {\n client: Ollama;\n provider: string;\n}\n\nexport class OllamaChatLanguageModel implements LanguageModelV2 {\n readonly specificationVersion = 'v2' as const;\n readonly defaultObjectGenerationMode = 'json';\n readonly supportsImages = false;\n readonly supportsVideoURLs = false;\n readonly supportsAudioURLs = false;\n readonly supportsVideoFile = false;\n readonly supportsAudioFile = false;\n readonly supportsImageFile = true;\n readonly supportedUrls: Record<string, RegExp[]> = {};\n\n constructor(\n public readonly modelId: string,\n public readonly settings: OllamaChatSettings,\n private readonly config: OllamaChatConfig,\n ) {}\n\n get provider(): string {\n return this.config.provider;\n }\n\n get supportsStructuredOutputs(): boolean {\n return this.settings.structuredOutputs ?? false;\n }\n\n private getCallOptions(options: LanguageModelV2CallOptions): {\n messages: OllamaMessage[];\n options: Record<string, unknown>;\n format?: string;\n tools?: Tool[];\n warnings: LanguageModelV2CallWarning[];\n } {\n const {\n prompt,\n temperature,\n maxOutputTokens,\n topP,\n topK,\n frequencyPenalty,\n presencePenalty,\n stopSequences,\n seed,\n responseFormat,\n tools,\n } = options;\n\n const warnings: LanguageModelV2CallWarning[] = [];\n\n // Check for unsupported features and throw errors\n if (\n responseFormat?.type === 'json' &&\n responseFormat.schema &&\n !this.supportsStructuredOutputs\n ) {\n throw new Error(\n 'JSON schema is only supported when structuredOutputs is enabled',\n );\n }\n\n // Convert AI SDK tools to Ollama format (error already thrown if unsupported)\n const ollamaTools: Tool[] | undefined = tools\n ? tools.map((tool): Tool => {\n if (tool.type === 'function') {\n // The inputSchema from AI SDK should already be a JSON schema\n // when tools are passed to providers\n let jsonSchema: Record<string, unknown>;\n\n // Check if we have a Zod schema (has parse method) or a JSON schema\n if (tool.inputSchema && typeof tool.inputSchema === 'object') {\n if (\n 'parse' in tool.inputSchema &&\n typeof tool.inputSchema.parse === 'function'\n ) {\n // It's a Zod schema - we need to convert it\n // For now, we'll use a basic fallback since zod-to-json-schema has version issues\n console.warn(\n `Tool ${tool.name} is using a Zod schema directly. Schema conversion may not work properly due to Zod version mismatch.`,\n );\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n } else if (\n 'properties' in tool.inputSchema ||\n 'type' in tool.inputSchema\n ) {\n // It looks like a JSON schema already\n jsonSchema = tool.inputSchema as Record<string, unknown>;\n } else {\n // Unknown schema format\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n }\n } else {\n // No schema provided\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n }\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: jsonSchema,\n },\n };\n }\n // Provider-defined tools not supported by Ollama\n throw new Error(\n `Provider-defined tools are not supported by Ollama. Use function tools instead.`,\n );\n })\n : undefined;\n\n // Build options with correct precedence:\n // 1. AI SDK call parameters (mapped to Ollama equivalents)\n // 2. Model settings (Ollama options) override AI SDK parameters when both are specified\n const ollamaOptions: Record<string, unknown> = {\n // Start with AI SDK parameters mapped to Ollama names\n ...(temperature !== undefined && { temperature }),\n ...(maxOutputTokens !== undefined && { num_predict: maxOutputTokens }),\n ...(topP !== undefined && { top_p: topP }),\n ...(topK !== undefined && { top_k: topK }),\n ...(frequencyPenalty !== undefined && {\n frequency_penalty: frequencyPenalty,\n }),\n ...(presencePenalty !== undefined && {\n presence_penalty: presencePenalty,\n }),\n ...(stopSequences !== undefined && { stop: stopSequences }),\n ...(seed !== undefined && { seed }),\n // Ollama model options override AI SDK parameters\n ...this.settings.options,\n };\n\n // Remove undefined values\n for (const key of Object.keys(ollamaOptions)) {\n if (ollamaOptions[key] === undefined) {\n delete ollamaOptions[key];\n }\n }\n\n let format: string | undefined;\n if (responseFormat?.type === 'json') {\n format = 'json';\n }\n\n const messages = convertToOllamaChatMessages(prompt);\n\n return {\n messages,\n options: ollamaOptions,\n format,\n tools: ollamaTools,\n warnings,\n };\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n providerMetadata?: Record<string, Record<string, JSONValue>>;\n request?: { body: string };\n response?: { id?: string; timestamp?: Date; modelId?: string };\n warnings: LanguageModelV2CallWarning[];\n }> {\n const {\n messages,\n options: ollamaOptions,\n format,\n tools,\n warnings,\n } = this.getCallOptions(options);\n\n try {\n const response = (await this.config.client.chat({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n stream: false,\n })) as ChatResponse;\n\n const text = response.message.content;\n const toolCalls = response.message.tool_calls;\n\n // Convert content based on whether we have tool calls\n const content: LanguageModelV2Content[] = [];\n\n if (text) {\n content.push({ type: 'text', text });\n }\n\n if (toolCalls && toolCalls.length > 0) {\n for (const toolCall of toolCalls) {\n const toolInput = toolCall.function.arguments || {};\n\n content.push({\n type: 'tool-call',\n toolCallId: crypto.randomUUID(), // Ollama doesn't provide IDs\n toolName: toolCall.function.name,\n input: JSON.stringify(toolInput),\n });\n }\n }\n\n return {\n content,\n finishReason: mapOllamaFinishReason(\n response.done_reason,\n ) as LanguageModelV2FinishReason,\n usage: {\n inputTokens: response.prompt_eval_count || 0,\n outputTokens: response.eval_count || 0,\n totalTokens:\n (response.prompt_eval_count || 0) + (response.eval_count || 0),\n },\n providerMetadata: {\n ollama: {\n model: response.model,\n created_at: response.created_at\n ? new Date(response.created_at).toISOString()\n : undefined,\n total_duration: response.total_duration,\n load_duration: response.load_duration,\n eval_duration: response.eval_duration,\n } as Record<string, JSONValue>,\n },\n request: {\n body: JSON.stringify({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n }),\n },\n response: {\n timestamp: new Date(),\n modelId: this.modelId,\n },\n warnings,\n };\n } catch (error) {\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n rawCall: {\n rawPrompt: unknown;\n rawSettings: Record<string, unknown>;\n };\n warnings?: LanguageModelV2CallWarning[];\n }> {\n const {\n messages,\n options: ollamaOptions,\n format,\n tools,\n warnings,\n } = this.getCallOptions(options);\n\n try {\n const stream = await this.config.client.chat({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n stream: true,\n });\n\n let usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n\n const transformStream = new TransformStream<\n ChatResponse,\n LanguageModelV2StreamPart\n >({\n async transform(chunk: ChatResponse, controller) {\n // Validate chunk\n if (!chunk || typeof chunk !== 'object') {\n return; // Skip invalid chunks\n }\n\n // Regular chunk with content\n if (chunk.done) {\n // Final chunk with metadata\n usage = {\n inputTokens: chunk.prompt_eval_count || 0,\n outputTokens: chunk.eval_count || 0,\n totalTokens:\n (chunk.prompt_eval_count || 0) + (chunk.eval_count || 0),\n };\n finishReason = mapOllamaFinishReason(\n chunk.done_reason,\n ) as LanguageModelV2FinishReason;\n\n controller.enqueue({\n type: 'finish',\n finishReason,\n usage,\n });\n } else {\n // Handle tool calls in streaming\n if (\n chunk.message.tool_calls &&\n chunk.message.tool_calls.length > 0\n ) {\n for (const toolCall of chunk.message.tool_calls) {\n const toolInput = toolCall.function.arguments || {};\n\n controller.enqueue({\n type: 'tool-call',\n toolCallId: crypto.randomUUID(), // Ollama doesn't provide IDs\n toolName: toolCall.function.name,\n input: JSON.stringify(toolInput),\n });\n }\n } else if (\n chunk.message.content &&\n typeof chunk.message.content === 'string'\n ) {\n controller.enqueue({\n type: 'text-delta',\n id: crypto.randomUUID(), // Generate unique ID for each text chunk\n delta: chunk.message.content,\n });\n }\n }\n },\n });\n\n // Create a readable stream from the async generator\n const readableStream = new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Ensure chunk is valid before enqueuing\n if (chunk && typeof chunk === 'object') {\n controller.enqueue(chunk);\n }\n }\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n\n return {\n stream: readableStream.pipeThrough(transformStream),\n rawCall: {\n rawPrompt: messages,\n rawSettings: {\n model: this.modelId,\n options: ollamaOptions,\n format,\n tools,\n },\n },\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (error) {\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n}\n","import { EmbeddingModelV2, EmbeddingModelV2Embedding } from '@ai-sdk/provider';\nimport { Ollama } from 'ollama';\nimport { OllamaEmbeddingSettings } from '../provider';\nimport { OllamaError } from '../utils/ollama-error';\n\nexport interface OllamaEmbeddingConfig {\n client: Ollama;\n provider: string;\n}\n\nexport class OllamaEmbeddingModel implements EmbeddingModelV2<string> {\n readonly specificationVersion = 'v2' as const;\n readonly modelId: string;\n readonly maxEmbeddingsPerCall = 2048;\n readonly supportsParallelCalls = true;\n\n constructor(\n modelId: string,\n private readonly settings: OllamaEmbeddingSettings,\n private readonly config: OllamaEmbeddingConfig,\n ) {\n this.modelId = modelId;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n async doEmbed(params: {\n values: string[];\n abortSignal?: AbortSignal;\n }): Promise<{\n embeddings: EmbeddingModelV2Embedding[];\n }> {\n const { values, abortSignal } = params;\n if (values.length > this.maxEmbeddingsPerCall) {\n throw new OllamaError({\n message: `Too many values to embed. Maximum: ${this.maxEmbeddingsPerCall}, Received: ${values.length}`,\n });\n }\n\n // Handle empty array case\n if (values.length === 0) {\n return { embeddings: [] };\n }\n\n try {\n const embeddings: EmbeddingModelV2Embedding[] = [];\n\n // Ollama's embed API currently only supports single prompts\n // So we need to make multiple requests\n for (const value of values) {\n // Skip undefined values (AI SDK interface issue workaround)\n if (value === undefined || value === null) {\n continue;\n }\n\n const response = await this.config.client.embed({\n model: this.modelId,\n input: value,\n options: this.settings.options,\n });\n\n if (!response.embeddings) {\n throw new OllamaError({\n message: `No embeddings field in response`,\n });\n }\n\n if (response.embeddings.length === 0) {\n throw new OllamaError({\n message: `Empty embeddings array returned`,\n });\n }\n\n embeddings.push(response.embeddings[0] as number[]);\n\n // Check if we should abort\n if (abortSignal?.aborted) {\n throw new Error('Embedding generation aborted');\n }\n }\n\n if (embeddings.length === 0) {\n throw new OllamaError({\n message: `No valid values provided for embedding (all were undefined/null)`,\n });\n }\n\n return {\n embeddings,\n };\n } catch (error) {\n if (error instanceof OllamaError) {\n throw error;\n }\n\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n}\n"],"mappings":";AAAA;AAAA,EAIE;AAAA,OACK;AACP,SAAS,cAAc;;;ACHhB,SAAS,4BACd,QACiB;AACjB,QAAM,WAA4B,CAAC;AAEnC,aAAW,WAAW,QAAQ;AAC5B,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK,UAAU;AACb,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,SAAS,QAAQ;AAAA,QACnB,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,QAAQ;AACX,YAAI,OAAO,QAAQ,YAAY,UAAU;AACvC,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,SAAS,QAAQ;AAAA,UACnB,CAAC;AAAA,QACH,OAAO;AAEL,gBAAM,YAAY,QAAQ,QACvB,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EACrC,IAAI,CAAC,SAAS,KAAK,IAAI,EACvB,KAAK,IAAI;AAEZ,gBAAM,aAAa,QAAQ,QACxB;AAAA,YACC,CAAC,SACC,KAAK,SAAS;AAAA,UAClB,EACC,OAAO,CAAC,SAAS,KAAK,UAAU,WAAW,QAAQ,CAAC,EACpD,IAAI,CAAC,SAAS;AACb,gBAAI,KAAK,gBAAgB,KAAK;AAC5B,qBAAO,KAAK,KAAK;AAAA,YACnB,WAAW,OAAO,KAAK,SAAS,UAAU;AAExC,kBAAI,KAAK,KAAK,WAAW,OAAO,GAAG;AACjC,sBAAM,cAAc,KAAK,KAAK,MAAM,wBAAwB;AAC5D,oBAAI,aAAa;AACf,yBAAO,YAAY,CAAC;AAAA,gBACtB;AAAA,cACF;AACA,qBAAO,KAAK;AAAA,YACd,WAAW,KAAK,gBAAgB,YAAY;AAE1C,qBAAO,OAAO,KAAK,KAAK,IAAI,EAAE,SAAS,QAAQ;AAAA,YACjD,OAAO;AAEL,qBAAO,OAAO,KAAK,IAAI;AAAA,YACzB;AAAA,UACF,CAAC;AAEH,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,SAAS;AAAA,YACT,QACE,WAAW,SAAS,IAChB,WAAW,OAAO,CAAC,QAAuB,QAAQ,MAAS,IAC3D;AAAA,UACR,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAAA,MAEA,KAAK,aAAa;AAChB,YAAI,UAAU;AAEd,YAAI,OAAO,QAAQ,YAAY,UAAU;AACvC,oBAAU,QAAQ;AAAA,QACpB,OAAO;AAEL,oBAAU,QAAQ,QACf,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EACrC,IAAI,CAAC,SAAS,KAAK,IAAI,EACvB,KAAK,EAAE;AAGV,gBAAM,YAAY,QAAQ,QAAQ;AAAA,YAChC,CAAC,SAAS,KAAK,SAAS;AAAA,UAC1B;AACA,cAAI,UAAU,SAAS,GAAG;AAExB,kBAAM,eAAe,UAClB,IAAI,CAAC,OAAO,eAAe,GAAG,QAAQ,GAAG,EACzC,KAAK,IAAI;AACZ,gBAAI,cAAc;AAChB,wBAAU,UAAU,GAAG,OAAO;AAAA,EAAK,YAAY,KAAK;AAAA,YACtD;AAAA,UACF;AAAA,QACF;AAEA,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,QAAQ;AAEX,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AACD;AAAA,MACF;AAAA,MAEA,SAAS;AAEP,cAAM,IAAI;AAAA,UACR,6BAA8B,QAA6B,IAAI;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ACzHO,SAAS,sBACd,QAC6B;AAC7B,MAAI,CAAC,OAAQ,QAAO;AAEpB,UAAQ,QAAQ;AAAA,IACd,KAAK,QAAQ;AACX,aAAO;AAAA,IACT;AAAA,IACA,KAAK,UAAU;AACb,aAAO;AAAA,IACT;AAAA,IACA,SAAS;AACP,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACZO,IAAM,cAAN,MAAM,qBAAoB,MAAM;AAAA,EAC5B;AAAA,EACA;AAAA,EAET,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,OAAO,cAAc,OAAsC;AACzD,WAAO,iBAAiB;AAAA,EAC1B;AACF;;;ACPO,IAAM,0BAAN,MAAyD;AAAA,EAW9D,YACkB,SACA,UACC,QACjB;AAHgB;AACA;AACC;AAAA,EAChB;AAAA,EAdM,uBAAuB;AAAA,EACvB,8BAA8B;AAAA,EAC9B,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,oBAAoB;AAAA,EACpB,gBAA0C,CAAC;AAAA,EAQpD,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,IAAI,4BAAqC;AACvC,WAAO,KAAK,SAAS,qBAAqB;AAAA,EAC5C;AAAA,EAEQ,eAAe,SAMrB;AACA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI;AAEJ,UAAM,WAAyC,CAAC;AAGhD,QACE,gBAAgB,SAAS,UACzB,eAAe,UACf,CAAC,KAAK,2BACN;AACA,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAGA,UAAM,cAAkC,QACpC,MAAM,IAAI,CAAC,SAAe;AACxB,UAAI,KAAK,SAAS,YAAY;AAG5B,YAAI;AAGJ,YAAI,KAAK,eAAe,OAAO,KAAK,gBAAgB,UAAU;AAC5D,cACE,WAAW,KAAK,eAChB,OAAO,KAAK,YAAY,UAAU,YAClC;AAGA,oBAAQ;AAAA,cACN,QAAQ,KAAK,IAAI;AAAA,YACnB;AACA,yBAAa;AAAA,cACX,MAAM;AAAA,cACN,YAAY,CAAC;AAAA,cACb,sBAAsB;AAAA,YACxB;AAAA,UACF,WACE,gBAAgB,KAAK,eACrB,UAAU,KAAK,aACf;AAEA,yBAAa,KAAK;AAAA,UACpB,OAAO;AAEL,yBAAa;AAAA,cACX,MAAM;AAAA,cACN,YAAY,CAAC;AAAA,cACb,sBAAsB;AAAA,YACxB;AAAA,UACF;AAAA,QACF,OAAO;AAEL,uBAAa;AAAA,YACX,MAAM;AAAA,YACN,YAAY,CAAC;AAAA,YACb,sBAAsB;AAAA,UACxB;AAAA,QACF;AAEA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU;AAAA,YACR,MAAM,KAAK;AAAA,YACX,aAAa,KAAK;AAAA,YAClB,YAAY;AAAA,UACd;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF,CAAC,IACD;AAKJ,UAAM,gBAAyC;AAAA;AAAA,MAE7C,GAAI,gBAAgB,UAAa,EAAE,YAAY;AAAA,MAC/C,GAAI,oBAAoB,UAAa,EAAE,aAAa,gBAAgB;AAAA,MACpE,GAAI,SAAS,UAAa,EAAE,OAAO,KAAK;AAAA,MACxC,GAAI,SAAS,UAAa,EAAE,OAAO,KAAK;AAAA,MACxC,GAAI,qBAAqB,UAAa;AAAA,QACpC,mBAAmB;AAAA,MACrB;AAAA,MACA,GAAI,oBAAoB,UAAa;AAAA,QACnC,kBAAkB;AAAA,MACpB;AAAA,MACA,GAAI,kBAAkB,UAAa,EAAE,MAAM,cAAc;AAAA,MACzD,GAAI,SAAS,UAAa,EAAE,KAAK;AAAA;AAAA,MAEjC,GAAG,KAAK,SAAS;AAAA,IACnB;AAGA,eAAW,OAAO,OAAO,KAAK,aAAa,GAAG;AAC5C,UAAI,cAAc,GAAG,MAAM,QAAW;AACpC,eAAO,cAAc,GAAG;AAAA,MAC1B;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,gBAAgB,SAAS,QAAQ;AACnC,eAAS;AAAA,IACX;AAEA,UAAM,WAAW,4BAA4B,MAAM;AAEnD,WAAO;AAAA,MACL;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA,OAAO;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAQd;AACD,UAAM;AAAA,MACJ;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,KAAK,eAAe,OAAO;AAE/B,QAAI;AACF,YAAM,WAAY,MAAM,KAAK,OAAO,OAAO,KAAK;AAAA,QAC9C,OAAO,KAAK;AAAA,QACZ;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,YAAM,OAAO,SAAS,QAAQ;AAC9B,YAAM,YAAY,SAAS,QAAQ;AAGnC,YAAM,UAAoC,CAAC;AAE3C,UAAI,MAAM;AACR,gBAAQ,KAAK,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,MACrC;AAEA,UAAI,aAAa,UAAU,SAAS,GAAG;AACrC,mBAAW,YAAY,WAAW;AAChC,gBAAM,YAAY,SAAS,SAAS,aAAa,CAAC;AAElD,kBAAQ,KAAK;AAAA,YACX,MAAM;AAAA,YACN,YAAY,OAAO,WAAW;AAAA;AAAA,YAC9B,UAAU,SAAS,SAAS;AAAA,YAC5B,OAAO,KAAK,UAAU,SAAS;AAAA,UACjC,CAAC;AAAA,QACH;AAAA,MACF;AAEA,aAAO;AAAA,QACL;AAAA,QACA,cAAc;AAAA,UACZ,SAAS;AAAA,QACX;AAAA,QACA,OAAO;AAAA,UACL,aAAa,SAAS,qBAAqB;AAAA,UAC3C,cAAc,SAAS,cAAc;AAAA,UACrC,cACG,SAAS,qBAAqB,MAAM,SAAS,cAAc;AAAA,QAChE;AAAA,QACA,kBAAkB;AAAA,UAChB,QAAQ;AAAA,YACN,OAAO,SAAS;AAAA,YAChB,YAAY,SAAS,aACjB,IAAI,KAAK,SAAS,UAAU,EAAE,YAAY,IAC1C;AAAA,YACJ,gBAAgB,SAAS;AAAA,YACzB,eAAe,SAAS;AAAA,YACxB,eAAe,SAAS;AAAA,UAC1B;AAAA,QACF;AAAA,QACA,SAAS;AAAA,UACP,MAAM,KAAK,UAAU;AAAA,YACnB,OAAO,KAAK;AAAA,YACZ;AAAA,YACA,SAAS;AAAA,YACT;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAAA,QACA,UAAU;AAAA,UACR,WAAW,oBAAI,KAAK;AAAA,UACpB,SAAS,KAAK;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,SAOZ;AACD,UAAM;AAAA,MACJ;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,KAAK,eAAe,OAAO;AAE/B,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,OAAO,OAAO,KAAK;AAAA,QAC3C,OAAO,KAAK;AAAA,QACZ;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA,QAAQ;AAAA,MACV,CAAC;AAED,UAAI,QAA8B;AAAA,QAChC,aAAa;AAAA,QACb,cAAc;AAAA,QACd,aAAa;AAAA,MACf;AACA,UAAI,eAA4C;AAEhD,YAAM,kBAAkB,IAAI,gBAG1B;AAAA,QACA,MAAM,UAAU,OAAqB,YAAY;AAE/C,cAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC;AAAA,UACF;AAGA,cAAI,MAAM,MAAM;AAEd,oBAAQ;AAAA,cACN,aAAa,MAAM,qBAAqB;AAAA,cACxC,cAAc,MAAM,cAAc;AAAA,cAClC,cACG,MAAM,qBAAqB,MAAM,MAAM,cAAc;AAAA,YAC1D;AACA,2BAAe;AAAA,cACb,MAAM;AAAA,YACR;AAEA,uBAAW,QAAQ;AAAA,cACjB,MAAM;AAAA,cACN;AAAA,cACA;AAAA,YACF,CAAC;AAAA,UACH,OAAO;AAEL,gBACE,MAAM,QAAQ,cACd,MAAM,QAAQ,WAAW,SAAS,GAClC;AACA,yBAAW,YAAY,MAAM,QAAQ,YAAY;AAC/C,sBAAM,YAAY,SAAS,SAAS,aAAa,CAAC;AAElD,2BAAW,QAAQ;AAAA,kBACjB,MAAM;AAAA,kBACN,YAAY,OAAO,WAAW;AAAA;AAAA,kBAC9B,UAAU,SAAS,SAAS;AAAA,kBAC5B,OAAO,KAAK,UAAU,SAAS;AAAA,gBACjC,CAAC;AAAA,cACH;AAAA,YACF,WACE,MAAM,QAAQ,WACd,OAAO,MAAM,QAAQ,YAAY,UACjC;AACA,yBAAW,QAAQ;AAAA,gBACjB,MAAM;AAAA,gBACN,IAAI,OAAO,WAAW;AAAA;AAAA,gBACtB,OAAO,MAAM,QAAQ;AAAA,cACvB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAGD,YAAM,iBAAiB,IAAI,eAAe;AAAA,QACxC,MAAM,MAAM,YAAY;AACtB,cAAI;AACF,6BAAiB,SAAS,QAAQ;AAEhC,kBAAI,SAAS,OAAO,UAAU,UAAU;AACtC,2BAAW,QAAQ,KAAK;AAAA,cAC1B;AAAA,YACF;AACA,uBAAW,MAAM;AAAA,UACnB,SAAS,OAAO;AACd,uBAAW,MAAM,KAAK;AAAA,UACxB;AAAA,QACF;AAAA,MACF,CAAC;AAED,aAAO;AAAA,QACL,QAAQ,eAAe,YAAY,eAAe;AAAA,QAClD,SAAS;AAAA,UACP,WAAW;AAAA,UACX,aAAa;AAAA,YACX,OAAO,KAAK;AAAA,YACZ,SAAS;AAAA,YACT;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,QACA,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,MAC7C;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AChZO,IAAM,uBAAN,MAA+D;AAAA,EAMpE,YACE,SACiB,UACA,QACjB;AAFiB;AACA;AAEjB,SAAK,UAAU;AAAA,EACjB;AAAA,EAXS,uBAAuB;AAAA,EACvB;AAAA,EACA,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EAUjC,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,MAAM,QAAQ,QAKX;AACD,UAAM,EAAE,QAAQ,YAAY,IAAI;AAChC,QAAI,OAAO,SAAS,KAAK,sBAAsB;AAC7C,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS,sCAAsC,KAAK,oBAAoB,eAAe,OAAO,MAAM;AAAA,MACtG,CAAC;AAAA,IACH;AAGA,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO,EAAE,YAAY,CAAC,EAAE;AAAA,IAC1B;AAEA,QAAI;AACF,YAAM,aAA0C,CAAC;AAIjD,iBAAW,SAAS,QAAQ;AAE1B,YAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,QACF;AAEA,cAAM,WAAW,MAAM,KAAK,OAAO,OAAO,MAAM;AAAA,UAC9C,OAAO,KAAK;AAAA,UACZ,OAAO;AAAA,UACP,SAAS,KAAK,SAAS;AAAA,QACzB,CAAC;AAED,YAAI,CAAC,SAAS,YAAY;AACxB,gBAAM,IAAI,YAAY;AAAA,YACpB,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAEA,YAAI,SAAS,WAAW,WAAW,GAAG;AACpC,gBAAM,IAAI,YAAY;AAAA,YACpB,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAEA,mBAAW,KAAK,SAAS,WAAW,CAAC,CAAa;AAGlD,YAAI,aAAa,SAAS;AACxB,gBAAM,IAAI,MAAM,8BAA8B;AAAA,QAChD;AAAA,MACF;AAEA,UAAI,WAAW,WAAW,GAAG;AAC3B,cAAM,IAAI,YAAY;AAAA,UACpB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM;AAAA,MACR;AAEA,YAAM,IAAI,YAAY;AAAA,QACpB,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ALkDO,SAAS,aACd,UAAkC,CAAC,GACnB;AAChB,QAAM,SAAS,IAAI,OAAO;AAAA,IACxB,MAAM,QAAQ;AAAA,IACd,OAAO,QAAQ;AAAA,IACf,SAAS,QAAQ;AAAA,EACnB,CAAC;AAED,QAAM,kBAAkB,CACtB,SACA,WAA+B,CAAC,MAC7B;AACH,WAAO,IAAI,wBAAwB,SAAS,UAAU;AAAA,MACpD;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,QAAM,uBAAuB,CAC3B,SACA,WAAoC,CAAC,MAClC;AACH,WAAO,IAAI,qBAAqB,SAAS,UAAU;AAAA,MACjD;AAAA,MACA,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,SAAU,SAAiB,UAA+B;AACzE,QAAI,YAAY;AACd,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO,gBAAgB,SAAS,QAAQ;AAAA,EAC1C;AAEA,WAAS,OAAO;AAChB,WAAS,gBAAgB;AACzB,WAAS,YAAY;AACrB,WAAS,gBAAgB;AACzB,WAAS,qBAAqB;AAC9B,WAAS,aAAa,CAAC,YAAoB;AACzC,UAAM,IAAI,iBAAiB;AAAA,MACzB;AAAA,MACA,WAAW;AAAA,MACX,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKO,IAAM,SAAS,aAAa;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.ts","../src/utils/convert-to-ollama-messages.ts","../src/utils/map-ollama-finish-reason.ts","../src/utils/ollama-error.ts","../src/models/chat-language-model.ts","../src/models/embedding-model.ts"],"sourcesContent":["import {\n LanguageModelV2,\n EmbeddingModelV2,\n ProviderV2,\n NoSuchModelError,\n} from '@ai-sdk/provider';\nimport { Ollama } from 'ollama';\nimport { OllamaChatLanguageModel } from './models/chat-language-model';\nimport { OllamaEmbeddingModel } from './models/embedding-model';\n\nexport interface OllamaProviderSettings {\n /**\n * Base URL for the Ollama API (defaults to http://127.0.0.1:11434)\n */\n baseURL?: string;\n\n /**\n * Custom headers for API requests\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof fetch;\n}\n\nexport interface OllamaProvider extends ProviderV2 {\n /**\n * Create a language model instance\n */\n (modelId: string, settings?: OllamaChatSettings): LanguageModelV2;\n\n /**\n * Create a language model instance with the `chat` method\n */\n chat(modelId: string, settings?: OllamaChatSettings): LanguageModelV2;\n\n /**\n * Create a language model instance with the `languageModel` method\n */\n languageModel(\n modelId: string,\n settings?: OllamaChatSettings,\n ): LanguageModelV2;\n\n /**\n * Create an embedding model instance\n */\n embedding(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n\n /**\n * Create an embedding model instance with the `textEmbedding` method\n */\n textEmbedding(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n\n /**\n * Create an embedding model instance with the `textEmbeddingModel` method\n */\n textEmbeddingModel(\n modelId: string,\n settings?: OllamaEmbeddingSettings,\n ): EmbeddingModelV2<string>;\n}\n\nexport interface OllamaChatSettings {\n /**\n * Enable structured output mode\n */\n structuredOutputs?: boolean;\n\n /**\n * Enable reasoning support for models that support it\n */\n reasoning?: boolean;\n\n /**\n * Additional model parameters\n */\n options?: {\n num_ctx?: number;\n num_predict?: number;\n temperature?: number;\n top_k?: number;\n top_p?: number;\n min_p?: number;\n seed?: number;\n stop?: string[];\n num_keep?: number;\n typical_p?: number;\n repeat_last_n?: number;\n repeat_penalty?: number;\n presence_penalty?: number;\n frequency_penalty?: number;\n mirostat?: number;\n mirostat_tau?: number;\n mirostat_eta?: number;\n penalize_newline?: boolean;\n numa?: boolean;\n num_thread?: number;\n num_gpu?: number;\n main_gpu?: number;\n low_vram?: boolean;\n f16_kv?: boolean;\n vocab_only?: boolean;\n use_mmap?: boolean;\n use_mlock?: boolean;\n };\n}\n\nexport interface OllamaEmbeddingSettings {\n /**\n * Additional embedding parameters\n */\n options?: {\n num_thread?: number;\n };\n}\n\n/**\n * Options for configuring Ollama provider calls\n */\nexport interface OllamaProviderOptions {\n /**\n * Additional headers to include in requests\n */\n headers?: Record<string, string>;\n}\n\n/**\n * Options for configuring Ollama chat model calls\n */\nexport interface OllamaChatProviderOptions extends OllamaProviderOptions {\n /**\n * Enable structured output mode for object generation\n */\n structuredOutputs?: boolean;\n}\n\n/**\n * Options for configuring Ollama embedding model calls\n */\nexport interface OllamaEmbeddingProviderOptions extends OllamaProviderOptions {\n /**\n * Maximum number of embeddings to process in a single call\n */\n maxEmbeddingsPerCall?: number;\n}\n\n/**\n * Create an Ollama provider instance\n */\nexport function createOllama(\n options: OllamaProviderSettings = {},\n): OllamaProvider {\n const client = new Ollama({\n host: options.baseURL,\n fetch: options.fetch,\n headers: options.headers,\n });\n\n const createChatModel = (\n modelId: string,\n settings: OllamaChatSettings = {},\n ) => {\n return new OllamaChatLanguageModel(modelId, settings, {\n client,\n provider: 'ollama',\n });\n };\n\n const createEmbeddingModel = (\n modelId: string,\n settings: OllamaEmbeddingSettings = {},\n ) => {\n return new OllamaEmbeddingModel(modelId, settings, {\n client,\n provider: 'ollama',\n });\n };\n\n const provider = function (modelId: string, settings?: OllamaChatSettings) {\n if (new.target) {\n throw new Error(\n 'The Ollama provider cannot be called with the new keyword.',\n );\n }\n return createChatModel(modelId, settings);\n };\n\n provider.chat = createChatModel;\n provider.languageModel = createChatModel;\n provider.embedding = createEmbeddingModel;\n provider.textEmbedding = createEmbeddingModel;\n provider.textEmbeddingModel = createEmbeddingModel;\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'imageModel',\n message: 'Image generation is not supported by Ollama',\n });\n };\n\n return provider as OllamaProvider;\n}\n\n/**\n * Default Ollama provider instance\n */\nexport const ollama = createOllama();\n","import { LanguageModelV2Prompt } from '@ai-sdk/provider';\nimport { Message as OllamaMessage } from 'ollama';\n\n/**\n * Enhanced message conversion that supports all Ollama capabilities\n * and handles edge cases better than the referenced implementation\n */\nexport function convertToOllamaChatMessages(\n prompt: LanguageModelV2Prompt,\n): OllamaMessage[] {\n const messages: OllamaMessage[] = [];\n\n for (const message of prompt) {\n switch (message.role) {\n case 'system': {\n messages.push({\n role: 'system',\n content: message.content,\n });\n break;\n }\n\n case 'user': {\n if (typeof message.content === 'string') {\n messages.push({\n role: 'user',\n content: message.content,\n });\n } else {\n // Handle multi-part content with enhanced image support\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('\\n');\n\n const imageParts = message.content\n .filter(\n (part): part is Extract<typeof part, { type: 'file' }> =>\n part.type === 'file',\n )\n .filter((part) => {\n // Support image files only\n return part.mediaType?.startsWith('image/') || false;\n })\n .map((part) => {\n const imageData = part.data;\n\n if (imageData instanceof URL) {\n // Handle image URLs - extract base64 from data URLs or use URL directly\n if (imageData.protocol === 'data:') {\n const base64Match = imageData.href.match(\n /data:[^;]+;base64,(.+)/,\n );\n if (base64Match) {\n return base64Match[1]; // Return just the base64 part\n }\n // If no base64 match, return the full data URL\n return imageData.href;\n }\n // For HTTP URLs, return as-is (Ollama will handle them)\n return imageData.href;\n } else if (typeof imageData === 'string') {\n // Handle base64 strings\n if (imageData.startsWith('data:')) {\n const base64Match = imageData.match(/data:[^;]+;base64,(.+)/);\n if (base64Match) {\n return base64Match[1]; // Return just the base64 part\n }\n }\n return imageData;\n } else if (imageData instanceof Uint8Array) {\n // Handle Uint8Array by converting to base64\n return Buffer.from(imageData).toString('base64');\n } else {\n // Fallback for other types\n console.warn(\n `Unsupported image data type: ${typeof imageData}`,\n );\n return null;\n }\n })\n .filter((img): img is string => img !== null);\n\n messages.push({\n role: 'user',\n content: textParts || '', // Ensure content is never undefined\n images: imageParts.length > 0 ? imageParts : undefined,\n });\n }\n break;\n }\n\n case 'assistant': {\n let content = '';\n\n if (typeof message.content === 'string') {\n content = message.content;\n } else {\n // Enhanced content handling with better tool call support\n const textParts = message.content\n .filter((part) => part.type === 'text')\n .map((part) => part.text)\n .join('');\n\n const reasoningParts = message.content\n .filter((part) => part.type === 'reasoning')\n .map((part) => part.text)\n .join('\\n');\n\n // Combine text and reasoning\n content = [textParts, reasoningParts].filter(Boolean).join('\\n');\n\n // Handle tool calls if present\n const toolCalls = message.content.filter(\n (part) => part.type === 'tool-call',\n );\n if (toolCalls.length > 0) {\n // For now, we'll append tool calls as text since Ollama doesn't have native support\n const toolCallText = toolCalls\n .map((tc) => `[Tool Call: ${tc.toolName}]`)\n .join('\\n');\n if (toolCallText) {\n content = content ? `${content}\\n${toolCallText}` : toolCallText;\n }\n }\n }\n\n messages.push({\n role: 'assistant',\n content: content || '', // Ensure content is never undefined\n });\n break;\n }\n\n case 'tool': {\n // Enhanced tool result handling\n if (typeof message.content === 'string') {\n messages.push({\n role: 'user', // Ollama doesn't have native tool role, so we use user\n content: `[Tool Result]: ${message.content}`,\n });\n } else {\n // Handle multi-part tool results\n const toolResultParts = message.content\n .filter((part) => part.type === 'tool-result')\n .map((part) => {\n if (part.output.type === 'text') {\n return part.output.value;\n } else if (part.output.type === 'json') {\n return JSON.stringify(part.output.value);\n }\n return String(part.output.value);\n })\n .join('\\n');\n\n messages.push({\n role: 'user',\n content: `[Tool Result]: ${toolResultParts || ''}`,\n });\n }\n break;\n }\n\n default: {\n // Enhanced error handling with more descriptive messages\n const role = (message as { role: string }).role;\n throw new Error(\n `Unsupported message role: ${role}. Supported roles are: system, user, assistant, tool`,\n );\n }\n }\n }\n\n return messages;\n}\n","import { LanguageModelV2FinishReason } from '@ai-sdk/provider';\n\nexport function mapOllamaFinishReason(\n reason?: string | null,\n): LanguageModelV2FinishReason {\n if (!reason) return 'unknown';\n\n switch (reason) {\n case 'stop': {\n return 'stop';\n }\n case 'length': {\n return 'length';\n }\n default: {\n return 'unknown';\n }\n }\n}\n","export interface OllamaErrorData {\n message: string;\n code?: string;\n details?: unknown;\n}\n\nexport class OllamaError extends Error {\n readonly cause?: unknown;\n readonly data?: OllamaErrorData;\n\n constructor({\n message,\n cause,\n data,\n }: {\n message: string;\n cause?: unknown;\n data?: OllamaErrorData;\n }) {\n super(message);\n this.name = 'OllamaError';\n this.cause = cause;\n this.data = data;\n }\n\n static isOllamaError(error: unknown): error is OllamaError {\n return error instanceof OllamaError;\n }\n}\n","import {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2FinishReason,\n LanguageModelV2StreamPart,\n LanguageModelV2Usage,\n LanguageModelV2Content,\n JSONValue,\n} from '@ai-sdk/provider';\nimport { Ollama, Message as OllamaMessage, ChatResponse, Tool } from 'ollama';\nimport { OllamaChatSettings } from '../provider';\nimport { convertToOllamaChatMessages } from '../utils/convert-to-ollama-messages';\nimport { mapOllamaFinishReason } from '../utils/map-ollama-finish-reason';\nimport { OllamaError } from '../utils/ollama-error';\n\nexport interface OllamaChatConfig {\n client: Ollama;\n provider: string;\n}\n\nexport class OllamaChatLanguageModel implements LanguageModelV2 {\n readonly specificationVersion = 'v2' as const;\n readonly defaultObjectGenerationMode = 'json';\n readonly supportsImages = true; // โ
Ollama supports images (URLs, files, base64)\n readonly supportsVideoURLs = false; // โ Not supported by Ollama API\n readonly supportsAudioURLs = false; // โ Not supported by Ollama API\n readonly supportsVideoFile = false; // โ Not supported by Ollama API\n readonly supportsAudioFile = false; // โ Not supported by Ollama API\n readonly supportsImageFile = true; // โ
Already correct\n readonly supportedUrls: Record<string, RegExp[]> = {\n // Support common image URL patterns\n image: [\n /^https?:\\/\\/.*\\.(jpg|jpeg|png|gif|webp|bmp|svg)(\\?.*)?$/i,\n /^data:image\\/[^;]+;base64,/i, // Data URLs\n ],\n };\n\n constructor(\n public readonly modelId: string,\n public readonly settings: OllamaChatSettings,\n private readonly config: OllamaChatConfig,\n ) {}\n\n get provider(): string {\n return this.config.provider;\n }\n\n get supportsStructuredOutputs(): boolean {\n // Auto-detect structured outputs when JSON schema is provided\n // This allows generateObject and streamObject to work without explicit structuredOutputs: true\n return this.settings.structuredOutputs ?? false;\n }\n\n /**\n * Check if structured outputs should be enabled based on the call options\n * This is used internally to auto-detect when structured outputs are needed\n */\n private shouldEnableStructuredOutputs(\n options: LanguageModelV2CallOptions,\n ): boolean {\n // Auto-detect: if we have a JSON schema, we need structured outputs\n // This overrides explicit settings to ensure object generation works\n if (\n options.responseFormat?.type === 'json' &&\n options.responseFormat.schema\n ) {\n // Warn if structuredOutputs was explicitly set to false but we're auto-enabling it\n if (this.settings.structuredOutputs === false) {\n console.warn(\n 'Ollama: structuredOutputs was set to false but auto-enabled for object generation. ' +\n 'This ensures generateObject and streamObject work correctly.',\n );\n }\n return true;\n }\n\n // If explicitly set, use that value (for text generation)\n if (this.settings.structuredOutputs !== undefined) {\n return this.settings.structuredOutputs;\n }\n\n // Default to false for regular text generation\n return false;\n }\n\n private getCallOptions(options: LanguageModelV2CallOptions): {\n messages: OllamaMessage[];\n options: Record<string, unknown>;\n format?: string | Record<string, unknown>;\n tools?: Tool[];\n warnings: LanguageModelV2CallWarning[];\n } {\n const {\n prompt,\n temperature,\n maxOutputTokens,\n topP,\n topK,\n frequencyPenalty,\n presencePenalty,\n stopSequences,\n seed,\n responseFormat,\n tools,\n } = options;\n\n const warnings: LanguageModelV2CallWarning[] = [];\n\n // Auto-detect structured outputs when JSON schema is provided\n const needsStructuredOutputs = this.shouldEnableStructuredOutputs(options);\n\n // Check for unsupported features and throw errors\n if (\n responseFormat?.type === 'json' &&\n responseFormat.schema &&\n !needsStructuredOutputs\n ) {\n throw new Error(\n 'JSON schema is only supported when structuredOutputs is enabled',\n );\n }\n\n // Convert AI SDK tools to Ollama format (error already thrown if unsupported)\n const ollamaTools: Tool[] | undefined = tools\n ? tools.map((tool): Tool => {\n if (tool.type === 'function') {\n // The inputSchema from AI SDK should already be a JSON schema\n // when tools are passed to providers\n let jsonSchema: Record<string, unknown>;\n\n // Check if we have a Zod schema (has parse method) or a JSON schema\n if (tool.inputSchema && typeof tool.inputSchema === 'object') {\n if (\n 'parse' in tool.inputSchema &&\n typeof tool.inputSchema.parse === 'function'\n ) {\n // It's a Zod schema - we need to convert it\n // For now, we'll use a basic fallback since zod-to-json-schema has version issues\n console.warn(\n `Tool ${tool.name} is using a Zod schema directly. Schema conversion may not work properly due to Zod version mismatch.`,\n );\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n } else if (\n 'properties' in tool.inputSchema ||\n 'type' in tool.inputSchema\n ) {\n // It looks like a JSON schema already\n jsonSchema = tool.inputSchema as Record<string, unknown>;\n } else {\n // Unknown schema format\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n }\n } else {\n // No schema provided\n jsonSchema = {\n type: 'object',\n properties: {},\n additionalProperties: false,\n };\n }\n\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: jsonSchema,\n },\n };\n }\n // Provider-defined tools not supported by Ollama\n throw new Error(\n `Provider-defined tools are not supported by Ollama. Use function tools instead.`,\n );\n })\n : undefined;\n\n // Build options with correct precedence:\n // 1. AI SDK call parameters (mapped to Ollama equivalents)\n // 2. Model settings (Ollama options) override AI SDK parameters when both are specified\n const ollamaOptions: Record<string, unknown> = {\n // Start with AI SDK parameters mapped to Ollama names\n ...(temperature !== undefined && { temperature }),\n ...(maxOutputTokens !== undefined && { num_predict: maxOutputTokens }),\n ...(topP !== undefined && { top_p: topP }),\n ...(topK !== undefined && { top_k: topK }),\n ...(frequencyPenalty !== undefined && {\n frequency_penalty: frequencyPenalty,\n }),\n ...(presencePenalty !== undefined && {\n presence_penalty: presencePenalty,\n }),\n ...(stopSequences !== undefined && { stop: stopSequences }),\n ...(seed !== undefined && { seed }),\n // Ollama model options override AI SDK parameters\n ...this.settings.options,\n };\n\n // Remove undefined values\n for (const key of Object.keys(ollamaOptions)) {\n if (ollamaOptions[key] === undefined) {\n delete ollamaOptions[key];\n }\n }\n\n let format: string | Record<string, unknown> | undefined;\n if (responseFormat?.type === 'json') {\n format =\n responseFormat.schema && needsStructuredOutputs\n ? (responseFormat.schema as Record<string, unknown>)\n : 'json';\n }\n\n const messages = convertToOllamaChatMessages(prompt);\n\n return {\n messages,\n options: ollamaOptions,\n format,\n tools: ollamaTools,\n warnings,\n };\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<{\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n providerMetadata?: Record<string, Record<string, JSONValue>>;\n request?: { body: string };\n response?: { id?: string; timestamp?: Date; modelId?: string };\n warnings: LanguageModelV2CallWarning[];\n }> {\n const {\n messages,\n options: ollamaOptions,\n format,\n tools,\n warnings,\n } = this.getCallOptions(options);\n\n try {\n const response = (await this.config.client.chat({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n stream: false,\n })) as ChatResponse;\n\n const text = response.message.content;\n const toolCalls = response.message.tool_calls;\n const thinking = response.message.thinking;\n\n // Convert content based on whether we have tool calls, reasoning, or text\n const content: LanguageModelV2Content[] = [];\n\n // Add reasoning content if present and enabled\n if (thinking && this.settings.reasoning) {\n content.push({ type: 'reasoning', text: thinking });\n }\n\n // Add text content if present\n if (text) {\n content.push({ type: 'text', text });\n }\n\n // Add tool calls if present\n if (toolCalls && toolCalls.length > 0) {\n for (const toolCall of toolCalls) {\n const toolInput = toolCall.function.arguments || {};\n\n content.push({\n type: 'tool-call',\n toolCallId: crypto.randomUUID(), // Ollama doesn't provide IDs\n toolName: toolCall.function.name,\n input: JSON.stringify(toolInput),\n });\n }\n }\n\n return {\n content,\n finishReason: mapOllamaFinishReason(\n response.done_reason,\n ) as LanguageModelV2FinishReason,\n usage: {\n inputTokens: response.prompt_eval_count || 0,\n outputTokens: response.eval_count || 0,\n totalTokens:\n (response.prompt_eval_count || 0) + (response.eval_count || 0),\n },\n providerMetadata: {\n ollama: {\n model: response.model,\n created_at: response.created_at\n ? new Date(response.created_at).toISOString()\n : undefined,\n total_duration: response.total_duration,\n load_duration: response.load_duration,\n eval_duration: response.eval_duration,\n } as Record<string, JSONValue>,\n },\n request: {\n body: JSON.stringify({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n }),\n },\n response: {\n timestamp: new Date(),\n modelId: this.modelId,\n },\n warnings,\n };\n } catch (error) {\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n rawCall: {\n rawPrompt: unknown;\n rawSettings: Record<string, unknown>;\n };\n warnings?: LanguageModelV2CallWarning[];\n }> {\n const {\n messages,\n options: ollamaOptions,\n format,\n tools,\n warnings,\n } = this.getCallOptions(options);\n\n try {\n const stream = await this.config.client.chat({\n model: this.modelId,\n messages,\n options: ollamaOptions,\n format,\n tools,\n stream: true,\n });\n\n let usage: LanguageModelV2Usage = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n };\n let finishReason: LanguageModelV2FinishReason = 'unknown';\n\n // Capture settings for use in transform function\n const reasoningEnabled = this.settings.reasoning;\n\n const transformStream = new TransformStream<\n ChatResponse,\n LanguageModelV2StreamPart\n >({\n async transform(chunk: ChatResponse, controller) {\n // Validate chunk\n if (!chunk || typeof chunk !== 'object') {\n return; // Skip invalid chunks\n }\n\n // Regular chunk with content\n if (chunk.done) {\n // Final chunk with metadata\n usage = {\n inputTokens: chunk.prompt_eval_count || 0,\n outputTokens: chunk.eval_count || 0,\n totalTokens:\n (chunk.prompt_eval_count || 0) + (chunk.eval_count || 0),\n };\n finishReason = mapOllamaFinishReason(\n chunk.done_reason,\n ) as LanguageModelV2FinishReason;\n\n controller.enqueue({\n type: 'finish',\n finishReason,\n usage,\n });\n } else {\n // Handle reasoning in streaming\n if (chunk.message.thinking && reasoningEnabled) {\n // For reasoning, we'll emit it as a single reasoning content\n // since Ollama doesn't stream reasoning in chunks\n controller.enqueue({\n type: 'reasoning-start',\n id: crypto.randomUUID(),\n });\n\n controller.enqueue({\n type: 'reasoning-delta',\n id: crypto.randomUUID(),\n delta: chunk.message.thinking,\n });\n\n controller.enqueue({\n type: 'reasoning-end',\n id: crypto.randomUUID(),\n });\n }\n\n // Handle tool calls in streaming\n if (\n chunk.message.tool_calls &&\n chunk.message.tool_calls.length > 0\n ) {\n for (const toolCall of chunk.message.tool_calls) {\n const toolInput = toolCall.function.arguments || {};\n\n controller.enqueue({\n type: 'tool-call',\n toolCallId: crypto.randomUUID(), // Ollama doesn't provide IDs\n toolName: toolCall.function.name,\n input: JSON.stringify(toolInput),\n });\n }\n }\n\n // Handle text content in streaming (always emit if present)\n if (\n chunk.message.content &&\n typeof chunk.message.content === 'string' &&\n chunk.message.content.length > 0\n ) {\n controller.enqueue({\n type: 'text-delta',\n id: crypto.randomUUID(), // Generate unique ID for each text chunk\n delta: chunk.message.content,\n });\n }\n }\n },\n });\n\n // Create a readable stream from the async generator\n const readableStream = new ReadableStream({\n async start(controller) {\n try {\n for await (const chunk of stream) {\n // Ensure chunk is valid before enqueuing\n if (chunk && typeof chunk === 'object') {\n controller.enqueue(chunk);\n }\n }\n controller.close();\n } catch (error) {\n controller.error(error);\n }\n },\n });\n\n return {\n stream: readableStream.pipeThrough(transformStream),\n rawCall: {\n rawPrompt: messages,\n rawSettings: {\n model: this.modelId,\n options: ollamaOptions,\n format,\n tools,\n },\n },\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (error) {\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n}\n","import { EmbeddingModelV2, EmbeddingModelV2Embedding } from '@ai-sdk/provider';\nimport { Ollama } from 'ollama';\nimport { OllamaEmbeddingSettings } from '../provider';\nimport { OllamaError } from '../utils/ollama-error';\n\nexport interface OllamaEmbeddingConfig {\n client: Ollama;\n provider: string;\n}\n\nexport class OllamaEmbeddingModel implements EmbeddingModelV2<string> {\n readonly specificationVersion = 'v2' as const;\n readonly modelId: string;\n readonly maxEmbeddingsPerCall = 2048;\n readonly supportsParallelCalls = true;\n\n constructor(\n modelId: string,\n private readonly settings: OllamaEmbeddingSettings,\n private readonly config: OllamaEmbeddingConfig,\n ) {\n this.modelId = modelId;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n async doEmbed(params: {\n values: string[];\n abortSignal?: AbortSignal;\n }): Promise<{\n embeddings: EmbeddingModelV2Embedding[];\n }> {\n const { values, abortSignal } = params;\n if (values.length > this.maxEmbeddingsPerCall) {\n throw new OllamaError({\n message: `Too many values to embed. Maximum: ${this.maxEmbeddingsPerCall}, Received: ${values.length}`,\n });\n }\n\n // Handle empty array case\n if (values.length === 0) {\n return { embeddings: [] };\n }\n\n try {\n const embeddings: EmbeddingModelV2Embedding[] = [];\n\n // Ollama's embed API currently only supports single prompts\n // So we need to make multiple requests\n for (const value of values) {\n // Skip undefined values (AI SDK interface issue workaround)\n if (value === undefined || value === null) {\n continue;\n }\n\n const response = await this.config.client.embed({\n model: this.modelId,\n input: value,\n options: this.settings.options,\n });\n\n if (!response.embeddings) {\n throw new OllamaError({\n message: `No embeddings field in response`,\n });\n }\n\n if (response.embeddings.length === 0) {\n throw new OllamaError({\n message: `Empty embeddings array returned`,\n });\n }\n\n embeddings.push(response.embeddings[0] as number[]);\n\n // Check if we should abort\n if (abortSignal?.aborted) {\n throw new Error('Embedding generation aborted');\n }\n }\n\n if (embeddings.length === 0) {\n throw new OllamaError({\n message: `No valid values provided for embedding (all were undefined/null)`,\n });\n }\n\n return {\n embeddings,\n };\n } catch (error) {\n if (error instanceof OllamaError) {\n throw error;\n }\n\n throw new OllamaError({\n message: error instanceof Error ? error.message : String(error),\n cause: error,\n });\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-sdk-ollama",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vercel AI SDK Provider for Ollama using official ollama-js library",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -82,9 +82,11 @@
|
|
|
82
82
|
"format": "prettier --write .",
|
|
83
83
|
"format:check": "prettier --check src/**/*.ts",
|
|
84
84
|
"type-check": "tsc --noEmit",
|
|
85
|
-
"test": "
|
|
86
|
-
"test:
|
|
87
|
-
"test:
|
|
85
|
+
"test": "vitest run --config vitest.unit.config.ts",
|
|
86
|
+
"test:watch": "vitest --config vitest.unit.config.ts",
|
|
87
|
+
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
88
|
+
"test:integration:watch": "vitest --config vitest.integration.config.ts",
|
|
89
|
+
"test:all": "npm run test && npm run test:integration",
|
|
88
90
|
"check-format": "prettier --check .",
|
|
89
91
|
"check-exports": "attw --pack . --ignore-rules false-esm no-resolution",
|
|
90
92
|
"local-release": "npm run ci && changeset version && changeset publish --access public"
|