@dedenlabs/claude-code-router-cli 2.0.5 → 2.0.6-beta.1

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/README.md CHANGED
@@ -112,6 +112,35 @@ ccr start
112
112
  ccr start -b
113
113
  ```
114
114
 
115
+ **修改配置文件:**
116
+
117
+ 启动服务后会创建默认配置,您可以通过两种方式修改:
118
+
119
+ 1. **手动编辑**:修改 `~/.claude-code-router/config.json` 配置文件
120
+ 2. **可视化界面**:访问 http://localhost:3456/ui/ 实时编辑路由规则和替换密钥
121
+
122
+ 推荐使用模型替换规则,只需修改路由映射,所有IDE工具无需改动:
123
+
124
+ ```json
125
+ {
126
+ "Router": {
127
+ "rules": [
128
+ {
129
+ "name": "haiku模型替换规则",
130
+ "condition": {
131
+ "type": "modelContains",
132
+ "value": "haiku"
133
+ },
134
+ "action": {
135
+ "route": "haiku-XXX"
136
+ },
137
+ "priority": 205
138
+ }
139
+ ]
140
+ }
141
+ }
142
+ ```
143
+
115
144
  **配置 Claude 环境变量:**
116
145
  ```bash
117
146
  # 编辑 Claude 配置文件
@@ -124,9 +153,9 @@ ccr start -b
124
153
  "ANTHROPIC_AUTH_TOKEN": "sk-anything",
125
154
  "API_TIMEOUT_MS": "3000000",
126
155
  "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
127
- "ANTHROPIC_DEFAULT_HAIKU_MODEL": "haiku-glm",
128
- "ANTHROPIC_DEFAULT_SONNET_MODEL": "sonnet-minimax",
129
- "ANTHROPIC_DEFAULT_OPUS_MODEL": "opus-minimax"
156
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL": "haiku",
157
+ "ANTHROPIC_DEFAULT_SONNET_MODEL": "sonnet",
158
+ "ANTHROPIC_DEFAULT_OPUS_MODEL": "opus"
130
159
  },
131
160
  "model": "sonnet"
132
161
  }
@@ -319,6 +348,49 @@ function isBusinessHours(context) {
319
348
  "engine": "unified",
320
349
  "defaultRoute": "sonnet-minimax",
321
350
  "rules": [
351
+ {
352
+ "name": "haiku模型替换规则",
353
+ "condition": {
354
+ "type": "modelContains",
355
+ "value": "haiku",
356
+ "operator": "contains"
357
+ },
358
+ "action": {
359
+ "route": "haiku-minimax",
360
+ "description": "模型替换任意模型规则"
361
+ },
362
+ "priority": 205,
363
+ "enabled": true
364
+ },
365
+ {
366
+ "name": "sonnet模型替换规则",
367
+ "condition": {
368
+ "type": "modelContains",
369
+ "value": "sonnet",
370
+ "operator": "contains"
371
+ },
372
+ "action": {
373
+ "route": "sonnet-minimax",
374
+ "description": "模型替换任意模型规则"
375
+ },
376
+ "priority": 205,
377
+ "enabled": true
378
+ },
379
+ {
380
+ "name": "opus模型替换规则",
381
+ "condition": {
382
+ "type": "modelContains",
383
+ "value": "opus",
384
+ "operator": "contains"
385
+ },
386
+ "action": {
387
+ "route": "opus-minimax",
388
+ "description": "模型替换任意模型规则"
389
+ },
390
+ "priority": 205,
391
+ "enabled": true
392
+ },
393
+ //---------以下规则不是必须的-----------
322
394
  {
323
395
  "name": "用户指定规则",
324
396
  "priority": 200,
package/dist/cli.js CHANGED
@@ -67706,7 +67706,7 @@ var require_package3 = __commonJS({
67706
67706
  "package.json"(exports2, module2) {
67707
67707
  module2.exports = {
67708
67708
  name: "@dedenlabs/claude-code-router-cli",
67709
- version: "2.0.4",
67709
+ version: "2.0.6-beta.1",
67710
67710
  description: "\u57FA\u4E8E@musistudio/claude-code-router\u7684\u589E\u5F3A\u7248CLI\u8DEF\u7531\u5DE5\u5177 - \u652F\u6301\u7EDF\u4E00\u8DEF\u7531\u5F15\u64CE\u3001\u5916\u90E8\u89C4\u5219\u52A0\u8F7D\u3001\u667A\u80FD\u65E5\u5FD7\u7CFB\u7EDF\u3001\u81EA\u52A8\u914D\u7F6E\u8FC1\u79FB\u548CGLM\u601D\u8003\u6A21\u5F0F",
67711
67711
  bin: {
67712
67712
  ccr: "dist/cli.js"
@@ -70984,7 +70984,7 @@ var DEFAULT_CONFIG = {
70984
70984
  "api_base_url": "https://open.bigmodel.cn/api/anthropic/v1/messages",
70985
70985
  "api_key": "YOUR_GLM_API_KEY",
70986
70986
  "models": [
70987
- "glm-4.6"
70987
+ "glm-4.7"
70988
70988
  ],
70989
70989
  "transformer": {
70990
70990
  "use": [
@@ -70997,7 +70997,7 @@ var DEFAULT_CONFIG = {
70997
70997
  "api_base_url": "https://open.bigmodel.cn/api/anthropic/v1/messages",
70998
70998
  "api_key": "YOUR_GLM_API_KEY",
70999
70999
  "models": [
71000
- "glm-4.6"
71000
+ "glm-4.7"
71001
71001
  ],
71002
71002
  "transformer": {
71003
71003
  "use": [
@@ -71010,7 +71010,7 @@ var DEFAULT_CONFIG = {
71010
71010
  "api_base_url": "https://api.z.ai/api/coding/paas/v4/chat/completions",
71011
71011
  "api_key": "YOUR_GLM_API_KEY",
71012
71012
  "models": [
71013
- "glm-4.6"
71013
+ "glm-4.7"
71014
71014
  ],
71015
71015
  "transformer": {
71016
71016
  "use": [
@@ -71038,6 +71038,48 @@ var DEFAULT_CONFIG = {
71038
71038
  "engine": "unified",
71039
71039
  "defaultRoute": "sonnet",
71040
71040
  "rules": [
71041
+ {
71042
+ "name": "haiku\u6A21\u578B\u66FF\u6362\u89C4\u5219",
71043
+ "condition": {
71044
+ "type": "modelContains",
71045
+ "value": "haiku",
71046
+ "operator": "contains"
71047
+ },
71048
+ "action": {
71049
+ "route": "haiku-minimax",
71050
+ "description": "\u6A21\u578B\u66FF\u6362\u4EFB\u610F\u6A21\u578B\u89C4\u5219"
71051
+ },
71052
+ "priority": 205,
71053
+ "enabled": true
71054
+ },
71055
+ {
71056
+ "name": "sonnet\u6A21\u578B\u66FF\u6362\u89C4\u5219",
71057
+ "condition": {
71058
+ "type": "modelContains",
71059
+ "value": "sonnet",
71060
+ "operator": "contains"
71061
+ },
71062
+ "action": {
71063
+ "route": "sonnet-minimax",
71064
+ "description": "\u6A21\u578B\u66FF\u6362\u4EFB\u610F\u6A21\u578B\u89C4\u5219"
71065
+ },
71066
+ "priority": 205,
71067
+ "enabled": true
71068
+ },
71069
+ {
71070
+ "name": "opus\u6A21\u578B\u66FF\u6362\u89C4\u5219",
71071
+ "condition": {
71072
+ "type": "modelContains",
71073
+ "value": "opus",
71074
+ "operator": "contains"
71075
+ },
71076
+ "action": {
71077
+ "route": "opus-minimax",
71078
+ "description": "\u6A21\u578B\u66FF\u6362\u4EFB\u610F\u6A21\u578B\u89C4\u5219"
71079
+ },
71080
+ "priority": 205,
71081
+ "enabled": true
71082
+ },
71041
71083
  {
71042
71084
  "name": "\u7528\u6237\u6307\u5B9A\u89C4\u5219",
71043
71085
  "condition": {
@@ -84710,7 +84752,10 @@ var UnifiedRouter = class {
84710
84752
  } else {
84711
84753
  const requestedModel2 = req.body?.model;
84712
84754
  if (matchResult.matched && matchResult.ruleName === "directMapping" && requestedModel2 && !requestedModel2.includes(",")) {
84713
- const mappedRoute = this.mapDirectModelToProvider(requestedModel2, req);
84755
+ const mappedRoute = this.mapDirectModelToProvider(
84756
+ requestedModel2,
84757
+ req
84758
+ );
84714
84759
  if (mappedRoute) {
84715
84760
  finalRoute = mappedRoute;
84716
84761
  if (mappedRoute === this.config.defaultRoute) {
@@ -84724,6 +84769,7 @@ var UnifiedRouter = class {
84724
84769
  }
84725
84770
  }
84726
84771
  }
84772
+ finalRoute = this.resolveProviderModel(finalRoute, req, context, true);
84727
84773
  const cacheKey = this.generateCacheKey(req, tokenCount, finalRoute);
84728
84774
  var result;
84729
84775
  if (this.config.cache?.enabled !== false) {
@@ -85163,61 +85209,95 @@ ${allLines[totalLines - 1] || ""}`
85163
85209
  this.logger.debug("${subagent} \u53D8\u91CF\u66FF\u6362\u5931\u8D25\uFF0C\u4FDD\u6301\u539F\u6837");
85164
85210
  return processedRoute;
85165
85211
  }
85166
- this.logger.warn(`\u53D8\u91CF\u66FF\u6362\u672A\u5B8C\u6210\uFF0C\u4ECD\u5305\u542B\u672A\u66FF\u6362\u7684\u53D8\u91CF: ${processedRoute}\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u8DEF\u7531`);
85212
+ this.logger.warn(
85213
+ `\u53D8\u91CF\u66FF\u6362\u672A\u5B8C\u6210\uFF0C\u4ECD\u5305\u542B\u672A\u66FF\u6362\u7684\u53D8\u91CF: ${processedRoute}\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u8DEF\u7531`
85214
+ );
85167
85215
  return this.config.defaultRoute;
85168
85216
  }
85169
85217
  return processedRoute;
85170
85218
  }
85171
85219
  /**
85172
- * 将provider作为代号,映射到对应的model模型
85220
+ * 将provider名称或模型名称转换为完整的 "provider,model" 路由格式
85221
+ *
85222
+ * 支持两种输入模式:
85223
+ * 1. 模型名映射:如 "claude-3.5-sonnet" → "openrouter,claude-3.5-sonnet"
85224
+ * 2. Provider名称补全:如 "haiku-glm" → "haiku-glm,glm-4.7"
85225
+ *
85226
+ * @param input - 模型名称或provider名称
85227
+ * @param req - 请求对象,包含config.Providers配置
85228
+ * @param context - 路由上下文(可选)
85229
+ * @param fallbackToInput - 失败时是否返回原输入(用于规则路由),默认false
85230
+ * @returns 完整的 "provider,model" 路由,或null表示无法映射
85173
85231
  */
85174
- mapDirectModelToProvider(modelName, req) {
85232
+ resolveProviderModel(input, req, context, fallbackToInput = false) {
85233
+ if (input.includes(",")) {
85234
+ return input;
85235
+ }
85175
85236
  const providers = req.config?.Providers || [];
85176
- this.logger.debug("\u5C1D\u8BD5\u4EE3\u53F7\u6A21\u578B\u6620\u5C04", {
85177
- modelName,
85237
+ this.logger.debug("\u5C1D\u8BD5provider\u6A21\u578B\u89E3\u6790", {
85238
+ input,
85178
85239
  providersCount: providers.length
85179
85240
  });
85180
85241
  for (const provider of providers) {
85181
85242
  if (provider.models && Array.isArray(provider.models)) {
85182
- if (provider.models.includes(modelName)) {
85183
- const mappedRoute = `${provider.name},${provider.models[0]}`;
85243
+ if (provider.models.includes(input)) {
85244
+ const route = `${provider.name},${provider.models[0]}`;
85184
85245
  this.logger.info("\u2713 \u6A21\u578B\u540D\u5339\u914D", {
85185
- request: modelName,
85186
- route: mappedRoute
85246
+ request: input,
85247
+ route
85187
85248
  });
85188
- return mappedRoute;
85249
+ return route;
85189
85250
  }
85190
85251
  }
85191
- if (provider.model === modelName) {
85192
- const mappedRoute = `${provider.name},${provider.model}`;
85252
+ if (provider.model === input) {
85253
+ const route = `${provider.name},${provider.model}`;
85193
85254
  this.logger.info("\u2713 \u6A21\u578B\u540D\u5339\u914D", {
85194
- request: modelName,
85195
- route: mappedRoute
85255
+ request: input,
85256
+ route
85196
85257
  });
85197
- return mappedRoute;
85258
+ return route;
85198
85259
  }
85199
85260
  }
85200
- this.logger.debug("\u672A\u627E\u5230\u4EE3\u53F7\u6A21\u578B\u6620\u5C04\uFF0C\u5C1D\u8BD5\u901A\u8FC7 provider \u540D\u79F0\u5339\u914D", {
85201
- modelName
85202
- });
85261
+ this.logger.debug("\u672A\u627E\u5230\u6A21\u578B\u540D\uFF0C\u5C1D\u8BD5\u4F5C\u4E3Aprovider\u540D\u79F0\u5339\u914D", { input });
85203
85262
  const matchedProvider = providers.find(
85204
- (p) => p.name.toLowerCase() === modelName.toLowerCase()
85263
+ (p) => p.name.toLowerCase() === input.toLowerCase()
85205
85264
  );
85206
- if (matchedProvider) {
85207
- const defaultModel = matchedProvider.models?.[0] || matchedProvider.model;
85208
- if (defaultModel) {
85209
- const mappedRoute = `${matchedProvider.name},${defaultModel}`;
85210
- return mappedRoute;
85211
- } else {
85212
- this.logger.error(`Provider '${matchedProvider.name}' \u6CA1\u6709\u914D\u7F6E\u6A21\u578B\uFF01`, {
85213
- providerName: matchedProvider.name
85214
- });
85215
- return null;
85265
+ if (!matchedProvider) {
85266
+ this.logger.debug(`\u672A\u627E\u5230provider '${input}' \u7684\u914D\u7F6E`);
85267
+ if (fallbackToInput) {
85268
+ this.logger.debug(`fallback\u6A21\u5F0F\uFF1A\u4FDD\u6301\u539F\u6837\u8FD4\u56DE ${input}`);
85269
+ return input;
85216
85270
  }
85271
+ return null;
85272
+ }
85273
+ let model;
85274
+ if (matchedProvider.defaultModel) {
85275
+ model = matchedProvider.defaultModel;
85276
+ this.logger.info(`\u2713 \u4F7F\u7528provider '${input}' \u7684\u9ED8\u8BA4\u6A21\u578B: ${model}`);
85277
+ } else if (matchedProvider.models && matchedProvider.models.length > 0) {
85278
+ model = matchedProvider.models[0];
85279
+ this.logger.info(`\u2713 \u4F7F\u7528provider '${input}' \u7684\u7B2C\u4E00\u4E2A\u6A21\u578B: ${model}`);
85280
+ } else if (matchedProvider.model) {
85281
+ model = matchedProvider.model;
85282
+ this.logger.info(`\u2713 \u4F7F\u7528provider '${input}' \u7684\u6A21\u578B: ${model}`);
85283
+ }
85284
+ if (model) {
85285
+ return `${matchedProvider.name},${model}`;
85286
+ }
85287
+ this.logger.error(`Provider '${input}' \u6CA1\u6709\u914D\u7F6E\u4EFB\u4F55\u6A21\u578B`);
85288
+ if (fallbackToInput) {
85289
+ this.logger.debug(`fallback\u6A21\u5F0F\uFF1A\u4FDD\u6301\u539F\u6837\u8FD4\u56DE ${input}`);
85290
+ return input;
85217
85291
  }
85218
- this.logger.debug(`\u672A\u627E\u5230\u6A21\u578B '${modelName}' \u7684\u6620\u5C04\uFF0C\u8FD4\u56DEnull`);
85219
85292
  return null;
85220
85293
  }
85294
+ /**
85295
+ * 将provider作为代号,映射到对应的model模型(旧方法别名)
85296
+ * @deprecated 使用 resolveProviderModel 替代
85297
+ */
85298
+ mapDirectModelToProvider(modelName, req) {
85299
+ return this.resolveProviderModel(modelName, req);
85300
+ }
85221
85301
  /**
85222
85302
  * 生成缓存键
85223
85303
  */
@@ -89595,7 +89675,10 @@ var AVAILABLE_TRANSFORMERS = [
89595
89675
  "rovo-cli"
89596
89676
  ];
89597
89677
  function getConfigPath() {
89598
- const configDir = path7.join(process.env.HOME || process.env.USERPROFILE || "", ".claude-code-router");
89678
+ const configDir = path7.join(
89679
+ process.env.HOME || process.env.USERPROFILE || "",
89680
+ ".claude-code-router"
89681
+ );
89599
89682
  const configPath = path7.join(configDir, "config.json");
89600
89683
  if (!fs6.existsSync(configPath)) {
89601
89684
  throw new Error(`config.json not found at ${configPath}`);
@@ -89629,11 +89712,15 @@ ${BOLDCYAN}Provider:${RESET} ${provider.name}`,
89629
89712
  return models;
89630
89713
  }
89631
89714
  function displayCurrentConfig(config) {
89632
- console.log(`
89633
- ${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550${RESET}`);
89715
+ console.log(
89716
+ `
89717
+ ${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550${RESET}`
89718
+ );
89634
89719
  console.log(`${BOLDCYAN} Current Configuration${RESET}`);
89635
- console.log(`${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550${RESET}
89636
- `);
89720
+ console.log(
89721
+ `${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550${RESET}
89722
+ `
89723
+ );
89637
89724
  const formatModel = (routerValue) => {
89638
89725
  if (!routerValue || typeof routerValue === "number") {
89639
89726
  return `${DIM}Not configured${RESET}`;
@@ -89670,11 +89757,15 @@ ${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2
89670
89757
  console.log(` ${formatModel(config.Router.image)}
89671
89758
  `);
89672
89759
  }
89673
- console.log(`
89674
- ${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550${RESET}`);
89760
+ console.log(
89761
+ `
89762
+ ${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550${RESET}`
89763
+ );
89675
89764
  console.log(`${BOLDCYAN} Add/Update Model${RESET}`);
89676
- console.log(`${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550${RESET}
89677
- `);
89765
+ console.log(
89766
+ `${BOLDCYAN}\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550${RESET}
89767
+ `
89768
+ );
89678
89769
  }
89679
89770
  async function selectModelType() {
89680
89771
  return await esm_default4({
@@ -89742,7 +89833,10 @@ ${BOLDYELLOW}Add provider routing options?${RESET}`,
89742
89833
  message: "Provider (e.g., moonshotai/fp8):",
89743
89834
  validate: (value) => value.trim() !== "" || "Provider cannot be empty"
89744
89835
  });
89745
- transformers.push(["openrouter", { provider: { only: [providerInput] } }]);
89836
+ transformers.push([
89837
+ "openrouter",
89838
+ { provider: { only: [providerInput] } }
89839
+ ]);
89746
89840
  } else {
89747
89841
  transformers.push(transformer);
89748
89842
  }
@@ -89762,7 +89856,10 @@ async function addNewModel(config) {
89762
89856
  name: p.name,
89763
89857
  value: p.name
89764
89858
  }));
89765
- providerChoices.push({ name: `${BOLDGREEN}+ Add New Provider${RESET}`, value: "__new__" });
89859
+ providerChoices.push({
89860
+ name: `${BOLDGREEN}+ Add New Provider${RESET}`,
89861
+ value: "__new__"
89862
+ });
89766
89863
  const selectedProvider = await esm_default4({
89767
89864
  message: `
89768
89865
  ${BOLDYELLOW}Select provider for the new model:${RESET}`,
@@ -89807,7 +89904,9 @@ ${BOLDYELLOW}Add model-specific transformer configuration?${RESET}`,
89807
89904
  }
89808
89905
  }
89809
89906
  saveConfig(config);
89810
- console.log(`${GREEN}\u2713 Model "${modelName}" added to provider "${providerName}"${RESET}`);
89907
+ console.log(
89908
+ `${GREEN}\u2713 Model "${modelName}" added to provider "${providerName}"${RESET}`
89909
+ );
89811
89910
  const setAsDefault = await esm_default2({
89812
89911
  message: `
89813
89912
  ${BOLDYELLOW}Do you want to set this model in router configuration?${RESET}`,
@@ -89894,8 +89993,10 @@ ${BOLDYELLOW}Model names (comma-separated):${RESET}`,
89894
89993
  }
89895
89994
  config.Providers.push(newProvider);
89896
89995
  saveConfig(config);
89897
- console.log(`${GREEN}
89898
- \u2713 Provider "${providerName}" added successfully${RESET}`);
89996
+ console.log(
89997
+ `${GREEN}
89998
+ \u2713 Provider "${providerName}" added successfully${RESET}`
89999
+ );
89899
90000
  const setAsDefault = await esm_default2({
89900
90001
  message: `
89901
90002
  ${BOLDYELLOW}Do you want to set one of these models in router configuration?${RESET}`,
@@ -89938,13 +90039,17 @@ async function runModelSelector() {
89938
90039
  config = loadConfig();
89939
90040
  config.Router[result.modelType] = `${result.providerName},${result.modelName}`;
89940
90041
  saveConfig(config);
89941
- console.log(`${GREEN}\u2713 ${result.modelType} set to ${result.providerName},${result.modelName}${RESET}`);
90042
+ console.log(
90043
+ `${GREEN}\u2713 ${result.modelType} set to ${result.providerName},${result.modelName}${RESET}`
90044
+ );
89942
90045
  }
89943
90046
  } else {
89944
90047
  const selectedModel = await selectModel(config, action);
89945
90048
  config.Router[action] = selectedModel;
89946
90049
  saveConfig(config);
89947
- console.log(`${GREEN}\u2713 ${action} model updated to: ${selectedModel}${RESET}`);
90050
+ console.log(
90051
+ `${GREEN}\u2713 ${action} model updated to: ${selectedModel}${RESET}`
90052
+ );
89948
90053
  }
89949
90054
  displayCurrentConfig(config);
89950
90055
  } catch (error) {
@@ -18,6 +18,48 @@
18
18
  }
19
19
  ],
20
20
  "Providers": [
21
+ {
22
+ "name": "haiku模型替换规则",
23
+ "condition": {
24
+ "type": "modelContains",
25
+ "value": "haiku",
26
+ "operator": "contains"
27
+ },
28
+ "action": {
29
+ "route": "haiku-minimax",
30
+ "description": "模型替换任意模型规则"
31
+ },
32
+ "priority": 205,
33
+ "enabled": true
34
+ },
35
+ {
36
+ "name": "sonnet模型替换规则",
37
+ "condition": {
38
+ "type": "modelContains",
39
+ "value": "sonnet",
40
+ "operator": "contains"
41
+ },
42
+ "action": {
43
+ "route": "sonnet-minimax",
44
+ "description": "模型替换任意模型规则"
45
+ },
46
+ "priority": 205,
47
+ "enabled": true
48
+ },
49
+ {
50
+ "name": "opus模型替换规则",
51
+ "condition": {
52
+ "type": "modelContains",
53
+ "value": "opus",
54
+ "operator": "contains"
55
+ },
56
+ "action": {
57
+ "route": "opus-minimax",
58
+ "description": "模型替换任意模型规则"
59
+ },
60
+ "priority": 205,
61
+ "enabled": true
62
+ },
21
63
  {
22
64
  "name": "haiku-minimax",
23
65
  "api_base_url": "https://api.minimaxi.com/anthropic/v1/messages",
@@ -242,4 +284,4 @@
242
284
  "OPENAI_API_KEY": "",
243
285
  "OPENAI_BASE_URL": "",
244
286
  "OPENAI_MODEL": ""
245
- }
287
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dedenlabs/claude-code-router-cli",
3
- "version": "2.0.5",
3
+ "version": "2.0.6-beta.1",
4
4
  "description": "基于@musistudio/claude-code-router的增强版CLI路由工具 - 支持统一路由引擎、外部规则加载、智能日志系统、自动配置迁移和GLM思考模式",
5
5
  "bin": {
6
6
  "ccr": "dist/cli.js"