@ottocode/sdk 0.1.230 → 0.1.232
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/index.ts +1 -0
- package/src/core/src/index.ts +6 -0
- package/src/core/src/mcp/copilot-auth.ts +104 -0
- package/src/core/src/mcp/index.ts +9 -0
- package/src/core/src/mcp/server-manager.ts +44 -75
- package/src/index.ts +6 -0
- package/src/providers/src/catalog-manual.ts +1 -0
- package/src/providers/src/catalog.ts +249 -5
- package/src/providers/src/openrouter-client.ts +1 -0
- package/src/providers/src/utils.ts +1 -0
- package/src/types/src/config.ts +1 -0
- package/src/types/src/provider.ts +1 -0
package/package.json
CHANGED
package/src/config/src/index.ts
CHANGED
package/src/core/src/index.ts
CHANGED
|
@@ -115,9 +115,15 @@ export { isDebugEnabled, isTraceEnabled } from './utils/debug.ts';
|
|
|
115
115
|
export {
|
|
116
116
|
MCPClientWrapper,
|
|
117
117
|
MCPServerManager,
|
|
118
|
+
COPILOT_MCP_SCOPE,
|
|
118
119
|
convertMCPToolsToAISDK,
|
|
120
|
+
getCopilotMCPOAuthKey,
|
|
121
|
+
getStoredCopilotMCPToken,
|
|
119
122
|
getMCPManager,
|
|
123
|
+
hasCopilotMCPScopes,
|
|
120
124
|
initializeMCP,
|
|
125
|
+
isGitHubCopilotUrl,
|
|
126
|
+
isStoredCopilotMCPAuthenticated,
|
|
121
127
|
shutdownMCP,
|
|
122
128
|
loadMCPConfig,
|
|
123
129
|
addMCPServerToConfig,
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import type { MCPScope } from './types.ts';
|
|
3
|
+
import type { OAuthCredentialStore } from './oauth/store.ts';
|
|
4
|
+
|
|
5
|
+
export const GITHUB_COPILOT_HOSTS = [
|
|
6
|
+
'api.githubcopilot.com',
|
|
7
|
+
'copilot-proxy.githubusercontent.com',
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
export const COPILOT_MCP_REQUIRED_SCOPES = [
|
|
11
|
+
'repo',
|
|
12
|
+
'read:org',
|
|
13
|
+
'gist',
|
|
14
|
+
'notifications',
|
|
15
|
+
'read:project',
|
|
16
|
+
'security_events',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export const COPILOT_MCP_SCOPE =
|
|
20
|
+
'repo read:org read:packages gist notifications read:project security_events';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns whether a URL points at a GitHub Copilot-backed MCP endpoint.
|
|
24
|
+
*/
|
|
25
|
+
export function isGitHubCopilotUrl(url?: string): boolean {
|
|
26
|
+
if (!url) return false;
|
|
27
|
+
try {
|
|
28
|
+
const parsed = new URL(url);
|
|
29
|
+
return GITHUB_COPILOT_HOSTS.some(
|
|
30
|
+
(host) =>
|
|
31
|
+
parsed.hostname === host || parsed.hostname.endsWith(`.${host}`),
|
|
32
|
+
);
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns whether the stored scope string satisfies the GitHub Copilot MCP requirements.
|
|
40
|
+
*/
|
|
41
|
+
export function hasCopilotMCPScopes(scopes?: string): boolean {
|
|
42
|
+
if (!scopes) return false;
|
|
43
|
+
const granted = scopes.split(/[\s,]+/).filter(Boolean);
|
|
44
|
+
return COPILOT_MCP_REQUIRED_SCOPES.every((scope) => granted.includes(scope));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Builds the MCP OAuth store key for a GitHub Copilot MCP server.
|
|
49
|
+
*/
|
|
50
|
+
export function getCopilotMCPOAuthKey(
|
|
51
|
+
serverName: string,
|
|
52
|
+
scope: MCPScope = 'global',
|
|
53
|
+
projectRoot?: string,
|
|
54
|
+
): string {
|
|
55
|
+
if (scope === 'project' && projectRoot) {
|
|
56
|
+
const hash = createHash('sha256')
|
|
57
|
+
.update(projectRoot)
|
|
58
|
+
.digest('hex')
|
|
59
|
+
.slice(0, 8);
|
|
60
|
+
return `${serverName}_proj_${hash}`;
|
|
61
|
+
}
|
|
62
|
+
return serverName;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Loads the stored GitHub Copilot MCP bearer token for a server.
|
|
67
|
+
*/
|
|
68
|
+
export async function getStoredCopilotMCPToken(
|
|
69
|
+
store: OAuthCredentialStore,
|
|
70
|
+
serverName: string,
|
|
71
|
+
scope: MCPScope = 'global',
|
|
72
|
+
projectRoot?: string,
|
|
73
|
+
): Promise<{ token: string | null; needsReauth: boolean; scopes?: string }> {
|
|
74
|
+
const tokens = await store.loadTokens(
|
|
75
|
+
getCopilotMCPOAuthKey(serverName, scope, projectRoot),
|
|
76
|
+
);
|
|
77
|
+
const token = tokens?.access_token ?? null;
|
|
78
|
+
if (!token) {
|
|
79
|
+
return { token: null, needsReauth: true };
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
token,
|
|
83
|
+
needsReauth: !hasCopilotMCPScopes(tokens?.scope),
|
|
84
|
+
scopes: tokens?.scope,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Returns whether the stored GitHub Copilot MCP credentials are usable.
|
|
90
|
+
*/
|
|
91
|
+
export async function isStoredCopilotMCPAuthenticated(
|
|
92
|
+
store: OAuthCredentialStore,
|
|
93
|
+
serverName: string,
|
|
94
|
+
scope: MCPScope = 'global',
|
|
95
|
+
projectRoot?: string,
|
|
96
|
+
): Promise<boolean> {
|
|
97
|
+
const { token, needsReauth } = await getStoredCopilotMCPToken(
|
|
98
|
+
store,
|
|
99
|
+
serverName,
|
|
100
|
+
scope,
|
|
101
|
+
projectRoot,
|
|
102
|
+
);
|
|
103
|
+
return !!token && !needsReauth;
|
|
104
|
+
}
|
|
@@ -13,6 +13,15 @@ export { MCPServerManager } from './server-manager.ts';
|
|
|
13
13
|
|
|
14
14
|
export { convertMCPToolsToAISDK } from './tools.ts';
|
|
15
15
|
|
|
16
|
+
export {
|
|
17
|
+
COPILOT_MCP_SCOPE,
|
|
18
|
+
getCopilotMCPOAuthKey,
|
|
19
|
+
getStoredCopilotMCPToken,
|
|
20
|
+
hasCopilotMCPScopes,
|
|
21
|
+
isGitHubCopilotUrl,
|
|
22
|
+
isStoredCopilotMCPAuthenticated,
|
|
23
|
+
} from './copilot-auth.ts';
|
|
24
|
+
|
|
16
25
|
export {
|
|
17
26
|
getMCPToolBriefs,
|
|
18
27
|
buildLoadMCPToolsTool,
|
|
@@ -2,66 +2,12 @@ import { MCPClientWrapper, type MCPToolInfo } from './client.ts';
|
|
|
2
2
|
import type { MCPServerConfig, MCPServerStatus } from './types.ts';
|
|
3
3
|
import { OAuthCredentialStore } from './oauth/store.ts';
|
|
4
4
|
import { OttoOAuthProvider } from './oauth/provider.ts';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
];
|
|
12
|
-
|
|
13
|
-
function isGitHubCopilotUrl(url?: string): boolean {
|
|
14
|
-
if (!url) return false;
|
|
15
|
-
try {
|
|
16
|
-
const parsed = new URL(url);
|
|
17
|
-
return GITHUB_COPILOT_HOSTS.some(
|
|
18
|
-
(h) => parsed.hostname === h || parsed.hostname.endsWith(`.${h}`),
|
|
19
|
-
);
|
|
20
|
-
} catch {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const COPILOT_MCP_REQUIRED_SCOPES = [
|
|
26
|
-
'repo',
|
|
27
|
-
'read:org',
|
|
28
|
-
'gist',
|
|
29
|
-
'notifications',
|
|
30
|
-
'read:project',
|
|
31
|
-
'security_events',
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
function hasMCPScopes(scopes?: string): boolean {
|
|
35
|
-
if (!scopes) return false;
|
|
36
|
-
const granted = scopes.split(/[\s,]+/).filter(Boolean);
|
|
37
|
-
return COPILOT_MCP_REQUIRED_SCOPES.every((s) => granted.includes(s));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async function getCopilotToken(): Promise<string | null> {
|
|
41
|
-
try {
|
|
42
|
-
const auth = await getAuth('copilot');
|
|
43
|
-
if (auth?.type === 'oauth' && auth.refresh) {
|
|
44
|
-
return auth.refresh;
|
|
45
|
-
}
|
|
46
|
-
} catch {}
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async function getCopilotMCPToken(): Promise<{
|
|
51
|
-
token: string | null;
|
|
52
|
-
needsReauth: boolean;
|
|
53
|
-
}> {
|
|
54
|
-
try {
|
|
55
|
-
const auth = await getAuth('copilot');
|
|
56
|
-
if (auth?.type === 'oauth' && auth.refresh) {
|
|
57
|
-
if (!hasMCPScopes(auth.scopes)) {
|
|
58
|
-
return { token: auth.refresh, needsReauth: true };
|
|
59
|
-
}
|
|
60
|
-
return { token: auth.refresh, needsReauth: false };
|
|
61
|
-
}
|
|
62
|
-
} catch {}
|
|
63
|
-
return { token: null, needsReauth: true };
|
|
64
|
-
}
|
|
5
|
+
import {
|
|
6
|
+
getCopilotMCPOAuthKey,
|
|
7
|
+
getStoredCopilotMCPToken,
|
|
8
|
+
isGitHubCopilotUrl,
|
|
9
|
+
isStoredCopilotMCPAuthenticated,
|
|
10
|
+
} from './copilot-auth.ts';
|
|
65
11
|
|
|
66
12
|
type IndexedTool = {
|
|
67
13
|
server: string;
|
|
@@ -88,14 +34,11 @@ export class MCPServerManager {
|
|
|
88
34
|
|
|
89
35
|
private oauthKey(serverName: string): string {
|
|
90
36
|
const scope = this.serverScopes.get(serverName);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
return `${serverName}_proj_${hash}`;
|
|
97
|
-
}
|
|
98
|
-
return serverName;
|
|
37
|
+
return getCopilotMCPOAuthKey(
|
|
38
|
+
serverName,
|
|
39
|
+
scope,
|
|
40
|
+
this.projectRoot ?? undefined,
|
|
41
|
+
);
|
|
99
42
|
}
|
|
100
43
|
|
|
101
44
|
async startServers(configs: MCPServerConfig[]): Promise<void> {
|
|
@@ -115,7 +58,12 @@ export class MCPServerManager {
|
|
|
115
58
|
|
|
116
59
|
if (transport !== 'stdio') {
|
|
117
60
|
if (isGitHubCopilotUrl(config.url)) {
|
|
118
|
-
const { token, needsReauth } = await
|
|
61
|
+
const { token, needsReauth } = await getStoredCopilotMCPToken(
|
|
62
|
+
this.oauthStore,
|
|
63
|
+
config.name,
|
|
64
|
+
config.scope ?? 'global',
|
|
65
|
+
this.projectRoot ?? undefined,
|
|
66
|
+
);
|
|
119
67
|
if (token && !needsReauth) {
|
|
120
68
|
config = {
|
|
121
69
|
...config,
|
|
@@ -159,7 +107,7 @@ export class MCPServerManager {
|
|
|
159
107
|
return;
|
|
160
108
|
}
|
|
161
109
|
console.error(
|
|
162
|
-
`[mcp] GitHub Copilot MCP server "${config.name}" requires authentication. Run \`otto
|
|
110
|
+
`[mcp] GitHub Copilot MCP server "${config.name}" requires authentication. Run \`otto mcp auth ${config.name}\`.`,
|
|
163
111
|
);
|
|
164
112
|
this.clients.set(config.name, client);
|
|
165
113
|
return;
|
|
@@ -296,7 +244,12 @@ export class MCPServerManager {
|
|
|
296
244
|
const config = client.serverConfig;
|
|
297
245
|
let authenticated = false;
|
|
298
246
|
if (isGitHubCopilotUrl(config.url)) {
|
|
299
|
-
authenticated =
|
|
247
|
+
authenticated = await isStoredCopilotMCPAuthenticated(
|
|
248
|
+
this.oauthStore,
|
|
249
|
+
name,
|
|
250
|
+
config.scope ?? 'global',
|
|
251
|
+
this.projectRoot ?? undefined,
|
|
252
|
+
).catch(() => false);
|
|
300
253
|
} else {
|
|
301
254
|
const key = this.oauthKey(name);
|
|
302
255
|
authenticated = await this.oauthStore
|
|
@@ -334,8 +287,13 @@ export class MCPServerManager {
|
|
|
334
287
|
if (transport === 'stdio') return null;
|
|
335
288
|
|
|
336
289
|
if (isGitHubCopilotUrl(config.url)) {
|
|
337
|
-
const token = await
|
|
338
|
-
|
|
290
|
+
const { token, needsReauth } = await getStoredCopilotMCPToken(
|
|
291
|
+
this.oauthStore,
|
|
292
|
+
config.name,
|
|
293
|
+
config.scope ?? 'global',
|
|
294
|
+
this.projectRoot ?? undefined,
|
|
295
|
+
);
|
|
296
|
+
if (token && !needsReauth) {
|
|
339
297
|
const authedConfig = {
|
|
340
298
|
...config,
|
|
341
299
|
headers: {
|
|
@@ -472,8 +430,19 @@ export class MCPServerManager {
|
|
|
472
430
|
): Promise<{ authenticated: boolean; expiresAt?: number }> {
|
|
473
431
|
const client = this.clients.get(name);
|
|
474
432
|
if (client && isGitHubCopilotUrl(client.serverConfig.url)) {
|
|
475
|
-
const
|
|
476
|
-
|
|
433
|
+
const key = this.oauthKey(name);
|
|
434
|
+
const tokens = await this.oauthStore.loadTokens(key);
|
|
435
|
+
return {
|
|
436
|
+
authenticated:
|
|
437
|
+
!!tokens?.access_token &&
|
|
438
|
+
(await isStoredCopilotMCPAuthenticated(
|
|
439
|
+
this.oauthStore,
|
|
440
|
+
name,
|
|
441
|
+
client.serverConfig.scope ?? 'global',
|
|
442
|
+
this.projectRoot ?? undefined,
|
|
443
|
+
)),
|
|
444
|
+
expiresAt: tokens?.expires_at,
|
|
445
|
+
};
|
|
477
446
|
}
|
|
478
447
|
const key = this.oauthKey(name);
|
|
479
448
|
const tokens = await this.oauthStore.loadTokens(key);
|
package/src/index.ts
CHANGED
|
@@ -362,9 +362,15 @@ export type { TunnelConnection, TunnelEvents } from './tunnel/index.ts';
|
|
|
362
362
|
export {
|
|
363
363
|
MCPClientWrapper,
|
|
364
364
|
MCPServerManager,
|
|
365
|
+
COPILOT_MCP_SCOPE,
|
|
365
366
|
convertMCPToolsToAISDK,
|
|
367
|
+
getCopilotMCPOAuthKey,
|
|
368
|
+
getStoredCopilotMCPToken,
|
|
366
369
|
getMCPManager,
|
|
370
|
+
hasCopilotMCPScopes,
|
|
367
371
|
initializeMCP,
|
|
372
|
+
isGitHubCopilotUrl,
|
|
373
|
+
isStoredCopilotMCPAuthenticated,
|
|
368
374
|
shutdownMCP,
|
|
369
375
|
loadMCPConfig,
|
|
370
376
|
addMCPServerToConfig,
|
|
@@ -14,6 +14,7 @@ const OWNER_NPM: Record<ModelOwner, string> = {
|
|
|
14
14
|
openai: '@ai-sdk/openai',
|
|
15
15
|
anthropic: '@ai-sdk/anthropic',
|
|
16
16
|
google: '@ai-sdk/google',
|
|
17
|
+
openrouter: '@openrouter/ai-sdk-provider',
|
|
17
18
|
xai: '@ai-sdk/xai',
|
|
18
19
|
moonshot: '@ai-sdk/openai-compatible',
|
|
19
20
|
zai: '@ai-sdk/openai-compatible',
|
|
@@ -762,7 +762,7 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
762
762
|
ownedBy: 'openai',
|
|
763
763
|
label: 'GPT-5.4',
|
|
764
764
|
modalities: {
|
|
765
|
-
input: ['text', 'image'],
|
|
765
|
+
input: ['text', 'image', 'pdf'],
|
|
766
766
|
output: ['text'],
|
|
767
767
|
},
|
|
768
768
|
toolCall: true,
|
|
@@ -2323,6 +2323,57 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
2323
2323
|
output: 64000,
|
|
2324
2324
|
},
|
|
2325
2325
|
},
|
|
2326
|
+
{
|
|
2327
|
+
id: 'gemini-3.1-flash-image-preview',
|
|
2328
|
+
ownedBy: 'google',
|
|
2329
|
+
label: 'Gemini 3.1 Flash Image (Preview)',
|
|
2330
|
+
modalities: {
|
|
2331
|
+
input: ['text', 'image', 'pdf'],
|
|
2332
|
+
output: ['text', 'image'],
|
|
2333
|
+
},
|
|
2334
|
+
toolCall: false,
|
|
2335
|
+
reasoningText: true,
|
|
2336
|
+
attachment: true,
|
|
2337
|
+
temperature: true,
|
|
2338
|
+
knowledge: '2025-01',
|
|
2339
|
+
releaseDate: '2026-02-26',
|
|
2340
|
+
lastUpdated: '2026-02-26',
|
|
2341
|
+
openWeights: false,
|
|
2342
|
+
cost: {
|
|
2343
|
+
input: 0.25,
|
|
2344
|
+
output: 60,
|
|
2345
|
+
},
|
|
2346
|
+
limit: {
|
|
2347
|
+
context: 131072,
|
|
2348
|
+
output: 32768,
|
|
2349
|
+
},
|
|
2350
|
+
},
|
|
2351
|
+
{
|
|
2352
|
+
id: 'gemini-3.1-flash-lite-preview',
|
|
2353
|
+
ownedBy: 'google',
|
|
2354
|
+
label: 'Gemini 3.1 Flash Lite Preview',
|
|
2355
|
+
modalities: {
|
|
2356
|
+
input: ['text', 'image', 'video', 'audio', 'pdf'],
|
|
2357
|
+
output: ['text'],
|
|
2358
|
+
},
|
|
2359
|
+
toolCall: true,
|
|
2360
|
+
reasoningText: true,
|
|
2361
|
+
attachment: true,
|
|
2362
|
+
temperature: true,
|
|
2363
|
+
knowledge: '2025-01',
|
|
2364
|
+
releaseDate: '2026-03-03',
|
|
2365
|
+
lastUpdated: '2026-03-03',
|
|
2366
|
+
openWeights: false,
|
|
2367
|
+
cost: {
|
|
2368
|
+
input: 0.5,
|
|
2369
|
+
output: 3,
|
|
2370
|
+
cacheRead: 0.05,
|
|
2371
|
+
},
|
|
2372
|
+
limit: {
|
|
2373
|
+
context: 1048576,
|
|
2374
|
+
output: 65536,
|
|
2375
|
+
},
|
|
2376
|
+
},
|
|
2326
2377
|
{
|
|
2327
2378
|
id: 'gemini-3.1-pro-preview',
|
|
2328
2379
|
ownedBy: 'google',
|
|
@@ -3940,6 +3991,78 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
3940
3991
|
output: 2000,
|
|
3941
3992
|
},
|
|
3942
3993
|
},
|
|
3994
|
+
{
|
|
3995
|
+
id: 'inception/mercury',
|
|
3996
|
+
label: 'Mercury',
|
|
3997
|
+
modalities: {
|
|
3998
|
+
input: ['text'],
|
|
3999
|
+
output: ['text'],
|
|
4000
|
+
},
|
|
4001
|
+
toolCall: true,
|
|
4002
|
+
reasoningText: false,
|
|
4003
|
+
attachment: false,
|
|
4004
|
+
temperature: true,
|
|
4005
|
+
releaseDate: '2025-06-26',
|
|
4006
|
+
lastUpdated: '2025-06-26',
|
|
4007
|
+
openWeights: false,
|
|
4008
|
+
cost: {
|
|
4009
|
+
input: 0.25,
|
|
4010
|
+
output: 0.75,
|
|
4011
|
+
cacheRead: 0.025,
|
|
4012
|
+
},
|
|
4013
|
+
limit: {
|
|
4014
|
+
context: 128000,
|
|
4015
|
+
output: 32000,
|
|
4016
|
+
},
|
|
4017
|
+
},
|
|
4018
|
+
{
|
|
4019
|
+
id: 'inception/mercury-2',
|
|
4020
|
+
label: 'Mercury 2',
|
|
4021
|
+
modalities: {
|
|
4022
|
+
input: ['text'],
|
|
4023
|
+
output: ['text'],
|
|
4024
|
+
},
|
|
4025
|
+
toolCall: true,
|
|
4026
|
+
reasoningText: true,
|
|
4027
|
+
attachment: false,
|
|
4028
|
+
temperature: true,
|
|
4029
|
+
releaseDate: '2026-03-04',
|
|
4030
|
+
lastUpdated: '2026-03-04',
|
|
4031
|
+
openWeights: false,
|
|
4032
|
+
cost: {
|
|
4033
|
+
input: 0.25,
|
|
4034
|
+
output: 0.75,
|
|
4035
|
+
cacheRead: 0.025,
|
|
4036
|
+
},
|
|
4037
|
+
limit: {
|
|
4038
|
+
context: 128000,
|
|
4039
|
+
output: 50000,
|
|
4040
|
+
},
|
|
4041
|
+
},
|
|
4042
|
+
{
|
|
4043
|
+
id: 'inception/mercury-coder',
|
|
4044
|
+
label: 'Mercury Coder',
|
|
4045
|
+
modalities: {
|
|
4046
|
+
input: ['text'],
|
|
4047
|
+
output: ['text'],
|
|
4048
|
+
},
|
|
4049
|
+
toolCall: true,
|
|
4050
|
+
reasoningText: false,
|
|
4051
|
+
attachment: false,
|
|
4052
|
+
temperature: true,
|
|
4053
|
+
releaseDate: '2025-04-30',
|
|
4054
|
+
lastUpdated: '2025-04-30',
|
|
4055
|
+
openWeights: false,
|
|
4056
|
+
cost: {
|
|
4057
|
+
input: 0.25,
|
|
4058
|
+
output: 0.75,
|
|
4059
|
+
cacheRead: 0.025,
|
|
4060
|
+
},
|
|
4061
|
+
limit: {
|
|
4062
|
+
context: 128000,
|
|
4063
|
+
output: 32000,
|
|
4064
|
+
},
|
|
4065
|
+
},
|
|
3943
4066
|
{
|
|
3944
4067
|
id: 'kwaipilot/kat-coder-pro:free',
|
|
3945
4068
|
label: 'Kat Coder Pro (free)',
|
|
@@ -5743,6 +5866,77 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
5743
5866
|
output: 50000,
|
|
5744
5867
|
},
|
|
5745
5868
|
},
|
|
5869
|
+
{
|
|
5870
|
+
id: 'openrouter/free',
|
|
5871
|
+
label: 'Free Models Router',
|
|
5872
|
+
modalities: {
|
|
5873
|
+
input: ['text', 'image'],
|
|
5874
|
+
output: ['text'],
|
|
5875
|
+
},
|
|
5876
|
+
toolCall: true,
|
|
5877
|
+
reasoningText: true,
|
|
5878
|
+
attachment: true,
|
|
5879
|
+
temperature: true,
|
|
5880
|
+
releaseDate: '2026-02-01',
|
|
5881
|
+
lastUpdated: '2026-02-01',
|
|
5882
|
+
openWeights: false,
|
|
5883
|
+
cost: {
|
|
5884
|
+
input: 0,
|
|
5885
|
+
output: 0,
|
|
5886
|
+
},
|
|
5887
|
+
limit: {
|
|
5888
|
+
context: 200000,
|
|
5889
|
+
output: 8000,
|
|
5890
|
+
},
|
|
5891
|
+
},
|
|
5892
|
+
{
|
|
5893
|
+
id: 'openrouter/healer-alpha',
|
|
5894
|
+
label: 'Healer Alpha',
|
|
5895
|
+
modalities: {
|
|
5896
|
+
input: ['text', 'image', 'audio', 'pdf'],
|
|
5897
|
+
output: ['text'],
|
|
5898
|
+
},
|
|
5899
|
+
toolCall: true,
|
|
5900
|
+
reasoningText: true,
|
|
5901
|
+
attachment: true,
|
|
5902
|
+
temperature: true,
|
|
5903
|
+
knowledge: '2026-03-11',
|
|
5904
|
+
releaseDate: '2026-03-11',
|
|
5905
|
+
lastUpdated: '2026-03-11',
|
|
5906
|
+
openWeights: false,
|
|
5907
|
+
cost: {
|
|
5908
|
+
input: 0,
|
|
5909
|
+
output: 0,
|
|
5910
|
+
},
|
|
5911
|
+
limit: {
|
|
5912
|
+
context: 262144,
|
|
5913
|
+
output: 64000,
|
|
5914
|
+
},
|
|
5915
|
+
},
|
|
5916
|
+
{
|
|
5917
|
+
id: 'openrouter/hunter-alpha',
|
|
5918
|
+
label: 'Hunter Alpha',
|
|
5919
|
+
modalities: {
|
|
5920
|
+
input: ['text', 'image', 'pdf'],
|
|
5921
|
+
output: ['text'],
|
|
5922
|
+
},
|
|
5923
|
+
toolCall: true,
|
|
5924
|
+
reasoningText: true,
|
|
5925
|
+
attachment: true,
|
|
5926
|
+
temperature: true,
|
|
5927
|
+
knowledge: '2026-03-11',
|
|
5928
|
+
releaseDate: '2026-03-11',
|
|
5929
|
+
lastUpdated: '2026-03-11',
|
|
5930
|
+
openWeights: false,
|
|
5931
|
+
cost: {
|
|
5932
|
+
input: 0,
|
|
5933
|
+
output: 0,
|
|
5934
|
+
},
|
|
5935
|
+
limit: {
|
|
5936
|
+
context: 1048576,
|
|
5937
|
+
output: 64000,
|
|
5938
|
+
},
|
|
5939
|
+
},
|
|
5746
5940
|
{
|
|
5747
5941
|
id: 'openrouter/sherlock-dash-alpha',
|
|
5748
5942
|
label: 'Sherlock Dash Alpha',
|
|
@@ -8199,6 +8393,31 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
8199
8393
|
output: 262144,
|
|
8200
8394
|
},
|
|
8201
8395
|
},
|
|
8396
|
+
{
|
|
8397
|
+
id: 'mimo-v2-flash-free',
|
|
8398
|
+
label: 'MiMo V2 Flash Free',
|
|
8399
|
+
modalities: {
|
|
8400
|
+
input: ['text'],
|
|
8401
|
+
output: ['text'],
|
|
8402
|
+
},
|
|
8403
|
+
toolCall: true,
|
|
8404
|
+
reasoningText: true,
|
|
8405
|
+
attachment: false,
|
|
8406
|
+
temperature: true,
|
|
8407
|
+
knowledge: '2024-12',
|
|
8408
|
+
releaseDate: '2025-12-16',
|
|
8409
|
+
lastUpdated: '2025-12-16',
|
|
8410
|
+
openWeights: true,
|
|
8411
|
+
cost: {
|
|
8412
|
+
input: 0,
|
|
8413
|
+
output: 0,
|
|
8414
|
+
cacheRead: 0,
|
|
8415
|
+
},
|
|
8416
|
+
limit: {
|
|
8417
|
+
context: 262144,
|
|
8418
|
+
output: 65536,
|
|
8419
|
+
},
|
|
8420
|
+
},
|
|
8202
8421
|
{
|
|
8203
8422
|
id: 'minimax-m2.1',
|
|
8204
8423
|
ownedBy: 'minimax',
|
|
@@ -8309,6 +8528,31 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
8309
8528
|
npm: '@ai-sdk/anthropic',
|
|
8310
8529
|
},
|
|
8311
8530
|
},
|
|
8531
|
+
{
|
|
8532
|
+
id: 'nemotron-3-super-free',
|
|
8533
|
+
label: 'Nemotron 3 Super Free',
|
|
8534
|
+
modalities: {
|
|
8535
|
+
input: ['text'],
|
|
8536
|
+
output: ['text'],
|
|
8537
|
+
},
|
|
8538
|
+
toolCall: true,
|
|
8539
|
+
reasoningText: true,
|
|
8540
|
+
attachment: false,
|
|
8541
|
+
temperature: true,
|
|
8542
|
+
knowledge: '2026-02',
|
|
8543
|
+
releaseDate: '2026-03-11',
|
|
8544
|
+
lastUpdated: '2026-03-11',
|
|
8545
|
+
openWeights: true,
|
|
8546
|
+
cost: {
|
|
8547
|
+
input: 0,
|
|
8548
|
+
output: 0,
|
|
8549
|
+
cacheRead: 0,
|
|
8550
|
+
},
|
|
8551
|
+
limit: {
|
|
8552
|
+
context: 1000000,
|
|
8553
|
+
output: 128000,
|
|
8554
|
+
},
|
|
8555
|
+
},
|
|
8312
8556
|
{
|
|
8313
8557
|
id: 'qwen3-coder',
|
|
8314
8558
|
label: 'Qwen3 Coder',
|
|
@@ -8593,7 +8837,7 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
8593
8837
|
temperature: true,
|
|
8594
8838
|
releaseDate: '2026-02-11',
|
|
8595
8839
|
lastUpdated: '2026-02-11',
|
|
8596
|
-
openWeights:
|
|
8840
|
+
openWeights: true,
|
|
8597
8841
|
cost: {
|
|
8598
8842
|
input: 1,
|
|
8599
8843
|
output: 3.2,
|
|
@@ -8868,7 +9112,7 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
8868
9112
|
temperature: true,
|
|
8869
9113
|
releaseDate: '2026-02-11',
|
|
8870
9114
|
lastUpdated: '2026-02-11',
|
|
8871
|
-
openWeights:
|
|
9115
|
+
openWeights: true,
|
|
8872
9116
|
cost: {
|
|
8873
9117
|
input: 0,
|
|
8874
9118
|
output: 0,
|
|
@@ -9661,7 +9905,7 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
9661
9905
|
output: 0,
|
|
9662
9906
|
},
|
|
9663
9907
|
limit: {
|
|
9664
|
-
context:
|
|
9908
|
+
context: 264000,
|
|
9665
9909
|
output: 64000,
|
|
9666
9910
|
},
|
|
9667
9911
|
},
|
|
@@ -9686,7 +9930,7 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
9686
9930
|
output: 0,
|
|
9687
9931
|
},
|
|
9688
9932
|
limit: {
|
|
9689
|
-
context:
|
|
9933
|
+
context: 400000,
|
|
9690
9934
|
output: 128000,
|
|
9691
9935
|
},
|
|
9692
9936
|
},
|
package/src/types/src/config.ts
CHANGED