feat: 更新版本至 0.0.96,重构claude命令,新增opencode模型切换功能
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kevisual/cli",
|
||||
"version": "0.0.95",
|
||||
"version": "0.0.96",
|
||||
"description": "envision 命令行工具",
|
||||
"type": "module",
|
||||
"basename": "/root/cli",
|
||||
|
||||
148
src/command/coding-plan/oc.ts
Normal file
148
src/command/coding-plan/oc.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import { program, Command } from '@/program.ts';
|
||||
import { chalk } from '../../module/chalk.ts';
|
||||
import path from 'node:path';
|
||||
import os from 'node:os';
|
||||
import fs from 'node:fs';
|
||||
import { select } from '@inquirer/prompts';
|
||||
|
||||
type ProviderConfig = {
|
||||
npm: string;
|
||||
name: string;
|
||||
models: Record<string, { name: string }>;
|
||||
options?: {
|
||||
baseURL?: string;
|
||||
apiKey?: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
};
|
||||
|
||||
type OpencodeConfig = {
|
||||
$schema?: string;
|
||||
autoshare?: boolean;
|
||||
share?: string;
|
||||
autoupdate?: boolean;
|
||||
permission?: string;
|
||||
model?: string;
|
||||
watcher?: {
|
||||
ignore?: string[];
|
||||
};
|
||||
plugin?: string[];
|
||||
provider?: Record<string, ProviderConfig>;
|
||||
};
|
||||
|
||||
/**
|
||||
* 读取 opencode 配置文件
|
||||
*/
|
||||
const readOpencodeConfig = (configPath: string): OpencodeConfig => {
|
||||
if (fs.existsSync(configPath)) {
|
||||
const content = fs.readFileSync(configPath, 'utf-8');
|
||||
try {
|
||||
return JSON.parse(content);
|
||||
} catch {
|
||||
return { provider: {} };
|
||||
}
|
||||
}
|
||||
return { provider: {} };
|
||||
};
|
||||
|
||||
/**
|
||||
* 保存 opencode 配置文件
|
||||
*/
|
||||
const saveOpencodeConfig = (configPath: string, config: OpencodeConfig) => {
|
||||
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
||||
};
|
||||
|
||||
/**
|
||||
* 从 provider 配置中提取所有可用的模型
|
||||
*/
|
||||
const extractAvailableModels = (config: OpencodeConfig): Array<{ name: string; provider: string; model: string; label: string }> => {
|
||||
const models: Array<{ name: string; provider: string; model: string; label: string }> = [];
|
||||
const providers = config.provider || {};
|
||||
|
||||
for (const [providerKey, providerConfig] of Object.entries(providers)) {
|
||||
const providerModels = providerConfig.models || {};
|
||||
for (const [modelKey] of Object.entries(providerModels)) {
|
||||
models.push({
|
||||
name: providerConfig.name,
|
||||
provider: providerKey,
|
||||
model: modelKey,
|
||||
label: `${providerKey}/${modelKey}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return models;
|
||||
};
|
||||
|
||||
export const command = new Command('oc')
|
||||
.description('切换 opencode 模型,从配置的 provider 中选择')
|
||||
.option('-m, --model <model:string>', '选择模型 (格式: provider/model)')
|
||||
.action(async (options) => {
|
||||
const configPath = path.join(os.homedir(), '.config', 'opencode', 'opencode.json');
|
||||
|
||||
// 读取配置
|
||||
const config = readOpencodeConfig(configPath);
|
||||
|
||||
// 提取可用的模型
|
||||
const availableModels = extractAvailableModels(config);
|
||||
|
||||
if (availableModels.length === 0) {
|
||||
console.log(chalk.red('没有找到可用的模型配置,请检查 opencode.json 中的 provider 配置'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果没有指定模型,使用 select 选择
|
||||
let selectedModel: string;
|
||||
if (options.model) {
|
||||
selectedModel = options.model;
|
||||
} else {
|
||||
selectedModel = await select({
|
||||
message: '请选择模型:',
|
||||
choices: availableModels.map((m) => ({
|
||||
name: `${m.name} - ${m.model}`,
|
||||
value: m.label,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
// 验证选择的模型是否有效
|
||||
const validModel = availableModels.find((m) => m.label === selectedModel);
|
||||
if (!validModel) {
|
||||
console.log(chalk.red(`无效的模型选择: ${selectedModel}`));
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新配置
|
||||
config.model = selectedModel;
|
||||
saveOpencodeConfig(configPath, config);
|
||||
|
||||
console.log(`已切换到模型: ${chalk.green(selectedModel)}`);
|
||||
console.log(`提供商: ${chalk.cyan(validModel.name)}`);
|
||||
console.log(`配置已保存到: ${configPath}`);
|
||||
});
|
||||
|
||||
// show 子命令:显示当前配置的 model
|
||||
export const showCommand = new Command('show')
|
||||
.description('显示当前 opencode 配置的 model')
|
||||
.action(() => {
|
||||
const configPath = path.join(os.homedir(), '.config', 'opencode', 'opencode.json');
|
||||
const config = readOpencodeConfig(configPath);
|
||||
|
||||
if (!config.model) {
|
||||
console.log(chalk.yellow('当前没有配置 model'));
|
||||
return;
|
||||
}
|
||||
|
||||
const availableModels = extractAvailableModels(config);
|
||||
const currentModel = availableModels.find((m) => m.label === config.model);
|
||||
|
||||
console.log(chalk.bold('当前 opencode 配置:'));
|
||||
console.log(`模型: ${chalk.green(config.model)}`);
|
||||
if (currentModel) {
|
||||
console.log(`提供商: ${chalk.cyan(currentModel.name)}`);
|
||||
}
|
||||
console.log(`配置文件: ${configPath}`);
|
||||
});
|
||||
|
||||
command.addCommand(showCommand);
|
||||
program.addCommand(command);
|
||||
@@ -17,7 +17,8 @@ import './command/gist/index.ts';
|
||||
import './command/config-remote.ts';
|
||||
import './command/config-secret-remote.ts';
|
||||
import './command/ai.ts';
|
||||
import './command/claude/cc.ts'
|
||||
import './command/coding-plan/cc.ts'
|
||||
import './command/coding-plan/oc.ts'
|
||||
import './command/docker.ts';
|
||||
import './command/jwks.ts';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user