CogitoAgent 技术演进之路:从终端到桌面,从工具到生态 ——CogitoAgent开发实战(最终篇)

CogitoAgent 技术演进之路:从终端到桌面,从工具到生态

------CogitoAgent开发实战(最终篇)

📖 本文是专栏的最终篇。从第一篇的状态机到第十一篇的桌面应用,我们共同走过了一条完整的AI Agent构建之路。这一篇,我们不写新代码,不展开新功能------而是回望来路,审视项目从v1.0到v2.3的每一次关键跃迁,复盘那些影响深远的设计决策,坦诚地聊聊踩过的坑与犯过的错,并邀请你一起加入这场开源共建。


开源地址

Gitee(国内主站): https://gitee.com/cnt-code/cogito-agent

GitHub(国际镜像): https://github.com/SnowLeopard-io/CogitoAgent

欢迎⭐Star、🍴Fork、📥下载体验、🐛提Issue、✨提交PR。

一、从一份README说起

如果你现在打开 CogitoAgent 的 README,你会看到这样的描述:

CogitoAgent 是一款运行于本地的自主 AI 智能体,融合了文件管理、知识挖掘、系统操作、代码执行与联网能力。它直接在用户配置的工作目录下运行,无需上传任何文件至第三方服务器,在保障数据隐私安全的同时,提供持续运转的智能助理服务。

这段简洁的文字背后,是19个工具模块、14个分类、103+测试用例、v2.3.0版本的积累,是几十个夜晚的代码与思考。

但最早的时候,它只是一个念头------一个让AI真正"活"在电脑里的念头。

这个念头源于一个简单的观察:我们每天都在电脑里产生海量的文件------代码、文档、笔记、图片、设计稿------但AI却看不见它们。每次使用ChatGPT,你都得手动上传文件;每次想让它帮你整理文件夹,它无能为力;每次对话结束,它什么都不记得。

于是我想:能不能做一个AI,让它主动走进我的文件世界,而不是等着我把文件塞给它?

这就是CogitoAgent的起点。

从那个念头到现在,项目走过了四个大版本,经历了从"终端工具"到"桌面应用"、从"个人项目"到"开源生态"的完整演进。这一篇,我们不讲代码细节------那些已经在前面十一篇文章里讲透了。我们讲历程、讲决策、讲教训、讲未来。

二、版本演进:从v1.0到v2.3的四个里程碑

v1.0:从零到一

时间:项目启动初期

核心能力:

  • 状态机(THINKING / AWAITING_INPUT)
  • 5个文件工具(ls/read/copy/mkdir/create)
  • 联网搜索
  • 终端UI(彩色输出)

标志性事件:第一个可运行的版本诞生,AI能在终端里持续思考,每隔3秒自动触发一轮思考循环。

当时的状态:这是一个纯粹的终端工具,用户通过命令行交互,AI能做的事情有限------看看目录、读读文件、搜搜网页。但它证明了"持续思考"这个想法是可行的。

局限:

  • 只有终端界面,普通用户无从下手
  • 工具调用用switch-case硬编码,每加一个工具都要改核心代码
  • 没有记忆系统,每次重启都是"初次见面"
  • 没有会话管理,所有对话挤在同一条时间线上

v2.0:功能爆发

时间:第一次大版本迭代

新增功能:

  • 代码执行引擎(JavaScript/Python)
  • Git版本控制集成
  • 任务管理系统
  • 记忆系统
  • 数据处理工具(CSV/JSON)
  • SQLite数据库操作
  • 邮件功能
  • 系统监控
  • 定时任务调度
  • 多模型支持(OpenAI/Moark/Anthropic/Google)

架构变化:工具数量从5个跃升至12+模块,Agent.js开始膨胀到几百行。

用户价值:从一个"文件助手"变成了"全能工具平台"。AI不仅能看文件,还能帮你写代码、提交Git、管理任务、记住信息、处理数据。

这个阶段的核心思考:AI Agent的能力边界在哪里?答案是------只要你能定义清楚一个操作(文件、代码、Git、数据库),AI就能学会调用它。所以工具的数量会持续增长,架构必须在第一天就为扩展做好准备。

v2.1:安全加固

时间:发现安全漏洞后的紧急迭代

关键决策:移除存在安全漏洞的vm2依赖,改用Node.js原生vm模块。

背景:vm2是一个流行的JavaScript沙箱库,但被发现存在原型链逃逸漏洞,且已停止维护。继续使用意味着用户的系统可能暴露在风险中。

跨平台改进 :工作区路径从硬编码的D:\\改为默认使用用户主目录(os.homedir()),移除了Windows路径的硬编码。

教训:安全不能妥协。一个沙箱逃逸漏洞就可能让用户的整个系统暴露在风险中。定期审计依赖库的安全状态是必须的。同时,跨平台意识应该从第一天就建立,而不是后期补救。

v2.2:架构重构

时间:项目规模膨胀后的必要调整

核心变化:Agent.js拆分为独立模块

  • state.js:状态机管理
  • registry.js:工具注册表
  • commands.js:命令处理

新增 :logger.js分级日志系统(DEBUG/INFO/WARN/ERROR)

测试:测试用例从43增至103+

本质:从"功能堆积"走向"工程化设计"。当Agent.js超过800行时,继续堆功能只会让代码难以维护。拆分不是"重构完成",而是"为未来扩展腾出空间"。

v2.3:桌面化与生态化

时间:当前最新版本

桌面革命:

  • Electron桌面应用(悬浮窗 + Dashboard仪表盘)
  • WebSocket桥接(Electron ↔ Agent独立进程)
  • 双模式切换(桌面模式 / 仪表盘模式)
  • 毛玻璃UI + 虚拟人物视频

会话管理:

  • 多会话系统(创建/切换/删除/重命名)
  • 自动压缩归档(150轮 / 100K token)
  • 会话持久化存储

新工具:

  • OCR图像文字识别(基于视觉大模型)
  • Office文档生成(PPT/Word/Excel)

架构升级:

  • isolated-vm进程级沙箱(替代原生vm)
  • 插件系统(动态加载自定义工具)
  • MCP协议兼容(Model Context Protocol)
  • tracing.js追踪模块
  • retry.js熔断与重试机制

意义:这是项目的一次质变------从"开发者工具"进化为"人人可用的桌面应用"。普通用户不再需要打开命令行,双击图标就能和AI对话。

三、架构演进的五个关键决策

3.1 状态机:从"双状态"到"三状态"

最初:THINKING + AWAITING_INPUT

AI要么在思考,要么在等用户输入。用户按Enter可以打断思考。这个设计解决了"AI自顾自说话,用户插不上嘴"的问题。

现在:增加了AWAITING_CONFIRMATION(危险操作确认)

javascript 复制代码
const STATE = {
  THINKING: 'THINKING',               // AI自主思考
  AWAITING_INPUT: 'AWAITING_INPUT',   // 等待用户输入
  AWAITING_CONFIRMATION: 'AWAITING_CONFIRMATION'  // 等待用户确认危险操作
};

为什么需要确认态?

危险操作(如gitPush、executeCode、deleteData)如果自动执行,用户可能不小心触发删除文件、覆盖远程仓库等不可逆操作。确认态让用户对高风险操作有最终决定权。

javascript 复制代码
if (isDangerousOperation(toolName)) {
  const confirmed = await requestConfirmation(toolName, args);
  if (!confirmed) return { success: false, error: '用户拒绝' };
}

核心原则:AI可以建议,但用户决定。这个原则贯穿了整个项目的安全设计。

3.2 工具系统:从"switch-case"到"注册表"

这是架构演进中最能体现"预见性"的决策。

第一阶段:switch-case

javascript 复制代码
async function executeTool(tool, args) {
  switch (tool) {
    case 'ls': return await ls(args[0]);
    case 'read': return await read(args[0]);
    case 'copy': return await copy(args[0], args[1]);
    // ... 100+ 个 case
  }
}

问题很明显:每加一个工具,就要改一次核心文件。100个工具意味着100个case分支。而且每个工具的参数处理方式不同------create需要把后面的参数拼成内容,search需要把所有参数用逗号连接------这些特殊逻辑散落在各个case里,维护成本极高。

第二阶段:注册表模式

javascript 复制代码
const TOOL_REGISTRY = {
  ls: { fn: tools.ls, argCount: 1, category: 'file' },
  read: { fn: tools.read, argCount: 1, category: 'file' },
  create: { fn: tools.create, argCount: 2, customArgs: true, category: 'file' },
  // ...
};

加工具只需要写函数 + 在注册表里加一条配置,核心代码(executeTool)完全不用动。参数处理的特殊逻辑也集中在注册表里声明,而不是散落在各个分支。

进阶:甚至支持自动扫描生成注册表,加工具只需要写函数 + 导出两步。

核心启示:工具数量会迅速膨胀。架构必须在第一天就为扩展做好准备。这就是开闭原则(对扩展开放,对修改关闭)在实践中的体现。

3.3 工具调用协议:为什么不用Function Calling?

我们没有使用OpenAI的Function Calling,而是设计了纯文本标记协议:

复制代码
[TOOL] toolName("参数1", "参数2") [/TOOL]

为什么?

对比项 Function Calling 纯文本标记
API兼容性 仅OpenAI格式 任何LLM都支持
参数schema 需要JSON定义 自然语言/简单字符串
多工具调用 需要特殊处理 正则匹配即可
调试难度 黑盒 纯文本,一目了然

核心启示:不要被特定厂商的"标准"绑定。跨模型兼容性比"标准化"更重要。一个你完全掌控的简单协议,比一个依赖外部SDK的复杂协议更可靠。

3.4 API客户端:从"SDK依赖"到"原生fetch"

最初:使用OpenAI官方SDK。

现在 :完全移除SDK依赖,改用原生fetch直接调用API并解析SSE流。

javascript 复制代码
// 直接读取SSE流
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = '';

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  // 逐行解析 data: {...}
}

理由:

  • SDK体积大,增加了项目依赖和安装时间
  • SDK的SSE解析在某些网络环境下有bug(连接提前关闭)
  • 原生fetch更可控,支持精细化的重试和错误处理
  • 减少了一层抽象,调试更容易

启示:不要因为"官方SDK"就默认它是最佳选择。有时候,手写一个轻量级客户端更可靠、更可控。

3.5 桌面化:从"终端"到"Electron"

这是v2.3最大的变化------让AI从"命令行工具"变成"桌面应用"。

架构:Electron主进程 + 独立Agent进程 + WebSocket桥接
#mermaid-svg-tqECSGvrAYGakLb0{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tqECSGvrAYGakLb0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tqECSGvrAYGakLb0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tqECSGvrAYGakLb0 .error-icon{fill:#552222;}#mermaid-svg-tqECSGvrAYGakLb0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tqECSGvrAYGakLb0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tqECSGvrAYGakLb0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tqECSGvrAYGakLb0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tqECSGvrAYGakLb0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tqECSGvrAYGakLb0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tqECSGvrAYGakLb0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tqECSGvrAYGakLb0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tqECSGvrAYGakLb0 .marker.cross{stroke:#333333;}#mermaid-svg-tqECSGvrAYGakLb0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tqECSGvrAYGakLb0 p{margin:0;}#mermaid-svg-tqECSGvrAYGakLb0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-tqECSGvrAYGakLb0 .cluster-label text{fill:#333;}#mermaid-svg-tqECSGvrAYGakLb0 .cluster-label span{color:#333;}#mermaid-svg-tqECSGvrAYGakLb0 .cluster-label span p{background-color:transparent;}#mermaid-svg-tqECSGvrAYGakLb0 .label text,#mermaid-svg-tqECSGvrAYGakLb0 span{fill:#333;color:#333;}#mermaid-svg-tqECSGvrAYGakLb0 .node rect,#mermaid-svg-tqECSGvrAYGakLb0 .node circle,#mermaid-svg-tqECSGvrAYGakLb0 .node ellipse,#mermaid-svg-tqECSGvrAYGakLb0 .node polygon,#mermaid-svg-tqECSGvrAYGakLb0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tqECSGvrAYGakLb0 .rough-node .label text,#mermaid-svg-tqECSGvrAYGakLb0 .node .label text,#mermaid-svg-tqECSGvrAYGakLb0 .image-shape .label,#mermaid-svg-tqECSGvrAYGakLb0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-tqECSGvrAYGakLb0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tqECSGvrAYGakLb0 .rough-node .label,#mermaid-svg-tqECSGvrAYGakLb0 .node .label,#mermaid-svg-tqECSGvrAYGakLb0 .image-shape .label,#mermaid-svg-tqECSGvrAYGakLb0 .icon-shape .label{text-align:center;}#mermaid-svg-tqECSGvrAYGakLb0 .node.clickable{cursor:pointer;}#mermaid-svg-tqECSGvrAYGakLb0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tqECSGvrAYGakLb0 .arrowheadPath{fill:#333333;}#mermaid-svg-tqECSGvrAYGakLb0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tqECSGvrAYGakLb0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tqECSGvrAYGakLb0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tqECSGvrAYGakLb0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tqECSGvrAYGakLb0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tqECSGvrAYGakLb0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tqECSGvrAYGakLb0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tqECSGvrAYGakLb0 .cluster text{fill:#333;}#mermaid-svg-tqECSGvrAYGakLb0 .cluster span{color:#333;}#mermaid-svg-tqECSGvrAYGakLb0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tqECSGvrAYGakLb0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tqECSGvrAYGakLb0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-tqECSGvrAYGakLb0 .icon-shape,#mermaid-svg-tqECSGvrAYGakLb0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tqECSGvrAYGakLb0 .icon-shape p,#mermaid-svg-tqECSGvrAYGakLb0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tqECSGvrAYGakLb0 .icon-shape .label rect,#mermaid-svg-tqECSGvrAYGakLb0 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tqECSGvrAYGakLb0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tqECSGvrAYGakLb0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tqECSGvrAYGakLb0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent 独立进程
Electron 桌面应用
WebSocket
spawn 启动
main.js

主进程
UI 渲染进程

桌面/仪表盘
agent-bridge.js

WebSocket 桥接
ws-server.js

WebSocket 服务

端口 9527
agent/Agent.js

思考循环 + 工具执行
session.js

会话管理

为什么选择独立进程?

方案 优点 缺点
嵌入Electron 通信简单 Agent崩溃会拖垮整个界面
独立进程 隔离性好,可独立重启 需要进程间通信

独立进程让界面和推理分离,即使Agent出现异常,界面也不会卡死。WebSocket作为通信桥梁,支持双向实时消息传递,正好适配流式输出的场景。

双模式设计:

模式 命令 定位
桌面模式(悬浮窗) npm run electron:desktop 轻量级,桌面伴侣
仪表盘模式 npm run electron:dashboard 全功能工作台

四、踩过的坑与修正

4.1 "完全本地"的表述错误(已修正)

问题:早期宣传中用了"完全本地运行"的表述,但CogitoAgent需要调用云端API进行推理。这个表述会让用户误以为"完全不联网",产生错误的预期。

修正:改为"云端推理、本地执行",明确区分"推理在云端、文件数据在本地"。

正确的架构说明:

能力 运行位置 说明
AI推理 ☁️ 云端API 调用大模型处理指令和上下文
工具执行 💻 本地 文件操作、代码执行、Git、数据库等
数据存储 💻 本地 对话历史、记忆、任务等存储在本地JSON/SQLite

教训:技术宣传必须精准。一个模糊的表述会误导用户,损害信任。与其用"完全本地"这种绝对化的词,不如用"云端驱动、本地执行"这样准确的描述。

4.2 路径安全:至今未完全解决

问题 :file.js中所有工具函数使用path.isAbsolute(targetPath) ? targetPath : path.join(basePath, targetPath)。用户可传入C:\Windows或/etc/passwd逃逸工作区。

javascript 复制代码
// ❌ 危险:用户可传入工作区外的绝对路径
const fullPath = path.isAbsolute(targetPath) ? targetPath : path.join(basePath, targetPath);

应该怎么做:

javascript 复制代码
// ✅ 安全:严格限制在工作区内
function secureResolvePath(targetPath) {
  const base = path.resolve(getBasePath());
  const full = path.resolve(base, targetPath);
  if (!full.startsWith(base)) {
    throw new Error(`路径越权: ${targetPath} 不在工作区内`);
  }
  return full;
}

为什么至今没修?

这是一个已知的技术债务。原因不是"不知道怎么修",而是"修了之后需要全面测试所有文件操作,确保不影响正常使用"。在功能快速迭代的阶段,这个优先级被排在了后面。

但这不应该是借口。文件操作的权限控制是本地AI Agent最核心的安全防线。应该在第一天就实现严格的路径验证函数,而不是事后补救。

4.3 上下文管理:从"激进压缩"到"智能压缩"

最初:压缩过于激进,简单粗暴地截断历史,导致AI丢失关键上下文。

问题表现:用户和AI聊了100轮后,AI突然"失忆",不记得之前讨论过的重要文件或决策。

现在:混合策略------保留最近10轮对话,将更早的内容生成摘要归档,摘要里包含"已发现的重要文件""已执行的关键操作""当前工作状态"等结构化信息。

javascript 复制代码
function compressHistory() {
  // 1. 保留最近10轮
  const recentMessages = nonSystemMessages.slice(-10);
  
  // 2. 生成摘要
  const summary = generateSummary(recentMessages);
  
  // 3. 重建历史(系统提示 + 摘要 + 最近对话)
  conversationHistory = [
    { role: 'system', content: buildSystemPrompt() },
    { role: 'user', content: `[上下文摘要] ${summary}` },
    ...recentMessages
  ];
}

启示:上下文管理是AI Agent的"记忆系统"。既要控制token成本,又要保留足够的信息让AI理解全局。压缩不是"丢弃",而是"提炼"。

4.4 沙箱选择:从vm2到原生vm到isolated-vm

第一阶段 :使用vm2。它是当时最流行的JavaScript沙箱库。

第二阶段 :发现vm2存在原型链逃逸漏洞,且已停止维护。紧急切换到Node.js原生vm模块。

第三阶段 :发现原生vm虽然比vm2安全,但仍有已知的逃逸路径。进一步升级到isolated-vm------它使用独立的V8 Isolate,真正的进程级隔离,内存限制128MB,CPU超时控制。

javascript 复制代码
// sandbox.js - 优先使用isolated-vm
async function getIvm() {
  try {
    const mod = await import('isolated-vm');
    return mod.default || mod;
  } catch {
    console.warn('[sandbox] isolated-vm 不可用,使用原生 vm');
    return null;
  }
}

教训:安全领域没有"一劳永逸"。依赖库会过时,漏洞会不断被发现。定期审计、及时升级是必须的。

4.5 多会话:从"单线程"到"多线程"

问题:早期所有对话挤在同一条时间线上。用户想讨论项目A,就得清空之前关于项目B的对话;想切换话题,AI会用旧话题的背景来回答新问题。

现在:多会话系统,每个会话独立存储、独立上下文,支持切换、创建、删除、重命名。

会话存储结构:

复制代码
data/sessions/
├── meta.json                     # 会话列表 + 当前激活ID
├── sess_abc123.json              # 会话A的完整历史
├── sess_def456.json              # 会话B的完整历史
└── sess_abc123_archive.json      # 会话A的归档文件

启示:用户的需求是多样化的。一个"万能对话"永远满足不了所有场景。提供组织和分类的能力,是产品从"可用"到"好用"的关键一步。

五、项目现状全景

5.1 功能全景

类别 工具 状态
文件操作 ls, read, copy, mkdir, create, delete, move ✅
网页工具 search, browse, fetchPage, searchOnEngine ✅
浏览器自动化 initBrowser, clickElement, fillField, takeScreenshot, getText, waitForElement, closeBrowser ✅
系统操作 listApps, openApp, closeApp ✅ (Windows为主)
代码执行 executeCode, runJavaScript, runPython ✅
Git gitStatus, gitCommit, gitPush, gitPull, gitDiff, gitLog ✅
任务管理 createTask, getTasks, completeTask, splitTask ✅
记忆系统 addMemory, searchMemory, getRelatedMemories, deleteMemory ✅
数据处理 readCSV, writeJSON, csvToJSON, queryData ✅
数据库 executeSQL, query, insert, update, createTable, getTables ✅
邮件 sendEmail, sendTextEmail, sendHtmlEmail ✅
系统监控 getCPUInfo, getMemoryInfo, monitorSystem ✅
定时任务 addScheduleTask, getScheduleTasks, toggleScheduleTask ✅
OCR ocr, ocrBatch ✅
Office文档 createPpt, createWord, createExcel, readExcel ✅

共计:19个工具模块,14个分类,约50+工具函数。

5.2 桌面与终端双轨制

模式 命令 适用场景
桌面模式(悬浮窗) npm run electron:desktop 日常快速问答,桌面伴侣
Dashboard模式 npm run electron:dashboard 复杂任务,多会话管理,工具可视化
CLI模式 npm run cli 服务器环境,远程连接,资源受限
设置向导 npm start 首次配置

5.3 多会话管理

命令:

命令 功能
/sessions 列出所有会话
/new 创建新会话
/switch <id> 切换到指定会话
/delete <id> 删除会话
/rename <name> 重命名当前会话

压缩策略:

  • 触发条件:150轮 或 100K token
  • 保留最近10轮,之前的生成摘要归档
  • 归档文件保留最近3个

5.4 安全机制全景

安全层 实现 状态
代码沙箱 isolated-vm进程级隔离 + 原生vm降级 ✅
Git安全 execFile + 子命令白名单 + 参数验证 + cwd验证 ✅
危险操作确认 AWAITING_CONFIRMATION状态 + 用户手动确认 ✅
配置安全 敏感信息存.env,config.json自动过滤 ✅
工作区隔离 路径验证(path.isAbsolute直接拼接) ⚠️ 待修复
跨平台路径 os.homedir() + path.sep ✅

5.5 可观测性

模块 功能
tracing.js LLM调用追踪、工具执行追踪、状态转换追踪、错误追踪
logger.js DEBUG/INFO/WARN/ERROR分级日志
retry.js 熔断器(5次失败触发,60秒恢复)+ 指数退避重试

六、核心技术决策清单

决策点 选择 替代方案 选择理由
编程语言 Node.js Python/Go 适合文件操作和命令行工具,生态成熟
工具调用协议 纯文本标记 Function Calling 跨模型兼容,调试方便
沙箱方案 isolated-vm vm2/原生vm 更强隔离,进程级安全
桌面框架 Electron Tauri/React Native 成熟稳定,Web技术栈
进程通信 WebSocket IPC/HTTP 双向实时通信,适合流式输出
配置存储 JSON + .env 纯JSON/纯环境变量 兼顾可读性和安全性
会话存储 JSON文件 SQLite/内存 简单够用,无需额外依赖
日志系统 自定义分级日志 winston/pino 轻量,满足需求
测试框架 Jest Mocha/Vitest ES Module支持好,生态成熟

七、未来方向

短期(v2.4)

方向 描述 优先级
路径安全加固 实现secureResolvePath防止越权 P0
跨平台系统工具 system.js和monitor.js补充Linux/macOS支持 P1
搜索API抽象 解除对Moark格式的强依赖 P1

中期(v3.0)

方向 描述
多智能体协作 多个Agent分工协作,完成复杂任务
插件市场 社区贡献独立工具包,按需安装
向量记忆 引入向量数据库(如Chroma),实现语义搜索
RAG增强 结合本地文档,实现知识库问答

长期

方向 描述
语音交互 集成语音识别和合成,实现对话式交互
多模态理解 支持图像、音频、视频等多模态输入
跨设备同步 多台设备之间的会话和记忆同步

八、开源共建:邀请你一起参与

CogitoAgent采用 Apache 2.0 许可证开源。它的成长离不开社区的参与。

你可以做什么?

角色 行动
用户 ⭐ Star收藏,下载体验,提Issue反馈
开发者 🍴 Fork仓库,提交PR修复bug或新增功能
技术博主 📝 写文章分享,引用本项目
产品经理 💡 提建议,讨论产品方向
设计师 🎨 为桌面界面提供设计改进

如何开始贡献?

  1. 阅读文档 :README.md 和 src/agent/tools/TOOL_DEVELOPMENT.md
  2. 找一个方向 :
    • 修复已知问题(路径安全、跨平台)
    • 添加新工具(按照TOOL_DEVELOPMENT.md的流程)
    • 改进界面(Electron桌面/仪表盘)
    • 补充测试用例
  3. 提交PR:Fork → 开发 → 测试 → Pull Request

不需要会写代码也能参与

  • 写一篇使用体验文章
  • 翻译文档
  • 在社区推荐项目
  • 提Issue反馈使用中的问题

九、结语

从v1.0到v2.3,CogitoAgent走过了一条从"功能堆积"到"工程化设计"、从"终端工具"到"桌面应用"、从"个人项目"到"开源生态"的演进之路。

它不是一个完美的项目------有已知的安全隐患,有平台限制,有未覆盖的测试。但它用一次次迭代证明了一件事:

一个由个人开发者构建的本地AI智能体,可以做到功能完备、架构清晰、可扩展、可维护。

这个专栏的十一篇文章,记录了这条路上的每一个关键节点。希望它们能为你构建自己的AI Agent提供参考和启发。

一个人可以起头,但一群人能把它推得更远。欢迎你加入。


开源仓库:

Gitee | GitHub

⭐ 你的 Star 是项目前进的动力