@contractspec/lib.ai-providers 3.7.12 → 3.7.14

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.
@@ -1,737 +1 @@
1
- // src/models.ts
2
- var DEFAULT_MODELS = {
3
- ollama: "llama3.2",
4
- openai: "gpt-5.4",
5
- anthropic: "claude-sonnet-4-6",
6
- mistral: "mistral-large-latest",
7
- gemini: "gemini-2.5-flash"
8
- };
9
- var MODELS = [
10
- {
11
- id: "llama3.2",
12
- name: "Llama 3.2",
13
- provider: "ollama",
14
- contextWindow: 128000,
15
- capabilities: {
16
- vision: false,
17
- tools: true,
18
- reasoning: false,
19
- streaming: true
20
- }
21
- },
22
- {
23
- id: "codellama",
24
- name: "Code Llama",
25
- provider: "ollama",
26
- contextWindow: 16000,
27
- capabilities: {
28
- vision: false,
29
- tools: false,
30
- reasoning: false,
31
- streaming: true
32
- }
33
- },
34
- {
35
- id: "deepseek-coder",
36
- name: "DeepSeek Coder",
37
- provider: "ollama",
38
- contextWindow: 16000,
39
- capabilities: {
40
- vision: false,
41
- tools: false,
42
- reasoning: false,
43
- streaming: true
44
- }
45
- },
46
- {
47
- id: "mistral",
48
- name: "Mistral 7B",
49
- provider: "ollama",
50
- contextWindow: 32000,
51
- capabilities: {
52
- vision: false,
53
- tools: false,
54
- reasoning: false,
55
- streaming: true
56
- }
57
- },
58
- {
59
- id: "gpt-5.4",
60
- name: "GPT-5.4",
61
- provider: "openai",
62
- contextWindow: 1e6,
63
- capabilities: {
64
- vision: true,
65
- tools: true,
66
- reasoning: true,
67
- streaming: true
68
- },
69
- costPerMillion: { input: 2.5, output: 15 }
70
- },
71
- {
72
- id: "gpt-4o",
73
- name: "GPT-4o",
74
- provider: "openai",
75
- contextWindow: 128000,
76
- capabilities: {
77
- vision: true,
78
- tools: true,
79
- reasoning: false,
80
- streaming: true
81
- },
82
- costPerMillion: { input: 2.5, output: 10 }
83
- },
84
- {
85
- id: "gpt-4o-mini",
86
- name: "GPT-4o Mini",
87
- provider: "openai",
88
- contextWindow: 128000,
89
- capabilities: {
90
- vision: true,
91
- tools: true,
92
- reasoning: false,
93
- streaming: true
94
- },
95
- costPerMillion: { input: 0.15, output: 0.6 }
96
- },
97
- {
98
- id: "o1",
99
- name: "o1",
100
- provider: "openai",
101
- contextWindow: 200000,
102
- capabilities: {
103
- vision: true,
104
- tools: true,
105
- reasoning: true,
106
- streaming: true
107
- },
108
- costPerMillion: { input: 15, output: 60 }
109
- },
110
- {
111
- id: "o1-mini",
112
- name: "o1 Mini",
113
- provider: "openai",
114
- contextWindow: 128000,
115
- capabilities: {
116
- vision: false,
117
- tools: true,
118
- reasoning: true,
119
- streaming: true
120
- },
121
- costPerMillion: { input: 3, output: 12 }
122
- },
123
- {
124
- id: "gpt-5-mini",
125
- name: "GPT-5 Mini",
126
- provider: "openai",
127
- contextWindow: 400000,
128
- capabilities: {
129
- vision: true,
130
- tools: true,
131
- reasoning: false,
132
- streaming: true
133
- },
134
- costPerMillion: { input: 0.25, output: 2 }
135
- },
136
- {
137
- id: "claude-opus-4-6",
138
- name: "Claude Opus 4.6",
139
- provider: "anthropic",
140
- contextWindow: 200000,
141
- capabilities: {
142
- vision: true,
143
- tools: true,
144
- reasoning: true,
145
- streaming: true
146
- },
147
- costPerMillion: { input: 5, output: 25 }
148
- },
149
- {
150
- id: "claude-sonnet-4-6",
151
- name: "Claude Sonnet 4.6",
152
- provider: "anthropic",
153
- contextWindow: 200000,
154
- capabilities: {
155
- vision: true,
156
- tools: true,
157
- reasoning: true,
158
- streaming: true
159
- },
160
- costPerMillion: { input: 3, output: 15 }
161
- },
162
- {
163
- id: "claude-haiku-4-5",
164
- name: "Claude Haiku 4.5",
165
- provider: "anthropic",
166
- contextWindow: 200000,
167
- capabilities: {
168
- vision: true,
169
- tools: true,
170
- reasoning: false,
171
- streaming: true
172
- },
173
- costPerMillion: { input: 1, output: 5 }
174
- },
175
- {
176
- id: "claude-sonnet-4-20250514",
177
- name: "Claude Sonnet 4",
178
- provider: "anthropic",
179
- contextWindow: 200000,
180
- capabilities: {
181
- vision: true,
182
- tools: true,
183
- reasoning: true,
184
- streaming: true
185
- },
186
- costPerMillion: { input: 3, output: 15 }
187
- },
188
- {
189
- id: "claude-3-5-sonnet-20241022",
190
- name: "Claude 3.5 Sonnet",
191
- provider: "anthropic",
192
- contextWindow: 200000,
193
- capabilities: {
194
- vision: true,
195
- tools: true,
196
- reasoning: false,
197
- streaming: true
198
- },
199
- costPerMillion: { input: 3, output: 15 }
200
- },
201
- {
202
- id: "claude-3-5-haiku-20241022",
203
- name: "Claude 3.5 Haiku",
204
- provider: "anthropic",
205
- contextWindow: 200000,
206
- capabilities: {
207
- vision: true,
208
- tools: true,
209
- reasoning: false,
210
- streaming: true
211
- },
212
- costPerMillion: { input: 0.8, output: 4 }
213
- },
214
- {
215
- id: "mistral-large-2512",
216
- name: "Mistral Large 3",
217
- provider: "mistral",
218
- contextWindow: 256000,
219
- capabilities: {
220
- vision: true,
221
- tools: true,
222
- reasoning: false,
223
- streaming: true
224
- },
225
- costPerMillion: { input: 0.5, output: 1.5 }
226
- },
227
- {
228
- id: "devstral-2512",
229
- name: "Devstral 2",
230
- provider: "mistral",
231
- contextWindow: 256000,
232
- capabilities: {
233
- vision: false,
234
- tools: true,
235
- reasoning: true,
236
- streaming: true
237
- },
238
- costPerMillion: { input: 0.4, output: 2 }
239
- },
240
- {
241
- id: "mistral-medium-2508",
242
- name: "Mistral Medium 3.1",
243
- provider: "mistral",
244
- contextWindow: 128000,
245
- capabilities: {
246
- vision: true,
247
- tools: true,
248
- reasoning: false,
249
- streaming: true
250
- },
251
- costPerMillion: { input: 0.4, output: 2 }
252
- },
253
- {
254
- id: "mistral-small-2506",
255
- name: "Mistral Small 3.2",
256
- provider: "mistral",
257
- contextWindow: 128000,
258
- capabilities: {
259
- vision: false,
260
- tools: true,
261
- reasoning: false,
262
- streaming: true
263
- }
264
- },
265
- {
266
- id: "mistral-large-latest",
267
- name: "Mistral Large",
268
- provider: "mistral",
269
- contextWindow: 128000,
270
- capabilities: {
271
- vision: false,
272
- tools: true,
273
- reasoning: false,
274
- streaming: true
275
- },
276
- costPerMillion: { input: 2, output: 6 }
277
- },
278
- {
279
- id: "mistral-medium-latest",
280
- name: "Mistral Medium",
281
- provider: "mistral",
282
- contextWindow: 128000,
283
- capabilities: {
284
- vision: false,
285
- tools: true,
286
- reasoning: false,
287
- streaming: true
288
- }
289
- },
290
- {
291
- id: "codestral-latest",
292
- name: "Codestral",
293
- provider: "mistral",
294
- contextWindow: 256000,
295
- capabilities: {
296
- vision: false,
297
- tools: true,
298
- reasoning: false,
299
- streaming: true
300
- },
301
- costPerMillion: { input: 0.2, output: 0.6 }
302
- },
303
- {
304
- id: "devstral-small-latest",
305
- name: "Devstral Small",
306
- provider: "mistral",
307
- contextWindow: 128000,
308
- capabilities: {
309
- vision: false,
310
- tools: true,
311
- reasoning: true,
312
- streaming: true
313
- }
314
- },
315
- {
316
- id: "magistral-medium-latest",
317
- name: "Magistral Medium",
318
- provider: "mistral",
319
- contextWindow: 128000,
320
- capabilities: {
321
- vision: false,
322
- tools: true,
323
- reasoning: true,
324
- streaming: true
325
- }
326
- },
327
- {
328
- id: "pixtral-large-latest",
329
- name: "Pixtral Large",
330
- provider: "mistral",
331
- contextWindow: 128000,
332
- capabilities: {
333
- vision: true,
334
- tools: true,
335
- reasoning: false,
336
- streaming: true
337
- }
338
- },
339
- {
340
- id: "mistral-small-latest",
341
- name: "Mistral Small",
342
- provider: "mistral",
343
- contextWindow: 32000,
344
- capabilities: {
345
- vision: false,
346
- tools: true,
347
- reasoning: false,
348
- streaming: true
349
- },
350
- costPerMillion: { input: 0.2, output: 0.6 }
351
- },
352
- {
353
- id: "gemini-2.0-flash",
354
- name: "Gemini 2.0 Flash",
355
- provider: "gemini",
356
- contextWindow: 1e6,
357
- capabilities: {
358
- vision: true,
359
- tools: true,
360
- reasoning: false,
361
- streaming: true
362
- },
363
- costPerMillion: { input: 0.075, output: 0.3 }
364
- },
365
- {
366
- id: "gemini-2.5-pro-preview-06-05",
367
- name: "Gemini 2.5 Pro",
368
- provider: "gemini",
369
- contextWindow: 1e6,
370
- capabilities: {
371
- vision: true,
372
- tools: true,
373
- reasoning: true,
374
- streaming: true
375
- },
376
- costPerMillion: { input: 1.25, output: 10 }
377
- },
378
- {
379
- id: "gemini-2.5-flash-preview-05-20",
380
- name: "Gemini 2.5 Flash",
381
- provider: "gemini",
382
- contextWindow: 1e6,
383
- capabilities: {
384
- vision: true,
385
- tools: true,
386
- reasoning: true,
387
- streaming: true
388
- },
389
- costPerMillion: { input: 0.15, output: 0.6 }
390
- },
391
- {
392
- id: "gemini-3.1-pro-preview",
393
- name: "Gemini 3.1 Pro",
394
- provider: "gemini",
395
- contextWindow: 1e6,
396
- capabilities: {
397
- vision: true,
398
- tools: true,
399
- reasoning: true,
400
- streaming: true
401
- }
402
- },
403
- {
404
- id: "gemini-3.1-flash-lite-preview",
405
- name: "Gemini 3.1 Flash-Lite",
406
- provider: "gemini",
407
- contextWindow: 1e6,
408
- capabilities: {
409
- vision: true,
410
- tools: true,
411
- reasoning: true,
412
- streaming: true
413
- }
414
- },
415
- {
416
- id: "gemini-3-flash-preview",
417
- name: "Gemini 3 Flash",
418
- provider: "gemini",
419
- contextWindow: 1e6,
420
- capabilities: {
421
- vision: true,
422
- tools: true,
423
- reasoning: false,
424
- streaming: true
425
- }
426
- }
427
- ];
428
- function getModelsForProvider(provider) {
429
- return MODELS.filter((m) => m.provider === provider);
430
- }
431
- function getModelInfo(modelId) {
432
- return MODELS.find((m) => m.id === modelId);
433
- }
434
- function getRecommendedModels(provider) {
435
- const normalizedProvider = provider === "claude" ? "anthropic" : provider === "custom" ? "openai" : provider;
436
- return getModelsForProvider(normalizedProvider).map((m) => m.id);
437
- }
438
- function getDefaultModel(provider) {
439
- return DEFAULT_MODELS[provider];
440
- }
441
-
442
- // src/factory.ts
443
- import { createAnthropic } from "@ai-sdk/anthropic";
444
- import { createGoogleGenerativeAI } from "@ai-sdk/google";
445
- import { createMistral } from "@ai-sdk/mistral";
446
- import { createOpenAI } from "@ai-sdk/openai";
447
- import { createOllama } from "ollama-ai-provider";
448
- class BaseProvider {
449
- name;
450
- model;
451
- mode;
452
- config;
453
- transport;
454
- authMethod;
455
- apiVersion;
456
- customHeaders;
457
- cachedModel = null;
458
- constructor(config) {
459
- this.name = config.provider;
460
- this.model = config.model ?? DEFAULT_MODELS[config.provider];
461
- this.mode = this.determineMode(config);
462
- this.config = config;
463
- this.transport = config.transport;
464
- this.authMethod = config.authMethod;
465
- this.apiVersion = config.apiVersion;
466
- this.customHeaders = config.customHeaders;
467
- }
468
- getModel() {
469
- if (!this.cachedModel) {
470
- this.cachedModel = this.createModel();
471
- }
472
- return this.cachedModel;
473
- }
474
- async listModels() {
475
- if (this.name === "ollama") {
476
- return this.listOllamaModels();
477
- }
478
- return getModelsForProvider(this.name);
479
- }
480
- async validate() {
481
- if (this.name === "ollama") {
482
- return this.validateOllama();
483
- }
484
- if (this.mode === "byok" && !this.config.apiKey) {
485
- return {
486
- valid: false,
487
- error: `API key required for ${this.name}`
488
- };
489
- }
490
- if (this.mode === "managed" && !this.config.proxyUrl && !this.config.organizationId) {
491
- return {
492
- valid: false,
493
- error: "Managed mode requires proxyUrl or organizationId"
494
- };
495
- }
496
- return { valid: true };
497
- }
498
- determineMode(config) {
499
- if (config.provider === "ollama")
500
- return "local";
501
- if (config.apiKey)
502
- return "byok";
503
- return "managed";
504
- }
505
- createModel() {
506
- const { baseUrl, proxyUrl, apiKey } = this.config;
507
- const headers = this.customHeaders;
508
- if (this.name === "ollama") {
509
- const provider = createOllama({ baseURL: baseUrl, headers });
510
- return provider(this.model);
511
- }
512
- if (this.mode === "managed" && proxyUrl) {
513
- const provider = createOpenAI({ baseURL: proxyUrl, apiKey, headers });
514
- return provider(this.model);
515
- }
516
- switch (this.name) {
517
- case "openai": {
518
- const provider = createOpenAI({ apiKey, headers });
519
- return provider(this.model);
520
- }
521
- case "anthropic": {
522
- const provider = createAnthropic({ apiKey, headers });
523
- return provider(this.model);
524
- }
525
- case "mistral": {
526
- const provider = createMistral({ apiKey, headers });
527
- return provider(this.model);
528
- }
529
- case "gemini": {
530
- const provider = createGoogleGenerativeAI({ apiKey, headers });
531
- return provider(this.model);
532
- }
533
- default:
534
- throw new Error(`Unknown provider: ${this.name}`);
535
- }
536
- }
537
- async listOllamaModels() {
538
- try {
539
- const baseUrl = this.config.baseUrl ?? "http://localhost:11434";
540
- const response = await fetch(`${baseUrl}/api/tags`);
541
- if (!response.ok) {
542
- return getModelsForProvider("ollama");
543
- }
544
- const data = await response.json();
545
- const models = data.models ?? [];
546
- return models.map((m) => ({
547
- id: m.name,
548
- name: m.name,
549
- provider: "ollama",
550
- contextWindow: 8000,
551
- capabilities: {
552
- vision: false,
553
- tools: false,
554
- reasoning: false,
555
- streaming: true
556
- }
557
- }));
558
- } catch {
559
- return getModelsForProvider("ollama");
560
- }
561
- }
562
- async validateOllama() {
563
- try {
564
- const baseUrl = this.config.baseUrl ?? "http://localhost:11434";
565
- const response = await fetch(`${baseUrl}/api/tags`);
566
- if (!response.ok) {
567
- return {
568
- valid: false,
569
- error: `Ollama server returned ${response.status}`
570
- };
571
- }
572
- const data = await response.json();
573
- const models = data.models ?? [];
574
- const hasModel = models.some((m) => m.name === this.model);
575
- if (!hasModel) {
576
- return {
577
- valid: false,
578
- error: `Model "${this.model}" not found. Available: ${models.map((m) => m.name).join(", ")}`
579
- };
580
- }
581
- return { valid: true };
582
- } catch (error) {
583
- const baseUrl = this.config.baseUrl ?? "http://localhost:11434";
584
- return {
585
- valid: false,
586
- error: `Cannot connect to Ollama at ${baseUrl}: ${error instanceof Error ? error.message : String(error)}`
587
- };
588
- }
589
- }
590
- }
591
- function createProvider(config) {
592
- return new BaseProvider(config);
593
- }
594
- function createProviderFromEnv() {
595
- const provider = process.env.CONTRACTSPEC_AI_PROVIDER ?? "openai";
596
- const model = process.env.CONTRACTSPEC_AI_MODEL;
597
- let apiKey;
598
- switch (provider) {
599
- case "openai":
600
- apiKey = process.env.OPENAI_API_KEY;
601
- break;
602
- case "anthropic":
603
- apiKey = process.env.ANTHROPIC_API_KEY;
604
- break;
605
- case "mistral":
606
- apiKey = process.env.MISTRAL_API_KEY;
607
- break;
608
- case "gemini":
609
- apiKey = process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;
610
- break;
611
- case "ollama":
612
- break;
613
- }
614
- const transport = process.env.CONTRACTSPEC_AI_TRANSPORT;
615
- const apiVersion = process.env.CONTRACTSPEC_AI_API_VERSION;
616
- return createProvider({
617
- provider,
618
- model,
619
- apiKey,
620
- baseUrl: process.env.OLLAMA_BASE_URL,
621
- proxyUrl: process.env.CONTRACTSPEC_AI_PROXY_URL,
622
- organizationId: process.env.CONTRACTSPEC_ORG_ID,
623
- transport,
624
- apiVersion
625
- });
626
- }
627
- function getAvailableProviders() {
628
- const providers = [];
629
- providers.push({
630
- provider: "ollama",
631
- available: true,
632
- mode: "local",
633
- transports: ["rest", "sdk"],
634
- authMethods: []
635
- });
636
- const openaiKey = process.env.OPENAI_API_KEY;
637
- providers.push({
638
- provider: "openai",
639
- available: Boolean(openaiKey) || Boolean(process.env.CONTRACTSPEC_AI_PROXY_URL),
640
- mode: openaiKey ? "byok" : "managed",
641
- reason: !openaiKey ? "Set OPENAI_API_KEY for BYOK mode" : undefined,
642
- transports: ["rest", "sdk"],
643
- authMethods: ["api-key"]
644
- });
645
- const anthropicKey = process.env.ANTHROPIC_API_KEY;
646
- providers.push({
647
- provider: "anthropic",
648
- available: Boolean(anthropicKey) || Boolean(process.env.CONTRACTSPEC_AI_PROXY_URL),
649
- mode: anthropicKey ? "byok" : "managed",
650
- reason: !anthropicKey ? "Set ANTHROPIC_API_KEY for BYOK mode" : undefined,
651
- transports: ["rest", "sdk"],
652
- authMethods: ["api-key"]
653
- });
654
- const mistralKey = process.env.MISTRAL_API_KEY;
655
- providers.push({
656
- provider: "mistral",
657
- available: Boolean(mistralKey) || Boolean(process.env.CONTRACTSPEC_AI_PROXY_URL),
658
- mode: mistralKey ? "byok" : "managed",
659
- reason: !mistralKey ? "Set MISTRAL_API_KEY for BYOK mode" : undefined,
660
- transports: ["rest", "sdk"],
661
- authMethods: ["api-key"]
662
- });
663
- const geminiKey = process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;
664
- providers.push({
665
- provider: "gemini",
666
- available: Boolean(geminiKey) || Boolean(process.env.CONTRACTSPEC_AI_PROXY_URL),
667
- mode: geminiKey ? "byok" : "managed",
668
- reason: !geminiKey ? "Set GOOGLE_API_KEY for BYOK mode" : undefined,
669
- transports: ["rest", "sdk"],
670
- authMethods: ["api-key"]
671
- });
672
- return providers;
673
- }
674
-
675
- // src/validation.ts
676
- async function validateProvider(config) {
677
- const provider = createProvider(config);
678
- return provider.validate();
679
- }
680
- function hasCredentials(provider) {
681
- switch (provider) {
682
- case "ollama":
683
- return true;
684
- case "openai":
685
- return Boolean(process.env.OPENAI_API_KEY);
686
- case "anthropic":
687
- return Boolean(process.env.ANTHROPIC_API_KEY);
688
- case "mistral":
689
- return Boolean(process.env.MISTRAL_API_KEY);
690
- case "gemini":
691
- return Boolean(process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY);
692
- default:
693
- return false;
694
- }
695
- }
696
- function getEnvVarName(provider) {
697
- switch (provider) {
698
- case "ollama":
699
- return null;
700
- case "openai":
701
- return "OPENAI_API_KEY";
702
- case "anthropic":
703
- return "ANTHROPIC_API_KEY";
704
- case "mistral":
705
- return "MISTRAL_API_KEY";
706
- case "gemini":
707
- return "GOOGLE_API_KEY";
708
- default:
709
- return null;
710
- }
711
- }
712
- async function isOllamaRunning(baseUrl = "http://localhost:11434") {
713
- try {
714
- const response = await fetch(`${baseUrl}/api/tags`);
715
- return response.ok;
716
- } catch {
717
- return false;
718
- }
719
- }
720
- async function listOllamaModels(baseUrl = "http://localhost:11434") {
721
- try {
722
- const response = await fetch(`${baseUrl}/api/tags`);
723
- if (!response.ok)
724
- return [];
725
- const data = await response.json();
726
- return (data.models ?? []).map((m) => m.name);
727
- } catch {
728
- return [];
729
- }
730
- }
731
- export {
732
- validateProvider,
733
- listOllamaModels,
734
- isOllamaRunning,
735
- hasCredentials,
736
- getEnvVarName
737
- };
1
+ var Q={ollama:"llama3.2",openai:"gpt-5.4",anthropic:"claude-sonnet-4-6",mistral:"mistral-large-latest",gemini:"gemini-2.5-flash"},W=[{id:"llama3.2",name:"Llama 3.2",provider:"ollama",contextWindow:128000,capabilities:{vision:!1,tools:!0,reasoning:!1,streaming:!0}},{id:"codellama",name:"Code Llama",provider:"ollama",contextWindow:16000,capabilities:{vision:!1,tools:!1,reasoning:!1,streaming:!0}},{id:"deepseek-coder",name:"DeepSeek Coder",provider:"ollama",contextWindow:16000,capabilities:{vision:!1,tools:!1,reasoning:!1,streaming:!0}},{id:"mistral",name:"Mistral 7B",provider:"ollama",contextWindow:32000,capabilities:{vision:!1,tools:!1,reasoning:!1,streaming:!0}},{id:"gpt-5.4",name:"GPT-5.4",provider:"openai",contextWindow:1e6,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:2.5,output:15}},{id:"gpt-4o",name:"GPT-4o",provider:"openai",contextWindow:128000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:2.5,output:10}},{id:"gpt-4o-mini",name:"GPT-4o Mini",provider:"openai",contextWindow:128000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:0.15,output:0.6}},{id:"o1",name:"o1",provider:"openai",contextWindow:200000,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:15,output:60}},{id:"o1-mini",name:"o1 Mini",provider:"openai",contextWindow:128000,capabilities:{vision:!1,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:3,output:12}},{id:"gpt-5-mini",name:"GPT-5 Mini",provider:"openai",contextWindow:400000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:0.25,output:2}},{id:"claude-opus-4-6",name:"Claude Opus 4.6",provider:"anthropic",contextWindow:200000,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:5,output:25}},{id:"claude-sonnet-4-6",name:"Claude Sonnet 4.6",provider:"anthropic",contextWindow:200000,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:3,output:15}},{id:"claude-haiku-4-5",name:"Claude Haiku 4.5",provider:"anthropic",contextWindow:200000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:1,output:5}},{id:"claude-sonnet-4-20250514",name:"Claude Sonnet 4",provider:"anthropic",contextWindow:200000,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:3,output:15}},{id:"claude-3-5-sonnet-20241022",name:"Claude 3.5 Sonnet",provider:"anthropic",contextWindow:200000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:3,output:15}},{id:"claude-3-5-haiku-20241022",name:"Claude 3.5 Haiku",provider:"anthropic",contextWindow:200000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:0.8,output:4}},{id:"mistral-large-2512",name:"Mistral Large 3",provider:"mistral",contextWindow:256000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:0.5,output:1.5}},{id:"devstral-2512",name:"Devstral 2",provider:"mistral",contextWindow:256000,capabilities:{vision:!1,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:0.4,output:2}},{id:"mistral-medium-2508",name:"Mistral Medium 3.1",provider:"mistral",contextWindow:128000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:0.4,output:2}},{id:"mistral-small-2506",name:"Mistral Small 3.2",provider:"mistral",contextWindow:128000,capabilities:{vision:!1,tools:!0,reasoning:!1,streaming:!0}},{id:"mistral-large-latest",name:"Mistral Large",provider:"mistral",contextWindow:128000,capabilities:{vision:!1,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:2,output:6}},{id:"mistral-medium-latest",name:"Mistral Medium",provider:"mistral",contextWindow:128000,capabilities:{vision:!1,tools:!0,reasoning:!1,streaming:!0}},{id:"codestral-latest",name:"Codestral",provider:"mistral",contextWindow:256000,capabilities:{vision:!1,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:0.2,output:0.6}},{id:"devstral-small-latest",name:"Devstral Small",provider:"mistral",contextWindow:128000,capabilities:{vision:!1,tools:!0,reasoning:!0,streaming:!0}},{id:"magistral-medium-latest",name:"Magistral Medium",provider:"mistral",contextWindow:128000,capabilities:{vision:!1,tools:!0,reasoning:!0,streaming:!0}},{id:"pixtral-large-latest",name:"Pixtral Large",provider:"mistral",contextWindow:128000,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0}},{id:"mistral-small-latest",name:"Mistral Small",provider:"mistral",contextWindow:32000,capabilities:{vision:!1,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:0.2,output:0.6}},{id:"gemini-2.0-flash",name:"Gemini 2.0 Flash",provider:"gemini",contextWindow:1e6,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0},costPerMillion:{input:0.075,output:0.3}},{id:"gemini-2.5-pro-preview-06-05",name:"Gemini 2.5 Pro",provider:"gemini",contextWindow:1e6,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:1.25,output:10}},{id:"gemini-2.5-flash-preview-05-20",name:"Gemini 2.5 Flash",provider:"gemini",contextWindow:1e6,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0},costPerMillion:{input:0.15,output:0.6}},{id:"gemini-3.1-pro-preview",name:"Gemini 3.1 Pro",provider:"gemini",contextWindow:1e6,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0}},{id:"gemini-3.1-flash-lite-preview",name:"Gemini 3.1 Flash-Lite",provider:"gemini",contextWindow:1e6,capabilities:{vision:!0,tools:!0,reasoning:!0,streaming:!0}},{id:"gemini-3-flash-preview",name:"Gemini 3 Flash",provider:"gemini",contextWindow:1e6,capabilities:{vision:!0,tools:!0,reasoning:!1,streaming:!0}}];function J(j){return W.filter((q)=>q.provider===j)}function u(j){return W.find((q)=>q.id===j)}function x(j){return J(j==="claude"?"anthropic":j==="custom"?"openai":j).map((z)=>z.id)}function B(j){return Q[j]}import{createAnthropic as Z}from"@ai-sdk/anthropic";import{createGoogleGenerativeAI as $}from"@ai-sdk/google";import{createMistral as w}from"@ai-sdk/mistral";import{createOpenAI as X}from"@ai-sdk/openai";import{createOllama as V}from"ollama-ai-provider";class Y{name;model;mode;config;transport;authMethod;apiVersion;customHeaders;cachedModel=null;constructor(j){this.name=j.provider,this.model=j.model??Q[j.provider],this.mode=this.determineMode(j),this.config=j,this.transport=j.transport,this.authMethod=j.authMethod,this.apiVersion=j.apiVersion,this.customHeaders=j.customHeaders}getModel(){if(!this.cachedModel)this.cachedModel=this.createModel();return this.cachedModel}async listModels(){if(this.name==="ollama")return this.listOllamaModels();return J(this.name)}async validate(){if(this.name==="ollama")return this.validateOllama();if(this.mode==="byok"&&!this.config.apiKey)return{valid:!1,error:`API key required for ${this.name}`};if(this.mode==="managed"&&!this.config.proxyUrl&&!this.config.organizationId)return{valid:!1,error:"Managed mode requires proxyUrl or organizationId"};return{valid:!0}}determineMode(j){if(j.provider==="ollama")return"local";if(j.apiKey)return"byok";return"managed"}createModel(){let{baseUrl:j,proxyUrl:q,apiKey:z}=this.config,C=this.customHeaders;if(this.name==="ollama")return V({baseURL:j,headers:C})(this.model);if(this.mode==="managed"&&q)return X({baseURL:q,apiKey:z,headers:C})(this.model);switch(this.name){case"openai":return X({apiKey:z,headers:C})(this.model);case"anthropic":return Z({apiKey:z,headers:C})(this.model);case"mistral":return w({apiKey:z,headers:C})(this.model);case"gemini":return $({apiKey:z,headers:C})(this.model);default:throw Error(`Unknown provider: ${this.name}`)}}async listOllamaModels(){try{let j=this.config.baseUrl??"http://localhost:11434",q=await fetch(`${j}/api/tags`);if(!q.ok)return J("ollama");return((await q.json()).models??[]).map((H)=>({id:H.name,name:H.name,provider:"ollama",contextWindow:8000,capabilities:{vision:!1,tools:!1,reasoning:!1,streaming:!0}}))}catch{return J("ollama")}}async validateOllama(){try{let j=this.config.baseUrl??"http://localhost:11434",q=await fetch(`${j}/api/tags`);if(!q.ok)return{valid:!1,error:`Ollama server returned ${q.status}`};let C=(await q.json()).models??[];if(!C.some((N)=>N.name===this.model))return{valid:!1,error:`Model "${this.model}" not found. Available: ${C.map((N)=>N.name).join(", ")}`};return{valid:!0}}catch(j){return{valid:!1,error:`Cannot connect to Ollama at ${this.config.baseUrl??"http://localhost:11434"}: ${j instanceof Error?j.message:String(j)}`}}}}function R(j){return new Y(j)}function F(){let j=process.env.CONTRACTSPEC_AI_PROVIDER??"openai",q=process.env.CONTRACTSPEC_AI_MODEL,z;switch(j){case"openai":z=process.env.OPENAI_API_KEY;break;case"anthropic":z=process.env.ANTHROPIC_API_KEY;break;case"mistral":z=process.env.MISTRAL_API_KEY;break;case"gemini":z=process.env.GOOGLE_API_KEY??process.env.GEMINI_API_KEY;break;case"ollama":break}let C=process.env.CONTRACTSPEC_AI_TRANSPORT,H=process.env.CONTRACTSPEC_AI_API_VERSION;return R({provider:j,model:q,apiKey:z,baseUrl:process.env.OLLAMA_BASE_URL,proxyUrl:process.env.CONTRACTSPEC_AI_PROXY_URL,organizationId:process.env.CONTRACTSPEC_ORG_ID,transport:C,apiVersion:H})}function I(){let j=[];j.push({provider:"ollama",available:!0,mode:"local",transports:["rest","sdk"],authMethods:[]});let q=process.env.OPENAI_API_KEY;j.push({provider:"openai",available:Boolean(q)||Boolean(process.env.CONTRACTSPEC_AI_PROXY_URL),mode:q?"byok":"managed",reason:!q?"Set OPENAI_API_KEY for BYOK mode":void 0,transports:["rest","sdk"],authMethods:["api-key"]});let z=process.env.ANTHROPIC_API_KEY;j.push({provider:"anthropic",available:Boolean(z)||Boolean(process.env.CONTRACTSPEC_AI_PROXY_URL),mode:z?"byok":"managed",reason:!z?"Set ANTHROPIC_API_KEY for BYOK mode":void 0,transports:["rest","sdk"],authMethods:["api-key"]});let C=process.env.MISTRAL_API_KEY;j.push({provider:"mistral",available:Boolean(C)||Boolean(process.env.CONTRACTSPEC_AI_PROXY_URL),mode:C?"byok":"managed",reason:!C?"Set MISTRAL_API_KEY for BYOK mode":void 0,transports:["rest","sdk"],authMethods:["api-key"]});let H=process.env.GOOGLE_API_KEY??process.env.GEMINI_API_KEY;return j.push({provider:"gemini",available:Boolean(H)||Boolean(process.env.CONTRACTSPEC_AI_PROXY_URL),mode:H?"byok":"managed",reason:!H?"Set GOOGLE_API_KEY for BYOK mode":void 0,transports:["rest","sdk"],authMethods:["api-key"]}),j}async function P(j){return R(j).validate()}function b(j){switch(j){case"ollama":return!0;case"openai":return Boolean(process.env.OPENAI_API_KEY);case"anthropic":return Boolean(process.env.ANTHROPIC_API_KEY);case"mistral":return Boolean(process.env.MISTRAL_API_KEY);case"gemini":return Boolean(process.env.GOOGLE_API_KEY??process.env.GEMINI_API_KEY);default:return!1}}function M(j){switch(j){case"ollama":return null;case"openai":return"OPENAI_API_KEY";case"anthropic":return"ANTHROPIC_API_KEY";case"mistral":return"MISTRAL_API_KEY";case"gemini":return"GOOGLE_API_KEY";default:return null}}async function O(j="http://localhost:11434"){try{return(await fetch(`${j}/api/tags`)).ok}catch{return!1}}async function U(j="http://localhost:11434"){try{let q=await fetch(`${j}/api/tags`);if(!q.ok)return[];return((await q.json()).models??[]).map((C)=>C.name)}catch{return[]}}export{P as validateProvider,U as listOllamaModels,O as isOllamaRunning,b as hasCredentials,M as getEnvVarName};