ollama-ai-provider-v2 1.6.0-beta.0 → 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -7,6 +7,20 @@ Use Ollama with the Vercel AI SDK, implementing the official Ollama API. This pr
7
7
  [![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
8
8
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-yellow.svg)](https://opensource.org/licenses/Apache-2.0)
9
9
 
10
+ ## 🎉 AI SDK 6 Beta Support
11
+
12
+ This provider now supports **AI SDK 6 Beta** features including:
13
+
14
+ - **🤖 Agent Abstraction** - Build complex agents with `ToolLoopAgent`
15
+ - **🔐 Tool Approval** - Request user confirmation before executing tools
16
+ - **📊 Structured Output** - Generate typed data alongside tool calling
17
+ - **⚡ Enhanced Performance** - Optimized for the latest AI SDK features
18
+
19
+ ```bash
20
+ # Install AI SDK 6 Beta + Ollama Provider
21
+ npm install ai@beta ollama-ai-provider-v2
22
+ ```
23
+
10
24
  ## Why Choose Ollama Provider V2?
11
25
 
12
26
  - ✅ **Minimal Dependencies** - Lean codebase with just 2 core dependencies
@@ -82,19 +96,11 @@ const { text, toolCalls } = await generateText({
82
96
  Unique feature for models that support chain-of-thought reasoning:
83
97
 
84
98
  ```typescript
85
- // For most models - simple boolean
86
99
  const { text } = await generateText({
87
100
  model: ollama('deepseek-r1:7b'),
88
101
  providerOptions: { ollama: { think: true } },
89
102
  prompt: 'Solve this complex math problem step by step: 2x + 5 = 17',
90
103
  });
91
-
92
- // For GPT-OSS models - use thinking levels for trace length control
93
- const { text } = await generateText({
94
- model: ollama('gpt-oss:7b'),
95
- providerOptions: { ollama: { think: 'high' } }, // 'low', 'medium', or 'high'
96
- prompt: 'Analyze this complex scenario in detail',
97
- });
98
104
  ```
99
105
 
100
106
  ### Advanced Ollama Options
@@ -182,7 +188,7 @@ Works with any model in your Ollama installation, including:
182
188
 
183
189
  - **Chat Models**: `llama3.2`, `mistral`, `phi4-mini`, `qwen2.5`, `codellama`, `gemma3`
184
190
  - **Vision Models**: `llava`, `llama3.2-vision`, `minicpm-v`
185
- - **Reasoning Models**: `deepseek-r1:7b`, `deepseek-r1:1.5b`, `deepseek-r1:8b`, `gpt-oss:7b`
191
+ - **Reasoning Models**: `deepseek-r1:7b`, `deepseek-r1:1.5b`, `deepseek-r1:8b`
186
192
  - **Code Models**: `codellama:code`, `codellama:python`, `deepseek-coder-v2`
187
193
  - **Embedding Models**: `nomic-embed-text`, `all-minilm`, `mxbai-embed-large`
188
194
 
@@ -200,6 +206,147 @@ ollama serve
200
206
  ollama pull llama3.2
201
207
  ```
202
208
 
209
+ # AI SDK 6 Beta examples
210
+ ## Agent Abstraction
211
+
212
+ AI SDK 6 introduces the `ToolLoopAgent` class for building agents with full control over execution flow.
213
+
214
+ ### Basic Agent
215
+
216
+ ```typescript
217
+ import { ToolLoopAgent } from 'ai';
218
+ import { ollama } from 'ollama-ai-provider-v2';
219
+
220
+ const weatherAgent = new ToolLoopAgent({
221
+ model: ollama('llama3.3:70b'),
222
+ instructions: 'You are a helpful weather assistant.',
223
+ tools: {
224
+ weather: weatherTool,
225
+ },
226
+ });
227
+
228
+ const result = await weatherAgent.generate({
229
+ prompt: 'What is the weather in San Francisco?',
230
+ });
231
+ ```
232
+
233
+ ### Agent with Call Options
234
+
235
+ Use call options to pass runtime configuration to agents:
236
+
237
+ ```typescript
238
+ import { ToolLoopAgent } from 'ai';
239
+ import { ollama } from 'ollama-ai-provider-v2';
240
+ import { z } from 'zod';
241
+
242
+ const supportAgent = new ToolLoopAgent({
243
+ model: ollama('qwen2.5:32b'),
244
+ callOptionsSchema: z.object({
245
+ userId: z.string(),
246
+ accountType: z.enum(['free', 'pro', 'enterprise']),
247
+ }),
248
+ instructions: 'You are a helpful customer support agent.',
249
+ prepareCall: ({ options, ...settings }) => ({
250
+ ...settings,
251
+ instructions: `${settings.instructions}
252
+
253
+ User context:
254
+ - Account type: ${options.accountType}
255
+ - User ID: ${options.userId}
256
+
257
+ Adjust your response based on the user's account level.`,
258
+ }),
259
+ });
260
+
261
+ const result = await supportAgent.generate({
262
+ prompt: 'How do I upgrade my account?',
263
+ options: {
264
+ userId: 'user_123',
265
+ accountType: 'free',
266
+ },
267
+ });
268
+ ```
269
+
270
+ ## Tool Execution Approval
271
+
272
+ AI SDK 6 allows you to require user approval before executing tools.
273
+
274
+ ### Basic Tool Approval
275
+
276
+ ```typescript
277
+ import { tool } from 'ai';
278
+ import { z } from 'zod';
279
+
280
+ export const weatherTool = tool({
281
+ description: 'Get the weather in a location',
282
+ inputSchema: z.object({
283
+ city: z.string(),
284
+ }),
285
+ needsApproval: true, // Always require approval
286
+ execute: async ({ city }) => {
287
+ const weather = await fetchWeather(city);
288
+ return weather;
289
+ },
290
+ });
291
+ ```
292
+
293
+ ### Dynamic Approval
294
+
295
+ Make approval decisions based on tool input:
296
+
297
+ ```typescript
298
+ export const paymentTool = tool({
299
+ description: 'Process a payment',
300
+ inputSchema: z.object({
301
+ amount: z.number(),
302
+ recipient: z.string(),
303
+ }),
304
+ needsApproval: async ({ amount }) => amount > 1000, // Only large payments
305
+ execute: async ({ amount, recipient }) => {
306
+ return await processPayment(amount, recipient);
307
+ },
308
+ });
309
+ ```
310
+
311
+ ## UI Integration
312
+
313
+ ### Server-side API Route
314
+
315
+ ```typescript
316
+ import { createAgentUIStreamResponse } from 'ai';
317
+ import { weatherAgent } from '@/lib/agents';
318
+
319
+ export async function POST(request: Request) {
320
+ const { messages } = await request.json();
321
+
322
+ return createAgentUIStreamResponse({
323
+ agent: weatherAgent,
324
+ messages,
325
+ });
326
+ }
327
+ ```
328
+
329
+ ### Client-side with Type Safety
330
+
331
+ ```typescript
332
+ import { useChat } from '@ai-sdk/react';
333
+ import { InferAgentUIMessage } from 'ai';
334
+ import { weatherAgent } from '@/lib/agents';
335
+
336
+ type WeatherAgentUIMessage = InferAgentUIMessage<typeof weatherAgent>;
337
+
338
+ export function WeatherChat() {
339
+ const { messages, sendMessage } = useChat<WeatherAgentUIMessage>();
340
+
341
+ return (
342
+ <div>
343
+ {/* Your chat UI */}
344
+ </div>
345
+ );
346
+ }
347
+ ```
348
+
349
+
203
350
  ## Contributing
204
351
 
205
352
  Contributions are welcome! Here's how to get started:
package/dist/index.d.mts CHANGED
@@ -4,11 +4,7 @@ import { z } from 'zod/v4';
4
4
 
5
5
  type OllamaChatModelId = "athene-v2" | "athene-v2:72b" | "aya-expanse" | "aya-expanse:8b" | "aya-expanse:32b" | "codegemma" | "codegemma:2b" | "codegemma:7b" | "codellama" | "codellama:7b" | "codellama:13b" | "codellama:34b" | "codellama:70b" | "codellama:code" | "codellama:python" | "command-r" | "command-r:35b" | "command-r-plus" | "command-r-plus:104b" | "command-r7b" | "command-r7b:7b" | "deepseek-r1" | "deepseek-r1:1.5b" | "deepseek-r1:7b" | "deepseek-r1:8b" | "deepseek-r1:14b" | "deepseek-r1:32b" | "deepseek-r1:70b" | "deepseek-r1:671b" | "deepseek-coder-v2" | "deepseek-coder-v2:16b" | "deepseek-coder-v2:236b" | "deepseek-v3" | "deepseek-v3:671b" | "devstral" | "devstral:24b" | "dolphin3" | "dolphin3:8b" | "exaone3.5" | "exaone3.5:2.4b" | "exaone3.5:7.8b" | "exaone3.5:32b" | "falcon2" | "falcon2:11b" | "falcon3" | "falcon3:1b" | "falcon3:3b" | "falcon3:7b" | "falcon3:10b" | "firefunction-v2" | "firefunction-v2:70b" | "gemma" | "gemma:2b" | "gemma:7b" | "gemma2" | "gemma2:2b" | "gemma2:9b" | "gemma2:27b" | "gemma3" | "gemma3:1b" | "gemma3:4b" | "gemma3:12b" | "gemma3:27b" | "granite3-dense" | "granite3-dense:2b" | "granite3-dense:8b" | "granite3-guardian" | "granite3-guardian:2b" | "granite3-guardian:8b" | "granite3-moe" | "granite3-moe:1b" | "granite3-moe:3b" | "granite3.1-dense" | "granite3.1-dense:2b" | "granite3.1-dense:8b" | "granite3.1-moe" | "granite3.1-moe:1b" | "granite3.1-moe:3b" | "llama2" | "llama2:7b" | "llama2:13b" | "llama2:70b" | "llama3" | "llama3:8b" | "llama3:70b" | "llama3-chatqa" | "llama3-chatqa:8b" | "llama3-chatqa:70b" | "llama3-gradient" | "llama3-gradient:8b" | "llama3-gradient:70b" | "llama3.1" | "llama3.1:8b" | "llama3.1:70b" | "llama3.1:405b" | "llama3.2" | "llama3.2:1b" | "llama3.2:3b" | "llama3.2-vision" | "llama3.2-vision:11b" | "llama3.2-vision:90b" | "llama3.3" | "llama3.3:70b" | "llama4" | "llama4:16x17b" | "llama4:128x17b" | "llama-guard3" | "llama-guard3:1b" | "llama-guard3:8b" | "llava" | "llava:7b" | "llava:13b" | "llava:34b" | "llava-llama3" | "llava-llama3:8b" | "llava-phi3" | "llava-phi3:3.8b" | "marco-o1" | "marco-o1:7b" | "mistral" | "mistral:7b" | "mistral-large" | "mistral-large:123b" | "mistral-nemo" | "mistral-nemo:12b" | "mistral-small" | "mistral-small:22b" | "mixtral" | "mixtral:8x7b" | "mixtral:8x22b" | "moondream" | "moondream:1.8b" | "openhermes" | "openhermes:v2.5" | "nemotron" | "nemotron:70b" | "nemotron-mini" | "nemotron-mini:4b" | "olmo" | "olmo:7b" | "olmo:13b" | "opencoder" | "opencoder:1.5b" | "opencoder:8b" | "phi3" | "phi3:3.8b" | "phi3:14b" | "phi3.5" | "phi3.5:3.8b" | "phi4" | "phi4:14b" | "qwen" | "qwen:7b" | "qwen:14b" | "qwen:32b" | "qwen:72b" | "qwen:110b" | "qwen2" | "qwen2:0.5b" | "qwen2:1.5b" | "qwen2:7b" | "qwen2:72b" | "qwen2.5" | "qwen2.5:0.5b" | "qwen2.5:1.5b" | "qwen2.5:3b" | "qwen2.5:7b" | "qwen2.5:14b" | "qwen2.5:32b" | "qwen2.5:72b" | "qwen2.5-coder" | "qwen2.5-coder:0.5b" | "qwen2.5-coder:1.5b" | "qwen2.5-coder:3b" | "qwen2.5-coder:7b" | "qwen2.5-coder:14b" | "qwen2.5-coder:32b" | "qwen3" | "qwen3:0.6b" | "qwen3:1.7b" | "qwen3:4b" | "qwen3:8b" | "qwen3:14b" | "qwen3:30b" | "qwen3:32b" | "qwen3:235b" | "qwq" | "qwq:32b" | "sailor2" | "sailor2:1b" | "sailor2:8b" | "sailor2:20b" | "shieldgemma" | "shieldgemma:2b" | "shieldgemma:9b" | "shieldgemma:27b" | "smallthinker" | "smallthinker:3b" | "smollm" | "smollm:135m" | "smollm:360m" | "smollm:1.7b" | "tinyllama" | "tinyllama:1.1b" | "tulu3" | "tulu3:8b" | "tulu3:70b" | (string & {});
6
6
  declare const ollamaProviderOptions: z.ZodObject<{
7
- think: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
8
- low: "low";
9
- medium: "medium";
10
- high: "high";
11
- }>]>>;
7
+ think: z.ZodOptional<z.ZodBoolean>;
12
8
  options: z.ZodOptional<z.ZodObject<{
13
9
  num_ctx: z.ZodOptional<z.ZodNumber>;
14
10
  repeat_last_n: z.ZodOptional<z.ZodNumber>;
@@ -31,12 +27,9 @@ interface OllamaCompletionSettings {
31
27
  * the model's thinking from the model's output. When disabled, the model will not think
32
28
  * and directly output the content.
33
29
  *
34
- * For GPT-OSS models: accepts "low", "medium", or "high" to tune trace length.
35
- * For other models: accepts boolean true/false.
36
- *
37
- * Only supported by certain models like DeepSeek R1, Qwen 3, and GPT-OSS.
30
+ * Only supported by certain models like DeepSeek R1 and Qwen 3.
38
31
  */
39
- think?: boolean | "low" | "medium" | "high";
32
+ think?: boolean;
40
33
  /**
41
34
  * Echo back the prompt in addition to the completion.
42
35
  */
@@ -153,11 +146,7 @@ declare const ollamaEmbeddingProviderOptions: z.ZodObject<{
153
146
  type OllamaEmbeddingProviderOptions = z.infer<typeof ollamaEmbeddingProviderOptions>;
154
147
 
155
148
  declare const ollamaCompletionProviderOptions: z.ZodObject<{
156
- think: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
157
- low: "low";
158
- medium: "medium";
159
- high: "high";
160
- }>]>>;
149
+ think: z.ZodOptional<z.ZodBoolean>;
161
150
  user: z.ZodOptional<z.ZodString>;
162
151
  suffix: z.ZodOptional<z.ZodString>;
163
152
  echo: z.ZodOptional<z.ZodBoolean>;
package/dist/index.d.ts CHANGED
@@ -4,11 +4,7 @@ import { z } from 'zod/v4';
4
4
 
5
5
  type OllamaChatModelId = "athene-v2" | "athene-v2:72b" | "aya-expanse" | "aya-expanse:8b" | "aya-expanse:32b" | "codegemma" | "codegemma:2b" | "codegemma:7b" | "codellama" | "codellama:7b" | "codellama:13b" | "codellama:34b" | "codellama:70b" | "codellama:code" | "codellama:python" | "command-r" | "command-r:35b" | "command-r-plus" | "command-r-plus:104b" | "command-r7b" | "command-r7b:7b" | "deepseek-r1" | "deepseek-r1:1.5b" | "deepseek-r1:7b" | "deepseek-r1:8b" | "deepseek-r1:14b" | "deepseek-r1:32b" | "deepseek-r1:70b" | "deepseek-r1:671b" | "deepseek-coder-v2" | "deepseek-coder-v2:16b" | "deepseek-coder-v2:236b" | "deepseek-v3" | "deepseek-v3:671b" | "devstral" | "devstral:24b" | "dolphin3" | "dolphin3:8b" | "exaone3.5" | "exaone3.5:2.4b" | "exaone3.5:7.8b" | "exaone3.5:32b" | "falcon2" | "falcon2:11b" | "falcon3" | "falcon3:1b" | "falcon3:3b" | "falcon3:7b" | "falcon3:10b" | "firefunction-v2" | "firefunction-v2:70b" | "gemma" | "gemma:2b" | "gemma:7b" | "gemma2" | "gemma2:2b" | "gemma2:9b" | "gemma2:27b" | "gemma3" | "gemma3:1b" | "gemma3:4b" | "gemma3:12b" | "gemma3:27b" | "granite3-dense" | "granite3-dense:2b" | "granite3-dense:8b" | "granite3-guardian" | "granite3-guardian:2b" | "granite3-guardian:8b" | "granite3-moe" | "granite3-moe:1b" | "granite3-moe:3b" | "granite3.1-dense" | "granite3.1-dense:2b" | "granite3.1-dense:8b" | "granite3.1-moe" | "granite3.1-moe:1b" | "granite3.1-moe:3b" | "llama2" | "llama2:7b" | "llama2:13b" | "llama2:70b" | "llama3" | "llama3:8b" | "llama3:70b" | "llama3-chatqa" | "llama3-chatqa:8b" | "llama3-chatqa:70b" | "llama3-gradient" | "llama3-gradient:8b" | "llama3-gradient:70b" | "llama3.1" | "llama3.1:8b" | "llama3.1:70b" | "llama3.1:405b" | "llama3.2" | "llama3.2:1b" | "llama3.2:3b" | "llama3.2-vision" | "llama3.2-vision:11b" | "llama3.2-vision:90b" | "llama3.3" | "llama3.3:70b" | "llama4" | "llama4:16x17b" | "llama4:128x17b" | "llama-guard3" | "llama-guard3:1b" | "llama-guard3:8b" | "llava" | "llava:7b" | "llava:13b" | "llava:34b" | "llava-llama3" | "llava-llama3:8b" | "llava-phi3" | "llava-phi3:3.8b" | "marco-o1" | "marco-o1:7b" | "mistral" | "mistral:7b" | "mistral-large" | "mistral-large:123b" | "mistral-nemo" | "mistral-nemo:12b" | "mistral-small" | "mistral-small:22b" | "mixtral" | "mixtral:8x7b" | "mixtral:8x22b" | "moondream" | "moondream:1.8b" | "openhermes" | "openhermes:v2.5" | "nemotron" | "nemotron:70b" | "nemotron-mini" | "nemotron-mini:4b" | "olmo" | "olmo:7b" | "olmo:13b" | "opencoder" | "opencoder:1.5b" | "opencoder:8b" | "phi3" | "phi3:3.8b" | "phi3:14b" | "phi3.5" | "phi3.5:3.8b" | "phi4" | "phi4:14b" | "qwen" | "qwen:7b" | "qwen:14b" | "qwen:32b" | "qwen:72b" | "qwen:110b" | "qwen2" | "qwen2:0.5b" | "qwen2:1.5b" | "qwen2:7b" | "qwen2:72b" | "qwen2.5" | "qwen2.5:0.5b" | "qwen2.5:1.5b" | "qwen2.5:3b" | "qwen2.5:7b" | "qwen2.5:14b" | "qwen2.5:32b" | "qwen2.5:72b" | "qwen2.5-coder" | "qwen2.5-coder:0.5b" | "qwen2.5-coder:1.5b" | "qwen2.5-coder:3b" | "qwen2.5-coder:7b" | "qwen2.5-coder:14b" | "qwen2.5-coder:32b" | "qwen3" | "qwen3:0.6b" | "qwen3:1.7b" | "qwen3:4b" | "qwen3:8b" | "qwen3:14b" | "qwen3:30b" | "qwen3:32b" | "qwen3:235b" | "qwq" | "qwq:32b" | "sailor2" | "sailor2:1b" | "sailor2:8b" | "sailor2:20b" | "shieldgemma" | "shieldgemma:2b" | "shieldgemma:9b" | "shieldgemma:27b" | "smallthinker" | "smallthinker:3b" | "smollm" | "smollm:135m" | "smollm:360m" | "smollm:1.7b" | "tinyllama" | "tinyllama:1.1b" | "tulu3" | "tulu3:8b" | "tulu3:70b" | (string & {});
6
6
  declare const ollamaProviderOptions: z.ZodObject<{
7
- think: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
8
- low: "low";
9
- medium: "medium";
10
- high: "high";
11
- }>]>>;
7
+ think: z.ZodOptional<z.ZodBoolean>;
12
8
  options: z.ZodOptional<z.ZodObject<{
13
9
  num_ctx: z.ZodOptional<z.ZodNumber>;
14
10
  repeat_last_n: z.ZodOptional<z.ZodNumber>;
@@ -31,12 +27,9 @@ interface OllamaCompletionSettings {
31
27
  * the model's thinking from the model's output. When disabled, the model will not think
32
28
  * and directly output the content.
33
29
  *
34
- * For GPT-OSS models: accepts "low", "medium", or "high" to tune trace length.
35
- * For other models: accepts boolean true/false.
36
- *
37
- * Only supported by certain models like DeepSeek R1, Qwen 3, and GPT-OSS.
30
+ * Only supported by certain models like DeepSeek R1 and Qwen 3.
38
31
  */
39
- think?: boolean | "low" | "medium" | "high";
32
+ think?: boolean;
40
33
  /**
41
34
  * Echo back the prompt in addition to the completion.
42
35
  */
@@ -153,11 +146,7 @@ declare const ollamaEmbeddingProviderOptions: z.ZodObject<{
153
146
  type OllamaEmbeddingProviderOptions = z.infer<typeof ollamaEmbeddingProviderOptions>;
154
147
 
155
148
  declare const ollamaCompletionProviderOptions: z.ZodObject<{
156
- think: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodEnum<{
157
- low: "low";
158
- medium: "medium";
159
- high: "high";
160
- }>]>>;
149
+ think: z.ZodOptional<z.ZodBoolean>;
161
150
  user: z.ZodOptional<z.ZodString>;
162
151
  suffix: z.ZodOptional<z.ZodString>;
163
152
  echo: z.ZodOptional<z.ZodBoolean>;
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ var import_provider_utils8 = require("@ai-sdk/provider-utils");
31
31
 
32
32
  // src/completion/ollama-completion-language-model.ts
33
33
  var import_provider_utils2 = require("@ai-sdk/provider-utils");
34
- var import_v43 = require("zod/v4");
34
+ var import_v42 = require("zod/v4");
35
35
 
36
36
  // src/completion/ollama-error.ts
37
37
  var import_v4 = require("zod/v4");
@@ -156,63 +156,38 @@ function getResponseMetadata({
156
156
  };
157
157
  }
158
158
 
159
- // src/ollama-chat-settings.ts
160
- var import_v42 = require("zod/v4");
161
- var ollamaProviderOptions = import_v42.z.object({
162
- /**
163
- * Enable or disable the model's thinking process. When enabled, the output will separate
164
- * the model's thinking from the model's output. When disabled, the model will not think
165
- * and directly output the content.
166
- *
167
- * For GPT-OSS models: accepts "low", "medium", or "high" to tune trace length.
168
- * For other models: accepts boolean true/false.
169
- *
170
- * Only supported by certain models like DeepSeek R1, Qwen 3, and GPT-OSS.
171
- */
172
- think: import_v42.z.union([
173
- import_v42.z.boolean(),
174
- import_v42.z.enum(["low", "medium", "high"])
175
- ]).optional(),
176
- options: import_v42.z.object({
177
- num_ctx: import_v42.z.number().optional(),
178
- repeat_last_n: import_v42.z.number().optional(),
179
- repeat_penalty: import_v42.z.number().optional(),
180
- temperature: import_v42.z.number().optional(),
181
- seed: import_v42.z.number().optional(),
182
- stop: import_v42.z.array(import_v42.z.string()).optional(),
183
- num_predict: import_v42.z.number().optional(),
184
- top_k: import_v42.z.number().optional(),
185
- top_p: import_v42.z.number().optional(),
186
- min_p: import_v42.z.number().optional()
187
- }).optional()
188
- });
189
- function validateThinkParameter(modelId, think) {
190
- if (think === void 0) {
191
- return void 0;
192
- }
193
- const isGptOss = modelId.toLowerCase().includes("gpt-oss");
194
- if (isGptOss) {
195
- if (typeof think === "boolean") {
196
- return think ? "medium" : void 0;
197
- }
198
- return think;
199
- } else {
200
- if (typeof think === "string") {
201
- return think !== void 0;
159
+ // src/completion/ollama-completion-language-model.ts
160
+ function createJsonStreamResponseHandler(schema) {
161
+ return async ({ response }) => {
162
+ if (!response.body) {
163
+ throw new Error("Response body is null");
202
164
  }
203
- return think;
204
- }
165
+ const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new TransformStream({
166
+ transform(chunk, controller) {
167
+ const lines = chunk.split("\n");
168
+ for (const line of lines) {
169
+ if (line.trim()) {
170
+ const result = (0, import_provider_utils2.safeParseJSON)({ text: line.trim(), schema });
171
+ controller.enqueue(result);
172
+ }
173
+ }
174
+ }
175
+ }));
176
+ const responseHeaders = {};
177
+ response.headers.forEach((value, key) => {
178
+ responseHeaders[key] = value;
179
+ });
180
+ return {
181
+ value: stream,
182
+ responseHeaders
183
+ };
184
+ };
205
185
  }
206
-
207
- // src/completion/ollama-completion-language-model.ts
208
- var ollamaCompletionProviderOptions = import_v43.z.object({
209
- think: import_v43.z.union([
210
- import_v43.z.boolean(),
211
- import_v43.z.enum(["low", "medium", "high"])
212
- ]).optional(),
213
- user: import_v43.z.string().optional(),
214
- suffix: import_v43.z.string().optional(),
215
- echo: import_v43.z.boolean().optional()
186
+ var ollamaCompletionProviderOptions = import_v42.z.object({
187
+ think: import_v42.z.boolean().optional(),
188
+ user: import_v42.z.string().optional(),
189
+ suffix: import_v42.z.string().optional(),
190
+ echo: import_v42.z.boolean().optional()
216
191
  });
217
192
  var OllamaCompletionLanguageModel = class {
218
193
  constructor(modelId, settings, config) {
@@ -270,14 +245,13 @@ var OllamaCompletionLanguageModel = class {
270
245
  }
271
246
  const { prompt: completionPrompt, stopSequences } = convertToOllamaCompletionPrompt({ prompt });
272
247
  const stop = [...stopSequences != null ? stopSequences : [], ...userStopSequences != null ? userStopSequences : []];
273
- const validatedThink = validateThinkParameter(this.modelId, ollamaOptions.think);
274
248
  return {
275
249
  args: {
276
250
  // model id:
277
251
  model: this.modelId,
278
252
  // Ollama-supported settings:
279
253
  user: ollamaOptions.user,
280
- think: validatedThink,
254
+ think: ollamaOptions.think,
281
255
  // standardized settings:
282
256
  max_tokens: maxOutputTokens,
283
257
  temperature,
@@ -356,7 +330,7 @@ var OllamaCompletionLanguageModel = class {
356
330
  headers: (0, import_provider_utils2.combineHeaders)(this.config.headers(), options.headers),
357
331
  body,
358
332
  failedResponseHandler: ollamaFailedResponseHandler,
359
- successfulResponseHandler: (0, import_provider_utils2.createJsonStreamResponseHandler)(
333
+ successfulResponseHandler: createJsonStreamResponseHandler(
360
334
  baseOllamaResponseSchema
361
335
  ),
362
336
  abortSignal: options.abortSignal,
@@ -417,28 +391,28 @@ var OllamaCompletionLanguageModel = class {
417
391
  };
418
392
  }
419
393
  };
420
- var baseOllamaResponseSchema = import_v43.z.object({
421
- model: import_v43.z.string(),
422
- created_at: import_v43.z.string(),
423
- response: import_v43.z.string(),
424
- done: import_v43.z.boolean(),
425
- context: import_v43.z.array(import_v43.z.number()),
426
- eval_count: import_v43.z.number().optional(),
427
- eval_duration: import_v43.z.number().optional(),
428
- load_duration: import_v43.z.number().optional(),
429
- total_duration: import_v43.z.number().optional(),
430
- prompt_eval_count: import_v43.z.number().optional(),
431
- prompt_eval_duration: import_v43.z.number().optional()
394
+ var baseOllamaResponseSchema = import_v42.z.object({
395
+ model: import_v42.z.string(),
396
+ created_at: import_v42.z.string(),
397
+ response: import_v42.z.string(),
398
+ done: import_v42.z.boolean(),
399
+ context: import_v42.z.array(import_v42.z.number()),
400
+ eval_count: import_v42.z.number().optional(),
401
+ eval_duration: import_v42.z.number().optional(),
402
+ load_duration: import_v42.z.number().optional(),
403
+ total_duration: import_v42.z.number().optional(),
404
+ prompt_eval_count: import_v42.z.number().optional(),
405
+ prompt_eval_duration: import_v42.z.number().optional()
432
406
  });
433
407
 
434
408
  // src/embedding/ollama-embedding-model.ts
435
409
  var import_provider2 = require("@ai-sdk/provider");
436
410
  var import_provider_utils3 = require("@ai-sdk/provider-utils");
437
- var import_v44 = require("zod/v4");
438
- var ollamaEmbeddingProviderOptions = import_v44.z.object({
439
- dimensions: import_v44.z.number().optional(),
440
- truncate: import_v44.z.boolean().optional(),
441
- keepAlive: import_v44.z.string().optional()
411
+ var import_v43 = require("zod/v4");
412
+ var ollamaEmbeddingProviderOptions = import_v43.z.object({
413
+ dimensions: import_v43.z.number().optional(),
414
+ truncate: import_v43.z.boolean().optional(),
415
+ keepAlive: import_v43.z.string().optional()
442
416
  });
443
417
  var OllamaEmbeddingModel = class {
444
418
  constructor(modelId, settings, config) {
@@ -520,12 +494,12 @@ var OllamaEmbeddingModel = class {
520
494
  };
521
495
  }
522
496
  };
523
- var ollamaTextEmbeddingResponseSchema = import_v44.z.object({
524
- model: import_v44.z.string(),
525
- embeddings: import_v44.z.array(import_v44.z.array(import_v44.z.number())),
526
- total_duration: import_v44.z.number(),
527
- load_duration: import_v44.z.number(),
528
- prompt_eval_count: import_v44.z.number()
497
+ var ollamaTextEmbeddingResponseSchema = import_v43.z.object({
498
+ model: import_v43.z.string(),
499
+ embeddings: import_v43.z.array(import_v43.z.array(import_v43.z.number())),
500
+ total_duration: import_v43.z.number(),
501
+ load_duration: import_v43.z.number(),
502
+ prompt_eval_count: import_v43.z.number()
529
503
  });
530
504
 
531
505
  // src/responses/ollama-responses-language-model.ts
@@ -857,6 +831,31 @@ function prepareResponsesTools({
857
831
  }
858
832
  }
859
833
 
834
+ // src/ollama-chat-settings.ts
835
+ var import_v44 = require("zod/v4");
836
+ var ollamaProviderOptions = import_v44.z.object({
837
+ /**
838
+ * Enable or disable the model's thinking process. When enabled, the output will separate
839
+ * the model's thinking from the model's output. When disabled, the model will not think
840
+ * and directly output the content.
841
+ *
842
+ * Only supported by certain models like DeepSeek R1 and Qwen 3.
843
+ */
844
+ think: import_v44.z.boolean().optional(),
845
+ options: import_v44.z.object({
846
+ num_ctx: import_v44.z.number().optional(),
847
+ repeat_last_n: import_v44.z.number().optional(),
848
+ repeat_penalty: import_v44.z.number().optional(),
849
+ temperature: import_v44.z.number().optional(),
850
+ seed: import_v44.z.number().optional(),
851
+ stop: import_v44.z.array(import_v44.z.string()).optional(),
852
+ num_predict: import_v44.z.number().optional(),
853
+ top_k: import_v44.z.number().optional(),
854
+ top_p: import_v44.z.number().optional(),
855
+ min_p: import_v44.z.number().optional()
856
+ }).optional()
857
+ });
858
+
860
859
  // src/responses/ollama-responses-request-builder.ts
861
860
  var OllamaRequestBuilder = class {
862
861
  async buildRequest({
@@ -949,8 +948,7 @@ var OllamaRequestBuilder = class {
949
948
  responseFormat,
950
949
  ollamaOptions
951
950
  }) {
952
- var _a;
953
- const validatedThink = validateThinkParameter(modelId, ollamaOptions == null ? void 0 : ollamaOptions.think);
951
+ var _a, _b;
954
952
  return {
955
953
  model: modelId,
956
954
  messages: convertToOllamaChatMessages({
@@ -963,8 +961,8 @@ var OllamaRequestBuilder = class {
963
961
  ...(responseFormat == null ? void 0 : responseFormat.type) === "json" && {
964
962
  format: responseFormat.schema != null ? responseFormat.schema : "json"
965
963
  },
966
- think: validatedThink,
967
- options: (_a = ollamaOptions == null ? void 0 : ollamaOptions.options) != null ? _a : void 0
964
+ think: (_a = ollamaOptions == null ? void 0 : ollamaOptions.think) != null ? _a : false,
965
+ options: (_b = ollamaOptions == null ? void 0 : ollamaOptions.options) != null ? _b : void 0
968
966
  };
969
967
  }
970
968
  };
@@ -1264,6 +1262,32 @@ var OllamaStreamProcessor = class {
1264
1262
  };
1265
1263
 
1266
1264
  // src/responses/ollama-responses-language-model.ts
1265
+ function createJsonStreamResponseHandler2(schema) {
1266
+ return async ({ response }) => {
1267
+ if (!response.body) {
1268
+ throw new Error("Response body is null");
1269
+ }
1270
+ const stream = response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new TransformStream({
1271
+ transform(chunk, controller) {
1272
+ const lines = chunk.split("\n");
1273
+ for (const line of lines) {
1274
+ if (line.trim()) {
1275
+ const result = (0, import_provider_utils7.safeParseJSON)({ text: line.trim(), schema });
1276
+ controller.enqueue(result);
1277
+ }
1278
+ }
1279
+ }
1280
+ }));
1281
+ const responseHeaders = {};
1282
+ response.headers.forEach((value, key) => {
1283
+ responseHeaders[key] = value;
1284
+ });
1285
+ return {
1286
+ value: stream,
1287
+ responseHeaders
1288
+ };
1289
+ };
1290
+ }
1267
1291
  var OllamaResponsesLanguageModel = class {
1268
1292
  constructor(modelId, config) {
1269
1293
  this.specificationVersion = "v2";
@@ -1321,7 +1345,7 @@ var OllamaResponsesLanguageModel = class {
1321
1345
  headers: (0, import_provider_utils7.combineHeaders)(this.config.headers(), options.headers),
1322
1346
  body: { ...body, stream: true },
1323
1347
  failedResponseHandler: ollamaFailedResponseHandler,
1324
- successfulResponseHandler: (0, import_provider_utils7.createJsonStreamResponseHandler)(baseOllamaResponseSchema2),
1348
+ successfulResponseHandler: createJsonStreamResponseHandler2(baseOllamaResponseSchema2),
1325
1349
  abortSignal: options.abortSignal,
1326
1350
  fetch: this.config.fetch
1327
1351
  });