Skip to content

Commit ab52de6

Browse files
committed
fix:修复metadata设置无效&&增加输出格式错误自我纠正&&整理代码复用函数
1 parent 78812fd commit ab52de6

File tree

4 files changed

+157
-69
lines changed

4 files changed

+157
-69
lines changed

src/cvbManager.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,12 @@ const g_objLanguageMapping: { [key: string]: string } = {
2121
// ================== CVB 核心类 ==================
2222
export class Cvb
2323
{
24-
private m_strContent : string;
2524
private m_recMetadata : Record<string, string>;
2625
private m_recFiles : Record<string, string>;
2726

2827
constructor(cvbContent: string)
2928
{
30-
const { cvbContent: m_strContent, metadata: m_recMetadata, files: m_recFiles } = this.parse(cvbContent);
31-
this.m_strContent = m_strContent;
29+
const { metadata: m_recMetadata, files: m_recFiles } = this.parse(cvbContent);
3230
this.m_recMetadata = m_recMetadata;
3331
this.m_recFiles = m_recFiles;
3432
}
@@ -58,9 +56,27 @@ export class Cvb
5856
return this.m_recMetadata['@时间戳'] || '';
5957
}
6058

61-
public toString() : string
62-
{
63-
return this.m_strContent;
59+
public toString(): string {
60+
// 将元数据转换成字符串
61+
let metaStr = '## META\n';
62+
for (const key in this.m_recMetadata) {
63+
metaStr += `${key}: ${this.m_recMetadata[key]}\n`;
64+
}
65+
metaStr += '## END_META\n';
66+
67+
// 将文件内容转换成字符串
68+
let filesStr = '';
69+
for (const filePath in this.m_recFiles) {
70+
// 这里假设文件内容不需要包裹代码块标记,如果需要,可自行添加
71+
filesStr += `## FILE:${filePath}\n${this.m_recFiles[filePath]}\n`;
72+
}
73+
74+
// 重新组装整个 CVB 内容
75+
const cvbContent = `## BEGIN_CVB
76+
${metaStr}
77+
${filesStr}
78+
## END_CVB`;
79+
return cvbContent;
6480
}
6581

6682
private parse(strCvbContent: string) : { cvbContent: string, metadata: Record<string, string>, files: Record<string, string> }
@@ -479,6 +495,9 @@ export function mergeCvb(baseCvb: Cvb, tcvb: TCVB) : Cvb
479495
}
480496
else if (op instanceof CreateOperation)
481497
{
498+
if (mapMergedFiles.has(strFilePath)){
499+
throw new Error(`${strFilePath} 已经存在,不可以使用 ## OPERATION:CREATE`)
500+
}
482501
// CREATE 操作:直接以新内容覆盖原有内容
483502
strContent = op.m_strContent;
484503
}

src/deepseekApi.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ function getDeepSeekModelConfig(): { modelName: string, apiBaseURL: string, apiK
3939
return defaultConfigs[modelConfig] || defaultConfigs['deepseek-chat'];
4040
}
4141

42+
let lastMessageBody : OpenAI.ChatCompletionMessageParam[];
43+
4244
/**
4345
* 调用 DeepSeek API
4446
* @param userContent 用户输入内容
@@ -155,6 +157,8 @@ async function callDeepSeekApi(
155157
vscode.window.showWarningMessage('响应未包含结束标记');
156158
}
157159

160+
messages_body.push({ role: 'assistant', content: fullResponse });
161+
lastMessageBody = messages_body;
158162
return fullResponse;
159163

160164
} catch (error) {
@@ -167,6 +171,79 @@ async function callDeepSeekApi(
167171
}
168172
}
169173

174+
export async function callDeepSeekFixApi(
175+
errorInfo: string,
176+
outputChannel?: vscode.OutputChannel,
177+
streamMode: boolean = true,
178+
abortSignal?: AbortSignal
179+
): Promise<string | null> {
180+
const { modelName, apiBaseURL, apiKey } = getDeepSeekModelConfig();
181+
const userStopException = 'operation stop by user';
182+
183+
if (!apiKey) {
184+
vscode.window.showErrorMessage('DeepSeek API Key is not configured. Please set it in the settings.');
185+
return null;
186+
}
187+
188+
if (!modelName || !apiBaseURL) {
189+
vscode.window.showErrorMessage('DeepSeek Model Name or API Base URL is not configured.');
190+
return null;
191+
}
192+
193+
const openai = new OpenAI({
194+
apiKey: apiKey,
195+
baseURL: apiBaseURL,
196+
});
197+
198+
if (outputChannel) {
199+
outputChannel.clear();
200+
outputChannel.show();
201+
}
202+
203+
let messages_body = lastMessageBody;
204+
205+
messages_body.push(
206+
{ role: 'user', content:`接收的数据格式有错误: ${errorInfo}, 修正后重新完整输出:`}
207+
);
208+
209+
let fullResponse = '';
210+
let chunkResponse = '';
211+
let finishReason: string | null = null;
212+
213+
vscode.window.showInformationMessage('开始上传DeepSeek API, 进行修复');
214+
215+
const response = await openai.chat.completions.create({
216+
model: modelName,
217+
messages: messages_body,
218+
stream: streamMode,
219+
max_tokens: 8192,
220+
temperature: 0
221+
});
222+
223+
if (streamMode) {
224+
for await (const chunk of response as AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>) {
225+
if (abortSignal?.aborted) {
226+
throw new Error(userStopException);
227+
}
228+
const content = chunk.choices[0]?.delta?.content || '';
229+
chunkResponse += content;
230+
if (outputChannel) {
231+
outputChannel.append(content);
232+
}
233+
finishReason = chunk.choices[0]?.finish_reason || null;
234+
}
235+
} else {
236+
const completion = response as OpenAI.Chat.Completions.ChatCompletion;
237+
chunkResponse = completion.choices[0].message.content || "";
238+
finishReason = completion.choices[0].finish_reason || null;
239+
if (outputChannel) {
240+
outputChannel.append(chunkResponse);
241+
}
242+
}
243+
244+
return fullResponse;
245+
}
246+
170247
/**
171248
* 应用代码重构功能
172249
* @param cvbContent CVB 文件内容

src/extension.ts

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from 'path';
33
import * as fs from 'fs';
44
import { selectFiles } from './fileSelector';
55
import { generateCvb, applyCvbToWorkspace, generateTimestamp, Cvb, TCVB, mergeCvb} from './cvbManager';
6-
import { queryCodeReDesign, generateFilenameFromRequest, analyzeCode } from './deepseekApi';
6+
import { queryCodeReDesign, generateFilenameFromRequest, analyzeCode, callDeepSeekFixApi } from './deepseekApi';
77
import { setupCvbAsMarkdown } from './cvbMarkdownHandler';
88
import { registerCvbContextMenu } from './siderBar';
99

@@ -31,6 +31,55 @@ export function clearCurrentOperationController() {
3131
}
3232
}
3333

34+
export async function doUploadCommand(cvbFilePath: string, userPrompt: string, outputChannel: vscode.OutputChannel){
35+
const workspaceFolders = vscode.workspace.workspaceFolders;
36+
if (!workspaceFolders) {
37+
vscode.window.showErrorMessage('No workspace folder found');
38+
return;
39+
}
40+
41+
const workspacePath = workspaceFolders[0].uri.fsPath;
42+
const tmpDir = path.join(workspacePath, '.CodeReDesignWorkSpace');
43+
44+
const filenameSummary = await generateFilenameFromRequest(userPrompt);
45+
const timestamp = generateTimestamp();
46+
let baseFileName = `${timestamp}_${filenameSummary}.cvb`;
47+
let fileName = baseFileName;
48+
let i = 1;
49+
while (fs.existsSync(path.join(tmpDir, fileName))) {
50+
fileName = `${timestamp}_${filenameSummary}_${i}.cvb`;
51+
i++;
52+
}
53+
54+
const cvbContent = fs.readFileSync(cvbFilePath, 'utf-8');
55+
56+
resetCurrentOperationController();
57+
58+
let apiResponse = await queryCodeReDesign(cvbContent, userPrompt, outputChannel, getCurrentOperationController().signal);
59+
let processSuccess = true;
60+
do {
61+
try {
62+
if (apiResponse) {
63+
const tcvb = new TCVB(apiResponse);
64+
const oldCvb = new Cvb(cvbContent);
65+
const cvb = mergeCvb(oldCvb, tcvb);
66+
67+
processSuccess = true;
68+
69+
cvb.setMetaData("用户需求", userPrompt);
70+
const newCvbFilePath = path.join(tmpDir, fileName);
71+
fs.writeFileSync(newCvbFilePath, cvb.toString(), 'utf-8');
72+
vscode.window.showInformationMessage(`API response saved as CVB file: ${newCvbFilePath}`);
73+
}
74+
} catch (err : any){
75+
apiResponse = await callDeepSeekFixApi(err.message, outputChannel, true, getCurrentOperationController().signal);
76+
processSuccess = false;
77+
}
78+
} while (!processSuccess);
79+
80+
clearCurrentOperationController();
81+
}
82+
3483
// 插件激活时调用
3584
export function activate(context: vscode.ExtensionContext) {
3685
console.log('Congratulations, your extension "CodeReDesign" is now active!');
@@ -98,33 +147,10 @@ export function activate(context: vscode.ExtensionContext) {
98147
if (!userPrompt) {
99148
return;
100149
}
101-
102-
const filenameSummary = await generateFilenameFromRequest(userPrompt);
103-
const timestamp = generateTimestamp();
104-
let baseFileName = `${timestamp}_${filenameSummary}.cvb`;
105-
let fileName = baseFileName;
106-
let i = 1;
107-
while (fs.existsSync(path.join(tmpDir, fileName))) {
108-
fileName = `${timestamp}_${filenameSummary}_${i}.cvb`;
109-
i++;
110-
}
111-
112-
const cvbFilePath = path.join(tmpDir, selectedCvbFile);
113-
const cvbContent = fs.readFileSync(cvbFilePath, 'utf-8');
114-
115-
resetCurrentOperationController();
116150

117-
const apiResponse = await queryCodeReDesign(cvbContent, userPrompt, outputChannel, getCurrentOperationController().signal);
118-
if (apiResponse) {
119-
const tcvb = new TCVB(apiResponse);
120-
const oldCvb = new Cvb(cvbContent);
121-
const cvb = mergeCvb(oldCvb, tcvb);
122-
cvb.setMetaData("用户需求", userPrompt);
123-
const newCvbFilePath = path.join(tmpDir, fileName);
124-
fs.writeFileSync(newCvbFilePath, cvb.toString(), 'utf-8');
125-
vscode.window.showInformationMessage(`API response saved as CVB file: ${newCvbFilePath}`);
126-
}
127-
clearCurrentOperationController();
151+
const cvbFilePath = path.join(tmpDir, selectedCvbFile);
152+
153+
doUploadCommand(cvbFilePath, userPrompt, outputChannel);
128154
});
129155

130156
// 注册命令:中断当前的上传操作

src/siderBar.ts

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as path from 'path';
33
import * as fs from 'fs';
44
import { applyCvbToWorkspace, generateTimestamp, Cvb, TCVB, mergeCvb } from './cvbManager';
55
import { queryCodeReDesign, analyzeCode, generateFilenameFromRequest } from './deepseekApi';
6-
import { getCurrentOperationController, resetCurrentOperationController, clearCurrentOperationController} from './extension';
6+
import { getCurrentOperationController, resetCurrentOperationController, clearCurrentOperationController, doUploadCommand} from './extension';
77

88
export function registerCvbContextMenu(context: vscode.ExtensionContext) {
99

@@ -188,42 +188,8 @@ async function uploadThisCvb(filePath: string) {
188188
if (!userPrompt) {
189189
return;
190190
}
191-
192-
const workspaceFolders = vscode.workspace.workspaceFolders;
193-
if (!workspaceFolders) {
194-
vscode.window.showErrorMessage('No workspace folder found.');
195-
return;
196-
}
197-
const workspacePath = workspaceFolders[0].uri.fsPath;
198-
const tmpDir = path.join(workspacePath, '.CodeReDesignWorkSpace');
199-
200-
const filenameSummary = await generateFilenameFromRequest(userPrompt);
201-
const timestamp = generateTimestamp();
202-
let baseFileName = `${timestamp}_${filenameSummary}.cvb`;
203-
let fileName = baseFileName;
204-
let i = 1;
205-
while (fs.existsSync(path.join(tmpDir, fileName))) {
206-
fileName = `${timestamp}_${filenameSummary}_${i}.cvb`;
207-
i++;
208-
}
209-
210-
const cvbContent = fs.readFileSync(filePath, 'utf-8').replace(/\r\n?/g, "\n");
211191
const outputChannel = vscode.window.createOutputChannel('CodeReDesign API Stream');
212-
213-
resetCurrentOperationController();
214-
215-
let apiResponse = await queryCodeReDesign(cvbContent, userPrompt, outputChannel, getCurrentOperationController().signal);
216-
if (apiResponse) {
217-
apiResponse = apiResponse.replace(/\r\n?/g, "\n");
218-
const tcvb = new TCVB(apiResponse);
219-
const oldCvb = new Cvb(cvbContent);
220-
const cvb = mergeCvb(oldCvb, tcvb);
221-
cvb.setMetaData("用户需求", userPrompt);
222-
const newCvbFilePath = path.join(tmpDir, fileName);
223-
fs.writeFileSync(newCvbFilePath, cvb.toString(), 'utf-8');
224-
vscode.window.showInformationMessage(`API response saved as CVB file: ${newCvbFilePath}`);
225-
}
226-
clearCurrentOperationController();
192+
doUploadCommand(filePath, userPrompt, outputChannel);
227193
}
228194

229195
/**

0 commit comments

Comments
 (0)