Skip to content

Commit

Permalink
♻️ refactor(commands): 重构命令处理逻辑并优化错误处理
Browse files Browse the repository at this point in the history
- 【基础】在 BaseCommand 中添加统一的错误处理方法 handleError
- 【重构】将模型选择器逻辑抽取到独立的 ModelPickerService 服务
- 【优化】重构 GenerateCommitCommand 中的配置处理逻辑,提取至独立方法
- 【改进】简化 SelectModelCommand 中的模型选择器实现
- 【错误处理】统一使用本地化的错误消息展示
  • Loading branch information
littleCareless committed Dec 10, 2024
1 parent fa072f1 commit d708190
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 147 deletions.
10 changes: 10 additions & 0 deletions src/commands/BaseCommand.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as vscode from "vscode";
import { NotificationHandler } from "../utils/NotificationHandler";
import { ConfigurationManager } from "../config/ConfigurationManager";
import { LocalizationManager } from '../utils/LocalizationManager'

export abstract class BaseCommand {
constructor(protected readonly context: vscode.ExtensionContext) {}
Expand All @@ -13,5 +14,14 @@ export abstract class BaseCommand {
return true;
}

protected async handleError(error: unknown, errorMessage: string): Promise<void> {
console.error(errorMessage, error);
if (error instanceof Error) {
await NotificationHandler.error(
LocalizationManager.getInstance().format(errorMessage, error.message)
);
}
}

abstract execute(...args: any[]): Promise<void>;
}
119 changes: 34 additions & 85 deletions src/commands/GenerateCommitCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getProviderModelConfig } from "../config/types";
import { DISPLAY_NAME } from "../constants";
import { getMaxCharacters } from "../ai/types";
import { LocalizationManager } from "../utils/LocalizationManager";
import { ModelPickerService } from "../services/ModelPickerService";

export class GenerateCommitCommand extends BaseCommand {
private async showConfigWizard(): Promise<boolean> {
Expand Down Expand Up @@ -135,12 +136,38 @@ export class GenerateCommitCommand extends BaseCommand {
return { provider: modelSelection.provider, model: modelSelection.model };
}

async execute(resources: vscode.SourceControlResourceState[]): Promise<void> {
const locManager = LocalizationManager.getInstance();
private async handleConfiguration(): Promise<
{ provider: string; model: string } | undefined
> {
if (!(await this.ensureConfiguration()) || !(await this.validateConfig())) {
return;
}

const config = ConfigurationManager.getInstance();
const configuration = config.getConfiguration();
let { provider, model } = configuration;

if (!provider || !model) {
const result = await this.selectAndUpdateModelConfiguration(
provider,
model
);
if (!result) {
return;
}
return result;
}

return { provider, model };
}

async execute(resources: vscode.SourceControlResourceState[]): Promise<void> {
const configResult = await this.handleConfiguration();
if (!configResult) {
return;
}

const locManager = LocalizationManager.getInstance();
try {
// 检测当前 SCM 类型
const scmProvider = await SCMFactory.detectSCM();
Expand All @@ -160,24 +187,6 @@ export class GenerateCommitCommand extends BaseCommand {

// 如果没有配置提供商或模型,提示用户选择
if (!provider || !model) {
// const modelSelection = await this.showModelPicker(
// provider || "Ollama",
// model || "Ollama"
// );

// if (!modelSelection) {
// return;
// }

// // 使用新的封装方法更新配置
// await config.updateAIConfiguration(
// modelSelection.provider,
// modelSelection.model
// );

// provider = modelSelection.provider;
// model = modelSelection.model;

const { provider: newProvider, model: newModel } =
await this.selectAndUpdateModelConfiguration(provider, model);

Expand Down Expand Up @@ -244,12 +253,13 @@ export class GenerateCommitCommand extends BaseCommand {
}
if (response?.content) {
try {
// 统一使用 setCommitInput 写入提交信息
await scmProvider.setCommitInput(response.content);
await NotificationHandler.info(
locManager.format(
"commit.message.generated",
scmProvider.type.toUpperCase()
scmProvider.type.toUpperCase(),
provider,
model
)
);
} catch (error) {
Expand Down Expand Up @@ -312,68 +322,7 @@ export class GenerateCommitCommand extends BaseCommand {
];
}

private async showModelPicker(
currentProvider: string,
currentModel: string
): Promise<{ provider: string; model: string } | undefined> {
const locManager = LocalizationManager.getInstance();
try {
const providers = AIProviderFactory.getAllProviders();
const modelsMap = new Map<string, string[]>();

await Promise.all(
providers.map(async (provider) => {
if (await provider.isAvailable()) {
const models = await provider.getModels();
modelsMap.set(
provider.getName(),
models.map((model) => model.name)
);
}
})
);

const items: vscode.QuickPickItem[] = [];
for (const [provider, models] of modelsMap) {
items.push({
label: provider,
kind: vscode.QuickPickItemKind.Separator,
});
models.forEach((model) => {
items.push({
label: model,
description: provider,
picked: provider === currentProvider && model === currentModel,
});
});
}

const quickPick = vscode.window.createQuickPick();
quickPick.items = items;
quickPick.title = locManager.getMessage("ai.model.picker.title");
quickPick.placeholder = locManager.getMessage(
"ai.model.picker.placeholder"
);
quickPick.ignoreFocusOut = true;

const result = await new Promise<vscode.QuickPickItem | undefined>(
(resolve) => {
quickPick.onDidAccept(() => resolve(quickPick.selectedItems[0]));
quickPick.onDidHide(() => resolve(undefined));
quickPick.show();
}
);

quickPick.dispose();

if (result && result.description) {
return { provider: result.description, model: result.label };
}
return undefined;
} catch (error) {
console.error("获取模型列表失败:", error);
await NotificationHandler.error("获取模型列表失败");
return undefined;
}
private async showModelPicker(currentProvider: string, currentModel: string) {
return ModelPickerService.showModelPicker(currentProvider, currentModel);
}
}
64 changes: 2 additions & 62 deletions src/commands/SelectModelCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { NotificationHandler } from "../utils/NotificationHandler";
import { AIProviderFactory } from "../ai/AIProviderFactory";
import { getProviderModelConfig } from "../config/types";
import { LocalizationManager } from "../utils/LocalizationManager";
import { ModelPickerService } from "../services/ModelPickerService";

export class SelectModelCommand extends BaseCommand {
async execute(): Promise<void> {
Expand All @@ -30,68 +31,7 @@ export class SelectModelCommand extends BaseCommand {
}
}

// 从原来的 CommandManager 移动过来的 showModelPicker 方法
private async showModelPicker(currentProvider: string, currentModel: string) {
try {
const providers = AIProviderFactory.getAllProviders();
const modelsMap = new Map<string, string[]>();

await Promise.all(
providers.map(async (provider) => {
if (await provider.isAvailable()) {
const models = await provider.getModels();
modelsMap.set(
provider.getName(),
models.map((model) => model.name)
);
}
})
);

const items: vscode.QuickPickItem[] = [];
for (const [provider, models] of modelsMap) {
items.push({
label: provider,
kind: vscode.QuickPickItemKind.Separator,
});
models.forEach((model) => {
items.push({
label: model,
description: provider,
picked: provider === currentProvider && model === currentModel,
});
});
}

const quickPick = vscode.window.createQuickPick();
quickPick.items = items;
quickPick.title =
LocalizationManager.getInstance().getMessage("model.picker.title");
quickPick.placeholder = LocalizationManager.getInstance().getMessage(
"model.picker.placeholder"
);
quickPick.ignoreFocusOut = true;

const result = await new Promise<vscode.QuickPickItem | undefined>(
(resolve) => {
quickPick.onDidAccept(() => resolve(quickPick.selectedItems[0]));
quickPick.onDidHide(() => resolve(undefined));
quickPick.show();
}
);

quickPick.dispose();

console.log('result:', result);

if (result && result.description) {
return { provider: result.description, model: result.label };
}
return undefined;
} catch (error) {
console.error("获取模型列表失败:", error);
await NotificationHandler.error("model.list.failed");
return undefined;
}
return ModelPickerService.showModelPicker(currentProvider, currentModel);
}
}

0 comments on commit d708190

Please sign in to comment.