@compilr-dev/sdk 0.18.8 → 0.18.10

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/dist/config.d.ts CHANGED
@@ -49,7 +49,7 @@ export interface CapabilitiesConfig {
49
49
  /**
50
50
  * Supported provider types for auto-detection
51
51
  */
52
- export type ProviderType = 'claude' | 'openai' | 'gemini' | 'ollama' | 'together' | 'groq' | 'fireworks' | 'perplexity' | 'openrouter' | 'custom';
52
+ export type ProviderType = 'claude' | 'openai' | 'gemini' | 'ollama' | 'ollama-anthropic' | 'together' | 'groq' | 'fireworks' | 'perplexity' | 'openrouter' | 'custom';
53
53
  /**
54
54
  * Tool configuration for controlling which tools are available
55
55
  */
package/dist/index.d.ts CHANGED
@@ -45,7 +45,7 @@ export type { Preset } from './presets/index.js';
45
45
  export type { AnyTool } from './presets/types.js';
46
46
  export { resolveProvider, detectProviderFromEnv, createProviderFromType } from './provider.js';
47
47
  export { DEFAULT_MODELS, getContextWindow, DEFAULT_CONTEXT_WINDOW } from './models.js';
48
- export { type ModelTier, type TierInfo, type ProviderModelMap, MODEL_TIERS, TIER_INFO, isValidTier, type ThinkingFormat, type ModelStatus, type ModelInfo, MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, modelSupportsImages, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription, getModelForTier, getTierMappings, getTierDisplayName, getShortModelName, getDefaultTierMappings, type ProviderMetadata, type OthersProviderModel, PROVIDER_METADATA, TOGETHER_MODELS, GROQ_MODELS, FIREWORKS_MODELS, PERPLEXITY_MODELS, OPENROUTER_MODELS, getModelsForOthersProvider, getOthersProviders, getProviderMetadata, isOthersProvider, } from './models/index.js';
48
+ export { type ModelTier, type TierInfo, type ProviderModelMap, MODEL_TIERS, TIER_INFO, isValidTier, type ThinkingFormat, type ModelStatus, type ModelInfo, MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, modelSupportsImages, modelSupportsTools, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription, getModelForTier, getTierMappings, getTierDisplayName, getShortModelName, getDefaultTierMappings, type ProviderMetadata, type OthersProviderModel, PROVIDER_METADATA, TOGETHER_MODELS, GROQ_MODELS, FIREWORKS_MODELS, PERPLEXITY_MODELS, OPENROUTER_MODELS, getModelsForOthersProvider, getOthersProviders, getProviderMetadata, isOthersProvider, type OllamaModelInfo, type OllamaModelsResult, OLLAMA_ANTHROPIC_MIN_VERSION, listOllamaModels, getOllamaVersion, isOllamaAnthropicCompatible, clearOllamaModelsCache, formatOllamaModelSize, getOllamaModelDisplayName, getOllamaModelDescription, } from './models/index.js';
49
49
  export { assembleTools, deduplicateTools } from './tools.js';
50
50
  export { MetaToolsRegistry, createMetaTools, META_TOOLS_SYSTEM_PROMPT_PREFIX, } from './meta-tools/index.js';
51
51
  export type { MetaToolStats, MetaTools, FallbackOptions } from './meta-tools/index.js';
package/dist/index.js CHANGED
@@ -83,9 +83,9 @@ export { DEFAULT_MODELS, getContextWindow, DEFAULT_CONTEXT_WINDOW } from './mode
83
83
  // =============================================================================
84
84
  // Model Registry, Tiers, Providers (full model system)
85
85
  // =============================================================================
86
- export { MODEL_TIERS, TIER_INFO, isValidTier, MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, modelSupportsImages, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription,
86
+ export { MODEL_TIERS, TIER_INFO, isValidTier, MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, modelSupportsImages, modelSupportsTools, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription,
87
87
  // Model tiers (pure, settings-free)
88
- getModelForTier, getTierMappings, getTierDisplayName, getShortModelName, getDefaultTierMappings, PROVIDER_METADATA, TOGETHER_MODELS, GROQ_MODELS, FIREWORKS_MODELS, PERPLEXITY_MODELS, OPENROUTER_MODELS, getModelsForOthersProvider, getOthersProviders, getProviderMetadata, isOthersProvider, } from './models/index.js';
88
+ getModelForTier, getTierMappings, getTierDisplayName, getShortModelName, getDefaultTierMappings, PROVIDER_METADATA, TOGETHER_MODELS, GROQ_MODELS, FIREWORKS_MODELS, PERPLEXITY_MODELS, OPENROUTER_MODELS, getModelsForOthersProvider, getOthersProviders, getProviderMetadata, isOthersProvider, OLLAMA_ANTHROPIC_MIN_VERSION, listOllamaModels, getOllamaVersion, isOllamaAnthropicCompatible, clearOllamaModelsCache, formatOllamaModelSize, getOllamaModelDisplayName, getOllamaModelDescription, } from './models/index.js';
89
89
  // =============================================================================
90
90
  // Tool Assembly
91
91
  // =============================================================================
@@ -2,6 +2,7 @@
2
2
  * Models Module — Barrel Export
3
3
  */
4
4
  export { type ModelTier, type TierInfo, type ProviderModelMap, MODEL_TIERS, TIER_INFO, isValidTier, } from './types.js';
5
- export { type ThinkingFormat, type ModelStatus, type ModelInfo, MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, modelSupportsImages, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription, } from './model-registry.js';
5
+ export { type ThinkingFormat, type ModelStatus, type ModelInfo, MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, modelSupportsImages, modelSupportsTools, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription, } from './model-registry.js';
6
6
  export { getModelForTier, getTierMappings, getTierDisplayName, getShortModelName, getDefaultTierMappings, } from './model-tiers.js';
7
7
  export { type ProviderMetadata, type OthersProviderModel, PROVIDER_METADATA, TOGETHER_MODELS, GROQ_MODELS, FIREWORKS_MODELS, PERPLEXITY_MODELS, OPENROUTER_MODELS, getModelsForOthersProvider, getOthersProviders, getProviderMetadata, isOthersProvider, } from './providers.js';
8
+ export { type OllamaModelInfo, type OllamaModelsResult, OLLAMA_ANTHROPIC_MIN_VERSION, listOllamaModels, getOllamaVersion, isOllamaAnthropicCompatible, clearOllamaModelsCache, formatOllamaModelSize, getOllamaModelDisplayName, getOllamaModelDescription, } from './ollama-discovery.js';
@@ -4,8 +4,10 @@
4
4
  // Types & constants
5
5
  export { MODEL_TIERS, TIER_INFO, isValidTier, } from './types.js';
6
6
  // Model registry
7
- export { MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, modelSupportsImages, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription, } from './model-registry.js';
7
+ export { MODEL_REGISTRY, getModelsForProvider, getModelsSortedForDisplay, getModelInfo, isKnownModel, isModelSupported, modelSupportsImages, modelSupportsTools, getThinkingFormat, getStatusIndicator, getStatusLabel, getDefaultModelForTier, areThinkingFormatsCompatible, shouldClearHistoryOnModelChange, getModelContextWindow, getModelDisplayName, getModelDescription, } from './model-registry.js';
8
8
  // Model tiers (pure, settings-free)
9
9
  export { getModelForTier, getTierMappings, getTierDisplayName, getShortModelName, getDefaultTierMappings, } from './model-tiers.js';
10
10
  // Provider metadata
11
11
  export { PROVIDER_METADATA, TOGETHER_MODELS, GROQ_MODELS, FIREWORKS_MODELS, PERPLEXITY_MODELS, OPENROUTER_MODELS, getModelsForOthersProvider, getOthersProviders, getProviderMetadata, isOthersProvider, } from './providers.js';
12
+ // Ollama discovery (host-agnostic — list installed models + version gate)
13
+ export { OLLAMA_ANTHROPIC_MIN_VERSION, listOllamaModels, getOllamaVersion, isOllamaAnthropicCompatible, clearOllamaModelsCache, formatOllamaModelSize, getOllamaModelDisplayName, getOllamaModelDescription, } from './ollama-discovery.js';
@@ -34,6 +34,11 @@ export interface ModelInfo {
34
34
  /** Whether the model accepts image inputs (vision / multimodal). When unset,
35
35
  * callers fall back to a provider/id heuristic — see modelSupportsImages(). */
36
36
  supportsImages?: boolean;
37
+ /** Whether the model supports native tool / function calling. When unset,
38
+ * callers fall back to a provider/id heuristic — see modelSupportsTools().
39
+ * Set explicitly to `false` for models with weak/absent tool support (e.g.
40
+ * some small local models) so callers can warn or filter. */
41
+ supportsTools?: boolean;
37
42
  /** Default tier mapping (fast/balanced/powerful) - undefined if not a default */
38
43
  defaultTier?: ModelTier;
39
44
  /** Thinking block format this model uses */
@@ -86,6 +91,19 @@ export declare function isModelSupported(modelId: string): boolean;
86
91
  * dropping an attached image (canvas-robustness: image on a text-only model).
87
92
  */
88
93
  export declare function modelSupportsImages(modelId: string): boolean;
94
+ /**
95
+ * Whether a model supports native tool / function calling.
96
+ *
97
+ * Uses the registry's `supportsTools` when set; otherwise infers from the
98
+ * provider/id — all modern Claude, Gemini, and GPT-4o/4.1/5 support tools, as
99
+ * do the hosted OpenAI-compatible aggregators (Together/Groq/Fireworks/
100
+ * OpenRouter). Perplexity Sonar (search) and reasoning-only local models
101
+ * (deepseek-r1, mistral, codellama) do not. Defaults to TRUE for anything
102
+ * unrecognized — the wired providers all send the tools param, so a false
103
+ * negative would needlessly disable tools; genuinely tool-incapable models are
104
+ * marked `supportsTools: false` explicitly in the registry.
105
+ */
106
+ export declare function modelSupportsTools(modelId: string): boolean;
89
107
  /**
90
108
  * Get the thinking format for a model.
91
109
  * Returns 'none' for unknown models (safe default).
@@ -17,7 +17,9 @@
17
17
  */
18
18
  export const MODEL_REGISTRY = [
19
19
  // ---------------------------------------------------------------------------
20
- // Claude Models (Anthropic) — Current generation (4.6 + Haiku 4.5)
20
+ // Claude Models (Anthropic) — Current generation
21
+ // Fable 5 / Opus 4.8 / Sonnet 5 / Haiku 4.5. The 4.6+ family is 1M-context
22
+ // native (no beta opt-in). All support text+image input and tool use.
21
23
  // ---------------------------------------------------------------------------
22
24
  {
23
25
  id: 'claude-haiku-4-5-20251001',
@@ -25,69 +27,84 @@ export const MODEL_REGISTRY = [
25
27
  description: 'Fast, low cost',
26
28
  provider: 'claude',
27
29
  supportsImages: true,
30
+ supportsTools: true,
28
31
  defaultTier: 'fast',
29
32
  thinkingFormat: 'claude',
30
33
  status: 'supported',
31
34
  contextWindow: 200000,
32
35
  },
33
36
  {
34
- id: 'claude-sonnet-4-6',
35
- displayName: 'Sonnet 4.6',
37
+ id: 'claude-sonnet-5',
38
+ displayName: 'Sonnet 5',
36
39
  description: 'Balanced (recommended)',
37
40
  provider: 'claude',
38
41
  supportsImages: true,
42
+ supportsTools: true,
39
43
  defaultTier: 'balanced',
40
44
  thinkingFormat: 'claude',
41
45
  status: 'supported',
42
- contextWindow: 200000,
43
- extendedContextWindow: 1000000,
46
+ contextWindow: 1000000,
44
47
  },
45
48
  {
46
- id: 'claude-opus-4-6',
47
- displayName: 'Opus 4.6',
49
+ id: 'claude-opus-4-8',
50
+ displayName: 'Opus 4.8',
48
51
  description: 'Most capable',
49
52
  provider: 'claude',
50
53
  supportsImages: true,
54
+ supportsTools: true,
51
55
  defaultTier: 'powerful',
52
56
  thinkingFormat: 'claude',
53
57
  status: 'supported',
54
- contextWindow: 200000,
55
- extendedContextWindow: 1000000,
58
+ contextWindow: 1000000,
59
+ },
60
+ {
61
+ id: 'claude-fable-5',
62
+ displayName: 'Fable 5',
63
+ description: 'Highest capability, long-running agents',
64
+ provider: 'claude',
65
+ supportsImages: true,
66
+ supportsTools: true,
67
+ thinkingFormat: 'claude',
68
+ status: 'supported',
69
+ contextWindow: 1000000,
70
+ notes: 'Flagship: adaptive thinking always on; premium pricing ($10/$50 per MTok)',
56
71
  },
57
72
  // Legacy Claude models (still supported)
58
73
  {
59
- id: 'claude-sonnet-4-5-20250929',
60
- displayName: 'Sonnet 4.5',
74
+ id: 'claude-opus-4-7',
75
+ displayName: 'Opus 4.7',
61
76
  description: 'Previous generation',
62
77
  provider: 'claude',
63
78
  supportsImages: true,
79
+ supportsTools: true,
64
80
  thinkingFormat: 'claude',
65
81
  status: 'supported',
66
- contextWindow: 200000,
67
- notes: 'Legacy — consider upgrading to Sonnet 4.6',
82
+ contextWindow: 1000000,
83
+ notes: 'Legacy — consider upgrading to Opus 4.8',
68
84
  },
69
85
  {
70
- id: 'claude-opus-4-5-20251101',
71
- displayName: 'Opus 4.5',
86
+ id: 'claude-opus-4-6',
87
+ displayName: 'Opus 4.6',
72
88
  description: 'Previous generation',
73
89
  provider: 'claude',
74
90
  supportsImages: true,
91
+ supportsTools: true,
75
92
  thinkingFormat: 'claude',
76
93
  status: 'supported',
77
- contextWindow: 200000,
78
- notes: 'Legacy — consider upgrading to Opus 4.6',
94
+ contextWindow: 1000000,
95
+ notes: 'Legacy — consider upgrading to Opus 4.8',
79
96
  },
80
97
  {
81
- id: 'claude-sonnet-4-20250514',
82
- displayName: 'Sonnet 4',
98
+ id: 'claude-sonnet-4-6',
99
+ displayName: 'Sonnet 4.6',
83
100
  description: 'Previous generation',
84
101
  provider: 'claude',
85
102
  supportsImages: true,
103
+ supportsTools: true,
86
104
  thinkingFormat: 'claude',
87
105
  status: 'supported',
88
- contextWindow: 200000,
89
- extendedContextWindow: 1000000,
90
- notes: 'Legacy',
106
+ contextWindow: 1000000,
107
+ notes: 'Legacy — consider upgrading to Sonnet 5',
91
108
  },
92
109
  // ---------------------------------------------------------------------------
93
110
  // Gemini Models (Google)
@@ -163,12 +180,26 @@ export const MODEL_REGISTRY = [
163
180
  // ---------------------------------------------------------------------------
164
181
  // OpenAI Models
165
182
  // ---------------------------------------------------------------------------
183
+ {
184
+ id: 'gpt-5.2-2025-12-11',
185
+ displayName: 'GPT-5.2',
186
+ description: 'Most capable',
187
+ provider: 'openai',
188
+ supportsImages: true,
189
+ supportsTools: true,
190
+ defaultTier: 'powerful',
191
+ thinkingFormat: 'none',
192
+ status: 'supported',
193
+ contextWindow: 400000,
194
+ notes: 'Latest generation',
195
+ },
166
196
  {
167
197
  id: 'gpt-4o',
168
198
  displayName: 'GPT-4o',
169
199
  description: 'Balanced (recommended)',
170
200
  provider: 'openai',
171
201
  supportsImages: true,
202
+ supportsTools: true,
172
203
  defaultTier: 'balanced',
173
204
  thinkingFormat: 'none',
174
205
  status: 'supported',
@@ -180,151 +211,139 @@ export const MODEL_REGISTRY = [
180
211
  description: 'Fast, low cost',
181
212
  provider: 'openai',
182
213
  supportsImages: true,
214
+ supportsTools: true,
183
215
  defaultTier: 'fast',
184
216
  thinkingFormat: 'none',
185
217
  status: 'supported',
186
218
  contextWindow: 128000,
187
219
  },
188
220
  {
189
- id: 'gpt-4-turbo',
190
- displayName: 'GPT-4 Turbo',
191
- description: 'Most capable',
221
+ id: 'gpt-5-mini-2025-08-07',
222
+ displayName: 'GPT-5 Mini',
223
+ description: 'Balanced, latest generation',
192
224
  provider: 'openai',
193
225
  supportsImages: true,
194
- defaultTier: 'powerful',
226
+ supportsTools: true,
195
227
  thinkingFormat: 'none',
196
228
  status: 'supported',
197
- contextWindow: 128000,
229
+ contextWindow: 400000,
198
230
  },
199
- // GPT-5 models (if available)
200
231
  {
201
232
  id: 'gpt-5-nano-2025-08-07',
202
233
  displayName: 'GPT-5 Nano',
203
- description: 'Fast, experimental',
204
- provider: 'openai',
205
- supportsImages: true,
206
- thinkingFormat: 'none',
207
- status: 'experimental',
208
- contextWindow: 128000,
209
- notes: 'Latest generation',
210
- },
211
- {
212
- id: 'gpt-5-mini-2025-08-07',
213
- displayName: 'GPT-5 Mini',
214
- description: 'Balanced, experimental',
215
- provider: 'openai',
216
- supportsImages: true,
217
- thinkingFormat: 'none',
218
- status: 'experimental',
219
- contextWindow: 128000,
220
- notes: 'Latest generation',
221
- },
222
- {
223
- id: 'gpt-5.2-2025-12-11',
224
- displayName: 'GPT-5.2',
225
- description: 'Most capable, experimental',
234
+ description: 'Fast, latest generation',
226
235
  provider: 'openai',
227
236
  supportsImages: true,
237
+ supportsTools: true,
228
238
  thinkingFormat: 'none',
229
- status: 'experimental',
230
- contextWindow: 128000,
231
- notes: 'Latest generation',
239
+ status: 'supported',
240
+ contextWindow: 400000,
232
241
  },
233
242
  // ---------------------------------------------------------------------------
234
243
  // Ollama Models (Local)
235
244
  // ---------------------------------------------------------------------------
236
245
  {
237
- id: 'llama3.2:8b',
238
- displayName: 'Llama 3.2 8B',
246
+ id: 'llama3.2:3b',
247
+ displayName: 'Llama 3.2 3B',
239
248
  description: 'Fast, small',
240
249
  provider: 'ollama',
250
+ supportsTools: true,
241
251
  defaultTier: 'fast',
242
252
  thinkingFormat: 'none',
243
253
  status: 'supported',
244
- notes: 'Requires: ollama pull llama3.2:8b',
254
+ notes: 'Requires: ollama pull llama3.2:3b',
245
255
  },
246
256
  {
247
- id: 'llama3.2:70b',
248
- displayName: 'Llama 3.2 70B',
249
- description: 'Most capable',
257
+ id: 'qwen2.5:7b',
258
+ displayName: 'Qwen 2.5 7B',
259
+ description: 'Balanced, multilingual',
250
260
  provider: 'ollama',
251
- defaultTier: 'powerful',
261
+ supportsTools: true,
262
+ defaultTier: 'balanced',
252
263
  thinkingFormat: 'none',
253
264
  status: 'supported',
254
- notes: 'Requires: ollama pull llama3.2:70b',
265
+ notes: 'Tool-capable. Requires: ollama pull qwen2.5:7b',
255
266
  },
256
267
  {
257
- id: 'deepseek-r1:14b',
258
- displayName: 'DeepSeek R1 14B',
259
- description: 'Balanced, reasoning',
268
+ id: 'llama3.3:70b',
269
+ displayName: 'Llama 3.3 70B',
270
+ description: 'Most capable',
260
271
  provider: 'ollama',
261
- defaultTier: 'balanced',
272
+ supportsTools: true,
273
+ defaultTier: 'powerful',
262
274
  thinkingFormat: 'none',
263
275
  status: 'supported',
264
- notes: 'Requires: ollama pull deepseek-r1:14b',
276
+ notes: 'Requires: ollama pull llama3.3:70b',
265
277
  },
266
278
  {
267
- id: 'deepseek-r1:32b',
268
- displayName: 'DeepSeek R1 32B',
269
- description: 'Strong reasoning',
279
+ id: 'qwen2.5:32b',
280
+ displayName: 'Qwen 2.5 32B',
281
+ description: 'Strong multilingual',
270
282
  provider: 'ollama',
283
+ supportsTools: true,
271
284
  thinkingFormat: 'none',
272
285
  status: 'supported',
273
- notes: 'Requires: ollama pull deepseek-r1:32b',
286
+ notes: 'Requires: ollama pull qwen2.5:32b',
274
287
  },
275
288
  {
276
- id: 'qwen2.5:7b',
277
- displayName: 'Qwen 2.5 7B',
278
- description: 'Fast, multilingual',
289
+ id: 'deepseek-r1:14b',
290
+ displayName: 'DeepSeek R1 14B',
291
+ description: 'Reasoning (no tools)',
279
292
  provider: 'ollama',
293
+ supportsTools: false,
280
294
  thinkingFormat: 'none',
281
295
  status: 'supported',
282
- notes: 'Requires: ollama pull qwen2.5:7b',
296
+ notes: 'Reasoning model — limited/no function calling. Requires: ollama pull deepseek-r1:14b',
283
297
  },
284
298
  {
285
- id: 'qwen2.5:32b',
286
- displayName: 'Qwen 2.5 32B',
287
- description: 'Strong multilingual',
299
+ id: 'deepseek-r1:32b',
300
+ displayName: 'DeepSeek R1 32B',
301
+ description: 'Strong reasoning (no tools)',
288
302
  provider: 'ollama',
303
+ supportsTools: false,
289
304
  thinkingFormat: 'none',
290
305
  status: 'supported',
291
- notes: 'Requires: ollama pull qwen2.5:32b',
306
+ notes: 'Reasoning model — limited/no function calling. Requires: ollama pull deepseek-r1:32b',
292
307
  },
293
308
  {
294
309
  id: 'mistral:7b',
295
310
  displayName: 'Mistral 7B',
296
- description: 'Fast, efficient',
311
+ description: 'Fast, efficient (no tools)',
297
312
  provider: 'ollama',
313
+ supportsTools: false,
298
314
  thinkingFormat: 'none',
299
315
  status: 'supported',
300
- notes: 'Requires: ollama pull mistral:7b',
316
+ notes: 'Weak/no native tool calling. Requires: ollama pull mistral:7b',
301
317
  },
302
318
  {
303
319
  id: 'codellama:13b',
304
320
  displayName: 'Code Llama 13B',
305
- description: 'Code-focused',
321
+ description: 'Code-focused (no tools)',
306
322
  provider: 'ollama',
323
+ supportsTools: false,
307
324
  thinkingFormat: 'none',
308
325
  status: 'supported',
309
- notes: 'Optimized for code. Requires: ollama pull codellama:13b',
326
+ notes: 'No native tool calling. Requires: ollama pull codellama:13b',
310
327
  },
311
328
  // ---------------------------------------------------------------------------
312
329
  // Together AI Models (OpenAI-compatible)
313
330
  // ---------------------------------------------------------------------------
314
331
  {
315
- id: 'meta-llama/Llama-3.2-8B-Instruct-Turbo',
316
- displayName: 'Llama 3.2 8B Instruct',
332
+ id: 'meta-llama/Llama-3.1-8B-Instruct-Turbo',
333
+ displayName: 'Llama 3.1 8B Instruct',
317
334
  description: 'Fast, low cost',
318
335
  provider: 'together',
336
+ supportsTools: true,
319
337
  defaultTier: 'fast',
320
338
  thinkingFormat: 'none',
321
339
  status: 'supported',
322
340
  },
323
341
  {
324
- id: 'meta-llama/Llama-3.2-70B-Instruct-Turbo',
325
- displayName: 'Llama 3.2 70B Instruct',
342
+ id: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
343
+ displayName: 'Llama 3.3 70B Instruct',
326
344
  description: 'Balanced',
327
345
  provider: 'together',
346
+ supportsTools: true,
328
347
  defaultTier: 'balanced',
329
348
  thinkingFormat: 'none',
330
349
  status: 'supported',
@@ -334,6 +353,7 @@ export const MODEL_REGISTRY = [
334
353
  displayName: 'DeepSeek R1 70B',
335
354
  description: 'Most capable',
336
355
  provider: 'together',
356
+ supportsTools: true,
337
357
  defaultTier: 'powerful',
338
358
  thinkingFormat: 'none',
339
359
  status: 'supported',
@@ -342,19 +362,21 @@ export const MODEL_REGISTRY = [
342
362
  // Groq Models (OpenAI-compatible, fast inference)
343
363
  // ---------------------------------------------------------------------------
344
364
  {
345
- id: 'llama-3.2-8b-instant',
346
- displayName: 'Llama 3.2 8B',
365
+ id: 'llama-3.1-8b-instant',
366
+ displayName: 'Llama 3.1 8B',
347
367
  description: 'Fast, low cost',
348
368
  provider: 'groq',
369
+ supportsTools: true,
349
370
  defaultTier: 'fast',
350
371
  thinkingFormat: 'none',
351
372
  status: 'supported',
352
373
  },
353
374
  {
354
- id: 'llama-3.2-70b-versatile',
355
- displayName: 'Llama 3.2 70B',
375
+ id: 'llama-3.3-70b-versatile',
376
+ displayName: 'Llama 3.3 70B',
356
377
  description: 'Balanced',
357
378
  provider: 'groq',
379
+ supportsTools: true,
358
380
  defaultTier: 'balanced',
359
381
  thinkingFormat: 'none',
360
382
  status: 'supported',
@@ -364,6 +386,7 @@ export const MODEL_REGISTRY = [
364
386
  displayName: 'DeepSeek R1 70B',
365
387
  description: 'Most capable',
366
388
  provider: 'groq',
389
+ supportsTools: true,
367
390
  defaultTier: 'powerful',
368
391
  thinkingFormat: 'none',
369
392
  status: 'supported',
@@ -372,19 +395,21 @@ export const MODEL_REGISTRY = [
372
395
  // Fireworks AI Models (OpenAI-compatible)
373
396
  // ---------------------------------------------------------------------------
374
397
  {
375
- id: 'accounts/fireworks/models/llama-v3p2-8b-instruct',
376
- displayName: 'Llama 3.2 8B',
398
+ id: 'accounts/fireworks/models/llama-v3p1-8b-instruct',
399
+ displayName: 'Llama 3.1 8B',
377
400
  description: 'Fast, low cost',
378
401
  provider: 'fireworks',
402
+ supportsTools: true,
379
403
  defaultTier: 'fast',
380
404
  thinkingFormat: 'none',
381
405
  status: 'supported',
382
406
  },
383
407
  {
384
- id: 'accounts/fireworks/models/llama-v3p2-70b-instruct',
385
- displayName: 'Llama 3.2 70B',
408
+ id: 'accounts/fireworks/models/llama-v3p3-70b-instruct',
409
+ displayName: 'Llama 3.3 70B',
386
410
  description: 'Balanced',
387
411
  provider: 'fireworks',
412
+ supportsTools: true,
388
413
  defaultTier: 'balanced',
389
414
  thinkingFormat: 'none',
390
415
  status: 'supported',
@@ -394,6 +419,7 @@ export const MODEL_REGISTRY = [
394
419
  displayName: 'DeepSeek R1',
395
420
  description: 'Most capable',
396
421
  provider: 'fireworks',
422
+ supportsTools: true,
397
423
  defaultTier: 'powerful',
398
424
  thinkingFormat: 'none',
399
425
  status: 'supported',
@@ -402,61 +428,67 @@ export const MODEL_REGISTRY = [
402
428
  // Perplexity Models (Search-augmented AI)
403
429
  // ---------------------------------------------------------------------------
404
430
  {
405
- id: 'llama-3.1-sonar-small-128k-online',
406
- displayName: 'Sonar Small',
431
+ id: 'sonar',
432
+ displayName: 'Sonar',
407
433
  description: 'Fast, low cost',
408
434
  provider: 'perplexity',
435
+ supportsTools: false,
409
436
  defaultTier: 'fast',
410
437
  thinkingFormat: 'none',
411
438
  status: 'supported',
412
- notes: 'Includes real-time web search',
439
+ notes: 'Real-time web search; no function calling',
413
440
  },
414
441
  {
415
- id: 'llama-3.1-sonar-large-128k-online',
416
- displayName: 'Sonar Large',
442
+ id: 'sonar-pro',
443
+ displayName: 'Sonar Pro',
417
444
  description: 'Balanced',
418
445
  provider: 'perplexity',
446
+ supportsTools: false,
419
447
  defaultTier: 'balanced',
420
448
  thinkingFormat: 'none',
421
449
  status: 'supported',
422
- notes: 'Includes real-time web search',
450
+ notes: 'Real-time web search; no function calling',
423
451
  },
424
452
  {
425
- id: 'llama-3.1-sonar-huge-128k-online',
426
- displayName: 'Sonar Huge',
453
+ id: 'sonar-reasoning-pro',
454
+ displayName: 'Sonar Reasoning Pro',
427
455
  description: 'Most capable',
428
456
  provider: 'perplexity',
457
+ supportsTools: false,
429
458
  defaultTier: 'powerful',
430
459
  thinkingFormat: 'none',
431
460
  status: 'supported',
432
- notes: 'Includes real-time web search',
461
+ notes: 'Real-time web search + reasoning; no function calling',
433
462
  },
434
463
  // ---------------------------------------------------------------------------
435
464
  // OpenRouter Models (Aggregator - access many providers)
436
465
  // ---------------------------------------------------------------------------
437
466
  {
438
- id: 'meta-llama/llama-3.2-8b-instruct',
439
- displayName: 'Llama 3.2 8B',
467
+ id: 'meta-llama/llama-3.1-8b-instruct',
468
+ displayName: 'Llama 3.1 8B',
440
469
  description: 'Fast, low cost',
441
470
  provider: 'openrouter',
471
+ supportsTools: true,
442
472
  defaultTier: 'fast',
443
473
  thinkingFormat: 'none',
444
474
  status: 'supported',
445
475
  },
446
476
  {
447
- id: 'anthropic/claude-sonnet-4-6',
448
- displayName: 'Claude Sonnet 4.6',
477
+ id: 'anthropic/claude-sonnet-5',
478
+ displayName: 'Claude Sonnet 5',
449
479
  description: 'Balanced (via OpenRouter)',
450
480
  provider: 'openrouter',
481
+ supportsTools: true,
451
482
  defaultTier: 'balanced',
452
483
  thinkingFormat: 'none',
453
484
  status: 'supported',
454
485
  },
455
486
  {
456
- id: 'anthropic/claude-opus-4-6',
457
- displayName: 'Claude Opus 4.6',
487
+ id: 'anthropic/claude-opus-4-8',
488
+ displayName: 'Claude Opus 4.8',
458
489
  description: 'Most capable (via OpenRouter)',
459
490
  provider: 'openrouter',
491
+ supportsTools: true,
460
492
  defaultTier: 'powerful',
461
493
  thinkingFormat: 'none',
462
494
  status: 'supported',
@@ -538,6 +570,29 @@ export function modelSupportsImages(modelId) {
538
570
  return true;
539
571
  return false;
540
572
  }
573
+ /**
574
+ * Whether a model supports native tool / function calling.
575
+ *
576
+ * Uses the registry's `supportsTools` when set; otherwise infers from the
577
+ * provider/id — all modern Claude, Gemini, and GPT-4o/4.1/5 support tools, as
578
+ * do the hosted OpenAI-compatible aggregators (Together/Groq/Fireworks/
579
+ * OpenRouter). Perplexity Sonar (search) and reasoning-only local models
580
+ * (deepseek-r1, mistral, codellama) do not. Defaults to TRUE for anything
581
+ * unrecognized — the wired providers all send the tools param, so a false
582
+ * negative would needlessly disable tools; genuinely tool-incapable models are
583
+ * marked `supportsTools: false` explicitly in the registry.
584
+ */
585
+ export function modelSupportsTools(modelId) {
586
+ const info = getModelInfo(modelId);
587
+ if (info?.supportsTools !== undefined)
588
+ return info.supportsTools;
589
+ const id = modelId.toLowerCase();
590
+ if (id.includes('sonar'))
591
+ return false;
592
+ if (/deepseek-r1|mistral|codellama/.test(id))
593
+ return false;
594
+ return true;
595
+ }
541
596
  /**
542
597
  * Get the thinking format for a model.
543
598
  * Returns 'none' for unknown models (safe default).
@@ -629,6 +684,7 @@ function getProviderContextLimitFallback(provider) {
629
684
  case 'openai':
630
685
  return 128000;
631
686
  case 'ollama':
687
+ case 'ollama-anthropic':
632
688
  return 32000;
633
689
  case 'together':
634
690
  return 131072;
@@ -26,7 +26,9 @@ export declare function getTierMappings(provider: ProviderType, overrides?: Part
26
26
  export declare function getTierDisplayName(tier: ModelTier): string;
27
27
  /**
28
28
  * Get short model name from full model ID (for display).
29
- * e.g., "claude-sonnet-4-5-20250929" -> "Sonnet 4.5"
29
+ * Prefers the registry's exact display name (single source of truth);
30
+ * falls back to a version-less heuristic for ids not in the registry.
31
+ * e.g., "claude-opus-4-8" -> "Opus 4.8"; "claude-opus-9" -> "Opus".
30
32
  */
31
33
  export declare function getShortModelName(modelId: string): string;
32
34
  /**
@@ -6,7 +6,7 @@
6
6
  * CLI wraps these with its settings layer.
7
7
  */
8
8
  import { TIER_INFO } from './types.js';
9
- import { getDefaultModelForTier as getDefaultFromRegistry } from './model-registry.js';
9
+ import { getDefaultModelForTier as getDefaultFromRegistry, getModelInfo, } from './model-registry.js';
10
10
  /**
11
11
  * Get the default model ID for a tier from the registry.
12
12
  */
@@ -50,41 +50,33 @@ export function getTierDisplayName(tier) {
50
50
  }
51
51
  /**
52
52
  * Get short model name from full model ID (for display).
53
- * e.g., "claude-sonnet-4-5-20250929" -> "Sonnet 4.5"
53
+ * Prefers the registry's exact display name (single source of truth);
54
+ * falls back to a version-less heuristic for ids not in the registry.
55
+ * e.g., "claude-opus-4-8" -> "Opus 4.8"; "claude-opus-9" -> "Opus".
54
56
  */
55
57
  export function getShortModelName(modelId) {
56
- // Claude models
58
+ // Registry is authoritative for known models.
59
+ const info = getModelInfo(modelId);
60
+ if (info)
61
+ return info.displayName;
62
+ // Heuristic fallback for unregistered ids (version unknown → omit it).
57
63
  if (modelId.includes('claude-haiku'))
58
- return 'Haiku 4.5';
64
+ return 'Haiku';
59
65
  if (modelId.includes('claude-sonnet'))
60
- return 'Sonnet 4.5';
66
+ return 'Sonnet';
61
67
  if (modelId.includes('claude-opus'))
62
- return 'Opus 4.5';
63
- // OpenAI models
64
- if (modelId.includes('gpt-5-nano'))
65
- return 'GPT-5 Nano';
66
- if (modelId.includes('gpt-5-mini'))
67
- return 'GPT-5 Mini';
68
- if (modelId.includes('gpt-5.2'))
69
- return 'GPT-5.2';
70
- if (modelId.includes('gpt-4o-mini'))
71
- return 'GPT-4o Mini';
68
+ return 'Opus';
69
+ if (modelId.includes('claude-fable'))
70
+ return 'Fable';
71
+ if (modelId.includes('gpt-5'))
72
+ return 'GPT-5';
72
73
  if (modelId.includes('gpt-4o'))
73
74
  return 'GPT-4o';
74
- if (modelId.includes('gpt-4-turbo'))
75
- return 'GPT-4 Turbo';
76
- // Gemini models
77
- if (modelId.includes('gemini-2.5-flash-lite'))
78
- return 'Flash Lite 2.5';
79
- if (modelId.includes('gemini-2.5-flash'))
80
- return 'Flash 2.5';
81
- if (modelId.includes('gemini-2.5-pro'))
82
- return 'Pro 2.5';
83
- if (modelId.includes('gemini-3-flash'))
84
- return 'Flash 3';
85
- if (modelId.includes('gemini-3-pro'))
86
- return 'Pro 3';
87
- // Ollama - just return the model ID
75
+ if (modelId.includes('gemini-3'))
76
+ return 'Gemini 3';
77
+ if (modelId.includes('gemini-2.5'))
78
+ return 'Gemini 2.5';
79
+ // Unknown — return the raw model ID.
88
80
  return modelId;
89
81
  }
90
82
  /**
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Ollama discovery — host-agnostic helpers to list locally-pulled models and
3
+ * detect the Ollama version. Shared by CLI + Desktop so both surface installed
4
+ * models (closing the Desktop parity gap) for BOTH ollama providers
5
+ * (`ollama` OpenAI-compat and `ollama-anthropic`). Uses Ollama's native
6
+ * `/api/tags` and `/api/version` (same on both providers — same port).
7
+ *
8
+ * The base URL is a parameter (hosts pass their configured value); this module
9
+ * has no settings dependency. Results are cached per base URL for 30s.
10
+ * See ollama-anthropic-provider-spec.md §6.
11
+ */
12
+ /** Minimum Ollama version that supports the native Anthropic `/v1/messages` endpoint. */
13
+ export declare const OLLAMA_ANTHROPIC_MIN_VERSION = "0.14.0";
14
+ /** Information about an Ollama model as returned by `/api/tags`. */
15
+ export interface OllamaModelInfo {
16
+ /** Model name/tag (e.g., "llama3.3:70b", "ornith:latest") */
17
+ name: string;
18
+ /** Model size in bytes */
19
+ size: number;
20
+ /** When the model was modified/pulled */
21
+ modifiedAt: string;
22
+ /** Model digest (hash) */
23
+ digest: string;
24
+ /** Model details (family, parameter size, quantization) */
25
+ details?: {
26
+ family?: string;
27
+ parameterSize?: string;
28
+ quantizationLevel?: string;
29
+ };
30
+ }
31
+ /** Result of listing Ollama models. */
32
+ export interface OllamaModelsResult {
33
+ success: boolean;
34
+ models: OllamaModelInfo[];
35
+ error?: string;
36
+ /** Whether the Ollama server responded at all */
37
+ ollamaRunning: boolean;
38
+ fetchedAt: number;
39
+ }
40
+ /** Clear the models cache (testing / forced refresh). */
41
+ export declare function clearOllamaModelsCache(): void;
42
+ /**
43
+ * List locally-available Ollama models via `/api/tags`. Cached per base URL for
44
+ * 30s. Returns gracefully (success:false) when Ollama isn't running.
45
+ */
46
+ export declare function listOllamaModels(baseUrl?: string, forceRefresh?: boolean): Promise<OllamaModelsResult>;
47
+ /**
48
+ * Get the running Ollama server version via `/api/version`, or null if
49
+ * unreachable. Used to gate the `ollama-anthropic` provider.
50
+ */
51
+ export declare function getOllamaVersion(baseUrl?: string): Promise<string | null>;
52
+ /**
53
+ * Whether the Ollama server supports the native Anthropic `/v1/messages`
54
+ * endpoint (version >= 0.14.0). Returns false if unreachable/unknown — callers
55
+ * should treat that as "offer classic ollama, gate/warn on ollama-anthropic".
56
+ */
57
+ export declare function isOllamaAnthropicCompatible(baseUrl?: string): Promise<boolean>;
58
+ /** Format a byte size for display (e.g. "4.1 GB"). */
59
+ export declare function formatOllamaModelSize(bytes: number): string;
60
+ /** Friendly display name for a model tag (e.g. "ornith:latest" → "Ornith (latest)"). */
61
+ export declare function getOllamaModelDisplayName(name: string): string;
62
+ /** Short description from model metadata (params · quant · size). */
63
+ export declare function getOllamaModelDescription(model: OllamaModelInfo): string;
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Ollama discovery — host-agnostic helpers to list locally-pulled models and
3
+ * detect the Ollama version. Shared by CLI + Desktop so both surface installed
4
+ * models (closing the Desktop parity gap) for BOTH ollama providers
5
+ * (`ollama` OpenAI-compat and `ollama-anthropic`). Uses Ollama's native
6
+ * `/api/tags` and `/api/version` (same on both providers — same port).
7
+ *
8
+ * The base URL is a parameter (hosts pass their configured value); this module
9
+ * has no settings dependency. Results are cached per base URL for 30s.
10
+ * See ollama-anthropic-provider-spec.md §6.
11
+ */
12
+ const DEFAULT_BASE_URL = 'http://localhost:11434';
13
+ /** Minimum Ollama version that supports the native Anthropic `/v1/messages` endpoint. */
14
+ export const OLLAMA_ANTHROPIC_MIN_VERSION = '0.14.0';
15
+ const CACHE_DURATION_MS = 30_000;
16
+ const modelsCache = new Map();
17
+ function resolveBaseUrl(baseUrl) {
18
+ return baseUrl ?? process.env.OLLAMA_BASE_URL ?? process.env.OLLAMA_HOST ?? DEFAULT_BASE_URL;
19
+ }
20
+ /** Clear the models cache (testing / forced refresh). */
21
+ export function clearOllamaModelsCache() {
22
+ modelsCache.clear();
23
+ }
24
+ /**
25
+ * List locally-available Ollama models via `/api/tags`. Cached per base URL for
26
+ * 30s. Returns gracefully (success:false) when Ollama isn't running.
27
+ */
28
+ export async function listOllamaModels(baseUrl, forceRefresh = false) {
29
+ const host = resolveBaseUrl(baseUrl);
30
+ const cached = modelsCache.get(host);
31
+ if (!forceRefresh && cached && Date.now() - cached.fetchedAt < CACHE_DURATION_MS) {
32
+ return cached;
33
+ }
34
+ try {
35
+ const response = await fetch(`${host}/api/tags`, {
36
+ method: 'GET',
37
+ signal: AbortSignal.timeout(5000),
38
+ });
39
+ if (!response.ok) {
40
+ const result = {
41
+ success: false,
42
+ models: [],
43
+ error: `Ollama returned status ${String(response.status)}`,
44
+ ollamaRunning: true,
45
+ fetchedAt: Date.now(),
46
+ };
47
+ modelsCache.set(host, result);
48
+ return result;
49
+ }
50
+ const data = (await response.json());
51
+ const models = (data.models ?? [])
52
+ .map((m) => ({
53
+ name: m.name,
54
+ size: m.size,
55
+ modifiedAt: m.modified_at,
56
+ digest: m.digest,
57
+ details: m.details
58
+ ? {
59
+ family: m.details.family,
60
+ parameterSize: m.details.parameter_size,
61
+ quantizationLevel: m.details.quantization_level,
62
+ }
63
+ : undefined,
64
+ }))
65
+ .sort((a, b) => a.name.localeCompare(b.name));
66
+ const result = {
67
+ success: true,
68
+ models,
69
+ ollamaRunning: true,
70
+ fetchedAt: Date.now(),
71
+ };
72
+ modelsCache.set(host, result);
73
+ return result;
74
+ }
75
+ catch (error) {
76
+ let errorMsg = 'Unknown error';
77
+ const ollamaRunning = false;
78
+ if (error instanceof Error) {
79
+ if (error.name === 'AbortError' || error.message.includes('timeout')) {
80
+ errorMsg = 'Connection timed out';
81
+ }
82
+ else if (error.message.includes('ECONNREFUSED') || error.message.includes('fetch failed')) {
83
+ errorMsg = 'Ollama is not running. Start it with: ollama serve';
84
+ }
85
+ else {
86
+ errorMsg = error.message;
87
+ }
88
+ }
89
+ const result = {
90
+ success: false,
91
+ models: [],
92
+ error: errorMsg,
93
+ ollamaRunning,
94
+ fetchedAt: Date.now(),
95
+ };
96
+ modelsCache.set(host, result);
97
+ return result;
98
+ }
99
+ }
100
+ /**
101
+ * Get the running Ollama server version via `/api/version`, or null if
102
+ * unreachable. Used to gate the `ollama-anthropic` provider.
103
+ */
104
+ export async function getOllamaVersion(baseUrl) {
105
+ const host = resolveBaseUrl(baseUrl);
106
+ try {
107
+ const response = await fetch(`${host}/api/version`, {
108
+ method: 'GET',
109
+ signal: AbortSignal.timeout(5000),
110
+ });
111
+ if (!response.ok)
112
+ return null;
113
+ const data = (await response.json());
114
+ return data.version ?? null;
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ /** Compare dotted numeric versions: -1 / 0 / 1. Non-numeric segments treated as 0. */
121
+ function compareVersions(a, b) {
122
+ const pa = a.split('.').map((n) => parseInt(n, 10) || 0);
123
+ const pb = b.split('.').map((n) => parseInt(n, 10) || 0);
124
+ const len = Math.max(pa.length, pb.length);
125
+ for (let i = 0; i < len; i++) {
126
+ const d = (pa[i] ?? 0) - (pb[i] ?? 0);
127
+ if (d !== 0)
128
+ return d < 0 ? -1 : 1;
129
+ }
130
+ return 0;
131
+ }
132
+ /**
133
+ * Whether the Ollama server supports the native Anthropic `/v1/messages`
134
+ * endpoint (version >= 0.14.0). Returns false if unreachable/unknown — callers
135
+ * should treat that as "offer classic ollama, gate/warn on ollama-anthropic".
136
+ */
137
+ export async function isOllamaAnthropicCompatible(baseUrl) {
138
+ const version = await getOllamaVersion(baseUrl);
139
+ if (!version)
140
+ return false;
141
+ return compareVersions(version, OLLAMA_ANTHROPIC_MIN_VERSION) >= 0;
142
+ }
143
+ // ── Display helpers (shared so hosts format installed models consistently) ──
144
+ /** Format a byte size for display (e.g. "4.1 GB"). */
145
+ export function formatOllamaModelSize(bytes) {
146
+ if (bytes < 1024)
147
+ return `${String(bytes)} B`;
148
+ if (bytes < 1024 * 1024)
149
+ return `${(bytes / 1024).toFixed(1)} KB`;
150
+ if (bytes < 1024 * 1024 * 1024)
151
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
152
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
153
+ }
154
+ /** Friendly display name for a model tag (e.g. "ornith:latest" → "Ornith (latest)"). */
155
+ export function getOllamaModelDisplayName(name) {
156
+ const [baseName, tag] = name.split(':');
157
+ const formattedBase = baseName
158
+ .split(/[-_]/)
159
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
160
+ .join(' ');
161
+ return tag ? `${formattedBase} (${tag})` : formattedBase;
162
+ }
163
+ /** Short description from model metadata (params · quant · size). */
164
+ export function getOllamaModelDescription(model) {
165
+ const parts = [];
166
+ if (model.details?.parameterSize)
167
+ parts.push(model.details.parameterSize);
168
+ if (model.details?.quantizationLevel)
169
+ parts.push(model.details.quantizationLevel);
170
+ parts.push(formatOllamaModelSize(model.size));
171
+ return parts.join(' · ');
172
+ }
@@ -56,6 +56,16 @@ export const PROVIDER_METADATA = {
56
56
  requiresKey: false,
57
57
  category: 'local',
58
58
  },
59
+ 'ollama-anthropic': {
60
+ type: 'ollama-anthropic',
61
+ displayName: 'Ollama (Claude API)',
62
+ description: "Local models via Ollama's Anthropic endpoint (thinking; needs Ollama ≥ 0.14)",
63
+ endpoint: 'http://localhost:11434',
64
+ envVar: '',
65
+ keyUrl: 'https://ollama.ai',
66
+ requiresKey: false,
67
+ category: 'local',
68
+ },
59
69
  // "Others" providers (OpenAI-compatible APIs)
60
70
  together: {
61
71
  type: 'together',
@@ -128,15 +138,15 @@ export const PROVIDER_METADATA = {
128
138
  */
129
139
  export const TOGETHER_MODELS = [
130
140
  {
131
- id: 'meta-llama/Llama-3.2-8B-Instruct-Turbo',
132
- displayName: 'Llama 3.2 8B Instruct',
141
+ id: 'meta-llama/Llama-3.1-8B-Instruct-Turbo',
142
+ displayName: 'Llama 3.1 8B Instruct',
133
143
  description: 'Fast, low cost',
134
144
  provider: 'together',
135
145
  tier: 'fast',
136
146
  },
137
147
  {
138
- id: 'meta-llama/Llama-3.2-70B-Instruct-Turbo',
139
- displayName: 'Llama 3.2 70B Instruct',
148
+ id: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',
149
+ displayName: 'Llama 3.3 70B Instruct',
140
150
  description: 'Balanced',
141
151
  provider: 'together',
142
152
  tier: 'balanced',
@@ -154,15 +164,15 @@ export const TOGETHER_MODELS = [
154
164
  */
155
165
  export const GROQ_MODELS = [
156
166
  {
157
- id: 'llama-3.2-8b-instant',
158
- displayName: 'Llama 3.2 8B',
167
+ id: 'llama-3.1-8b-instant',
168
+ displayName: 'Llama 3.1 8B',
159
169
  description: 'Fast, low cost',
160
170
  provider: 'groq',
161
171
  tier: 'fast',
162
172
  },
163
173
  {
164
- id: 'llama-3.2-70b-versatile',
165
- displayName: 'Llama 3.2 70B',
174
+ id: 'llama-3.3-70b-versatile',
175
+ displayName: 'Llama 3.3 70B',
166
176
  description: 'Balanced',
167
177
  provider: 'groq',
168
178
  tier: 'balanced',
@@ -180,15 +190,15 @@ export const GROQ_MODELS = [
180
190
  */
181
191
  export const FIREWORKS_MODELS = [
182
192
  {
183
- id: 'accounts/fireworks/models/llama-v3p2-8b-instruct',
184
- displayName: 'Llama 3.2 8B',
193
+ id: 'accounts/fireworks/models/llama-v3p1-8b-instruct',
194
+ displayName: 'Llama 3.1 8B',
185
195
  description: 'Fast, low cost',
186
196
  provider: 'fireworks',
187
197
  tier: 'fast',
188
198
  },
189
199
  {
190
- id: 'accounts/fireworks/models/llama-v3p2-70b-instruct',
191
- displayName: 'Llama 3.2 70B',
200
+ id: 'accounts/fireworks/models/llama-v3p3-70b-instruct',
201
+ displayName: 'Llama 3.3 70B',
192
202
  description: 'Balanced',
193
203
  provider: 'fireworks',
194
204
  tier: 'balanced',
@@ -206,22 +216,22 @@ export const FIREWORKS_MODELS = [
206
216
  */
207
217
  export const PERPLEXITY_MODELS = [
208
218
  {
209
- id: 'llama-3.1-sonar-small-128k-online',
210
- displayName: 'Sonar Small',
219
+ id: 'sonar',
220
+ displayName: 'Sonar',
211
221
  description: 'Fast, low cost',
212
222
  provider: 'perplexity',
213
223
  tier: 'fast',
214
224
  },
215
225
  {
216
- id: 'llama-3.1-sonar-large-128k-online',
217
- displayName: 'Sonar Large',
226
+ id: 'sonar-pro',
227
+ displayName: 'Sonar Pro',
218
228
  description: 'Balanced',
219
229
  provider: 'perplexity',
220
230
  tier: 'balanced',
221
231
  },
222
232
  {
223
- id: 'llama-3.1-sonar-huge-128k-online',
224
- displayName: 'Sonar Huge',
233
+ id: 'sonar-reasoning-pro',
234
+ displayName: 'Sonar Reasoning Pro',
225
235
  description: 'Most capable',
226
236
  provider: 'perplexity',
227
237
  tier: 'powerful',
@@ -232,22 +242,22 @@ export const PERPLEXITY_MODELS = [
232
242
  */
233
243
  export const OPENROUTER_MODELS = [
234
244
  {
235
- id: 'meta-llama/llama-3.2-8b-instruct',
236
- displayName: 'Llama 3.2 8B',
245
+ id: 'meta-llama/llama-3.1-8b-instruct',
246
+ displayName: 'Llama 3.1 8B',
237
247
  description: 'Fast, low cost',
238
248
  provider: 'openrouter',
239
249
  tier: 'fast',
240
250
  },
241
251
  {
242
- id: 'anthropic/claude-3-5-sonnet',
243
- displayName: 'Claude 3.5 Sonnet',
252
+ id: 'anthropic/claude-sonnet-5',
253
+ displayName: 'Claude Sonnet 5',
244
254
  description: 'Balanced (via OpenRouter)',
245
255
  provider: 'openrouter',
246
256
  tier: 'balanced',
247
257
  },
248
258
  {
249
- id: 'anthropic/claude-3-opus',
250
- displayName: 'Claude 3 Opus',
259
+ id: 'anthropic/claude-opus-4-8',
260
+ displayName: 'Claude Opus 4.8',
251
261
  description: 'Most capable (via OpenRouter)',
252
262
  provider: 'openrouter',
253
263
  tier: 'powerful',
package/dist/provider.js CHANGED
@@ -48,6 +48,22 @@ export function createProviderFromType(type, options) {
48
48
  return createGeminiNativeProvider({ model, apiKey, estimateTokens, maxTokens });
49
49
  case 'ollama':
50
50
  return createOllamaProvider({ model, baseUrl, estimateTokens, maxTokens });
51
+ case 'ollama-anthropic':
52
+ // Ollama's native Anthropic Messages endpoint (Ollama >= 0.14). Reuses the
53
+ // Claude provider pointed at the Ollama base URL — the Anthropic SDK POSTs
54
+ // to {baseURL}/v1/messages. Anthropic-only features Ollama doesn't support
55
+ // are disabled; the dummy key is accepted-not-validated. Surfaces thinking
56
+ // that the OpenAI-compat `ollama` path drops. See ollama-anthropic spec.
57
+ return createClaudeProvider({
58
+ model,
59
+ apiKey: apiKey || 'ollama',
60
+ baseURL: baseUrl ?? 'http://localhost:11434',
61
+ estimateTokens,
62
+ maxTokens,
63
+ enablePromptCaching: false,
64
+ enableTokenEfficientTools: false,
65
+ enableExtendedContext: false,
66
+ });
51
67
  case 'together':
52
68
  return createTogetherProvider({ model, apiKey, estimateTokens, maxTokens });
53
69
  case 'groq':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@compilr-dev/sdk",
3
- "version": "0.18.8",
3
+ "version": "0.18.10",
4
4
  "description": "Universal agent runtime for building AI-powered applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -76,7 +76,7 @@
76
76
  "node": ">=20.0.0"
77
77
  },
78
78
  "dependencies": {
79
- "@compilr-dev/agents": "^0.6.7",
79
+ "@compilr-dev/agents": "^0.6.8",
80
80
  "@compilr-dev/logger": "^0.1.0",
81
81
  "ajv": "^6.14.0",
82
82
  "yaml": "^2.8.4"