@kikkimo/claude-launcher 2.5.0 → 3.1.0

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/lib/launcher.js CHANGED
@@ -7,11 +7,111 @@ const colors = require('./ui/colors');
7
7
  const i18n = require('./i18n');
8
8
  const { getProvider } = require('./presets/providers');
9
9
  const stdinManager = require('./utils/stdin-manager');
10
+ const { loadConfigSync } = require('./utils/version-checker');
11
+
12
+ // Module-level flag for console handoff state
13
+ let consoleRelinquished = false;
14
+
15
+ /**
16
+ * Detach stdin and suspend stdinManager so the child process owns the terminal
17
+ */
18
+ function relinquishConsoleToChild() {
19
+ if (consoleRelinquished) return;
20
+ consoleRelinquished = true;
21
+ try {
22
+ if (process.stdin.isTTY) {
23
+ process.stdin.setRawMode(false);
24
+ }
25
+ } catch (_) {}
26
+
27
+ // Detach only current scope listeners to avoid affecting other modules
28
+ if (stdinManager.activeScope && typeof stdinManager.activeScope.detach === 'function') {
29
+ stdinManager.activeScope.detach();
30
+ }
31
+
32
+ // Suspend stdin manager so no new listeners are attached while Claude is running
33
+ if (typeof stdinManager.suspend === 'function') {
34
+ stdinManager.suspend();
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Restore stdinManager after child process exits
40
+ */
41
+ function restoreConsoleForLauncher() {
42
+ if (!consoleRelinquished) return;
43
+ consoleRelinquished = false;
44
+ if (typeof stdinManager.resume === 'function') {
45
+ stdinManager.resume();
46
+ }
47
+ stdinManager.enableCtrlC();
48
+ }
49
+
50
+ /**
51
+ * Handle launch failures with optional rollback and user prompt
52
+ */
53
+ function handleLaunchFailure(message, opts = {}) {
54
+ if (opts.afterHandover) {
55
+ restoreConsoleForLauncher();
56
+ } else {
57
+ stdinManager.enableCtrlC();
58
+ }
59
+
60
+ // Rollback launch statistics if callback provided — pass error message for lastError
61
+ if (typeof opts.rollbackFn === 'function') {
62
+ try { opts.rollbackFn(message); } catch (_) {}
63
+ }
64
+
65
+ console.log(colors.red + '[x] ' + message + colors.reset);
66
+ console.log(colors.gray + i18n.tSync('ui.general.press_key_return_menu') + colors.reset);
67
+
68
+ if (process.stdin.isTTY) {
69
+ try {
70
+ process.stdin.setRawMode(true);
71
+ process.stdin.resume();
72
+ } catch (_) {
73
+ // Ignore setup failures
74
+ }
75
+
76
+ // Set timeout to prevent infinite hanging
77
+ const timeoutId = setTimeout(() => {
78
+ try {
79
+ process.stdin.setRawMode(false);
80
+ } catch (_) {
81
+ // Ignore cleanup failures
82
+ }
83
+ process.exit(1);
84
+ }, 60000); // 60 second timeout
85
+
86
+ process.stdin.once('data', () => {
87
+ clearTimeout(timeoutId);
88
+ try {
89
+ process.stdin.setRawMode(false);
90
+ } catch (_) {
91
+ // Ignore cleanup failures
92
+ }
93
+ // Exit after user acknowledges the error
94
+ process.exit(1);
95
+ });
96
+ } else {
97
+ // For non-TTY environments, exit immediately
98
+ process.exit(1);
99
+ }
100
+ }
10
101
 
11
102
  /**
12
103
  * Launch Claude Code with specified environment variables
13
104
  */
14
- function launchClaude(command, envVars = {}, disableAuthTokens = false) {
105
+ function launchClaude(command, envVars = {}, disableAuthTokens = false, opts = {}) {
106
+ // Inject telemetry control from config
107
+ const launcherConfig = loadConfigSync();
108
+ if (launcherConfig.disableTelemetry) {
109
+ envVars.DISABLE_TELEMETRY = '1';
110
+ }
111
+ if (launcherConfig.noFlicker) {
112
+ envVars.CLAUDE_CODE_NO_FLICKER = '1';
113
+ }
114
+
15
115
  // Disable Ctrl+C monitoring before launching Claude Code
16
116
  // This allows Ctrl+C to be handled exclusively by Claude Code process
17
117
  stdinManager.disableCtrlC();
@@ -40,90 +140,14 @@ function launchClaude(command, envVars = {}, disableAuthTokens = false) {
40
140
 
41
141
  // Disable conflicting auth tokens when using third-party API
42
142
  if (disableAuthTokens) {
43
- // Only delete CLAUDE_CODE_OAUTH_TOKEN - keep ANTHROPIC_AUTH_TOKEN that we just set
44
143
  delete env.CLAUDE_CODE_OAUTH_TOKEN;
45
- console.log(colors.gray + ' Disabled: CLAUDE_CODE_OAUTH_TOKEN' + colors.reset);
144
+ delete env.ANTHROPIC_API_KEY;
46
145
  }
47
146
 
48
147
  // Parse command and arguments
49
148
  const args = command.split(' ');
50
149
  const cmd = args.shift();
51
150
 
52
- let consoleRelinquished = false;
53
- const relinquishConsoleToChild = () => {
54
- if (consoleRelinquished) return;
55
- consoleRelinquished = true;
56
- // Do the minimal changes: switch to cooked mode and detach current scope, but do not pause stdin nor swallow signals
57
- try {
58
- if (process.stdin.isTTY) {
59
- process.stdin.setRawMode(false);
60
- }
61
- } catch (_) {}
62
-
63
- // Detach only current scope listeners to avoid affecting other modules
64
- if (stdinManager.activeScope && typeof stdinManager.activeScope.detach === 'function') {
65
- stdinManager.activeScope.detach();
66
- }
67
-
68
- // Suspend stdin manager so no new listeners are attached while Claude is running
69
- if (typeof stdinManager.suspend === 'function') {
70
- stdinManager.suspend();
71
- }
72
- };
73
-
74
- const restoreConsoleForLauncher = () => {
75
- if (!consoleRelinquished) return;
76
- consoleRelinquished = false;
77
- if (typeof stdinManager.resume === 'function') {
78
- stdinManager.resume();
79
- }
80
- stdinManager.enableCtrlC();
81
- };
82
-
83
- const handleLaunchFailure = (message, opts = {}) => {
84
- if (opts.afterHandover) {
85
- restoreConsoleForLauncher();
86
- } else {
87
- stdinManager.enableCtrlC();
88
- }
89
-
90
- console.log(colors.red + '[x] ' + message + colors.reset);
91
- console.log(colors.gray + i18n.tSync('ui.general.press_key_return_menu') + colors.reset);
92
-
93
- if (process.stdin.isTTY) {
94
- try {
95
- process.stdin.setRawMode(true);
96
- process.stdin.resume();
97
- } catch (_) {
98
- // Ignore setup failures
99
- }
100
-
101
- // Set timeout to prevent infinite hanging
102
- const timeoutId = setTimeout(() => {
103
- try {
104
- process.stdin.setRawMode(false);
105
- } catch (_) {
106
- // Ignore cleanup failures
107
- }
108
- process.exit(1);
109
- }, 60000); // 60 second timeout
110
-
111
- process.stdin.once('data', () => {
112
- clearTimeout(timeoutId);
113
- try {
114
- process.stdin.setRawMode(false);
115
- } catch (_) {
116
- // Ignore cleanup failures
117
- }
118
- // Exit after user acknowledges the error
119
- process.exit(1);
120
- });
121
- } else {
122
- // For non-TTY environments, exit immediately
123
- process.exit(1);
124
- }
125
- };
126
-
127
151
  try {
128
152
  // Clean up terminal state before launching Claude
129
153
  if (process.stdin.isTTY) {
@@ -135,15 +159,8 @@ function launchClaude(command, envVars = {}, disableAuthTokens = false) {
135
159
  }
136
160
  }
137
161
 
138
- // Note: stdin listener management is handled by relinquishConsoleToChild()
139
- // using stdinManager.activeScope.detach() and stdinManager.suspend().
140
- // This ensures only the current scope's listeners are detached while
141
- // preserving any listeners from other modules.
142
- //
143
- // Note: Do NOT remove global SIGINT/SIGTERM handlers here.
144
- // The existing handlers already check stdinManager.isSuspended() and
145
- // will properly ignore signals during child process execution.
146
- // Removing all handlers would break other modules and degrade reliability.
162
+ // Relinquish console before spawn so the child inherits a clean terminal
163
+ relinquishConsoleToChild();
147
164
 
148
165
  // Launch Claude in current terminal, inherit stdio
149
166
  const child = spawn(cmd, args, {
@@ -153,19 +170,22 @@ function launchClaude(command, envVars = {}, disableAuthTokens = false) {
153
170
  shell: true
154
171
  });
155
172
 
156
- relinquishConsoleToChild();
157
-
158
173
  child.on('close', (code) => {
159
174
  restoreConsoleForLauncher();
160
175
  process.exit(code || 0);
161
176
  });
162
177
 
163
178
  child.on('error', (error) => {
164
- handleLaunchFailure('Error running Claude: ' + error.message, { afterHandover: true });
179
+ handleLaunchFailure('Error running Claude: ' + error.message, {
180
+ afterHandover: true,
181
+ rollbackFn: opts.rollbackFn
182
+ });
165
183
  });
166
184
 
167
185
  } catch (error) {
168
- handleLaunchFailure('Error launching Claude Code: ' + error.message);
186
+ handleLaunchFailure('Error launching Claude Code: ' + error.message, {
187
+ rollbackFn: opts.rollbackFn
188
+ });
169
189
  }
170
190
  }
171
191
 
@@ -196,47 +216,83 @@ function launchClaudeAutoMode() {
196
216
  * Get environment variables based on provider type
197
217
  */
198
218
  function getProviderEnvVars(api) {
199
- // Decrypt the auth token (all tokens are stored encrypted)
200
219
  const { decrypt } = require('./crypto');
201
220
  const decrypted = decrypt(api.authToken);
202
-
203
221
  if (!decrypted.success) {
204
- console.error('Failed to decrypt auth token:', decrypted.error);
205
222
  throw new Error('Failed to decrypt API auth token. Please check your configuration.');
206
223
  }
207
224
 
208
225
  const authToken = decrypted.value;
209
226
 
210
- const baseEnvVars = {
227
+ // Step 1: Base variables
228
+ const env = {
211
229
  ANTHROPIC_BASE_URL: api.baseUrl,
212
230
  ANTHROPIC_AUTH_TOKEN: authToken,
213
231
  ANTHROPIC_MODEL: api.model,
214
- ANTHROPIC_SMALL_FAST_MODEL: api.smallFastModel || api.model
232
+ ANTHROPIC_SMALL_FAST_MODEL: api.smallFastModel || api.model,
215
233
  };
216
234
 
217
- // Get provider configuration and merge provider-specific environment variables
235
+ // Step 2: Provider-level defaults
218
236
  const providerConfig = getProvider(api.provider);
219
-
220
237
  if (providerConfig && providerConfig.envVars) {
221
- // Merge base env vars with provider-specific env vars
222
- return {
223
- ...baseEnvVars,
224
- ...providerConfig.envVars
225
- };
238
+ Object.assign(env, providerConfig.envVars);
239
+ }
240
+
241
+ const { PREDEFINED_MODEL_ENV_KEYS, PREDEFINED_RUNTIME_KEYS, TYPE_A_FIELDS, RESERVED_ENV_KEYS } = require('./validators');
242
+
243
+ // Step 3: modelEnvVars (whitelist, non-empty)
244
+ if (api.modelEnvVars) {
245
+ for (const key of PREDEFINED_MODEL_ENV_KEYS) {
246
+ const val = api.modelEnvVars[key];
247
+ if (val !== undefined && val !== '') env[key] = val;
248
+ }
226
249
  }
227
250
 
228
- return baseEnvVars;
251
+ // Step 4: runtimeEnvVars (whitelist, non-empty, skip "off")
252
+ if (api.runtimeEnvVars) {
253
+ for (const key of PREDEFINED_RUNTIME_KEYS) {
254
+ const val = api.runtimeEnvVars[key];
255
+ if (val !== undefined && val !== '' && val !== 'off') env[key] = val;
256
+ }
257
+ }
258
+
259
+ // Step 5: customEnvVars (skip reserved/predefined)
260
+ if (api.customEnvVars) {
261
+ const allPredefined = new Set([...RESERVED_ENV_KEYS, ...PREDEFINED_RUNTIME_KEYS, ...PREDEFINED_MODEL_ENV_KEYS]);
262
+ for (const [key, val] of Object.entries(api.customEnvVars)) {
263
+ if (allPredefined.has(key)) continue;
264
+ if (val !== undefined && val !== '') env[key] = val;
265
+ }
266
+ }
267
+
268
+ // Step 6: Remove Type A fields with "off" (tombstone)
269
+ if (api.runtimeEnvVars) {
270
+ for (const key of TYPE_A_FIELDS) {
271
+ if (api.runtimeEnvVars[key] === 'off') delete env[key];
272
+ }
273
+ }
274
+
275
+ return env;
229
276
  }
230
277
 
231
278
  /**
232
279
  * Launch Claude with third-party API configuration
233
280
  */
234
- function launchClaudeWithApi(api, skipPermissions = false) {
281
+ function launchClaudeWithApi(api, skipPermissions = false, opts = {}) {
235
282
  const command = skipPermissions
236
283
  ? 'claude --dangerously-skip-permissions'
237
284
  : 'claude';
238
285
 
239
- const envVars = getProviderEnvVars(api);
286
+ let envVars;
287
+ try {
288
+ envVars = getProviderEnvVars(api);
289
+ } catch (error) {
290
+ handleLaunchFailure('Failed to prepare API environment: ' + error.message, {
291
+ afterHandover: true,
292
+ rollbackFn: opts.rollbackFn
293
+ });
294
+ return;
295
+ }
240
296
 
241
297
  console.log('');
242
298
  console.log(colors.bright + colors.orange + '🔗 ' + i18n.tSync('launch.using_third_party_api') + colors.reset);
@@ -254,8 +310,8 @@ function launchClaudeWithApi(api, skipPermissions = false) {
254
310
  if (providerConfig && providerConfig.envVars && Object.keys(providerConfig.envVars).length > 0) {
255
311
  console.log(colors.yellow + ' ⚡ ' + i18n.tSync('launch.provider_optimizations_applied') + colors.reset);
256
312
 
257
- // Display specific optimizations based on envVars
258
- const msRaw = providerConfig.envVars.API_TIMEOUT_MS;
313
+ // Display specific optimizations from merged envVars
314
+ const msRaw = envVars.API_TIMEOUT_MS;
259
315
  const ms = Number(msRaw);
260
316
  if (Number.isFinite(ms) && ms > 0) {
261
317
  const timeoutSec = Math.floor(ms / 1000);
@@ -281,7 +337,7 @@ function launchClaudeWithApi(api, skipPermissions = false) {
281
337
 
282
338
  console.log('');
283
339
 
284
- launchClaude(command, envVars, true);
340
+ launchClaude(command, envVars, true, { rollbackFn: opts.rollbackFn });
285
341
  }
286
342
 
287
343
  /**
@@ -365,5 +421,6 @@ module.exports = {
365
421
  launchClaudeAutoMode,
366
422
  launchClaudeWithApi,
367
423
  getProviderEnvVars,
368
- testApiConnection
424
+ testApiConnection,
425
+ handleLaunchFailure
369
426
  };
@@ -4,50 +4,106 @@
4
4
  * Note: Only includes APIs that are compatible with Claude Code's Anthropic API format
5
5
  */
6
6
 
7
+ // Template factory: same-gen fast model downgrade via lookup map
8
+ function makeFastMapTemplate(fastMap) {
9
+ return {
10
+ getValues(model) {
11
+ const fastModel = fastMap[model] || model;
12
+ return {
13
+ ANTHROPIC_CUSTOM_MODEL_OPTION: model,
14
+ ANTHROPIC_CUSTOM_MODEL_OPTION_NAME: model,
15
+ ANTHROPIC_DEFAULT_SONNET_MODEL: model,
16
+ ANTHROPIC_DEFAULT_OPUS_MODEL: model,
17
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: fastModel,
18
+ CLAUDE_CODE_SUBAGENT_MODEL: fastModel,
19
+ smallFastModel: fastModel,
20
+ };
21
+ },
22
+ };
23
+ }
24
+
25
+ // Template factory: for providers with single model, no tier split
26
+ function makeSingleTemplate() {
27
+ return {
28
+ getValues(model) {
29
+ return {
30
+ ANTHROPIC_CUSTOM_MODEL_OPTION: model,
31
+ ANTHROPIC_CUSTOM_MODEL_OPTION_NAME: model,
32
+ ANTHROPIC_DEFAULT_SONNET_MODEL: model,
33
+ ANTHROPIC_DEFAULT_OPUS_MODEL: model,
34
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: model,
35
+ CLAUDE_CODE_SUBAGENT_MODEL: model,
36
+ smallFastModel: model,
37
+ };
38
+ },
39
+ };
40
+ }
41
+
42
+ // Anthropic models — defined as const so the template factory can reference them
43
+ const anthropicModels = [
44
+ 'claude-opus-4-7',
45
+ 'claude-sonnet-4-6',
46
+ 'claude-haiku-4-5-20251001',
47
+ 'claude-sonnet-4-5',
48
+ 'claude-opus-4-6',
49
+ 'claude-opus-4-5',
50
+ ];
51
+
7
52
  const providers = {
8
53
  anthropic: {
9
54
  name: 'Anthropic (Official)',
10
55
  baseUrl: 'https://api.anthropic.com',
11
- models: [
12
- 'claude-3-5-haiku-20241022',
13
- 'claude-3-7-sonnet',
14
- 'claude-sonnet-4',
15
- 'claude-sonnet-4-5',
16
- 'claude-opus-4',
17
- 'claude-opus-4-1',
18
- 'claude-opus-4-5',
19
- 'claude-opus-4-6'
20
- ],
21
- // Version aliases for upgrade detection (manually maintained)
22
- // Covers ALL models in each series for comprehensive upgrade detection
56
+ models: anthropicModels,
23
57
  versionAliases: {
24
- // Opus series -> latest opus
25
- 'claude-opus-4': 'claude-opus-4-6',
26
- 'claude-opus-4-1': 'claude-opus-4-6',
27
- 'claude-opus-4-5': 'claude-opus-4-6',
28
- // Sonnet series -> latest sonnet
29
- 'claude-sonnet-4': 'claude-sonnet-4-5',
30
- 'claude-3-7-sonnet': 'claude-sonnet-4-5'
58
+ 'claude-opus-4': 'claude-opus-4-7',
59
+ 'claude-opus-4-1': 'claude-opus-4-7',
60
+ 'claude-opus-4-5': 'claude-opus-4-7',
61
+ 'claude-opus-4-6': 'claude-opus-4-7',
62
+ 'claude-sonnet-4': 'claude-sonnet-4-6',
63
+ 'claude-sonnet-4-5': 'claude-sonnet-4-6',
64
+ 'claude-3-7-sonnet': 'claude-sonnet-4-6',
31
65
  },
32
66
  authTokenFormat: 'sk-ant-api03-...',
33
67
  description: 'Official Anthropic API - Fully compatible',
34
68
  requiresToken: true,
35
- compatibility: 'native'
69
+ compatibility: 'native',
70
+ envVars: {
71
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
72
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
73
+ },
74
+ modelEnvTemplate: {
75
+ getValues(model) {
76
+ const latestSonnet = anthropicModels.find(m => m.includes('sonnet')) || model;
77
+ const latestOpus = anthropicModels.find(m => m.includes('opus')) || model;
78
+ const latestHaiku = anthropicModels.find(m => m.includes('haiku')) || model;
79
+ return {
80
+ ANTHROPIC_CUSTOM_MODEL_OPTION: model,
81
+ ANTHROPIC_CUSTOM_MODEL_OPTION_NAME: model,
82
+ ANTHROPIC_DEFAULT_SONNET_MODEL: latestSonnet,
83
+ ANTHROPIC_DEFAULT_OPUS_MODEL: latestOpus,
84
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: latestHaiku,
85
+ CLAUDE_CODE_SUBAGENT_MODEL: latestHaiku,
86
+ smallFastModel: latestHaiku,
87
+ };
88
+ },
89
+ },
36
90
  },
37
91
  moonshot: {
38
- name: 'Moonshot AI (Kimi-K2.5/K2-Thinking)',
92
+ name: 'Moonshot AI (Kimi-K2.6/K2.5/K2-Thinking)',
39
93
  baseUrl: 'https://api.moonshot.cn/anthropic',
40
94
  models: [
95
+ 'kimi-k2.6',
41
96
  'kimi-k2.5',
42
97
  'kimi-k2-thinking',
43
- 'kimi-k2-thinking-turbo'
98
+ 'kimi-k2-thinking-turbo',
44
99
  ],
45
100
  versionAliases: {
46
- 'kimi-k2-0711-preview': 'kimi-k2.5',
47
- 'kimi-k2-0905-preview': 'kimi-k2.5',
48
- 'kimi-k2-turbo-preview': 'kimi-k2.5',
49
- 'kimi-k2-thinking': 'kimi-k2.5',
50
- 'kimi-k2-thinking-turbo': 'kimi-k2.5'
101
+ 'kimi-k2-0711-preview': 'kimi-k2.6',
102
+ 'kimi-k2-0905-preview': 'kimi-k2.6',
103
+ 'kimi-k2-turbo-preview': 'kimi-k2.6',
104
+ 'kimi-k2-thinking': 'kimi-k2.6',
105
+ 'kimi-k2-thinking-turbo': 'kimi-k2.6',
106
+ 'kimi-k2.5': 'kimi-k2.6',
51
107
  },
52
108
  authTokenFormat: 'sk-...',
53
109
  description: 'Moonshot AI - Provides Anthropic-compatible API',
@@ -55,8 +111,12 @@ const providers = {
55
111
  compatibility: 'anthropic-compatible',
56
112
  envVars: {
57
113
  API_TIMEOUT_MS: '3000000',
58
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
114
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
115
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
116
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
117
+ CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK: '1'
59
118
  },
119
+ modelEnvTemplate: makeFastMapTemplate({"kimi-k2.6":"kimi-k2-thinking-turbo","kimi-k2-thinking":"kimi-k2-thinking-turbo"}),
60
120
  note: 'Requires extended timeout for large responses'
61
121
  },
62
122
  kimi_for_coding: {
@@ -71,8 +131,12 @@ const providers = {
71
131
  compatibility: 'anthropic-compatible',
72
132
  envVars: {
73
133
  API_TIMEOUT_MS: '3000000',
74
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
134
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
135
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
136
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
137
+ CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK: '1'
75
138
  },
139
+ modelEnvTemplate: makeSingleTemplate(),
76
140
  note: 'Requires extended timeout for large responses'
77
141
  },
78
142
  minimax_cn: {
@@ -80,8 +144,12 @@ const providers = {
80
144
  baseUrl: 'https://api.minimaxi.com/anthropic',
81
145
  models: [
82
146
  'MiniMax-M2.7',
147
+ 'MiniMax-M2.7-highspeed',
83
148
  'MiniMax-M2.5',
84
- 'MiniMax-M2.1'
149
+ 'MiniMax-M2.5-highspeed',
150
+ 'MiniMax-M2.1',
151
+ 'MiniMax-M2.1-highspeed',
152
+ 'MiniMax-M2',
85
153
  ],
86
154
  versionAliases: {
87
155
  'MiniMax-M2.1': 'MiniMax-M2.7',
@@ -93,8 +161,12 @@ const providers = {
93
161
  compatibility: 'anthropic-compatible',
94
162
  envVars: {
95
163
  API_TIMEOUT_MS: '3000000',
96
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
164
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
165
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
166
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
167
+ CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK: '1'
97
168
  },
169
+ modelEnvTemplate: makeFastMapTemplate({"MiniMax-M2.7":"MiniMax-M2.7-highspeed","MiniMax-M2.5":"MiniMax-M2.5-highspeed","MiniMax-M2.1":"MiniMax-M2.1-highspeed"}),
98
170
  note: 'Requires extended timeout for large responses'
99
171
  },
100
172
  minimax_global: {
@@ -102,8 +174,12 @@ const providers = {
102
174
  baseUrl: 'https://api.minimax.io/anthropic',
103
175
  models: [
104
176
  'MiniMax-M2.7',
177
+ 'MiniMax-M2.7-highspeed',
105
178
  'MiniMax-M2.5',
106
- 'MiniMax-M2.1'
179
+ 'MiniMax-M2.5-highspeed',
180
+ 'MiniMax-M2.1',
181
+ 'MiniMax-M2.1-highspeed',
182
+ 'MiniMax-M2',
107
183
  ],
108
184
  versionAliases: {
109
185
  'MiniMax-M2.1': 'MiniMax-M2.7',
@@ -115,26 +191,41 @@ const providers = {
115
191
  compatibility: 'anthropic-compatible',
116
192
  envVars: {
117
193
  API_TIMEOUT_MS: '3000000',
118
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
194
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
195
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
196
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
197
+ CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK: '1'
119
198
  },
199
+ modelEnvTemplate: makeFastMapTemplate({"MiniMax-M2.7":"MiniMax-M2.7-highspeed","MiniMax-M2.5":"MiniMax-M2.5-highspeed","MiniMax-M2.1":"MiniMax-M2.1-highspeed"}),
120
200
  note: 'Requires extended timeout for large responses'
121
201
  },
122
202
  deepseek: {
123
- name: 'DeepSeek (DeepSeek V3/V3.1)',
203
+ name: 'DeepSeek (V4-Pro/V4-Flash)',
124
204
  baseUrl: 'https://api.deepseek.com/anthropic',
125
205
  models: [
206
+ 'deepseek-v4-pro[1m]',
207
+ 'deepseek-v4-flash[1m]',
126
208
  'deepseek-chat',
127
- 'deepseek-reasoner'
209
+ 'deepseek-reasoner',
128
210
  ],
211
+ versionAliases: {
212
+ 'deepseek-chat': 'deepseek-v4-flash[1m]',
213
+ 'deepseek-reasoner': 'deepseek-v4-pro[1m]',
214
+ },
129
215
  authTokenFormat: 'sk-...',
130
216
  description: 'DeepSeek AI - Anthropic-compatible endpoint',
131
217
  requiresToken: true,
132
218
  compatibility: 'anthropic-compatible',
133
219
  envVars: {
134
220
  API_TIMEOUT_MS: '600000',
135
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
221
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
222
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
223
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
224
+ CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK: '1',
225
+ CLAUDE_CODE_EFFORT_LEVEL: 'max',
136
226
  },
137
- note: 'Requires extended timeout for complex reasoning tasks'
227
+ modelEnvTemplate: makeFastMapTemplate({"deepseek-v4-pro[1m]":"deepseek-v4-flash[1m]"}),
228
+ note: 'Requires extended timeout for complex reasoning tasks',
138
229
  },
139
230
  zhipu: {
140
231
  name: 'ZhiPu AI (GLM-5.1/5-Turbo/5/4.7) - 智谱清言',
@@ -158,8 +249,12 @@ const providers = {
158
249
  compatibility: 'anthropic-compatible',
159
250
  envVars: {
160
251
  API_TIMEOUT_MS: '3000000',
161
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
252
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
253
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
254
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
255
+ CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK: '1'
162
256
  },
257
+ modelEnvTemplate: makeFastMapTemplate({"glm-5.1":"glm-5-turbo"}),
163
258
  note: 'Requires extended timeout for large responses'
164
259
  },
165
260
  zai: {
@@ -184,8 +279,12 @@ const providers = {
184
279
  compatibility: 'anthropic-compatible',
185
280
  envVars: {
186
281
  API_TIMEOUT_MS: '3000000',
187
- CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1'
282
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1',
283
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
284
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
285
+ CLAUDE_CODE_DISABLE_NONSTREAMING_FALLBACK: '1'
188
286
  },
287
+ modelEnvTemplate: makeFastMapTemplate({"glm-5.1":"glm-5-turbo"}),
189
288
  note: 'Requires extended timeout for large responses'
190
289
  },
191
290
  custom: {
@@ -198,6 +297,11 @@ const providers = {
198
297
  description: 'Custom server with Anthropic-compatible API',
199
298
  requiresToken: true,
200
299
  compatibility: 'anthropic-compatible',
300
+ envVars: {
301
+ CLAUDE_CODE_ATTRIBUTION_HEADER: '0',
302
+ CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: '1',
303
+ },
304
+ modelEnvTemplate: makeSingleTemplate(),
201
305
  note: 'Replace URL and model with your actual server details'
202
306
  }
203
307
  };