@@ -15,11 +15,21 @@ function getDeepSeekApiKey(): string | null {
1515 return apiKey ;
1616}
1717
18+ /**
19+ * 调用 DeepSeek API
20+ * @param userContent 用户输入内容
21+ * @param systemContent 系统提示内容
22+ * @param outputChannel 输出通道,用于实时显示流式内容
23+ * @param streamMode 是否启用流式模式
24+ * @param endstring 结束字符串,用于检查输出是否包含特定字符串
25+ * @returns API 返回的完整内容
26+ */
1827async function callDeepSeekApi (
1928 userContent : string ,
2029 systemContent : string = 'You are a helpful assistant.' ,
2130 outputChannel ?: vscode . OutputChannel ,
22- streamMode : boolean = true
31+ streamMode : boolean = true ,
32+ endstring ?: string
2333) : Promise < string | null > {
2434 const apiKey = getDeepSeekApiKey ( ) ;
2535 if ( ! apiKey ) {
@@ -42,9 +52,11 @@ async function callDeepSeekApi(
4252 { role : 'user' , content : userContent } ,
4353 ] ;
4454 let fullResponse = '' ;
45- let continueResponse = true ;
55+ let maxAttempts = 5 ;
56+ let attempts = 0 ;
4657
47- while ( continueResponse ) {
58+ while ( attempts < maxAttempts ) {
59+ attempts ++ ;
4860 const response = await openai . chat . completions . create ( {
4961 model : 'deepseek-chat' ,
5062 messages : messages_body ,
@@ -53,41 +65,53 @@ async function callDeepSeekApi(
5365 temperature : 0
5466 } ) ;
5567
68+ let chunkResponse = '' ;
69+ let finishReason : string | null = null ;
70+
5671 if ( streamMode ) {
57- let lastChunk : any = null ;
5872 for await ( const chunk of response as AsyncIterable < OpenAI . Chat . Completions . ChatCompletionChunk > ) {
5973 const content = chunk . choices [ 0 ] ?. delta ?. content || '' ;
60- fullResponse += content ;
74+ chunkResponse += content ;
6175 if ( outputChannel ) {
6276 outputChannel . append ( content ) ;
6377 }
64- lastChunk = chunk ;
65- }
66- // 检查最后的 finish_reason
67- if ( lastChunk && lastChunk . choices [ 0 ] . finish_reason === 'length' ) {
68- // 需要继续
69- messages_body . push ( { role : 'user' , content : 'Please continue.' } ) ;
70- } else {
71- continueResponse = false ;
78+ finishReason = chunk . choices [ 0 ] ?. finish_reason || null ;
7279 }
7380 } else {
74- fullResponse = ( response as OpenAI . Chat . Completions . ChatCompletion ) . choices [ 0 ] . message . content || "" ;
81+ const completion = response as OpenAI . Chat . Completions . ChatCompletion ;
82+ chunkResponse = completion . choices [ 0 ] . message . content || "" ;
83+ finishReason = completion . choices [ 0 ] . finish_reason || null ;
7584 if ( outputChannel ) {
76- outputChannel . append ( fullResponse ) ;
77- }
78- if ( ( response as OpenAI . Chat . Completions . ChatCompletion ) . choices [ 0 ] . finish_reason === 'length' ) {
79- // 需要继续
80- messages_body . push ( { role : 'user' , content : 'Please continue.' } ) ;
81- } else {
82- continueResponse = false ;
85+ outputChannel . append ( chunkResponse ) ;
8386 }
8487 }
88+
89+ // 累积完整响应
90+ fullResponse += chunkResponse ;
91+
92+ // 检查终止条件
93+ const shouldContinue =
94+ finishReason === 'length' ||
95+ ( endstring && ! fullResponse . includes ( endstring ) ) ;
96+
97+ if ( ! shouldContinue ) { break } ;
98+
99+ // 准备下一次请求
100+ messages_body . push (
101+ { role : 'assistant' , content : fullResponse } ,
102+ { role : 'user' , content : '你的输出被截断了,请继续输出剩余部分:' }
103+ ) ;
104+ }
105+
106+ // 最终检查
107+ if ( endstring && ! fullResponse . includes ( endstring ) ) {
108+ vscode . window . showWarningMessage ( '响应未包含结束标记' ) ;
85109 }
86110
87111 return fullResponse ;
88112
89113 } catch ( error ) {
90- vscode . window . showErrorMessage ( 'Failed to call DeepSeek API : ' + ( error as Error ) . message ) ;
114+ vscode . window . showErrorMessage ( 'API调用失败 : ' + ( error as Error ) . message ) ;
91115 return null ;
92116 }
93117}
@@ -121,14 +145,24 @@ ${getCvbFormatDescription()}
121145${ cvbContent }
122146` ;
123147
124- return callDeepSeekApi ( requestContent , undefined , outputChannel , true ) ;
148+ return callDeepSeekApi ( requestContent , undefined , outputChannel , true , '## END_CVB' ) ; // 添加结束字符串
125149}
126150
151+ /**
152+ * 清理文件名
153+ * @param str 原始字符串
154+ * @returns 清理后的文件名
155+ */
127156function cleanFilename ( str : string ) {
128- // Replace invalid filename characters for Windows with underscores
157+ // 替换 Windows 文件名中的非法字符
129158 return str . replace ( / [ \\ / : * ? " < > | ] / g, '_' ) ;
130159}
131160
161+ /**
162+ * 根据用户需求生成文件名
163+ * @param userRequest 用户需求
164+ * @returns 生成的文件名
165+ */
132166export async function generateFilenameFromRequest ( userRequest : string ) : Promise < string > {
133167 const summaryResponse = await callDeepSeekApi (
134168 `请简单概括一下需求,输出字符串作为文件名。如果描述里有版本名称,这个名称一定要保留并放在开头。 需求:"${ userRequest } "` ,
@@ -140,16 +174,15 @@ export async function generateFilenameFromRequest(userRequest: string): Promise<
140174 let summary = summaryResponse || '' ;
141175 console . log ( 'Raw Summary:' , summary ) ;
142176
143- // Clean the summary
177+ // 清理文件名
144178 summary = cleanFilename ( summary ) ;
145- summary = summary . replace ( / ^ \. + | \. + $ / g, '' ) ; // Remove leading/trailing dots
146- summary = summary . replace ( / ^ + | + $ / g, '' ) ; // Remove leading/trailing spaces
147- summary = summary . substring ( 0 , 15 ) ; // Truncate to 15 characters
179+ summary = summary . replace ( / ^ \. + | \. + $ / g, '' ) ; // 移除开头和结尾的点
180+ summary = summary . replace ( / ^ + | + $ / g, '' ) ; // 移除开头和结尾的空格
181+ summary = summary . substring ( 0 , 15 ) ; // 截取前15个字符
148182
149183 if ( summary . length === 0 ) {
150184 summary = 'summary' ;
151185 }
152186
153187 return summary ;
154- }
155-
188+ }
0 commit comments