桌面应用与多会话管理:让AI真正“住”进你的电脑 ——CogitoAgent开发实战(第十一篇)

桌面应用与多会话管理:让AI真正“住”进你的电脑

——CogitoAgent开发实战(第11篇)

📖 本文是专栏的第十一篇。前面十篇文章,我们一步步构建了一个完整的AI智能体——它能思考、能动手、能联网、能记忆、能执行代码。但它一直“住”在终端里,一个黑底白字的命令行窗口。这一篇,我们给AI盖一栋“房子”——一个真正的桌面应用,让它从“字符界面”走进“图形世界”。同时,我们还会给AI装上一个“档案室”——多会话管理系统,让它能同时处理多个独立的任务线索。


请添加图片描述

📌 从一个对比开始

先想象两个场景:

场景A:终端模式

你在命令行里启动AI,看着彩色文字一行行滚动。你和AI的对话像一条没有尽头的时间线——昨天聊的、今天聊的、全都混在一起。想切到另一个话题?得手动清空历史,或者忍受AI用旧话题的背景来回答新问题。

场景B:桌面模式

你打开一个毛玻璃质感的悬浮窗,AI的虚拟形象在窗口里静静等待。你点开“会话列表”,看到三个独立的对话线索:“项目A设计”、“代码审查”、“日常记录”。点一下,就能切换到对应的对话上下文。每个会话都有自己的“记忆”,互不干扰。

这就是CogitoAgent v2.3 带来的改变——从“终端里的聊天机器人”进化为“桌面上的智能体伴侣”。
请添加图片描述


一、为什么需要桌面应用?

1.1 终端的局限性

命令行界面的优势是轻量、高效、适合开发者。但它的局限性也很明显:

问题说明
视觉单调只有文字,没有图形界面,无法展示复杂信息
交互单一只能输入文本,无法点击、拖拽、直观操作
缺少陪伴感AI只是一个“程序”,不是一个“伙伴”
会话混乱所有对话挤在同一条时间线上,难以组织

1.2 桌面应用的目标

CogitoAgent的桌面模式不是简单的“网页包装”,而是围绕三个核心目标设计的:

  1. 让AI可视:通过虚拟人物形象、界面布局、视觉反馈,让AI“活”起来
  2. 让交互更自然:支持点击、拖拽、多窗口,降低使用门槛
  3. 让会话可管理:引入多会话系统,让对话像文档一样可组织、可切换

二、整体架构:两条腿走路

CogitoAgent 的桌面方案采用 Electron + WebSocket + 独立Agent进程 的架构,而不是把Agent直接嵌入Electron主进程。

2.1 为什么是独立进程?

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

CogitoAgent选择了独立进程方案:

Agent 独立进程

Electron 桌面应用

WebSocket

spawn 启动

main.js
主进程

preload.cjs
安全桥接

UI 渲染进程
桌面/仪表盘/配置向导

agent-bridge.js
WebSocket 桥接

ws-server.js
WebSocket 服务
(端口 9527)

agent/Agent.js
思考循环 + 工具执行

session.js
会话管理

2.2 进程分工

进程职责
Electron主进程窗口管理、系统托盘、启动Agent子进程、路由模式切换
Agent独立进程思考循环、工具执行、会话管理、WebSocket服务
UI渲染进程界面展示、用户交互、消息渲染

关键设计:Agent进程不依赖Electron,即使桌面窗口关闭,Agent也可以继续在后台运行(当然,当前版本设计为窗口关闭时Agent也随之退出)。


三、启动流程解析

3.1 入口:main.js

当用户执行 npm run electron:desktopnpm run electron:dashboard 时,package.json 脚本会调用 Electron,加载 electron/main.js

// main.js 的核心启动流程
app.whenReady().then(async () => {
  // 1. 检查配置
  if (!isConfigured()) {
    createSetupWindow();   // 打开配置向导
  } else {
    launchMainApp();       // 直接启动主应用
  }
});

async function launchMainApp() {
  // 2. 清理端口(防止旧进程占用)
  killPortProcess(9527);
  
  // 3. 启动Agent子进程
  await startAgentProcess();
  
  // 4. 读取启动模式
  const mode = envConfig['COGITO_MODE'] || 'desktop';
  
  // 5. 创建对应模式的窗口
  if (mode === 'dashboard') {
    createDashboardWindow();
  } else {
    createMainWindow();
  }
}

3.2 关键细节:Agent启动等待

startAgentProcess 函数会等待Agent输出 WebSocket 服务已启动 后才返回,确保WebSocket服务就绪后再创建窗口:

function startAgentProcess() {
  agentProcess = spawn('node', ['src/index.js'], { ... });
  
  return new Promise((resolve) => {
    agentProcess.stdout.on('data', (data) => {
      if (data.toString().includes('WebSocket 服务已启动')) {
        resolve();  // 收到这个日志才继续
      }
    });
  });
}

3.3 配置向导与主应用分离

首次运行时,会先打开一个独立的配置向导窗口(setup/),完成API配置、模型选择、工作区设置后才进入主应用。这个设计让首次配置流程清晰、专注,不会与主界面混杂。


四、双模式设计:桌面 vs 仪表盘

CogitoAgent 提供了两种桌面交互模式,满足不同使用场景。

4.1 桌面模式(Desktop Mode)

启动命令npm run electron:desktop

定位:轻量级悬浮窗,像“桌面宠物”一样常驻。

界面特点

  • 半透明毛玻璃效果,融入桌面背景
  • 左侧是虚拟人物视频(可拖拽移动)
  • 右侧是对话面板(可点击人物头像切换显示/隐藏)
  • 极简交互,专注于快速问答

适用场景

  • 日常快速问答
  • 作为桌面“伴侣”常驻
  • 资源占用少,适合长时间后台运行

核心文件

  • electron/desktop/index.html — 界面
  • electron/desktop/renderer.js — 逻辑
  • electron/desktop/style.css — 毛玻璃样式

4.2 仪表盘模式(Dashboard Mode)

启动命令npm run electron:dashboard

定位:全功能工作台,像IDE一样集成所有工具。

界面特点

  • 左侧边栏:会话列表 + 快捷操作 + 人物形象
  • 主内容区:欢迎页 / 技能浏览 / 对话视图(三态切换)
  • 全窗口设计,最大化信息展示空间
  • 工具调用可视化(黄色卡片显示调用,绿色卡片显示结果)

适用场景

  • 复杂任务处理
  • 需要多会话切换的场景
  • 工具探索和管理

核心文件

  • electron/dashboard/index.html — 界面
  • electron/dashboard/renderer.js — 逻辑
  • electron/dashboard/style.css — 布局样式

4.3 双模式切换

用户可以在两种模式间自由切换:

// renderer.js
// 桌面模式点击"工作台模式"按钮
btnDashboard.addEventListener('click', () => {
  window.electronAPI.switchToDashboard();
});

// 仪表盘模式点击"桌宠模式"按钮
btnDesktop.addEventListener('click', () => {
  window.electronAPI.switchToDesktop();
});

主进程处理模式切换:

ipcMain.on('switch-to-dashboard', () => {
  if (mainWindow) mainWindow.close();
  if (!dashboardWindow) createDashboardWindow();
});

五、WebSocket桥接:连接桌面与Agent

5.1 为什么需要桥接?

Electron渲染进程不能直接与Node.js子进程通信(出于安全隔离考虑)。因此需要一个桥接层

Agent.js ws-server.js agent-bridge.js preload.cjs UI渲染进程 Agent.js ws-server.js agent-bridge.js preload.cjs UI渲染进程 ipcRenderer.send('user-message') 转发IPC事件 ws.send(JSON) 解析并处理 广播回复 WebSocket消息 ipcRenderer.send('agent-reply') 渲染消息

5.2 桥接模块:agent-bridge.js

agent-bridge.js 是连接Electron和Agent的“翻译官”:

// 连接WebSocket
function connect() {
  ws = new WebSocket('ws://localhost:9527');
  
  ws.on('message', (raw) => {
    const msg = JSON.parse(raw);
    // 向所有已注册窗口转发消息
    connectedWindows.forEach(win => {
      win.webContents.send('agent-reply', msg);
    });
  });
}

// 处理来自渲染进程的消息
ipcMain.on('user-message', (_event, text) => {
  ws.send(JSON.stringify({ type: 'user-message', text }));
});

5.3 多窗口支持

agent-bridge.js 通过 connectedWindows Set 支持多个窗口同时连接到同一个Agent,适合未来扩展多窗口场景。


六、多会话管理:AI的“档案室”

6.1 什么是多会话?

在终端模式下,所有对话都在同一个上下文中。多会话系统允许用户创建多个独立的对话空间

会话用途状态
默认会话日常对话当前激活
项目A讨论记录项目A的设计决策已归档
代码审查代码评审记录活跃

每个会话拥有:

  • 独立的对话历史
  • 独立的上下文(不会被其他会话污染)
  • 独立的人设(可单独设置)
  • 持久化存储(关闭程序后不丢失)

6.2 会话数据结构

元数据(meta.json)

{
  "sessions": [
    {
      "id": "sess_abc123",
      "name": "项目A讨论",
      "createdAt": "2024-06-20T10:00:00Z",
      "lastActiveAt": "2024-06-20T15:30:00Z",
      "messageCount": 45
    }
  ],
  "activeId": "sess_abc123"
}

会话文件(sess_abc123.json)

[
  { "role": "system", "content": "...系统提示词..." },
  { "role": "user", "content": "我们开始讨论项目A" },
  { "role": "assistant", "content": "好的,我已经记录了..." }
]

6.3 会话管理命令

在CLI模式下,用户可以通过以下命令管理会话:

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

6.4 会话切换流程

function switchSession(sessionId) {
  // 1. 归档当前会话
  archiveCurrentSession();
  saveSession(currentSessionId, conversationHistory);
  
  // 2. 切换
  currentSessionId = sessionId;
  meta.activeId = sessionId;
  
  // 3. 加载新会话
  const messages = loadSession(sessionId);
  conversationHistory = messages.length > 0 
    ? messages 
    : [{ role: 'system', content: buildSystemPrompt() }];
  
  // 4. 更新元数据
  saveMeta(meta);
}

6.5 会话压缩与归档

长时间对话会导致上下文膨胀,CogitoAgent采用自动压缩 + 归档策略:

  1. 触发条件:对话轮数超过150轮 或 Token估算超过100K
  2. 压缩策略
    • 保留最近10轮对话
    • 将更早的对话生成摘要
    • 完整历史归档到文件
  3. 归档保留:每个会话最多保留3个归档文件
function compressHistory() {
  const nonSystemMessages = conversationHistory.filter(m => m.role !== 'system');
  if (nonSystemMessages.length <= 10) return;
  
  // 归档旧对话
  const toArchive = nonSystemMessages.slice(0, -10);
  archiveConversation(toArchive);
  
  // 保留最近10轮
  const recentMessages = nonSystemMessages.slice(-10);
  const summary = generateSummary(recentMessages);
  
  // 重建历史
  conversationHistory = [
    { role: 'system', content: buildSystemPrompt() },
    { role: 'user', content: `[上下文摘要] ${summary}` },
    ...recentMessages
  ];
}

七、工具调用可视化

7.1 为什么需要可视化?

在终端模式下,工具调用显示为灰色小框。在桌面模式下,我们可以做得更好:

终端显示桌面显示
灰色小框彩色卡片(黄色=调用,绿色=成功,红色=失败)
纯文本可折叠展开
无法交互点击展开/收起详情

7.2 工具卡片的实现

Dashboard模式下的工具调用通过 MessageRenderer 渲染为卡片:

// message-renderer.js
addToolCall(toolName, args) {
  const card = document.createElement('div');
  card.className = 'tool-result-card tool-result-collapsed';
  
  // 头部:工具名称 + 状态
  const header = `
    <div class="tool-result-header">
      <div class="tool-icon">✓</div>
      <div class="tool-name">${toolName}</div>
      <div class="tool-status success">成功</div>
    </div>
  `;
  
  // 内容:参数和结果(可折叠)
  const content = `
    <div class="tool-result-content">
      <pre>${JSON.stringify(data, null, 2)}</pre>
    </div>
  `;
  
  // 点击切换折叠状态
  card.addEventListener('click', () => {
    card.classList.toggle('tool-result-collapsed');
    card.classList.toggle('tool-result-expanded');
  });
}

7.3 流式渲染优化

Dashboard模式使用双缓冲 + requestAnimationFrame 节流优化流式输出:

// 流式渲染
_streamBuffer = '';
_streamPending = false;

_appendToStream(text) {
  this._streamBuffer = text;
  if (!this._streamPending) {
    this._streamPending = true;
    requestAnimationFrame(() => this._flushStream(false));
  }
}

_flushStream(isFinal) {
  this._streamPending = false;
  // 用 textContent 更新,不重建DOM
  this._streamTextNode.textContent = this._streamBuffer;
}

效果:文字逐字出现,流畅无闪烁,性能优于直接DOM操作。


八、配置向导:首次体验的设计

8.1 向导流程

首次运行时,CogitoAgent会打开一个独立的配置向导窗口(setup/),引导用户完成5步配置:

步骤配置项说明
1API Base URL如 https://api.openai.com/v1
2API Key用户的API密钥
3模型名称如 gpt-4o
4工作区路径AI可访问的目录
5人设选择从13种人设中选择

8.2 预设按钮

向导界面提供了常用服务的预设按钮,一键填入:

<div class="preset-btns">
  <button data-preset="https://api.openai.com/v1">OpenAI</button>
  <button data-preset="https://api.moark.com/v1">Moark</button>
  <button data-preset="https://api.deepseek.com/v1">DeepSeek</button>
  <button data-preset="https://openrouter.ai/api/v1">OpenRouter</button>
</div>

8.3 配置存储

配置完成后,系统会:

  1. 将敏感信息写入 .env 文件
  2. 将非敏感配置写入 config.json
  3. 将人设文件复制为 persona.md

这种双文件存储策略兼顾了安全性和可读性。


九、共享组件库的设计

9.1 为什么需要共享库?

Desktop 和 Dashboard 两种模式有很多重复的UI逻辑——消息渲染、工具卡片、人物形象管理。如果各自实现,会导致代码重复和维护困难。

9.2 共享组件

electron/shared/ 目录下包含了公共组件:

文件功能
common.css消息气泡、Markdown、工具卡片等公共样式
utils.jsMarkdown渲染、HTML净化、工具调用过滤
message-renderer.js消息渲染引擎(支持两种布局模式)
persona-manager.js人物形象管理(视频/图片切换)

9.3 使用方式

// desktop/renderer.js 和 dashboard/renderer.js 共用
MessageRenderer.init({
  messagesEl,
  layout: 'desktop',  // 或 'dashboard'
  showAvatar: true,   // dashboard显示头像,desktop不显示
});

PersonaManager.init({
  containerEl: characterEl,
  defaultMediaPath: '../shared/video.mp4',
});

十、设计原则与启发

10.1 渐进增强

CogitoAgent的桌面方案遵循“渐进增强”原则:

  • 终端模式:核心功能完整可用
  • 桌面模式:增加视觉和交互增强
  • 仪表盘模式:增加会话管理和工具可视化

用户可以从终端开始,逐步升级到桌面模式,不需要一次性学习所有功能。

10.2 关注点分离

关注点实现位置
AI推理Agent独立进程
界面交互Electron渲染进程
进程通信WebSocket + IPC
会话管理session.js(Agent侧)
数据持久化文件系统

10.3 善用现有生态

  • Electron:成熟的桌面应用框架
  • WebSocket:标准的双向通信协议
  • V8 Isolateisolated-vm 提供进程级隔离
  • CSS毛玻璃backdrop-filter: blur() 实现视觉效果

十一、小结

这一篇我们看了CogitoAgent的桌面应用与多会话管理:

模块核心实现
桌面架构Electron + 独立Agent进程 + WebSocket桥接
双模式桌面模式(轻量悬浮窗)+ 仪表盘模式(全功能工作台)
进程通信agent-bridge.js 桥接Electron IPC和WebSocket
多会话管理独立会话文件 + 自动压缩归档 + CLI命令管理
工具可视化彩色卡片 + 折叠展开 + 实时流式渲染
共享组件公共样式、渲染器、人物形象管理
配置向导5步引导 + 预设按钮 + 双文件存储

核心设计原则

  1. 独立进程隔离风险,WebSocket桥接通信
  2. 双模式满足不同使用场景
  3. 多会话让对话可组织、可管理
  4. 共享组件避免代码重复
  5. 渐进增强降低使用门槛

开源仓库

  • Gitee: https://gitee.com/cnt-code/cogito-agent
  • GitHub: https://github.com/SnowLeopard-io/CogitoAgent

如果这篇文章对你有帮助,欢迎 ⭐Star 支持一下开源项目!

👉 Gitee | GitHub 👈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌云拓界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值