fix: 工具面板/帮助面板同步更新 + 图片上传限制
- 工具面板: 20→29个工具,补齐 web_search/memory_*/session_*/spawn_task/browser_* - 帮助面板: 工具数量21→29,新增人格模式/MCP/Cron/Heartbeat说明,补充/retry等命令 - 图片上传: preload透传完整options,ipc尊重multiple参数,图片选择器限制单文件
This commit is contained in:
+13
-2
@@ -80,9 +80,20 @@ function summarizeResult(toolName: string, result: Record<string, unknown>): str
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function setupIPC(): Promise<void> {
|
export async function setupIPC(): Promise<void> {
|
||||||
ipcMain.handle('dialog:openFile', async (_, options?: { filters?: Array<{ name: string; extensions: string[] }> }) => {
|
ipcMain.handle('dialog:openFile', async (_, options?: { filters?: Array<{ name: string; extensions: string[] }>; properties?: string[]; multiple?: boolean }) => {
|
||||||
|
const dialogProperties: Array<'openFile' | 'multiSelections' | 'openDirectory'> = ['openFile'];
|
||||||
|
if (options?.multiple !== false && !options?.properties?.includes('openFile')) {
|
||||||
|
dialogProperties.push('multiSelections');
|
||||||
|
}
|
||||||
|
if (options?.properties) {
|
||||||
|
for (const p of options.properties) {
|
||||||
|
if (p === 'multiSelections' && !dialogProperties.includes('multiSelections')) {
|
||||||
|
dialogProperties.push('multiSelections');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const result = await dialog.showOpenDialog(mainWindow!, {
|
const result = await dialog.showOpenDialog(mainWindow!, {
|
||||||
properties: ['openFile', 'multiSelections'],
|
properties: dialogProperties,
|
||||||
filters: options?.filters || [{ name: '所有文件', extensions: ['*'] }]
|
filters: options?.filters || [{ name: '所有文件', extensions: ['*'] }]
|
||||||
});
|
});
|
||||||
if (result.canceled) return null;
|
if (result.canceled) return null;
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ contextBridge.exposeInMainWorld('metonaDesktop', {
|
|||||||
isDesktop: true,
|
isDesktop: true,
|
||||||
info: () => ipcRenderer.invoke('app:info'),
|
info: () => ipcRenderer.invoke('app:info'),
|
||||||
dialog: {
|
dialog: {
|
||||||
openFile: (filters?: unknown) => ipcRenderer.invoke('dialog:openFile', { filters }),
|
openFile: (options?: unknown) => ipcRenderer.invoke('dialog:openFile', options),
|
||||||
saveFile: (options?: unknown) => ipcRenderer.invoke('dialog:saveFile', options)
|
saveFile: (options?: unknown) => ipcRenderer.invoke('dialog:saveFile', options)
|
||||||
},
|
},
|
||||||
fs: {
|
fs: {
|
||||||
|
|||||||
@@ -90,7 +90,9 @@ export function initInputArea(): void {
|
|||||||
const bridge = getBridge();
|
const bridge = getBridge();
|
||||||
if (!bridge) return;
|
if (!bridge) return;
|
||||||
const paths = await bridge.dialog.openFile({
|
const paths = await bridge.dialog.openFile({
|
||||||
filters: [{ name: '图片', extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg'] }]
|
filters: [{ name: '图片', extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg'] }],
|
||||||
|
properties: ['openFile'],
|
||||||
|
multiple: false
|
||||||
});
|
});
|
||||||
if (!paths || paths.length === 0) return;
|
if (!paths || paths.length === 0) return;
|
||||||
await handleImagePaths(paths);
|
await handleImagePaths(paths);
|
||||||
|
|||||||
+65
-5
@@ -413,11 +413,15 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="help-section"><h4>🚀 快速开始</h4><ol><li>确保 Ollama 已启动(默认 <code>http://127.0.0.1:11434</code>,可在设置中修改)</li><li>顶部模型栏选择一个模型,右侧会显示模型能力徽章(🧠 Think / 👁️ Vision / 🔧 Tools)</li><li>输入消息,按 <kbd>Enter</kbd> 发送,<kbd>Shift+Enter</kbd> 换行</li></ol></div>
|
<div class="help-section"><h4>🚀 快速开始</h4><ol><li>确保 Ollama 已启动(默认 <code>http://127.0.0.1:11434</code>,可在设置中修改)</li><li>顶部模型栏选择一个模型,右侧会显示模型能力徽章(🧠 Think / 👁️ Vision / 🔧 Tools)</li><li>输入消息,按 <kbd>Enter</kbd> 发送,<kbd>Shift+Enter</kbd> 换行</li></ol></div>
|
||||||
<div class="help-section"><h4>💬 聊天功能</h4><ul><li><strong>流式回复</strong> — 实时打字效果,随时点 ■ 停止</li><li><strong>Think 推理</strong> — 设置中开启,让模型展示深度思考过程(需模型支持,如 Qwen3)</li><li><strong>多模态</strong> — 上传图片,模型需支持 Vision 能力</li><li><strong>文件分析</strong> — 支持 50+ 种文本/代码格式,单文件 ≤500KB,内容以代码块发送给模型</li><li><strong>上下文长度</strong> — 设置中调整 <code>num_ctx</code>,越大记忆越长,消耗显存越多</li></ul></div>
|
<div class="help-section"><h4>💬 聊天功能</h4><ul><li><strong>流式回复</strong> — 实时打字效果,随时点 ■ 停止</li><li><strong>Think 推理</strong> — 设置中开启,让模型展示深度思考过程(需模型支持,如 Qwen3)</li><li><strong>多模态</strong> — 上传图片,模型需支持 Vision 能力</li><li><strong>文件分析</strong> — 支持 50+ 种文本/代码格式,单文件 ≤500KB,内容以代码块发送给模型</li><li><strong>上下文长度</strong> — 设置中调整 <code>num_ctx</code>,越大记忆越长,消耗显存越多</li></ul></div>
|
||||||
<div class="help-section"><h4>🔧 Tool Calling(AI 自主操作)</h4><ul><li>设置中开启后,AI 可以在对话中<strong>自主调用本地工具</strong>,像一个本地 Agent</li><li><strong>21 个工具</strong>:文件读写、目录管理、搜索替换、联网搜索、网页抓取、下载、Git、压缩/解压等</li><li>仅 <code>run_command</code>(命令执行)支持三模式切换:自动/需确认/禁用</li><li>危险命令(<code>rm -rf</code>、<code>mkfs</code>、反弹 shell 等)和系统路径(<code>/etc</code>、<code>~/.ssh</code> 等)被自动拦截</li><li>工具调用以<strong>可视化卡片</strong>展示状态(pending → running → success/error)</li><li>最多自动循环 <strong>10 轮</strong>工具调用,也可随时中断</li><li>⚠️ 需要模型支持 Tool Calling(推荐 Qwen3、Llama 3.1+、Mistral)</li></ul></div>
|
<div class="help-section"><h4>🔧 Tool Calling(AI 自主操作)</h4><ul><li>设置中开启后,AI 可以在对话中<strong>自主调用本地工具</strong>,像一个本地 Agent</li><li><strong>29 个工具</strong>,分为 6 类:<ul><li><strong>文件操作</strong>(14 个):read_file / write_file / list_directory / search_files / create_directory / delete_file / move_file / copy_file / append_file / edit_file / get_file_info / tree / diff_files / replace_in_files / read_multiple_files</li><li><strong>网络工具</strong>(3 个):web_search(联网搜索)/ web_fetch(网页抓取)/ download_file</li><li><strong>浏览器控制</strong>(8 个):browser_open / browser_screenshot / browser_evaluate / browser_extract / browser_click / browser_type / browser_scroll / browser_close</li><li><strong>系统工具</strong>(3 个):run_command / git / compress</li><li><strong>记忆/会话</strong>(4 个):memory_search / memory_add / session_list / session_read</li><li><strong>子代理</strong>(1 个):spawn_task</li></ul></li><li>仅 <code>run_command</code>(命令执行)支持三模式切换:自动/需确认/禁用</li><li>危险命令(<code>rm -rf</code>、<code>mkfs</code>、反弹 shell 等)和系统路径(<code>/etc</code>、<code>~/.ssh</code> 等)被自动拦截</li><li>工具调用以<strong>可视化卡片</strong>展示状态(pending → running → success/error)</li><li>最多自动循环 <strong>15 轮</strong>工具调用,总超时 10 分钟,也可随时中断</li><li>独立工具自动并行执行,有依赖关系的工具串行执行</li><li>⚠️ 需要模型支持 Tool Calling(推荐 Qwen3、Llama 3.1+、Mistral)</li></ul></div>
|
||||||
<div class="help-section"><h4>🧠 Agent 记忆系统</h4><ul><li>设置中开启后,AI 从对话中<strong>自动提取关键信息</strong>(事实/偏好/规则),跨会话持续积累</li><li>对话满 <strong>6 条消息</strong>后自动触发记忆提取</li><li>新对话时自动检索相关记忆注入上下文,让 AI "记住"你</li><li>点击顶部 🧠 按钮打开记忆面板:搜索、筛选、编辑、删除</li><li><strong>向量语义搜索</strong>:在设置中选择嵌入模型后,支持语义级别记忆检索(更精准)</li><li>未选择嵌入模型时,使用关键词匹配检索记忆</li><li>记忆存储在本地 IndexedDB,不会上传到任何服务器</li></ul></div>
|
<div class="help-section"><h4>🧠 Agent 记忆系统</h4><ul><li>设置中开启后,AI 从对话中<strong>自动提取关键信息</strong>(事实/偏好/规则),跨会话持续积累</li><li>对话满 <strong>6 条消息</strong>后自动触发记忆提取</li><li>新对话时自动检索相关记忆注入上下文,让 AI "记住"你</li><li>点击顶部 🧠 按钮打开记忆面板:搜索、筛选、编辑、删除</li><li><strong>向量语义搜索</strong>:在设置中选择嵌入模型后,支持语义级别记忆检索(更精准)</li><li>未选择嵌入模型时,使用关键词匹配检索记忆</li><li>AI 可通过 <code>memory_search</code> / <code>memory_add</code> 工具主动管理记忆</li><li>AI 可通过 <code>session_list</code> / <code>session_read</code> 查阅历史会话</li><li>记忆存储在本地 SQLite,不会上传到任何服务器</li></ul></div>
|
||||||
|
<div class="help-section"><h4>🎭 人格模式</h4><ul><li>设置中可切换 6 种预设人格:通用助手 / 编程助手 / 写作助手 / 数据分析 / 翻译助手 / 代码审查</li><li>不同人格有独立的 system prompt 和温度偏好</li><li>通用助手不做额外约束,其他人格会调整行为风格</li></ul></div>
|
||||||
|
<div class="help-section"><h4>🔌 MCP(Model Context Protocol)</h4><ul><li>支持连接外部 MCP Server,动态扩展工具能力</li><li>设置面板可添加/启用/禁用/删除 MCP 服务器</li><li>MCP 工具以 <code>mcp_{server}_{tool}</code> 前缀注册,与内置工具统一调度</li><li>启动时自动连接已启用的 MCP 服务器</li></ul></div>
|
||||||
|
<div class="help-section"><h4>⏰ 定时任务(Cron)</h4><ul><li>支持一次性(at)和周期性(cron 表达式)任务调度</li><li>任务触发后将描述填入输入框,可直接发送给 AI 执行</li><li>设置面板可添加/管理/删除定时任务</li></ul></div>
|
||||||
|
<div class="help-section"><h4>💓 Heartbeat 后台检查</h4><ul><li>启用后定期检查 Ollama 连接状态和模型可用性</li><li>支持 10 分钟 / 30 分钟 / 1 小时 / 2 小时间隔</li><li>异常时通过系统通知提醒</li></ul></div>
|
||||||
<div class="help-section"><h4>🖥️ 布局说明</h4><ul><li><strong>左侧面板</strong> — 执行日志,实时显示应用运行日志(连接、模型加载、工具调用等)</li><li><strong>中间区域</strong> — 聊天消息,顶部 Header + 模型栏,底部输入框</li><li><strong>右侧面板</strong> — 工作空间(常驻显示),包含:<ul><li><strong>💻 命令行 Tab</strong> — 终端界面,实时流式输出,支持长时间运行(无超时),单一终端进程</li><li><strong>📁 文件 Tab</strong> — 浏览工作空间目录,点击文件预览内容</li></ul></li><li>工作空间目录可在设置中修改</li></ul></div>
|
<div class="help-section"><h4>🖥️ 布局说明</h4><ul><li><strong>左侧面板</strong> — 执行日志,实时显示应用运行日志(连接、模型加载、工具调用等)</li><li><strong>中间区域</strong> — 聊天消息,顶部 Header + 模型栏,底部输入框</li><li><strong>右侧面板</strong> — 工作空间(常驻显示),包含:<ul><li><strong>💻 命令行 Tab</strong> — 终端界面,实时流式输出,支持长时间运行(无超时),单一终端进程</li><li><strong>📁 文件 Tab</strong> — 浏览工作空间目录,点击文件预览内容</li></ul></li><li>工作空间目录可在设置中修改</li></ul></div>
|
||||||
<div class="help-section"><h4>🕐 历史记录</h4><ul><li>所有会话自动保存到本地 IndexedDB</li><li>点击顶部 🕐 按钮查看、搜索、恢复历史会话</li><li>支持导出 Markdown / HTML / TXT / <code>.metona</code> 加密备份</li></ul></div>
|
<div class="help-section"><h4>🕐 历史记录</h4><ul><li>所有会话自动保存到本地 SQLite</li><li>点击顶部 🕐 按钮查看、搜索、恢复历史会话</li><li>支持导出 JSON / <code>.metona</code> 加密备份</li></ul></div>
|
||||||
<div class="help-section"><h4>⚡ 快捷键</h4><table class="help-shortcuts"><tr><td><kbd>Enter</kbd></td><td>发送消息</td></tr><tr><td><kbd>Shift + Enter</kbd></td><td>换行</td></tr><tr><td><kbd>Ctrl + N</kbd></td><td>新建会话</td></tr><tr><td><kbd>Ctrl + M</kbd></td><td>记忆管理</td></tr><tr><td><kbd>Esc</kbd></td><td>关闭弹窗</td></tr></table></div>
|
<div class="help-section"><h4>⚡ 快捷键 & 命令</h4><table class="help-shortcuts"><tr><td><kbd>Enter</kbd></td><td>发送消息</td></tr><tr><td><kbd>Shift + Enter</kbd></td><td>换行</td></tr><tr><td><kbd>Ctrl + N</kbd></td><td>新建会话</td></tr><tr><td><kbd>Ctrl + M</kbd></td><td>记忆管理</td></tr><tr><td><kbd>Esc</kbd></td><td>关闭弹窗</td></tr></table><p style="margin-top:8px;font-size:12px;color:var(--text-secondary);">输入框命令(直接输入后发送):</p><table class="help-shortcuts"><tr><td><code>/retry</code></td><td>重试上一轮回复</td></tr><tr><td><code>/undo</code></td><td>撤销最后一条用户消息及回复</td></tr><tr><td><code>/compress</code></td><td>用 AI 摘要压缩长对话上下文</td></tr></table></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -426,7 +430,7 @@
|
|||||||
<div class="modal-overlay" id="toolsModal" style="display:none;">
|
<div class="modal-overlay" id="toolsModal" style="display:none;">
|
||||||
<div class="modal">
|
<div class="modal">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h3>🔧 工具面板(20 个)</h3>
|
<h3>🔧 工具面板(29 个)</h3>
|
||||||
<button class="icon-btn" id="btnCloseTools">
|
<button class="icon-btn" id="btnCloseTools">
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
||||||
@@ -532,6 +536,62 @@
|
|||||||
<div class="tool-card-header"><span class="tool-card-icon">🗜️</span><span class="tool-card-name">compress</span><span class="tool-card-badge auto">自动</span></div>
|
<div class="tool-card-header"><span class="tool-card-icon">🗜️</span><span class="tool-card-name">compress</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
<div class="tool-card-desc">创建或解压 zip/tar.gz 归档</div>
|
<div class="tool-card-desc">创建或解压 zip/tar.gz 归档</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">🔍</span><span class="tool-card-name">web_search</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">联网搜索(DuckDuckGo + Bing),返回标题/URL/摘要</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">🧠</span><span class="tool-card-name">memory_search</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">语义搜索 Agent 记忆,检索相关历史信息</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">💾</span><span class="tool-card-name">memory_add</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">添加记忆条目(事实/偏好/规则),跨会话积累</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">📋</span><span class="tool-card-name">session_list</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">列出历史会话,支持按标题搜索</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">📖</span><span class="tool-card-name">session_read</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">读取历史会话消息内容</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">🤖</span><span class="tool-card-name">spawn_task</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">生成子代理独立执行任务,完成后回传结果</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">🌐</span><span class="tool-card-name">browser_open</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">在 Agent 浏览器中打开 URL</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">📸</span><span class="tool-card-name">browser_screenshot</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">对浏览器页面截图(base64 PNG)</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">⚡</span><span class="tool-card-name">browser_evaluate</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">在浏览器页面中执行 JavaScript</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">📰</span><span class="tool-card-name">browser_extract</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">提取浏览器页面的文本内容和链接</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">👆</span><span class="tool-card-name">browser_click</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">通过 CSS 选择器点击页面元素</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">⌨️</span><span class="tool-card-name">browser_type</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">通过 CSS 选择器向输入框输入文本</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">↕️</span><span class="tool-card-name">browser_scroll</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">滚动浏览器页面(上/下/顶部/底部)</div>
|
||||||
|
</div>
|
||||||
|
<div class="tool-card">
|
||||||
|
<div class="tool-card-header"><span class="tool-card-icon">❌</span><span class="tool-card-name">browser_close</span><span class="tool-card-badge auto">自动</span></div>
|
||||||
|
<div class="tool-card-desc">关闭 Agent 浏览器并释放资源</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user