@dashscope-js/claude-code-config
Version:
Default configuration for claude-code-router with DashScope support
290 lines (258 loc) • 9.97 kB
JavaScript
const fs = require("fs-extra");
const path = require("path");
const os = require("os");
const readline = require("readline");
class ClaudeCodeRouterConfig {
constructor() {
this.homeDir = os.homedir();
this.configDir = path.join(this.homeDir, ".claude-code-router");
this.configFile = path.join(this.configDir, "config.json");
this.pluginsDir = path.join(this.configDir, "plugins");
this.transformerFile = path.join(
this.pluginsDir,
"dashscope-transformer.js"
);
this.language = this.detectLanguage();
this.messages = this.getMessages();
}
detectLanguage() {
// 检测系统语言
const locale = process.env.LANG || process.env.LANGUAGE || process.env.LC_ALL || "en_US.UTF-8";
return locale.toLowerCase().includes('zh') ? 'zh' : 'en';
}
async promptForRegion() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
const askForRegion = () => {
const prompt = `${this.messages.regionPrompt}\n${this.messages.regionOption1}\n${this.messages.regionOption2}\n${this.messages.regionInput}`;
rl.question(prompt, (answer) => {
const choice = answer.trim();
if (choice === '1') {
console.log(this.messages.regionSelected1);
rl.close();
resolve('cn');
} else if (choice === '2') {
console.log(this.messages.regionSelected2);
rl.close();
resolve('intl');
} else {
console.log(this.messages.regionInvalid);
askForRegion();
}
});
};
askForRegion();
});
}
getApiBaseUrl(region) {
return region === 'intl'
? "https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions"
: "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
}
getMessages() {
const messages = {
zh: {
configuring: "🚀 正在配置 claude-code-router...",
envKeyDetected: "🔑 检测到环境变量 DASHSCOPE_API_KEY,将使用环境变量中的 API Key",
envKeyNotFound: "⚠️ 未检测到环境变量 DASHSCOPE_API_KEY,将使用默认配置",
configComplete: "✅ claude-code-router 配置完成!",
configLocation: "📁 配置文件位置:",
usage: "📝 使用说明:",
step1: "1. 请确保已安装 @anthropic-ai/claude-code",
step2: "2. 请确保已安装 @musistudio/claude-code-router",
step3Warning: "3. ⚠️ 请手动配置环境变量DASHSCOPE_API_KEY:",
step3Success: "3. ✅ API Key 已从环境变量自动配置",
regionPrompt: "请选择服务区域 (Please select service region):",
regionOption1: "1. 阿里云 (Alibaba Cloud China)",
regionOption2: "2. 阿里云国际站 (Alibaba Cloud International)",
regionInput: "请输入 1 或 2 (Enter 1 or 2): ",
regionSelected1: "✅ 已选择阿里云中国站",
regionSelected2: "✅ 已选择阿里云国际站",
regionInvalid: "❌ 请输入 1 或 2",
promptApiKey: "请输入您的 DashScope API Key:",
apiKeyPrompt: "DashScope API Key",
apiKeyConfigured: "✅ API Key 已配置完成",
invalidApiKey: "❌ API Key 不能为空,请重新输入",
step4: "4. 运行 ccr code 开始使用",
configFailed: "❌ 配置失败:",
createDir: "📁 创建目录:",
createConfig: "📄 创建配置文件:",
createPlugin: "🔧 创建插件文件:",
editConfigInstructions: [
` cd `,
` open config.json # macOS`,
` # 或者用你喜欢的编辑器打开 config.json`,
` # 将 "api_key" 字段替换为你的 DashScope API Key`
]
},
en: {
configuring: "🚀 Configuring claude-code-router...",
envKeyDetected: "🔑 DASHSCOPE_API_KEY environment variable detected, will use API Key from environment",
envKeyNotFound: "⚠️ DASHSCOPE_API_KEY environment variable not found, will use default configuration",
configComplete: "✅ claude-code-router configuration completed!",
configLocation: "📁 Configuration file location:",
usage: "📝 Usage instructions:",
step1: "1. Please ensure @anthropic-ai/claude-code is installed",
step2: "2. Please ensure @musistudio/claude-code-router is installed",
step3Warning: "3. ⚠️ Please manually set your DASHSCOPE_API_KEY environment variable:",
step3Success: "3. ✅ API Key automatically configured from environment variable",
regionPrompt: "Please select service region:",
regionOption1: "1. Alibaba Cloud China",
regionOption2: "2. Alibaba Cloud International",
regionInput: "Enter 1 or 2: ",
regionSelected1: "✅ Selected Alibaba Cloud China",
regionSelected2: "✅ Selected Alibaba Cloud International",
regionInvalid: "❌ Please enter 1 or 2",
promptApiKey: "Please enter your DashScope API Key:",
apiKeyPrompt: "DashScope API Key",
apiKeyConfigured: "✅ API Key configured successfully",
invalidApiKey: "❌ API Key cannot be empty, please try again",
step4: "4. Run ccr code to start using",
configFailed: "❌ Configuration failed:",
createDir: "📁 Creating directory:",
createConfig: "📄 Creating configuration file:",
createPlugin: "🔧 Creating plugin file:",
editConfigInstructions: [
` cd `,
` open config.json # macOS`,
` # Or open config.json with your preferred editor`,
` # Replace the "api_key" field with your DashScope API Key`
]
}
};
return messages[this.language];
}
async promptForApiKey() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve) => {
const askForKey = () => {
rl.question(`${this.messages.promptApiKey} `, (apiKey) => {
const trimmedKey = apiKey.trim();
if (trimmedKey) {
console.log(this.messages.apiKeyConfigured);
rl.close();
resolve(trimmedKey);
} else {
console.log(this.messages.invalidApiKey);
askForKey();
}
});
};
askForKey();
});
}
async setup() {
try {
console.log(this.messages.configuring);
// 询问用户选择服务区域
const region = await this.promptForRegion();
// 检查环境变量
let apiKey = process.env.DASHSCOPE_API_KEY;
const hasEnvApiKey = !!apiKey;
if (hasEnvApiKey) {
console.log(this.messages.envKeyDetected);
} else {
console.log(this.messages.envKeyNotFound);
// 提示用户输入 API Key
apiKey = await this.promptForApiKey();
}
// 创建配置目录
await this.createDirectories();
// 创建配置文件
await this.createConfigFile(apiKey, region);
// 创建插件文件
await this.createTransformerFile();
console.log(this.messages.configComplete);
console.log(this.messages.configLocation, this.configDir);
console.log("");
console.log(this.messages.usage);
console.log(this.messages.step1);
console.log(this.messages.step2);
console.log(this.messages.step3Success);
console.log(this.messages.step4);
} catch (error) {
console.error(this.messages.configFailed, error.message);
process.exit(1);
}
}
async createDirectories() {
// 创建主配置目录
await fs.ensureDir(this.configDir);
// 创建插件目录
await fs.ensureDir(this.pluginsDir);
console.log(this.messages.createDir, this.configDir);
}
async createConfigFile(apiKey, region) {
// 使用传入的 API Key(可能来自环境变量或用户输入)
const dashscopeApiKey = apiKey;
const apiBaseUrl = this.getApiBaseUrl(region);
const configContent = {
LOG: true,
OPENAI_API_KEY: "",
OPENAI_BASE_URL: "",
OPENAI_MODEL: "",
transformers: [
{
path: path.join(
this.configDir,
"plugins",
"dashscope-transformer.js"
),
options: {
enable_thinking: false,
stream: true,
},
},
],
Providers: [
{
name: "dashscope",
api_base_url: apiBaseUrl,
api_key: dashscopeApiKey,
models: ["qwen3-coder-plus"],
transformer: {
use: ["dashscope"],
},
},
],
Router: {
default: "dashscope,qwen3-coder-plus",
think: "dashscope,qwen3-coder-plus",
background: "dashscope,qwen3-coder-plus",
longContext: "dashscope,qwen3-coder-plus",
},
};
await fs.writeJson(this.configFile, configContent, { spaces: 2 });
console.log(this.messages.createConfig, this.configFile);
}
async createTransformerFile() {
const transformerContent = `class DashScopeTransformer {
name = "dashscope";
constructor(options) {
this.max_tokens = options.max_tokens || 8192;
this.enable_thinking = options.enable_thinking || false;
}
async transformRequestIn(request, provider) {
request.max_tokens = this.max_tokens;
request.enable_thinking = this.enable_thinking;
return request;
}
}
module.exports = DashScopeTransformer;`;
await fs.writeFile(this.transformerFile, transformerContent);
console.log(this.messages.createPlugin, this.transformerFile);
}
}
// 如果直接运行此脚本
if (require.main === module) {
const config = new ClaudeCodeRouterConfig();
config.setup();
}
module.exports = ClaudeCodeRouterConfig;