feat: restructure command for Claude models and add new remote routes

- Deleted the old cc.ts command and created a new cc.ts under src/command/claude for better organization.
- Added support for a new model 'bailian' in the command.
- Implemented remote app connection status and connection routes in assistant/src/routes/remote/index.ts.
- Updated index.ts to reflect the new path for the cc command.
- Added a placeholder for future management of plugin operations in src/command/opencode/plugin.ts.
This commit is contained in:
2026-01-21 23:22:58 +08:00
parent a911334459
commit 028a6ac726
15 changed files with 469 additions and 276 deletions

150
src/command/claude/cc.ts Normal file
View File

@@ -0,0 +1,150 @@
import { program, Command } from '@/program.ts';
import { chalk } from '../../module/chalk.ts';
import path from 'node:path';
import { spawn } from 'node:child_process';
import { useKey } from '@kevisual/use-config';
import os from 'node:os'
import fs from 'node:fs';
import { select } from '@inquirer/prompts';
const MODELS = ['minimax', 'glm', 'volcengine', 'bailian'] as const;
type Model = typeof MODELS[number];
const changeMinimax = (token?: string) => {
const auth_token = token || useKey("MINIMAX_API_KEY")
return {
"env": {
"ANTHROPIC_AUTH_TOKEN": auth_token,
"ANTHROPIC_BASE_URL": "https://api.minimaxi.com/anthropic",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "MiniMax-M2.1",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "MiniMax-M2.1",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "MiniMax-M2.1",
"ANTHROPIC_MODEL": "MiniMax-M2.1",
"API_TIMEOUT_MS": "3000000",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": 1
}
}
}
const changeGLM = (token?: string) => {
const auth_token = token || useKey('ZHIPU_API_KEY')
return {
"env": {
"ANTHROPIC_AUTH_TOKEN": auth_token,
"ANTHROPIC_BASE_URL": "https://open.bigmodel.cn/api/anthropic",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.7",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-4.7",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-4.7",
"ANTHROPIC_MODEL": "glm-4.7"
}
}
}
const changeVolcengine = (token?: string) => {
const auth_token = token || useKey('VOLCENGINE_API_KEY')
return {
"env": {
"ANTHROPIC_AUTH_TOKEN": auth_token,
"ANTHROPIC_BASE_URL": "https://ark.cn-beijing.volces.com/api/coding",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "ark-code-latest",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "ark-code-latest",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "ark-code-latest",
"ANTHROPIC_MODEL": "ark-code-latest",
"API_TIMEOUT_MS": "3000000"
}
}
}
const changeBailian = (token?: string) => {
const auth_token = token || useKey('BAILIAN_API_KEY')
return {
"env": {
"ANTHROPIC_AUTH_TOKEN": auth_token,
"ANTHROPIC_BASE_URL": "https://coding.dashscope.aliyuncs.com/apps/anthropic",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "qwen3-coder-plus",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "qwen3-coder-plus",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "qwen3-coder-plus",
"ANTHROPIC_MODEL": "qwen3-coder-plus"
},
"includeCoAuthoredBy": false
}
}
/**
* 跳过登录检查,在~/.claude.json的配置中添加字段 "hasCompletedOnboarding": true
*/
const changeNoCheck = () => {
const homeDir = os.homedir();
const claudeConfigPath = path.join(homeDir, '.claude.json');
let claudeConfig = {};
if (fs.existsSync(claudeConfigPath)) {
const content = fs.readFileSync(claudeConfigPath, 'utf-8');
try {
claudeConfig = JSON.parse(content);
} catch {
claudeConfig = {};
}
}
claudeConfig = {
...claudeConfig,
hasCompletedOnboarding: true
};
fs.writeFileSync(claudeConfigPath, JSON.stringify(claudeConfig, null, 2));
}
const modelConfig: Record<Model, (token?: string) => object> = {
minimax: changeMinimax,
glm: changeGLM,
volcengine: changeVolcengine,
bailian: changeBailian,
};
const readOrCreateConfig = (configPath: string): Record<string, unknown> => {
if (fs.existsSync(configPath)) {
const content = fs.readFileSync(configPath, 'utf-8');
try {
return JSON.parse(content);
} catch {
return {};
}
}
return {};
};
const saveConfig = (configPath: string, config: Record<string, unknown>) => {
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
};
export const command = new Command('cc')
.description('切换claude code模型支持GLM4.7、Minimax和豆包')
.option('-m, --models <model:string>', `选择模型: ${MODELS.join(' | ')}`)
.action(async (options) => {
const configPath = path.join(os.homedir(), '.claude/settings.json');
// 读取或创建配置
const config = readOrCreateConfig(configPath);
// 如果没有指定模型,使用 inquire 选择
let selectedModel: Model;
if (options.models && MODELS.includes(options.models as Model)) {
selectedModel = options.models as Model;
} else {
selectedModel = await select({
message: '请选择模型:',
choices: MODELS,
});
}
// 更新配置
const updateConfig = modelConfig[selectedModel]();
Object.assign(config, updateConfig);
// 保存配置
saveConfig(configPath, config);
changeNoCheck();
console.log(`已切换到模型: ${chalk.green(selectedModel)}`);
console.log(`配置已保存到: ${configPath}`);
});
program.addCommand(command)