news 2026/3/2 18:30:56

AionUi:与AI终端代理协作的跨平台桌面界面

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AionUi:与AI终端代理协作的跨平台桌面界面


✨ 项目概述

AionUi 是一个基于 Electron 框架构建的跨平台桌面应用,旨在为用户提供一个统一、可视化的图形界面,用于与多种 AI 终端代理(例如 Gemini CLI、Claude Code、Qwen Code、Goose CLI、Auggie 等)进行协作。它遵循模块化架构原则,优先考虑用户体验、本地数据安全和开发者可维护性。

✨ 核心特性

  • 多AI代理集成:支持通过标准化适配器连接多种AI终端代理,每个代理可独立管理和配置。
  • 跨平台兼容:支持 macOS、Windows 和 Linux 操作系统。
  • 模块化架构:采用桥接模式处理进程间通信,核心功能(如对话框、文件系统、会话管理)均实现为独立的、可测试的模块。
  • 可视化交互界面:提供直观的聊天式界面,支持文件拖放、多会话管理和工作区集成。
  • 本地数据安全:对话历史和设置默认存储在本地,API密钥经加密管理,未经用户明确同意不传输数据。
  • WebUI模式:可通过嵌入式Web服务器启动,允许通过浏览器远程访问应用。
  • 开发者友好:采用 TypeScript 保证类型安全,配置了 ESLint、Prettier、Jest 等工具确保代码质量和一致性,并集成了 Git Hooks 和规范化的提交信息格式。
  • 丰富的技能库(Skills):内置支持 PDF、PPTX、DOCX、XLSX 等文档的创建、编辑与分析,并提供诸如“Manus风格文件规划”、“HUMAN 3.0 发展教练”等多种工作流技能。

🚀 安装指南

环境要求

  • Node.js: (版本建议参考package.json中的engines字段)
  • npmyarn
  • 系统: macOS / Windows / Linux

安装步骤

  1. 克隆仓库

    gitclone https://github.com/iOfficeAI/AionUi.gitcdAionUi
  2. 安装依赖

    npminstall

    安装过程会自动运行postinstall脚本,处理原生模块的安装。

  3. 开发环境运行

    npmstart

    这会启动 Electron 应用,并运行在开发模式下(支持热重载)。

  4. 构建与打包
    项目使用 Electron Forge 和 electron-builder 进行构建。

    • 开发构建:
      npmrun build
    • 生产环境打包:
      npmrun dist
      特定平台或架构的打包脚本可在package.jsonscripts部分找到,如dist:windist:macdist:linux

原生模块重建

项目依赖一些原生模块(如better-sqlite3bcrypt等)。跨架构构建或特定平台下,脚本会自动处理重建。如需手动强制重建,可设置环境变量:

FORCE_NATIVE_REBUILD=truenpmrun dist

📖 使用说明

基础使用

  1. 启动应用

    • 桌面模式:直接运行可执行文件或使用npm start
    • WebUI 模式
      # Windows"C:\Program Files\AionUi\AionUi.exe"--webui# macOS/Applications/AionUi.app/Contents/MacOS/AionUi --webui
      然后通过浏览器访问http://localhost:3000(端口可能根据配置变化)。
  2. 连接AI代理
    应用启动时会自动检测系统中已安装的、支持的AI CLI工具(如Gemini CLI, Claude Code等)。你可以在设置界面查看和管理已连接的代理。

  3. 开始协作
    在主界面的聊天窗口中输入指令,选择你想要协作的AI代理,即可开始工作。支持文件拖拽上传、多轮对话和上下文管理。

技能(Skills)使用

AionUi 集成了强大的 Cowork 模式,支持通过预定义的“技能”执行复杂任务。当你的请求中包含特定关键词时,对应的技能会被自动激活。

例如

  • 处理 PDF 文件时,可使用pdf技能进行合并、拆分、填写表单或转换图片。
  • 需要创建 PPT 时,可使用pptx技能,遵循html2pptx.jspptxgenjs的工作流生成幻灯片。
  • 需要进行复杂项目规划时,可激活 “Planning with Files - Manus风格文件规划” 技能,它将引导你创建task_plan.mdfindings.mdprogress.md文件来系统化管理任务。

开发与配置

  • 代码风格:项目使用 ESLint 和 Prettier。在提交代码前,Git Hooks 会自动运行检查和格式化。

    # 手动运行代码检查npmrun lint# 自动修复可修复的问题npmrun lint:fix# 格式化代码npmrunformat
  • 环境变量:可以通过环境变量覆盖开发服务器端口,例如:

    AIONUI_DEV_PORT=4000npmstart

💻 核心代码

1. 主进程入口 (main.ts)

此文件是 Electron 应用的主进程入口,负责初始化应用、创建浏览器窗口、设置全局错误处理、启动 Web 服务器和初始化与 AI 代理的通信桥梁。

/** * @license * Copyright 2025 AionUi (aionui.com) * SPDX-License-Identifier: Apache-2.0 */import'./utils/configureChromium';import{app,BrowserWindow,screen}from'electron';importfixPathfrom'fix-path';import*asfsfrom'fs';import*aspathfrom'path';import{initMainAdapterWithWindow}from'./adapter/main';// 初始化主进程与渲染进程的通信桥梁import{ipcBridge}from'./common';import{initializeProcess}from'./process';import{initializeAcpDetector}from'./process/bridge';// 初始化 ACP (AI 代理协议) 检测器import{registerWindowMaximizeListeners}from'./process/bridge/windowControlsBridge';importWorkerManagefrom'./process/WorkerManage';import{startWebServer}from'./webserver';// 启动 WebUI 模式的服务器import{SERVER_CONFIG}from'./webserver/config/constants';import{applyZoomToWindow}from'./process/utils/zoom';// 处理 Windows 安装器事件importelectronSquirrelStartupfrom'electron-squirrel-startup';// 修复 macOS/Linux 下 GUI 应用的 PATH 环境变量if(process.platform==='darwin'||process.platform==='linux'){fixPath();}// 处理 Squirrel 启动事件 (Windows)if(electronSquirrelStartup){app.quit();}// 全局未捕获异常处理器process.on('uncaughtException',(_error)=>{// 生产环境可记录日志或上报if(process.env.NODE_ENV!=='development'){// TODO: 添加错误处理逻辑}});// 应用准备就绪后创建窗口app.whenReady().then(()=>{createWindow();initializeAcpDetector();// 检测可用的 AI 代理// ... 其他初始化逻辑});// 创建浏览器窗口函数functioncreateWindow():void{const{width,height}=screen.getPrimaryDisplay().workAreaSize;constmainWindow=newBrowserWindow({width:Math.min(1440,width),height:Math.min(900,height),webPreferences:{preload:path.join(__dirname,'preload.js'),// 预加载脚本contextIsolation:true,nodeIntegration:false,},});// 加载 Webpack 打包的入口mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);// 初始化与该窗口的通信桥梁initMainAdapterWithWindow(mainWindow);}

2. 预加载脚本 (preload.ts)

预加载脚本在渲染进程加载网页之前运行,负责将安全的、受控的 Electron API 暴露给渲染进程,是实现进程间通信(IPC)的关键。

/** * @license * Copyright 2025 AionUi (aionui.com) * SPDX-License-Identifier: Apache-2.0 */import{contextBridge,ipcRenderer,webUtils}from'electron';import{ADAPTER_BRIDGE_EVENT_KEY}from'./adapter/constant';// 将 `electronAPI` 对象安全地暴露给渲染进程的 window 对象contextBridge.exposeInMainWorld('electronAPI',{// 发送消息到主进程emit:(name:string,data:any)=>{returnipcRenderer.invoke(ADAPTER_BRIDGE_EVENT_KEY,JSON.stringify({name:name,data:data,})).catch((error)=>{console.error('IPC invoke error:',error);throwerror;});},// 监听来自主进程的消息on:(callback:any)=>{consthandler=(event:any,value:any)=>{callback({event,value});};ipcRenderer.on(ADAPTER_BRIDGE_EVENT_KEY,handler);return()=>{ipcRenderer.off(ADAPTER_BRIDGE_EVENT_KEY,handler);};},// 获取拖拽文件的绝对路径(用于 WebUI 模式下的文件选择)getPathForFile:(file:File)=>webUtils.getPathForFile(file),});

3. AI代理连接与适配器 (AcpConnection.ts)

此类负责与支持 ACP (AI 代理协议) 的外部 CLI 工具建立连接、管理 JSON-RPC 通信和处理权限请求,是集成多种 AI 代理的核心。

/** * @license * Copyright 2025 AionUi (aionui.com) * SPDX-License-Identifier: Apache-2.0 */importtype{AcpBackend,AcpIncomingMessage,AcpMessage,AcpNotification,AcpPermissionRequest,AcpRequest,AcpResponse,AcpSessionUpdate}from'@/types/acpTypes';import{ACP_METHODS,JSONRPC_VERSION}from'@/types/acpTypes';importtype{ChildProcess,SpawnOptions}from'child_process';import{spawn}from'child_process';import{promisesasfs}from'fs';importpathfrom'path';interfacePendingRequest<T=unknown>{resolve:(value:T)=>void;reject:(error:Error)=>void;timeoutId?:NodeJS.Timeout;method:string;isPaused:boolean;startTime:number;timeoutDuration:number;}/** * 创建用于生成 ACP CLI 进程的配置。 */exportfunctioncreateGenericSpawnConfig(cliPath:string,workingDir:string,acpArgs?:string[],customEnv?:Record<string,string>){constisWindows=process.platform==='win32';constenv={...process.env,...customEnv};consteffectiveAcpArgs=acpArgs&&acpArgs.length>0?acpArgs:['--experimental-acp'];letspawnCommand:string;letspawnArgs:string[];if(cliPath.startsWith('npx ')){// 处理 npm 包命令constparts=cliPath.split(' ');spawnCommand=isWindows?'npx.cmd':'npx';spawnArgs=[...parts.slice(1),...effectiveAcpArgs];}else{// 处理直接路径或简单命令spawnCommand=cliPath;spawnArgs=effectiveAcpArgs;}constoptions:SpawnOptions={cwd:workingDir,env,stdio:['pipe','pipe','pipe'],// 标准输入、输出、错误流};return{spawnCommand,spawnArgs,options};}/** * ACP 连接管理类。 */exportclassAcpConnection{privatechild:ChildProcess|null=null;privatenextId=1;privatependingRequests=newMap<number|string,PendingRequest>();// ... 其他私有属性和方法/** * 启动 ACP 会话。 */asyncstartSession(cliPath:string,workingDir:string,acpArgs?:string[],customEnv?:Record<string,string>):Promise<void>{const{spawnCommand,spawnArgs,options}=createGenericSpawnConfig(cliPath,workingDir,acpArgs,customEnv);returnnewPromise((resolve,reject)=>{this.child=spawn(spawnCommand,spawnArgs,options);this.child.stdout?.on('data',(data)=>{this.handleStdout(data.toString());});this.child.stderr?.on('data',(data)=>{console.error(`[ACP STDERR]${data.toString()}`);});this.child.on('error',(error)=>{reject(newError(`Failed to spawn ACP process:${error.message}`));});this.child.on('close',(code)=>{constmessage=`ACP process exited with code${code}`;this.rejectAllPendingRequests(newError(message));});// 发送初始化请求以验证连接this.sendRequest('initialize',{protocolVersion:'0.1.0',capabilities:{tools:[]},}).then(resolve).catch(reject);});}/** * 发送 JSON-RPC 请求。 */privatesendRequest(method:string,params?:unknown,timeoutMs=30000):Promise<unknown>{returnnewPromise((resolve,reject)=>{constid=this.nextId++;constrequest:AcpRequest={jsonrpc:JSONRPC_VERSION,id,method,params,};consttimeoutId=setTimeout(()=>{this.pendingRequests.delete(id);reject(newError(`Request${method}timed out after${timeoutMs}ms`));},timeoutMs);this.pendingRequests.set(id,{resolve,reject,timeoutId,method,isPaused:false,startTime:Date.now(),timeoutDuration:timeoutMs,});if(this.child&&this.child.stdin&&!this.child.stdin.destroyed){this.child.stdin.write(JSON.stringify(request)+'\n');}else{reject(newError('Process stdin is not available'));}});}/** * 处理来自子进程标准输出的数据(解析 JSON-RPC 消息)。 */privatehandleStdout(data:string):void{try{constmessage=JSON.parse(data)asAcpIncomingMessage;if('id'inmessage&&message.id!==undefined){// 处理响应this.handleResponse(messageasAcpResponse);}elseif('method'inmessage){// 处理通知或请求(如权限请求)this.handleNotification(messageasAcpNotification);}}catch(error){console.warn('[ACP] Failed to parse stdout:',data,error);}}// ... 处理响应、通知、权限请求等其他方法}

XfkHivgPackSeBYb8h6edGRK+FQI9gdrv8FBRI2tlQs=
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/1 5:09:55

C++11的一些特性

1. 左值引用 vs 右值引用左值引用定义&#xff1a;给左值取别名&#xff0c;用 &表示。特点&#xff1a;能获取地址&#xff0c;有持久状态可出现在赋值符号左边或右边主要作用是减少拷贝&#xff0c;提高效率int a 10; int& ref_a a; // 左值引用 const int&…

作者头像 李华
网站建设 2026/3/1 5:48:02

通信原理篇---PAM与PCM

解释 PAM&#xff08;脉冲幅度调制&#xff09; 和 PCM&#xff08;脉冲编码调制&#xff09; 的区别。1. 基本概念PAM&#xff1a;模拟调制方式&#xff0c;用脉冲序列的幅度来模拟连续信号的瞬时值&#xff0c;仍然是模拟信号。PCM&#xff1a;数字调制方式&#xff0c;先对模…

作者头像 李华
网站建设 2026/2/27 6:10:27

Playwright数据库断言:测试前后数据验证

在自动化测试中&#xff0c;我们常常会遇到这样的场景&#xff1a;测试一个用户注册功能&#xff0c;接口返回了成功&#xff0c;但你真的确定用户数据正确写入数据库了吗&#xff1f;或者测试一个删除功能后&#xff0c;如何验证数据确实从数据库中移除了&#xff1f;这就是数…

作者头像 李华
网站建设 2026/2/21 14:40:59

> STM32-200-多功能门禁人脸识别指纹识别RFID刷卡密码(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

STM32-200-多功能门禁人脸识别指纹识别RFID刷卡密码(设计源文件万字报告讲解)&#xff08;支持资料、图片参考_相关定制&#xff09;_文章底部可以扫码产品功能描述&#xff1a; 本系统由STM32F103C8T6单片机核心板、1.44寸TFT彩屏、&#xff08;无线蓝牙/无线WIFI/无线视频监控…

作者头像 李华
网站建设 2026/2/21 0:32:36

51-C40-温湿度检测+上下限+加热+空调降温+加湿+除湿+手动+自动+OLED屏+声光报警+按键+(无线方式选择)(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

51-C40-温湿度检测上下限加热空调降温加湿除湿手动自动OLED屏声光报警按键(无线方式选择)51-C040B蓝牙无线-APP版: 51-C040W-WIFI无线-APP版: 51-C040CAN-视频监控WIFI无线-APP版: 产品功能描述&#xff1a; 本系统由51单片机最小系统电路、OLED屏、&#xff08;无线蓝牙/无线W…

作者头像 李华
网站建设 2026/2/19 10:42:29

JavaWeb从入门到进阶(vue与Ajax Axios)

什么是Vue: Vue是一套前端框架&#xff0c;免除原生javaScript中的DOM操作&#xff0c;简化书写。 基于MVVM(Model-View-ViewModel)思想&#xff0c;实现数据的双向绑定&#xff0c;将编程的关注点放在数据上本质区别&#xff1a;原生JS&#xff1a;你要告诉浏览器每一步怎么做…

作者头像 李华