ai-sdk-ollama 0.1.0 → 0.3.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/README.md +72 -18
  3. package/dist/compatibility.test.d.ts +2 -0
  4. package/dist/compatibility.test.d.ts.map +1 -0
  5. package/dist/compatibility.test.js +123 -0
  6. package/dist/index.cjs +115 -514
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +41 -86
  9. package/dist/index.d.ts +41 -86
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +78 -493
  12. package/dist/index.js.map +1 -1
  13. package/dist/integration.test.d.ts +2 -0
  14. package/dist/integration.test.d.ts.map +1 -0
  15. package/dist/integration.test.js +221 -0
  16. package/dist/internal/index.cjs +135 -0
  17. package/dist/internal/index.cjs.map +1 -0
  18. package/dist/internal/index.d.cts +18 -0
  19. package/dist/internal/index.d.ts +18 -0
  20. package/dist/internal/index.d.ts.map +1 -0
  21. package/dist/internal/index.js +107 -0
  22. package/dist/internal/index.js.map +1 -0
  23. package/dist/models/chat-language-model.d.ts +49 -0
  24. package/dist/models/chat-language-model.d.ts.map +1 -0
  25. package/dist/models/chat-language-model.js +278 -0
  26. package/dist/models/chat-language-model.test.d.ts +2 -0
  27. package/dist/models/chat-language-model.test.d.ts.map +1 -0
  28. package/dist/models/chat-language-model.test.js +486 -0
  29. package/dist/models/embedding-model.d.ts +24 -0
  30. package/dist/models/embedding-model.d.ts.map +1 -0
  31. package/dist/models/embedding-model.js +77 -0
  32. package/dist/models/embedding-model.test.d.ts +2 -0
  33. package/dist/models/embedding-model.test.d.ts.map +1 -0
  34. package/dist/models/embedding-model.test.js +281 -0
  35. package/dist/provider-dual-parameters.test.d.ts +2 -0
  36. package/dist/provider-dual-parameters.test.d.ts.map +1 -0
  37. package/dist/provider-dual-parameters.test.js +223 -0
  38. package/dist/provider.d.ts +123 -0
  39. package/dist/provider.d.ts.map +1 -0
  40. package/dist/provider.js +52 -0
  41. package/dist/provider.test.d.ts +2 -0
  42. package/dist/provider.test.d.ts.map +1 -0
  43. package/dist/provider.test.js +192 -0
  44. package/dist/test-setup.d.ts +4 -0
  45. package/dist/test-setup.d.ts.map +1 -0
  46. package/dist/test-setup.js +31 -0
  47. package/dist/utils/convert-to-ollama-messages.d.ts +4 -0
  48. package/dist/utils/convert-to-ollama-messages.d.ts.map +1 -0
  49. package/dist/utils/convert-to-ollama-messages.js +105 -0
  50. package/dist/utils/convert-to-ollama-messages.test.d.ts +2 -0
  51. package/dist/utils/convert-to-ollama-messages.test.d.ts.map +1 -0
  52. package/dist/utils/convert-to-ollama-messages.test.js +433 -0
  53. package/dist/utils/map-ollama-finish-reason.d.ts +3 -0
  54. package/dist/utils/map-ollama-finish-reason.d.ts.map +1 -0
  55. package/dist/utils/map-ollama-finish-reason.js +15 -0
  56. package/dist/utils/map-ollama-finish-reason.test.d.ts +2 -0
  57. package/dist/utils/map-ollama-finish-reason.test.d.ts.map +1 -0
  58. package/dist/utils/map-ollama-finish-reason.test.js +47 -0
  59. package/dist/utils/model-capabilities.d.ts +28 -0
  60. package/dist/utils/model-capabilities.d.ts.map +1 -0
  61. package/dist/utils/model-capabilities.js +327 -0
  62. package/dist/utils/model-suggestions.d.ts +38 -0
  63. package/dist/utils/model-suggestions.d.ts.map +1 -0
  64. package/dist/utils/model-suggestions.js +158 -0
  65. package/dist/utils/normalize-tool-parameters.d.ts +17 -0
  66. package/dist/utils/normalize-tool-parameters.d.ts.map +1 -0
  67. package/dist/utils/normalize-tool-parameters.js +63 -0
  68. package/dist/utils/normalize-tool-parameters.test.d.ts +2 -0
  69. package/dist/utils/normalize-tool-parameters.test.d.ts.map +1 -0
  70. package/dist/utils/normalize-tool-parameters.test.js +100 -0
  71. package/dist/utils/ollama-error.d.ts +16 -0
  72. package/dist/utils/ollama-error.d.ts.map +1 -0
  73. package/dist/utils/ollama-error.js +13 -0
  74. package/dist/utils/ollama-error.test.d.ts +2 -0
  75. package/dist/utils/ollama-error.test.d.ts.map +1 -0
  76. package/dist/utils/ollama-error.test.js +94 -0
  77. package/dist/utils/validate-model.d.ts +32 -0
  78. package/dist/utils/validate-model.d.ts.map +1 -0
  79. package/dist/utils/validate-model.js +32 -0
  80. package/package.json +7 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **Auto-Structured Outputs**: Enhanced structured outputs with intelligent auto-detection
8
+ - 🎯 **Smart Auto-Detection**: Automatically enables structured outputs when JSON schema is provided
9
+ - 🔧 **Backward Compatibility**: Explicit `structuredOutputs: true/false` settings are still respected
10
+ - ⚠️ **User-Friendly Warnings**: Clear warnings when auto-enabling structured outputs
11
+ - 📚 **Enhanced Documentation**: Updated examples and README with auto-detection guidance
12
+ - 🧪 **Comprehensive Testing**: Added integration tests for auto-detection scenarios
13
+ - 🛠️ **Improved Developer Experience**: No need to manually set `structuredOutputs: true` for object generation
14
+
15
+ ### Technical Improvements
16
+
17
+ - Enhanced `shouldEnableStructuredOutputs()` method for intelligent auto-detection
18
+ - Improved schema validation and error handling
19
+ - Updated README with auto-detection examples and best practices
20
+ - Added comprehensive integration tests for edge cases
21
+ - Streamlined configuration for common use cases
22
+
23
+ ## 0.2.0
24
+
25
+ ### Minor Changes
26
+
27
+ - bf0905a: Fix streaming examples and improve TypeScript type checking
28
+ - Fix "Stream error: text part not found" by using textStream instead of fullStream for basic streaming
29
+ - Fix TypeScript errors in all examples (error handling, index access, undefined checks)
30
+ - Remove rootDir restriction in tsconfig.json to enable type checking for examples
31
+ - Fix tool call parameter handling and error messages
32
+ - Remove deprecated model capabilities and suggestions utilities
33
+ - Improve error handling with proper type checking throughout examples
34
+ - Update streaming examples to work with AI SDK v5 API changes
35
+
3
36
  All notable changes to this project will be documented in this file.
4
37
 
5
38
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
@@ -66,7 +99,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66
99
 
67
100
  ### Supported Models
68
101
 
69
- - **Chat Models**: llama3.2, llama3.1, mistral, phi4-mini, qwen2.5, codellama, and all Ollama chat models
102
+ - **Chat Models**: llama3.2, mistral, phi4-mini, qwen2.5, codellama, and all Ollama chat models
70
103
  - **Vision Models**: llava, bakllava, llama3.2-vision, minicpm-v
71
104
  - **Embedding Models**: nomic-embed-text, all-minilm, mxbai-embed-large, and all Ollama embedding models
72
105
 
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
- - [Smart Model Intelligence](#smart-model-intelligence)
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
 
@@ -151,7 +153,7 @@ const { text } = await generateText({
151
153
 
152
154
  ### Tool Calling Support
153
155
 
154
- Ollama supports tool calling with compatible models:
156
+ Ollama supports tool calling with compatible models.
155
157
 
156
158
  ```typescript
157
159
  import { z } from 'zod';
@@ -162,7 +164,7 @@ const { text, toolCalls } = await generateText({
162
164
  tools: {
163
165
  getWeather: {
164
166
  description: 'Get current weather for a location',
165
- parameters: z.object({
167
+ inputSchema: z.object({
166
168
  location: z.string().describe('City name'),
167
169
  unit: z.enum(['celsius', 'fahrenheit']).optional(),
168
170
  }),
@@ -175,28 +177,26 @@ const { text, toolCalls } = await generateText({
175
177
  });
176
178
  ```
177
179
 
178
- ### Smart Model Intelligence
180
+ > **Note on Tool Parameters**: Due to Zod version compatibility issues, tool schemas may not always convert properly. When this happens, Ollama may use different parameter names than defined in your schema. It's recommended to handle parameter variations in your tool's execute function (e.g., checking for both `location` and `city`).
179
181
 
180
- The provider automatically detects model capabilities and provides helpful suggestions:
182
+ ### Simple and Predictable
183
+
184
+ The provider works the same way with any model - just try the features you need:
181
185
 
182
186
  ```typescript
183
- // The provider will automatically warn you if a model doesn't support tools
187
+ // No capability checking required - just use any model
184
188
  const { text } = await generateText({
185
- model: ollama('llama3'), // Older model without tool support
189
+ model: ollama('any-model'),
186
190
  prompt: 'What is the weather?',
187
191
  tools: {
188
192
  /* ... */
189
- }, // This will throw a helpful error with suggestions
193
+ }, // If the model doesn't support tools, you'll get a clear error
190
194
  });
191
195
 
192
- // Get model recommendations for specific features
193
- import { suggestModelsForFeatures } from 'ai-sdk-ollama';
194
-
195
- const suggestions = suggestModelsForFeatures({
196
- toolCalling: true,
197
- performance: 'fast',
198
- });
199
- // Returns: [{ modelId: 'llama3.2', reason: 'Excellent tool calling...' }]
196
+ // The provider is simple and predictable
197
+ // - Try any feature with any model
198
+ // - Get clear error messages if something doesn't work
199
+ // - No hidden complexity or capability detection
200
200
  ```
201
201
 
202
202
  ## Advanced Features
@@ -225,8 +225,9 @@ const { text } = await generateText({
225
225
  import { generateObject } from 'ai';
226
226
  import { z } from 'zod';
227
227
 
228
+ // Auto-detection: structuredOutputs is automatically enabled for object generation
228
229
  const { object } = await generateObject({
229
- model: ollama('llama3.2', { structuredOutputs: true }),
230
+ model: ollama('llama3.2'), // No need to set structuredOutputs: true
230
231
  schema: z.object({
231
232
  name: z.string(),
232
233
  age: z.number(),
@@ -237,6 +238,40 @@ const { object } = await generateObject({
237
238
 
238
239
  console.log(object);
239
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
+ });
240
275
  ```
241
276
 
242
277
  ## Common Issues
@@ -252,10 +287,29 @@ console.log(object);
252
287
 
253
288
  Works with any model in your Ollama installation:
254
289
 
255
- - **Chat**: `llama3.2`, `llama3.1`, `mistral`, `phi4-mini`, `qwen2.5`, `codellama`
290
+ - **Chat**: `llama3.2`, `mistral`, `phi4-mini`, `qwen2.5`, `codellama`
256
291
  - **Vision**: `llava`, `bakllava`, `llama3.2-vision`, `minicpm-v`
257
292
  - **Embeddings**: `nomic-embed-text`, `all-minilm`, `mxbai-embed-large`
258
293
 
294
+ ## Testing
295
+
296
+ The project includes unit and integration tests:
297
+
298
+ ```bash
299
+ # Run unit tests only (fast, no external dependencies)
300
+ npm test
301
+
302
+ # Run all tests (unit + integration)
303
+ npm run test:all
304
+
305
+ # Run integration tests only (requires Ollama running)
306
+ npm run test:integration
307
+ ```
308
+
309
+ > **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.
310
+
311
+ For detailed testing information, see [Integration Tests Documentation](./src/integration-tests/README.md).
312
+
259
313
  ## Learn More
260
314
 
261
315
  📚 **[Examples Directory](./examples/)** - Comprehensive usage patterns with real working code
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=compatibility.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compatibility.test.d.ts","sourceRoot":"","sources":["../src/compatibility.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,123 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ollama } from './index';
3
+ describe('OpenAI API Compatibility', () => {
4
+ describe('Provider Interface Compatibility', () => {
5
+ it('should implement standard provider pattern like OpenAI provider', () => {
6
+ // Test that our provider follows the same pattern as Vercel's OpenAI provider
7
+ expect(typeof ollama).toBe('function');
8
+ expect(typeof ollama.chat).toBe('function');
9
+ expect(typeof ollama.languageModel).toBe('function');
10
+ expect(typeof ollama.embedding).toBe('function');
11
+ expect(typeof ollama.textEmbedding).toBe('function');
12
+ expect(typeof ollama.textEmbeddingModel).toBe('function');
13
+ });
14
+ it('should create LanguageModelV2 compatible models', () => {
15
+ const model = ollama('llama3.2');
16
+ // Test LanguageModelV2 interface compliance
17
+ expect(model.specificationVersion).toBe('v2');
18
+ expect(typeof model.modelId).toBe('string');
19
+ expect(typeof model.provider).toBe('string');
20
+ expect(typeof model.doGenerate).toBe('function');
21
+ expect(typeof model.doStream).toBe('function');
22
+ // Test that model has expected properties (interface may have changed)
23
+ expect(typeof model.supportedUrls).toBe('object');
24
+ });
25
+ it('should create EmbeddingModelV2 compatible models', () => {
26
+ const model = ollama.embedding('nomic-embed-text');
27
+ // Test EmbeddingModelV2 interface compliance
28
+ expect(model.specificationVersion).toBe('v2');
29
+ expect(typeof model.modelId).toBe('string');
30
+ expect(typeof model.provider).toBe('string');
31
+ expect(typeof model.doEmbed).toBe('function');
32
+ // Test standard properties
33
+ expect(typeof model.maxEmbeddingsPerCall).toBe('number');
34
+ expect(typeof model.supportsParallelCalls).toBe('boolean');
35
+ });
36
+ });
37
+ describe('AI SDK Integration Compatibility', () => {
38
+ it('should work with generateText like OpenAI provider', () => {
39
+ const model = ollama('llama3.2');
40
+ // Test that model can be used with AI SDK functions
41
+ expect(typeof model.doGenerate).toBe('function');
42
+ expect(model.doGenerate.length).toBe(1); // Takes one parameter (options)
43
+ });
44
+ it('should work with streamText like OpenAI provider', () => {
45
+ const model = ollama('llama3.2');
46
+ expect(typeof model.doStream).toBe('function');
47
+ expect(model.doStream.length).toBe(1); // Takes one parameter (options)
48
+ });
49
+ it('should work with embed like OpenAI provider', () => {
50
+ const model = ollama.embedding('nomic-embed-text');
51
+ expect(() => {
52
+ // Test embedding interface compatibility
53
+ expect(typeof model.doEmbed).toBe('function');
54
+ expect(model.doEmbed.length).toBe(1); // Takes one parameter (options)
55
+ }).not.toThrow();
56
+ });
57
+ });
58
+ describe('Response Format Compatibility', () => {
59
+ it('should support JSON response format like OpenAI', () => {
60
+ const model = ollama('llama3.2');
61
+ // Test that our model exists and can be configured
62
+ expect(model.provider).toBe('ollama');
63
+ expect(model.modelId).toBe('llama3.2');
64
+ });
65
+ it('should support standard parameters like OpenAI', () => {
66
+ const model = ollama('llama3.2');
67
+ // Test basic model properties
68
+ expect(typeof model.doGenerate).toBe('function');
69
+ expect(typeof model.doStream).toBe('function');
70
+ });
71
+ });
72
+ describe('Error Handling Compatibility', () => {
73
+ it('should handle errors consistently with OpenAI provider', () => {
74
+ const model = ollama('llama3.2');
75
+ // Test that our error handling follows standard patterns
76
+ expect(model.provider).toBe('ollama');
77
+ expect(model.modelId).toBe('llama3.2');
78
+ // Models should have consistent error behavior
79
+ expect(() => {
80
+ // Test model creation with invalid parameters
81
+ ollama(''); // Empty model name
82
+ }).not.toThrow(); // Should create model, errors happen at runtime
83
+ });
84
+ });
85
+ describe('Provider Settings Compatibility', () => {
86
+ it('should support provider-specific settings like OpenAI', () => {
87
+ // Test custom settings similar to how OpenAI provider works
88
+ const modelWithSettings = ollama('llama3.2', {
89
+ options: {
90
+ temperature: 0.8,
91
+ num_ctx: 4096,
92
+ top_k: 50,
93
+ },
94
+ });
95
+ expect(modelWithSettings.modelId).toBe('llama3.2');
96
+ expect(modelWithSettings.provider).toBe('ollama');
97
+ });
98
+ it('should support structured outputs setting', () => {
99
+ const modelWithStructuredOutputs = ollama('llama3.2', {
100
+ structuredOutputs: true,
101
+ });
102
+ expect(modelWithStructuredOutputs.provider).toBe('ollama');
103
+ });
104
+ });
105
+ describe('Embedding Model Compatibility', () => {
106
+ it('should handle embeddings consistently with OpenAI', () => {
107
+ const embeddingModel = ollama.embedding('nomic-embed-text');
108
+ expect(embeddingModel.modelId).toBe('nomic-embed-text');
109
+ expect(embeddingModel.provider).toBe('ollama');
110
+ expect(embeddingModel.specificationVersion).toBe('v2');
111
+ expect(typeof embeddingModel.maxEmbeddingsPerCall).toBe('number');
112
+ expect(embeddingModel.maxEmbeddingsPerCall).toBeGreaterThan(0);
113
+ });
114
+ it('should support embedding settings', () => {
115
+ const embeddingModel = ollama.embedding('nomic-embed-text', {
116
+ options: {
117
+ num_thread: 8,
118
+ },
119
+ });
120
+ expect(embeddingModel.provider).toBe('ollama');
121
+ });
122
+ });
123
+ });