diff --git a/src/config/settings.ts b/src/config/settings.ts index 769ba9c..34bd658 100644 --- a/src/config/settings.ts +++ b/src/config/settings.ts @@ -8,7 +8,7 @@ import * as vscode from "vscode"; type Environment = "dev" | "test" | "prod"; /** 当前环境 - 修改这里切换环境 */ -const CURRENT_ENV: Environment = "test"; +const CURRENT_ENV: Environment = "dev"; /** 服务等级类型 */ export type ServiceTier = "lite" | "syntaxic" | "max" | "auto"; diff --git a/src/panels/ICHelperPanel.ts b/src/panels/ICHelperPanel.ts index 3a239d9..a31e328 100644 --- a/src/panels/ICHelperPanel.ts +++ b/src/panels/ICHelperPanel.ts @@ -9,6 +9,7 @@ import { handleReplaceInFile, handleUserAnswer, abortCurrentDialog, + handleOptimizePrompt, handlePlanAction, getCurrentTaskId, setLastTaskId, @@ -328,6 +329,17 @@ export async function showICHelperPanel( } } break; + case "optimizePrompt": + if (typeof message.prompt === "string") { + void handleOptimizePrompt(panel, message.prompt); + } else { + panel.webview.postMessage({ + command: "optimizeResult", + success: false, + error: "提示词为空或格式错误", + }); + } + break; // 处理计划操作(只做模式切换,响应已通过 submitAnswer 发送) case "planAction": if (message.action === "confirm") { diff --git a/src/services/creditsService.ts b/src/services/creditsService.ts index 475d379..ae5d341 100644 --- a/src/services/creditsService.ts +++ b/src/services/creditsService.ts @@ -100,7 +100,18 @@ export async function fetchBalance(): Promise { return null; } - const token = session.accessToken; + return await fetchBalanceWithToken(session.accessToken); + } catch (error) { + console.error('[CreditsService] 查询余额异常:', error); + return null; + } +} + +/** + * 使用指定 token 查询余额(登录过程中使用) + */ +export async function fetchBalanceWithToken(token: string): Promise { + try { console.log('[CreditsService] 开始查询余额,token 长度:', token.length); // 直接调用 StrangeLoop 的 /api/credit/balance 接口 diff --git a/src/services/icCoderAuthProvider.ts b/src/services/icCoderAuthProvider.ts index 2e40cee..4a34195 100644 --- a/src/services/icCoderAuthProvider.ts +++ b/src/services/icCoderAuthProvider.ts @@ -24,8 +24,23 @@ export class ICCoderAuthenticationProvider private _sessions: vscode.AuthenticationSession[] = []; constructor(private readonly context: vscode.ExtensionContext) { - // 从存储中恢复会话 - this.loadSessions(); + // 从存储中恢复会话(同步执行) + this.loadSessionsSync(); + } + + /** + * 从存储中加载会话(同步版本) + */ + private loadSessionsSync(): void { + const storedSessions = this.context.globalState.get< + vscode.AuthenticationSession[] + >("icCoderSessions", []); + this._sessions = storedSessions; + console.log("[AuthProvider] 同步加载 sessions, 数量:", this._sessions.length); + if (this._sessions.length > 0) { + console.log("[AuthProvider] Session ID:", this._sessions[0].id); + console.log("[AuthProvider] Account:", this._sessions[0].account.label); + } } /** @@ -42,7 +57,9 @@ export class ICCoderAuthenticationProvider * 保存会话到存储 */ private async saveSessions(): Promise { + console.log("[AuthProvider] 保存 sessions, 数量:", this._sessions.length); await this.context.globalState.update("icCoderSessions", this._sessions); + console.log("[AuthProvider] sessions 已保存到 globalState"); } /** @@ -51,6 +68,7 @@ export class ICCoderAuthenticationProvider async getSessions( scopes?: readonly string[] ): Promise { + console.log("[AuthProvider] getSessions 被调用, 当前 sessions 数量:", this._sessions.length); return [...this._sessions]; } diff --git a/src/services/promptOptimizeService.ts b/src/services/promptOptimizeService.ts new file mode 100644 index 0000000..d0436d4 --- /dev/null +++ b/src/services/promptOptimizeService.ts @@ -0,0 +1,103 @@ +/** + * 提示词优化服务 + * 调用后端 API 优化用户输入的提示词 + */ + +import * as vscode from 'vscode'; +import * as https from 'https'; +import * as http from 'http'; +import { URL } from 'url'; +import { getApiUrl } from '../config/settings'; + +/** 优化响应类型 */ +interface OptimizeResponse { + success: boolean; + optimizedPrompt?: string; + error?: string; +} + +/** + * 优化提示词 + * @param prompt 原始提示词 + * @returns 优化后的提示词 + */ +export async function optimizePrompt(prompt: string): Promise { + // 获取 JWT token + const session = await vscode.authentication.getSession('iccoder', [], { silent: true }); + if (!session?.accessToken) { + throw new Error('未登录,请先登录'); + } + + const response = await callOptimizeApi(prompt, session.accessToken); + + if (response.success && response.optimizedPrompt) { + return response.optimizedPrompt; + } else { + throw new Error(response.error || '优化失败'); + } +} + +/** + * 调用后端优化 API + */ +async function callOptimizeApi(prompt: string, token: string): Promise { + const urlStr = getApiUrl('/api/prompt/optimize'); + const url = new URL(urlStr); + + const isHttps = url.protocol === 'https:'; + const httpModule = isHttps ? https : http; + + const body = JSON.stringify({ prompt }); + + const requestOptions: http.RequestOptions = { + hostname: url.hostname, + port: url.port || (isHttps ? 443 : 80), + path: url.pathname + url.search, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(body), + 'Authorization': `Bearer ${token}` + }, + timeout: 30000 + }; + + return new Promise((resolve, reject) => { + const req = httpModule.request(requestOptions, (res) => { + let data = ''; + + res.on('data', (chunk) => { + data += chunk; + }); + + res.on('end', () => { + console.log('[PromptOptimize] 响应状态码:', res.statusCode); + + try { + const json = JSON.parse(data); + if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { + resolve(json as OptimizeResponse); + } else if (res.statusCode === 401 || res.statusCode === 403) { + resolve({ success: false, error: '登录已过期,请重新登录' }); + } else { + resolve({ success: false, error: json.error || json.message || `HTTP ${res.statusCode}` }); + } + } catch (e) { + resolve({ success: false, error: `解析响应失败: ${data}` }); + } + }); + }); + + req.on('error', (error) => { + reject(error); + }); + + req.on('timeout', () => { + req.destroy(); + reject(new Error('请求超时')); + }); + + req.write(body); + req.end(); + }); +} diff --git a/src/services/userService.ts b/src/services/userService.ts index e91d641..eb33028 100644 --- a/src/services/userService.ts +++ b/src/services/userService.ts @@ -8,7 +8,7 @@ import { URL } from 'url'; import * as vscode from 'vscode'; import { getStrangeLoopApiUrl, getConfig } from '../config/settings'; import type { UserInfoResponse, MembershipResponse, MultiMembershipVO, MembershipItemVO } from '../types/api'; -import { fetchBalance, getCachedBalance } from './creditsService'; +import { fetchBalanceWithToken, getCachedBalance } from './creditsService'; /** * HTTP 请求选项 @@ -230,7 +230,7 @@ export async function onTokenReceived(token: string): Promise { const [userInfo, membershipInfo, credits] = await Promise.all([ getUserInfo(token), getMembershipInfo(token), - fetchBalance() + fetchBalanceWithToken(token) ]); if (!userInfo) { diff --git a/src/utils/messageHandler.ts b/src/utils/messageHandler.ts index adfc75c..3f18e03 100644 --- a/src/utils/messageHandler.ts +++ b/src/utils/messageHandler.ts @@ -22,6 +22,7 @@ import { checkBalanceBeforeSend, fetchBalance, } from "../services/creditsService"; +import { optimizePrompt } from "../services/promptOptimizeService"; import type { RunMode, ServiceTier } from "../types/api"; @@ -1031,3 +1032,35 @@ async function handleVCDGeneration( vscode.window.showErrorMessage(errorMsg); } } + +/** + * 处理提示词优化请求 + */ +export async function handleOptimizePrompt( + panel: vscode.WebviewPanel, + prompt: string +): Promise { + console.log("[MessageHandler] ========== 收到提示词优化请求 =========="); + console.log("[MessageHandler] prompt:", prompt); + console.log("[MessageHandler] prompt 长度:", prompt?.length); + + try { + console.log("[MessageHandler] 开始调用 optimizePrompt..."); + const optimized = await optimizePrompt(prompt); + console.log("[MessageHandler] 优化成功,结果:", optimized); + panel.webview.postMessage({ + command: "optimizeResult", + success: true, + optimizedPrompt: optimized, + }); + } catch (error) { + const errorMsg = error instanceof Error ? error.message : "优化失败"; + console.error("[MessageHandler] 提示词优化失败:", errorMsg); + panel.webview.postMessage({ + command: "optimizeResult", + success: false, + error: errorMsg, + }); + vscode.window.showErrorMessage(`提示词优化失败: ${errorMsg}`); + } +} diff --git a/src/views/ICViewProvider.ts b/src/views/ICViewProvider.ts index 02eb3b6..4c1e6c3 100644 --- a/src/views/ICViewProvider.ts +++ b/src/views/ICViewProvider.ts @@ -11,6 +11,7 @@ import { handleReplaceInFile, handleUserAnswer, abortCurrentDialog, + handleOptimizePrompt, } from "../utils/messageHandler"; /** @@ -70,6 +71,9 @@ export function showICHelperPanel(context: vscode.ExtensionContext) { // 处理消息 panel.webview.onDidReceiveMessage( (message) => { + console.log("[ICViewProvider] ====== 收到 WebView 消息 ======"); + console.log("[ICViewProvider] command:", message.command); + console.log("[ICViewProvider] 完整消息:", JSON.stringify(message)); switch (message.command) { case "sendMessage": handleUserMessage(panel, message.text, context.extensionPath, message.mode); @@ -117,6 +121,10 @@ export function showICHelperPanel(context: vscode.ExtensionContext) { case "abortDialog": void abortCurrentDialog(); break; + // 新增:优化提示词 + case "optimizePrompt": + handleOptimizePrompt(panel, message.prompt); + break; } }, undefined, diff --git a/src/views/optimizeButton.ts b/src/views/optimizeButton.ts index 5043be9..db6df8d 100644 --- a/src/views/optimizeButton.ts +++ b/src/views/optimizeButton.ts @@ -60,35 +60,97 @@ export function getOptimizeButtonScript(): string { return ` let isOptimized = false; // 标记是否已优化 let originalText = ''; // 保存原始文本用于撤回 + let isOptimizing = false; // 标记是否正在优化中 function handleOptimize() { + console.log('[Optimize] handleOptimize 被调用'); + console.log('[Optimize] isOptimizing:', isOptimizing); + console.log('[Optimize] isOptimized:', isOptimized); + console.log('[Optimize] messageInput:', messageInput); + + if (isOptimizing) { + console.log('[Optimize] 正在优化中,忽略点击'); + return; // 正在优化中,忽略点击 + } + if (isOptimized) { // 撤回操作 + console.log('[Optimize] 执行撤回操作'); messageInput.value = originalText; resetOptimizeButton(); } else { // 优化操作 + const currentText = messageInput.value.trim(); + console.log('[Optimize] 当前输入内容:', currentText); + console.log('[Optimize] 内容长度:', currentText.length); + + if (!currentText) { + console.log('[Optimize] 输入框为空,不执行优化'); + return; // 输入框为空,不执行优化 + } + originalText = messageInput.value; // 保存原始文本 + isOptimizing = true; + console.log('[Optimize] 开始优化,显示加载状态'); - // 使用死数据替换输入框内容 - const optimizedTexts = [ - '请帮我优化这段代码,提高性能和可读性', - '请分析这个问题并给出最佳解决方案', - '请帮我重构这段代码,使其更加简洁高效', - '请检查代码中的潜在问题并提供改进建议' - ]; - const randomText = optimizedTexts[Math.floor(Math.random() * optimizedTexts.length)]; - messageInput.value = randomText; + // 显示加载状态 + showOptimizeLoading(); - // 切换到撤回状态 - isOptimized = true; - updateOptimizeButton(); + // 发送优化请求到扩展 + console.log('[Optimize] 发送 optimizePrompt 消息'); + vscode.postMessage({ + command: 'optimizePrompt', + prompt: currentText + }); + console.log('[Optimize] postMessage 已发送'); } messageInput.focus(); autoResizeTextarea(); } + // 处理优化结果 + function handleOptimizeResult(success, optimizedPrompt, error) { + isOptimizing = false; + hideOptimizeLoading(); + + if (success && optimizedPrompt) { + messageInput.value = optimizedPrompt; + isOptimized = true; + updateOptimizeButton(); + } else { + // 优化失败,恢复原始文本 + messageInput.value = originalText; + console.error('优化失败:', error); + } + + messageInput.focus(); + autoResizeTextarea(); + } + + function showOptimizeLoading() { + const optimizeButton = document.getElementById('optimizeButton'); + const optimizeIcon = document.getElementById('optimizeIcon'); + if (optimizeButton && optimizeIcon) { + optimizeButton.disabled = true; + optimizeButton.style.opacity = '0.5'; + // 显示加载动画 + optimizeIcon.innerHTML = ''; + } + } + + function hideOptimizeLoading() { + const optimizeButton = document.getElementById('optimizeButton'); + if (optimizeButton) { + optimizeButton.disabled = false; + optimizeButton.style.opacity = '1'; + } + // 恢复图标会在 updateOptimizeButton 或 resetOptimizeButton 中处理 + if (!isOptimized) { + resetOptimizeButton(); + } + } + function updateOptimizeButton() { const optimizeIcon = document.getElementById('optimizeIcon'); const optimizeTooltip = document.getElementById('optimizeTooltip'); diff --git a/src/views/webviewContent.ts b/src/views/webviewContent.ts index a4d03be..c8b810e 100644 --- a/src/views/webviewContent.ts +++ b/src/views/webviewContent.ts @@ -428,6 +428,7 @@ export function getWebviewContent(