@ottocode/sdk 0.1.201 → 0.1.203
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 +16 -14
- package/src/core/src/index.ts +1 -0
- package/src/core/src/mcp/index.ts +1 -0
- package/src/core/src/mcp/lifecycle.ts +58 -24
- package/src/core/src/mcp/oauth/store.ts +2 -8
- package/src/core/src/mcp/server-manager.ts +33 -5
- package/src/core/src/mcp/types.ts +3 -0
- package/src/index.ts +5 -0
- package/src/providers/src/catalog-manual.ts +12 -0
- package/src/providers/src/catalog.ts +155 -0
- package/src/providers/src/env.ts +1 -0
- package/src/providers/src/index.ts +2 -0
- package/src/providers/src/minimax-client.ts +24 -0
- package/src/providers/src/utils.ts +6 -0
- package/src/types/src/provider.ts +3 -1
package/package.json
CHANGED
package/src/config/src/paths.ts
CHANGED
|
@@ -35,29 +35,31 @@ export function getGlobalAuthPath(): string {
|
|
|
35
35
|
return joinPath(getGlobalConfigDir(), 'auth.json');
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
// - Linux: $XDG_STATE_HOME/otto/auth.json or ~/.local/state/otto/auth.json
|
|
40
|
-
// - macOS: ~/Library/Application Support/otto/auth.json
|
|
41
|
-
// - Windows: %APPDATA%\otto\auth.json
|
|
42
|
-
export function getSecureAuthPath(): string {
|
|
38
|
+
export function getSecureBaseDir(): string {
|
|
43
39
|
const platform = process.platform;
|
|
44
40
|
if (platform === 'darwin') {
|
|
45
|
-
return joinPath(
|
|
46
|
-
getHomeDir(),
|
|
47
|
-
'Library',
|
|
48
|
-
'Application Support',
|
|
49
|
-
'otto',
|
|
50
|
-
'auth.json',
|
|
51
|
-
);
|
|
41
|
+
return joinPath(getHomeDir(), 'Library', 'Application Support', 'otto');
|
|
52
42
|
}
|
|
53
43
|
if (platform === 'win32') {
|
|
54
44
|
const appData = (process.env.APPDATA || '').replace(/\\/g, '/');
|
|
55
45
|
const base = appData || joinPath(getHomeDir(), 'AppData', 'Roaming');
|
|
56
|
-
return joinPath(base, 'otto'
|
|
46
|
+
return joinPath(base, 'otto');
|
|
57
47
|
}
|
|
58
48
|
const stateHome = (process.env.XDG_STATE_HOME || '').replace(/\\/g, '/');
|
|
59
49
|
const base = stateHome || joinPath(getHomeDir(), '.local', 'state');
|
|
60
|
-
return joinPath(base, 'otto'
|
|
50
|
+
return joinPath(base, 'otto');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function getSecureOAuthDir(): string {
|
|
54
|
+
return joinPath(getSecureBaseDir(), 'oauth');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Secure location for auth secrets (not in config dir or project)
|
|
58
|
+
// - Linux: $XDG_STATE_HOME/otto/auth.json or ~/.local/state/otto/auth.json
|
|
59
|
+
// - macOS: ~/Library/Application Support/otto/auth.json
|
|
60
|
+
// - Windows: %APPDATA%\otto\auth.json
|
|
61
|
+
export function getSecureAuthPath(): string {
|
|
62
|
+
return joinPath(getSecureBaseDir(), 'auth.json');
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
// Global content under config dir
|
package/src/core/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MCPServerManager } from './server-manager.ts';
|
|
2
|
-
import type { MCPConfig, MCPServerConfig } from './types.ts';
|
|
2
|
+
import type { MCPConfig, MCPServerConfig, MCPScope } from './types.ts';
|
|
3
3
|
import { promises as fs } from 'node:fs';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
|
|
@@ -11,11 +11,15 @@ export function getMCPManager(): MCPServerManager | null {
|
|
|
11
11
|
|
|
12
12
|
export async function initializeMCP(
|
|
13
13
|
config: MCPConfig,
|
|
14
|
+
projectRoot?: string,
|
|
14
15
|
): Promise<MCPServerManager> {
|
|
15
16
|
if (globalMCPManager) {
|
|
16
17
|
await globalMCPManager.stopAll();
|
|
17
18
|
}
|
|
18
19
|
globalMCPManager = new MCPServerManager();
|
|
20
|
+
if (projectRoot) {
|
|
21
|
+
globalMCPManager.setProjectRoot(projectRoot);
|
|
22
|
+
}
|
|
19
23
|
await globalMCPManager.startServers(config.servers);
|
|
20
24
|
return globalMCPManager;
|
|
21
25
|
}
|
|
@@ -41,7 +45,7 @@ export async function loadMCPConfig(
|
|
|
41
45
|
const globalServers = await readMCPServersFromFile(globalPath);
|
|
42
46
|
for (const s of globalServers) {
|
|
43
47
|
seen.add(s.name);
|
|
44
|
-
servers.push(s);
|
|
48
|
+
servers.push({ ...s, scope: 'global' });
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
|
|
@@ -50,9 +54,9 @@ export async function loadMCPConfig(
|
|
|
50
54
|
for (const s of projectServers) {
|
|
51
55
|
if (seen.has(s.name)) {
|
|
52
56
|
const idx = servers.findIndex((existing) => existing.name === s.name);
|
|
53
|
-
if (idx >= 0) servers[idx] = s;
|
|
57
|
+
if (idx >= 0) servers[idx] = { ...s, scope: 'project' };
|
|
54
58
|
} else {
|
|
55
|
-
servers.push(s);
|
|
59
|
+
servers.push({ ...s, scope: 'project' });
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
|
|
@@ -81,11 +85,30 @@ async function readMCPServersFromFile(
|
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
|
|
88
|
+
function resolveConfigPath(
|
|
89
|
+
projectRoot: string,
|
|
90
|
+
globalConfigDir: string | undefined,
|
|
91
|
+
scope: MCPScope,
|
|
92
|
+
): string {
|
|
93
|
+
if (scope === 'global' && globalConfigDir) {
|
|
94
|
+
return join(globalConfigDir, 'config.json');
|
|
95
|
+
}
|
|
96
|
+
return join(projectRoot, '.otto', 'config.json');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function ensureConfigDir(configPath: string): Promise<void> {
|
|
100
|
+
const dir = configPath.replace(/[/\\][^/\\]+$/, '');
|
|
101
|
+
await fs.mkdir(dir, { recursive: true });
|
|
102
|
+
}
|
|
103
|
+
|
|
84
104
|
export async function addMCPServerToConfig(
|
|
85
105
|
projectRoot: string,
|
|
86
106
|
server: MCPServerConfig,
|
|
107
|
+
globalConfigDir?: string,
|
|
87
108
|
): Promise<void> {
|
|
88
|
-
const
|
|
109
|
+
const scope: MCPScope = server.scope ?? 'global';
|
|
110
|
+
const configPath = resolveConfigPath(projectRoot, globalConfigDir, scope);
|
|
111
|
+
|
|
89
112
|
let json: Record<string, unknown> = {};
|
|
90
113
|
try {
|
|
91
114
|
const text = await fs.readFile(configPath, 'utf-8');
|
|
@@ -98,37 +121,48 @@ export async function addMCPServerToConfig(
|
|
|
98
121
|
|
|
99
122
|
const servers = mcp.servers as MCPServerConfig[];
|
|
100
123
|
const idx = servers.findIndex((s) => s.name === server.name);
|
|
124
|
+
|
|
125
|
+
const { scope: _scope, ...serverWithoutScope } = server;
|
|
101
126
|
if (idx >= 0) {
|
|
102
|
-
servers[idx] =
|
|
127
|
+
servers[idx] = serverWithoutScope;
|
|
103
128
|
} else {
|
|
104
|
-
servers.push(
|
|
129
|
+
servers.push(serverWithoutScope);
|
|
105
130
|
}
|
|
106
131
|
|
|
107
|
-
await
|
|
132
|
+
await ensureConfigDir(configPath);
|
|
108
133
|
await fs.writeFile(configPath, JSON.stringify(json, null, '\t'), 'utf-8');
|
|
109
134
|
}
|
|
110
135
|
|
|
111
136
|
export async function removeMCPServerFromConfig(
|
|
112
137
|
projectRoot: string,
|
|
113
138
|
name: string,
|
|
139
|
+
globalConfigDir?: string,
|
|
114
140
|
): Promise<boolean> {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
141
|
+
const paths = [
|
|
142
|
+
...(globalConfigDir ? [join(globalConfigDir, 'config.json')] : []),
|
|
143
|
+
join(projectRoot, '.otto', 'config.json'),
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
for (const configPath of paths) {
|
|
147
|
+
let json: Record<string, unknown> = {};
|
|
148
|
+
try {
|
|
149
|
+
const text = await fs.readFile(configPath, 'utf-8');
|
|
150
|
+
json = JSON.parse(text);
|
|
151
|
+
} catch {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
123
154
|
|
|
124
|
-
|
|
125
|
-
|
|
155
|
+
const mcp = json.mcp as Record<string, unknown> | undefined;
|
|
156
|
+
if (!mcp || !Array.isArray(mcp.servers)) continue;
|
|
126
157
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
158
|
+
const servers = mcp.servers as MCPServerConfig[];
|
|
159
|
+
const idx = servers.findIndex((s) => s.name === name);
|
|
160
|
+
if (idx < 0) continue;
|
|
130
161
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
162
|
+
servers.splice(idx, 1);
|
|
163
|
+
await fs.writeFile(configPath, JSON.stringify(json, null, '\t'), 'utf-8');
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return false;
|
|
134
168
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
+
import { getSecureOAuthDir } from '../../../../config/src/paths.ts';
|
|
3
4
|
|
|
4
5
|
export interface StoredOAuthData {
|
|
5
6
|
tokens?: {
|
|
@@ -22,14 +23,7 @@ export class OAuthCredentialStore {
|
|
|
22
23
|
private storePath: string;
|
|
23
24
|
|
|
24
25
|
constructor(storePath?: string) {
|
|
25
|
-
this.storePath =
|
|
26
|
-
storePath ??
|
|
27
|
-
join(
|
|
28
|
-
process.env.HOME ?? process.env.USERPROFILE ?? '',
|
|
29
|
-
'.config',
|
|
30
|
-
'otto',
|
|
31
|
-
'oauth',
|
|
32
|
-
);
|
|
26
|
+
this.storePath = storePath ?? getSecureOAuthDir();
|
|
33
27
|
}
|
|
34
28
|
|
|
35
29
|
private filePath(serverName: string): string {
|
|
@@ -2,6 +2,7 @@ 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 { createHash } from 'node:crypto';
|
|
5
6
|
|
|
6
7
|
type IndexedTool = {
|
|
7
8
|
server: string;
|
|
@@ -14,17 +15,36 @@ export class MCPServerManager {
|
|
|
14
15
|
private authProviders = new Map<string, OttoOAuthProvider>();
|
|
15
16
|
private pendingAuth = new Map<string, string>();
|
|
16
17
|
private oauthStore = new OAuthCredentialStore();
|
|
18
|
+
private serverScopes = new Map<string, 'global' | 'project'>();
|
|
17
19
|
private _started = false;
|
|
20
|
+
private projectRoot: string | null = null;
|
|
18
21
|
|
|
19
22
|
get started(): boolean {
|
|
20
23
|
return this._started;
|
|
21
24
|
}
|
|
22
25
|
|
|
26
|
+
setProjectRoot(projectRoot: string): void {
|
|
27
|
+
this.projectRoot = projectRoot;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private oauthKey(serverName: string): string {
|
|
31
|
+
const scope = this.serverScopes.get(serverName);
|
|
32
|
+
if (scope === 'project' && this.projectRoot) {
|
|
33
|
+
const hash = createHash('sha256')
|
|
34
|
+
.update(this.projectRoot)
|
|
35
|
+
.digest('hex')
|
|
36
|
+
.slice(0, 8);
|
|
37
|
+
return `${serverName}_proj_${hash}`;
|
|
38
|
+
}
|
|
39
|
+
return serverName;
|
|
40
|
+
}
|
|
41
|
+
|
|
23
42
|
async startServers(configs: MCPServerConfig[]): Promise<void> {
|
|
24
43
|
await this.stopAll();
|
|
25
44
|
|
|
26
45
|
for (const config of configs) {
|
|
27
46
|
if (config.disabled) continue;
|
|
47
|
+
this.serverScopes.set(config.name, config.scope ?? 'global');
|
|
28
48
|
await this.startSingleServer(config);
|
|
29
49
|
}
|
|
30
50
|
this._started = true;
|
|
@@ -38,7 +58,8 @@ export class MCPServerManager {
|
|
|
38
58
|
const hasStaticAuth =
|
|
39
59
|
config.headers?.Authorization || config.headers?.authorization;
|
|
40
60
|
if (!hasStaticAuth) {
|
|
41
|
-
const
|
|
61
|
+
const key = this.oauthKey(config.name);
|
|
62
|
+
const provider = new OttoOAuthProvider(key, this.oauthStore, {
|
|
42
63
|
clientId: config.oauth?.clientId,
|
|
43
64
|
callbackPort: config.oauth?.callbackPort,
|
|
44
65
|
scopes: config.oauth?.scopes,
|
|
@@ -104,6 +125,7 @@ export class MCPServerManager {
|
|
|
104
125
|
this.toolsMap.clear();
|
|
105
126
|
this.authProviders.clear();
|
|
106
127
|
this.pendingAuth.clear();
|
|
128
|
+
this.serverScopes.clear();
|
|
107
129
|
this._started = false;
|
|
108
130
|
}
|
|
109
131
|
|
|
@@ -137,8 +159,9 @@ export class MCPServerManager {
|
|
|
137
159
|
.filter(([, v]) => v.server === name)
|
|
138
160
|
.map(([k]) => k);
|
|
139
161
|
const config = client.serverConfig;
|
|
162
|
+
const key = this.oauthKey(name);
|
|
140
163
|
const _authenticated = this.oauthStore
|
|
141
|
-
.isAuthenticated(
|
|
164
|
+
.isAuthenticated(key)
|
|
142
165
|
.catch(() => false);
|
|
143
166
|
|
|
144
167
|
statuses.push({
|
|
@@ -161,8 +184,9 @@ export class MCPServerManager {
|
|
|
161
184
|
.filter(([, v]) => v.server === name)
|
|
162
185
|
.map(([k]) => k);
|
|
163
186
|
const config = client.serverConfig;
|
|
187
|
+
const key = this.oauthKey(name);
|
|
164
188
|
const authenticated = await this.oauthStore
|
|
165
|
-
.isAuthenticated(
|
|
189
|
+
.isAuthenticated(key)
|
|
166
190
|
.catch(() => false);
|
|
167
191
|
|
|
168
192
|
statuses.push({
|
|
@@ -194,7 +218,9 @@ export class MCPServerManager {
|
|
|
194
218
|
const transport = config.transport ?? 'stdio';
|
|
195
219
|
if (transport === 'stdio') return null;
|
|
196
220
|
|
|
197
|
-
|
|
221
|
+
this.serverScopes.set(config.name, config.scope ?? 'global');
|
|
222
|
+
const key = this.oauthKey(config.name);
|
|
223
|
+
const provider = new OttoOAuthProvider(key, this.oauthStore, {
|
|
198
224
|
clientId: config.oauth?.clientId,
|
|
199
225
|
callbackPort: config.oauth?.callbackPort,
|
|
200
226
|
scopes: config.oauth?.scopes,
|
|
@@ -272,7 +298,8 @@ export class MCPServerManager {
|
|
|
272
298
|
async getAuthStatus(
|
|
273
299
|
name: string,
|
|
274
300
|
): Promise<{ authenticated: boolean; expiresAt?: number }> {
|
|
275
|
-
const
|
|
301
|
+
const key = this.oauthKey(name);
|
|
302
|
+
const tokens = await this.oauthStore.loadTokens(key);
|
|
276
303
|
if (!tokens?.access_token) return { authenticated: false };
|
|
277
304
|
return {
|
|
278
305
|
authenticated: true,
|
|
@@ -282,6 +309,7 @@ export class MCPServerManager {
|
|
|
282
309
|
|
|
283
310
|
async restartServer(config: MCPServerConfig): Promise<void> {
|
|
284
311
|
await this.stopServer(config.name);
|
|
312
|
+
this.serverScopes.set(config.name, config.scope ?? 'global');
|
|
285
313
|
await this.startSingleServer(config);
|
|
286
314
|
}
|
|
287
315
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type MCPTransport = 'stdio' | 'http' | 'sse';
|
|
2
|
+
export type MCPScope = 'global' | 'project';
|
|
2
3
|
|
|
3
4
|
export interface MCPOAuthConfig {
|
|
4
5
|
clientId?: string;
|
|
@@ -21,6 +22,8 @@ export interface MCPServerConfig {
|
|
|
21
22
|
oauth?: MCPOAuthConfig;
|
|
22
23
|
|
|
23
24
|
disabled?: boolean;
|
|
25
|
+
|
|
26
|
+
scope?: MCPScope;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
export interface MCPConfig {
|
package/src/index.ts
CHANGED
|
@@ -108,6 +108,8 @@ export { createOpencodeModel } from './providers/src/index.ts';
|
|
|
108
108
|
export type { OpencodeProviderConfig } from './providers/src/index.ts';
|
|
109
109
|
export { createMoonshotModel } from './providers/src/index.ts';
|
|
110
110
|
export type { MoonshotProviderConfig } from './providers/src/index.ts';
|
|
111
|
+
export { createMinimaxModel } from './providers/src/index.ts';
|
|
112
|
+
export type { MinimaxProviderConfig } from './providers/src/index.ts';
|
|
111
113
|
export {
|
|
112
114
|
createCopilotFetch,
|
|
113
115
|
createCopilotModel,
|
|
@@ -171,6 +173,8 @@ export {
|
|
|
171
173
|
getGlobalToolsDir,
|
|
172
174
|
getGlobalCommandsDir,
|
|
173
175
|
getSecureAuthPath,
|
|
176
|
+
getSecureBaseDir,
|
|
177
|
+
getSecureOAuthDir,
|
|
174
178
|
getHomeDir,
|
|
175
179
|
} from './config/src/paths.ts';
|
|
176
180
|
export {
|
|
@@ -358,6 +362,7 @@ export type {
|
|
|
358
362
|
MCPToolInfo,
|
|
359
363
|
MCPTransport,
|
|
360
364
|
MCPOAuthConfig,
|
|
365
|
+
MCPScope,
|
|
361
366
|
StoredOAuthData,
|
|
362
367
|
OttoOAuthProviderOptions,
|
|
363
368
|
CallbackResult,
|
|
@@ -36,6 +36,12 @@ const isAllowedZaiModel = (id: string): boolean => {
|
|
|
36
36
|
return false;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
const isAllowedMinimaxModel = (id: string): boolean => {
|
|
40
|
+
if (id === 'MiniMax-M2.5') return true;
|
|
41
|
+
if (id === 'MiniMax-M2.1') return true;
|
|
42
|
+
return false;
|
|
43
|
+
};
|
|
44
|
+
|
|
39
45
|
const SETU_SOURCES: Array<{
|
|
40
46
|
id: ProviderId;
|
|
41
47
|
npm: string;
|
|
@@ -66,6 +72,11 @@ const SETU_SOURCES: Array<{
|
|
|
66
72
|
npm: '@ai-sdk/openai-compatible',
|
|
67
73
|
family: 'openai-compatible',
|
|
68
74
|
},
|
|
75
|
+
{
|
|
76
|
+
id: 'minimax',
|
|
77
|
+
npm: '@ai-sdk/anthropic',
|
|
78
|
+
family: 'minimax',
|
|
79
|
+
},
|
|
69
80
|
];
|
|
70
81
|
|
|
71
82
|
function cloneModel(model: ModelInfo): ModelInfo {
|
|
@@ -95,6 +106,7 @@ function buildSetuEntry(base: CatalogMap): ProviderCatalogEntry | null {
|
|
|
95
106
|
if (id === 'anthropic') return isAllowedAnthropicModel(model.id);
|
|
96
107
|
if (id === 'google') return isAllowedGoogleModel(model.id);
|
|
97
108
|
if (id === 'zai') return isAllowedZaiModel(model.id);
|
|
109
|
+
if (id === 'minimax') return isAllowedMinimaxModel(model.id);
|
|
98
110
|
return true;
|
|
99
111
|
});
|
|
100
112
|
return sourceModels.map((model) => {
|
|
@@ -3924,6 +3924,30 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
3924
3924
|
output: 131072,
|
|
3925
3925
|
},
|
|
3926
3926
|
},
|
|
3927
|
+
{
|
|
3928
|
+
id: 'minimax/minimax-m2.5',
|
|
3929
|
+
label: 'MiniMax M2.5',
|
|
3930
|
+
modalities: {
|
|
3931
|
+
input: ['text'],
|
|
3932
|
+
output: ['text'],
|
|
3933
|
+
},
|
|
3934
|
+
toolCall: true,
|
|
3935
|
+
reasoningText: true,
|
|
3936
|
+
attachment: false,
|
|
3937
|
+
temperature: true,
|
|
3938
|
+
releaseDate: '2026-02-12',
|
|
3939
|
+
lastUpdated: '2026-02-12',
|
|
3940
|
+
openWeights: true,
|
|
3941
|
+
cost: {
|
|
3942
|
+
input: 0.3,
|
|
3943
|
+
output: 1.2,
|
|
3944
|
+
cacheRead: 0.03,
|
|
3945
|
+
},
|
|
3946
|
+
limit: {
|
|
3947
|
+
context: 204800,
|
|
3948
|
+
output: 131072,
|
|
3949
|
+
},
|
|
3950
|
+
},
|
|
3927
3951
|
{
|
|
3928
3952
|
id: 'mistralai/codestral-2508',
|
|
3929
3953
|
label: 'Codestral 2508',
|
|
@@ -6986,6 +7010,31 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
6986
7010
|
output: 131072,
|
|
6987
7011
|
},
|
|
6988
7012
|
},
|
|
7013
|
+
{
|
|
7014
|
+
id: 'glm-5',
|
|
7015
|
+
label: 'GLM-5',
|
|
7016
|
+
modalities: {
|
|
7017
|
+
input: ['text'],
|
|
7018
|
+
output: ['text'],
|
|
7019
|
+
},
|
|
7020
|
+
toolCall: true,
|
|
7021
|
+
reasoningText: true,
|
|
7022
|
+
attachment: false,
|
|
7023
|
+
temperature: true,
|
|
7024
|
+
knowledge: '2025-04',
|
|
7025
|
+
releaseDate: '2026-02-11',
|
|
7026
|
+
lastUpdated: '2026-02-11',
|
|
7027
|
+
openWeights: true,
|
|
7028
|
+
cost: {
|
|
7029
|
+
input: 1,
|
|
7030
|
+
output: 3.2,
|
|
7031
|
+
cacheRead: 0.2,
|
|
7032
|
+
},
|
|
7033
|
+
limit: {
|
|
7034
|
+
context: 204800,
|
|
7035
|
+
output: 131072,
|
|
7036
|
+
},
|
|
7037
|
+
},
|
|
6989
7038
|
{
|
|
6990
7039
|
id: 'gpt-5',
|
|
6991
7040
|
label: 'GPT-5',
|
|
@@ -7416,6 +7465,31 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
7416
7465
|
npm: '@ai-sdk/anthropic',
|
|
7417
7466
|
},
|
|
7418
7467
|
},
|
|
7468
|
+
{
|
|
7469
|
+
id: 'minimax-m2.5',
|
|
7470
|
+
label: 'MiniMax M2.5',
|
|
7471
|
+
modalities: {
|
|
7472
|
+
input: ['text'],
|
|
7473
|
+
output: ['text'],
|
|
7474
|
+
},
|
|
7475
|
+
toolCall: true,
|
|
7476
|
+
reasoningText: true,
|
|
7477
|
+
attachment: false,
|
|
7478
|
+
temperature: true,
|
|
7479
|
+
knowledge: '2025-01',
|
|
7480
|
+
releaseDate: '2026-02-12',
|
|
7481
|
+
lastUpdated: '2026-02-12',
|
|
7482
|
+
openWeights: true,
|
|
7483
|
+
cost: {
|
|
7484
|
+
input: 0.3,
|
|
7485
|
+
output: 1.2,
|
|
7486
|
+
cacheRead: 0.06,
|
|
7487
|
+
},
|
|
7488
|
+
limit: {
|
|
7489
|
+
context: 204800,
|
|
7490
|
+
output: 131072,
|
|
7491
|
+
},
|
|
7492
|
+
},
|
|
7419
7493
|
{
|
|
7420
7494
|
id: 'minimax-m2.5-free',
|
|
7421
7495
|
label: 'MiniMax M2.5 Free',
|
|
@@ -8134,6 +8208,87 @@ export const catalog: Partial<Record<ProviderId, ProviderCatalogEntry>> = {
|
|
|
8134
8208
|
api: 'https://api.moonshot.ai/v1',
|
|
8135
8209
|
doc: 'https://platform.moonshot.ai/docs/api/chat',
|
|
8136
8210
|
},
|
|
8211
|
+
minimax: {
|
|
8212
|
+
id: 'minimax',
|
|
8213
|
+
models: [
|
|
8214
|
+
{
|
|
8215
|
+
id: 'MiniMax-M2',
|
|
8216
|
+
label: 'MiniMax-M2',
|
|
8217
|
+
modalities: {
|
|
8218
|
+
input: ['text'],
|
|
8219
|
+
output: ['text'],
|
|
8220
|
+
},
|
|
8221
|
+
toolCall: true,
|
|
8222
|
+
reasoningText: true,
|
|
8223
|
+
attachment: false,
|
|
8224
|
+
temperature: true,
|
|
8225
|
+
releaseDate: '2025-10-27',
|
|
8226
|
+
lastUpdated: '2025-10-27',
|
|
8227
|
+
openWeights: true,
|
|
8228
|
+
cost: {
|
|
8229
|
+
input: 0.3,
|
|
8230
|
+
output: 1.2,
|
|
8231
|
+
},
|
|
8232
|
+
limit: {
|
|
8233
|
+
context: 196608,
|
|
8234
|
+
output: 128000,
|
|
8235
|
+
},
|
|
8236
|
+
},
|
|
8237
|
+
{
|
|
8238
|
+
id: 'MiniMax-M2.1',
|
|
8239
|
+
label: 'MiniMax-M2.1',
|
|
8240
|
+
modalities: {
|
|
8241
|
+
input: ['text'],
|
|
8242
|
+
output: ['text'],
|
|
8243
|
+
},
|
|
8244
|
+
toolCall: true,
|
|
8245
|
+
reasoningText: true,
|
|
8246
|
+
attachment: false,
|
|
8247
|
+
temperature: true,
|
|
8248
|
+
releaseDate: '2025-12-23',
|
|
8249
|
+
lastUpdated: '2025-12-23',
|
|
8250
|
+
openWeights: true,
|
|
8251
|
+
cost: {
|
|
8252
|
+
input: 0.3,
|
|
8253
|
+
output: 1.2,
|
|
8254
|
+
},
|
|
8255
|
+
limit: {
|
|
8256
|
+
context: 204800,
|
|
8257
|
+
output: 131072,
|
|
8258
|
+
},
|
|
8259
|
+
},
|
|
8260
|
+
{
|
|
8261
|
+
id: 'MiniMax-M2.5',
|
|
8262
|
+
label: 'MiniMax-M2.5',
|
|
8263
|
+
modalities: {
|
|
8264
|
+
input: ['text'],
|
|
8265
|
+
output: ['text'],
|
|
8266
|
+
},
|
|
8267
|
+
toolCall: true,
|
|
8268
|
+
reasoningText: true,
|
|
8269
|
+
attachment: false,
|
|
8270
|
+
temperature: true,
|
|
8271
|
+
releaseDate: '2026-02-12',
|
|
8272
|
+
lastUpdated: '2026-02-12',
|
|
8273
|
+
openWeights: true,
|
|
8274
|
+
cost: {
|
|
8275
|
+
input: 0.3,
|
|
8276
|
+
output: 1.2,
|
|
8277
|
+
cacheRead: 0.03,
|
|
8278
|
+
cacheWrite: 0.375,
|
|
8279
|
+
},
|
|
8280
|
+
limit: {
|
|
8281
|
+
context: 204800,
|
|
8282
|
+
output: 131072,
|
|
8283
|
+
},
|
|
8284
|
+
},
|
|
8285
|
+
],
|
|
8286
|
+
label: 'MiniMax (minimax.io)',
|
|
8287
|
+
env: ['MINIMAX_API_KEY'],
|
|
8288
|
+
npm: '@ai-sdk/anthropic',
|
|
8289
|
+
api: 'https://api.minimax.io/anthropic/v1',
|
|
8290
|
+
doc: 'https://platform.minimax.io/docs/guides/quickstart',
|
|
8291
|
+
},
|
|
8137
8292
|
copilot: {
|
|
8138
8293
|
id: 'copilot',
|
|
8139
8294
|
models: [
|
package/src/providers/src/env.ts
CHANGED
|
@@ -72,5 +72,7 @@ export { createOpencodeModel } from './opencode-client.ts';
|
|
|
72
72
|
export type { OpencodeProviderConfig } from './opencode-client.ts';
|
|
73
73
|
export { createMoonshotModel } from './moonshot-client.ts';
|
|
74
74
|
export type { MoonshotProviderConfig } from './moonshot-client.ts';
|
|
75
|
+
export { createMinimaxModel } from './minimax-client.ts';
|
|
76
|
+
export type { MinimaxProviderConfig } from './minimax-client.ts';
|
|
75
77
|
export { createCopilotFetch, createCopilotModel } from './copilot-client.ts';
|
|
76
78
|
export type { CopilotOAuthConfig } from './copilot-client.ts';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createAnthropic } from '@ai-sdk/anthropic';
|
|
2
|
+
import { catalog } from './catalog-merged.ts';
|
|
3
|
+
|
|
4
|
+
export type MinimaxProviderConfig = {
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
baseURL?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function createMinimaxModel(
|
|
10
|
+
model: string,
|
|
11
|
+
config?: MinimaxProviderConfig,
|
|
12
|
+
) {
|
|
13
|
+
const entry = catalog.minimax;
|
|
14
|
+
const baseURL =
|
|
15
|
+
config?.baseURL || entry?.api || 'https://api.minimax.io/anthropic/v1';
|
|
16
|
+
const apiKey = config?.apiKey || process.env.MINIMAX_API_KEY || '';
|
|
17
|
+
|
|
18
|
+
const instance = createAnthropic({
|
|
19
|
+
apiKey,
|
|
20
|
+
baseURL,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return instance(model);
|
|
24
|
+
}
|
|
@@ -124,6 +124,7 @@ export type UnderlyingProviderKey =
|
|
|
124
124
|
| 'openai'
|
|
125
125
|
| 'google'
|
|
126
126
|
| 'moonshot'
|
|
127
|
+
| 'minimax'
|
|
127
128
|
| 'glm'
|
|
128
129
|
| 'openai-compatible'
|
|
129
130
|
| null;
|
|
@@ -136,6 +137,7 @@ export function getUnderlyingProviderKey(
|
|
|
136
137
|
if (provider === 'openai') return 'openai';
|
|
137
138
|
if (provider === 'google') return 'google';
|
|
138
139
|
if (provider === 'moonshot') return 'moonshot';
|
|
140
|
+
if (provider === 'minimax') return 'minimax';
|
|
139
141
|
if (provider === 'copilot') return 'openai';
|
|
140
142
|
|
|
141
143
|
if (provider === 'zai' || provider === 'zai-coding') return 'glm';
|
|
@@ -158,6 +160,7 @@ export function getModelFamily(
|
|
|
158
160
|
if (provider === 'openai') return 'openai';
|
|
159
161
|
if (provider === 'google') return 'google';
|
|
160
162
|
if (provider === 'moonshot') return 'moonshot';
|
|
163
|
+
if (provider === 'minimax') return 'minimax';
|
|
161
164
|
if (provider === 'copilot') return 'openai';
|
|
162
165
|
if (provider === 'zai' || provider === 'zai-coding') return 'glm';
|
|
163
166
|
|
|
@@ -191,6 +194,9 @@ export function getModelFamily(
|
|
|
191
194
|
) {
|
|
192
195
|
return 'glm';
|
|
193
196
|
}
|
|
197
|
+
if (lowerModel.includes('minimax')) {
|
|
198
|
+
return 'minimax';
|
|
199
|
+
}
|
|
194
200
|
}
|
|
195
201
|
|
|
196
202
|
// 2) Check model's family field in catalog
|
|
@@ -11,7 +11,8 @@ export type ProviderId =
|
|
|
11
11
|
| 'setu'
|
|
12
12
|
| 'zai'
|
|
13
13
|
| 'zai-coding'
|
|
14
|
-
| 'moonshot'
|
|
14
|
+
| 'moonshot'
|
|
15
|
+
| 'minimax';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Provider family for prompt selection
|
|
@@ -21,6 +22,7 @@ export type ProviderFamily =
|
|
|
21
22
|
| 'anthropic'
|
|
22
23
|
| 'google'
|
|
23
24
|
| 'moonshot'
|
|
25
|
+
| 'minimax'
|
|
24
26
|
| 'openai-compatible';
|
|
25
27
|
|
|
26
28
|
export type ModelProviderBinding = {
|