v0.16.7: 引擎修复 + 工具面板统一 + AGENT.md 改为仅工作空间加载
核心引擎修复: - 状态转换表补全 THINKING/PARSING/EXECUTING -> COMPRESSING,修复紧急压缩成为死代码的 P1 问题 - 新增跨轮次死循环检测器(软性提示 + 硬性熔断),防止模型陷入重复工具调用死循环 - handleCompressing 空响应回到 THINKING 而非 REFLECTING,避免错误终止 - executeHooks 添加 .catch() 防止未处理的 Promise 拒绝 - ALWAYS_PARALLEL 移除 git 和 browser_evaluate(有副作用的工具不应并行) - thinking fallback:content 为空但有 thinking 时,用 [推理过程] 作为 content 保留上下文 - 8个写类工具添加专用格式化器(含 success + message 字段) - 清理死代码:3个未使用函数 + 3个未使用 import 工具面板统一: - 10个工具独立下拉框统一为1个全局执行模式选择器 - FIFO 队列防止并行 showToolConfirm 导致静默取消 - delete_file 支持 paths 数组参数批量删除 工具定义与实现一致性修复: - run_command 移除未使用的 timeout 参数,描述改为"超时可配置" - list_directory 添加 2000 条截断逻辑 + filter_extension 参数 - calculator 正则移除 ^ 字符(parser 用 ** 替代) - search_files/tree/web_search/fetch_top 描述与实现对齐 消息传递修复: - trimByTokenLimit 改为原子组选择(assistant+tool_calls 与后续 tool 消息作为一组) - 历史工具结果复用 formatToolResultForModel,与当前格式一致 AGENT.md 加载策略变更: - 删除内置 AGENT.md 文件 - 仅从工作空间加载:有则注入,无则跳过 其他修复: - 修复初始化失败 "Cannot convert undefined or null to object"(saveSetting null 导致 JSON.parse 陷阱) - 修复工作空间命令行标签页 idle 状态残留导致样式错乱 版本号: 0.16.5 -> 0.16.7
This commit is contained in:
@@ -285,6 +285,51 @@ export function initSettingsModal(): void {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ── 子代理相关设置(原顶层事件监听器移入此处,确保 DOM 已就绪)──
|
||||
// 子代理模型设置保存
|
||||
document.querySelector('#selectSubAgentModel')?.addEventListener('change', async () => {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
if (!db) return;
|
||||
const val = (document.querySelector('#selectSubAgentModel') as HTMLSelectElement).value;
|
||||
await db.saveSetting('subAgentModel', val);
|
||||
logSetting('子代理默认模型', val || '跟随当前模型');
|
||||
});
|
||||
|
||||
// 子代理最大轮次
|
||||
const saveSubAgentMaxLoops = debounce(async () => {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
const val = (document.querySelector('#inputSubAgentMaxLoops') as HTMLInputElement).value.trim();
|
||||
const maxLoops = val ? parseInt(val) : 10;
|
||||
state.set('subAgentMaxLoops', maxLoops);
|
||||
if (db) await db.saveSetting('subAgentMaxLoops', maxLoops);
|
||||
logSetting('子代理最大轮次', `${maxLoops} 轮`);
|
||||
}, 500);
|
||||
document.querySelector('#inputSubAgentMaxLoops')!.addEventListener('input', saveSubAgentMaxLoops);
|
||||
|
||||
// 子代理超时(秒)
|
||||
const saveSubAgentTimeout = debounce(async () => {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
const val = (document.querySelector('#inputSubAgentTimeout') as HTMLInputElement).value.trim();
|
||||
const sec = val ? parseInt(val) : -1; // -1=默认
|
||||
const ms = sec >= 0 ? sec * 1000 : 300_000;
|
||||
state.set('subAgentTimeout', ms);
|
||||
if (db) await db.saveSetting('subAgentTimeout', sec);
|
||||
logSetting('子代理超时', sec >= 0 ? (sec === 0 ? '已禁用' : `${sec}s`) : '默认(300s)');
|
||||
}, 500);
|
||||
document.querySelector('#inputSubAgentTimeout')!.addEventListener('input', saveSubAgentTimeout);
|
||||
|
||||
// ── 看门狗超时(分钟,0=禁用)──
|
||||
const saveLoopWatchdog = debounce(async () => {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
const val = (document.querySelector('#inputLoopWatchdog') as HTMLInputElement).value.trim();
|
||||
const minutes = val ? parseInt(val) : -1;
|
||||
const ms = minutes > 0 ? minutes * 60_000 : (minutes === 0 ? 0 : 1_800_000); // 默认30分钟
|
||||
state.set('loopWatchdogMs', ms);
|
||||
if (db) await db.saveSetting('loopWatchdogMs', ms);
|
||||
logSetting('看门狗超时', minutes >= 0 ? (minutes === 0 ? '已禁用' : `${minutes}分钟`) : '默认(30分钟)');
|
||||
}, 500);
|
||||
document.querySelector('#inputLoopWatchdog')!.addEventListener('input', saveLoopWatchdog);
|
||||
}
|
||||
|
||||
export function openSettingsModal(): void {
|
||||
@@ -429,50 +474,6 @@ async function populateSubAgentModels(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// 子代理模型设置保存
|
||||
document.querySelector('#selectSubAgentModel')?.addEventListener('change', async () => {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
if (!db) return;
|
||||
const val = (document.querySelector('#selectSubAgentModel') as HTMLSelectElement).value;
|
||||
await db.saveSetting('subAgentModel', val);
|
||||
logSetting('子代理默认模型', val || '跟随当前模型');
|
||||
});
|
||||
|
||||
// 子代理最大轮次
|
||||
const saveSubAgentMaxLoops = debounce(async () => {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
const val = (document.querySelector('#inputSubAgentMaxLoops') as HTMLInputElement).value.trim();
|
||||
const maxLoops = val ? parseInt(val) : 10;
|
||||
state.set('subAgentMaxLoops', maxLoops);
|
||||
if (db) await db.saveSetting('subAgentMaxLoops', maxLoops);
|
||||
logSetting('子代理最大轮次', `${maxLoops} 轮`);
|
||||
}, 500);
|
||||
document.querySelector('#inputSubAgentMaxLoops')!.addEventListener('input', saveSubAgentMaxLoops);
|
||||
|
||||
// 子代理超时(秒)
|
||||
const saveSubAgentTimeout = debounce(async () => {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
const val = (document.querySelector('#inputSubAgentTimeout') as HTMLInputElement).value.trim();
|
||||
const sec = val ? parseInt(val) : -1; // -1=默认
|
||||
const ms = sec >= 0 ? sec * 1000 : 300_000;
|
||||
state.set('subAgentTimeout', ms);
|
||||
if (db) await db.saveSetting('subAgentTimeout', sec);
|
||||
logSetting('子代理超时', sec >= 0 ? (sec === 0 ? '已禁用' : `${sec}s`) : '默认(300s)');
|
||||
}, 500);
|
||||
document.querySelector('#inputSubAgentTimeout')!.addEventListener('input', saveSubAgentTimeout);
|
||||
|
||||
// ── 看门狗超时(分钟,0=禁用)──
|
||||
const saveLoopWatchdog = debounce(async () => {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
const val = (document.querySelector('#inputLoopWatchdog') as HTMLInputElement).value.trim();
|
||||
const minutes = val ? parseInt(val) : -1;
|
||||
const ms = minutes > 0 ? minutes * 60_000 : (minutes === 0 ? 0 : 1_800_000); // 默认30分钟
|
||||
state.set('loopWatchdogMs', ms);
|
||||
if (db) await db.saveSetting('loopWatchdogMs', ms);
|
||||
logSetting('看门狗超时', minutes >= 0 ? (minutes === 0 ? '已禁用' : `${minutes}分钟`) : '默认(30分钟)');
|
||||
}, 500);
|
||||
document.querySelector('#inputLoopWatchdog')!.addEventListener('input', saveLoopWatchdog);
|
||||
|
||||
async function importSessions(filePath: string): Promise<void> {
|
||||
const db = state.get<ChatDB | null>(KEYS.DB);
|
||||
if (!db) return;
|
||||
|
||||
Reference in New Issue
Block a user