Skip to content

AgnesCode IPC 协议分析报告

协议端点: Renderer (React) ↔ Main Process (Electron Node.js)
通信方式: Electron IPC (contextBridge)
报告日期: 2026-07-25
分析版本: v1.0.17


1. 架构概述

┌────────────────────────────────────────────────────────────┐
│  Renderer Process (React 19)                               │
│  ┌──────────────────────────────────────────────────────┐  │
│  │ window.electron.xxx()  ←  contextBridge.exposeInMainWorld │
│  │ window.appConfig.xxx()                                │  │
│  └──────────────────────┬───────────────────────────────┘  │
│                         │ IPC                               │
│  ┌──────────────────────▼───────────────────────────────┐  │
│  │  Main Process (Node.js 24)                           │  │
│  │  ipcMain.handle("channel", handler)  ← invoke         │  │
│  │  ipcMain.on("channel", handler)      ← send           │  │
│  │  webContents.send("channel", data)   → on             │  │
│  └──────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────┘

安全模型:

  • contextIsolation: true — 上下文隔离开启
  • nodeIntegration: false — 渲染进程无法直接访问 Node.js
  • 所有系统功能通过 contextBridge.exposeInMainWorld 暴露
  • 严格的 CSP (Content-Security-Policy) 限制

2. IPC 通信模型

AgnesCode 使用三种 IPC 模式:

2.1 invoke/handle (双向请求-响应)

Renderer 调用 window.electron.xxx()ipcRenderer.invoke() → Main Process 的 ipcMain.handle() 处理 → 返回 Promise

javascript
// Renderer (preload.js)
startAuthLogin: () => ipcRenderer.invoke("start-auth-login")

// Main Process (main.js)
ipcMain.handle("start-auth-login", async (event) => {
    // ... 处理逻辑
    return { state: hexState };
});

2.2 send/on (单向消息)

Renderer 通过 ipcRenderer.send() 发送消息,Main Process 监听:

javascript
// Renderer
reactReady: () => ipcRenderer.send("react-ready")

// Main Process
ipcMain.on("react-ready", async (event) => { ... });

2.3 on/webContents.send (主进程推送)

Main Process 通过 webContents.send() 向 Renderer 推送事件:

javascript
// Main Process
webContents.send("auth-deeplink", { code, state });

// Renderer (preload.js)
on: (channel, callback) => { ipcRenderer.on(channel, callback) }

3. 完整 IPC API 清单

3.1 认证 & OAuth

方法类型方向参数返回值
startAuthLogininvokeR→M{ state: string }
authListenerReadysendR→M-
getSecretKeyinvokeR→Mstring
事件 auth-deeplinkonM→R{ code: string, state: string }-

认证流程:

  1. Renderer 调用 window.electron.startAuthLogin()
  2. Main Process 生成 32 字节 state, 打开浏览器登录页
  3. 用户登录后, 浏览器回调 agnes://auth/callback?code=...&state=...
  4. Main Process 验证 state 后发送 auth-deeplink 事件到 Renderer
  5. Renderer 用 code 调用远程 API 交换 access_token

3.2 后端管理 (agnest)

方法类型方向参数返回值
waitForBackendReadyinvokeR→Mboolean
getAcpUrlinvokeR→Mstring | null (WebSocket URL)
getGoosedHostPortinvokeR→Mstring | null (baseUrl)
reactReadysendR→M-

启动流程:

  1. Renderer 发送 react-ready 表示 UI 就绪
  2. Main Process 启动 agnesd 子进程
  3. 健康检查轮询: GET /health_check (每 250ms, 最长 30s)
  4. 就绪后, Renderer 通过 getAcpUrl() 获取 WebSocket URL
  5. WebSocket URL: wss://127.0.0.1:{port}/acp?token={secretKey}

3.3 窗口管理

方法类型方向参数返回值
hideWindowsendR→M-
closeWindowsendR→M-
createChatWindowsendR→M{...}?-
raiseMainWindowsendR→M-
setAlwaysOnTopinvokeR→Mbooleanboolean
getAlwaysOnTopinvokeR→Mboolean
getIsFullScreeninvokeR→Mboolean
isAnyWindowFocusedinvokeR→Mboolean
setWindowsTitleBarOverlaySurfacesendR→Mstring-

3.4 文件系统

方法类型方向参数返回值
readFileinvokeR→Mstring (path)string (content)
writeFileinvokeR→M(path, content)-
readFileDataUrlinvokeR→M(path, encoding?)string
readImageFileinvokeR→Mstring (path)ArrayBuffer
readOfficePreviewinvokeR→Mstring (path)any
directoryChooserinvokeR→Mstring | null
selectFileOrDirectoryinvokeR→Mstring? (defaultPath)string | null
selectImportSessionFileinvokeR→M{ filePath, contents, error? } | null
listFilesinvokeR→M(dir, pattern?)string[]
ensureDirectoryinvokeR→Mstring (path)-
showItemInFolderinvokeR→Mstring (path)-
openPathinvokeR→Mstring (path)-
openDirectoryInExplorerinvokeR→Mstring (path)-
shareExportZipinvokeR→M{...}-
writeSkillPreviewFileinvokeR→M(path, content)-
uploadBinaryToPresignedUrlinvokeR→M{ uploadUrl, contentType, body }-

3.5 设置 & 配置

方法类型方向参数返回值
getSettinginvokeR→Mstring (key)any
setSettinginvokeR→M(key, value)-
getConfig同步R→Mobject (启动参数)
getAll同步R→Mobject (全部 env)
getVersion同步R→Mstring

appConfig 对象 (通过 contextBridge 暴露):

javascript
window.appConfig = {
    get: (key) => config[key],              // 获取单个环境变量
    getAll: () => ({ ...config })           // 获取所有环境变量
};

暴露的环境变量:

AGNES_DEFAULT_PROVIDER, AGNES_DEFAULT_MODEL, AGNES_PREDEFINED_MODELS,
AGNES_VERSION, AGNES_API_HOST, AGNES_PATH_ROOT, AGNES_WORKING_DIR,
AGNES_INITIAL_THEME, AGNES_LOCALE, AGNES_API_URL

3.6 应用更新

方法类型方向参数返回值
checkForUpdatesinvokeR→MUpdateInfo
downloadUpdateinvokeR→M-
installUpdateinvokeR→M-
getUpdateStateinvokeR→MUpdateState
restartAppsendR→M-
reloadAppsendR→M-
事件 updater-eventonM→RUpdateEvent-

3.7 伪终端 (PTY)

方法类型方向参数返回值
createPtySessioninvokeR→M(cwd, cmd, args?)sessionId
writePtySessioninvokeR→M(sessionId, data)-
resizePtySessioninvokeR→M(sessionId, cols, rows)-
closePtySessioninvokeR→MsessionId-
事件 agnes-pty-eventonM→R{ sessionId, event, data }-

3.8 Git 集成

方法类型方向参数返回值
getGitSummaryinvokeR→Mstring (dir)GitSummary
watchGitSummaryinvokeR→Mstring (dir)-
unwatchGitSummaryinvokeR→Mstring (dir)-
listGitWorktreeDirsinvokeR→Mstring (dir)string[]
事件 agnes-git-summary-changedonM→RGitSummary-

3.9 Workspace 管理

方法类型方向参数返回值
listWorkspaceTreeinvokeR→Mstring (dir)TreeNode[]
listWorkspaceTreeChildreninvokeR→M(dir, path)TreeNode[]
readWorkspaceFileinvokeR→M(dir, path)string
checkLocalPreviewinvokeR→Mstring (path)boolean
addRecentDirinvokeR→Mstring (dir)-
listRecentDirsinvokeR→Mstring[]

3.10 通知 & 对话框

方法类型方向参数返回值
showNotificationsendR→MNotificationOptions-
showMessageBoxinvokeR→MMessageBoxOptions{ response: number }
showSaveDialoginvokeR→MSaveDialogOptions{ filePath: string }
openNotificationsSettingsinvokeR→Mboolean

3.11 外部链接

方法类型方向参数返回值
openExternalinvokeR→Mstring (url)-
openInChromesendR→Mstring (url)-
launchAppinvokeR→Mstring (app)-
getLaunchedAppinvokeR→Mstring (app)any
refreshAppinvokeR→Mstring (app)-
closeAppinvokeR→Mstring (app)-

3.12 语音 (腾讯云)

方法类型方向参数返回值
getTencentVoiceConfiginvokeR→MTencentVoiceConfig
transcribeTencentVoiceinvokeR→M(audio, mimeType)string
startTencentRealtimeSessioninvokeR→MsessionId
sendTencentRealtimePcmsendR→M(voiceId, pcmBase64)-
stopTencentRealtimeSessioninvokeR→MvoiceId-
cancelTencentRealtimeSessioninvokeR→MvoiceId-
事件 tencent-voice-realtime-eventonM→Revent-

3.13 mesh-llm (P2P 模型网络)

方法类型方向参数返回值
checkMeshinvokeR→M{ running, installed, models, ... }
startMeshinvokeR→Margs[]{ started, pid, error? }
stopMeshinvokeR→M{ stopped }
checkOllamainvokeR→Mboolean

3.14 其他

方法类型方向参数返回值
capturePageinvokeR→MNativeImage
collectElectronLogsinvokeR→Mstring
invokeAppMenuActioninvokeR→Mstring-
setMenuBarIconinvokeR→Mboolean-
getMenuBarIconStateinvokeR→Mboolean
setDockIconinvokeR→Mboolean-
getDockIconStateinvokeR→Mboolean
setWakelockinvokeR→Mboolean-
getWakelockStateinvokeR→Mboolean
setSpellcheckinvokeR→Mboolean-
getSpellcheckStateinvokeR→Mboolean
setVisualPinchZoomLockinvokeR→Mboolean-
broadcastThemeChangeinvokeR→Mstring (theme)-
hasAcceptedRecipeBeforeinvokeR→Mstring (recipe)boolean
recordRecipeHashinvokeR→Mstring (recipe)-
getGlobalShortcutFailuresinvokeR→Mstring[]
事件 mouse-back-button-clickedonM→R-
事件 network-interface-changedonM→Revent-

4. 预定义设置项

从 preload.js 提取的默认配置:

javascript
const R = {
    showMenuBarIcon: true,
    disableAutoDownload: false,
    showDockIcon: true,
    enableWakelock: false,
    enableNotifications: true,
    spellcheckEnabled: true,
    keyboardShortcuts: {
        focusWindow: "CommandOrControl+Alt+G",
        quickLauncher: "CommandOrControl+Alt+Shift+G",
        newChat: "CommandOrControl+T",
        newChatWindow: "CommandOrControl+N",
        openDirectory: "CommandOrControl+O",
        settings: "CommandOrControl+,",
        find: "CommandOrControl+F",
        findNext: "CommandOrControl+G",
        findPrevious: "CommandOrControl+Shift+G",
        alwaysOnTop: "CommandOrControl+Shift+T",
        toggleNavigation: "CommandOrControl+/"
    },
    disabledKeyboardShortcuts: {},
    externalGoosed: { enabled: false, url: "", secret: "" },
    theme: "light",
    useSystemTheme: true,
    language: "system",
    agentMode: "smart",
    responseStyle: "concise",
    showPricing: true,
    sessionSharing: { enabled: false, baseUrl: "" }
};

5. 安全性分析

  1. contextIsolation: Renderer 无法直接访问 Node.js API
  2. nodeIntegration: false: 渲染进程无法 require 模块
  3. CSP: 严格的 Content-Security-Policy, 限制 script-src 和 connect-src
  4. 预定义白名单: preload.js 只暴露了有限的方法
  5. 协议白名单: openExternal 检查危险协议 (如 file://)
  6. Secret Key 保护: 密钥通过 IPC 传递, 不在渲染进程存储

6. 关键数据流图

┌──────────┐    IPC invoke    ┌──────────────┐    spawn      ┌──────────┐
│ Renderer │◄───────────────►│ Main Process  │◄───────────►│  agnesd  │
│  (React) │    contextBridge   │  (Node.js)    │  HTTPS+WS    │  (Rust)  │
└────┬─────┘                  └──────┬───────┘              └──────────┘
     │                               │
     │  fetch (HTTPS)                │  shell.openExternal
     ▼                               ▼
┌──────────┐                  ┌──────────────┐
│  Agnes   │                  │  System      │
│  API     │                  │  Browser     │
│  Server  │                  │  (OAuth)     │
└──────────┘                  └──────────────┘

基于 MIT 协议发布