更新压缩机制,提高前缀缓存命中率,优化UI渲染机制,提高帧数
This commit is contained in:
1 parent
6131c2563e
commit
0ce72f74f1
175 files changed
+7621
-2611
No files matched your search
+131
-77
@@ -728,11 +728,11 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
|
||||
<div class="chips" data-reveal-list="left" data-stagger="70">
|
||||
<span class="chip"><span>🖥️</span><span><b>真能操作桌面</b> — 截图 → 视觉定位 → 键鼠模拟,闭环完成 ERP 录入、表单填写、软件操控</span></span>
|
||||
<span class="chip"><span>🧩</span><span><b>20 项内置工具</b> — 从终端命令到邮件收发,从 PPT 制作到图像生成,覆盖真实办公场景</span></span>
|
||||
<span class="chip"><span>🧩</span><span><b>20 项内置工具 + 单文件插件化</b> — 从终端命令到邮件收发,从 PPT 制作到图像生成;新增工具 = 一个文件 + 协议接入,前端面板自动生成,无需大面积改动</span></span>
|
||||
<span class="chip"><span>🏠</span><span><b>完全本地运行</b> — Electron 打包,数据不出本机;后端 FastAPI + 前端零延迟直读磁盘</span></span>
|
||||
<span class="chip"><span>🎨</span><span><b>可深度定制</b> — 主题 / 字体 / 字号 / 背景 / 工作空间 / 提示词分层架构,全部可调</span></span>
|
||||
<span class="chip"><span>🔁</span><span><b>工程级稳定性</b> — 循环检测、上下文压缩、阻塞式人工确认、轨迹回放,对抗 LLM 的「幻觉操作」</span></span>
|
||||
<span class="chip"><span>💾</span><span><b>存储双后端(接口隔离)</b> — 会话与定时任务存储统一接口驱动,<b>JSON 可视化 / MySQL</b> 一键切换、不双写;新增存储方式只需实现接口,消费方无感知后端</span></span>
|
||||
<span class="chip"><span>💾</span><span><b>存储多后端(接口隔离)</b> — 会话与定时任务存储统一接口驱动,<b>JSON / MySQL / SQLite</b> 一键切换、不双写;存储数据库与工具数据库配置隔离;新增存储方式只需实现接口,消费方无感知后端</span></span>
|
||||
</div>
|
||||
|
||||
<blockquote class="quote reveal">
|
||||
@@ -766,16 +766,16 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
<tr><th>工具</th><th>文件</th><th>能力</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><span class="tool-emoji">🖱️</span> <strong>gui</strong></td><td><code>tools/gui.py</code></td><td>桌面 GUI 自动化:截图、视觉批量定位、点击/输入/快捷键/滚动</td></tr>
|
||||
<tr><td><span class="tool-emoji">🌐</span> <strong>browser_control</strong></td><td><code>tools/browser_control.py</code></td><td>浏览器打开/关闭、地址导航、标签页交互</td></tr>
|
||||
<tr><td><span class="tool-emoji">💻</span> <strong>terminal_execute</strong></td><td><code>tools/terminal_execute.py</code></td><td>执行任意终端命令,支持工作目录与超时</td></tr>
|
||||
<tr><td><span class="tool-emoji">🖱️</span> <strong>gui</strong></td><td><code>tools/gui.py</code></td><td>桌面 GUI 自动化:截图、视觉批量定位、点击/输入/快捷键/滚动(桌面/任意应用轨)</td></tr>
|
||||
<tr><td><span class="tool-emoji">🌐</span> <strong>browser_control</strong></td><td><code>tools/browser_control.py</code></td><td>浏览器打开/关闭、地址导航、标签页交互(Playwright + CDP 分离进程,Profile 默认一次性临时目录,可配置持久)</td></tr>
|
||||
<tr><td><span class="tool-emoji">🧭</span> <strong>web_page</strong></td><td><code>tools/web_page.py</code></td><td>浏览器页面 <strong>DOM 级精准操作</strong>(浏览器轨):snapshot 元素清单、click/fill/scroll/press/extract/screenshot/eval_js 等,毫秒级、优于 GUI 视觉定位;典型流程 browser_control 打开 → web_page 操作</td></tr>
|
||||
<tr><td><span class="tool-emoji">💻</span> <strong>terminal_execute</strong></td><td><code>tools/terminal_execute.py</code></td><td>执行任意终端命令(含目录/文件操作,可替代 directory_listing),支持工作目录与超时</td></tr>
|
||||
<tr><td><span class="tool-emoji">🪟</span> <strong>software_control</strong></td><td><code>tools/software_control.py</code></td><td>Win32 API 启停软件、注册表、<code>os.startfile</code></td></tr>
|
||||
<tr><td><span class="tool-emoji">📧</span> <strong>email</strong></td><td><code>tools/email.py</code></td><td>IMAP 收邮件 + SMTP 发邮件(含附件)</td></tr>
|
||||
<tr><td><span class="tool-emoji">📄</span> <strong>doc</strong></td><td><code>tools/doc.py</code></td><td>创建/读取/编辑 docx / xlsx / pptx / pdf / txt</td></tr>
|
||||
<tr><td><span class="tool-emoji">📂</span> <strong>directory_listing</strong></td><td><code>tools/directory_listing.py</code></td><td>递归列目录、文件元信息</td></tr>
|
||||
<tr><td><span class="tool-emoji">📨</span> <strong>send_file</strong></td><td><code>tools/send_file.py</code></td><td>以邮件附件形式发送本地文件</td></tr>
|
||||
<tr><td><span class="tool-emoji">🔍</span> <strong>web_search</strong></td><td><code>tools/web_search.py</code></td><td>联网搜索(Tavily / Firecrawl / 火山引擎)</td></tr>
|
||||
<tr><td><span class="tool-emoji">🗄️</span> <strong>text2sql</strong></td><td><code>tools/text2sql.py</code></td><td>自然语言/SQL 操作数据库:查表结构、查询、增删改</td></tr>
|
||||
<tr><td><span class="tool-emoji">🗄️</span> <strong>text2sql</strong></td><td><code>tools/text2sql.py</code></td><td>自然语言/SQL 操作数据库(MySQL / SQLite,工具数据库配置):查表结构、查询、增删改、建库建表</td></tr>
|
||||
<tr><td><span class="tool-emoji">📚</span> <strong>rag</strong></td><td><code>tools/rag.py</code></td><td>ChromaDB 向量检索 + Reranker 重排序</td></tr>
|
||||
<tr><td><span class="tool-emoji">🎨</span> <strong>image_gen</strong></td><td><code>tools/image_gen.py</code></td><td>调用 Z-Image-Turbo 生成图片</td></tr>
|
||||
<tr><td><span class="tool-emoji">✅</span> <strong>todo_list</strong></td><td><code>tools/todo_list.py</code></td><td>多步任务规划与进度跟踪</td></tr>
|
||||
@@ -785,11 +785,13 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
<tr><td><span class="tool-emoji">📅</span> <strong>date_query</strong></td><td><code>tools/date_query.py</code></td><td>当前日期时间查询</td></tr>
|
||||
<tr><td><span class="tool-emoji">⏰</span> <strong>cron_manager</strong></td><td><code>tools/cron_manager.py</code></td><td>定时任务管理:查看/新增/修改/删除定时任务,支持 cron/间隔/一次性触发</td></tr>
|
||||
<tr><td><span class="tool-emoji">📊</span> <strong>hard_excel_read</strong></td><td><code>tools/hard_excel_read.py</code></td><td>复杂 Excel 表结构读取:前 N 行原始数据 + 维度/合并区/数据区范围建议,供大模型解析结构</td></tr>
|
||||
<tr><td><span class="tool-emoji">📥</span> <strong>excel2sql</strong></td><td><code>tools/excel2sql.py</code></td><td>按大模型给定的数据行列范围,将 Excel 数据区流式批量入库 MySQL(自动建库建表、表注释)</td></tr>
|
||||
<tr><td><span class="tool-emoji">📥</span> <strong>excel2sql</strong></td><td><code>tools/excel2sql.py</code></td><td>按大模型给定的数据行列范围,将 Excel 数据区流式批量入库(MySQL / SQLite,自动建库建表)</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<p class="reveal-up" style="color:var(--ink-soft);font-size:.92rem;margin-top:10px">🔒 <strong>main Agent 默认挂载</strong>(代码强制注入,不可通过配置移除,前端显示为锁定项):<code>call_subagent</code>(子 Agent 委派)、<code>doc_tool</code>(文档读写)、<code>human_interaction</code>(人机交互审查)、<code>todo_list</code>(任务规划)、<code>terminal_execute</code>(终端命令)。其余工具按 <code>config.json</code> 中 main agent 的 tools 列表自行增删;子 Agent 无此限制。</p>
|
||||
|
||||
<h3 class="reveal" style="font-size:1.4rem;margin:44px 0 16px">🎯 区别于其他 Agent 项目的核心设计</h3>
|
||||
|
||||
<div class="table-scroll reveal-scale">
|
||||
@@ -799,13 +801,16 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td><strong>GUI 操作粒度</strong></td><td>一步一调用,N 个动作 = 2N+1 次 LLM 调用</td><td><strong>动作序列合并</strong>:同页多操作打包为一次 <code>gui</code> 调用,N 个动作仅 2 次 LLM 调用</td></tr>
|
||||
<tr><td><strong>UI 自动化双轨</strong></td><td>单轨(截图 + 坐标模拟)</td><td><strong>Playwright + GUI 双轨兼顾容错与效率</strong>:浏览器内走 DOM 级精准操作(<code>web_page</code> 毫秒级、定位可靠);桌面/任意应用走 GUI 视觉定位(<code>gui_tool</code> 截图视觉闭环、可处理任意界面)——浏览器能 DOM 就不截图,桌面无 DOM 就走视觉</td></tr>
|
||||
<tr><td><strong>视觉反馈</strong></td><td>仅返回坐标文本</td><td><strong>截图作为视觉闭环</strong>注入上下文,多模态 LLM 看到真实屏幕状态</td></tr>
|
||||
<tr><td><strong>坐标定位</strong></td><td>逐元素请求</td><td><strong>批量定位</strong> <code>_batch_ground_elements</code>:N 个元素 1 次子模型调用</td></tr>
|
||||
<tr><td><strong>循环失控</strong></td><td>无防护,token 烧穿</td><td><strong>两级循环检测</strong>:连续 3 次同工具警告反思 → 连续 5 次强制终止</td></tr>
|
||||
<tr><td><strong>上下文膨胀</strong></td><td>简单截断</td><td><strong>图内分级压缩</strong>:token 超 <code>窗口×COMPRESS_RATE</code> 触发,压缩历史工具调用为累积摘要,每步 LLM 调用后检查</td></tr>
|
||||
<tr><td><strong>上下文连续性</strong></td><td>思考链跨轮丢失</td><td><strong>历史思考/反思注入</strong>:压缩游标后的思考、反思、工具调用按因果顺序交错注入(稳定 id、确定性构建,前缀缓存友好);深度思考与反思分离存储</td></tr>
|
||||
<tr><td><strong>部署形态</strong></td><td>仅 Web / 仅 API</td><td><strong>同一套源码双模式</strong>:<code>uvicorn</code> Web 服务 ↔ Electron 桌面应用</td></tr>
|
||||
<tr><td><strong>文件操作</strong></td><td>HTTP 上传下载</td><td>桌面端走 <strong>IPC 直读磁盘</strong>,零延迟;Web 端走 <code>/api/fs/*</code></td></tr>
|
||||
<tr><td><strong>提示词</strong></td><td>单层 system prompt</td><td><strong>四层提示词架构</strong>:系统级 / 工具描述 / 运行时注入 / 内部子模型</td></tr>
|
||||
<tr><td><strong>插件化</strong></td><td>注册式插件表(适配新插件需改框架主流程)</td><td><strong>前后端单文件插件化</strong>:后端按 <code>BaseTool</code> 协议单文件实现、前端按 <code>setXxxDeps</code> 依赖注入协议接入,<strong>监听事件 / 回调驱动而非注册式</strong>——新增或替换一个插件只需保持协议签名,宿主装配零改动</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -825,7 +830,7 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
<span class="img-path">./git_image/运行-todolist.png</span>
|
||||
</div>
|
||||
</figure>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>人机交互确认</b> — 敏感操作(终端执行、文件写入等)与信息收集以浮窗形式实时弹出,用户可同意、拒绝、跳过或补充信息;<b>拒绝也只是一次工具返回值</b>,Agent 自行调整方案继续,不会结束本轮 | <b>任务规划 TodoList</b> — 多步任务自动拆解与进度跟踪,支持主 / 子 Agent 独立任务列表</sub></p>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>人机交互确认</b> — 敏感操作(终端执行、文件写入等)与信息收集以「输入区上方通知条」形式实时弹出:只显示标题与数量角标,点击展开为完整卡片(标题/内容/选项胶囊/补充输入框),选择或补充后作为工具返回值,Agent 继续执行;<b>拒绝也只是一次工具返回值</b>,Agent 自行调整方案继续,不会结束本轮 | <b>任务规划 TodoList</b> — 多步任务自动拆解与进度跟踪,同样以通知条展示(最新步骤 + 数量角标,可展开全部步骤),Todo 状态<b>会话级存储</b>(chat 与 cron 各自独立,切换会话自动恢复)</sub></p>
|
||||
|
||||
<figure class="shot-card reveal-rotate" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:18px;justify-items:center;margin:24px 0 6px">
|
||||
<div class="img-card" style="width:min(360px,100%)" data-path="./git_image/运行-文件修改.png">
|
||||
@@ -839,7 +844,7 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
<span class="img-path">./git_image/运行-工具调用1.png</span>
|
||||
</div>
|
||||
</figure>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>文件编辑模式</b> — 内置 Monaco 编辑器,支持代码高亮、差异对比、文件树拖拽组织 | <b>工具调用记录</b> — 实时展示每轮 ReAct 的工具调用链、参数及返回值</sub></p>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>文件编辑模式</b> — 内置 Monaco 编辑器,支持代码高亮、差异对比、文件树拖拽组织 | <b>工具调用记录</b> — 实时展示每轮 ReAct 的工具调用链、参数及返回值;思考(reasoning_content)与反思(content)分离显示为独立的 Thought / Reflection 行</sub></p>
|
||||
|
||||
<figure class="shot-card reveal-rotate" style="margin:24px 0 6px;text-align:center">
|
||||
<div class="img-card" style="width:min(560px,100%);margin:0 auto" data-path="./git_image/运行-工具调用2.png">
|
||||
@@ -862,7 +867,7 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
<span class="img-path">./git_image/运行-edit模式.png</span>
|
||||
</div>
|
||||
</figure>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>定时任务管理</b> — 支持 cron / 间隔 / 一次性三种触发方式,状态实时可见 | <b>Edit 编辑模式</b> — 独立编辑区,Monaco 编辑器 + 文档树侧栏,支持拖拽文件/文件夹到附件区发送给 Agent</sub></p>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>定时任务管理</b> — 支持 cron / 间隔 / 一次性三种触发方式;任务按<b>工作区分组</b>展示;任务会话与聊天同构(点击会话式查看历史、多轮对话、流式渲染),任务在<b>独立子进程</b>中执行;模式切换锁:chat 运行时可查看 cron、cron 运行时可查看 chat,双容器渲染不打断流式输出 | <b>Edit 编辑模式</b> — 独立编辑区,Monaco 编辑器 + 文档树侧栏,支持拖拽文件/文件夹到附件区发送给 Agent</sub></p>
|
||||
|
||||
<figure class="shot-card reveal-rotate" style="margin:24px 0 6px;text-align:center">
|
||||
<div class="img-card" style="width:min(560px,100%);margin:0 auto" data-path="./git_image/修改图片.png">
|
||||
@@ -941,7 +946,7 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
|
||||
<div class="lead reveal" style="margin-top:26px">
|
||||
<ul data-reveal-list="left" data-stagger="60">
|
||||
<li class="li-rv"><strong><code>call_model</code></strong>(<code>core/nodes.py</code>):追加动态尾部(TodoList 状态 + 循环提醒;固定反思引导已并入系统提示词前缀)→ LLM 调用 → 每步检查压缩(token 超阈值标记)→ 提取 thinking</li>
|
||||
<li class="li-rv"><strong><code>call_model</code></strong>(<code>core/nodes.py</code>):本轮回插思考/反思(<code>[思考]</code> / <code>[反思]</code> 合成消息)→ 追加动态尾部(TodoList 状态 + 循环提醒;固定反思引导已并入系统提示词前缀)→ LLM 调用 → 每步检查压缩(token 超阈值标记)→ 提取 thinking / reflection 独立记录</li>
|
||||
<li class="li-rv"><strong><code>should_continue</code></strong>(<code>core/routing.py</code>):含 tool_calls → 循环检测 → 路由到 <code>tools</code> 或 <code>END</code>(需人工确认的工具不在此暂停,而是在工具执行钳点阻塞征求用户意见,见「阻塞式人机交互」)</li>
|
||||
<li class="li-rv"><strong><code>process_tool_artifact</code></strong>:gui 截图作为 synthetic HumanMessage 注入,实现视觉闭环</li>
|
||||
<li class="li-rv"><strong><code>compress</code></strong>(<code>core/nodes.py</code>):token 超 <code>窗口×COMPRESS_RATE</code> 时,将历史工具调用压缩为累积摘要(见「实现细节」)</li>
|
||||
@@ -951,7 +956,7 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
<h3 class="reveal" style="font-size:1.4rem;margin:44px 0 16px">多 Agent 模式</h3>
|
||||
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-bottom:18px">
|
||||
多 Agent 并非独立图,而是<strong>同一张 react 图内的工具级并行</strong>:<code>tools</code> 节点由 <code>make_parallel_tool_node</code>(线程池)取代 ToolNode,一轮内的多个工具调用并行执行;其中 <code>agent_call</code> 工具会以主 Agent 当前消息快照启动<strong>子 Agent 的独立图实例</strong>执行子任务,结果以工具返回值注入主 Agent 上下文。子 Agent 内的人机交互同样为阻塞式——在子图线程中等待浮窗应答,完成后自然回到主图:
|
||||
多 Agent 并非独立图,而是<strong>同一张 react 图内的工具级并行</strong>:<code>tools</code> 节点由 <code>make_parallel_tool_node</code>(线程池)取代 ToolNode,一轮内的多个工具调用并行执行;其中 <code>agent_call</code> 工具会以主 Agent 当前消息快照启动<strong>子 Agent 的独立图实例</strong>执行子任务,结果以工具返回值注入主 Agent 上下文。子 Agent 内的人机交互同样为阻塞式——在子图线程中等待通知条应答,完成后自然回到主图:
|
||||
</p>
|
||||
|
||||
<div class="line-cnt reveal" data-line="type" data-interval="55">
|
||||
@@ -960,7 +965,7 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
├─ 普通工具:直接并行执行
|
||||
└─ agent_call:spawn 子 Agent Runtime → 子图 invoke
|
||||
│(子图内 human_interaction 阻塞等待
|
||||
│ 浮窗应答,答案作为工具返回值)
|
||||
│ 通知条应答,答案作为工具返回值)
|
||||
└─ 结果作为 ToolMessage 注入主 Agent ◄┐
|
||||
▲ │
|
||||
└──────────────── 有 agent_call → 继续循环;无 → END ──────────────────────┘</pre>
|
||||
@@ -987,10 +992,12 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
├── src/
|
||||
│ ├── agent/ # 🧠 Agent 核心
|
||||
│ │ ├── agents/
|
||||
│ │ │ └── agent_runtime.py # 编排层入口:execute_agent(动态 Agent 工厂)
|
||||
│ │ │ ├── agent_runtime.py # 编排层入口:execute_agent(动态 Agent 工厂,main 默认挂载工具强制注入)
|
||||
│ │ │ ├── config.json # ★ 合并配置(agents/tools/env/gui/workspace/theme 分区,含密钥)
|
||||
│ │ │ └── config_dist.json # 配置模板(不含密钥)
|
||||
│ │ ├── core/
|
||||
│ │ │ ├── graph.py # LangGraph 构建(单 Agent + 多 Agent)
|
||||
│ │ │ ├── nodes.py # ReAct 节点:call_model / process_tool_artifact / 压缩
|
||||
│ │ │ ├── nodes.py # ReAct 节点:call_model(思考/反思提取与本轮回插)/ process_tool_artifact / 压缩
|
||||
│ │ │ ├── runtime.py # 图执行器:消息拼装、历史加载、轨迹落盘
|
||||
│ │ │ ├── routing.py # should_continue 路由 + 强制终止
|
||||
│ │ │ ├── state.py # Graph 状态定义(messages / agent_mode)
|
||||
@@ -999,17 +1006,18 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
│ │ │ ├── turn_runner.py # ★ 后台线程轮次执行器(解耦 HTTP 与图执行生命周期)
|
||||
│ │ │ ├── llm.py # ChatQwen 多模态封装(图像/附件/非标准 tool_call)
|
||||
│ │ │ ├── tool_policy.py # 工具执行策略(直执 / 需确认)
|
||||
│ │ │ ├── storage.py # ★ 统一存储层:接口 + JSON/MySQL 双实现 + 工厂 + scope
|
||||
│ │ │ └── config_manager.py# 配置读写:agent/tool/env/gui/model/theme
|
||||
│ │ │ ├── db.py # ★ 数据库基础设施:配置加载(存储库/工具库隔离)、连接、幂等建库建表(MySQL/SQLite)
|
||||
│ │ │ ├── storage.py # ★ 统一存储层:接口 + JSON/MySQL/SQLite 三实现 + 工厂 + scope
|
||||
│ │ │ └── config_manager.py# 配置读写:agent/tool/env/gui/model/theme + MAIN_DEFAULT_TOOLS
|
||||
│ │ ├── memory/
|
||||
│ │ │ └── system_prompt.py # ★ 四层提示词:MAIN / PLAN / REFLECTION / VISION...
|
||||
│ │ ├── tools/ # 20 项工具(见上表)
|
||||
│ │ │ ├── ...(gui / browser_control / terminal_execute / email / doc / web_search / text2sql / rag / cron_manager 等)
|
||||
│ │ ├── cron/ # ⏰ 定时任务引擎
|
||||
│ │ │ ├── models.py # 数据模型(CronTask / Trigger)
|
||||
│ │ │ ├── models.py # 数据模型(CronTask / Trigger,含 workspace 字段)
|
||||
│ │ │ ├── storage.py # 转发层(实现统一在 core/storage.py)
|
||||
│ │ │ ├── scheduler.py # 调度计算与触发扫描
|
||||
│ │ │ ├── runner.py # 任务执行器(子进程,切换存储 cron 作用域)
|
||||
│ │ │ ├── runner.py # 任务执行器(独立子进程,切换存储 cron 作用域)
|
||||
│ │ │ └── live.py # 常驻调度循环
|
||||
│ │ ├── skills/ # 5 项技能(skill.json + skill.md)
|
||||
│ │ │ ├── netease_mail_read/
|
||||
@@ -1021,16 +1029,10 @@ footer.visible .footer-line{width:min(560px,80%);transition:width 1.3s var(--eas
|
||||
│ │ │ └── streaming_client.py # 流式 TTS 客户端(SSE 收音频块)
|
||||
│ │ ├── history/
|
||||
│ │ │ ├── session_storage.py # 转发层(实现统一在 core/storage.py)
|
||||
│ │ │ └── tool_call_recorder.py # 每轮工具调用轨迹记录 (tool_{turn_id}.json)
|
||||
│ │ │ ├── tool_call_recorder.py # 每轮工具调用轨迹记录(含思考/反思双字段,tool_{turn_id}.json)
|
||||
│ │ │ └── sqlite/ # SQLite 存储默认目录(storage.sqlite / tool/ 每库一文件)
|
||||
│ │ ├── utils/ # env_utils / agent_utils / image_utils / ppt_utils / tool_call_utils
|
||||
│ │ └── config/ # ★ 配置文件目录
|
||||
│ │ ├── env_config.json # 运行时配置(首次向导生成,勿手动改)
|
||||
│ │ ├── env_config_dist.json # 配置模板(默认值)
|
||||
│ │ ├── agent_config.json # Agent 行为配置 + 兜底 system_prompt
|
||||
│ │ ├── tool_config.json # 各工具启用/参数
|
||||
│ │ ├── gui_config.json # GUI 工具参数
|
||||
│ │ ├── theme_config.json # 主题
|
||||
│ │ └── workspace_config.json # 工作空间列表与当前选择
|
||||
│ │ └── data/ # 运行时数据(浏览器 Profile 等,不入库)
|
||||
│ │
|
||||
│ └── web/ # 🎨 前端 UI
|
||||
│ ├── server.py # FastAPI 后端(75+ 路由)
|
||||
@@ -1080,7 +1082,7 @@ npm install</pre>
|
||||
</div>
|
||||
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin:14px 0 18px">
|
||||
首次运行会弹出<strong>配置向导</strong>(3 步),写入 <code>src/agent/config/env_config.json</code> 后自动启动:
|
||||
首次运行会弹出<strong>配置向导</strong>(3 步),写入 <code>src/agent/agents/config.json</code> 后自动启动:
|
||||
</p>
|
||||
|
||||
<div class="table-scroll reveal-scale">
|
||||
@@ -1094,7 +1096,7 @@ npm install</pre>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<blockquote class="quote reveal">💡 之后启动直接进入主界面,不再弹向导。如需重配,删除 <code>src/agent/config/env_config.json</code> 即可重触首次流程。</blockquote>
|
||||
<blockquote class="quote reveal">💡 之后启动直接进入主界面,不再弹向导。如需重配,删除 <code>src/agent/agents/config.json</code>(或复制 <code>config_dist.json</code> 为新配置)即可重触首次流程。</blockquote>
|
||||
|
||||
<h4 class="reveal-up" style="font-size:1.1rem;margin:22px 0 4px">3. 打包为安装程序</h4>
|
||||
<div class="term reveal">
|
||||
@@ -1113,10 +1115,10 @@ npm run build</pre>
|
||||
<summary>📦 打包原理(点击展开)</summary>
|
||||
<div class="pack-body">
|
||||
<ul data-reveal-list="left" data-stagger="50">
|
||||
<li class="li-rv"><code>package.json</code> 的 <code>build.files</code> 仅打包 <code>electron/</code>、<code>src/</code>、<code>requirements.txt</code>,<strong>排除</strong> <code>env_config.json</code>(每个用户独立生成)</li>
|
||||
<li class="li-rv"><code>package.json</code> 的 <code>build.files</code> 仅打包 <code>electron/</code>、<code>src/</code>、<code>requirements.txt</code>,<strong>排除</strong> <code>config.json</code>(每个用户独立生成,模板 <code>config_dist.json</code> 随包分发)</li>
|
||||
<li class="li-rv"><code>asar: false</code>:源码不加密,便于审计与二次开发</li>
|
||||
<li class="li-rv">NSIS 安装器:允许改安装目录、创建桌面/开始菜单快捷方式、卸载时清理 AppData</li>
|
||||
<li class="li-rv">首次启动由 <code>setup.html</code> 向导引导:检测 Python → 配置 LLM → 写 <code>env_config.json</code> → 启动 FastAPI → 加载 UI</li>
|
||||
<li class="li-rv">首次启动由 <code>setup.html</code> 向导引导:检测 Python → 配置 LLM → 写 <code>config.json</code> → 启动 FastAPI → 加载 UI</li>
|
||||
<li class="li-rv">主进程 <code>findSystemPython()</code> 依次检查:用户配置路径 → 常见 Python 安装位置 → PATH 中的 <code>python</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1142,8 +1144,8 @@ pip install -r requirements.txt
|
||||
|
||||
<span class="cmt"># 3. 配置环境(首次)</span>
|
||||
<span class="cmt"># 复制模板并填写 LLM 凭证</span>
|
||||
Copy-Item src\agent\config\env_config_dist.json src\agent\config\env_config.json
|
||||
<span class="cmt"># 编辑 env_config.json,至少填写 models[].base_url / api_key / model</span>
|
||||
Copy-Item src\agent\agents\config_dist.json src\agent\agents\config.json
|
||||
<span class="cmt"># 编辑 config.json,至少填写 env.models[].base_url / api_key / model</span>
|
||||
|
||||
<span class="cmt"># 4. 启动 Web 服务</span>
|
||||
$env:PYTHONPATH="src;$env:PYTHONPATH"
|
||||
@@ -1172,10 +1174,10 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<div class="section-head">
|
||||
<span class="sec-emoji">⚙️</span>
|
||||
<h2>配置说明</h2>
|
||||
<p class="sec-sub">所有运行时配置集中在 <code>src/agent/config/env_config.json</code>,首次向导自动生成。</p>
|
||||
<p class="sec-sub">所有运行时配置集中在 <code>src/agent/agents/config.json</code>(合并单文件,含 <code>agents / tools / env / gui / workspace / theme</code> 分区),模板见 <code>config_dist.json</code>,首次向导自动生成。</p>
|
||||
</div>
|
||||
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-bottom:12px">关键字段:</p>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-bottom:12px">env 分区关键字段:</p>
|
||||
|
||||
<div class="table-scroll reveal-scale">
|
||||
<table data-row-anim="alt">
|
||||
@@ -1183,12 +1185,9 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<tbody>
|
||||
<tr><td><code>models[]</code></td><td><code>SETUP_REQUIRED</code></td><td>LLM 列表:<code>{id, name, model, api_key, base_url, timeout, max_retries}</code>;ASR / TTS / RAG / ImageGen 四个本地服务也在此注册(按 <code>model</code> 字段匹配,<code>api_key</code> 留空)</td></tr>
|
||||
<tr><td><code>gui_model_id</code></td><td><code>""</code></td><td>GUI 视觉定位专用模型(留空则回退主模型)</td></tr>
|
||||
<tr><td><code>WORKING_DIR</code></td><td>项目根目录</td><td>工作根目录(桌面端自动设为安装目录)</td></tr>
|
||||
<tr><td><code>WORKSPACE_DIR</code></td><td><code>""</code></td><td>工作空间目录(相对 WORKING_DIR),留空则使用 WORKING_DIR</td></tr>
|
||||
<tr><td><code>USER_PYTHON_PATH</code></td><td><code>""</code></td><td>指定 Python 解释器路径</td></tr>
|
||||
<tr><td><code>LLM_CONTEXT_WINDOW</code></td><td><code>262144</code></td><td>上下文窗口大小(token)</td></tr>
|
||||
<tr><td><code>COMPRESS_RATE</code></td><td><code>0.6</code></td><td>上下文压缩阈值比例(0~1),token 用量超过 <code>窗口×该值</code> 时触发压缩</td></tr>
|
||||
<tr><td><code>THINKING_LEVEL</code></td><td><code>"low"</code></td><td>深度思考档位:low / high / xhigh / max / ultra(xhigh 及以上启用深度思考)</td></tr>
|
||||
<tr><td><code>IMG_SIZE</code></td><td><code>768</code></td><td>截图短边尺寸</td></tr>
|
||||
<tr><td><code>GROUNDING_WIDTH/HEIGHT</code></td><td><code>1000</code></td><td>视觉定位输入分辨率</td></tr>
|
||||
<tr><td><code>LOOP_DETECT_REPEATED_TOOL_WARN</code></td><td><code>3</code></td><td>连续同工具同参多少次警告</td></tr>
|
||||
@@ -1197,8 +1196,11 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<tr><td><code>SEND_FILE_SIZE_LIMIT</code></td><td><code>30</code></td><td>发送文件大小上限(MB)</td></tr>
|
||||
<tr><td><code>WEB_SEARCH_API_KEY</code></td><td><code>""</code></td><td>联网搜索 API Key</td></tr>
|
||||
<tr><td><code>WEB_SEARCH_ENGINE</code></td><td><code>"tavily"</code></td><td>搜索引擎选择(tavily / firecrawl / volcengine)</td></tr>
|
||||
<tr><td><code>STORAGE_BACKEND</code></td><td><code>"json"</code></td><td>存储后端(json / mysql)</td></tr>
|
||||
<tr><td><code>MYSQL_HOST</code> / <code>MYSQL_PORT</code> / <code>MYSQL_USER</code> / <code>MYSQL_PASSWORD</code> / <code>MYSQL_DATABASE</code></td><td><code>""</code></td><td>MySQL 连接参数(STORAGE_BACKEND=mysql 时生效)</td></tr>
|
||||
<tr><td><code>STORAGE_BACKEND</code></td><td><code>"json"</code></td><td>存储后端:json(本地文件)/ mysql / sqlite</td></tr>
|
||||
<tr><td><code>STORAGE_DB_TYPE</code> + <code>STORAGE_DB_HOST/PORT/USER/PASSWORD/DATABASE/PATH</code></td><td><code>""</code></td><td><strong>存储数据库</strong>配置(mysql 用 host/port/user/password/database;sqlite 用 path,留空默认 <code>history/sqlite/storage.sqlite</code>);缺省回退旧 <code>MYSQL_*</code>(零迁移)</td></tr>
|
||||
<tr><td><code>TOOL_DB_TYPE</code> + <code>TOOL_DB_HOST/PORT/USER/PASSWORD/DATABASE/PATH</code></td><td><code>"mysql"</code></td><td><strong>工具数据库</strong>配置——数据库操作工具(text2sql / excel2sql)专用,<strong>与存储后端完全隔离</strong>;sqlite path 留空默认 <code>history/sqlite/tool</code> 目录,每个库名一个 <code>.sqlite</code> 文件</td></tr>
|
||||
<tr><td><code>MYSQL_*</code></td><td><code>""</code></td><td><strong>旧键</strong>:存储数据库 MySQL 参数(已被 <code>STORAGE_DB_*</code> 取代,仅作回退兼容)</td></tr>
|
||||
<tr><td><code>BROWSER_PROFILE_DIR</code></td><td><code>""</code></td><td>浏览器控制工具持久 Profile 目录;留空 = 每次启动一次性临时 Profile(登录态不持久、不留盘)</td></tr>
|
||||
<tr><td><code>TOOL_TIMEOUT</code></td><td><code>300</code></td><td>工具执行超时时间(秒)</td></tr>
|
||||
<tr><td><code>CRON_TIME_PERIOD_MINUTES</code></td><td><code>30</code></td><td>定时任务时段长度(分钟),同一时段全局并发=1</td></tr>
|
||||
<tr><td><code>EMAIL_ADDRESS / EMAIL_AUTH_CODE</code></td><td><code>""</code></td><td>邮箱凭证(IMAP/SMTP)</td></tr>
|
||||
@@ -1206,9 +1208,9 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<blockquote class="quote reveal">⚙️ 以上参数均可在主界面「设置」面板热修改,或通过 <code>/api/config/*</code> 接口程序化调整。</blockquote>
|
||||
<blockquote class="quote reveal">⚙️ 思考档位(low / high / xhigh / max / ultra)为<strong>会话级</strong>配置(存于各会话 <code>session_meta.json</code>);以上参数均可在主界面「设置」面板热修改,或通过 <code>/api/config/*</code> 接口程序化调整。</blockquote>
|
||||
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin:16px 0">设置面板包含五个标签页,覆盖 Agent 运行的全部可调参数:</p>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin:16px 0">设置面板包含 11 个分组(常规 / 外观 / 模型 / Agent / 工具 / Skills / GUI / 网络搜索 / 邮件 / 存储与数据库 / 运行时参数),覆盖 Agent 运行的全部可调参数:</p>
|
||||
|
||||
<figure class="shot-card reveal-rotate" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:18px;justify-items:center;margin-bottom:6px">
|
||||
<div class="img-card" style="width:min(360px,100%)" data-path="./git_image/5.png">
|
||||
@@ -1222,7 +1224,7 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<span class="img-path">./git_image/1.png</span>
|
||||
</div>
|
||||
</figure>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>Agent 配置</b> — 管理多个 AI 角色,各自绑定独立模型与工具集 | <b>工具配置</b> — 启用/禁用工具、调整参数及执行策略</sub></p>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>Agent 配置</b> — 管理多个 AI 角色,各自绑定独立模型与工具集(main Agent 默认挂载 5 个工具为锁定项,不可移除) | <b>工具配置</b> — 启用/禁用工具、调整参数及执行策略</sub></p>
|
||||
|
||||
<figure class="shot-card reveal-rotate" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:18px;justify-items:center;margin:24px 0 6px">
|
||||
<div class="img-card" style="width:min(360px,100%)" data-path="./git_image/2.png">
|
||||
@@ -1245,7 +1247,7 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<span class="img-path">./git_image/4.png</span>
|
||||
</div>
|
||||
</figure>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>主题配置</b> — 12 套预设主题 + 自定义背景 / 模糊度 / 暗角 / 字体</sub></p>
|
||||
<p class="shot-cap reveal" style="transition-delay:.1s"><sub><b>主题配置</b> — 12 套预设主题 + 自定义背景 / 模糊度 / 暗角 / 字体;另含 常规 / 模型 / Skills / 网络搜索 / 邮件 / 存储与数据库 / 运行时参数 等分组</sub></p>
|
||||
</section>
|
||||
|
||||
<hr class="section-divider">
|
||||
@@ -1280,11 +1282,15 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-bottom:14px">上下文按「前缀稳定性」布局,最大化利用 LLM 服务端的前缀缓存:</p>
|
||||
<div class="pre-card reveal">
|
||||
[系统提示词(含固定反思引导,稳定)] + [压缩摘要] + [对话历史] + [用户消息] + [动态尾部(每轮变化)]
|
||||
[系统提示词(含固定反思引导,稳定)] + [压缩摘要] + [对话历史] + [本轮回插的思考/反思]
|
||||
+ [历史思考/反思/工具调用(压缩游标后)] + [用户消息] + [动态尾部(每轮变化)]
|
||||
</div>
|
||||
<div class="lead reveal" style="margin-top:18px">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv"><strong>固定部分放前缀</strong>:反思引导等不变提示文本并入系统提示词、位于上下文最前 —— 前缀稳定即可命中缓存;避免把固定文本逐轮塞在消息中间导致整段缓存失效。</li>
|
||||
<li class="li-rv"><strong>历史思考/反思/工具调用注入</strong>(<code>build_tool_history_messages</code>):压缩游标之后的所有轮次,按因果顺序交错注入 <code>[历史思考] → [历史反思] → [历史工具调用]</code>;思考/反思<strong>独立注入</strong>(工具无结果文本时仍保留),尾部未被工具消费的思考/反思去重后追加在轮末。所有消息从磁盘<strong>确定性构建、id 稳定</strong>(<code>think_ctx_{idx}</code> / <code>reflect_ctx_{idx}</code> / <code>tool_ctx_{idx}</code>),只追加在末尾 —— 满足前缀缓存命中条件;压缩节点按 id 精确移除。</li>
|
||||
<li class="li-rv"><strong>思考与反思分离</strong>:深度思考(<code>reasoning_content</code>)与反思(<code>content</code>)<strong>独立存储</strong>(工具记录的 <code>thinking</code> / <code>reflection</code> 字段 + 轮末 <code>reflections</code> 列表)并独立注入上下文,二者可同时存在,确保注入内容与真实消息一一对应、前缀缓存准确命中。</li>
|
||||
<li class="li-rv"><strong>本轮回插</strong>(<code>_inject_turn_thinking</code>):带工具调用的 AIMessage 前,将其携带的思考/反思以 <code>[思考]</code> / <code>[反思]</code> 合成消息插回本次调用的上下文(<code>reasoning_content</code> 不被 LLM API 回传),使模型在后续步骤中仍能看到自己的思考链;仅注入 <code>messages_for_llm</code>、不进图状态、id 稳定,不破坏前缀缓存。</li>
|
||||
<li class="li-rv"><strong>变化部分放末尾</strong>:TodoList 状态、循环警告等每轮变化的内容追加在消息列表<strong>末尾</strong>,变化只影响尾部、不破坏前缀缓存;无 TodoList 且无循环提醒时<strong>不注入任何尾部提示</strong>(省 token)。</li>
|
||||
<li class="li-rv"><strong>动态尾部作为长期记忆</strong>:每轮尾部文本持久化到 <code>session_meta</code> 的 <code>dynamic_tail_history</code>(连续相同去重),后续轮次把全部历史尾部注入上下文,Agent 能看到之前所有轮的 TodoList 状态与循环提醒。</li>
|
||||
</ul>
|
||||
@@ -1338,16 +1344,17 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<h3>阻塞式人机交互<span class="detail-tag">(交互类 / 展示类工具的统一模式)</span></h3>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-bottom:16px">
|
||||
人机交互不再「暂停图 + 存快照 + 续跑」,而是<strong>阻塞式普通工具</strong>:工具在图上线程中等待前端浮窗应答,答案(同意 / 拒绝 / 跳过 / 补充信息)只是普通工具返回值,图自然继续——<strong>拒绝不会结束整轮</strong>,Agent 自行调整方案。
|
||||
人机交互不再「暂停图 + 存快照 + 续跑」,而是<strong>阻塞式普通工具</strong>:工具在图上线程中等待前端应答,答案(同意 / 拒绝 / 跳过 / 补充信息)只是普通工具返回值,图自然继续——<strong>拒绝不会结束整轮</strong>,Agent 自行调整方案。
|
||||
</p>
|
||||
<div class="line-cnt reveal" data-line="type" data-interval="55">
|
||||
<pre>LLM 发出 human_interaction / 需确认工具调用
|
||||
→ tools 节点执行工具
|
||||
→ human_request.ask_human() 阻塞等待(注册到请求表,随 live snapshot 推送前端)
|
||||
→ 前端浮窗出现,工具调用行显示"运行中"
|
||||
→ 用户点击 → POST /api/human-action → 写入答案并唤醒
|
||||
→ 前端"通知条"出现(输入区上方,标题 + 数量角标),工具调用行显示"运行中"
|
||||
→ 用户点击展开 → 选项胶囊 / 补充输入框 → 提交(POST /api/human-action)→ 写入答案并唤醒
|
||||
→ 工具返回答案文本 → ToolMessage → 图继续(无快照重放、无续跑状态机)</pre>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin:14px 0 4px"><strong>通知条(notify-strip)</strong>:todo 与人机交互不再使用浮窗,改为输入区上方的水平通知条——收起态只显示标题/最新步骤 + 数量角标,点击上下展开完整卡片;通知条左侧按钮可收起为输入区按钮,再次点击恢复;todo 与人机交互的挂起状态<strong>会话级存储</strong>(chat 与 cron 各自独立,切换会话自动保存/恢复)。</p>
|
||||
<div class="table-scroll reveal-scale" style="margin-top:18px">
|
||||
<table data-row-anim="alt">
|
||||
<thead><tr><th>设计点</th><th>传统做法(本项目旧版)</th><th>阻塞式(当前)</th></tr></thead>
|
||||
@@ -1366,7 +1373,7 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<div class="lead reveal">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv"><strong>交互类工具</strong>(如 <code>human_interaction</code>):工具内调一次 <code>ask_human(meta)</code> 阻塞,自己格式化返回值</li>
|
||||
<li class="li-rv"><strong>展示类工具</strong>(如 <code>todo_list</code>):纯文本返回、不维护全局 store,前端从通用 live 记录(工具调用的 args/结果)按工具名写一个小 adapter 渲染浮窗(如 <code>js/todo.js</code> 的 <code>updateTodoOverlayFromRecords</code>)</li>
|
||||
<li class="li-rv"><strong>展示类工具</strong>(如 <code>todo_list</code>):纯文本返回、不维护全局 store,前端从通用 live 记录(工具调用的 args/结果)按工具名写一个小 adapter 渲染通知条(如 <code>js/notify-strip.js</code>)</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1386,6 +1393,28 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-top:14px">通过系统提示词前缀中的固定反思引导(<code>REFLECTION_PROMPT</code>)+ <code>MAIN_SYSTEM_PROMPT</code> 双重强调「同页操作必须合并为一次 <code>gui</code> 调用」实现。</p>
|
||||
|
||||
<!-- 5.1 UI 自动化双轨 -->
|
||||
<div class="detail-head reveal">
|
||||
<span class="detail-num">5.1</span>
|
||||
<h3>UI 自动化双轨<span class="detail-tag">(Playwright + GUI,兼顾容错与效率)</span></h3>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-bottom:12px">UI 操作按目标介质分两条轨道,由系统提示词引导 Agent 按「能 DOM 不截图」的原则选择:</p>
|
||||
<div class="table-scroll reveal-scale">
|
||||
<table data-row-anim="alt">
|
||||
<thead><tr><th>轨道</th><th>工具</th><th>机制</th><th>适用场景</th><th>特点</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><strong>浏览器轨</strong></td><td><code>browser_control</code> + <code>web_page</code></td><td>Playwright 会话管理器(CDP 分离进程,Agent 退出后浏览器保留、重启自动重连)+ DOM 级操作</td><td>浏览器内的网页操作</td><td><strong>毫秒级、定位可靠</strong>(snapshot 元素清单 → ref/selector 精准操作,不依赖视觉模型)</td></tr>
|
||||
<tr><td><strong>桌面轨</strong></td><td><code>gui</code></td><td>截图 + 视觉批量定位(<code>_batch_ground_elements</code>)+ 键鼠模拟</td><td>桌面应用 / 任意界面(含浏览器无 DOM 场景)</td><td><strong>通用容错</strong>:截图视觉闭环,多模态 LLM 看到真实屏幕状态,可处理任何界面</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="lead reveal" style="margin-top:14px">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv"><strong>典型流程</strong>:<code>browser_control</code> 打开 URL → <code>web_page</code> snapshot 获取元素清单 → 按 ref/selector 批量 click/fill/scroll → 页面跳转后重新 snapshot;浏览器不适用(如系统对话框、桌面软件)时回退 <code>gui</code> 视觉定位</li>
|
||||
<li class="li-rv"><strong>两轨均遵循</strong>「连续操作合并为一次调用」(actions 列表批量传入)的性能原则</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 6. 双模式源码共用 -->
|
||||
<div class="detail-head reveal">
|
||||
<span class="detail-num">6</span>
|
||||
@@ -1405,56 +1434,81 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-top:12px">前端通过 <code>window.electronAPI?.isElectron</code> 自动适配。</p>
|
||||
|
||||
<!-- 7. 存储双后端 -->
|
||||
<!-- 7. 存储多后端 -->
|
||||
<div class="detail-head reveal">
|
||||
<span class="detail-num">7</span>
|
||||
<h3>存储双后端<span class="detail-tag">(JSON 可视化 / MySQL,统一接口隔离)</span></h3>
|
||||
<h3>存储多后端<span class="detail-tag">(JSON / MySQL / SQLite,统一接口隔离)</span></h3>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-bottom:16px">
|
||||
会话历史与定时任务存储统一在 <strong><code>agent/core/storage.py</code></strong>:接口(Protocol)驱动、双后端实现、<strong>消费方零感知后端选择</strong>(不判断 <code>STORAGE_BACKEND</code>)。
|
||||
会话历史与定时任务存储统一在 <strong><code>agent/core/storage.py</code></strong>:接口(Protocol)驱动、多后端实现、<strong>消费方零感知后端选择</strong>(不判断 <code>STORAGE_BACKEND</code>)。
|
||||
</p>
|
||||
<p class="reveal-up" style="color:var(--ink);font-weight:800">接口与实现</p>
|
||||
<div class="lead reveal" style="margin-top:8px">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv"><code>ConversationRecordRepository</code>(对话消息 / 工具调用 / 轮次元数据 / 会话生命周期,16 方法)与 <code>TaskConfigRepository</code>(cron 任务配置,6 方法)两个 Protocol</li>
|
||||
<li class="li-rv">每后端一个实现类:<code>JsonRecordRepository</code> / <code>MysqlRecordRepository</code>(含会话与 cron 双作用域)、<code>JsonTaskConfigRepository</code> / <code>MysqlTaskConfigRepository</code></li>
|
||||
<li class="li-rv">每后端一个实现类:<code>JsonRecordRepository</code> / <code>MysqlRecordRepository</code> / <code>SqliteRecordRepository</code>(含会话与 cron 双作用域)、<code>JsonTaskConfigRepository</code> / <code>MysqlTaskConfigRepository</code> / <code>SqliteTaskConfigRepository</code></li>
|
||||
<li class="li-rv"><strong>新增存储后端只需实现上述接口并在工厂注册一行</strong>;消费方新增功能/字段无需改动存储层(消息原样 JSON 存储、工具记录 meta 全量透传)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink);font-weight:800;margin-top:22px">作用域(scope)</p>
|
||||
<div class="lead reveal" style="margin-top:8px">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv"><code>session</code>(默认):主进程普通会话,JSON 落盘 <code>history/sessions/{session_id}/</code>,MySQL 用 <code>sessions / session_messages / session_tool_calls</code> 三表</li>
|
||||
<li class="li-rv"><code>cron</code>:定时任务,JSON 落盘 <code>history/cron/{task_id}/</code>,MySQL 用 <code>cron_messages / cron_tool_calls</code> 两表;cron 子进程切换存储作用域后<strong>直写</strong>记录,主进程经 cron 作用域仓库读取</li>
|
||||
<li class="li-rv"><code>session</code>(默认):主进程普通会话,JSON 落盘 <code>history/sessions/{session_id}/</code>,MySQL/SQLite 用 <code>sessions / session_messages / session_tool_calls</code> 三表</li>
|
||||
<li class="li-rv"><code>cron</code>:定时任务,JSON 落盘 <code>history/cron/{task_id}/</code>,MySQL/SQLite 用 <code>cron_messages / cron_tool_calls</code> 两表;cron 子进程切换存储作用域后<strong>直写</strong>记录,主进程经 cron 作用域仓库读取</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="table-scroll reveal-scale" style="margin-top:18px">
|
||||
<table data-row-anim="alt">
|
||||
<thead><tr><th>后端</th><th>存储位置</th><th>说明</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><strong>json</strong>(默认)</td><td><code>history/sessions/{session_id}/</code></td><td>消息与工具调用以人类可读 JSON 文件落盘(<code>turn_{turn_id}.json</code> / <code>tool_{turn_id}.json</code> / <code>session_meta.json</code> / <code>_session_tokens.json</code>),可直接打开查看/修改,便于审计与调试</td></tr>
|
||||
<tr><td><strong>mysql</strong></td><td>session 三表 / cron 两表</td><td>消息与工具调用记录原样 JSON 入库、读取只走数据库;二进制产物(图片/附件等)两个后端均落盘</td></tr>
|
||||
<tr><td><strong>json</strong>(默认)</td><td><code>history/sessions/{session_id}/</code></td><td>消息与工具调用以人类可读 JSON 文件落盘(<code>turn_{turn_id}.json</code> / <code>tool_{turn_id}.json</code> / <code>session_meta.json</code>),可直接打开查看/修改,便于审计与调试</td></tr>
|
||||
<tr><td><strong>mysql</strong></td><td>session 三表 / cron 两表</td><td>消息与工具调用记录原样 JSON 入库、读取只走数据库;二进制产物(图片/附件等)所有后端均落盘</td></tr>
|
||||
<tr><td><strong>sqlite</strong></td><td><code>history/sqlite/storage.sqlite</code>(单文件,session+cron 共用)</td><td>内置 <code>sqlite3</code> 零依赖,JSON 存 TEXT 列;<code>cron_tool_calls</code> 含 meta 列,尾部思考可完整落库;WAL 模式支持多进程并发</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="lead reveal" style="margin-top:18px">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv">由 <code>STORAGE_BACKEND</code> + <code>MYSQL_HOST / MYSQL_PORT / MYSQL_USER / MYSQL_PASSWORD / MYSQL_DATABASE</code> 配置,<code>agent/core/db.py</code> 提供统一连接与幂等建表</li>
|
||||
<li class="li-rv">由 <code>STORAGE_BACKEND</code>(json / mysql / sqlite)+ 存储数据库配置驱动;<strong>存储数据库与工具数据库完全隔离</strong>:存储用 <code>STORAGE_DB_*</code>(缺省回退旧 <code>MYSQL_*</code>,零迁移),数据库操作工具(text2sql / excel2sql)用 <code>TOOL_DB_*</code>(<strong>不回退存储配置</strong>);SQLite 工具库目录模式下每个库名 = 一个 <code>.sqlite</code> 文件</li>
|
||||
<li class="li-rv">两类数据库均在设置 → 存储与数据库页配置(类型可选择 MySQL / SQLite);<code>agent/core/db.py</code> 提供统一连接(<code>connect_db</code>)与幂等建库建表(<code>ensure_database</code> / <code>ensure_sqlite_database</code> —— 库不存在时先建库再按表结构建表)</li>
|
||||
<li class="li-rv"><strong>不双写</strong>:选哪种后端,读写就只走该后端;写入幂等(同一 <code>(session_id, turn_id)</code> 先 DELETE 再 INSERT);DB 异常仅打印日志,不阻断主流程</li>
|
||||
<li class="li-rv">分支(<code>/api/sessions/branch</code>)与回滚等会话功能均基于存储接口实现,两个后端一致可用</li>
|
||||
<li class="li-rv">分支(<code>/api/sessions/branch</code>)与回滚等会话功能均基于存储接口实现,各后端一致可用</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink);font-weight:800;margin:22px 0 4px">双后端行为差异(设计内)</p>
|
||||
<p class="reveal-up" style="color:var(--ink);font-weight:800;margin:22px 0 4px">后端行为差异(设计内)</p>
|
||||
<div class="table-scroll reveal-scale">
|
||||
<table data-row-anim="alt">
|
||||
<thead><tr><th>场景</th><th>json</th><th>mysql</th></tr></thead>
|
||||
<thead><tr><th>场景</th><th>json</th><th>mysql / sqlite</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>轮次中实时工具记录</td><td>每次工具结果后<strong>增量写盘</strong> <code>tool_*.json</code>,进程崩溃后重启可回退恢复最近记录</td><td>不增量入库,由轮次结束 <code>save_tool_calls</code> 统一落库(无额外磁盘 IO,但崩溃时该轮记录丢失)</td></tr>
|
||||
<tr><td>服务重启后运行中轮次</td><td><code>get_live_tool_calls</code> 回退读取增量文件,可继续展示</td><td>内存记录丢失、数据库无该轮记录,实时面板为空</td></tr>
|
||||
<tr><td>cron 历史读取</td><td>直接读 <code>history/cron/</code> 下文件</td><td>子进程直写 cron 表,历史可正常读取</td></tr>
|
||||
<tr><td>cron 历史读取</td><td>直接读 <code>history/cron/</code> 下文件</td><td>子进程直写数据库表,历史可正常读取</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 8. 前后端单文件插件化 -->
|
||||
<div class="detail-head reveal">
|
||||
<span class="detail-num">8</span>
|
||||
<h3>前后端单文件插件化<span class="detail-tag">(协议驱动,非注册式)</span></h3>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink-soft);margin-bottom:14px"><strong>核心思想</strong>:一个插件 = 后端一个文件 + 前端一个文件(或 adapter),通过<strong>协议</strong>接入;框架与插件之间靠<strong>事件 / 回调监听</strong>通信,而不是集中式注册表 + 修改主流程——新增或替换插件只需保持协议签名,<strong>宿主装配零改动</strong>。</p>
|
||||
<p class="reveal-up" style="color:var(--ink);font-weight:800">后端:<code>BaseTool</code> 协议(<code>src/agent/tools/*.py</code>)</p>
|
||||
<div class="lead reveal" style="margin-top:8px">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv">每个工具是独立单文件,继承 LangChain <code>BaseTool</code>,实现 <code>name</code> / <code>description</code> / <code>args_schema</code> / <code>_run</code> 四要素即完成协议;<code>tools/__init__.py</code> 注册表一行挂载</li>
|
||||
<li class="li-rv"><strong>前端零改动</strong>:工具配置面板(工具列表、参数表单、权限/自动执行开关、main 默认挂载)全部由 <code>/api/config/tools</code> 的 <code>registered_tool_names</code> / <code>tool_parameters</code> / <code>forced_permissions</code> <strong>自动生成</strong>——新增工具自动出现在设置面板与 Agent 工具选择器</li>
|
||||
<li class="li-rv">展示类工具(如 <code>todo_list</code>)只需保持「纯文本返回」协议,前端按工具名写一个小 adapter 即可渲染通知条</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p class="reveal-up" style="color:var(--ink);font-weight:800;margin-top:20px">前端:<code>setXxxDeps / setXxxFn</code> 依赖注入协议(<code>src/web/js/*.js</code>)</p>
|
||||
<div class="lead reveal" style="margin-top:8px">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv">每个功能模块独立单文件,只导出 setter(协议接口)与自身功能函数,<strong>模块间零直接引用</strong>;宿主 <code>app.js</code> 作为装配中心做一次性连线(依赖注入):<code>setSendDeps({...})</code> / <code>setLiveUiDeps({...})</code> / <code>setRenderPersistentToolCalls(fn)</code> / <code>setRenderSkills(fn)</code></li>
|
||||
<li class="li-rv"><strong>事件监听式数据流</strong>:<code>toolcalls.js</code> 收到 live snapshot(SSE/轮询)后,通过 <code>setLiveUiDeps</code> 注入的回调分发给各展示组件——组件是被回调通知(监听事件),而非向全局注册表登记</li>
|
||||
<li class="li-rv"><strong>替换/新增模块零宿主改动</strong>:旧模块(如 <code>pending-overlay.js</code>)被新模块(<code>notify-strip.js</code>)替换时,只需保持协议导出签名(<code>setLiveUiDeps</code> / <code>updateTodoOverlayFromRecords</code> 等),宿主连线无需修改</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<hr class="section-divider">
|
||||
@@ -1500,11 +1554,11 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<tr><td><code>api.js</code></td><td>封装所有后端 API 请求</td></tr>
|
||||
<tr><td><code>state.js</code></td><td>全局状态管理</td></tr>
|
||||
<tr><td><code>send.js</code></td><td>消息发送逻辑</td></tr>
|
||||
<tr><td><code>chat-render.js</code></td><td>聊天消息渲染</td></tr>
|
||||
<tr><td><code>cron.js</code></td><td>定时任务管理面板</td></tr>
|
||||
<tr><td><code>sessions.js</code></td><td>会话列表管理</td></tr>
|
||||
<tr><td><code>toolcalls.js</code></td><td>工具调用实时面板</td></tr>
|
||||
<tr><td><code>todo.js</code></td><td>TodoList 面板</td></tr>
|
||||
<tr><td><code>chat-render.js</code></td><td>聊天消息渲染(双容器:chat / cron 各自独立,运行时增量渲染、空闲全量重渲染)</td></tr>
|
||||
<tr><td><code>cron.js</code></td><td>定时任务面板(按工作区分组列表、类 chat 会话式历史、模式切换锁、实时运行)</td></tr>
|
||||
<tr><td><code>sessions.js</code></td><td>会话列表管理(工作区分组,切换会话恢复会话级通知条状态)</td></tr>
|
||||
<tr><td><code>toolcalls.js</code></td><td>工具调用实时面板(思考 Thought / 反思 Reflection 分离显示,rAF 合并高频快照)</td></tr>
|
||||
<tr><td><code>notify-strip.js</code></td><td>★ 通知条系统:todo 与人机交互的输入区上方长条(收起/展开、按钮切换、会话级存储)</td></tr>
|
||||
<tr><td><code>edit-mode.js</code></td><td>编辑模式(Monaco)</td></tr>
|
||||
<tr><td><code>doc-tree.js</code> / <code>doc-mod-panel.js</code></td><td>文档树与修改面板</td></tr>
|
||||
<tr><td><code>action-bar.js</code></td><td>底部操作栏</td></tr>
|
||||
@@ -1520,7 +1574,7 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
<tr><td><code>token-ring.js</code></td><td>上下文 Token 用量环形指示器(含压缩阈值刻度与三类占比)</td></tr>
|
||||
<tr><td><code>access-mode.js</code></td><td>工作空间访问模式切换(限制访问 / 权限审查 / 完全访问)</td></tr>
|
||||
<tr><td><code>think-level.js</code></td><td>思考模式档位选择(low / high / xhigh / max / ultra)</td></tr>
|
||||
<tr><td><code>pending.js</code> / <code>pending-overlay.js</code></td><td>人工请求浮窗与决策提交(数据源为 live snapshot 的 <code>human_requests</code>)</td></tr>
|
||||
<tr><td><code>pending.js</code></td><td>人工请求决策提交(数据源为 live snapshot 的 <code>human_requests</code>,配合 notify-strip 渲染)</td></tr>
|
||||
<tr><td><code>rollback.js</code></td><td>消息回滚</td></tr>
|
||||
<tr><td><code>workspace.js</code></td><td>工作空间切换</td></tr>
|
||||
<tr><td><code>dialog.js</code></td><td>对话框</td></tr>
|
||||
@@ -1530,15 +1584,15 @@ cloudflared tunnel --url http://localhost:8765</pre>
|
||||
</div>
|
||||
|
||||
<h3 class="reveal" style="font-size:1.4rem;margin:44px 0 16px">CSS 架构(<code>src/web/css/</code>)</h3>
|
||||
<p class="reveal-up" style="color:var(--ink-soft)"><code>variables.css</code> 定义主题变量,其余按模块拆分:<code>base / layout / chat / composer / cron / dialog / settings / skills / todo / toolcalls / edit-mode / canvas-editor / audio / animations / pending / pending-overlay / toast / responsive</code>。</p>
|
||||
<p class="reveal-up" style="color:var(--ink-soft)"><code>variables.css</code> 定义主题变量,其余按模块拆分:<code>base / layout / chat / composer / cron / dialog / settings / skills / toolcalls / notify-strip / edit-mode / canvas-editor / audio / animations / toast / responsive</code>。</p>
|
||||
|
||||
<h3 class="reveal" style="font-size:1.4rem;margin:44px 0 16px">添加自定义工具</h3>
|
||||
<div class="lead reveal">
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv">在 <code>src/agent/tools/</code> 新建 <code>my_tool.py</code>,继承 LangChain <code>BaseTool</code>,实现 <code>_run</code>,填写 <code>name</code> / <code>description</code> / <code>args_schema</code></li>
|
||||
<li class="li-rv">在 <code>tool_config.json</code> 注册并配置启用状态与参数(权限设为 <code>confirm</code> 时,工具执行前会自动弹出确认浮窗,同意后执行、拒绝/跳过作为返回值继续)</li>
|
||||
<li class="li-rv">交互类工具(需要向用户提问)在 <code>_run</code> 中调用 <code>core/human_request.ask_human(meta)</code> 阻塞等待答案;展示类工具(如进度面板)返回纯文本即可,前端从 live 工具记录按工具名写 adapter 渲染浮窗</li>
|
||||
<li class="li-rv">重启后端,工具自动绑定到 LLM</li>
|
||||
<li class="li-rv">在 <code>src/agent/tools/</code> 新建 <code>my_tool.py</code>,继承 LangChain <code>BaseTool</code>,实现 <code>_run</code>,填写 <code>name</code> / <code>description</code> / <code>args_schema</code>(协议四要素)</li>
|
||||
<li class="li-rv">在 <code>config.json</code> 的 <code>tools</code> 分区注册并配置启用状态与参数(权限设为 <code>confirm</code> 时,工具执行前会自动弹出确认通知条,同意后执行、拒绝/跳过作为返回值继续);<strong>前端无需改动</strong>——设置面板工具列表 / 参数表单 / Agent 工具选择器由 API 自动生成</li>
|
||||
<li class="li-rv">交互类工具(需要向用户提问)在 <code>_run</code> 中调用 <code>core/human_request.ask_human(meta)</code> 阻塞等待答案;展示类工具(如进度面板)返回纯文本即可,前端从 live 工具记录按工具名写 adapter 渲染通知条</li>
|
||||
<li class="li-rv">重启后端,工具自动绑定到 LLM;若希望 main Agent 默认挂载,加入 <code>config_manager.MAIN_DEFAULT_TOOLS</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1567,7 +1621,7 @@ Copy-Item "src\web\js\themes.js" "src\web\js\themes.js" -Force</pre>
|
||||
<ul data-reveal-list="left" data-stagger="40">
|
||||
<li class="li-rv"><strong>后端日志</strong>:桌面端 <code>npm start</code> 会在终端打印 <code>[FastAPI]</code> 日志</li>
|
||||
<li class="li-rv"><strong>端口占用</strong>:<code>main.js</code> 的 <code>killPortProcess(8765)</code> 启动前自动清理</li>
|
||||
<li class="li-rv"><strong>重置配置</strong>:删除 <code>src/agent/config/env_config.json</code> 重触首次向导</li>
|
||||
<li class="li-rv"><strong>重置配置</strong>:删除 <code>src/agent/agents/config.json</code> 重触首次向导(或复制 <code>config_dist.json</code> 为新配置)</li>
|
||||
<li class="li-rv"><strong>工具调用轨迹</strong>:<code>history/sessions/{session_id}/tool_{turn_id}.json</code></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1589,7 +1643,7 @@ Copy-Item "src\web\js\themes.js" "src\web\js\themes.js" -Force</pre>
|
||||
<tr><td>🐍 <strong>Python 版本</strong></td><td>建议 Python 3.11 / 3.12 / 3.13;首次向导会自动检测</td></tr>
|
||||
<tr><td>🔐 <strong>未签名安装包</strong></td><td><code>.exe</code> 可能被 Windows Defender 拦截,点「更多信息 → 仍要运行」</td></tr>
|
||||
<tr><td>🌐 <strong>首次启动联网</strong></td><td>加载 Google Fonts 需联网;离线环境字体选择器有 HTML 硬编码兜底</td></tr>
|
||||
<tr><td>🔑 <strong>API Key 安全</strong></td><td><code>env_config.json</code> 含明文凭证,<strong>勿提交到公开仓库</strong>(已在 <code>.gitignore</code> 排除 <code>env_config.json</code>,仅保留 <code>env_config_dist.json</code> 模板)</td></tr>
|
||||
<tr><td>🔑 <strong>API Key 安全</strong></td><td><code>src/agent/agents/config.json</code> 含明文凭证,<strong>勿提交到公开仓库</strong>(已在 <code>.gitignore</code> 排除,仅保留 <code>config_dist.json</code> 模板)</td></tr>
|
||||
<tr><td>🎨 <strong>图标</strong></td><td>当前为 SVG,NSIS 打包后若显示默认图标,需准备 <code>.ico</code> 文件替换 <code>src/web/image/icon.ico</code></td></tr>
|
||||
<tr><td>💾 <strong>历史存储</strong></td><td>默认会话历史与工具轨迹以 JSON 落盘在 <code>history/</code>(可切换 MySQL 后端),长期使用注意清理</td></tr>
|
||||
<tr><td>⚡ <strong>GUI 性能</strong></td><td>同页多操作务必合并为一次 <code>gui</code> 调用,否则延迟显著(见「实现细节」)</td></tr>
|
||||
|
||||
Reference in new issue
Block a user