@ottocode/sdk 0.1.247 → 0.1.249
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/package.json +1 -1
- package/src/config/src/paths.ts +14 -8
- package/src/index.ts +14 -0
- package/src/providers/src/catalog-manual.ts +1 -1
- package/src/providers/src/catalog.ts +746 -0
- package/src/providers/src/index.ts +14 -0
- package/src/providers/src/model-catalog-cache.ts +147 -0
- package/src/providers/src/registry.ts +8 -3
- package/src/providers/src/utils.ts +16 -7
- package/src/providers/src/validate.ts +5 -3
package/package.json
CHANGED
package/src/config/src/paths.ts
CHANGED
|
@@ -110,18 +110,24 @@ export function getLocalDataDir(projectRoot: string): string {
|
|
|
110
110
|
return joinPath(projectRoot, '.otto');
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
async function loadFsPromises(): Promise<typeof import('node:fs/promises')> {
|
|
114
|
+
return Function('specifier', 'return import(specifier)')('node:fs/promises');
|
|
115
|
+
}
|
|
116
|
+
|
|
113
117
|
export async function ensureDir(dir: string) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
} catch {
|
|
118
|
-
const { promises: fs } = await import('node:fs');
|
|
119
|
-
await fs.mkdir(dir, { recursive: true }).catch(() => {});
|
|
120
|
-
}
|
|
118
|
+
const { mkdir, writeFile } = await loadFsPromises();
|
|
119
|
+
await mkdir(dir, { recursive: true }).catch(() => {});
|
|
120
|
+
await writeFile(joinPath(dir, '.keep'), '').catch(() => {});
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
export async function fileExists(p: string) {
|
|
124
|
-
|
|
124
|
+
try {
|
|
125
|
+
const { access } = await loadFsPromises();
|
|
126
|
+
await access(p);
|
|
127
|
+
return true;
|
|
128
|
+
} catch {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
125
131
|
}
|
|
126
132
|
|
|
127
133
|
export { joinPath };
|
package/src/index.ts
CHANGED
|
@@ -40,6 +40,20 @@ export type {
|
|
|
40
40
|
// Providers (from internal providers module)
|
|
41
41
|
// =======================
|
|
42
42
|
export { catalog } from './providers/src/index.ts';
|
|
43
|
+
export {
|
|
44
|
+
DEFAULT_REMOTE_MODEL_CATALOG_URL,
|
|
45
|
+
getCachedProviderCatalogEntry,
|
|
46
|
+
getModelCatalogCachePath,
|
|
47
|
+
mergeCachedModelCatalog,
|
|
48
|
+
normalizeModelCatalogPayload,
|
|
49
|
+
readCachedModelCatalog,
|
|
50
|
+
readCachedModelCatalogSync,
|
|
51
|
+
writeCachedModelCatalog,
|
|
52
|
+
} from './providers/src/index.ts';
|
|
53
|
+
export type {
|
|
54
|
+
CachedModelCatalog,
|
|
55
|
+
CachedProviderCatalogEntry,
|
|
56
|
+
} from './providers/src/index.ts';
|
|
43
57
|
export {
|
|
44
58
|
isProviderId,
|
|
45
59
|
providerIds,
|
|
@@ -104,7 +104,7 @@ function buildOllamaCloudEntry(): ProviderCatalogEntry {
|
|
|
104
104
|
export function mergeManualCatalog(
|
|
105
105
|
base: CatalogMap,
|
|
106
106
|
): Record<BuiltInProviderId, ProviderCatalogEntry> {
|
|
107
|
-
const ollamaCloudEntry = buildOllamaCloudEntry();
|
|
107
|
+
const ollamaCloudEntry = base[OLLAMA_CLOUD_ID] ?? buildOllamaCloudEntry();
|
|
108
108
|
const manualEntry = buildOttoRouterEntry();
|
|
109
109
|
const merged: Record<BuiltInProviderId, ProviderCatalogEntry> = {
|
|
110
110
|
...(base as Record<BuiltInProviderId, ProviderCatalogEntry>),
|
|
@@ -3567,6 +3567,56 @@ export const catalog: Partial<Record<BuiltInProviderId, ProviderCatalogEntry>> =
|
|
|
3567
3567
|
output: 65536,
|
|
3568
3568
|
},
|
|
3569
3569
|
},
|
|
3570
|
+
{
|
|
3571
|
+
id: 'deepseek/deepseek-v4-flash',
|
|
3572
|
+
label: 'DeepSeek V4 Flash',
|
|
3573
|
+
modalities: {
|
|
3574
|
+
input: ['text'],
|
|
3575
|
+
output: ['text'],
|
|
3576
|
+
},
|
|
3577
|
+
toolCall: true,
|
|
3578
|
+
reasoningText: true,
|
|
3579
|
+
attachment: false,
|
|
3580
|
+
temperature: true,
|
|
3581
|
+
knowledge: '2025-05',
|
|
3582
|
+
releaseDate: '2026-04-24',
|
|
3583
|
+
lastUpdated: '2026-04-24',
|
|
3584
|
+
openWeights: true,
|
|
3585
|
+
cost: {
|
|
3586
|
+
input: 0.14,
|
|
3587
|
+
output: 0.28,
|
|
3588
|
+
cacheRead: 0.028,
|
|
3589
|
+
},
|
|
3590
|
+
limit: {
|
|
3591
|
+
context: 1048576,
|
|
3592
|
+
output: 393216,
|
|
3593
|
+
},
|
|
3594
|
+
},
|
|
3595
|
+
{
|
|
3596
|
+
id: 'deepseek/deepseek-v4-pro',
|
|
3597
|
+
label: 'DeepSeek V4 Pro',
|
|
3598
|
+
modalities: {
|
|
3599
|
+
input: ['text'],
|
|
3600
|
+
output: ['text'],
|
|
3601
|
+
},
|
|
3602
|
+
toolCall: true,
|
|
3603
|
+
reasoningText: true,
|
|
3604
|
+
attachment: false,
|
|
3605
|
+
temperature: true,
|
|
3606
|
+
knowledge: '2025-05',
|
|
3607
|
+
releaseDate: '2026-04-24',
|
|
3608
|
+
lastUpdated: '2026-04-24',
|
|
3609
|
+
openWeights: true,
|
|
3610
|
+
cost: {
|
|
3611
|
+
input: 1.74,
|
|
3612
|
+
output: 3.48,
|
|
3613
|
+
cacheRead: 0.145,
|
|
3614
|
+
},
|
|
3615
|
+
limit: {
|
|
3616
|
+
context: 1048576,
|
|
3617
|
+
output: 393216,
|
|
3618
|
+
},
|
|
3619
|
+
},
|
|
3570
3620
|
{
|
|
3571
3621
|
id: 'google/gemini-2.0-flash-001',
|
|
3572
3622
|
ownedBy: 'google',
|
|
@@ -10465,4 +10515,700 @@ export const catalog: Partial<Record<BuiltInProviderId, ProviderCatalogEntry>> =
|
|
|
10465
10515
|
api: 'https://api.githubcopilot.com',
|
|
10466
10516
|
doc: 'https://docs.github.com/en/copilot',
|
|
10467
10517
|
},
|
|
10518
|
+
'ollama-cloud': {
|
|
10519
|
+
id: 'ollama-cloud',
|
|
10520
|
+
models: [
|
|
10521
|
+
{
|
|
10522
|
+
id: 'cogito-2.1:671b',
|
|
10523
|
+
label: 'cogito-2.1:671b',
|
|
10524
|
+
modalities: {
|
|
10525
|
+
input: ['text'],
|
|
10526
|
+
output: ['text'],
|
|
10527
|
+
},
|
|
10528
|
+
toolCall: true,
|
|
10529
|
+
reasoningText: true,
|
|
10530
|
+
attachment: false,
|
|
10531
|
+
releaseDate: '2025-11-19',
|
|
10532
|
+
lastUpdated: '2026-01-19',
|
|
10533
|
+
openWeights: true,
|
|
10534
|
+
limit: {
|
|
10535
|
+
context: 163840,
|
|
10536
|
+
output: 32000,
|
|
10537
|
+
},
|
|
10538
|
+
},
|
|
10539
|
+
{
|
|
10540
|
+
id: 'deepseek-v3.1:671b',
|
|
10541
|
+
label: 'deepseek-v3.1:671b',
|
|
10542
|
+
modalities: {
|
|
10543
|
+
input: ['text'],
|
|
10544
|
+
output: ['text'],
|
|
10545
|
+
},
|
|
10546
|
+
toolCall: true,
|
|
10547
|
+
reasoningText: true,
|
|
10548
|
+
attachment: false,
|
|
10549
|
+
releaseDate: '2025-08-21',
|
|
10550
|
+
lastUpdated: '2026-01-19',
|
|
10551
|
+
openWeights: true,
|
|
10552
|
+
limit: {
|
|
10553
|
+
context: 163840,
|
|
10554
|
+
output: 163840,
|
|
10555
|
+
},
|
|
10556
|
+
},
|
|
10557
|
+
{
|
|
10558
|
+
id: 'deepseek-v3.2',
|
|
10559
|
+
label: 'deepseek-v3.2',
|
|
10560
|
+
modalities: {
|
|
10561
|
+
input: ['text'],
|
|
10562
|
+
output: ['text'],
|
|
10563
|
+
},
|
|
10564
|
+
toolCall: true,
|
|
10565
|
+
reasoningText: true,
|
|
10566
|
+
attachment: false,
|
|
10567
|
+
releaseDate: '2025-06-15',
|
|
10568
|
+
lastUpdated: '2026-01-19',
|
|
10569
|
+
openWeights: true,
|
|
10570
|
+
limit: {
|
|
10571
|
+
context: 163840,
|
|
10572
|
+
output: 65536,
|
|
10573
|
+
},
|
|
10574
|
+
},
|
|
10575
|
+
{
|
|
10576
|
+
id: 'devstral-2:123b',
|
|
10577
|
+
label: 'devstral-2:123b',
|
|
10578
|
+
modalities: {
|
|
10579
|
+
input: ['text'],
|
|
10580
|
+
output: ['text'],
|
|
10581
|
+
},
|
|
10582
|
+
toolCall: true,
|
|
10583
|
+
reasoningText: false,
|
|
10584
|
+
attachment: false,
|
|
10585
|
+
releaseDate: '2025-12-09',
|
|
10586
|
+
lastUpdated: '2026-01-19',
|
|
10587
|
+
openWeights: true,
|
|
10588
|
+
limit: {
|
|
10589
|
+
context: 262144,
|
|
10590
|
+
output: 262144,
|
|
10591
|
+
},
|
|
10592
|
+
},
|
|
10593
|
+
{
|
|
10594
|
+
id: 'devstral-small-2:24b',
|
|
10595
|
+
label: 'devstral-small-2:24b',
|
|
10596
|
+
modalities: {
|
|
10597
|
+
input: ['text', 'image'],
|
|
10598
|
+
output: ['text'],
|
|
10599
|
+
},
|
|
10600
|
+
toolCall: true,
|
|
10601
|
+
reasoningText: false,
|
|
10602
|
+
attachment: true,
|
|
10603
|
+
releaseDate: '2025-12-09',
|
|
10604
|
+
lastUpdated: '2026-01-19',
|
|
10605
|
+
openWeights: true,
|
|
10606
|
+
limit: {
|
|
10607
|
+
context: 262144,
|
|
10608
|
+
output: 262144,
|
|
10609
|
+
},
|
|
10610
|
+
},
|
|
10611
|
+
{
|
|
10612
|
+
id: 'gemini-3-flash-preview',
|
|
10613
|
+
ownedBy: 'google',
|
|
10614
|
+
label: 'gemini-3-flash-preview',
|
|
10615
|
+
modalities: {
|
|
10616
|
+
input: ['text', 'image'],
|
|
10617
|
+
output: ['text'],
|
|
10618
|
+
},
|
|
10619
|
+
toolCall: true,
|
|
10620
|
+
reasoningText: true,
|
|
10621
|
+
attachment: true,
|
|
10622
|
+
knowledge: '2025-01',
|
|
10623
|
+
releaseDate: '2025-12-17',
|
|
10624
|
+
lastUpdated: '2026-04-08',
|
|
10625
|
+
openWeights: true,
|
|
10626
|
+
limit: {
|
|
10627
|
+
context: 1048576,
|
|
10628
|
+
output: 65536,
|
|
10629
|
+
},
|
|
10630
|
+
},
|
|
10631
|
+
{
|
|
10632
|
+
id: 'gemma3:12b',
|
|
10633
|
+
label: 'gemma3:12b',
|
|
10634
|
+
modalities: {
|
|
10635
|
+
input: ['text', 'image'],
|
|
10636
|
+
output: ['text'],
|
|
10637
|
+
},
|
|
10638
|
+
toolCall: false,
|
|
10639
|
+
reasoningText: false,
|
|
10640
|
+
attachment: true,
|
|
10641
|
+
releaseDate: '2024-12-01',
|
|
10642
|
+
lastUpdated: '2026-01-19',
|
|
10643
|
+
openWeights: true,
|
|
10644
|
+
limit: {
|
|
10645
|
+
context: 131072,
|
|
10646
|
+
output: 131072,
|
|
10647
|
+
},
|
|
10648
|
+
},
|
|
10649
|
+
{
|
|
10650
|
+
id: 'gemma3:27b',
|
|
10651
|
+
label: 'gemma3:27b',
|
|
10652
|
+
modalities: {
|
|
10653
|
+
input: ['text', 'image'],
|
|
10654
|
+
output: ['text'],
|
|
10655
|
+
},
|
|
10656
|
+
toolCall: false,
|
|
10657
|
+
reasoningText: false,
|
|
10658
|
+
attachment: true,
|
|
10659
|
+
releaseDate: '2025-07-27',
|
|
10660
|
+
lastUpdated: '2026-01-19',
|
|
10661
|
+
openWeights: true,
|
|
10662
|
+
limit: {
|
|
10663
|
+
context: 131072,
|
|
10664
|
+
output: 131072,
|
|
10665
|
+
},
|
|
10666
|
+
},
|
|
10667
|
+
{
|
|
10668
|
+
id: 'gemma3:4b',
|
|
10669
|
+
label: 'gemma3:4b',
|
|
10670
|
+
modalities: {
|
|
10671
|
+
input: ['text', 'image'],
|
|
10672
|
+
output: ['text'],
|
|
10673
|
+
},
|
|
10674
|
+
toolCall: false,
|
|
10675
|
+
reasoningText: false,
|
|
10676
|
+
attachment: true,
|
|
10677
|
+
releaseDate: '2024-12-01',
|
|
10678
|
+
lastUpdated: '2026-01-19',
|
|
10679
|
+
openWeights: true,
|
|
10680
|
+
limit: {
|
|
10681
|
+
context: 131072,
|
|
10682
|
+
output: 131072,
|
|
10683
|
+
},
|
|
10684
|
+
},
|
|
10685
|
+
{
|
|
10686
|
+
id: 'gemma4:31b',
|
|
10687
|
+
label: 'gemma4:31b',
|
|
10688
|
+
modalities: {
|
|
10689
|
+
input: ['text', 'image'],
|
|
10690
|
+
output: ['text'],
|
|
10691
|
+
},
|
|
10692
|
+
toolCall: true,
|
|
10693
|
+
reasoningText: true,
|
|
10694
|
+
attachment: true,
|
|
10695
|
+
knowledge: '2025-01',
|
|
10696
|
+
releaseDate: '2026-04-02',
|
|
10697
|
+
lastUpdated: '2026-04-08',
|
|
10698
|
+
openWeights: true,
|
|
10699
|
+
limit: {
|
|
10700
|
+
context: 262144,
|
|
10701
|
+
output: 262144,
|
|
10702
|
+
},
|
|
10703
|
+
},
|
|
10704
|
+
{
|
|
10705
|
+
id: 'glm-4.6',
|
|
10706
|
+
ownedBy: 'zai',
|
|
10707
|
+
label: 'glm-4.6',
|
|
10708
|
+
modalities: {
|
|
10709
|
+
input: ['text'],
|
|
10710
|
+
output: ['text'],
|
|
10711
|
+
},
|
|
10712
|
+
toolCall: true,
|
|
10713
|
+
reasoningText: true,
|
|
10714
|
+
attachment: false,
|
|
10715
|
+
releaseDate: '2025-09-29',
|
|
10716
|
+
lastUpdated: '2026-01-19',
|
|
10717
|
+
openWeights: true,
|
|
10718
|
+
limit: {
|
|
10719
|
+
context: 202752,
|
|
10720
|
+
output: 131072,
|
|
10721
|
+
},
|
|
10722
|
+
},
|
|
10723
|
+
{
|
|
10724
|
+
id: 'glm-4.7',
|
|
10725
|
+
ownedBy: 'zai',
|
|
10726
|
+
label: 'glm-4.7',
|
|
10727
|
+
modalities: {
|
|
10728
|
+
input: ['text'],
|
|
10729
|
+
output: ['text'],
|
|
10730
|
+
},
|
|
10731
|
+
toolCall: true,
|
|
10732
|
+
reasoningText: true,
|
|
10733
|
+
attachment: false,
|
|
10734
|
+
releaseDate: '2025-12-22',
|
|
10735
|
+
lastUpdated: '2026-01-19',
|
|
10736
|
+
openWeights: true,
|
|
10737
|
+
limit: {
|
|
10738
|
+
context: 202752,
|
|
10739
|
+
output: 131072,
|
|
10740
|
+
},
|
|
10741
|
+
},
|
|
10742
|
+
{
|
|
10743
|
+
id: 'glm-5',
|
|
10744
|
+
ownedBy: 'zai',
|
|
10745
|
+
label: 'glm-5',
|
|
10746
|
+
modalities: {
|
|
10747
|
+
input: ['text'],
|
|
10748
|
+
output: ['text'],
|
|
10749
|
+
},
|
|
10750
|
+
toolCall: true,
|
|
10751
|
+
reasoningText: true,
|
|
10752
|
+
attachment: false,
|
|
10753
|
+
releaseDate: '2026-02-11',
|
|
10754
|
+
lastUpdated: '2026-02-11',
|
|
10755
|
+
openWeights: true,
|
|
10756
|
+
limit: {
|
|
10757
|
+
context: 202752,
|
|
10758
|
+
output: 131072,
|
|
10759
|
+
},
|
|
10760
|
+
},
|
|
10761
|
+
{
|
|
10762
|
+
id: 'glm-5.1',
|
|
10763
|
+
ownedBy: 'zai',
|
|
10764
|
+
label: 'glm-5.1',
|
|
10765
|
+
modalities: {
|
|
10766
|
+
input: ['text'],
|
|
10767
|
+
output: ['text'],
|
|
10768
|
+
},
|
|
10769
|
+
toolCall: true,
|
|
10770
|
+
reasoningText: true,
|
|
10771
|
+
attachment: false,
|
|
10772
|
+
releaseDate: '2026-03-27',
|
|
10773
|
+
lastUpdated: '2026-04-07',
|
|
10774
|
+
openWeights: true,
|
|
10775
|
+
limit: {
|
|
10776
|
+
context: 202752,
|
|
10777
|
+
output: 131072,
|
|
10778
|
+
},
|
|
10779
|
+
},
|
|
10780
|
+
{
|
|
10781
|
+
id: 'gpt-oss:120b',
|
|
10782
|
+
ownedBy: 'openai',
|
|
10783
|
+
label: 'gpt-oss:120b',
|
|
10784
|
+
modalities: {
|
|
10785
|
+
input: ['text'],
|
|
10786
|
+
output: ['text'],
|
|
10787
|
+
},
|
|
10788
|
+
toolCall: true,
|
|
10789
|
+
reasoningText: true,
|
|
10790
|
+
attachment: false,
|
|
10791
|
+
releaseDate: '2025-08-05',
|
|
10792
|
+
lastUpdated: '2026-01-19',
|
|
10793
|
+
openWeights: true,
|
|
10794
|
+
limit: {
|
|
10795
|
+
context: 131072,
|
|
10796
|
+
output: 32768,
|
|
10797
|
+
},
|
|
10798
|
+
},
|
|
10799
|
+
{
|
|
10800
|
+
id: 'gpt-oss:20b',
|
|
10801
|
+
ownedBy: 'openai',
|
|
10802
|
+
label: 'gpt-oss:20b',
|
|
10803
|
+
modalities: {
|
|
10804
|
+
input: ['text'],
|
|
10805
|
+
output: ['text'],
|
|
10806
|
+
},
|
|
10807
|
+
toolCall: true,
|
|
10808
|
+
reasoningText: true,
|
|
10809
|
+
attachment: false,
|
|
10810
|
+
releaseDate: '2025-08-05',
|
|
10811
|
+
lastUpdated: '2026-01-19',
|
|
10812
|
+
openWeights: true,
|
|
10813
|
+
limit: {
|
|
10814
|
+
context: 131072,
|
|
10815
|
+
output: 32768,
|
|
10816
|
+
},
|
|
10817
|
+
},
|
|
10818
|
+
{
|
|
10819
|
+
id: 'kimi-k2-thinking',
|
|
10820
|
+
ownedBy: 'moonshot',
|
|
10821
|
+
label: 'kimi-k2-thinking',
|
|
10822
|
+
modalities: {
|
|
10823
|
+
input: ['text'],
|
|
10824
|
+
output: ['text'],
|
|
10825
|
+
},
|
|
10826
|
+
toolCall: true,
|
|
10827
|
+
reasoningText: true,
|
|
10828
|
+
attachment: false,
|
|
10829
|
+
knowledge: '2024-08',
|
|
10830
|
+
releaseDate: '2025-11-06',
|
|
10831
|
+
lastUpdated: '2026-01-19',
|
|
10832
|
+
openWeights: true,
|
|
10833
|
+
limit: {
|
|
10834
|
+
context: 262144,
|
|
10835
|
+
output: 262144,
|
|
10836
|
+
},
|
|
10837
|
+
},
|
|
10838
|
+
{
|
|
10839
|
+
id: 'kimi-k2:1t',
|
|
10840
|
+
ownedBy: 'moonshot',
|
|
10841
|
+
label: 'kimi-k2:1t',
|
|
10842
|
+
modalities: {
|
|
10843
|
+
input: ['text'],
|
|
10844
|
+
output: ['text'],
|
|
10845
|
+
},
|
|
10846
|
+
toolCall: true,
|
|
10847
|
+
reasoningText: false,
|
|
10848
|
+
attachment: false,
|
|
10849
|
+
knowledge: '2024-10',
|
|
10850
|
+
releaseDate: '2025-07-11',
|
|
10851
|
+
lastUpdated: '2026-01-19',
|
|
10852
|
+
openWeights: true,
|
|
10853
|
+
limit: {
|
|
10854
|
+
context: 262144,
|
|
10855
|
+
output: 262144,
|
|
10856
|
+
},
|
|
10857
|
+
},
|
|
10858
|
+
{
|
|
10859
|
+
id: 'kimi-k2.5',
|
|
10860
|
+
ownedBy: 'moonshot',
|
|
10861
|
+
label: 'kimi-k2.5',
|
|
10862
|
+
modalities: {
|
|
10863
|
+
input: ['text', 'image'],
|
|
10864
|
+
output: ['text'],
|
|
10865
|
+
},
|
|
10866
|
+
toolCall: true,
|
|
10867
|
+
reasoningText: true,
|
|
10868
|
+
attachment: true,
|
|
10869
|
+
releaseDate: '2026-01-27',
|
|
10870
|
+
lastUpdated: '2026-01-27',
|
|
10871
|
+
openWeights: true,
|
|
10872
|
+
limit: {
|
|
10873
|
+
context: 262144,
|
|
10874
|
+
output: 262144,
|
|
10875
|
+
},
|
|
10876
|
+
},
|
|
10877
|
+
{
|
|
10878
|
+
id: 'kimi-k2.6:cloud',
|
|
10879
|
+
ownedBy: 'moonshot',
|
|
10880
|
+
label: 'kimi-k2.6:cloud',
|
|
10881
|
+
modalities: {
|
|
10882
|
+
input: ['text', 'image'],
|
|
10883
|
+
output: ['text'],
|
|
10884
|
+
},
|
|
10885
|
+
toolCall: true,
|
|
10886
|
+
reasoningText: true,
|
|
10887
|
+
attachment: true,
|
|
10888
|
+
releaseDate: '2026-04-20',
|
|
10889
|
+
lastUpdated: '2026-04-20',
|
|
10890
|
+
openWeights: true,
|
|
10891
|
+
limit: {
|
|
10892
|
+
context: 262144,
|
|
10893
|
+
output: 262144,
|
|
10894
|
+
},
|
|
10895
|
+
},
|
|
10896
|
+
{
|
|
10897
|
+
id: 'minimax-m2',
|
|
10898
|
+
ownedBy: 'minimax',
|
|
10899
|
+
label: 'minimax-m2',
|
|
10900
|
+
modalities: {
|
|
10901
|
+
input: ['text'],
|
|
10902
|
+
output: ['text'],
|
|
10903
|
+
},
|
|
10904
|
+
toolCall: true,
|
|
10905
|
+
reasoningText: false,
|
|
10906
|
+
attachment: false,
|
|
10907
|
+
releaseDate: '2025-10-23',
|
|
10908
|
+
lastUpdated: '2026-01-19',
|
|
10909
|
+
openWeights: true,
|
|
10910
|
+
limit: {
|
|
10911
|
+
context: 204800,
|
|
10912
|
+
output: 128000,
|
|
10913
|
+
},
|
|
10914
|
+
},
|
|
10915
|
+
{
|
|
10916
|
+
id: 'minimax-m2.1',
|
|
10917
|
+
ownedBy: 'minimax',
|
|
10918
|
+
label: 'minimax-m2.1',
|
|
10919
|
+
modalities: {
|
|
10920
|
+
input: ['text'],
|
|
10921
|
+
output: ['text'],
|
|
10922
|
+
},
|
|
10923
|
+
toolCall: true,
|
|
10924
|
+
reasoningText: true,
|
|
10925
|
+
attachment: false,
|
|
10926
|
+
releaseDate: '2025-12-23',
|
|
10927
|
+
lastUpdated: '2026-01-19',
|
|
10928
|
+
openWeights: true,
|
|
10929
|
+
limit: {
|
|
10930
|
+
context: 204800,
|
|
10931
|
+
output: 131072,
|
|
10932
|
+
},
|
|
10933
|
+
},
|
|
10934
|
+
{
|
|
10935
|
+
id: 'minimax-m2.5',
|
|
10936
|
+
ownedBy: 'minimax',
|
|
10937
|
+
label: 'minimax-m2.5',
|
|
10938
|
+
modalities: {
|
|
10939
|
+
input: ['text'],
|
|
10940
|
+
output: ['text'],
|
|
10941
|
+
},
|
|
10942
|
+
toolCall: true,
|
|
10943
|
+
reasoningText: true,
|
|
10944
|
+
attachment: false,
|
|
10945
|
+
knowledge: '2025-01',
|
|
10946
|
+
releaseDate: '2026-02-12',
|
|
10947
|
+
lastUpdated: '2026-02-12',
|
|
10948
|
+
openWeights: true,
|
|
10949
|
+
limit: {
|
|
10950
|
+
context: 204800,
|
|
10951
|
+
output: 131072,
|
|
10952
|
+
},
|
|
10953
|
+
},
|
|
10954
|
+
{
|
|
10955
|
+
id: 'minimax-m2.7',
|
|
10956
|
+
ownedBy: 'minimax',
|
|
10957
|
+
label: 'minimax-m2.7',
|
|
10958
|
+
modalities: {
|
|
10959
|
+
input: ['text'],
|
|
10960
|
+
output: ['text'],
|
|
10961
|
+
},
|
|
10962
|
+
toolCall: true,
|
|
10963
|
+
reasoningText: true,
|
|
10964
|
+
attachment: false,
|
|
10965
|
+
releaseDate: '2026-03-18',
|
|
10966
|
+
lastUpdated: '2026-03-18',
|
|
10967
|
+
openWeights: true,
|
|
10968
|
+
limit: {
|
|
10969
|
+
context: 204800,
|
|
10970
|
+
output: 131072,
|
|
10971
|
+
},
|
|
10972
|
+
},
|
|
10973
|
+
{
|
|
10974
|
+
id: 'ministral-3:14b',
|
|
10975
|
+
label: 'ministral-3:14b',
|
|
10976
|
+
modalities: {
|
|
10977
|
+
input: ['text', 'image'],
|
|
10978
|
+
output: ['text'],
|
|
10979
|
+
},
|
|
10980
|
+
toolCall: true,
|
|
10981
|
+
reasoningText: false,
|
|
10982
|
+
attachment: true,
|
|
10983
|
+
releaseDate: '2024-12-01',
|
|
10984
|
+
lastUpdated: '2026-01-19',
|
|
10985
|
+
openWeights: true,
|
|
10986
|
+
limit: {
|
|
10987
|
+
context: 262144,
|
|
10988
|
+
output: 128000,
|
|
10989
|
+
},
|
|
10990
|
+
},
|
|
10991
|
+
{
|
|
10992
|
+
id: 'ministral-3:3b',
|
|
10993
|
+
label: 'ministral-3:3b',
|
|
10994
|
+
modalities: {
|
|
10995
|
+
input: ['text', 'image'],
|
|
10996
|
+
output: ['text'],
|
|
10997
|
+
},
|
|
10998
|
+
toolCall: true,
|
|
10999
|
+
reasoningText: false,
|
|
11000
|
+
attachment: true,
|
|
11001
|
+
releaseDate: '2024-10-22',
|
|
11002
|
+
lastUpdated: '2026-01-19',
|
|
11003
|
+
openWeights: true,
|
|
11004
|
+
limit: {
|
|
11005
|
+
context: 262144,
|
|
11006
|
+
output: 128000,
|
|
11007
|
+
},
|
|
11008
|
+
},
|
|
11009
|
+
{
|
|
11010
|
+
id: 'ministral-3:8b',
|
|
11011
|
+
label: 'ministral-3:8b',
|
|
11012
|
+
modalities: {
|
|
11013
|
+
input: ['text', 'image'],
|
|
11014
|
+
output: ['text'],
|
|
11015
|
+
},
|
|
11016
|
+
toolCall: true,
|
|
11017
|
+
reasoningText: false,
|
|
11018
|
+
attachment: true,
|
|
11019
|
+
releaseDate: '2024-12-01',
|
|
11020
|
+
lastUpdated: '2026-01-19',
|
|
11021
|
+
openWeights: true,
|
|
11022
|
+
limit: {
|
|
11023
|
+
context: 262144,
|
|
11024
|
+
output: 128000,
|
|
11025
|
+
},
|
|
11026
|
+
},
|
|
11027
|
+
{
|
|
11028
|
+
id: 'mistral-large-3:675b',
|
|
11029
|
+
label: 'mistral-large-3:675b',
|
|
11030
|
+
modalities: {
|
|
11031
|
+
input: ['text', 'image'],
|
|
11032
|
+
output: ['text'],
|
|
11033
|
+
},
|
|
11034
|
+
toolCall: true,
|
|
11035
|
+
reasoningText: false,
|
|
11036
|
+
attachment: true,
|
|
11037
|
+
releaseDate: '2025-12-02',
|
|
11038
|
+
lastUpdated: '2026-01-19',
|
|
11039
|
+
openWeights: true,
|
|
11040
|
+
limit: {
|
|
11041
|
+
context: 262144,
|
|
11042
|
+
output: 262144,
|
|
11043
|
+
},
|
|
11044
|
+
},
|
|
11045
|
+
{
|
|
11046
|
+
id: 'nemotron-3-nano:30b',
|
|
11047
|
+
label: 'nemotron-3-nano:30b',
|
|
11048
|
+
modalities: {
|
|
11049
|
+
input: ['text'],
|
|
11050
|
+
output: ['text'],
|
|
11051
|
+
},
|
|
11052
|
+
toolCall: true,
|
|
11053
|
+
reasoningText: true,
|
|
11054
|
+
attachment: false,
|
|
11055
|
+
releaseDate: '2025-12-15',
|
|
11056
|
+
lastUpdated: '2026-01-19',
|
|
11057
|
+
openWeights: true,
|
|
11058
|
+
limit: {
|
|
11059
|
+
context: 1048576,
|
|
11060
|
+
output: 131072,
|
|
11061
|
+
},
|
|
11062
|
+
},
|
|
11063
|
+
{
|
|
11064
|
+
id: 'nemotron-3-super',
|
|
11065
|
+
label: 'nemotron-3-super',
|
|
11066
|
+
modalities: {
|
|
11067
|
+
input: ['text'],
|
|
11068
|
+
output: ['text'],
|
|
11069
|
+
},
|
|
11070
|
+
toolCall: true,
|
|
11071
|
+
reasoningText: true,
|
|
11072
|
+
attachment: false,
|
|
11073
|
+
releaseDate: '2026-03-11',
|
|
11074
|
+
lastUpdated: '2026-03-12',
|
|
11075
|
+
openWeights: true,
|
|
11076
|
+
limit: {
|
|
11077
|
+
context: 262144,
|
|
11078
|
+
output: 65536,
|
|
11079
|
+
},
|
|
11080
|
+
},
|
|
11081
|
+
{
|
|
11082
|
+
id: 'qwen3-coder-next',
|
|
11083
|
+
label: 'qwen3-coder-next',
|
|
11084
|
+
modalities: {
|
|
11085
|
+
input: ['text'],
|
|
11086
|
+
output: ['text'],
|
|
11087
|
+
},
|
|
11088
|
+
toolCall: true,
|
|
11089
|
+
reasoningText: false,
|
|
11090
|
+
attachment: false,
|
|
11091
|
+
releaseDate: '2026-02-02',
|
|
11092
|
+
lastUpdated: '2026-02-08',
|
|
11093
|
+
openWeights: true,
|
|
11094
|
+
limit: {
|
|
11095
|
+
context: 262144,
|
|
11096
|
+
output: 65536,
|
|
11097
|
+
},
|
|
11098
|
+
},
|
|
11099
|
+
{
|
|
11100
|
+
id: 'qwen3-coder:480b',
|
|
11101
|
+
label: 'qwen3-coder:480b',
|
|
11102
|
+
modalities: {
|
|
11103
|
+
input: ['text'],
|
|
11104
|
+
output: ['text'],
|
|
11105
|
+
},
|
|
11106
|
+
toolCall: true,
|
|
11107
|
+
reasoningText: false,
|
|
11108
|
+
attachment: false,
|
|
11109
|
+
releaseDate: '2025-07-22',
|
|
11110
|
+
lastUpdated: '2026-01-19',
|
|
11111
|
+
openWeights: true,
|
|
11112
|
+
limit: {
|
|
11113
|
+
context: 262144,
|
|
11114
|
+
output: 65536,
|
|
11115
|
+
},
|
|
11116
|
+
},
|
|
11117
|
+
{
|
|
11118
|
+
id: 'qwen3-next:80b',
|
|
11119
|
+
label: 'qwen3-next:80b',
|
|
11120
|
+
modalities: {
|
|
11121
|
+
input: ['text'],
|
|
11122
|
+
output: ['text'],
|
|
11123
|
+
},
|
|
11124
|
+
toolCall: true,
|
|
11125
|
+
reasoningText: true,
|
|
11126
|
+
attachment: false,
|
|
11127
|
+
releaseDate: '2025-09-15',
|
|
11128
|
+
lastUpdated: '2026-01-19',
|
|
11129
|
+
openWeights: true,
|
|
11130
|
+
limit: {
|
|
11131
|
+
context: 262144,
|
|
11132
|
+
output: 32768,
|
|
11133
|
+
},
|
|
11134
|
+
},
|
|
11135
|
+
{
|
|
11136
|
+
id: 'qwen3-vl:235b',
|
|
11137
|
+
label: 'qwen3-vl:235b',
|
|
11138
|
+
modalities: {
|
|
11139
|
+
input: ['text', 'image'],
|
|
11140
|
+
output: ['text'],
|
|
11141
|
+
},
|
|
11142
|
+
toolCall: true,
|
|
11143
|
+
reasoningText: true,
|
|
11144
|
+
attachment: true,
|
|
11145
|
+
releaseDate: '2025-09-22',
|
|
11146
|
+
lastUpdated: '2026-01-19',
|
|
11147
|
+
openWeights: true,
|
|
11148
|
+
limit: {
|
|
11149
|
+
context: 262144,
|
|
11150
|
+
output: 32768,
|
|
11151
|
+
},
|
|
11152
|
+
},
|
|
11153
|
+
{
|
|
11154
|
+
id: 'qwen3-vl:235b-instruct',
|
|
11155
|
+
label: 'qwen3-vl:235b-instruct',
|
|
11156
|
+
modalities: {
|
|
11157
|
+
input: ['text', 'image'],
|
|
11158
|
+
output: ['text'],
|
|
11159
|
+
},
|
|
11160
|
+
toolCall: true,
|
|
11161
|
+
reasoningText: false,
|
|
11162
|
+
attachment: true,
|
|
11163
|
+
releaseDate: '2025-09-22',
|
|
11164
|
+
lastUpdated: '2026-01-19',
|
|
11165
|
+
openWeights: true,
|
|
11166
|
+
limit: {
|
|
11167
|
+
context: 262144,
|
|
11168
|
+
output: 131072,
|
|
11169
|
+
},
|
|
11170
|
+
},
|
|
11171
|
+
{
|
|
11172
|
+
id: 'qwen3.5:397b',
|
|
11173
|
+
label: 'qwen3.5:397b',
|
|
11174
|
+
modalities: {
|
|
11175
|
+
input: ['text', 'image'],
|
|
11176
|
+
output: ['text'],
|
|
11177
|
+
},
|
|
11178
|
+
toolCall: true,
|
|
11179
|
+
reasoningText: true,
|
|
11180
|
+
attachment: true,
|
|
11181
|
+
releaseDate: '2026-02-15',
|
|
11182
|
+
lastUpdated: '2026-02-17',
|
|
11183
|
+
openWeights: true,
|
|
11184
|
+
limit: {
|
|
11185
|
+
context: 262144,
|
|
11186
|
+
output: 81920,
|
|
11187
|
+
},
|
|
11188
|
+
},
|
|
11189
|
+
{
|
|
11190
|
+
id: 'rnj-1:8b',
|
|
11191
|
+
label: 'rnj-1:8b',
|
|
11192
|
+
modalities: {
|
|
11193
|
+
input: ['text'],
|
|
11194
|
+
output: ['text'],
|
|
11195
|
+
},
|
|
11196
|
+
toolCall: true,
|
|
11197
|
+
reasoningText: false,
|
|
11198
|
+
attachment: false,
|
|
11199
|
+
releaseDate: '2025-12-06',
|
|
11200
|
+
lastUpdated: '2026-01-19',
|
|
11201
|
+
openWeights: true,
|
|
11202
|
+
limit: {
|
|
11203
|
+
context: 32768,
|
|
11204
|
+
output: 4096,
|
|
11205
|
+
},
|
|
11206
|
+
},
|
|
11207
|
+
],
|
|
11208
|
+
label: 'Ollama Cloud',
|
|
11209
|
+
env: ['OLLAMA_API_KEY'],
|
|
11210
|
+
npm: 'ai-sdk-ollama',
|
|
11211
|
+
api: 'https://ollama.com',
|
|
11212
|
+
doc: 'https://docs.ollama.com/cloud',
|
|
11213
|
+
},
|
|
10468
11214
|
} as const satisfies Partial<Record<BuiltInProviderId, ProviderCatalogEntry>>;
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
export { isProviderAuthorized, ensureProviderEnv } from './authorization.ts';
|
|
2
2
|
export { catalog } from './catalog-merged.ts';
|
|
3
|
+
export {
|
|
4
|
+
DEFAULT_REMOTE_MODEL_CATALOG_URL,
|
|
5
|
+
getCachedProviderCatalogEntry,
|
|
6
|
+
getModelCatalogCachePath,
|
|
7
|
+
mergeCachedModelCatalog,
|
|
8
|
+
normalizeModelCatalogPayload,
|
|
9
|
+
readCachedModelCatalog,
|
|
10
|
+
readCachedModelCatalogSync,
|
|
11
|
+
writeCachedModelCatalog,
|
|
12
|
+
} from './model-catalog-cache.ts';
|
|
13
|
+
export type {
|
|
14
|
+
CachedModelCatalog,
|
|
15
|
+
CachedProviderCatalogEntry,
|
|
16
|
+
} from './model-catalog-cache.ts';
|
|
3
17
|
export type {
|
|
4
18
|
BuiltInProviderId,
|
|
5
19
|
ProviderId,
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { getGlobalConfigDir, joinPath } from '../../config/src/paths.ts';
|
|
2
|
+
import type { ModelInfo, ProviderId } from '../../types/src/index.ts';
|
|
3
|
+
|
|
4
|
+
export type CachedProviderCatalogEntry = {
|
|
5
|
+
id: ProviderId;
|
|
6
|
+
label?: string;
|
|
7
|
+
models: ModelInfo[];
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type CachedModelCatalog = {
|
|
11
|
+
version: 1;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
providers: Record<string, CachedProviderCatalogEntry>;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const DEFAULT_REMOTE_MODEL_CATALOG_URL =
|
|
17
|
+
'https://ottocode.io/catalog/models.json';
|
|
18
|
+
|
|
19
|
+
export function getModelCatalogCachePath(): string {
|
|
20
|
+
return joinPath(getGlobalConfigDir(), 'models-catalog.json');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
24
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function loadFsPromises(): Promise<typeof import('node:fs/promises')> {
|
|
28
|
+
return Function('specifier', 'return import(specifier)')('node:fs/promises');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function readFileSyncCompat(path: string): string | null {
|
|
32
|
+
try {
|
|
33
|
+
const req = Function(
|
|
34
|
+
'return typeof require === "function" ? require : null',
|
|
35
|
+
)() as ((specifier: string) => typeof import('node:fs')) | null;
|
|
36
|
+
return req?.('node:fs').readFileSync(path, 'utf8') ?? null;
|
|
37
|
+
} catch {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function normalizeProviderEntry(
|
|
43
|
+
id: string,
|
|
44
|
+
value: unknown,
|
|
45
|
+
): CachedProviderCatalogEntry | null {
|
|
46
|
+
if (!isRecord(value)) return null;
|
|
47
|
+
const models = Array.isArray(value.models)
|
|
48
|
+
? value.models.filter(
|
|
49
|
+
(model): model is ModelInfo =>
|
|
50
|
+
isRecord(model) && typeof model.id === 'string',
|
|
51
|
+
)
|
|
52
|
+
: [];
|
|
53
|
+
return {
|
|
54
|
+
id: (typeof value.id === 'string' ? value.id : id) as ProviderId,
|
|
55
|
+
label: typeof value.label === 'string' ? value.label : undefined,
|
|
56
|
+
models,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function normalizeModelCatalogPayload(
|
|
61
|
+
payload: unknown,
|
|
62
|
+
): Record<string, CachedProviderCatalogEntry> {
|
|
63
|
+
if (!isRecord(payload)) return {};
|
|
64
|
+
const source = isRecord(payload.providers) ? payload.providers : payload;
|
|
65
|
+
const providers: Record<string, CachedProviderCatalogEntry> = {};
|
|
66
|
+
for (const [id, value] of Object.entries(source)) {
|
|
67
|
+
const entry = normalizeProviderEntry(id, value);
|
|
68
|
+
if (entry) providers[id] = entry;
|
|
69
|
+
}
|
|
70
|
+
return providers;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function readCachedModelCatalog(): Promise<CachedModelCatalog | null> {
|
|
74
|
+
try {
|
|
75
|
+
const { readFile } = await loadFsPromises();
|
|
76
|
+
const payload = JSON.parse(
|
|
77
|
+
await readFile(getModelCatalogCachePath(), 'utf8'),
|
|
78
|
+
);
|
|
79
|
+
const providers = normalizeModelCatalogPayload(payload);
|
|
80
|
+
return {
|
|
81
|
+
version: 1,
|
|
82
|
+
updatedAt:
|
|
83
|
+
isRecord(payload) && typeof payload.updatedAt === 'string'
|
|
84
|
+
? payload.updatedAt
|
|
85
|
+
: new Date(0).toISOString(),
|
|
86
|
+
providers,
|
|
87
|
+
};
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function readCachedModelCatalogSync(): CachedModelCatalog | null {
|
|
94
|
+
try {
|
|
95
|
+
const text = readFileSyncCompat(getModelCatalogCachePath());
|
|
96
|
+
if (!text) return null;
|
|
97
|
+
const payload = JSON.parse(text);
|
|
98
|
+
const providers = normalizeModelCatalogPayload(payload);
|
|
99
|
+
return {
|
|
100
|
+
version: 1,
|
|
101
|
+
updatedAt:
|
|
102
|
+
isRecord(payload) && typeof payload.updatedAt === 'string'
|
|
103
|
+
? payload.updatedAt
|
|
104
|
+
: new Date(0).toISOString(),
|
|
105
|
+
providers,
|
|
106
|
+
};
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function getCachedProviderCatalogEntry(
|
|
113
|
+
provider: ProviderId,
|
|
114
|
+
): CachedProviderCatalogEntry | undefined {
|
|
115
|
+
return readCachedModelCatalogSync()?.providers[provider];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export async function writeCachedModelCatalog(
|
|
119
|
+
providers: Record<string, CachedProviderCatalogEntry>,
|
|
120
|
+
): Promise<void> {
|
|
121
|
+
const path = getModelCatalogCachePath();
|
|
122
|
+
const dir = path.slice(0, path.lastIndexOf('/'));
|
|
123
|
+
const { mkdir, writeFile } = await loadFsPromises();
|
|
124
|
+
await mkdir(dir, { recursive: true });
|
|
125
|
+
await writeFile(
|
|
126
|
+
path,
|
|
127
|
+
JSON.stringify(
|
|
128
|
+
{
|
|
129
|
+
version: 1,
|
|
130
|
+
updatedAt: new Date().toISOString(),
|
|
131
|
+
providers,
|
|
132
|
+
},
|
|
133
|
+
null,
|
|
134
|
+
2,
|
|
135
|
+
),
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function mergeCachedModelCatalog(
|
|
140
|
+
providers: Record<string, CachedProviderCatalogEntry>,
|
|
141
|
+
): Promise<void> {
|
|
142
|
+
const existing = await readCachedModelCatalog();
|
|
143
|
+
await writeCachedModelCatalog({
|
|
144
|
+
...(existing?.providers ?? {}),
|
|
145
|
+
...providers,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { catalog } from './catalog-merged.ts';
|
|
2
2
|
import { providerEnvVar } from './env.ts';
|
|
3
|
+
import { getCachedProviderCatalogEntry } from './model-catalog-cache.ts';
|
|
3
4
|
import { getUnderlyingProviderKey, providerIds } from './utils.ts';
|
|
4
5
|
import type {
|
|
5
6
|
BuiltInProviderId,
|
|
@@ -127,17 +128,21 @@ export function getProviderDefinition(
|
|
|
127
128
|
if (isBuiltInProviderId(provider)) {
|
|
128
129
|
const entry = catalog[provider];
|
|
129
130
|
if (!entry) return undefined;
|
|
131
|
+
const cachedEntry = getCachedProviderCatalogEntry(provider);
|
|
132
|
+
const models = cachedEntry?.models.length
|
|
133
|
+
? cachedEntry.models
|
|
134
|
+
: entry.models;
|
|
130
135
|
return {
|
|
131
136
|
id: provider,
|
|
132
|
-
label: settings?.label ?? entry.label ?? provider,
|
|
137
|
+
label: settings?.label ?? cachedEntry?.label ?? entry.label ?? provider,
|
|
133
138
|
source: 'built-in',
|
|
134
139
|
compatibility: BUILTIN_COMPATIBILITY[provider],
|
|
135
140
|
family: BUILTIN_FAMILY[provider],
|
|
136
|
-
baseURL: normalizeOptionalText(settings?.baseURL),
|
|
141
|
+
baseURL: normalizeOptionalText(settings?.baseURL) ?? entry.api,
|
|
137
142
|
apiKey: normalizeOptionalText(settings?.apiKey),
|
|
138
143
|
apiKeyEnv:
|
|
139
144
|
normalizeOptionalText(settings?.apiKeyEnv) ?? providerEnvVar(provider),
|
|
140
|
-
models
|
|
145
|
+
models,
|
|
141
146
|
allowAnyModel: provider === 'ollama-cloud',
|
|
142
147
|
};
|
|
143
148
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { catalog } from './catalog-merged.ts';
|
|
2
|
+
import { getCachedProviderCatalogEntry } from './model-catalog-cache.ts';
|
|
2
3
|
import type {
|
|
3
4
|
BuiltInProviderId,
|
|
4
5
|
ProviderId,
|
|
@@ -17,11 +18,11 @@ export function isProviderId(value: unknown): value is BuiltInProviderId {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export function defaultModelFor(provider: ProviderId): string | undefined {
|
|
20
|
-
return
|
|
21
|
+
return getProviderModels(provider)[0]?.id;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export function listModels(provider: ProviderId): string[] {
|
|
24
|
-
return (
|
|
25
|
+
return getProviderModels(provider).map((m) => m.id);
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export function hasModel(
|
|
@@ -49,7 +50,7 @@ const PREFERRED_FAST_MODELS_OAUTH: Partial<Record<ProviderId, string[]>> = {
|
|
|
49
50
|
};
|
|
50
51
|
|
|
51
52
|
export function getFastModel(provider: ProviderId): string | undefined {
|
|
52
|
-
const providerModels =
|
|
53
|
+
const providerModels = getProviderModels(provider);
|
|
53
54
|
if (!providerModels.length) return undefined;
|
|
54
55
|
|
|
55
56
|
const preferred = PREFERRED_FAST_MODELS[provider] ?? [];
|
|
@@ -70,7 +71,7 @@ export function getFastModelForAuth(
|
|
|
70
71
|
provider: ProviderId,
|
|
71
72
|
authType: 'api' | 'oauth' | 'wallet' | undefined,
|
|
72
73
|
): string | undefined {
|
|
73
|
-
const providerModels =
|
|
74
|
+
const providerModels = getProviderModels(provider);
|
|
74
75
|
if (!providerModels.length) return undefined;
|
|
75
76
|
|
|
76
77
|
const filteredModels = filterModelsForAuthType(
|
|
@@ -106,13 +107,13 @@ export function getModelNpmBinding(
|
|
|
106
107
|
model: string,
|
|
107
108
|
): string | undefined {
|
|
108
109
|
const entry = catalog[provider];
|
|
109
|
-
const modelInfo =
|
|
110
|
+
const modelInfo = getProviderModels(provider).find((m) => m.id === model);
|
|
110
111
|
if (modelInfo?.provider?.npm) return modelInfo.provider.npm;
|
|
111
112
|
if (entry?.npm) return entry.npm;
|
|
112
113
|
|
|
113
114
|
for (const key of Object.keys(catalog) as ProviderId[]) {
|
|
114
115
|
const e = catalog[key];
|
|
115
|
-
const m =
|
|
116
|
+
const m = getProviderModels(key).find((x) => x.id === model);
|
|
116
117
|
if (m?.provider?.npm) return m.provider.npm;
|
|
117
118
|
if (m && e?.npm) return e.npm;
|
|
118
119
|
}
|
|
@@ -234,7 +235,15 @@ export function getModelInfo(
|
|
|
234
235
|
): ModelInfo | undefined {
|
|
235
236
|
const entry = catalog[provider];
|
|
236
237
|
if (!entry) return undefined;
|
|
237
|
-
return
|
|
238
|
+
return getProviderModels(provider).find((m) => m.id === model);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function getProviderModels(provider: ProviderId): ModelInfo[] {
|
|
242
|
+
return (
|
|
243
|
+
getCachedProviderCatalogEntry(provider)?.models ??
|
|
244
|
+
catalog[provider]?.models ??
|
|
245
|
+
[]
|
|
246
|
+
);
|
|
238
247
|
}
|
|
239
248
|
|
|
240
249
|
export function modelSupportsReasoning(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { catalog } from './catalog-merged.ts';
|
|
2
|
+
import { getCachedProviderCatalogEntry } from './model-catalog-cache.ts';
|
|
2
3
|
import type { OttoConfig, ProviderId } from '../../types/src/index.ts';
|
|
3
4
|
import {
|
|
4
5
|
getProviderDefinition,
|
|
@@ -51,14 +52,15 @@ export function validateProviderModel(
|
|
|
51
52
|
if (!catalog[p]) {
|
|
52
53
|
throw new Error(`Provider not supported: ${provider}`);
|
|
53
54
|
}
|
|
54
|
-
const
|
|
55
|
+
const models = getCachedProviderCatalogEntry(p)?.models ?? catalog[p].models;
|
|
56
|
+
const entry = models.find((m) => m.id === model);
|
|
55
57
|
if (!entry) {
|
|
56
|
-
const list =
|
|
58
|
+
const list = models
|
|
57
59
|
.slice(0, 10)
|
|
58
60
|
.map((m) => m.id)
|
|
59
61
|
.join(', ');
|
|
60
62
|
throw new Error(
|
|
61
|
-
`Model not found for provider ${provider}: ${model}. Example models: ${list}${
|
|
63
|
+
`Model not found for provider ${provider}: ${model}. Example models: ${list}${models.length > 10 ? ', ...' : ''}`,
|
|
62
64
|
);
|
|
63
65
|
}
|
|
64
66
|
applyCapabilityValidation(model, entry, effectiveCap, { strict: true });
|