从 Web 到桌面:AI Mind Electron Desktop Host 的安全边界设计
本文基于
AI Mind项目的真实实现整理。GitHub:github.com/HWYD/ai-min...
对应代码版本:
v0.5.0线上链接:ai.hwyblog.cloud/instant-min...
AI Mind 是一个持续迭代中的 Next.js AI Chat 项目。从最基础的本地聊天开始,逐步加入流式协议、工具调用、MCP、Skill、Agent、图像生成和桌面端入口。
如果你对这个项目感兴趣,或者这篇文章对你有一点帮助,也欢迎顺手到 GitHub 帮 AI Mind 点个 Star⭐,这会是对我继续更新很大的鼓励。

在前面的版本里,AI Mind 已经逐步完成了聊天、工具调用、MCP、受控 Agent、HITL、checkpoint resume、多会话和图像生成等能力。
这些能力都跑在现有的线上 Web Runtime 里。
到了 v0.5.0,我开始给 AI Mind 增加桌面端入口。
一开始看,这好像只是一个 Electron 套壳问题:
text
打开一个 BrowserWindow
加载线上 URL
打包成 exe / dmg
但真正落到一个长期可维护的 AI 应用里,问题会复杂很多:
text
桌面端要不要打包 Next.js 服务?
要不要在本地保存数据库?
模型、MCP、Agent Runtime 要不要搬到桌面端?
远程页面能不能拿到 Node.js 或 IPC 能力?
用户能不能修改服务地址?
线上服务升级后,旧桌面端还能不能继续加载?
关闭桌面应用时,正在生成的流式回答要不要 cancel?
网络失败、TLS 失败、本地 profile 损坏时,用户怎么恢复?
未签名公开 Beta 要如何发布和校验?
所以 v0.5.0 的重点不是"把 AI Mind 套进 Electron",而是:
在不复制线上 AI Runtime、不向远程页面开放本机能力、不破坏既有会话和流式恢复语义的前提下,为 AI Mind 增加一个可长期维护的桌面宿主。
这篇文章复盘的就是这个过程。
1. 为什么 AI Mind 要做桌面端
AI Mind 本身已经是一个 Web 应用,用户可以直接在浏览器中使用。
那为什么还要做桌面端?
我的考虑主要有三个。
第一,桌面端更像一个长期产品入口。浏览器标签页适合快速访问,但独立桌面窗口更接近用户对"工具"的使用习惯。
第二,桌面端可以保留现有 Web Runtime。v0.5.0 并不是重写一套桌面 AI Mind,也不是把线上服务整体搬到用户电脑里,而是继续使用普通聊天、图像生成、受控 Agent、会话恢复和流式回答。
第三,桌面端可以逐步承接更多本地体验,比如系统托盘、快捷入口、本地文件交互、桌面通知等。但在第一版里,我更关注桌面宿主的基本边界是否站得住。
所以 v0.5.0 的桌面端分工很明确。
线上 webapp 继续负责:
text
聊天
图像生成
受控 Agent
会话
StreamRun
数据库
模型调用
MCP 能力
Electron desktop 只负责:
text
独立桌面窗口
固定官方服务地址
Chromium profile
本地失败恢复页
导航、权限和下载边界
脱敏诊断导出
Windows / macOS 打包
公开 Beta 发布链路
也可以这样理解:
桌面端不是第二套 AI Mind。桌面端是现有 AI Mind 的安全宿主。
2. v0.5.0 的定位:Electron Desktop Host,而不是本地 Runtime
v0.5.0 的正式定位是:
text
AI Mind Desktop Host
它是一个在线桌面宿主,而不是本地 AI Runtime。
这一版支持:
text
Windows x64 Squirrel 安装器
macOS arm64 DMG
面向 GitHub Pre-release 的公开发布 workflow
Unsigned Experimental Preview
这里的 GitHub Pre-release 是发布边界,而不是任意构建完成后就自动创建的下载页。只有固定 Origin 的服务端契约完成生产验证后,才会由同一 source commit 的手动 workflow 创建公开预发布。
这一版不支持:
text
macOS Intel x64
universal binary
Developer ID signing
notarization
自动更新
离线模式
本地 AI Runtime
代码结构上,我把 Electron 相关代码收束到独立 workspace:
text
apps/
desktop/
src/main/ # 主进程、状态机、安全策略、会话和本地协议
src/preload/ # 仅本地 Chrome/recovery 的窄 bridge
src/chrome-renderer/ # 本地 Desktop Chrome
src/recovery-renderer/# 本地失败/升级/重置/诊断 UI
tests/{unit,integration,packaged}/
forge.config.ts
package.json
webapp/
app/api/desktop/compatibility/route.ts
lib/desktop/compatibility-policy.ts
lib/security/browser-security-headers.ts
proxy.ts
apps/desktop 负责 Electron 主进程、本地桌面外壳、本地恢复页、打包配置和桌面测试。apps/webapp 只新增无身份 compatibility API 与 document 请求的浏览器安全响应头,不反向依赖 apps/desktop,也不改变原来的 AI Runtime 分层。
如果 Electron 代码散落在 webapp 里,Web 代码会开始感知桌面端实现细节,Desktop 主进程也容易复用 Web Runtime 内部状态。因此本版的工程拆分原则是:
Electron 特有能力收束到 apps/desktop,webapp 只暴露必要的 HTTP 契约。
3. 为什么首版不做本地 Runtime
做 Electron AI 应用时,很容易想到把 Next.js 服务、数据库、模型、MCP 和 Agent Runtime 一起搬进安装包。但这会同时引入本地服务生命周期、数据库迁移、模型密钥管理、MCP 安装升级、线上线下会话同步,以及 StreamRun/cancel/resume 跨端一致性等问题。
这些不是不能做,但它们应该成为后续独立版本的主题,而不是第一版桌面宿主一起做。
v0.5.0 选择的路径是:
text
AI Runtime 仍然在线上。
Electron 只负责安全承载线上服务。
这样可以复用现有聊天和 Agent 能力、会话和流式恢复语义、部署和数据库,同时避免本地数据迁移和桌面端/Web 端出现两套业务规则。
首版桌面端先解决入口、安全、会话、恢复和发布链路问题,不急着复制一套本地 Runtime。
4. 固定 Origin 与 compatibility gate:启动前先确认能不能加载
公开 Beta 使用固定官方生产 HTTPS Origin,用户不能在 UI、配置文件或环境变量里随意修改。开发模式才接受显式的 localhost 或 127.0.0.1 HTTP Origin,且两者在 build-config.ts(构建期桌面配置)中严格分开:
ts
export function createDesktopBuildConfig(input: {
desktopVersion: string
developmentOrigin?: string
isPackaged: boolean
}): DesktopBuildConfig {
if (input.isPackaged) {
return createConfig(input.desktopVersion, 'production', PRODUCTION_TRUSTED_ORIGIN)
}
if (!input.developmentOrigin) {
throw new Error('A development origin must be explicitly provided.')
}
return createConfig(input.desktopVersion, 'development', parseDevelopmentOrigin(input.developmentOrigin))
}
桌面端启动时不是直接加载 /instant-mind,而是先检查一个无身份、版本化的 compatibility API。启动、重试或 reset 都会创建一个新的 attemptId,兼容性请求、DTO 解析和首次工作区加载共用五秒预算:
text
process start / retry
-> acquire single-instance lock
-> initialize persistent profile + security handlers
-> create attempt { id, deadlineAt = now + 5s }
-> compatibility check
-> compatible -> remote work window
-> manual_upgrade_required -> packaged local recovery window
-> unavailable/invalid/TLS -> packaged local recovery window
只有 compatible 结果可以创建并加载远程工作视图。网络、TLS、HTTP、schema、contract version、超时或首屏加载失败,都会进入本地 recovery;过期 attempt 的异步回调不能把 recovery 切回工作区。
服务端 route 的边界很窄:它严格检查 Accept 和桌面版本 header,只调用无状态的版本 policy,返回 strict JSON、Cache-Control: no-store 和 X-Content-Type-Options: nosniff,不读取 cookie、不访问数据库、不创建会话,也不返回升级 URL 或 capability 列表。
ts
const desktopCompatibilityAccept = 'application/vnd.ai-mind.desktop-compatibility+json; version=1'
export function GET(request: NextRequest) {
if (request.headers.get('accept') !== desktopCompatibilityAccept) {
return Response.json(
{ code: 'DESKTOP_COMPATIBILITY_ACCEPT_INVALID', error: 'Desktop compatibility contract is not accepted.' },
{ headers: responseHeaders, status: 406 }
)
}
const result = resolveDesktopCompatibility(request.headers.get('x-ai-mind-desktop-version'))
if ('kind' in result) {
return Response.json(
{ code: 'DESKTOP_COMPATIBILITY_VERSION_INVALID', error: 'Desktop version is invalid.' },
{ headers: responseHeaders, status: 400 }
)
}
return Response.json(result, { headers: responseHeaders })
}
桌面端 compatibility.ts(兼容性客户端)使用 workspace session 的 Chromium 网络栈,凭据显式省略,并使用当前 attempt 的剩余时间:
ts
response = await input.session.fetch(new URL(input.config.compatibilityPath, input.config.trustedOrigin).toString(), {
credentials: 'omit',
headers: {
accept: 'application/vnd.ai-mind.desktop-compatibility+json; version=1',
'x-ai-mind-desktop-version': input.config.desktopVersion,
},
method: 'GET',
signal: AbortSignal.timeout(remainingDeadlineMs),
})
桌面端不要直接加载远程页面。先做版本兼容性检查,再决定是否进入工作窗口。
5. 远程工作窗口的安全边界:零本机能力
Electron 最大的风险之一,是远程页面拿到本机能力。
如果一个远程页面既能运行 Web 代码,又能通过 preload、IPC 或 Node.js 访问本机能力,那么它的安全边界就不再是普通网页,而更接近本机应用。
v0.5.0 的远程工作窗口选择了最保守的策略:
text
nodeIntegration = false
contextIsolation = true
sandbox = true
no preload
no generic IPC
不暴露 shell.openExternal
不暴露文件系统
不暴露系统权限 bridge
即使远程页面来自官方 AI Mind 服务,也不能默认获得本机能力。自己的站点也可能有 XSS、依赖注入、错误配置、内容策略漏洞;一旦 Web 层出问题,影响范围不应被放大到用户本机。
实际工作区位于本地 Desktop Chrome 下方的 WebContentsView,关键配置如下:
ts
contentPreferences: {
allowRunningInsecureContent: false,
contextIsolation: true,
experimentalFeatures: false,
nodeIntegration: false,
sandbox: true,
session: input.session,
webSecurity: true,
webviewTag: false,
}
这里没有 preload。远程工作页只作为 Web 页面运行,不能通过 Electron 获得额外本机权限。
security-policy.ts(工作区安全策略)再把导航、弹窗、权限和下载收束到主进程:
ts
input.webContents.on('will-navigate', preventUntrustedNavigation)
input.webContents.on('will-frame-navigate', event => preventUntrustedNavigation(event, event.url))
input.webContents.on('will-redirect', preventUntrustedNavigation)
input.webContents.setWindowOpenHandler(() => ({ action: 'deny' }))
input.session.setPermissionCheckHandler((_webContents, permission, requestingOrigin, details) =>
shouldAllowWorkspacePermission({
isMainFrame: details.isMainFrame,
permission,
requestingOrigin,
trustedOrigin: input.trustedOrigin,
})
)
TLS 校验继续由 Chromium 的正常信任链处理,桌面端没有证书绕过或 HTTP fallback。
Electron 安全不是只防第三方网站,也要防自己的远程页面越权。
6. 本地 recovery 页怎么实现:独立 session + 窄 IPC
如果 compatibility check 失败,或者网络、TLS、本地 profile 出问题,桌面端不能继续加载工作窗口,但也不能直接崩溃。
所以 v0.5.0 设计了本地 recovery 页面。它不是线上页面,也不是普通错误页,而是随安装包一起分发的本地页面。

它的职责很窄:
text
重试固定官方 Origin
显示手动升级说明
执行用户确认后的本地资料重置
复制或导出脱敏诊断信息
它不能加载任意外部 URL,不能打开外部升级链接,不能读取线上 cookie、工作页 cache 或 Service Worker,也不能调用通用本机 API。
远程工作窗口使用持久 profile:
text
persist:ai-mind-desktop
本地 recovery 页使用非持久 session:
text
ai-mind-desktop-recovery
它们由 session-profile.ts(会话 profile 与本地重置)统一创建:
ts
export function createDesktopSessions<Session>(fromPartition: (partition: string) => Session) {
return {
workspaceSession: fromPartition('persist:ai-mind-desktop'),
recoverySession: fromPartition('ai-mind-desktop-recovery'),
}
}
recovery 通过包内 protocol 加载,例如 ai-mind-desktop://local/...。local-protocol.ts(本地资源协议)只允许访问资源清单中的 Chrome 和 recovery HTML、JavaScript、CSS,并为每个响应设置独立 CSP;query、hash、路径遍历、未知 host/path 和白名单外资源都会被拒绝。
recovery 的 preload 只暴露四个具名操作:
ts
const recoveryApi: RecoveryBridgeApi = {
confirmResetProfile: input => ipcRenderer.invoke(recoveryBridgeChannels.confirmResetProfile, input),
copyDiagnostic: () => ipcRenderer.invoke(recoveryBridgeChannels.copyDiagnostic),
exportDiagnostic: () => ipcRenderer.invoke(recoveryBridgeChannels.exportDiagnostic),
retry: () => ipcRenderer.invoke(recoveryBridgeChannels.retry),
}
contextBridge.exposeInMainWorld('aiMindRecovery', recoveryApi)
主进程还会验证 sender、当前 recovery URL、参数 schema 和并发状态,因此这不是一条可被远程页面复用的通用 IPC。
recovery 页不是普通错误页,而是一个本地安全边界。它必须和远程工作页隔离。
7. 桌面本地状态和线上业务状态怎么分开
v0.5.0 不新增业务数据库表,这一版做的是状态边界划分。
| 状态 | 事实源 | 负责什么 | 不负责什么 |
|---|---|---|---|
| DesktopBuildConfig | 包内常量 | 桌面版本、固定 Origin、产品 identity、分发标识 | 用户配置、secret、任意 server URL |
| DesktopPreviewManifest | 打包后生成的只读文件 | 版本、平台、Electron 版本、SHA-256、public-beta/unsigned | 下载 URL、签名凭据、用户资料 |
| DesktopSessionProfile | Chromium persistent session | cookie、IndexedDB、localStorage、cache | 服务端密钥、数据库凭据、业务状态 |
| DesktopCompatibilityState | 启动期检查结果 | compatible / upgrade / unavailable | 聊天内容、cookie、原始异常 |
| DesktopRecoverySession | Electron memory session | recovery 页本地状态 | 线上 cookie、cache、Service Worker、工作页权限 |
| DesktopHostState | Electron main process | 启动、窗口类型、attempt、compat state | StreamRun、Agent state、用户业务数据 |
| Existing webapp / StreamRun | 线上 AI Mind 服务 | chat、Agent、image、idempotency、cursor、cancel | Electron 本地实现细节 |
这个分层的目的,是避免桌面端接管业务事实源:
text
桌面端保存 cookie,但不决定用户是否有权限。
桌面端保存 profile,但不保存聊天业务状态。
桌面端知道 compatibility state,但不保存 GraphState。
桌面端可以 reset 本地资料,但不删除服务端数据。
桌面端保存的是浏览器资料,不保存 AI Mind 的业务状态。
这和前面几个版本的设计是一致的。v0.3.x 里,业务状态和 checkpoint 分开;v0.4.x 里,聊天线程状态仍然由服务端 Runtime 管理;v0.5.0 里,Electron 也不能越界成为新的业务状态源。
8. 会话、流式恢复和关闭行为
桌面端接入后,一个很实际的问题是:会话怎么保留?
v0.5.0 没有重新设计一套本地身份系统。桌面端和网页端都使用服务端签发的持久会话 cookie,每次正常使用会将有效期续至未来 30 天,连续 30 天未使用才失效。
Electron 负责保存 Chromium profile,服务端负责 cookie 的授权、续期和失效。也就是说:
text
Electron 主进程不读取 cookie。
Electron 主进程不构造 cookie。
Electron 主进程不续期 cookie。
Electron 主进程不判断用户身份。
reset 也不会删除服务端数据。它只清理固定 Origin 对应的本地 trusted profile:
ts
export function clearWorkspaceProfile(session: SessionWithClearData, trustedOrigin: string): Promise<void> {
return session.clearData({
dataTypes: ['cache', 'cookies', 'downloads', 'fileSystems', 'indexedDB', 'localStorage', 'serviceWorkers', 'webSQL'],
origins: [trustedOrigin],
})
}
整体流程是:
text
用户点击 reset
-> recovery 页请求确认
-> 主进程销毁远程工作窗口
-> 清理 trusted Origin 对应的本地浏览器数据
-> 重新进入 compatibility check
流式回答还在生成时关闭桌面应用怎么办?v0.5.0 不伪造 cancel。关闭、崩溃、休眠和重开都不主动创建取消请求;重开后也不会重新挂接仍在活动中的流式订阅,更不会伪造成"已完成"。
它只按现有 Web 端的 hydration 和已持久化终态读取规则展示结果。如果桌面窗口关闭就主动 cancel,桌面端就改变了服务端 StreamRun 语义;如果重开后伪造完成结果,前端就可能展示一个并不存在的终态。
桌面端不要因为窗口关闭,就擅自改写服务端流式状态。
9. 权限、导航、下载:桌面端要默认拒绝
Electron 桌面端一旦提供本机窗口,读者很容易误以为它应该像普通桌面应用一样开放更多能力。
但 v0.5.0 的策略是反过来的:
默认拒绝,只为明确场景开窄口。
默认拒绝包括:
text
off-origin navigation
redirect / frame / popup
file: / javascript: / data: / 非本地 protocol
未声明 permission
clipboard read
file system access
device access
自动下载
外部打开请求
这里有一个实现细节:外部链接打开。
一开始可能会认为,用户主动点击的安全 https:// 链接可以交给系统浏览器打开。但在实际验证里,Windows / Electron 行为没有提供足够稳定的 metadata 来区分真实用户点击和脚本触发。因此 v0.5.0 最终选择:外部打开 allowlist 为空,所有外部打开请求都拒绝,不调用 shell.openExternal。
text
不能稳定识别安全条件时,不做"看起来方便"的放行。
下载策略也同样收敛。v0.5.0 只允许用户主动触发的受信图片保存:
text
必须来自受信工作区主框架
必须有用户手势
必须是同源 blob: 的单一 URL chain
必须经过原生保存对话框
不允许自动下载
不允许 redirect chain 绕过判断
不把保存路径写进诊断
security-policy.ts 对允许的图像下载只设置保存对话框选项,而不把路径交给 renderer:
ts
if (!decision.allowed) {
event.preventDefault()
return
}
item.setSaveDialogOptions({
defaultPath: decision.filename,
filters: [{ extensions: [decision.extension], name: '图像文件' }],
})
不要把 Web 页面升级成拥有本机权限的页面。桌面能力必须白名单化。
10. 发布链路:server-first public beta
Electron 项目很容易把发布理解成:
text
打包 exe / dmg
上传 GitHub Release
用户下载
但 v0.5.0 的发布链路不是这样。
因为这个桌面端依赖固定官方线上服务。它能不能工作,不只取决于安装包,也取决于线上 compatibility API 和页面安全响应头是否已经部署。
所以发布顺序必须是 server-first。
大致流程是:
text
1. 部署同一 source commit 的 webapp compatibility API 和安全 header
2. 运行 production verification
3. fixed Origin 验证通过
4. 手动触发 public release workflow
5. 构建 Windows x64 / macOS arm64 未签名制品
6. 生成 desktop-release.json 和 SHA-256
7. 验证实际 package fuse / hash
8. 完成 fresh install / overlay install smoke
9. 创建 GitHub Pre-release
在 server compatibility 没有验证通过之前,不应该创建公开 Pre-release,也不应该分发安装器。否则安装包和线上服务可能处于不兼容状态。
公开发布 workflow 的入口把这条约束写成了显式参数:
yaml
on:
workflow_dispatch:
inputs:
source_commit:
required: true
production_verified:
description: Confirm that production deployment and verify-production.sh passed
required: true
options: ['false', 'true']
jobs:
windows:
if: inputs.production_verified == 'true'
Windows 和 macOS job 会针对对应平台生成 installer 或 DMG、平台化 desktop-release.json 和 SHA-256,并在发布前校验真实 executable 的 fuses 与打包内容。
Electron 发布不是只产出安装包,还要和服务端兼容契约一起发布。
11. 实现过程中最值得写的几个踩坑点
v0.5.0 的实现里,有几个点比较适合单独记录。它们不是这篇文章的主线,但能让读者看到真实工程复杂度。
11.1 CSP 和桌面本地 UI 样式
桌面端接入后,Web 页面和 Electron 本地页面都需要安全响应头或本地 CSP。
Web document 为了兼容 Next.js、Radix UI 以及运行时样式,最终需要允许:
text
style-src 'self' 'unsafe-inline'
但这个例外不能扩散到 script-src、API response、static resource、prefetch 或 Electron local CSP 的其他资源边界。
本地 Chrome / recovery 页面也类似:可以允许受控的本地样式例外,但脚本仍然必须保持:
text
script-src 'self'
禁止 unsafe-eval
禁止白名单外资源
Web document 的脚本仍由 request nonce 和 strict-dynamic 约束;样式兼容例外只解决样式问题,不能顺手放宽脚本策略。
11.2 本地 Desktop Chrome 顶栏
v0.5.0 不只是加载一个网页。为了让桌面端更像真实应用,它还增加了本地 Desktop Chrome:
text
AI Mind 标识
查看菜单
帮助菜单
Windows 原生 titleBarOverlay controls
macOS traffic lights
拖动区域
no-drag 交互区
固定 /instant-mind workspace

Windows 和 macOS 的窗口控制区域不同,拖动区域也不同。菜单点击区域必须是 no-drag,否则用户点不到菜单;空白区域又应该保留拖动能力,否则窗口移动体验会很差。
实现上,Windows 的顶栏高度为 40px,titleBarOverlay 保留右侧系统控制;macOS 使用 hiddenInset 保留左侧 traffic lights。Desktop Chrome 的本地 bridge 只接受 view、help 两个菜单名,并校验 sender URL 与菜单坐标,远程工作页并不拥有这条 bridge。
11.3 CI、打包和安装验证不是一次成功
Electron 进入双平台打包后,验证成本会明显上升。
v0.5.0 需要覆盖:
text
workspace lint
typecheck
stable tests
build
desktop unit tests
desktop integration tests
package audit
fuse/hash verification
Windows lane
macOS arm64 lane
fresh install smoke
overlay install smoke
server-first production verification
这里的重点不只是生成 Squirrel 和 DMG。发布脚本还会生成和检查 release manifest、SHA-256、真实 executable 的 fuse 状态以及 package 内容;公开发布前,服务端验证和双平台安装 smoke 仍然属于同一条验收链路。
Electron 工程难点不只在写窗口,而在安全策略、跨平台 UI、CI、打包、发布和验收证据。
12. 这一版刻意不做什么
v0.5.0 的范围必须明确。
这一版不做:
text
本地 AI Runtime
离线模式
自动更新
Developer ID signing
notarization
Intel Mac
universal binary
任意 Origin
应用内升级 URL
远程页面本机 API
完整本地身份系统
新的服务端部署路径
这些不是永远不做,而是不适合放进 v0.5.0。尤其是本地 Runtime、自动更新、签名/公证和离线模式,每一项都足够成为一个独立版本。
v0.5.0 更像是桌面化的第一块地基:
text
固定服务地址
启动兼容性检查
远程窗口零本机能力
本地 recovery
会话资料复用
server-first 发布
公开 Beta 制品验证
地基先稳定,后面再考虑更复杂的桌面能力。
13. 总结:Electron 桌面端不是简单套壳,而是宿主边界设计
做完 v0.5.0 后,我对 Electron 接入 AI 应用有一个更明确的感受:
桌面端不是把网页装进一个窗口这么简单。
尤其是 AI 应用已经有会话、流式恢复、Agent、图像生成、模型调用和服务器状态时,桌面端首先要回答的不是"怎么打包",而是:
text
可信服务地址如何固定?
远程页面能不能拿本机能力?
加载前如何确认版本兼容?
失败时如何安全恢复?
会话资料保存在哪里?
服务端流式状态是否被桌面端改写?
本地 reset 会不会删除服务端数据?
发布时如何保证 server 与 desktop 同步?
未签名公开 Beta 如何标识和校验?
v0.5.0 的答案是:
text
只做 Online Host。
不复制线上 AI Runtime。
固定官方 HTTPS Origin。
远程工作窗口零本机能力。
兼容才加载,失败进 recovery。
桌面只保存 Chromium profile。
会话和业务状态仍由服务端负责。
发布先验证 server,再发布 desktop。
公开 Beta 明确标记 unsigned experimental preview。
这也是这篇文章想表达的核心:
v0.5.0 的重点不是"把 AI Mind 套进 Electron",而是在不复制线上 AI Runtime、不向远程页面开放本机能力、不破坏既有会话和流式恢复语义的前提下,为 AI Mind 增加一个可长期维护的桌面宿主。
从工程角度看,这个版本不是最显眼的功能版本。它没有新增一个模型能力,也没有新增一个 Agent 类型。
但它让 AI Mind 从 Web 项目往桌面产品形态迈了一步,而且这一步没有牺牲原有 Runtime 的边界。
这对后续继续做桌面增强、本地能力和多端体验,是一个比较稳的起点。
项目地址
GitHub:github.com/HWYD/ai-min...
线上体验:ai.hwyblog.cloud/instant-min...
如果这篇文章或者 AI Mind 项目对你有所帮助,也欢迎顺手帮项目点个 Star⭐。这个支持对我来说很重要,也会让我更有动力继续整理后续版本的实现过程、设计取舍和踩坑复盘。