@push.rocks/smartai 0.13.3 → 2.0.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 (98) hide show
  1. package/dist_ts/00_commitinfo_data.js +3 -3
  2. package/dist_ts/index.d.ts +6 -11
  3. package/dist_ts/index.js +6 -12
  4. package/dist_ts/plugins.d.ts +10 -15
  5. package/dist_ts/plugins.js +13 -19
  6. package/dist_ts/smartai.classes.smartai.d.ts +7 -0
  7. package/dist_ts/smartai.classes.smartai.js +51 -0
  8. package/dist_ts/smartai.interfaces.d.ts +41 -0
  9. package/dist_ts/smartai.interfaces.js +2 -0
  10. package/dist_ts/smartai.middleware.anthropic.d.ts +7 -0
  11. package/dist_ts/smartai.middleware.anthropic.js +36 -0
  12. package/dist_ts/smartai.provider.ollama.d.ts +8 -0
  13. package/dist_ts/smartai.provider.ollama.js +378 -0
  14. package/dist_ts_audio/index.d.ts +9 -0
  15. package/dist_ts_audio/index.js +15 -0
  16. package/dist_ts_audio/plugins.d.ts +2 -0
  17. package/dist_ts_audio/plugins.js +3 -0
  18. package/dist_ts_document/index.d.ts +11 -0
  19. package/dist_ts_document/index.js +45 -0
  20. package/dist_ts_document/plugins.d.ts +3 -0
  21. package/dist_ts_document/plugins.js +4 -0
  22. package/dist_ts_image/index.d.ts +46 -0
  23. package/dist_ts_image/index.js +110 -0
  24. package/dist_ts_image/plugins.d.ts +3 -0
  25. package/dist_ts_image/plugins.js +4 -0
  26. package/dist_ts_research/index.d.ts +19 -0
  27. package/dist_ts_research/index.js +98 -0
  28. package/dist_ts_research/plugins.d.ts +2 -0
  29. package/dist_ts_research/plugins.js +3 -0
  30. package/dist_ts_vision/index.d.ts +8 -0
  31. package/dist_ts_vision/index.js +21 -0
  32. package/dist_ts_vision/plugins.d.ts +2 -0
  33. package/dist_ts_vision/plugins.js +3 -0
  34. package/package.json +50 -22
  35. package/readme.hints.md +34 -88
  36. package/readme.md +284 -547
  37. package/ts/00_commitinfo_data.ts +2 -2
  38. package/ts/index.ts +8 -11
  39. package/ts/plugins.ts +19 -35
  40. package/ts/smartai.classes.smartai.ts +51 -0
  41. package/ts/smartai.interfaces.ts +53 -0
  42. package/ts/smartai.middleware.anthropic.ts +38 -0
  43. package/ts/smartai.provider.ollama.ts +426 -0
  44. package/ts_audio/index.ts +24 -0
  45. package/ts_audio/plugins.ts +2 -0
  46. package/ts_document/index.ts +61 -0
  47. package/ts_document/plugins.ts +3 -0
  48. package/ts_image/index.ts +147 -0
  49. package/ts_image/plugins.ts +3 -0
  50. package/ts_research/index.ts +120 -0
  51. package/ts_research/plugins.ts +2 -0
  52. package/ts_vision/index.ts +29 -0
  53. package/ts_vision/plugins.ts +2 -0
  54. package/dist_ts/abstract.classes.multimodal.d.ts +0 -212
  55. package/dist_ts/abstract.classes.multimodal.js +0 -43
  56. package/dist_ts/classes.conversation.d.ts +0 -31
  57. package/dist_ts/classes.conversation.js +0 -150
  58. package/dist_ts/classes.smartai.d.ts +0 -59
  59. package/dist_ts/classes.smartai.js +0 -139
  60. package/dist_ts/classes.tts.d.ts +0 -6
  61. package/dist_ts/classes.tts.js +0 -10
  62. package/dist_ts/interfaces.d.ts +0 -1
  63. package/dist_ts/interfaces.js +0 -2
  64. package/dist_ts/paths.d.ts +0 -2
  65. package/dist_ts/paths.js +0 -4
  66. package/dist_ts/provider.anthropic.d.ts +0 -48
  67. package/dist_ts/provider.anthropic.js +0 -369
  68. package/dist_ts/provider.elevenlabs.d.ts +0 -43
  69. package/dist_ts/provider.elevenlabs.js +0 -64
  70. package/dist_ts/provider.exo.d.ts +0 -40
  71. package/dist_ts/provider.exo.js +0 -116
  72. package/dist_ts/provider.groq.d.ts +0 -39
  73. package/dist_ts/provider.groq.js +0 -178
  74. package/dist_ts/provider.mistral.d.ts +0 -61
  75. package/dist_ts/provider.mistral.js +0 -288
  76. package/dist_ts/provider.ollama.d.ts +0 -141
  77. package/dist_ts/provider.ollama.js +0 -529
  78. package/dist_ts/provider.openai.d.ts +0 -62
  79. package/dist_ts/provider.openai.js +0 -403
  80. package/dist_ts/provider.perplexity.d.ts +0 -37
  81. package/dist_ts/provider.perplexity.js +0 -215
  82. package/dist_ts/provider.xai.d.ts +0 -52
  83. package/dist_ts/provider.xai.js +0 -160
  84. package/ts/abstract.classes.multimodal.ts +0 -240
  85. package/ts/classes.conversation.ts +0 -176
  86. package/ts/classes.smartai.ts +0 -187
  87. package/ts/classes.tts.ts +0 -15
  88. package/ts/interfaces.ts +0 -0
  89. package/ts/paths.ts +0 -4
  90. package/ts/provider.anthropic.ts +0 -446
  91. package/ts/provider.elevenlabs.ts +0 -116
  92. package/ts/provider.exo.ts +0 -155
  93. package/ts/provider.groq.ts +0 -219
  94. package/ts/provider.mistral.ts +0 -352
  95. package/ts/provider.ollama.ts +0 -705
  96. package/ts/provider.openai.ts +0 -462
  97. package/ts/provider.perplexity.ts +0 -259
  98. package/ts/provider.xai.ts +0 -214
package/readme.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # @push.rocks/smartai
2
2
 
3
- **One API to rule them all** 🚀
3
+ **A unified provider registry for the Vercel AI SDK** 🧠⚡
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@push.rocks/smartai.svg)](https://www.npmjs.com/package/@push.rocks/smartai)
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
8
 
9
- SmartAI unifies the world's leading AI providersOpenAI, Anthropic, Mistral, Perplexity, Ollama, Groq, XAI, Exo, and ElevenLabs under a single, elegant TypeScript interface. Build AI applications at lightning speed without vendor lock-in.
9
+ SmartAI gives you a single `getModel()` function that returns a standard `LanguageModelV3` for **any** supported provider — Anthropic, OpenAI, Google, Groq, Mistral, XAI, Perplexity, or Ollama. Use the returned model with the Vercel AI SDK's `generateText()`, `streamText()`, and tool ecosystem. Specialized capabilities like vision, audio, image generation, document analysis, and web research are available as dedicated subpath imports.
10
10
 
11
11
  ## Issue Reporting and Security
12
12
 
@@ -14,679 +14,416 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
14
14
 
15
15
  ## 🎯 Why SmartAI?
16
16
 
17
- - **🔌 Universal Interface**: Write once, run with any AI provider. Switch between GPT-5, Claude, Llama, or Grok with a single line change.
18
- - **🛡️ Type-Safe**: Full TypeScript support with comprehensive type definitions for all operations.
19
- - **🌊 Streaming First**: Built for real-time applications with native streaming support.
20
- - **🎨 Multi-Modal**: Seamlessly work with text, images, audio, and documents.
21
- - **🏠 Local & Cloud**: Support for both cloud providers and local models via Ollama/Exo.
22
- - **⚡ Zero Lock-In**: Your code remains portable across all AI providers.
17
+ - **🔌 One function, eight providers** `getModel()` returns a standard `LanguageModelV3`. Switch providers by changing a string.
18
+ - **🧱 Built on Vercel AI SDK** — Uses `ai` v6 under the hood. Your model works with `generateText()`, `streamText()`, tool calling, structured output, and everything else in the AI SDK ecosystem.
19
+ - **🏠 Custom Ollama provider** — A full `LanguageModelV3` implementation for Ollama with support for `think` mode, `num_ctx`, auto-tuned temperature for Qwen models, and native tool calling.
20
+ - **💰 Anthropic prompt caching** Automatic `cacheControl` middleware reduces cost and latency on repeated calls. Enabled by default, opt out with `promptCaching: false`.
21
+ - **📦 Modular subpath exports** Vision, audio, image, document, and research capabilities ship as separate imports. Only import what you need.
22
+ - **⚡ Zero lock-in** Your code uses standard AI SDK types. Swap providers without touching application logic.
23
23
 
24
24
  ## 📦 Installation
25
25
 
26
26
  ```bash
27
- npm install @push.rocks/smartai
28
- # or
29
27
  pnpm install @push.rocks/smartai
30
28
  ```
31
29
 
32
30
  ## 🚀 Quick Start
33
31
 
34
32
  ```typescript
35
- import { SmartAi } from '@push.rocks/smartai';
36
-
37
- // Initialize with your favorite providers
38
- const ai = new SmartAi({
39
- openaiToken: 'sk-...',
40
- anthropicToken: 'sk-ant-...',
41
- elevenlabsToken: 'sk-...',
42
- elevenlabs: {
43
- defaultVoiceId: '19STyYD15bswVz51nqLf', // Optional: Samara voice
44
- },
45
- });
33
+ import { getModel, generateText, streamText } from '@push.rocks/smartai';
46
34
 
47
- await ai.start();
35
+ // Get a model for any provider
36
+ const model = getModel({
37
+ provider: 'anthropic',
38
+ model: 'claude-sonnet-4-5-20250929',
39
+ apiKey: process.env.ANTHROPIC_TOKEN,
40
+ });
48
41
 
49
- // Same API, multiple providers
50
- const response = await ai.openaiProvider.chat({
51
- systemMessage: 'You are a helpful assistant.',
52
- userMessage: 'Explain quantum computing in simple terms',
53
- messageHistory: [],
42
+ // Use it with the standard AI SDK functions
43
+ const result = await generateText({
44
+ model,
45
+ prompt: 'Explain quantum computing in simple terms.',
54
46
  });
55
47
 
56
- console.log(response.message);
48
+ console.log(result.text);
57
49
  ```
58
50
 
59
- ## 📊 Provider Capabilities Matrix
60
-
61
- Choose the right provider for your use case:
51
+ That's it. Change `provider` to `'openai'` and `model` to `'gpt-4o'` and the rest of your code stays exactly the same.
62
52
 
63
- | Provider | Chat | Streaming | TTS | Vision | Documents | Research | Images | Highlights |
64
- | -------------- | :--: | :-------: | :-: | :----: | :-------: | :------: | :----: | --------------------------------------------------------------- |
65
- | **OpenAI** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | gpt-image-1 • DALL-E 3 • Deep Research API |
66
- | **Anthropic** | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | Claude Sonnet 4.5 • Extended Thinking • Web Search API |
67
- | **Mistral** | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | Native PDF OCR • mistral-large • Fast inference |
68
- | **ElevenLabs** | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | Premium TTS • 70+ languages • v3 model |
69
- | **Ollama** | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | 100% local • Privacy-first • No API costs |
70
- | **XAI** | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | Grok 2 • Real-time data |
71
- | **Perplexity** | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ | Web-aware • Research-focused • Sonar Pro |
72
- | **Groq** | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | 10x faster • LPU inference • Llama 3.3 |
73
- | **Exo** | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | Distributed • P2P compute • Decentralized |
53
+ ## 🔧 Core API
74
54
 
75
- ## 🎮 Core Features
55
+ ### `getModel(options): LanguageModelV3`
76
56
 
77
- ### 💬 Universal Chat Interface
78
-
79
- Works identically across all providers:
57
+ The primary export. Returns a standard `LanguageModelV3` you can use with any AI SDK function.
80
58
 
81
59
  ```typescript
82
- // Use GPT-5 for complex reasoning
83
- const gptResponse = await ai.openaiProvider.chat({
84
- systemMessage: 'You are an expert physicist.',
85
- userMessage: 'Explain the implications of quantum entanglement',
86
- messageHistory: [],
87
- });
88
-
89
- // Use Claude for safety-critical applications
90
- const claudeResponse = await ai.anthropicProvider.chat({
91
- systemMessage: 'You are a medical advisor.',
92
- userMessage: 'Review this patient data for concerns',
93
- messageHistory: [],
94
- });
95
-
96
- // Use Groq for lightning-fast responses
97
- const groqResponse = await ai.groqProvider.chat({
98
- systemMessage: 'You are a code reviewer.',
99
- userMessage: 'Quick! Find the bug in this code: ...',
100
- messageHistory: [],
101
- });
60
+ import { getModel } from '@push.rocks/smartai';
61
+ import type { ISmartAiOptions } from '@push.rocks/smartai';
62
+
63
+ const options: ISmartAiOptions = {
64
+ provider: 'anthropic', // 'anthropic' | 'openai' | 'google' | 'groq' | 'mistral' | 'xai' | 'perplexity' | 'ollama'
65
+ model: 'claude-sonnet-4-5-20250929',
66
+ apiKey: 'sk-ant-...',
67
+ // Anthropic-only: prompt caching (default: true)
68
+ promptCaching: true,
69
+ // Ollama-only: base URL (default: http://localhost:11434)
70
+ baseUrl: 'http://localhost:11434',
71
+ // Ollama-only: model runtime options
72
+ ollamaOptions: { think: true, num_ctx: 4096 },
73
+ };
74
+
75
+ const model = getModel(options);
102
76
  ```
103
77
 
104
- ### 🌊 Real-Time Streaming
78
+ ### Re-exported AI SDK Functions
105
79
 
106
- Build responsive chat interfaces with token-by-token streaming:
80
+ SmartAI re-exports the most commonly used functions from `ai` for convenience:
107
81
 
108
82
  ```typescript
109
- // Create a chat stream
110
- const stream = await ai.openaiProvider.chatStream(inputStream);
111
- const reader = stream.getReader();
83
+ import {
84
+ getModel,
85
+ generateText,
86
+ streamText,
87
+ tool,
88
+ jsonSchema,
89
+ } from '@push.rocks/smartai';
90
+
91
+ import type {
92
+ ModelMessage,
93
+ ToolSet,
94
+ StreamTextResult,
95
+ LanguageModelV3,
96
+ } from '@push.rocks/smartai';
97
+ ```
112
98
 
113
- // Display responses as they arrive
114
- while (true) {
115
- const { done, value } = await reader.read();
116
- if (done) break;
99
+ ## 🤖 Supported Providers
117
100
 
118
- // Update UI in real-time
119
- process.stdout.write(value);
120
- }
121
- ```
101
+ | Provider | Package | Example Models |
102
+ |----------|---------|----------------|
103
+ | **Anthropic** | `@ai-sdk/anthropic` | `claude-sonnet-4-5-20250929`, `claude-opus-4-5-20250929` |
104
+ | **OpenAI** | `@ai-sdk/openai` | `gpt-4o`, `gpt-4o-mini`, `o3-mini` |
105
+ | **Google** | `@ai-sdk/google` | `gemini-2.0-flash`, `gemini-2.5-pro` |
106
+ | **Groq** | `@ai-sdk/groq` | `llama-3.3-70b-versatile`, `mixtral-8x7b-32768` |
107
+ | **Mistral** | `@ai-sdk/mistral` | `mistral-large-latest`, `mistral-small-latest` |
108
+ | **XAI** | `@ai-sdk/xai` | `grok-3`, `grok-3-mini` |
109
+ | **Perplexity** | `@ai-sdk/perplexity` | `sonar-pro`, `sonar` |
110
+ | **Ollama** | Custom `LanguageModelV3` | `qwen3:8b`, `llama3:8b`, `deepseek-r1` |
122
111
 
123
- ### 🎙️ Text-to-Speech
112
+ ## 💬 Text Generation
124
113
 
125
- Generate natural voices with OpenAI or ElevenLabs:
114
+ ### Generate Text
126
115
 
127
116
  ```typescript
128
- // OpenAI TTS
129
- const audioStream = await ai.openaiProvider.audio({
130
- message: 'Welcome to the future of AI development!',
117
+ import { getModel, generateText } from '@push.rocks/smartai';
118
+
119
+ const model = getModel({
120
+ provider: 'openai',
121
+ model: 'gpt-4o',
122
+ apiKey: process.env.OPENAI_TOKEN,
131
123
  });
132
124
 
133
- // ElevenLabs TTS - Premium quality, natural voices (uses v3 by default)
134
- const elevenLabsAudio = await ai.elevenlabsProvider.audio({
135
- message: 'Experience the most lifelike text to speech technology.',
136
- voiceId: '19STyYD15bswVz51nqLf', // Optional: Samara voice
137
- modelId: 'eleven_v3', // Optional: defaults to eleven_v3 (70+ languages)
138
- voiceSettings: {
139
- // Optional: fine-tune voice characteristics
140
- stability: 0.5, // 0-1: Speech consistency
141
- similarity_boost: 0.8, // 0-1: Voice similarity to original
142
- style: 0.0, // 0-1: Expressiveness
143
- use_speaker_boost: true, // Enhanced clarity
144
- },
125
+ const result = await generateText({
126
+ model,
127
+ system: 'You are a helpful assistant.',
128
+ prompt: 'What is 2 + 2?',
145
129
  });
146
130
 
147
- // Stream directly to speakers or save to file
148
- audioStream.pipe(fs.createWriteStream('welcome.mp3'));
131
+ console.log(result.text); // "4"
149
132
  ```
150
133
 
151
- ### 👁️ Vision Analysis
152
-
153
- Understand images with multiple providers:
134
+ ### Stream Text
154
135
 
155
136
  ```typescript
156
- const image = fs.readFileSync('product-photo.jpg');
137
+ import { getModel, streamText } from '@push.rocks/smartai';
157
138
 
158
- // OpenAI: General purpose vision
159
- const gptVision = await ai.openaiProvider.vision({
160
- image,
161
- prompt: 'Describe this product and suggest marketing angles',
139
+ const model = getModel({
140
+ provider: 'anthropic',
141
+ model: 'claude-sonnet-4-5-20250929',
142
+ apiKey: process.env.ANTHROPIC_TOKEN,
162
143
  });
163
144
 
164
- // Anthropic: Detailed analysis with extended thinking
165
- const claudeVision = await ai.anthropicProvider.vision({
166
- image,
167
- prompt: 'Identify any safety concerns or defects',
145
+ const result = await streamText({
146
+ model,
147
+ prompt: 'Count from 1 to 10.',
168
148
  });
169
149
 
170
- // Ollama: Private, local analysis
171
- const ollamaVision = await ai.ollamaProvider.vision({
172
- image,
173
- prompt: 'Extract all text and categorize the content',
174
- });
150
+ for await (const chunk of result.textStream) {
151
+ process.stdout.write(chunk);
152
+ }
175
153
  ```
176
154
 
177
- ### 📄 Document Intelligence
178
-
179
- Extract insights from PDFs with AI:
155
+ ### Tool Calling
180
156
 
181
157
  ```typescript
182
- const contract = fs.readFileSync('contract.pdf');
183
- const invoice = fs.readFileSync('invoice.pdf');
184
-
185
- // Analyze documents with OpenAI
186
- const analysis = await ai.openaiProvider.document({
187
- systemMessage: 'You are a legal expert.',
188
- userMessage: 'Compare these documents and highlight key differences',
189
- messageHistory: [],
190
- pdfDocuments: [contract, invoice],
158
+ import { getModel, generateText, tool, jsonSchema } from '@push.rocks/smartai';
159
+
160
+ const model = getModel({
161
+ provider: 'anthropic',
162
+ model: 'claude-sonnet-4-5-20250929',
163
+ apiKey: process.env.ANTHROPIC_TOKEN,
191
164
  });
192
165
 
193
- // Multi-document analysis with Anthropic
194
- const taxDocs = [form1099, w2, receipts];
195
- const taxAnalysis = await ai.anthropicProvider.document({
196
- systemMessage: 'You are a tax advisor.',
197
- userMessage: 'Prepare a tax summary from these documents',
198
- messageHistory: [],
199
- pdfDocuments: taxDocs,
166
+ const result = await generateText({
167
+ model,
168
+ prompt: 'What is the weather in London?',
169
+ tools: {
170
+ getWeather: tool({
171
+ description: 'Get weather for a location',
172
+ parameters: jsonSchema({
173
+ type: 'object',
174
+ properties: {
175
+ location: { type: 'string' },
176
+ },
177
+ required: ['location'],
178
+ }),
179
+ execute: async ({ location }) => {
180
+ return { temperature: 18, condition: 'cloudy' };
181
+ },
182
+ }),
183
+ },
200
184
  });
201
185
  ```
202
186
 
203
- ### 🔬 Research & Web Search
187
+ ## 🏠 Ollama (Local Models)
204
188
 
205
- Perform deep research with web search capabilities across multiple providers:
189
+ The custom Ollama provider implements `LanguageModelV3` directly, calling Ollama's native `/api/chat` endpoint. This gives you features that generic OpenAI-compatible wrappers miss:
206
190
 
207
191
  ```typescript
208
- // OpenAI Deep Research - Comprehensive analysis
209
- const deepResearch = await ai.openaiProvider.research({
210
- query: 'What are the latest developments in quantum computing?',
211
- searchDepth: 'deep',
212
- includeWebSearch: true,
213
- });
214
-
215
- console.log(deepResearch.answer);
216
- console.log('Sources:', deepResearch.sources);
217
-
218
- // Anthropic Web Search - Domain-filtered research
219
- import { AnthropicProvider } from '@push.rocks/smartai';
220
-
221
- const anthropic = new AnthropicProvider({
222
- anthropicToken: 'sk-ant-...',
223
- enableWebSearch: true,
224
- searchDomainAllowList: ['nature.com', 'science.org'],
192
+ import { getModel, generateText } from '@push.rocks/smartai';
193
+
194
+ const model = getModel({
195
+ provider: 'ollama',
196
+ model: 'qwen3:8b',
197
+ baseUrl: 'http://localhost:11434', // default
198
+ ollamaOptions: {
199
+ think: true, // Enable thinking/reasoning mode
200
+ num_ctx: 8192, // Context window size
201
+ temperature: 0.7, // Override default (Qwen models auto-default to 0.55)
202
+ },
225
203
  });
226
204
 
227
- const scientificResearch = await anthropic.research({
228
- query: 'Latest breakthroughs in CRISPR gene editing',
229
- searchDepth: 'advanced',
205
+ const result = await generateText({
206
+ model,
207
+ prompt: 'Solve this step by step: what is 15% of 340?',
230
208
  });
231
209
 
232
- // Perplexity - Research-focused with citations
233
- const perplexityResearch = await ai.perplexityProvider.research({
234
- query: 'Current state of autonomous vehicle technology',
235
- searchDepth: 'deep', // Uses Sonar Pro model
236
- });
210
+ console.log(result.text);
237
211
  ```
238
212
 
239
- **Research Options:**
240
-
241
- - `searchDepth`: `'basic'` | `'advanced'` | `'deep'`
242
- - `maxSources`: Number of sources to include
243
- - `includeWebSearch`: Enable web search (OpenAI)
244
- - `background`: Run as background task (OpenAI)
213
+ ### Ollama Features
245
214
 
246
- **Supported Providers:**
215
+ - **`think` mode** — Enables reasoning for models that support it (Qwen3, QwQ, DeepSeek-R1). The `think` parameter is sent at the top level of the request body as required by the Ollama API.
216
+ - **Auto-tuned temperature** — Qwen models automatically get `temperature: 0.55` when no explicit temperature is set, matching the recommended inference setting.
217
+ - **Native tool calling** — Full tool call support via Ollama's native format (not shimmed through OpenAI-compatible endpoints).
218
+ - **Streaming with reasoning** — `doStream()` emits proper `reasoning-start`, `reasoning-delta`, `reasoning-end` parts alongside text.
219
+ - **All Ollama options** — `num_ctx`, `top_k`, `top_p`, `repeat_penalty`, `num_predict`, `stop`, `seed`.
247
220
 
248
- - **OpenAI**: Deep Research API with specialized models (`o3-deep-research-*`, `o4-mini-deep-research-*`)
249
- - **Anthropic**: Web Search API with domain filtering
250
- - **Perplexity**: Sonar and Sonar Pro models with built-in citations
221
+ ## 💰 Anthropic Prompt Caching
251
222
 
252
- ### 🧠 Extended Thinking (Anthropic)
253
-
254
- Enable Claude to spend more time reasoning about complex problems before generating responses:
223
+ When using the Anthropic provider, SmartAI automatically wraps the model with caching middleware that adds `cacheControl: { type: 'ephemeral' }` to the last system message and last user message. This can significantly reduce cost and latency for repeated calls with the same system prompt.
255
224
 
256
225
  ```typescript
257
- import { AnthropicProvider } from '@push.rocks/smartai';
258
-
259
- // Configure extended thinking mode at provider level
260
- const anthropic = new AnthropicProvider({
261
- anthropicToken: 'sk-ant-...',
262
- extendedThinking: 'normal', // Options: 'quick' | 'normal' | 'deep' | 'off'
226
+ // Caching enabled by default
227
+ const model = getModel({
228
+ provider: 'anthropic',
229
+ model: 'claude-sonnet-4-5-20250929',
230
+ apiKey: process.env.ANTHROPIC_TOKEN,
263
231
  });
264
232
 
265
- await anthropic.start();
266
-
267
- // Extended thinking is automatically applied to all methods
268
- const response = await anthropic.chat({
269
- systemMessage: 'You are an expert mathematician.',
270
- userMessage: 'Prove the Pythagorean theorem from first principles',
271
- messageHistory: [],
233
+ // Opt out of caching
234
+ const modelNoCaching = getModel({
235
+ provider: 'anthropic',
236
+ model: 'claude-sonnet-4-5-20250929',
237
+ apiKey: process.env.ANTHROPIC_TOKEN,
238
+ promptCaching: false,
272
239
  });
273
240
  ```
274
241
 
275
- **Thinking Modes:**
276
-
277
- | Mode | Budget Tokens | Use Case |
278
- | ---------- | ------------- | ------------------------------------------------ |
279
- | `'quick'` | 2,048 | Lightweight reasoning for simple queries |
280
- | `'normal'` | 8,000 | **Default** — Balanced reasoning for most tasks |
281
- | `'deep'` | 16,000 | Complex reasoning for difficult problems |
282
- | `'off'` | 0 | Disable extended thinking |
283
-
284
- **Best Practices:**
285
-
286
- - Start with `'normal'` (default) for general usage
287
- - Use `'deep'` for complex analytical tasks, philosophy, mathematics, or research
288
- - Use `'quick'` for simple factual queries where deep reasoning isn't needed
289
- - Thinking budget counts against total token usage
290
-
291
- ### 📑 Native PDF OCR (Mistral)
292
-
293
- Mistral provides native PDF document processing via their OCR API — no image conversion required:
242
+ You can also use the middleware directly:
294
243
 
295
244
  ```typescript
296
- import { MistralProvider } from '@push.rocks/smartai';
297
-
298
- const mistral = new MistralProvider({
299
- mistralToken: 'your-api-key',
300
- chatModel: 'mistral-large-latest', // Default
301
- ocrModel: 'mistral-ocr-latest', // Default
302
- tableFormat: 'markdown', // 'markdown' | 'html'
303
- });
304
-
305
- await mistral.start();
245
+ import { createAnthropicCachingMiddleware } from '@push.rocks/smartai';
246
+ import { wrapLanguageModel } from 'ai';
306
247
 
307
- // Direct PDF processing - no image conversion overhead
308
- const result = await mistral.document({
309
- systemMessage: 'You are a document analyst.',
310
- userMessage: 'Extract all invoice details and calculate the total.',
311
- pdfDocuments: [invoicePdfBuffer],
312
- messageHistory: [],
313
- });
248
+ const middleware = createAnthropicCachingMiddleware();
249
+ const cachedModel = wrapLanguageModel({ model: baseModel, middleware });
314
250
  ```
315
251
 
316
- **Key Advantage**: Unlike other providers that convert PDFs to images first, Mistral's OCR API processes PDFs natively, potentially offering faster and more accurate text extraction for document-heavy workloads.
317
-
318
- **Supported Formats:**
252
+ ## 📦 Subpath Exports
319
253
 
320
- - Native PDF processing via Files API
321
- - Image OCR (JPEG, PNG, GIF, WebP) for vision tasks
322
- - Table extraction with markdown or HTML output
254
+ SmartAI provides specialized capabilities as separate subpath imports. Each one is a focused utility that takes a model (or API key) and does one thing well.
323
255
 
324
- ### 🎨 Image Generation & Editing
256
+ ### 👁️ Vision `@push.rocks/smartai/vision`
325
257
 
326
- Generate and edit images with OpenAI's cutting-edge models:
258
+ Analyze images using any vision-capable model.
327
259
 
328
260
  ```typescript
329
- // Basic image generation with gpt-image-1
330
- const image = await ai.openaiProvider.imageGenerate({
331
- prompt: 'A futuristic robot assistant in a modern office, digital art',
332
- model: 'gpt-image-1',
333
- quality: 'high',
334
- size: '1024x1024',
335
- });
336
-
337
- // Save the generated image
338
- const imageBuffer = Buffer.from(image.images[0].b64_json!, 'base64');
339
- fs.writeFileSync('robot.png', imageBuffer);
340
-
341
- // Advanced: Transparent background with custom format
342
- const logo = await ai.openaiProvider.imageGenerate({
343
- prompt: 'Minimalist mountain peak logo, geometric design',
344
- model: 'gpt-image-1',
345
- quality: 'high',
346
- size: '1024x1024',
347
- background: 'transparent',
348
- outputFormat: 'png',
349
- });
350
-
351
- // WebP with compression for web use
352
- const webImage = await ai.openaiProvider.imageGenerate({
353
- prompt: 'Product showcase: sleek smartphone on marble surface',
354
- model: 'gpt-image-1',
355
- quality: 'high',
356
- size: '1536x1024',
357
- outputFormat: 'webp',
358
- outputCompression: 85,
261
+ import { analyzeImage } from '@push.rocks/smartai/vision';
262
+ import { getModel } from '@push.rocks/smartai';
263
+ import * as fs from 'fs';
264
+
265
+ const model = getModel({
266
+ provider: 'anthropic',
267
+ model: 'claude-sonnet-4-5-20250929',
268
+ apiKey: process.env.ANTHROPIC_TOKEN,
359
269
  });
360
270
 
361
- // Superior text rendering (gpt-image-1's strength)
362
- const signage = await ai.openaiProvider.imageGenerate({
363
- prompt:
364
- 'Vintage cafe sign saying "COFFEE & CODE" in hand-lettered typography',
365
- model: 'gpt-image-1',
366
- quality: 'high',
367
- size: '1024x1024',
271
+ const description = await analyzeImage({
272
+ model,
273
+ image: fs.readFileSync('photo.jpg'),
274
+ prompt: 'Describe this image in detail.',
275
+ mediaType: 'image/jpeg', // optional, defaults to 'image/jpeg'
368
276
  });
369
277
 
370
- // Generate multiple variations at once
371
- const variations = await ai.openaiProvider.imageGenerate({
372
- prompt: 'Abstract geometric pattern, colorful minimalist art',
373
- model: 'gpt-image-1',
374
- n: 3,
375
- quality: 'medium',
376
- size: '1024x1024',
377
- });
378
-
379
- // Edit an existing image
380
- const editedImage = await ai.openaiProvider.imageEdit({
381
- image: originalImageBuffer,
382
- prompt: 'Add sunglasses and change the background to a beach sunset',
383
- model: 'gpt-image-1',
384
- quality: 'high',
385
- });
278
+ console.log(description);
386
279
  ```
387
280
 
388
- **Image Generation Options:**
389
-
390
- - `model`: `'gpt-image-1'` | `'dall-e-3'` | `'dall-e-2'`
391
- - `quality`: `'low'` | `'medium'` | `'high'` | `'auto'`
392
- - `size`: Multiple aspect ratios up to 4096×4096
393
- - `background`: `'transparent'` | `'opaque'` | `'auto'`
394
- - `outputFormat`: `'png'` | `'jpeg'` | `'webp'`
395
- - `outputCompression`: 0–100 for webp/jpeg
396
- - `moderation`: `'low'` | `'auto'`
397
- - `n`: Number of images (1–10)
398
-
399
- **gpt-image-1 Advantages:**
400
-
401
- - Superior text rendering in images
402
- - Up to 4096×4096 resolution
403
- - Transparent background support
404
- - Advanced output formats (WebP with compression)
405
- - Better prompt understanding
406
- - Streaming support for progressive rendering
281
+ **`analyzeImage(options)`** accepts:
282
+ - `model` — Any `LanguageModelV3` with vision support
283
+ - `image` `Buffer` or `Uint8Array`
284
+ - `prompt` What to ask about the image
285
+ - `mediaType` `'image/jpeg'` | `'image/png'` | `'image/webp'` | `'image/gif'`
407
286
 
408
- ### 🔄 Persistent Conversations
287
+ ### 🎙️ Audio — `@push.rocks/smartai/audio`
409
288
 
410
- Maintain context across interactions:
289
+ Text-to-speech using OpenAI's TTS models.
411
290
 
412
291
  ```typescript
413
- // Create a coding assistant conversation
414
- const assistant = ai.createConversation('openai');
415
- await assistant.setSystemMessage('You are an expert TypeScript developer.');
416
-
417
- // First question
418
- const inputWriter = assistant.getInputStreamWriter();
419
- await inputWriter.write('How do I implement a singleton pattern?');
420
-
421
- // Continue the conversation
422
- await inputWriter.write('Now show me how to make it thread-safe');
292
+ import { textToSpeech } from '@push.rocks/smartai/audio';
293
+ import * as fs from 'fs';
294
+
295
+ const stream = await textToSpeech({
296
+ apiKey: process.env.OPENAI_TOKEN,
297
+ text: 'Welcome to the future of AI development!',
298
+ voice: 'nova', // 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer'
299
+ model: 'tts-1-hd', // 'tts-1' | 'tts-1-hd'
300
+ responseFormat: 'mp3', // 'mp3' | 'opus' | 'aac' | 'flac'
301
+ speed: 1.0, // 0.25 to 4.0
302
+ });
423
303
 
424
- // The assistant remembers the entire context
304
+ stream.pipe(fs.createWriteStream('welcome.mp3'));
425
305
  ```
426
306
 
427
- ## 🚀 Real-World Examples
307
+ ### 🎨 Image — `@push.rocks/smartai/image`
428
308
 
429
- ### Build a Customer Support Bot
309
+ Generate and edit images using OpenAI's image models.
430
310
 
431
311
  ```typescript
432
- const supportBot = new SmartAi({
433
- anthropicToken: process.env.ANTHROPIC_KEY, // Claude for empathetic responses
312
+ import { generateImage, editImage } from '@push.rocks/smartai/image';
313
+
314
+ // Generate an image
315
+ const result = await generateImage({
316
+ apiKey: process.env.OPENAI_TOKEN,
317
+ prompt: 'A futuristic cityscape at sunset, digital art',
318
+ model: 'gpt-image-1', // 'gpt-image-1' | 'dall-e-3' | 'dall-e-2'
319
+ quality: 'high', // 'low' | 'medium' | 'high' | 'auto'
320
+ size: '1024x1024',
321
+ background: 'transparent', // gpt-image-1 only
322
+ outputFormat: 'png', // 'png' | 'jpeg' | 'webp'
323
+ n: 1,
434
324
  });
435
325
 
436
- async function handleCustomerQuery(query: string, history: ChatMessage[]) {
437
- try {
438
- const response = await supportBot.anthropicProvider.chat({
439
- systemMessage: `You are a helpful customer support agent.
440
- Be empathetic, professional, and solution-oriented.`,
441
- userMessage: query,
442
- messageHistory: history,
443
- });
444
-
445
- return response.message;
446
- } catch (error) {
447
- // Fallback to another provider if needed
448
- return await supportBot.openaiProvider.chat({ /* ... */ });
449
- }
450
- }
451
- ```
452
-
453
- ### Create a Code Review Assistant
326
+ // result.images[0].b64_json base64-encoded image data
327
+ const imageBuffer = Buffer.from(result.images[0].b64_json!, 'base64');
454
328
 
455
- ```typescript
456
- const codeReviewer = new SmartAi({
457
- groqToken: process.env.GROQ_KEY, // Groq for speed
329
+ // Edit an existing image
330
+ const edited = await editImage({
331
+ apiKey: process.env.OPENAI_TOKEN,
332
+ image: imageBuffer,
333
+ prompt: 'Add a rainbow in the sky',
334
+ model: 'gpt-image-1',
458
335
  });
459
-
460
- async function reviewCode(code: string, language: string) {
461
- const review = await codeReviewer.groqProvider.chat({
462
- systemMessage: `You are a ${language} expert. Review code for:
463
- - Security vulnerabilities
464
- - Performance issues
465
- - Best practices
466
- - Potential bugs`,
467
- userMessage: `Review this code:\n\n${code}`,
468
- messageHistory: [],
469
- });
470
-
471
- return review.message;
472
- }
473
336
  ```
474
337
 
475
- ### Build a Research Assistant
338
+ ### 📄 Document `@push.rocks/smartai/document`
339
+
340
+ Analyze PDF documents by converting them to images and using a vision model. Uses `@push.rocks/smartpdf` for PDF-to-PNG conversion (requires Chromium/Puppeteer).
476
341
 
477
342
  ```typescript
478
- const researcher = new SmartAi({
479
- perplexityToken: process.env.PERPLEXITY_KEY,
343
+ import { analyzeDocuments, stopSmartpdf } from '@push.rocks/smartai/document';
344
+ import { getModel } from '@push.rocks/smartai';
345
+ import * as fs from 'fs';
346
+
347
+ const model = getModel({
348
+ provider: 'anthropic',
349
+ model: 'claude-sonnet-4-5-20250929',
350
+ apiKey: process.env.ANTHROPIC_TOKEN,
480
351
  });
481
352
 
482
- async function research(topic: string) {
483
- // Perplexity excels at web-aware research
484
- const findings = await researcher.perplexityProvider.research({
485
- query: `Research the latest developments in ${topic}`,
486
- searchDepth: 'deep',
487
- });
488
-
489
- return {
490
- answer: findings.answer,
491
- sources: findings.sources,
492
- };
493
- }
494
- ```
495
-
496
- ### Local AI for Sensitive Data
497
-
498
- ```typescript
499
- const localAI = new SmartAi({
500
- ollama: {
501
- baseUrl: 'http://localhost:11434',
502
- model: 'llama2',
503
- visionModel: 'llava',
504
- },
353
+ const analysis = await analyzeDocuments({
354
+ model,
355
+ systemMessage: 'You are a legal document analyst.',
356
+ userMessage: 'Summarize the key terms and conditions.',
357
+ pdfDocuments: [fs.readFileSync('contract.pdf')],
358
+ messageHistory: [], // optional: prior conversation context
505
359
  });
506
360
 
507
- // Process sensitive documents without leaving your infrastructure
508
- async function analyzeSensitiveDoc(pdfBuffer: Buffer) {
509
- const analysis = await localAI.ollamaProvider.document({
510
- systemMessage: 'Extract and summarize key information.',
511
- userMessage: 'Analyze this confidential document',
512
- messageHistory: [],
513
- pdfDocuments: [pdfBuffer],
514
- });
515
-
516
- // Data never leaves your servers
517
- return analysis.message;
518
- }
361
+ console.log(analysis);
362
+
363
+ // Clean up the SmartPdf instance when done
364
+ await stopSmartpdf();
519
365
  ```
520
366
 
521
- ## Performance Tips
367
+ ### 🔬 Research — `@push.rocks/smartai/research`
522
368
 
523
- ### 1. Provider Selection Strategy
369
+ Perform web-search-powered research using Anthropic's `web_search_20250305` tool.
524
370
 
525
371
  ```typescript
526
- class SmartAIRouter {
527
- constructor(private ai: SmartAi) {}
528
-
529
- async query(
530
- message: string,
531
- requirements: {
532
- speed?: boolean;
533
- accuracy?: boolean;
534
- cost?: boolean;
535
- privacy?: boolean;
536
- }
537
- ) {
538
- if (requirements.privacy) {
539
- return this.ai.ollamaProvider.chat({ /* ... */ }); // Local only
540
- }
541
- if (requirements.speed) {
542
- return this.ai.groqProvider.chat({ /* ... */ }); // 10x faster
543
- }
544
- if (requirements.accuracy) {
545
- return this.ai.anthropicProvider.chat({ /* ... */ }); // Best reasoning
546
- }
547
- // Default fallback
548
- return this.ai.openaiProvider.chat({ /* ... */ });
549
- }
550
- }
551
- ```
372
+ import { research } from '@push.rocks/smartai/research';
552
373
 
553
- ### 2. Streaming for Large Responses
374
+ const result = await research({
375
+ apiKey: process.env.ANTHROPIC_TOKEN,
376
+ query: 'What are the latest developments in quantum computing?',
377
+ searchDepth: 'basic', // 'basic' | 'advanced' | 'deep'
378
+ maxSources: 10, // optional: limit number of search results
379
+ allowedDomains: ['nature.com', 'arxiv.org'], // optional: restrict to domains
380
+ blockedDomains: ['reddit.com'], // optional: exclude domains
381
+ });
554
382
 
555
- ```typescript
556
- // Don't wait for the entire response
557
- async function streamResponse(userQuery: string) {
558
- const stream = await ai.openaiProvider.chatStream(
559
- createInputStream(userQuery)
560
- );
561
-
562
- // Process tokens as they arrive
563
- for await (const chunk of stream) {
564
- updateUI(chunk); // Immediate feedback
565
- await processChunk(chunk); // Parallel processing
566
- }
567
- }
383
+ console.log(result.answer);
384
+ console.log('Sources:', result.sources); // Array<{ url, title, snippet }>
385
+ console.log('Queries:', result.searchQueries); // search queries the model used
568
386
  ```
569
387
 
570
- ### 3. Parallel Multi-Provider Queries
388
+ ## 🧪 Testing
571
389
 
572
- ```typescript
573
- // Get the best answer from multiple AIs
574
- async function consensusQuery(question: string) {
575
- const providers = [
576
- ai.openaiProvider.chat({ /* ... */ }),
577
- ai.anthropicProvider.chat({ /* ... */ }),
578
- ai.perplexityProvider.chat({ /* ... */ }),
579
- ];
580
-
581
- const responses = await Promise.all(providers);
582
- return synthesizeResponses(responses);
583
- }
390
+ ```bash
391
+ # All tests
392
+ pnpm test
393
+
394
+ # Individual test files
395
+ tstest test/test.smartai.ts --verbose # Core getModel + generateText + streamText
396
+ tstest test/test.ollama.ts --verbose # Ollama provider (mocked, no API needed)
397
+ tstest test/test.vision.ts --verbose # Vision analysis
398
+ tstest test/test.image.ts --verbose # Image generation
399
+ tstest test/test.research.ts --verbose # Web research
400
+ tstest test/test.audio.ts --verbose # Text-to-speech
401
+ tstest test/test.document.ts --verbose # Document analysis (needs Chromium)
584
402
  ```
585
403
 
586
- ## 🛠️ Advanced Configuration
587
-
588
- ### Provider-Specific Options
589
-
590
- ```typescript
591
- const ai = new SmartAi({
592
- // OpenAI
593
- openaiToken: 'sk-...',
594
-
595
- // Anthropic with extended thinking
596
- anthropicToken: 'sk-ant-...',
597
-
598
- // Perplexity for research
599
- perplexityToken: 'pplx-...',
404
+ Most tests skip gracefully when API keys are not set. The Ollama tests are fully mocked and require no external services.
600
405
 
601
- // Groq for speed
602
- groqToken: 'gsk_...',
406
+ ## 📐 Architecture
603
407
 
604
- // Mistral with OCR settings
605
- mistralToken: 'your-key',
606
- mistral: {
607
- chatModel: 'mistral-large-latest',
608
- ocrModel: 'mistral-ocr-latest',
609
- tableFormat: 'markdown',
610
- },
611
-
612
- // XAI (Grok)
613
- xaiToken: 'xai-...',
614
-
615
- // ElevenLabs TTS
616
- elevenlabsToken: 'sk-...',
617
- elevenlabs: {
618
- defaultVoiceId: '19STyYD15bswVz51nqLf',
619
- defaultModelId: 'eleven_v3',
620
- },
621
-
622
- // Ollama (local)
623
- ollama: {
624
- baseUrl: 'http://localhost:11434',
625
- model: 'llama2',
626
- visionModel: 'llava',
627
- defaultOptions: {
628
- num_ctx: 4096,
629
- temperature: 0.7,
630
- top_p: 0.9,
631
- },
632
- defaultTimeout: 120000,
633
- },
634
-
635
- // Exo (distributed)
636
- exo: {
637
- baseUrl: 'http://localhost:8080/v1',
638
- apiKey: 'optional-key',
639
- },
640
- });
641
408
  ```
642
-
643
- ### Error Handling & Fallbacks
644
-
645
- ```typescript
646
- class ResilientAI {
647
- private providers = ['openai', 'anthropic', 'groq'];
648
-
649
- async query(opts: ChatOptions): Promise<ChatResponse> {
650
- for (const provider of this.providers) {
651
- try {
652
- return await this.ai[`${provider}Provider`].chat(opts);
653
- } catch (error) {
654
- console.warn(`${provider} failed, trying next...`);
655
- continue;
656
- }
657
- }
658
- throw new Error('All providers failed');
659
- }
660
- }
409
+ @push.rocks/smartai
410
+ ├── ts/ # Core package
411
+ │ ├── index.ts # Re-exports getModel, AI SDK functions, types
412
+ │ ├── smartai.classes.smartai.ts # getModel() — provider switch
413
+ │ ├── smartai.interfaces.ts # ISmartAiOptions, TProvider, IOllamaModelOptions
414
+ │ ├── smartai.provider.ollama.ts # Custom LanguageModelV3 for Ollama
415
+ │ ├── smartai.middleware.anthropic.ts # Prompt caching middleware
416
+ │ └── plugins.ts # AI SDK provider factories
417
+ ├── ts_vision/ # @push.rocks/smartai/vision
418
+ ├── ts_audio/ # @push.rocks/smartai/audio
419
+ ├── ts_image/ # @push.rocks/smartai/image
420
+ ├── ts_document/ # @push.rocks/smartai/document
421
+ └── ts_research/ # @push.rocks/smartai/research
661
422
  ```
662
423
 
663
- ## 🎯 Choosing the Right Provider
664
-
665
- | Use Case | Recommended Provider | Why |
666
- | --------------------- | -------------------- | --------------------------------------------------------- |
667
- | **General Purpose** | OpenAI | Most features, stable, well-documented |
668
- | **Complex Reasoning** | Anthropic | Superior logical thinking, extended thinking, safer |
669
- | **Document OCR** | Mistral | Native PDF processing, no image conversion overhead |
670
- | **Research & Facts** | Perplexity | Web-aware, provides citations |
671
- | **Deep Research** | OpenAI | Deep Research API with comprehensive analysis |
672
- | **Premium TTS** | ElevenLabs | Most natural voices, 70+ languages, v3 model |
673
- | **Speed Critical** | Groq | 10x faster inference, sub-second responses |
674
- | **Privacy Critical** | Ollama | 100% local, no data leaves your servers |
675
- | **Real-time Data** | XAI | Grok with access to current information |
676
- | **Cost Sensitive** | Ollama/Exo | Free (local) or distributed compute |
677
-
678
- ## 📈 Roadmap
679
-
680
- - [x] Research & Web Search API
681
- - [x] Image generation support (gpt-image-1, DALL-E 3, DALL-E 2)
682
- - [x] Extended thinking (Anthropic)
683
- - [x] Native PDF OCR (Mistral)
684
- - [ ] Streaming function calls
685
- - [ ] Voice input processing
686
- - [ ] Fine-tuning integration
687
- - [ ] Embedding support
688
- - [ ] Agent framework
689
- - [ ] More providers (Cohere, AI21, etc.)
424
+ The core package is a thin registry. `getModel()` creates the appropriate `@ai-sdk/*` provider, calls it with the model ID, and returns the resulting `LanguageModelV3`. For Anthropic, it optionally wraps the model with prompt caching middleware. For Ollama, it returns a custom `LanguageModelV3` implementation that talks directly to Ollama's `/api/chat` endpoint.
425
+
426
+ Subpath modules are independent they import `ai` and provider SDKs directly, not through the core package. This keeps the dependency graph clean and allows tree-shaking.
690
427
 
691
428
  ## License and Legal Information
692
429