Skip to content

Repository files navigation

minor Agent

一个可本地运行的多模态 Agent 桌面应用 —— 真正能"动手"操作你电脑的 AI 助手

基于 LangGraph 构建,具备 GUI 自动化、浏览器控制、终端执行、RAG 知识库、邮件收发、图像生成、语音对话、数据库操作、定时任务等 20 项工具,并提供 Electron 桌面端一键安装体验。

minor Agent 主界面

功能亮点 · 快速开始 · 项目架构 · 开发手册 · LLM 推理服务


📖 项目简介

minor Agent 最初按 Web 在线应用开发,后转为本地桌面应用开源。它不是又一个"对话框 + 联网搜索"的套壳 Agent,而是一个以"工具执行 + 视觉闭环"为核心的通用智能体:

🎓 项目初衷:这是一个 LangChain + LangGraph 的学习项目。基于两者构建 Agent 工作流,结构清晰、上手容易、扩展方便,适合作为 Agent 开发的参考实现。

  • 🖥️ 真能操作桌面:截图 → 视觉定位 → 键鼠模拟,闭环完成 ERP 录入、表单填写、软件操控
  • 🧩 20 项内置工具 + 单文件插件化:从终端命令到邮件收发,从 PPT 制作到图像生成;新增工具 = 一个文件 + 协议接入,前端面板自动生成,无需大面积改动
  • 🏠 完全本地运行:Electron 打包,数据不出本机;后端 FastAPI + 前端零延迟直读磁盘
  • 🎨 可深度定制:主题 / 字体 / 字号 / 背景 / 工作空间 / 提示词分层架构,全部可调
  • 🔁 工程级稳定性:循环检测、上下文压缩、阻塞式人工确认、轨迹回放,对抗 LLM 的"幻觉操作"
  • 💾 存储多后端(接口隔离):会话与定时任务存储统一接口驱动,JSON / MySQL / SQLite 一键切换、不双写;存储数据库与工具数据库配置隔离;新增存储方式只需实现接口,消费方无感知后端

💡 项目演进:Web 在线应用Electron 桌面应用。源码同一套 src/,既可由 uvicorn 作 Web 服务启动,也可由 Electron 主进程拉起,双模式共用

系统架构总览


✨ 功能亮点

🛠️ 20 项工具能力

工具 文件 能力
🖱️ gui tools/gui.py 桌面 GUI 自动化:截图、视觉批量定位、点击/输入/快捷键/滚动(桌面/任意应用轨)
🌐 browser_control tools/browser_control.py 浏览器打开/关闭、地址导航、标签页交互(Playwright + CDP 分离进程,Profile 默认一次性临时目录,可配置持久)
🧭 web_page tools/web_page.py 浏览器页面 DOM 级精准操作(浏览器轨):snapshot 元素清单、click/fill/scroll/press/extract/screenshot/eval_js 等,毫秒级、优于 GUI 视觉定位;典型流程 browser_control 打开 → web_page 操作
💻 terminal_execute tools/terminal_execute.py 执行任意终端命令(含目录/文件操作,可替代 directory_listing),支持工作目录与超时;background=True 挂起长驻任务(立即返回任务ID/PID,不阻塞;不支持交互式输入,密码/采集输入类命令应放弃并建议用户手动执行)
📟 terminal_info tools/terminal_info.py 查看挂起的后台终端任务状态(运行中/已完成/异常退出/已终止)与最新输出(截断 1000 字符)
wait tools/wait.py 通用等待工具:阻塞等待指定后台任务结束并取回最终输出(超时返回运行中摘要)
🪟 software_control tools/software_control.py Win32 API 启停软件、注册表、os.startfile
📧 email tools/email.py IMAP 收邮件 + SMTP 发邮件(含附件)
📄 doc tools/doc.py 创建/读取/编辑 docx / xlsx / pptx / pdf / txt
📨 send_file tools/send_file.py 以邮件附件形式发送本地文件
🔍 web_search tools/web_search.py 联网搜索(Tavily / Firecrawl / 火山引擎)
🗄️ text2sql tools/text2sql.py 自然语言/SQL 操作数据库(MySQL / SQLite,工具数据库配置):查表结构、查询、增删改、建库建表
📚 rag tools/rag.py ChromaDB 向量检索 + Reranker 重排序
🎨 image_gen tools/image_gen.py 调用 Z-Image-Turbo 生成图片
todo_list tools/todo_list.py 多步任务规划与进度跟踪
🤝 human_interaction tools/human_interaction.py 阻塞式询问用户:收集信息 / 多选一,答案作为普通工具返回值
🤖 agent_call tools/agent_call.py 委派子 Agent 处理子任务
🧭 skill_router tools/skill_router.py 匹配并路由到预定义 Skill 流程
📅 date_query tools/date_query.py 当前日期时间查询
cron_manager tools/cron_manager.py 定时任务管理:查看/新增/修改/删除定时任务,支持 cron/间隔/一次性触发
📊 hard_excel_read tools/hard_excel_read.py 复杂 Excel 表结构读取:前 N 行原始数据 + 维度/合并区/数据区范围建议,供大模型解析结构
📥 excel2sql tools/excel2sql.py 按大模型给定的数据行列范围,将 Excel 数据区流式批量入库(MySQL / SQLite,自动建库建表)

🔒 main Agent 默认挂载(代码强制注入,不可通过配置移除,前端显示为锁定项):call_subagent(子 Agent 委派)、doc_tool(文档读写)、human_interaction(人机交互审查)、todo_list(任务规划)、terminal_execute(终端命令,含挂起)、terminal_info(终端信息)、wait(等待)。其余工具按 config.json 中 main agent 的 tools 列表自行增删;子 Agent 无此限制。

🎯 区别于其他 Agent 项目的核心设计

设计点 多数 Agent 项目 minor Agent
GUI 操作粒度 一步一调用,N 个动作 = 2N+1 次 LLM 调用 动作序列合并:同页多操作打包为一次 gui 调用,N 个动作仅 2 次 LLM 调用
UI 自动化双轨 单轨(截图 + 坐标模拟) Playwright + GUI 双轨兼顾容错与效率:浏览器内走 DOM 级精准操作(web_page 毫秒级、定位可靠);桌面/任意应用走 GUI 视觉定位(gui_tool 截图视觉闭环、可处理任意界面)——浏览器能 DOM 就不截图,桌面无 DOM 就走视觉
视觉反馈 仅返回坐标文本 截图作为视觉闭环注入上下文,多模态 LLM 看到真实屏幕状态
坐标定位 逐元素请求 批量定位 _batch_ground_elements:N 个元素 1 次子模型调用
循环失控 无防护,token 烧穿 循环检测:连续同工具同参(默认 3 次)注入反思警告,引导模型自我纠偏
上下文膨胀 简单截断 图内分级压缩:token 超 窗口×COMPRESS_RATE 触发,压缩历史工具调用为累积摘要,每步 LLM 调用后检查
上下文连续性 思考链跨轮丢失 历史思考/反思注入:压缩游标后的思考、反思、工具调用按因果顺序交错注入(稳定 id、确定性构建,前缀缓存友好);深度思考与反思分离存储
部署形态 仅 Web / 仅 API 同一套源码双模式uvicorn Web 服务 ↔ Electron 桌面应用
文件操作 HTTP 上传下载 桌面端走 IPC 直读磁盘,零延迟;Web 端走 /api/fs/*
提示词 单层 system prompt 四层提示词架构:系统级 / 工具描述 / 运行时注入 / 内部子模型
插件化 注册式插件表(适配新插件需改框架主流程) 前后端单文件插件化:后端按 BaseTool 协议单文件实现、前端按 setXxxDeps 依赖注入协议接入,监听事件 / 回调驱动而非注册式——新增或替换一个插件只需保持协议签名,宿主装配零改动

🖼️ 运行界面

Agent 运行过程中的关键交互界面,支持文件从任意位置拖拽到聊天区或编辑区,灵活组织工作流:

人机交互确认 任务规划 TodoList
人机交互确认 — 敏感操作(终端执行、文件写入等)与信息收集以「输入区上方通知条」形式实时弹出:只显示标题与数量角标,点击展开为完整卡片(标题/内容/选项胶囊/补充输入框),选择或补充后作为工具返回值,Agent 继续执行;**拒绝也只是一次工具返回值**,Agent 自行调整方案继续,不会结束本轮 | 任务规划 TodoList — 多步任务自动拆解与进度跟踪,同样以通知条展示(最新步骤 + 数量角标,可展开全部步骤),Todo 状态**会话级存储**(chat 与 cron 各自独立,切换会话自动恢复) | 后台终端任务 — `terminal_execute(background=True)` 挂起的长驻任务以第三条通知条展示("x 后台运行中 - y 已完成",展开可终止/查看状态);点击顶栏终端按钮展开底部终端栏,Agent 挂起任务以 "任务#PID" 标签与用户交互式 PowerShell 终端并列且视觉区分,实时滚动输出

文件编辑模式 工具调用记录
文件编辑模式 — 内置 Monaco 编辑器,支持代码高亮、差异对比、文件树拖拽组织 | 工具调用记录 — 实时展示每轮 ReAct 的工具调用链、参数及返回值;思考(reasoning_content)与反思(content)分离显示为独立的 Thought / Reflection 行

子 Agent 嵌套调用
子 Agent 嵌套调用 — 主 Agent 委派子 Agent 执行子任务,工具调用以嵌套结构展示,思考过程穿插显示,支持展开/折叠查看详情

定时任务创建 Edit 编辑模式
定时任务管理 — 支持 cron / 间隔 / 一次性三种触发方式;任务按**工作区分组**展示;任务会话与聊天同构(点击会话式查看历史、多轮对话、流式渲染),任务在**独立子进程**中执行;模式切换锁:chat 运行时可查看 cron、cron 运行时可查看 chat,双容器渲染不打断流式输出 | Edit 编辑模式 — 独立编辑区,Monaco 编辑器 + 文档树侧栏,支持拖拽文件/文件夹到附件区发送给 Agent

图片修改画板
图片修改画板 — 附件图片缩略图 hover 显示删除按钮,点击图片打开预览浮窗,支持下载/修改/关闭;点击「修改」进入画板编辑器,在底图上使用画笔/矩形/圆形/直线/文字/橡皮擦进行标注编辑,Ctrl+滚轮缩放,中键拖动平移,支持撤销/重做,确定后替换原图

空白画板
空白画板 — 输入区画板按钮一键打开 1536×768 空白画布,支持画笔/矩形/圆形/直线/文字/橡皮擦绘图,颜色与粗细可调,文字对象可拖拽/缩放/旋转,Ctrl+滚轮缩放画布,中键平移,完成导出为 PNG 自动添至附件区


🏗️ 项目架构

整体分层

┌──────────────────────────────────────────────────────────────┐
│                   Electron 主进程 (main.js)                    │
│   窗口管理 · 首次配置向导 · Python 生命周期 · 端口清理 · IPC    │
└───────────────────────────────┬──────────────────────────────┘
                                 │ spawn uvicorn (127.0.0.1:8765)
                                 ▼
┌──────────────────────────────────────────────────────────────┐
│                   FastAPI 后端 (web/server.py)                 │
│   会话管理 · 多模态收发 · SSE 流式 · 文件服务 · 工具调用推送    │
└───────────────────────────────┬──────────────────────────────┘
                                 │ turn_runner.start_turn()
                                 │(每会话一个后台线程,HTTP 请求
                                 │  挂载等待;断连不影响执行)
                                 ▼
┌──────────────────────────────────────────────────────────────┐
│                Agent 编排层 (agents/agent_runtime.py)          │
│   消息拼装 · 历史持久化 · 跨轮工具上下文 · 实时推送             │
└───────────────────────────────┬──────────────────────────────┘
                                 │ graph.invoke()
                                 ▼
┌──────────────────────────────────────────────────────────────┐
│            LangGraph ReAct 图 (core/graph.py)                 │
│   agent 节点 → tools 节点 → process_tool_artifact 节点         │
│   内含: 动态尾部注入 · 压缩 · 循环检测 · 路由                  │
│   人机交互: 阻塞式普通工具(core/human_request.py)            │
└───────────────────────────────┬──────────────────────────────┘
                                 │ 调用
                                 ▼
┌──────────────────────────────────────────────────────────────┐
│             20 项工具 (tools/*.py) · 5 项技能 (skills/)        │
└──────────────────────────────────────────────────────────────┘

ReAct 循环(图内)

START → [agent: call_model] ──有 tool_calls──▶ [tools: 并行工具节点] ──▶ [process_tool_artifact] ──▶ [compress]
              ▲                                      ▲                     │                            │
              │ 无 tool_calls                        │                     ◀────────────────────────────┘
              ▼                                      └── 子 Agent 结果 / 工具返回值注入 ◀── 并行工具节点(线程池)
             END
  • call_modelcore/nodes.py):追加动态尾部(TodoList 状态 + 循环提醒;固定反思引导已并入系统提示词前缀)→ LLM 调用 → 每步检查压缩(token 超阈值标记)→ 提取 thinking
  • should_continuecore/routing.py):含 tool_calls → 循环检测 → 路由到 toolsEND(需人工确认的工具不在此暂停,而是在工具执行钳点阻塞征求用户意见,见「阻塞式人机交互」)
  • process_tool_artifact:gui 截图作为 synthetic HumanMessage 注入,实现视觉闭环
  • compresscore/nodes.py):token 超 窗口×COMPRESS_RATE 时,将历史工具调用压缩为累积摘要(见「实现细节」)

多 Agent 模式

多 Agent 并非独立图,而是同一张 react 图内的工具级并行tools 节点由 make_parallel_tool_node(线程池)取代 ToolNode,一轮内的多个工具调用并行执行;其中 agent_call 工具会以主 Agent 当前消息快照启动子 Agent 的独立图实例执行子任务,结果以工具返回值注入主 Agent 上下文。子 Agent 内的人机交互同样为阻塞式——在子图线程中等待通知条应答,完成后自然回到主图:

[agent] ──有 agent_call──▶ [tools: parallel_tool_node(线程池)]
                               │
                               ├─ 普通工具:直接并行执行
                               └─ agent_call:spawn 子 Agent Runtime → 子图 invoke
                                              │(子图内 human_interaction 阻塞等待
                                              │  通知条应答,答案作为工具返回值)
                                              └─ 结果作为 ToolMessage 注入主 Agent ◄┐
          ▲                                                                          │
          └──────────────── 有 agent_call → 继续循环;无 → END ──────────────────────┘

📂 项目结构

Agent/
├── electron/                    # 🖥️ Electron 桌面端
│   ├── main.js                  #   主进程:窗口/IPC/Python生命周期/端口清理
│   ├── preload.js               #   安全桥接层:fs/dialog/window/Python setup API
│   └── setup.html               #   首次配置向导(3 步:Python环境 → LLM → 高级参数)
│
├── src/
│   ├── agent/                   # 🧠 Agent 核心
│   │   ├── agents/
│   │   │   ├── 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 / 压缩
│   │   │   ├── runtime.py       #   图执行器:消息拼装、历史加载、轨迹落盘
│   │   │   ├── routing.py       #   should_continue 路由
│   │   │   ├── state.py         #   Graph 状态定义(messages / agent_mode)
│   │   │   ├── loop_detector.py #   循环检测:重复工具调用,反思警告
│   │   │   ├── human_request.py #   ★ 人工请求注册表:交互类工具的通用阻塞通道(ask_human)
│   │   │   ├── turn_runner.py   #   ★ 后台线程轮次执行器(解耦 HTTP 与图执行生命周期)
│   │   │   ├── llm.py           #   ChatQwen 多模态封装(图像/附件/非标准 tool_call)
│   │   │   ├── tool_policy.py   #   工具执行策略(直执 / 需确认)
│   │   │   ├── 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,含 workspace 字段)
│   │   │   ├── storage.py        #     转发层(实现统一在 core/storage.py)
│   │   │   ├── scheduler.py      #     调度计算与触发扫描
│   │   │   ├── runner.py         #     任务执行器(独立子进程,切换存储 cron 作用域)
│   │   │   └── live.py           #     常驻调度循环
│   │   ├── skills/              #   5 项技能(skill.json + skill.md)
│   │   │   ├── netease_mail_read/
│   │   │   ├── netease_mail_send/
│   │   │   ├── ppt_maker/       #   HTML 模板 → PPT(含 9 个附件文档 + 模板)
│   │   │   ├── taste/           #   代码生成界面美化
│   │   │   └── wechat_send_message/
│   │   ├── tts/
│   │   │   └── streaming_client.py  # 流式 TTS 客户端(SSE 收音频块)
│   │   ├── history/
│   │   │   ├── session_storage.py     # 转发层(实现统一在 core/storage.py)
│   │   │   ├── 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
│   │   ├── memory/              #   系统提示词 / 会话历史
│   │   └── data/                #   运行时数据(浏览器 Profile 等,不入库)
│   │
│   └── web/                     # 🎨 前端 UI
│       ├── server.py            #   FastAPI 后端(75+ 路由)
│       ├── ui_session.py        #   UI 会话状态管理
│       ├── index.html           #   主页面(侧边栏/聊天/编辑/Agent面板/操作栏)
│       ├── app.js / app.css     #   入口
│       ├── js/                  #   30 个前端模块(见开发手册)
│       ├── css/                 #   18 个样式模块 + variables.css 主题变量
│       ├── packages/            #   Monaco Editor 本地 npm 包
│       └── image/               #   SVG 图标资源
│
├── llm_server/                  # 🧠 LLM 推理服务(独立部署,详见该目录 README)
├── git_image/                   # 📸 README 展示图片
├── package.json                 # Electron + electron-builder 配置
├── requirements.txt             # Python 依赖
└── README.md                    # 本文件

🚀 快速开始

minor Agent 提供两种运行方式:桌面应用(推荐)Web 开发模式。两者共用同一套 src/ 源码。

方式一:桌面应用(推荐体验)

1. 安装依赖

cd C:\Users\86166\Desktop\Agent_Learning_minor\Agent

# 设置国内镜像(可选,加速 Electron 下载)
$env:ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"

npm install

2. 启动应用

npm start

首次运行会弹出配置向导(3 步),写入 src/agent/agents/config.json 后自动启动:

步骤 配置内容 说明
Step 1 Python 环境 选择 / 自动检测系统 Python 主进程会调用系统 Python 启动 uvicorn;可选自动 pip install 依赖
Step 2 LLM 设置 base_url / api_key / model 必填;可填任何 OpenAI 兼容端点
Step 3 高级参数 TTS / ASR / RAG / 搜索 / 压缩 / 循环阈值 可选;不填则对应能力禁用

💡 之后启动直接进入主界面,不再弹向导。如需重配,删除 src/agent/agents/config.json(或复制 config_dist.json 为新配置)即可重触首次流程。

3. 打包为安装程序

# 设置镜像 + 自定义缓存目录后构建
$env:ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
$env:ELECTRON_BUILDER_CACHE="$PWD\electron-builder-cache"
npm run build

输出 dist/minor Agent Setup 1.0.0.exe,双击安装即可。安装包使用系统 Python + 运行时安装依赖方案,体积远小于打包完整 venv 的方案。

📦 打包原理(点击展开)
  • package.jsonbuild.files 仅打包 electron/src/requirements.txt排除 config.json(每个用户独立生成,模板 config_dist.json 随包分发)
  • asar: false:源码不加密,便于审计与二次开发
  • NSIS 安装器:允许改安装目录、创建桌面/开始菜单快捷方式、卸载时清理 AppData
  • 首次启动由 setup.html 向导引导:检测 Python → 配置 LLM → 写 config.json → 启动 FastAPI → 加载 UI
  • 主进程 findSystemPython() 依次检查:用户配置路径 → 常见 Python 安装位置 → PATH 中的 python

方式二:Web 开发模式(调试用)

适合前端开发与快速迭代,无需 Electron。

cd C:\Users\86166\Desktop\Agent_Learning_minor\Agent

# 1. 创建并激活虚拟环境
python -m venv myenv
.\myenv\Scripts\Activate.ps1          # Windows
# source myenv/bin/activate           # macOS / Linux

# 2. 安装依赖
pip install --upgrade pip
pip install -r requirements.txt

# 3. 配置环境(首次)
#    复制模板并填写 LLM 凭证
Copy-Item src\agent\agents\config_dist.json src\agent\agents\config.json
#    编辑 config.json,至少填写 env.models[].base_url / api_key / model

# 4. 启动 Web 服务
$env:PYTHONPATH="src;$env:PYTHONPATH"
uvicorn web.server:app --host 127.0.0.1 --port 8765 --reload

# 5. 浏览器打开
#    http://127.0.0.1:8765
🌐 (可选)公网暴露
# 通过 Cloudflare Tunnel 临时暴露
cloudflared tunnel --url http://localhost:8765

⚙️ 配置说明

所有运行时配置集中在 src/agent/agents/config.json(合并单文件,含 agents / tools / env / gui / workspace / theme 分区),模板见 config_dist.json,首次向导自动生成。env 分区的关键字段:

字段 默认值 说明
models[] SETUP_REQUIRED LLM 列表:{id, name, model, api_key, base_url, timeout, max_retries};ASR / TTS / RAG / ImageGen 四个本地服务也在此注册(按 model 字段匹配,api_key 留空)
gui_model_id "" GUI 视觉定位专用模型(留空则回退主模型)
USER_PYTHON_PATH "" 指定 Python 解释器路径
LLM_TIMEOUT 60 LLM 单次请求超时(秒)
LLM_MAX_RETRIES 3 LLM 调用超时自动重试次数(仅 ReAct 节点调用;重试期间前端提示"超时正在重试")
LLM_CONTEXT_WINDOW 262144 上下文窗口大小(token)
COMPRESS_RATE 0.6 上下文压缩阈值比例(0~1),token 用量超过 窗口×该值 时触发压缩
IMG_SIZE 768 截图短边尺寸
GROUNDING_WIDTH/HEIGHT 1000 视觉定位输入分辨率
LOOP_DETECT_REPEATED_TOOL_WARN 3 连续同工具同参多少次注入反思警告
RAG_CHUNK_SIZE / OVERLAP 500 / 50 RAG 分块大小与重叠
SEND_FILE_SIZE_LIMIT 30 发送文件大小上限(MB)
WEB_SEARCH_API_KEY "" 联网搜索 API Key
WEB_SEARCH_ENGINE "tavily" 搜索引擎选择(tavily / firecrawl / volcengine)
STORAGE_BACKEND "json" 存储后端:json(本地文件)/ mysql / sqlite
STORAGE_DB_TYPE "" 存储数据库类型(mysql / sqlite;留空随 STORAGE_BACKEND 推导)
STORAGE_DB_HOST / PORT / USER / PASSWORD / DATABASE / PATH "" 存储数据库连接参数(mysql 用 host/port/user/password/database;sqlite 用 path,留空默认 history/sqlite/storage.sqlite);缺省回退旧 MYSQL_*
TOOL_DB_TYPE "mysql" 工具数据库类型(mysql / sqlite)——数据库操作工具(text2sql / excel2sql)专用,与存储后端完全隔离
TOOL_DB_HOST / PORT / USER / PASSWORD / DATABASE / PATH "" 工具数据库连接参数(sqlite path 留空默认 history/sqlite/tool 目录,每个库名一个 .sqlite 文件)
MYSQL_* "" 旧键:存储数据库 MySQL 参数(已被 STORAGE_DB_* 取代,仅作回退兼容)
BROWSER_PROFILE_DIR "" 浏览器控制工具持久 Profile 目录;留空 = 每次启动一次性临时 Profile(登录态不持久、不留盘)
TOOL_TIMEOUT 300 工具执行超时时间(秒)
CRON_TIME_PERIOD_MINUTES 30 定时任务时段长度(分钟),同一时段全局并发=1
EMAIL_ADDRESS / EMAIL_AUTH_CODE "" 邮箱凭证(IMAP/SMTP)

⚙️ 思考档位(low / high / xhigh / max / ultra)为会话级配置(存于各会话 session_meta.json);以上参数均可在主界面「设置」面板热修改,或通过 /api/config/* 接口程序化调整。

⚠️ 首次向导中的「轻度压缩率 / 深度压缩率」(写入 MINI_COMPRESS_RATE / HARD_COMPRESS_RATE)目前不参与运行时逻辑——运行时仅使用单一 COMPRESS_RATE(默认 0.6,见「实现细节 · 上下文分级压缩」),两键为兼容性预留。

设置面板包含 11 个分组,覆盖 Agent 运行的全部可调参数:

Agent 配置 工具配置
Agent 配置 — 管理多个 AI 角色,各自绑定独立模型与工具集(main Agent 默认挂载 5 个工具为锁定项,不可移除) | 工具配置 — 启用/禁用工具、调整参数及执行策略

环境变量 GUI 设置
环境变量 — LLM 密钥、路径、压缩阈值等全局参数 | GUI 设置 — 选择 GUI 自动化操作的目标显示器

主题配置
主题配置 — 12 套预设主题 + 自定义背景 / 模糊度 / 暗角 / 字体;另含 常规 / 模型 / Skills / 网络搜索 / 邮件 / 存储与数据库 / 运行时参数 等分组


🧠 实现细节

1. 四层提示词架构

层级 位置 注入时机 作用
L1 系统级 memory/system_prompt.py 会话开始 MAIN_SYSTEM_PROMPT 定义角色;PLAN_MODE_PROMPT 强制先规划;固定反思引导 REFLECTION_PROMPT 并入系统提示词前缀(思考关闭档位,前缀缓存友好)
L2 工具描述 tools/*.pydescription 工具绑定时 指导 LLM 正确调用(含 one-shot 示例)
L3 运行时动态尾部 nodes.py / loop_detector.py 每轮 ReAct 变化部分(TodoList 状态 + 循环警告)作为动态尾部追加到消息末尾,并持久化为长期记忆(session_meta.dynamic_tail_history)供后续轮次查看
L4 内部子模型 gui.py _build_batch_prompt 工具内部 批量坐标定位,one-shot 强制纯坐标输出

1.1 前缀缓存(Prompt Caching)

上下文按「前缀稳定性」布局,最大化利用 LLM 服务端的前缀缓存:

[系统提示词(含固定反思引导,稳定) + 链式压缩块 #1..#N(只增不删)]
+ [压缩游标后的原生历史(user → AI(思考/反思/工具调用) → Tool* → 尾部反思 → 最终回复)]
+ [本轮用户消息] + [动态尾部(每轮变化)]
  • 固定部分放前缀:反思引导等不变提示文本并入系统提示词、链式压缩块按序位于其后(字节不变、只增不删)——前缀稳定即可命中缓存;避免把固定文本逐轮塞在消息中间导致整段缓存失效。
  • 原生历史重建build_native_history_messagesutils/agent_utils.py):压缩游标之后的所有轮次,按 turn 文件确定性重建为原生 LangChain 消息——HumanMessage(文本/图片/附件多模态部分)、AIMessage(思考→additional_kwargs.reasoning_content、反思→content、工具调用→tool_calls,同一模型响应的并行调用合并为一条)、ToolMessagetool_call_id/name 严格匹配);单轮顺序:user → (AI + Tool)* → 未被消费的尾部反思(文本去重)→ 最终无工具回复。消息 id 稳定(hist_user_{tid} / hist_assist_{tid}_{g} / hist_tool_{tid}_{g}_{i} / hist_tail_{tid}_{i} / hist_final_{tid}),注入只追加在末尾 —— 满足前缀缓存命中条件;压缩节点按 id 精确移除。
  • 思考/反思原生透传llm.pyMultimodel_LLM._get_request_payload 在 LangChain 消息转换后补回 assistant 消息的 reasoning_content 字段(langchain-openai 默认丢弃该附加字段),使深度思考以原生 AIMessage 字段进入请求体(前缀缓存格式);图中当前轮的 [思考]/[反思] 合成为兜底(原生历史不再合成,消息带 reasoning_content 时跳过)。
  • 思考与反思分离:深度思考(reasoning_content)与反思(content独立存储(工具记录的 thinking / reflection 字段 + 轮末 reflections 列表),重建时分别落入 AIMessage 的 reasoning_contentcontent,二者可同时存在。
  • 变化部分放末尾:TodoList 状态、循环警告等每轮变化的内容追加在消息列表末尾,变化只影响尾部、不破坏前缀缓存;无 TodoList 且无循环提醒时不注入任何尾部提示(省 token)。
  • 动态尾部作为长期记忆:每轮尾部文本持久化到 session_metadynamic_tail_history(连续相同去重),后续轮次把全部历史尾部注入上下文,Agent 能看到之前所有轮的 TodoList 状态与循环提醒。

2. 上下文分级压缩(图内)

多级压缩机制

每次 LLM 调用后读取 response.usage_metadata.total_tokens
   ├─ 未超阈值        → 不处理,继续下一轮
   ├─ 主 Agent 超阈值 → 标记压缩,由 compress 节点统一执行:
   │    将「上次游标后 → 当前用户消息前」的全部原生历史压缩为摘要块,
   │    以链式压缩块追加存储(只增不删),RemoveMessage 移除已覆盖消息
   └─ 子 Agent 超阈值 → 注入整理提示词,整理进度后直接返回主 Agent(子 Agent 不压缩)
  • 触发call_model 内每步检查 total_tokens,超过 LLM_CONTEXT_WINDOW × COMPRESS_RATE(默认 0.6,即 262144 × 0.6 ≈ 157k)即标记压缩
  • 压缩范围:上次压缩游标之后 → 当前轮用户消息之前全部原生历史——思考/反思、对话(user/AI)、工具调用与返回值均压缩;固定提示词(系统提示词 + 工具描述,后者为 API 级 bind_tools 非消息)永不压缩;当前进行轮不压缩(其消息保持原样,下一轮起随重建进入压缩范围)
  • 合并:相邻同角色消息(多条 HumanMessage / 多条 AIMessage)预合并为一条大单元再送摘要模型(工具结果不合并),合并后的单元数计入统计
  • 链式存储:摘要追加为压缩块写入 session_meta.main.compressed_contextblocks 数组,seq 递增),不覆盖旧块cursor_msg 推进到压缩末尾的全局单元序号(每条消息 = 1 个单元,1 起)
  • 替换语义:以 RemoveMessage 精确移除被覆盖的 hist_* 原生消息,图内追加固定 idcompressed_block_{seq})的摘要 SystemMessage;下一轮由 runtime._inject_summary_context 将全部块放回系统提示词之后的前缀位置(图内只能尾部追加)

补充细节(与 nodes.py 一致):

  • 触发位置execute_agent 节点每次 LLM 响应后调用 _maybe_trigger_compressnodes.py),子 Agent 超限返回 sub_oom(注入整理提示词引导其总结任务进度后返回),主 Agent 超限置 _need_compress=True 交给图内压缩节点;同时将 token 用量与「消息 / 工具 / 系统提示词」三类占比估算存入 tool_call_recorder 并聚合 usage_stats(前端环形指示器 + 欢迎区活跃度矩阵的数据源)
  • 摘要生成summarize_chat_text(默认 LLM)对合并后的文本生成摘要;统计项:msg_from/msg_to(消息区间)、units/merged_units(原始/合并单元数)、turns(按 YYYYMMDD_HHMMSS 轮次去重)、tokens_before/tokens_after(CJK≈1 字符/token、ASCII≈4 字符/token 的估算口径)
  • 流式反馈:压缩以「summarizer」虚拟工具记录经 live SSE 推送(压缩中附统计 / 完成附统计 / 失败),前端工具面板可见
  • 异常路径:压缩 LLM 超时 → 本轮中止并由 execute_agent 回复「压缩节点超时」(消息不删、完整保留落盘);其他异常 → 跳过压缩直接继续本轮

3. 循环检测(反思警告)

在 ReAct 循环的 agent 节点调用 LLM 前,检测连续相同工具调用(仅保留警告响应,强制终止已移除):

触发条件 响应
连续同工具同参 ≥ LOOP_DETECT_REPEATED_TOOL_WARN(默认 3) 注入反思提示引导模型自我纠偏:更换工具或策略、检查之前的工具返回结果、无法推进时向用户说明困难并请求帮助

4. 阻塞式人机交互(交互类 / 展示类工具的统一模式)

人机交互不再"暂停图 + 存快照 + 续跑",而是阻塞式普通工具:工具在图上线程中等待前端应答,答案(同意 / 拒绝 / 跳过 / 补充信息)只是普通工具返回值,图自然继续——拒绝不会结束整轮,Agent 自行调整方案。

LLM 发出 human_interaction / 需确认工具调用
   → tools 节点执行工具
   → human_request.ask_human() 阻塞等待(注册到请求表,随 live snapshot 推送前端)
   → 前端"通知条"出现(输入区上方,标题 + 数量角标),工具调用行显示"运行中"
   → 用户点击展开 → 选项胶囊 / 补充输入框 → 提交(POST /api/human-action)→ 写入答案并唤醒
   → 工具返回答案文本 → ToolMessage → 图继续(无快照重放、无续跑状态机)

通知条(notify-strip):todo 与人机交互不再使用浮窗,改为输入区上方的水平通知条——收起态只显示标题/最新步骤 + 数量角标,点击上下展开完整卡片;通知条左侧按钮可收起为输入区按钮,再次点击恢复;todo 与人机交互的挂起状态会话级存储(chat 与 cron 各自独立,切换会话自动保存/恢复)。

设计点 传统做法(本项目旧版) 阻塞式(当前)
图执行 请求线程内同步 invoke 后台线程(core/turn_runner.py),断连/关页不影响执行,双发请求挂同一轮
等待答案 图 END + 消息快照存 PENDING_TOOL_APPROVALS 工具内 threading.Event 阻塞(core/human_request.py
决策处理 continue_after_human_action 重放快照续跑 答案即返回值,无续跑路径
拒绝 结束整轮(等同手动暂停) 仅返回值,Agent 调整后继续
工具列表 确认时清空重建、续跑时重放 自然展示:等待中 running → 应答后 done
子 Agent 交互 异常冒泡(SubAgentPendingError)+ 恢复状态机 子图线程内直接阻塞,完成自然回主图
无人值守(cron) 悬死靠超时兜底 ask_human 检测 headless 立即返回默认答案

两类工具的扩展模式(新增能力零框架改动):

  • 交互类工具(如 human_interaction):工具内调一次 ask_human(meta) 阻塞,自己格式化返回值
  • 展示类工具(如 todo_list):纯文本返回、不维护全局 store,前端从通用 live 记录(工具调用的 args/结果)按工具名写一个小 adapter 渲染通知条(如 js/notify-strip.js

5. GUI 动作序列化(性能关键)

模式 N 个动作的 LLM 调用次数
单步执行(多数项目) 2N + 1
序列合并(本项目) 2(1 次批量定位 + 1 次决策)

通过系统提示词前缀中的固定反思引导(REFLECTION_PROMPT)+ MAIN_SYSTEM_PROMPT 双重强调"同页操作必须合并为一次 gui 调用"实现。

5.1 UI 自动化双轨(Playwright + GUI,兼顾容错与效率)

UI 操作按目标介质分两条轨道,由系统提示词引导 Agent 按"能 DOM 不截图"的原则选择:

轨道 工具 机制 适用场景 特点
浏览器轨 browser_control + web_page Playwright 会话管理器(CDP 分离进程,Agent 退出后浏览器保留、重启自动重连)+ DOM 级操作 浏览器内的网页操作 毫秒级、定位可靠(snapshot 元素清单 → ref/selector 精准操作,不依赖视觉模型)
桌面轨 gui 截图 + 视觉批量定位(_batch_ground_elements)+ 键鼠模拟 桌面应用 / 任意界面(含浏览器无 DOM 场景) 通用容错:截图视觉闭环,多模态 LLM 看到真实屏幕状态,可处理任何界面
  • 典型流程:browser_control 打开 URL → web_page snapshot 获取元素清单 → 按 ref/selector 批量 click/fill/scroll → 页面跳转后重新 snapshot;浏览器不适用(如系统对话框、桌面软件)时回退 gui 视觉定位
  • 两轨均遵循"连续操作合并为一次调用"(actions 列表批量传入)的性能原则

6. 双模式源码共用

src/web/ 同一套代码两种部署:

Web 模式 桌面模式
启动 uvicorn web.server:app Electron spawn uvicorn
文件操作 /api/fs/* HTTP electron-api.js → IPC 直读磁盘
对话框 浏览器原生 Electron dialog 模块
加载协议 http:// file:// + IPC

前端通过 window.electronAPI?.isElectron 自动适配。

7. 存储多后端(JSON / MySQL / SQLite,统一接口隔离)

会话历史与定时任务存储统一在 agent/core/storage.py:接口(Protocol)驱动、多后端实现、消费方零感知后端选择(不判断 STORAGE_BACKEND)。

接口与实现

  • ConversationRecordRepository(对话消息 / 工具调用 / 轮次元数据 / 会话生命周期,16 方法)与 TaskConfigRepository(cron 任务配置,6 方法)两个 Protocol
  • 每后端一个实现类:JsonRecordRepository / MysqlRecordRepository / SqliteRecordRepository(含会话与 cron 双作用域)、JsonTaskConfigRepository / MysqlTaskConfigRepository / SqliteTaskConfigRepository
  • 新增存储后端只需实现上述接口并在工厂注册一行;消费方新增功能/字段无需改动存储层(消息原样 JSON 存储、工具记录 meta 全量透传)

作用域(scope)

  • session(默认):主进程普通会话,JSON 落盘 history/sessions/{session_id}/,MySQL/SQLite 用 sessions / session_messages / session_tool_calls 三表
  • cron:定时任务,JSON 落盘 history/cron/{task_id}/,MySQL/SQLite 用 cron_messages / cron_tool_calls 两表;cron 子进程切换存储作用域后直写记录,主进程经 cron 作用域仓库读取
后端 存储位置 说明
json(默认) history/sessions/{session_id}/ 消息与工具调用以人类可读 JSON 文件落盘(turn_{turn_id}.json / tool_{turn_id}.json / session_meta.json),可直接打开查看/修改,便于审计与调试
mysql session 三表 / cron 两表 消息与工具调用记录原样 JSON 入库、读取只走数据库;二进制产物(图片/附件等)所有后端均落盘
sqlite history/sqlite/storage.sqlite(单文件,session+cron 共用) 内置 sqlite3 零依赖,JSON 存 TEXT 列;cron_tool_calls 含 meta 列,尾部思考可完整落库;WAL 模式支持多进程并发
  • STORAGE_BACKEND(json / mysql / sqlite)+ 存储数据库配置驱动;存储数据库与工具数据库完全隔离
    • 存储数据库配置STORAGE_DB_TYPE + STORAGE_DB_HOST/PORT/USER/PASSWORD/DATABASE/PATH):会话/定时任务存储用,STORAGE_DB_* 缺省回退旧 MYSQL_*(零迁移)
    • 工具数据库配置TOOL_DB_TYPE + TOOL_DB_HOST/PORT/USER/PASSWORD/DATABASE/PATH):数据库操作工具(text2sql / excel2sql)用,不回退存储配置;SQLite 目录模式下每个库名 = 一个 .sqlite 文件
    • 两者均在设置 → 存储与数据库页配置,类型可选择 MySQL / SQLite;agent/core/db.py 提供统一连接(connect_db)与幂等建库建表(ensure_database / ensure_sqlite_database —— 库不存在时先建库再按表结构建表)
  • 不双写:选哪种后端,读写就只走该后端;写入幂等(同一 (session_id, turn_id) 先 DELETE 再 INSERT);DB 异常仅打印日志,不阻断主流程
  • 分支(/api/sessions/branch)与回滚等会话功能均基于存储接口实现,各后端一致可用

后端行为差异(设计内)

场景 json mysql / sqlite
轮次中实时工具记录 每次工具结果后增量写盘 tool_*.json,进程崩溃后重启可回退恢复最近记录 不增量入库,由轮次结束 save_tool_calls 统一落库(无额外磁盘 IO,但崩溃时该轮记录丢失)
服务重启后运行中轮次 get_live_tool_calls 回退读取增量文件,可继续展示 内存记录丢失、数据库无该轮记录,实时面板为空
cron 历史读取 直接读 history/cron/ 下文件 子进程直写数据库表,历史可正常读取

8. 前后端单文件插件化(协议驱动,非注册式)

核心思想:一个插件 = 后端一个文件 + 前端一个文件(或 adapter),通过协议接入;框架与插件之间靠事件 / 回调监听通信,而不是集中式注册表 + 修改主流程——新增或替换插件只需保持协议签名,宿主装配零改动

后端:BaseTool 协议(src/agent/tools/*.py

  • 每个工具是独立单文件,继承 LangChain BaseTool,实现 name / description / args_schema / _run 四要素即完成协议
  • tools/__init__.py 注册表一行挂载;_ALL_AVAILABLE_TOOL_CLASSES 从实例自动推导
  • 前端零改动:工具配置面板(工具列表、参数表单、权限/自动执行开关、main 默认挂载)全部由 /api/config/toolsregistered_tool_names / tool_parameters / forced_permissions 自动生成——新增工具自动出现在设置面板与 Agent 工具选择器
  • 展示类工具(如 todo_list)只需保持"纯文本返回"协议,前端按工具名写一个小 adapter 即可渲染通知条

前端:setXxxDeps / setXxxFn 依赖注入协议(src/web/js/*.js

  • 每个功能模块独立单文件,只导出 setter(协议接口)与自身功能函数,模块间零直接引用
  • 宿主 app.js 作为装配中心做一次性连线(依赖注入):
setSendDeps({ renderSessions, renderMessages, streamAssistantMessage, injectLiveToolCalls, ... });
setLiveUiDeps({ updatePendingOverlay, updateTodoOverlayFromRecords });   // live 快照事件分发
setRenderPersistentToolCalls(renderPersistentToolCalls);
setRenderSkills(renderSkills);
  • 事件监听式数据流toolcalls.js 收到 live snapshot(SSE/轮询)后,通过 setLiveUiDeps 注入的回调分发给各展示组件——组件是被回调通知(监听事件),而非向全局注册表登记
  • 替换/新增模块零宿主改动:旧模块(如 pending-overlay.js)被新模块(notify-strip.js)替换时,只需保持协议导出签名(setLiveUiDeps / updateTodoOverlayFromRecords 等),宿主连线无需修改

9. 前端渲染性能与消息 API 增量

针对长会话 / 工具密集运行 / 高频文件变更场景的两轮优化,目标:运行期主线程低占用、点击后 hover 不失效、消息响应按增量传输

运行期渲染(src/web/js/ + tool_call_recorder.py

优化点 说明
SSE 推送防抖合并 工具每次状态变更即时推帧 → 按会话 120ms 防抖合并为一批增量(tool_call_recorder.py,与 0.8s 落盘防抖同模式),前端 rAF + 120ms 注入节流同步对齐
思考伪流降频 30fps → 12fps(toolcalls.js),长思考文本不再持续占用主线程
回复伪流 O(n) 伪打字从每帧全量重解析整段 markdown(O(n²))改为预拆分块、仅重建最后一个未完成块(chat-render.js
乐观渲染增量 发送消息的乐观渲染改走增量 append,不再 innerHTML="" 重建全历史
会话删除原地移除 删除会话仅移除对应列表节点(空工作区组连组移除),不再全量重建
文件树增量着色 git 状态仅切换既有节点类名(edit-mode.js),展开右栏不再全量重建;右栏关闭期间文件变更只标记 dirty、打开时补刷
其他 背景层移除常驻 will-change.composer-row transition: all 收窄为 max-width;侧边栏拖拽改 Pointer Events + setPointerCapture(消除状态泄漏)

消息 API 增量与附件 URL 化(server.py + chat-render.js + send.js

改动 说明
附件不再 base64 内联 _serialize_content 输出 /api/media?session={sid}&file={relpath} 服务端 URL;cron 附件(目录隔离)回退内联
/api/media 安全路由 会话 ID 格式校验 + 相对路径 + commonpath 根目录守卫(防穿越);拒绝 turn_/tool_/session_ 元数据文件;媒体类 inline / 其余 attachment;Cache-Control + stat 弱 ETag(手动 304)
三条主链路增量 POST /api/chat/startnew_message + base_count + totalPOST /api/chat/complete 与 SSE text 事件 → new_messages + base_count + total(服务端仅序列化增量);bootstrap / abort / rollback / clear / delete / branch / cron 保持全量
会话 ETag _messages_etag(turn 文件数 + 最大 mtime 轻量指纹)+ If-None-Match → 304,未变化时跳过整表序列化
前端会话缓存 state._msgCache(浅拷贝快照,LRU 20):切换会话先渲染缓存(秒开)再带 ETag 后台校验;appendNewMessages 原语负责乐观用户消息按 turn_id 就地替换、计数校验(不一致回退全量 GET)与 _renderedCount / 簿记同步(含 streamAssistantMessage 此前缺失的计数簿记)
传输压缩 全局 GZipMiddleware(≥1KB 响应);删除接口按 current_session_id 条件化(删除非当前会话不返回全量历史)

安全加固(顺带修复)

  • /api/tool-image/api/tool-file 此前为任意文件读取(路径无根目录校验)→ 限定 SESSIONS_ROOT / CRON_ROOT 白名单;注册路径 URL 拼接补 quote 转义 + 缓存头。——本地 API 无鉴权且 CORS 全开,勿将端口 8765 暴露到公网

🔌 LLM 推理服务

项目自带一套 6 服务推理后端(llm_server/),可独立部署在 GPU 服务器上,为 Agent 提供 LLM / ASR / TTS / RAG / 图像生成能力。

服务 端口 模型 脚本
LLM 8900 Qwen3.6-35B-A3B-FP8 start_llm.sh
ASR 8901 Qwen3-ASR-1.7B start_asr.sh
TTS 8902 VoxCPM start_streaming_tts.sh
RAG 8903 Qwen3-Embedding-0.6B + Reranker-4B start_rag_server.sh
Image Gen 8904 Z-Image-Turbo start_image_gen.sh

📄 完整部署、模型下载、测试方法见 llm_server/README.md

💡 也可不自建推理服务,直接在配置向导填入任何 OpenAI 兼容 API(如云端 Qwen / DeepSeek / OpenAI)。


🛠️ 开发手册

前端模块职责(src/web/js/

模块 职责
app.js 应用入口,初始化与事件绑定
api.js 封装所有后端 API 请求(api / apiWithHeaders(读取 ETag 等响应头)/ streamApi SSE)
state.js 全局状态管理(含按会话消息缓存 _msgCache
send.js 消息发送逻辑(增量契约:start / complete / SSE text 只消费 new_message / new_messages
chat-render.js 聊天消息渲染(双容器:chat / cron 各自独立,运行时增量渲染、空闲全量重渲染;appendNewMessages 增量追加原语)
cron.js 定时任务面板(按工作区分组列表、类 chat 会话式历史、模式切换锁、实时运行)
sessions.js 会话列表管理(工作区分组,切换会话恢复会话级通知条状态)
toolcalls.js 工具调用实时面板(思考 Thought / 反思 Reflection 分离显示,rAF 合并高频快照)
notify-strip.js ★ 通知条系统:todo 与人机交互的输入区上方长条(收起/展开、按钮切换、会话级存储)
edit-mode.js 编辑模式(Monaco)
doc-tree.js / doc-mod-panel.js 文档树与修改面板
action-bar.js 底部操作栏
skills.js 技能管理
settings.js 设置面板
themes.js 主题切换
layout.js 布局与分隔条拖拽
electron-api.js ★ Electron IPC 适配层
file-preview.js 文件预览(图片/HTML/PDF)
canvas-editor.js 画板编辑器(画笔/形状/文字/橡皮擦,支持缩放与图片修改)
audio.js 语音录制与播放
i18n.js 国际化
token-ring.js 上下文 Token 用量环形指示器(含压缩阈值刻度与三类占比)
access-mode.js 工作空间访问模式切换(限制访问 / 权限审查 / 完全访问)
think-level.js 思考模式档位选择(low / high / xhigh / max / ultra)
pending.js 人工请求决策提交(数据源为 live snapshot 的 human_requests,配合 notify-strip 渲染)
rollback.js 消息回滚
workspace.js 工作空间切换
dialog.js 对话框
utils.js 通用工具

CSS 架构(src/web/css/

variables.css 定义主题变量,其余按模块拆分:base / layout / chat / composer / cron / dialog / settings / skills / toolcalls / notify-strip / edit-mode / canvas-editor / audio / animations / toast / responsive

添加自定义工具

  1. src/agent/tools/ 新建 my_tool.py,继承 LangChain BaseTool,实现 _run,填写 name / description / args_schema(协议四要素)
  2. config.jsontools 分区注册并配置启用状态与参数(权限设为 confirm 时,工具执行前会自动弹出确认通知条,同意后执行、拒绝/跳过作为返回值继续);前端无需改动——设置面板工具列表 / 参数表单 / Agent 工具选择器由 API 自动生成
  3. 交互类工具(需要向用户提问)在 _run 中调用 core/human_request.ask_human(meta) 阻塞等待答案;展示类工具(如进度面板)返回纯文本即可,前端从 live 工具记录按工具名写 adapter 渲染通知条
  4. 重启后端,工具自动绑定到 LLM;若希望 main Agent 默认挂载,加入 config_manager.MAIN_DEFAULT_TOOLS

添加自定义技能

  1. src/agent/skills/ 新建 my_skill/ 目录
  2. 编写 skill.json(名称、描述、标签)与 skill.md(操作流程,支持 {SKILL_DIR} 占位)
  3. 可放 attachments/ 附件(模板、脚本)
  4. skill_router 会自动匹配并路由

同步 Web ↔ 桌面端

桌面端与 Web 端共用 src/web/。UI 改动无需同步;仅当分叉修改时手动合并。常用同步命令:

# 桌面端 → Web 端(按需)
Copy-Item "src\web\index.html"      "src\web\index.html"      -Force
Copy-Item "src\web\css\*.css"       "src\web\css\"            -Force
Copy-Item "src\web\js\themes.js"    "src\web\js\themes.js"    -Force

调试技巧

  • 后端日志:桌面端 npm start 会在终端打印 [FastAPI] 日志
  • 端口占用main.jskillPortProcess(8765) 启动前自动清理
  • 重置配置:删除 src/agent/agents/config.json 重触首次向导(或复制 config_dist.json 为新配置)
  • 工具调用轨迹history/sessions/{session_id}/tool_{turn_id}.json

⚠️ 注意事项

事项 说明
🖥️ 平台 桌面自动化工具(gui / software_control)依赖 Win32 / pywin32 / pyautogui,目前仅支持 Windows;Web 模式下这些工具不可用
🐍 Python 版本 建议 Python 3.11 / 3.12 / 3.13;首次向导会自动检测
🔐 未签名安装包 .exe 可能被 Windows Defender 拦截,点「更多信息 → 仍要运行」
🌐 首次启动联网 加载 Google Fonts 需联网;离线环境字体选择器有 HTML 硬编码兜底
🔑 API Key 安全 src/agent/agents/config.json 含明文凭证,勿提交到公开仓库(已在 .gitignore 排除,仅保留 config_dist.json 模板)
🎨 图标 当前为 SVG,NSIS 打包后若显示默认图标,需准备 .ico 文件替换 src/web/image/icon.ico
💾 历史存储 默认会话历史与工具轨迹以 JSON 落盘在 history/(可切换 MySQL / SQLite 后端),长期使用注意清理
GUI 性能 同页多操作务必合并为一次 gui 调用,否则延迟显著(见「实现细节」)
🌐 浏览器 Profile browser_control 默认使用一次性临时 Profile(登录态不持久);需要持久登录态时在设置 → 运行时参数配置 BROWSER_PROFILE_DIR
🔌 附件传输 会话附件经 /api/media URL 加载(不再内联 base64);媒体路由带根目录守卫与 1 天缓存,旧历史消息中的 base64 附件仍正常展示
🛡️ 媒体接口安全 /api/tool-image/api/tool-file 已限定白名单目录(history/sessionshistory/cron),白名单外路径返回 404;本地 API 无鉴权,不要对外暴露 8765 端口

👥 Contributors

  • minor:项目话事人,主导整体架构设计与核心实现(LangGraph 编排、20 项工具体系、多 Agent 模式、上下文分级压缩、循环检测、Electron 桌面端等),完成大部分的开发工作。

📄 License

MIT License — 详见 LICENSE

如果这个项目对你有帮助,欢迎 ⭐ Star 支持一下!

About

minorAgent —— 轻量、清晰的 Agent 框架。内置丰富工具与多 Agent 协作,强可扩展性,适合 Agent 入门学习与二次开发。期待与社区共建。

Topics

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages