feat: WebView 集成运行模式
- webviewContent 集成模式选择器脚本和样式 - inputArea 适配模式传递 - ICViewProvider/ICHelperPanel 传递模式参数
This commit is contained in:
@ -17,7 +17,7 @@ export interface IccoderConfig {
|
|||||||
/** 默认配置 */
|
/** 默认配置 */
|
||||||
const DEFAULT_CONFIG: IccoderConfig = {
|
const DEFAULT_CONFIG: IccoderConfig = {
|
||||||
backendUrl: "http://localhost:8080",
|
backendUrl: "http://localhost:8080",
|
||||||
timeout: 60000,
|
timeout: 3600000, // 1小时
|
||||||
userId: "default-user",
|
userId: "default-user",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,9 @@ import {
|
|||||||
handleReplaceInFile,
|
handleReplaceInFile,
|
||||||
handleUserAnswer,
|
handleUserAnswer,
|
||||||
abortCurrentDialog,
|
abortCurrentDialog,
|
||||||
|
handlePlanAction,
|
||||||
|
setPendingPlanExecution,
|
||||||
|
getCurrentTaskId,
|
||||||
} from "../utils/messageHandler";
|
} from "../utils/messageHandler";
|
||||||
import { VCDViewerPanel } from "./VCDViewerPanel";
|
import { VCDViewerPanel } from "./VCDViewerPanel";
|
||||||
import { ChatHistoryManager } from "../utils/chatHistoryManager";
|
import { ChatHistoryManager } from "../utils/chatHistoryManager";
|
||||||
@ -107,7 +110,7 @@ export async function showICHelperPanel(
|
|||||||
// 切换到当前面板的任务上下文
|
// 切换到当前面板的任务上下文
|
||||||
historyManager.switchToPanelTask(panelId);
|
historyManager.switchToPanelTask(panelId);
|
||||||
|
|
||||||
handleUserMessage(panel, message.text, context.extensionPath);
|
handleUserMessage(panel, message.text, context.extensionPath, message.mode);
|
||||||
break;
|
break;
|
||||||
case "readFile":
|
case "readFile":
|
||||||
handleReadFile(panel, message.filePath);
|
handleReadFile(panel, message.filePath);
|
||||||
@ -181,6 +184,24 @@ export async function showICHelperPanel(
|
|||||||
case "abortDialog":
|
case "abortDialog":
|
||||||
abortCurrentDialog();
|
abortCurrentDialog();
|
||||||
break;
|
break;
|
||||||
|
// 处理计划操作(只做模式切换,响应已通过 submitAnswer 发送)
|
||||||
|
case "planAction":
|
||||||
|
if (message.action === 'confirm') {
|
||||||
|
// 确认执行:切换到 Agent 模式
|
||||||
|
panel.webview.postMessage({
|
||||||
|
command: 'switchMode',
|
||||||
|
mode: 'agent'
|
||||||
|
});
|
||||||
|
// 获取当前会话的 taskId,用于复用知识图谱数据
|
||||||
|
const taskId = getCurrentTaskId();
|
||||||
|
if (taskId) {
|
||||||
|
// 设置待执行的计划,对话结束后自动执行(复用 taskId)
|
||||||
|
setPendingPlanExecution(panel, message.planTitle || '计划', context.extensionPath, taskId);
|
||||||
|
} else {
|
||||||
|
console.warn('[ICHelperPanel] 无法获取当前 taskId,知识图谱数据可能丢失');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export function showICHelperPanel(context: vscode.ExtensionContext) {
|
|||||||
(message) => {
|
(message) => {
|
||||||
switch (message.command) {
|
switch (message.command) {
|
||||||
case "sendMessage":
|
case "sendMessage":
|
||||||
handleUserMessage(panel, message.text, context.extensionPath);
|
handleUserMessage(panel, message.text, context.extensionPath, message.mode);
|
||||||
break;
|
break;
|
||||||
case "readFile":
|
case "readFile":
|
||||||
handleReadFile(panel, message.filePath);
|
handleReadFile(panel, message.filePath);
|
||||||
|
|||||||
@ -261,7 +261,7 @@ export function getInputAreaStyles(): string {
|
|||||||
*/
|
*/
|
||||||
export function getInputAreaScript(): string {
|
export function getInputAreaScript(): string {
|
||||||
return `
|
return `
|
||||||
${getModeSelectorScript()}
|
// 注意:getModeSelectorScript() 已在 webviewContent.ts 开头加载,这里不再重复加载
|
||||||
${getModelSelectorScript()}
|
${getModelSelectorScript()}
|
||||||
${getContextButtonScript()}
|
${getContextButtonScript()}
|
||||||
${getContextCompressScript()}
|
${getContextCompressScript()}
|
||||||
@ -328,13 +328,14 @@ export function getInputAreaScript(): string {
|
|||||||
|
|
||||||
const mode = getCurrentMode(); // 从模式选择器组件获取当前模式
|
const mode = getCurrentMode(); // 从模式选择器组件获取当前模式
|
||||||
const model = getCurrentModel(); // 从模型选择器组件获取当前模型
|
const model = getCurrentModel(); // 从模型选择器组件获取当前模型
|
||||||
|
const planMode = document.getElementById('planToggle')?.checked || false;
|
||||||
|
|
||||||
addMessage(text, 'user');
|
addMessage(text, 'user');
|
||||||
|
|
||||||
// 切换按钮为暂停状态
|
// 切换按钮为暂停状态
|
||||||
setSendButtonState(true);
|
setSendButtonState(true);
|
||||||
|
|
||||||
vscode.postMessage({ command: 'sendMessage', text: text, mode: mode, model: model });
|
vscode.postMessage({ command: 'sendMessage', text: text, mode: mode, model: model, planMode: planMode });
|
||||||
messageInput.value = '';
|
messageInput.value = '';
|
||||||
autoResizeTextarea(); // 重置输入框高度
|
autoResizeTextarea(); // 重置输入框高度
|
||||||
messageInput.focus();
|
messageInput.focus();
|
||||||
|
|||||||
@ -417,6 +417,62 @@ export function getWebviewContent(iconUri?: string): string {
|
|||||||
let loadingIndicator = null;
|
let loadingIndicator = null;
|
||||||
let currentSegmentedMessage = null; // 当前分段消息容器
|
let currentSegmentedMessage = null; // 当前分段消息容器
|
||||||
|
|
||||||
|
// ========== 模式选择器脚本(直接内联,避免模板字符串嵌套问题)==========
|
||||||
|
let currentMode = 'agent';
|
||||||
|
|
||||||
|
function toggleModeDropdown() {
|
||||||
|
const modeSelectEl = document.getElementById('modeSelect');
|
||||||
|
const modelSelectEl = document.getElementById('modelSelect');
|
||||||
|
if (modeSelectEl) {
|
||||||
|
modeSelectEl.classList.toggle('active');
|
||||||
|
if (modelSelectEl) {
|
||||||
|
modelSelectEl.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectMode(value, label) {
|
||||||
|
currentMode = value;
|
||||||
|
const modeValue = document.getElementById('modeValue');
|
||||||
|
const modeTooltip = document.getElementById('modeTooltip');
|
||||||
|
if (modeValue) {
|
||||||
|
modeValue.textContent = label;
|
||||||
|
}
|
||||||
|
if (modeTooltip) {
|
||||||
|
const tooltipMap = {
|
||||||
|
'plan': '只读模式 - 只能查询分析',
|
||||||
|
'ask': '逐个确认 - 每个写操作需确认',
|
||||||
|
'agent': '智能体自主模式',
|
||||||
|
'auto': '完全自动 - 所有操作自动执行'
|
||||||
|
};
|
||||||
|
modeTooltip.textContent = tooltipMap[value] || '切换模式';
|
||||||
|
}
|
||||||
|
const options = document.querySelectorAll('.mode-option');
|
||||||
|
options.forEach(option => {
|
||||||
|
if (option.getAttribute('data-value') === value) {
|
||||||
|
option.classList.add('selected');
|
||||||
|
} else {
|
||||||
|
option.classList.remove('selected');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const modeSelectEl = document.getElementById('modeSelect');
|
||||||
|
if (modeSelectEl) {
|
||||||
|
modeSelectEl.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentMode() {
|
||||||
|
return currentMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
const modeSelectEl = document.getElementById('modeSelect');
|
||||||
|
if (modeSelectEl && !modeSelectEl.contains(event.target)) {
|
||||||
|
modeSelectEl.classList.remove('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// ========== 模式选择器脚本结束 ==========
|
||||||
|
|
||||||
function quickAction(type) {
|
function quickAction(type) {
|
||||||
const questions = {
|
const questions = {
|
||||||
counter: '生成一个4位同步计数器',
|
counter: '生成一个4位同步计数器',
|
||||||
@ -588,6 +644,27 @@ export function getWebviewContent(iconUri?: string): string {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'switchMode':
|
||||||
|
// 切换运行模式(Plan 确认后自动切换到 Agent)
|
||||||
|
if (message.mode && typeof selectMode === 'function') {
|
||||||
|
const labelMap = {
|
||||||
|
'plan': 'Plan',
|
||||||
|
'ask': 'Ask',
|
||||||
|
'agent': 'Agent',
|
||||||
|
'auto': 'Auto'
|
||||||
|
};
|
||||||
|
selectMode(message.mode, labelMap[message.mode] || message.mode);
|
||||||
|
console.log('[WebView] 模式已切换到:', message.mode);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'addMessage':
|
||||||
|
// 添加消息(通用)
|
||||||
|
if (message.text && message.sender) {
|
||||||
|
addMessage(message.text, message.sender);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.log('[WebView] 未处理的消息类型:', message.command);
|
console.log('[WebView] 未处理的消息类型:', message.command);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user