把 DeepSeek Harness 装进自己窗口的桌面外壳。Tauri v2 加 Vue 3,负责内核安装与切换、插件与技能管理、额度与用量看板,以及把内核跑起来的那一堆进程、端口和环境变量。每个内核按实例运行、互不干扰,内核代码一行不改,装的是 npm 上官方发布的包。内核版本跟着官方 deepseek-ai/deepseek-harness 的 dsh-v* tag 一键安装、切换、删除。
面板跟随系统浅色 / 深色,也可以手动切。下面是同一套界面的两种外观,以及独立的模型用量窗口。
| 概览页(浅色) | 内核版本 |
|---|---|
![]() |
![]() |
- 下载安装包:Releases 页 取 Windows 的
.exe或 Intel Mac 的.dmg。目前未做操作系统代码签名,Windows SmartScreen 与 macOS Gatekeeper 可能提示来源未受信任;先核对下载来源。若安全软件检出、隔离文件,或启动报「拒绝访问」,按安全软件与文件访问排查记录检测名称、完整路径和原始错误后处理。 - 装内核:应用启动后在「内核版本」页选一个版本点「安装」,进度面板会实时滚动安装日志。首次安装不会自动启动,装完回「概览」页点「启动工作台」。没装 Node.js 会在这一步弹窗问你要不要自动装。
- 配模型凭据:工作台「设置 → 模型」填好 DeepSeek 的
DEEPSEEK_API_KEY,然后就能开始对话。
会话、凭据、插件与技能全部落在 ~/.dsh-xlink/ 下,面板不外发使用数据。
Harness 本身是个 Web 服务,日常用就要自己起进程、记端口、记 Node 路径。这一层把这些事收进一个窗口:
- 内核版本自己管。npm registry 上的全部发布版本(含
-rc/-alpha)都能装、能切、能删,不用翻 GitHub Releases 找 tag。切换前会先记下当前配置。 - 出事了有回头路。启动前自动存档环境(内核版本、插件物化模式、技能启用位),一键回到最近一次被成功启动验证过的那套配置。装插件前还有一次性沙盒预检,装坏了原样回滚。
- 账算得清。本地会话扫出一份按天 × 模型的 token 账目(90 天滚动),云端那边 DeepSeek 余额、MiniMax、智谱、OpenAI、opencode 以及自定义中转 2api.store 的剩余额度并排看,全部只读当前实例已配置的凭据。
- 不打扰正在做的事。关窗口只是收进后台,内核和任务照跑;任务跑完弹通知加角标,切回工作台即清零;开机自启默认不弹窗,只在菜单栏 / 托盘留一个图标。
- 插件出事能定位。工作台白屏时自动上报证据并归类(疑似插件 / 疑似内核 / 前端 bundle / 环境),实在归不出来还能二分:按嫌疑度每轮装一半进沙盒,n 个插件 ⌈log₂n⌉ 轮缩小到最小可疑集合。
- 两个壳互不干扰。开发版与正式版各有各的实例、内核安装树、端口和插件中央库,可以同时跑。
多内核模型:内核族(family)是一等概念,注册表 state/instances.json(dev 壳 instances-dev.json)、安装树、数据目录都按它分 namespace。目前只注册了 dsh 一个族,mcode 是留着证明通用实例模型能容纳第二种内核的 mock。界面侧暂时没有切换入口:顶部那条内核族页签与概览页的实例切换器已在 2026-10-07 移除(后端只定义一个族,页签从第一天起就只会画出一个、点自己等于没点),set_default_instance 命令本身留着,等第二个族接进来时直接调。
0 侵入内核:外壳通过 KernelAdapter trait 与每个内核族对接。DshAdapter(active)负责 DeepSeek Harness 的实例准备,McodeAdapter(mock)证明通用实例模型能容纳第二种内核。外壳只做三件事:拉起实例前准备 home / profile / workspace / 端口 / customSkillDirs;启动时把 DSH_HOME、DSH_PROFILE 等环境变量塞给进程(技能目录也注入了 DSH_CUSTOM_SKILL_DIRS,但当前内核不消费它,接通靠的是 patch 接线行);跑起来后用 WebSocket / HTTP 探测健康、回收进程组、订阅事件流。内核二进制、profile 结构、cordis 配置、session 格式一概不动。接入新内核 = 加一个 KernelAdapter 实现并注册进 adapters(),通用实例模型一行不动。
+------------------------------ dsh-xlink (Tauri v2) ------------------------------+
| |
| main window (panel) harness window official-chat |
| ui/ static page WebviewWindow window |
| - kernel status / start "harness" WebviewWindow |
| - update menu loads "official-chat" |
| - settings / logs http://127.0.0.1:<port> loads |
| - open official chat button = kernel web UI https:// |
| | invoke ^ ^ chat.deepseek |
| v | | .com |
| +-----------------------------------------------------------------------+ |
| | Rust shell: kernel lifecycle via KernelAdapter trait | |
| | - DshAdapter: @deepseek-ai/dsh, prepare home/profile/workspace | |
| | -> <DSH_XLINK_HOME>/kernels/dsh/instances/<id>/ | |
| | - McodeAdapter (mock): structural placeholder, same lifecycle | |
| | - install: pnpm add @deepseek-ai/dsh@<version> | |
| | (node-linker=hoisted; live log stream to UI) | |
| | - start: node .../lib/bin.js web --no-open --port <port> | |
| +-----------------------------------------------------------------------+ |
| ^ |
| kernel data (sessions, settings, credentials) | per-instance home/ |
| extensions/plugins/<id>/ |
| ^ |
| shared skills active view (skills/active/) | read by every kernel via an |
| xlink-skill-filesystem row |
| appended to cordis.patch.yml |
+----------------------------------------------------------------------------------+
- 内置工作台:外壳在本地起
dsh web,用专用窗口加载其 Web UI。往这个窗口注入七段脚本:标题栏品牌条带、拉绳小台灯(静态)、健康自愈探针、未发送草稿与历史会话保护、右键兜底(系统原生菜单一律不弹;内核自绘的菜单照常,输入框 / 选区上则改弹壳自己的复制粘贴菜单)、外观镜像(把内核「设置 → 外观」选定的浅色 / 深色 / 跟随系统同步到窗口原生外观;跟随系统时不覆盖,页内的系统配色查询保持有效)。窗口原生标题栏跟着内核的会话标题走,进出全屏时通知内核调整布局;内核自己发起的window.open(账号登录的授权页、终端里的链接)在壳托管的临时弹窗里打开,普通外链仍交系统浏览器——既保留内核原本的流程,也不在壳外长出无主窗口。草稿(含还没发出去的图片)经壳落盘,窗口被自愈重建或手动刷新换掉之后,输入框里的东西仍能回到原处,已经发出去的那条不会又填回来。 - 官方对话快捷入口:概览页的「打开官方对话」拉起独立的
official-chat窗口,固定加载 chat.deepseek.com。默认只初始化 DeepSeek 页签,MiniMax 在首次选择时才创建,并保留本窗口状态,首开的 CPU、内存与网络开销因此小得多。窗口只注入静态的 chrome-row 品牌条带与拉绳挂件,不跑常驻动画,避免 WKWebView 空闲时持续渲染。窗口不覆盖 user-agent:WebView2 本身就是真实的桌面版 Edge,原生 UA、Sec-CH-UA与navigator.userAgentData一致;改写成 Chrome 反而造出「HTTP 层报 Edge、JS 层报 Chrome」的自相矛盾,那正是环境检测的特征。专属目录同时充当持久化配置档案,DeepSeek 登录态跨重启保留。窗口已开时按钮变为「关闭官方对话」,复用现有窗口并set_focus。设计细节与OFFICIAL_CHAT_BROWSER_ARGS见 docs/architecture/architecture.md。 - 官网对话引用:启用内置插件后,在工作台输入
@DeepSeek/、@MiniMax/或@ChatGPT/选择最近会话,选中后保存固定正文供当前提问使用。须在壳内官网页签登录;目录和正文不保证覆盖全部历史。当前实现、账户身份验证及验收边界见功能状态。 - macOS / Windows 自定义标题栏:管理面板在这两个平台用前端自绘标题栏,窗顶一条 2 px 的构建标识线(
--build-color),正式版深 Gitea 绿、dev 构建换低亮度鲸眼红系,一眼分清两个壳;它叠在标题栏上缘、不占高度。窗口按钮按平台惯例绘制,macOS 是左上角红黄绿交通灯,Windows 是右侧的最小化 / 关闭按钮(46×38 命中区、10 px 细线字形,hover 覆浅色底,关闭 hover 变系统红)。无边框由tauri.conf.json的decorations: false在建窗时给定。独立窗口(日志 / 模型用量 / 套餐用量)只保留关闭按钮:它们是只读数据面板,不参与后台常驻——关掉就是关掉,重新打开走主面板里的入口,所以最小化对它们没有意义(Windows 上那枚按钮点下去只会得到一句Command minimize_shell not allowed by ACL,该命令的授权只归管理面板)。建窗期同时给了minimizable(false),任务栏右键「最小化」、Win+D 这类绕开自绘标题栏的入口也一并关掉。 - 后台常驻(两平台统一):关闭窗口只是把它收进后台,内核、工作台、官方对话与更新检查继续运行;真正退出只在常驻入口图标的右键菜单「退出 Dsh-Xlink」,退出前若内核在跑会先问一句。Windows 的入口是通知区域托盘(收起时用
ITaskbarList::DeleteTab从任务栏移除按钮,任务栏与 Alt+Tab 都不再留一个点了没反应的窗口),macOS 的入口是菜单栏状态项(收起时把面板移出 Dock,菜单栏图标自动跟随系统明暗反色)。两端行为完全一致,实现只有一份,此前只有 Windows 是常驻,macOS 上关窗即退出,同一份产品在两个平台上得学两遍。图标左键单击叫回窗口,右键出菜单。从后台重新打开时,每次启动只在第一次提示「刚才只是把窗口收进了后台」(4 秒):窗口隐藏时收不到页内提示,靠它避免看起来像崩溃,此后收起与恢复一律静默。 - 开机自启动:「设置 → 后台常驻」里可开。开启后下次开机系统会把 dsh-xlink 拉进后台但不显示面板,菜单栏 / 托盘图标是全部可见痕迹。机制是系统登录项:macOS 写
~/Library/LaunchAgents/*.plist,Windows 写HKCU\...\CurrentVersion\Run,都只动当前用户、不需要管理员权限。另有独立的「开机启动工作台」开关(默认关)。两个开关刻意分开,因为代价不同、接受度也不同:开机弹窗口挡在用户面前是自动启动最招人烦的地方,而开机就占端口、起 node 进程、订阅事件流,多数用户不需要。搬过目录或换了构建后,条目仍指向旧位置会被识别出来并提示重勾。 - 磁盘用量:「内核版本」页底部自动统计,按内核版本 / 实例数据 / 插件 / 技能 / 备份 / 壳日志四类以瓦片卡片并排两列,条目按大小降序。四个类型各配一色(圆点 / 占比条 / 容量数字同色),悬停标题给出这一类是什么、能不能删的说明,因为四类的可回收性完全不同,而这正是你点进这块区域要答的问题。两个壳显示为「开发版 / 正式版」而不是目录名里的
dev/release。「内核版本」页每个已安装版本行上还有一个「共享存储」标记:那棵树是旧版方式装的、文件仍与其他目录共享,删除或重装会短暂惊动对面正在用的工作台(会自动恢复),卸载后重装一次即彻底隔离。进页面立即显示上次结果,后台每天自动重扫一次,界面上标着这组数字是什么时候扫的;旁边的「刷新」立刻强制重扫一遍。自动刷新一天一次即可,进面板时重扫要遍历两万多个文件。只读,没有任何删除入口:最大的两块是内核node_modules与实例 DSH home(装的是你的会话与附件),壳无法替你判断哪块该删,删错了不可逆。给数字,删除的决定权和操作都留给你(用 Finder 处理)。统计按目录树展开且不跟随软链,因此是上界。点击任意条目(某个版本 / 实例 / 中央库)可就地展开它下一层子目录与文件的占用,展开过的行还能继续往下点,逐层定位「这块到底大在哪」;文件行是叶子点不开(pnpm-lock.yaml这类大文件直接给数)。下钻按需统计——展开一节扫一节,结果在面板内缓存,报表重扫后自动作废重取;路径限定在 dsh-xlink 数据目录之内,依旧只读。 - 内核更新:npm registry 的
@deepseek-ai/dsh与 GitHubdsh-v<semver>tag 一一对应。更新菜单直接读 npm registry 拿到全量版本与dist-tags,可安装、切换、删除任意已发布版本;npm registry 不可达时才回退 GitHub Releases API 与其 Atom feed。 - 右键策略按窗口分:管理面板(含日志、模型用量、套餐用量与官方对话页签栏这几个独立窗口)与官方对话的两个页签里按右键都不弹菜单,页面自绘的右键菜单也一并取消;工作台改为只压系统原生菜单,内核自己画的菜单照常可用——JSON 树复制按钮右键出来的「选择复制方式」、右侧栏标签页的右键菜单都不再被误伤。工作台上页面没处理的右键分两种:输入框 / textarea / 可编辑区域或只读选区上,弹壳自己的编辑菜单(撤销 / 重做 / 剪切 / 复制 / 粘贴 / 全选,只有只读选区时只给「复制」),与内核官方桌面壳同一套项;其余位置什么都不弹。左键拖选与 Ctrl/⌘+C 复制照旧可用,禁的只是系统菜单。注入脚本只作用于主文档,工作台里 iframe 内容(Browser 页签、HTML 预览)不归它管。安装新版本后需要重新打开工作台与官方对话窗口,已存在的 WebView 不会自动替换注入脚本。
多内核改造记录:P0–P8 已落地(内核族注册表、实例切换、插件按实例物化、技能全局共享、数据迁移向导、release threshold 验证)。
KERNEL_FAMILY_DSH = "dsh"/KERNEL_FAMILY_MCODE = "mcode"共存于KernelAdapter::adapters()注册表。2026-09-19 的阶段快照见 docs/architecture/multi-kernel/multi-kernel-migration-status-2026-09-19.md,设计意图见 docs/architecture/multi-kernel/dsh-xlink-multi-kernel-design.md,实际数据布局以 docs/architecture/architecture.md 为准。文档总索引见 docs/README.md。
- 一键启动 / 停止工作台。概览页主按钮切换内核状态;同排的「打开工作台窗口」「打开官方对话」是次级入口,都不改内核状态(这一排原有的第三枚「刷新工作台」2026-10-15 起不在界面上,机制仍留着,见 docs/ui/panel-decisions.md)。全应用的日志入口走概览页「系统健康 → 日志系统」弹层,要更大屏就在弹层里点「全屏」开独立窗口(原先概览页那枚「查看日志」快捷按钮已删,它和这里其实是两套不同行为);事故面板与插件预检对话框各自带一个「打开日志」,跳的是同一个弹层。日志列表按用途分组(内核 / 安装 / 插件 / pnpm / Node / 其它),点分组标题即可收起或展开那一类,收起后标题右侧显示这一组还剩几份;收起状态记在本地,弹层与独立窗口共用,下次打开仍是收起的(当前正在看的那一份所在的组会自动展开,不会出现「内容在显示、列表里却找不到它」)。
- 打开官方对话:拉起独立窗口,固定排布 DeepSeek / MiniMax 两个页签;本机 Codex 登录可用时会在末尾追加一个 ChatGPT 页签(判据与额度查询同源,见下文「OpenAI 模型登录与额度查询不是同一种授权」)。与工作台窗口互不干扰。使用原生 Edge UA 与可持久化登录的专属 user-data 目录。窗口已开时按钮变为「关闭官方对话」并销毁当前窗口。
- 多内核模型:内核族注册表
KernelAdapter::adapters()里并存DshAdapter(active)与McodeAdapter(mock),每个族可同时跑多个实例,插件与内核安装树按实例物化。界面侧暂不提供切换入口(顶部内核族页签与实例切换器已移除,只有一个族时它们从第一天起就是空操作),set_default_instance命令保留待用。侧栏菜单、插件页、技能页、设置页都作用于本壳的默认实例。已迁移的用户不再看到启动弹窗,需要时从侧栏「系统」组的「数据迁移」进入回查最近一次迁移。 - 更新菜单:列出 npm registry
@deepseek-ai/dsh的所有发布版本(含预发布版本,列表里不再单独打「预发布」标签,版本号里的-rc/-alpha段已经说明了),可安装、切换活动版本、删除本地版本。已安装与官方版本两栏之间用上下两端收细的竖向刻蚀线分隔。 - 内核安装通过 pnpm:
node-linker=hoisted保持扁平node_modules,内容寻址存储让重复安装更快;导入方式固定package-import-method=copy,新装的树不与任何目录共享 inode,装 / 删内核因此碰不到另一个壳正在跑的工作台。代价是每个版本实占约 450 MB。安装过程逐行流式显示在进度面板,完整日志落盘~/.dsh-xlink/shell/release/logs/<kind>-install-<版本>-<日期>.log(dev 壳为~/.dsh-xlink/shell/dev/logs/dev-install-<版本>-<日期>.log,<日期>为本地日期)。下载先写临时文件、成功后才发布;npm 包由外壳做路径受限、禁止链接和有展开大小上限的 Rust 解包,无需额外安装系统tar。 - Node.js 自动检测与手动指定:要求
^22.19 || >=24,与 dsh 的 engines 一致。自动发现 nvm(macOS/Linux~/.nvm/versions/node/<v>/bin/node跟随alias/default链,Windows%NVM_SYMLINK%与%NVM_HOME%/v*/node.exe)。检测为空时弹窗询问是否「帮我安装」,确认后自动下载官方 Node.js(v24 LTS,SHA-256 校验)到数据目录tools/node/;概览页 Node 行随时可再次触发。已安装的托管运行时优先于环境检测,显式配置的 node 路径仍最高优先。 - pnpm 路径可配置(默认取 node 同目录或 PATH)。
- 端口可配置:release 默认 3090,dev 壳默认 3091。设置页的「工作台」卡只保留这一项可改的(插件接线 profile 名是固定值,跟着端口一起保存)。概览页「当前内核」标题旁的 ℹ️ 悬浮显示自动检测的 Node 环境结论;该卡的 Node.js 行提供「重新检测」与「自动安装」。
- 任务完成通知:macOS Dock 与 Windows 任务栏图标右上角都有数字角标,两端同时弹一条系统通知气泡。气泡三行:📋 会话标题、💬 用户最后发的那条提问、尾行用时(
用时 N 分 N 秒)。几处刻意的取舍:- 用时紧跟在那一轮对话之后,不挂在标题行。它量的就是这一轮,而长会话名在气泡里先被截断,挂着时长的标题行会只剩半句。
- 正文不写完成时刻。通知讲的是「刚刚发生的这一轮」,横幅本来也不显示时间,正文再写一遍只是替系统说它不会说的话,还白占一行;确切时间去「设置 → 任务通知」的最近完成列表查。
- 提问超长时只取前 15 个字符加省略号。macOS 通知最多三行,全量塞进去会把尾行的用时挤出可视区,而那行恰恰是用户判断「刚才跑了多久」的关键。
- 提问行用图标而不是「最近对话:」这类文字标签:通知正文是纯文本、没有可排版的元素,文字标签既占宽度又和上方标题的措辞混在一起,扫一眼分不出哪行是结论、哪行是上下文。💬 与本项目「官方对话」用的是同一个符号。
- 角标数字是已完成但用户未读的任务数。工作台不在前台时完成的任务才计数(正在看工作台时不打扰),切回工作台或点面板「全部已读」即清零。
- 「设置 → 任务通知」的最近完成列表逐条展示会话名、完成时间、用时与最近一轮对话(问 / 答预览,不截断,悬浮可见全文)。
- 检测方式是让外壳以客户端身份订阅内核自己的 WebSocket 流(
/api/remote.mux的$events判完成、session/control取会话标题与turnOutline最近一轮对话),不轮询、不占内核 CPU。子代理会话不打扰。 - 通知开关与「试听」提示音都在「设置 → 任务通知」里,自检按钮只在 dev 构建显示。
- 通知通路被系统挡住时不会静默:Windows 的「设置 → 系统 → 通知」关着时,系统照常接受
Show却不显示任何气泡(角标走任务栏 API,只剩红点),壳会主动问系统的ToastNotifier::Setting()并在设置页给出灰字说明、写入错误,指向那个开关。macOS 上未打包的开发构建同理(拿不到应用 bundle)。 - 设计与取舍见 docs/features/notifications/notification-design.md。
- 点通知横幅回到工作台:通知的意义是让用户回来看结果,所以横幅本身必须能点。Windows 上未打包应用的通知被点中时,系统启动的是本 exe而不是「叫醒」已运行的窗口;第二个进程照常启动的话,会顺手把第一个进程正在服务的内核回收掉,等于「回来看看结果」先把结果弄没了。壳因此在启动最前面抢一个具名互斥体:抢到的负责监听一条命名管道,后来的进程把「回到工作台」写进管道就立即退出,
setup()一行都不会执行。macOS 上系统是激活已运行的进程,壳改为在应用被重新打开时把工作台抬到台前。两条路径最终都汇到同一个动作:工作台已经开着就把它拉到台前(角标同时清零),没开过就按当前内核地址开一个。工作台打不开时不静默失败,管理面板会被叫回前台并说明原因与下一步。点击后定位到具体那个会话尚未实现(内核还没有「聚焦某个会话」的入口)。 - 插件管理(按实例定制):社区插件(npm 包或 GitHub 仓库)由外壳统一管理,源存放在
DSH_XLINK_HOME。中央库一份,按实例各物化一份:每个实例把中央库的链接(默认,Windows 自动降级复制)落到自己的extensions/plugins/<id>/,再由该实例自己的extensions/wiring.json记录 profile 接线。不同实例可以装不同插件、不同模式、不同启停状态,切换实例无需重装。GitHub 仓库地址安装时优先使用对应 GitHub Release 的 tarball 版本数据,Release 不可用时回退 git clone,其它 Git 地址保持原 clone 行为。「插件仓库」分组对接 dshfind.com 插件超市目录(关键词 / 分类 / 排序三个参数一起交给壳去搜、只回一页;6 小时本地缓存,官方 market 兜底)。面板提供安装 / 卸载 / 更新 / 切换模式 / 「同步内核」(把中央库重新物化到所有已装内核);检测到新版本时在卡片与启动时提醒;侧栏「插件」项上挂一个红色圆点,悬浮说明是「插件有 N 个可更新」。「同步」重新物化中央库中的插件,并清除外壳明确标记的已删除残留。link模式插件启动前会检查中央目录中的普通运行时依赖,缺失时自动用 pnpm 恢复。多实例隔离规则与权威目录布局见 docs/architecture/architecture.md。 - 插件安装沙盒预检:点「安装」时先在一个一次性沙盒实例里真的装一次、真的启动一次内核,确认没问题才装到当前实例;装坏了原样撤销,中央库按字节回滚,你的环境一个字节都不会变。判定分三态:通过 / 未通过 / 未能验证,绝不把「没能验证」说成「没问题」。之所以要多跑一次基线:装了插件起不来,可能是插件的锅,也可能是环境本来就坏了;只有基线正常、装了插件才失败,才判未通过。这与
diagnostics/guard.rs那条「不肯因为环境问题停用无辜插件」是同一条纪律。代价是多花十几秒,可在插件中心关闭。预检只覆盖内核启动阶段(进程存活、端口监听、HTTP 应答、启动日志),工作台页面加载后的运行时异常仍由工作台窗口的健康自检负责。实现见src-tauri/src/plugins/sandbox.rs(沙盒生命周期)与src-tauri/src/plugins/precheck.rs(两段式事务),坏掉之后怎么捞回来的规划见 docs/features/diagnostics/safety-net-design.md。 - 深入排查(安全网 P2):工作台起不来、回退也解决不了时,用二分法把范围缩到「能解释现象的最小集合」。按嫌疑度排序后每轮只把当轮那几个插件装进一次性沙盒,看内核起不来就排除另一半,直到剩下的就是可疑的那几个(⌈log₂n⌉ 轮,n=12 时 4 轮,比逐个停用的最坏 12 次快得多)。被排除的那半边既不物化也不进 profile 清单,内核因此真的在「缺它们」的状态下启动,分治的全部前提就在这一步。全程逐轮显示「在试哪一半 / 上一轮结果 / 已排除几个 / 还要几轮」,可随时中断且已排除的结果保留。候选只含插件:技能是全局共享的、没有按实例的接线可写,要「二分技能」只能去改你的真实技能状态,那比它要诊断的问题更危险。收尾只有三种说法,定位到最小可疑集合 / 原因不在插件里 / 已中断,绝不叫「根因」:组合效应(两个扩展单独都正常、一起就炸)会让二分停在一个不可修的答案上。工作台运行时不接受排查,与恢复同一条理由,环境正被真实内核占用,查出来的现象和你眼前的对不上。
- 一键回到良好状态(安全网 P1):设置页「环境回退点」卡的「回到良好状态」把环境恢复到最近一次被成功启动验证过的那套配置。两步分开:先把将要发生的改动逐条列出来(内核版本、插件启用与物化模式、技能启用位),确认后才动手;动不了的那几条(中央库已删的插件、没装回的内核版本、补丁方向)在确认之前就标出来,不让你在一个不完整的承诺上点确认。动手前自动把当前环境另存成新的回退点,恢复本身失败也能再退回来。插件与技能只会被停用,不会被卸载或删除,卸载不可逆,让一次回退顺手做了等于用恢复换数据。改完后会把恢复后的那套配置真的装进一次性沙盒再启动一次内核实测(不是起一个裸内核空转),实测结论分三种在界面上画成三种不同的东西:「实测通过」/「实测未通过」(附具体原因)/「本次没有改动,因此没做实测」。把「没测」画成「测过没问题」是这类工具最容易犯也最伤害信任的错,界面宁可显得啰嗦也不合并它们。恢复需要工作台已停止,重复确认只问一次(有信息量的是第一次)。
- 环境回退点(安全网 P0,只读记录):每次成功启动工作台、以及你改动配置(装 / 卸插件、切内核版本、切物化模式)之前,桌面端都会记下「当时那套配置长什么样」:内核版本、插件集与物化模式、启用的技能、已应用的补丁。设置页的「环境回退点」卡逐条列出,并标出哪一份被真正启动验证过、哪一份此刻仍在生效。快照里不含任何凭据或 API Key;文档损坏时面板会如实提示「读不出来」,而不是显示成「从来没有过回退点」。完整设计与 P2/P3 的二分定位规划见 docs/features/diagnostics/safety-net-design.md。
- 插件面板信息架构:单 panel 双 tab,「当前内核」显示本实例的安装 / 启停 / 更新,「已安装」展示全部实例的插件视图(每行带「内核族 · 实例 id」与状态徽标:已接线 / 未接线 / 版本不一致 / 未同步 / 已隔离,悬停给出原因)。面板骨架屏 + 并行加载 + 收紧切换动画。
- 工作台健康自检:工作台窗口自动监听白屏、运行时错误、未处理的 Promise 异常,以及内核客户端模块 bundle 的
<script>加载失败。最后这一类最关键:内核把加载失败的模块行静默丢掉,页面照常起来,随后只会抛renderSlot('root') before any 'root' registration (boot order)之类的启动顺序错误,而那类堆栈落在多成员 bundle 组合上、没有包名,凭它是无法归因的。自检改为把失败脚本的完整地址一并上报,于是能直接归因到具体插件或内核版本。外壳把前端证据(异常类型与消息、cause链、堆栈、页面地址)与今天的内核日志一起分析,归类为「疑似插件问题」「疑似内核问题」「前端 bundle 异常」「运行环境问题」或「暂未能归因」,并在事故面板展示证据和对应的处置入口。归不出包名的「前端 bundle 异常」不弹事故面板(页面仍在运行、没有可处置对象),只在概览页横幅提示,点「查看详情」展开完整证据:按提示先看日志、反馈错误消息,再考虑停用第三方插件或切换内核版本。完整设计见 docs/operations/troubleshooting.md。 - 工作台黑屏时的手动出路:关掉工作台窗口,再点概览页的「工作台窗口」重新打开——那一步走完整建窗路径,拆掉整个窗口也就换掉了渲染进程(原先那枚一键的「刷新工作台」2026-10-15 起不在界面上,机制仍留着,见 docs/ui/panel-decisions.md)。它针对的正是自动自愈够不到的那一类:WebView2 渲染进程崩在页面加载完成之后(装内核时 pnpm 的文件风暴实测会打崩它),而自动看门狗的判据是「开始加载后 15 秒没等到加载完成」,此时页面早就加载完了、判据永远不会触发,
reload()落在死掉的文档上仍然是黑的(用户原话:「reload 后,还是会黑屏」)。代价是窗口里的滚动位置、侧栏面板、终端标签回到初始状态(没发出去的草稿会保住),会话在服务端不受影响。自动重建有预算:同一进程最多 3 次、两次之间至少隔 20 秒,单个窗口最多自动重载 2 次,所以「一直闪」不会发生,超限后停下来把真实错误留给用户;手动这两步不受那个预算约束(它只管自动重建),但也不会把已经用掉的额度清零。自动重建每次都记进「日志系统 → 工作台窗口」里的harness-window.log并写明成因,关窗重开走的是另一条路、不记那一行。内核没在跑时点「工作台窗口」会被拒绝并指路(「请先点击『启动工作台』」),不做一次让人白等窗口闪动的无效重建。 - 内嵌 OpenAI 插件(实验性,默认关闭):随应用交付一个 dsh 专属的 OpenAI 套餐接入插件(Sign in with ChatGPT 授权路线,与普通 API Key 路线互不影响)。它是插件页「当前内核」列表的第一行,带一枚「内嵌」来源徽标,行尾开关打开即可启用,启用无需联网安装:插件资源随应用交付,启用时按内核指纹物化到实例自己的目录,内核安装树保持只读。启用后重启工作台,在「设置 → 模型」的 OpenAI 提供方卡上登录 ChatGPT 账号(系统浏览器完成授权,令牌加密存放于系统凭据库,不进浏览器页面),会话即可选择账号可用的 OpenAI 模型并按模型能力设置思考强度。账号目录里的模型默认全都进会话选择器,几十条里混着实验模型,所以卡片下半部分提供「常用模型」(默认收起成一行:摘要显示已选哪几项,点「选择模型」才展开;勾选只改草稿,点「保存」才写盘,保存后自动收起;「恢复默认」同样要点保存,未保存时显示「未保存的更改」且不许收起,另有「放弃改动」)。保存后不用刷新页面——插件的 Host 侧盯着偏好文件,一变就让内核重拉模型目录;取消勾选正在使用的模型时,那条会话会被要求另选一个(不会静默换模型,也不会报模型不存在)。已启用的内嵌插件在每次工作台启动前自动刷新资源与接线,同版本源码修复也会更新实例副本。支持发送图片及在后续对话中继续引用历史图片;图片由内核附件服务校验并转换后发送,文件附件沿用内核的文字句柄与工具读取方式。模型目录与对话请求统一走 OpenAI 资源服务(https://api.openai.com/v1),授权服务只负责登录与令牌刷新。当前捆绑版本 v0.1.15 把常用模型收成一行摘要(v0.1.14 改成「勾选后点保存才记」,v0.1.13 增加常用模型勾选,v0.1.12 修复了工具请求里的
Unknown parameter: tools[0].namespace:本地函数按官方命名空间容器分组,并保持工具调用与结果的标识一致);升级后重新启动工作台即可加载(服务端提示套餐额度用尽时仍需等待额度重置)。兼容最近 3 个官方 dsh 内核版本(离线验证覆盖 0.2.1-alpha.1 / 0.2.0-rc.2 / 0.2.0-rc.1);真实 OpenAI 服务的联调验收仍在进行,行为可能随版本调整。设计与实现状态见 docs/features/extensions/openai-oauth-design.md 与 docs/features/extensions/openai-oauth-development-plan.md。 - 内嵌 Ponytail 插件(默认关闭):把 Ponytail(MIT)的「懒惰阶梯」接进工作台——写代码前先找现成的、再考虑标准库、最后才自己写。它默认关闭:技能与规则是指令文本、会整体进模型上下文,与 OAuth 那类「不登录就没副作用」的内置插件不是一回事。首次启用需要联网:内容不在安装包里,由壳在启用时从上游拉取并校验完整性(之后每次启动工作台自动检查更新,一天一次;也可随时用
/ponytail-update或插件面板的「检查更新」立即拉取)。规则在会话启动时注入一次,之后本会话持续有效,/ponytail lite|full|ultra可当场调松紧;同名时你自己装的技能优先。这两项能力依赖@deepseek-ai/dsh-hooks-claude-code这个桥,而它随不随内核安装由内核上游的打包决定(实测0.2.1-alpha.2把它降级成了开发依赖,内核树里没有它):缺了壳会自己按内核版本从 npm 补一份(只补树里没有的、版本严格等于内核版本、落进插件自己的数据目录;0.2.1-alpha.2上实测补得到,Node 能正常加载),补到之后规则注入与档位切换照常有。连补也补不到(离线或 registry 不可达)时,插件仍能正常启用、六个技能照常可用,只是这两项能力暂时缺席——插件面板会挂一条 ⚠ 说明,联网后重启工作台会自动重试;也可以换回带这个包的内核版本(如0.2.1-alpha.1),不必重装本应用。做不到的:状态栏徽标与收益记分牌(宿主没有对应面)。出处、许可与适配说明见 plugins/ponytail/README.md。 - 技能管理(全局共享):社区技能(npm 包 / GitHub 仓库 / 本地文件夹)由外壳统一管理,源存放在
DSH_XLINK_HOME/skills/packages/,按包安装的粒度以链接(失败降级复制)物化进一份 v1 全局共享的活动视图(skills/active/)。所有内核实例共用同一份活动视图,壳在每个实例的cordis.patch.yml里插一条自己的skill-filesystem行,把它作为customSkillDirs交给内核(DSH_CUSTOM_SKILL_DIRS只是留给未来内核版本的兜底,当前内核不读它)。不改 cordis 配置、不装依赖、切换实例零操作这一侧是确定的:内核对技能根做文件监视,安装 / 卸载 / 更新对运行中的工作台即时生效,无需重启。技能页的社区浏览与手动安装之间使用两端收细的刻蚀线分隔。- 接线只在工作台启动时写入,所以升级后要重启一次工作台技能才会出现。
- 另有一类情况壳改不动:若你的家目录本身是 git 仓库,内核会把
~/.dsh/skills与~/.agents/skills当作「项目级」技能根(优先级高于壳的活动视图),与那里同名的技能会盖掉壳管理的那一份。此时面板顶部会列出被盖住的条目与对应文件,并给一个「移走被盖住的条目」按钮,只把那份改名让路(文件名加时间戳后缀)、不删除;改回原名即可恢复,移走后壳的启停与更新立刻对它们生效,不必重启工作台。 - 安装前逐个校验 SKILL.md frontmatter(kebab-case
name+description必填),避免「装了却不出现」。已安装卡片在包头提供逐个启用 / 停用开关(粒度是单个技能),停用只把条目移出活动视图,包仍留在中央库,随时可恢复。 - 中央库与活动视图的条目状态包括「未同步」,本地活动根条目与中央库记录不一致时显示,提示用户先「重新同步」。
- 机制与验证见 docs/features/extensions/skill-management.md §「技能接线」;多实例共享活动视图的设计理由见 docs/architecture/architecture.md。
- 内嵌本地记忆插件(默认关闭):把「这个项目约定怎么做事」「我一贯的偏好」这类长期有效的东西存在本机,相关会话自动带上。它需要两个开关:插件页启用「本地记忆」(内置插件,改完要重启工作台),记忆页打开「使用已批准的记忆」——只开一个不会有任何效果,所以记忆页在另一个没开时会直接说出来并给一个启用按钮。模型只能读与提候选、不能自己改库:
memory_search按关键词检索、memory_read按 id 读完整正文,memory_propose提交候选;自动提取出来的长期约定会直接存成记忆(标为「未验证」),只有与既有记忆冲突、或推翻旧候选的才进「待确认」由你裁决;模型改不了开关、删不掉东西,也不替你决定冲突。检索是有界的:一次最多 6 条、单条正文截断、单次注入 12 KiB,同一个会话最多注入 8 次(内容没变不重复注入,会话级累计不超过 36 KiB;会话中途改过库的话另有至多 2 次刷新)。记忆按「实例 × profile」隔离,项目按内核的工作区归属——面板的「本项目」是一个下拉,列出工作台里用过的项目(也可以手填目录),保存时同时记下内核的工作区 id 与路径,项目改名或换盘后仍能对上。数据落<实例目录>/memory/<profile>/memory.json(0600、原子替换);删除会留下正文指纹,防止将来的自动提取把刚删掉的东西长回来。「导出 Markdown」生成一份一次性快照到同目录的exports/(不参与运行时,手工改那份文件不会反向入库;权威记录读不出来时快照头部会写明,不会给你一份看起来正常的空文件)。自动提取默认关闭,跟着「使用已批准的记忆」这个开关一起开关;打开后聊完一轮,模型会把这一段里长期可复用的偏好与约定提出来直接存成记忆——一次性事件、临时故障、排障结果与只跟当前任务有关的细节不会提取,整段就是一次排障或单个任务时不会被记下来。隐私边界:记忆会随请求进入模型上下文,选远端模型时它和其他上下文一样出网——默认关闭正是为此。设计与验证进度见 docs/features/memory/dsh-xlink-memory-design.md。 - 工作交接与经验:记忆面板新增交接与经验视图。交接按项目保存目标、完成项、待办和阻塞,新建下一条会归档旧交接;经验保存适用情境、做法、实际结果与教训,模型提出后需用户审核才可召回。模型可用 memory_context 读取当前交接与匹配经验。归档交接与经验都随快照导出。数据格式升级至 schema 6 后,旧版只能读取、不能继续写入,避免降级丢字段。
- 数据迁移向导:侧栏「系统」组提供常驻入口,设置页不再重复展示。嵌入式 4 步向导,发现 → 选择 → 运行 → 完成 / 回滚。迁移运行期间走
ProgressOverlay,与安装内核 / 装插件共享同一进度 UI。凭据与会话首版不纳入迁移(旧版默认保守),冲突策略默认SkipIfNewer(保留用户后来修改),旧源永不被删除(rollback 路径依赖)。启动弹窗只在从未处理过迁移时出现:成功迁移(后端自动记录静音标记)、点过「否」或已有迁移历史(含旧版本迁完、部分失败与回滚过的用户)重启后都不再被询问,需要时从侧栏「数据迁移」进入。完成后回主界面,顶部 banner 报告最近一次迁移的状态。向导里还有一张「找回历史会话」卡:别的实例 home 里存着本实例缺的sessions/与attachments/时才出现,只复制、源永不删除、目标已有条目永不覆盖,执行前要求目标实例的内核没有在跑。这个功能已定在 v0.6.0 之后整体移除(过渡期内仍是正式功能),届时前后端四块一起删,只删前端菜单不算数。完整设计见 docs/features/migration/migration-wizard-ui-proposal.md。 - 模型用量统计:概览页「当前内核」卡显示今日 token 用量,点同排的「模型用量」弹出独立可缩放窗口(与日志查看器「全屏」同一条建窗路径;默认吸附主窗右侧、高度与本体一致,主窗拖动时 60fps 合帧跟随)。窗口提供 6 档范围:今日 / 7 / 15 / 30 / 60 / 90 天。顶部摘要卡含「今日用量 / 日均用量 / 请求次数 / 活跃天数 / 最常用模型」瓦片,另有 GitHub 式活跃热力图、按模型堆叠的按天 Token 趋势柱状图(token 数精确到小数点后两位),以及模型用量环形图(中心显示当前范围合计 token)和列表(每模型的 token 数与占比,列表自适应高度,滚动期间才显形滚动条)。统计口径是最近 90 天,超过的记录自动丢弃,窗口标题旁的 ℹ️ tooltip 与卡片悬浮提示都会说明这一点。数据来自本机内核的会话文件(
sessions/下的多帧 zstd JSONL,逐条读取模型回复自带的 token 计量,只认真实模型调用),按「天 × 模型」预聚合进一份增量账目(<实例目录>/usage/state.json,百 KB 量级),不保存任何会话原文。扫描按文件增量进行(只解新追加的帧、旧文件整跳过),首次全量秒级、之后毫秒级。窗口是只读的,每次打开都会强制重扫一次;账目按实例隔离,与壳的 release / dev 模式无关。视觉布局见仓库顶部截图,机制与存储设计见 docs/architecture/architecture.md。 - OpenAI 登录入口:「插件 → 当前内核」的 OpenAI-OAuth-Plugin 行可直接登录 ChatGPT。已登录时显示脱敏邮箱、刷新模型列表与退出登录;授权中可取消,需要重新登录时可重新授权或退出。这里和工作台「设置 → 模型」的账号卡使用同一套账号服务,状态自动同步(定期回读最长约 5 秒)。停用插件不退出账号,账号操作也不修改插件开关。
Windows 上已存在的登录密钥从凭据管理器读取并复用。查询脚本先调用 RetrievePassword() 加载密码,再读取 Password 属性;修复了把方法的空返回值误报为“查询没有返回任何结果”的问题,已有凭据无需删除或重新生成。
- 套餐 / Token Plan 用量(云端):概览页「当前内核」卡下方的独立卡片展示云端账户的剩余额度,共 7 个分区(
usage/subscription.rs的PROVIDER_ORDER固定展示顺序:DeepSeek → MiniMax-CN → MiniMax-EN → 智谱 GLM → OpenAI → opencode → 2api)。- DeepSeek 是货币余额(多币种逐行,总额 / 赠金(未过期)/ 充值三项分别列出,余额不足以发起调用时单独标红)。MiniMax-CN 与 MiniMax-EN 的 5 小时 / 周窗口、智谱 GLM 编程套餐的 5 小时 / 周窗口、OpenAI ChatGPT 套餐的 5 小时 / 7 天窗口、opencode(厂商)Go 套餐的滚动 5 小时 / 周 / 月三窗口是剩余百分比(进度条按剩余量三档配色,附重置倒计时,并在倒计时旁标出已用 X%——厂商自己的界面基本都按已用显示,两个读数并排才好对照;智谱、OpenAI 与 opencode 接口给的是已用百分比,展示口径统一换算为剩余)。各云端 API 都不提供绝对剩余 token 数,这里只有百分比与金额,不做任何估算。
- opencode 的 Go 套餐复用内核模型设置里这家那两行取源的密钥(
opencode行的OPENCODE_API_KEY,或opencode-go行的OPENCODE_GO_API_KEY——同一个 workspace 一把 Key,实测两行都能查这个容量接口),查询 opencode.ai 第一方的 Go 套餐容量接口。不读 opencode 自己的~/.local/share/opencode/auth.json:那是另一个应用的凭据库,这条查询与它无关(与 Codex 额度那条「本机凭据要用户显式许可」是同一条纪律)。这个接口只给整数百分比(不足 1% 记 0),并且可能比 opencode 自己的用量界面晚一拍(2026-10-13 实测:同一分钟它家界面 weekly 已显示 1%,接口给的是 0;23 分钟后接口也变成 1),所以个别时刻卡上的数字会比它家界面差 1 个点——那是接口精度与更新时机,不是显示错误;它家界面读的是带登录态的页面,本功能刻意不去读它。三个窗口都缺席时显示「暂无额度数据」,绝不补成 100%。 - 2api.store(TokenShop 中转)展示用户自定义 provider 的密钥剩余额度:在内核模型设置里把这条中转加成自定义 provider(本机实测 route 名
z-2api、apiKeyEnv: Z_2API_API_KEY、Base URL: https://2api.store/v1)后,壳按「route 名含2api」或「Base URL 主机是 2api.store(含子域)」认出它(该判据排在厂商 route 名之前,免得deepseek-2api这类「中转 + 厂商」的命名被当成官方 provider),用那一行自己的apiKeyEnv查询<origin>/v1/usage(Base URL 以…/v1结尾时补/usage;只填 origin 或直接填完整用量地址也认;只接受 HTTPS,推不出端点时不发请求并提示改 Base URL)。响应按 2api 文档 / cc-switch 自定义脚本同款口径取值:remaining→quota.remaining→balance(数字或数字字符串),单位取unit→quota.unit→USD,is_active/isValid为 false 时标「密钥已停用或已过期」(与 DeepSeek 的「余额不足」文案分开)。只展示一个剩余额度读数:rate_limits[]的 5h / 1d / 7d 周期窗口与usage/daily_usage/model_stats等消费明细本版本不展示;自定义 JS 提取器不是本功能的能力(内置识别,不执行脚本)。2026-10-18 用钱包模式(mode: "unrestricted")真机验证过端点与字段。 - OpenAI 模型登录与额度查询不是同一种授权。内嵌 openai-oauth 插件使用 Sign in with ChatGPT(通过 ChatGPT 登录,SIWC)的推理令牌,它不支持
chatgpt.com/backend-api/wham/usage这个内部额度接口;重新登录或补充账号 ID 不能解决权限不兼容。已登录时保留分区并说明原因,未登录时隐藏;可在 ChatGPT 设置 → 用量查看官方数据。概览卡与详情窗口提供默认关闭的「使用本机 Codex 登录查询额度」开关:开启后只读CODEX_HOME/auth.json(默认~/.codex/auth.json),校验与本壳登录的邮箱和已有账号 ID 一致,显示「Codex 额度」;凭据过期或身份无法确认则拒绝,不刷新、修改或复制凭据,也不改变 DSH 模型登录。关闭时不读取 Codex 凭据。缺失的 5h / 7d 窗口只显示「暂无数据」,不显示无限额度、进度条或 100%。 - 未在内核配置对应厂商凭据的分区自动隐藏。卡片直接展示进度条、重置倒计时与查询时间,点「查看详情」弹出独立窗口(与模型用量窗口同一条建窗与吸附跟随路径,窗口内可刷新、可跳「模型用量」窗口、可前往模型设置)。
- 凭据复用当前内核模型设置:外壳不收集、不保存任何 Key,查询用当前实例 / profile 已配置的模型凭据(工作台的模型设置是唯一凭据编辑入口)。设置页不设套餐用量卡:逐 provider 的「只查这一个」是概览卡分区标题旁那枚年龄胶囊(点一下即
force重查),一个凭据都没配时卡头给「前往模型设置」。 - 数据约 5 分钟更新一次,「刷新」立即重查。查询失败时保留上次成功数据并显示错误横幅;凭据失效(HTTP 401/403)后停止自动重试、点刷新才重试。配置了凭据但一直查不到数据的分区会询问是否隐藏(选择被记住、不再展示与报错),之后某次查询成功(含每次启动时的首次强制查询)会自动恢复显示。缓存与展示都按实例隔离,切换实例不会看到别的实例的余额。
- MiniMax 查询套餐需用 Token Plan 页的订阅 Key,若与当前模型凭据不同,以真机验证为准(见设计文档步骤 0)。
- 智谱额度接口除 API Key 外还要求组织 / 项目上下文:在环境变量、
<DSH_HOME>/.credentials.yaml的 refs 或.env里配置ZAI_CODING_CN_ORGANIZATION/ZAI_CODING_CN_PROJECT(浏览器登录 bigmodel.cn 后,DevTools Network 面板中quota/limit请求的bigmodel-organization/bigmodel-project请求头即这两个值),可选ZAI_CODING_CN_PLAN_TYPE(个人 = 1 / 团队 = 2,默认 1);未配置时对应分区给出带获取方法的错误提示。 - 机制与缓存设计见 docs/architecture/architecture.md 与 docs/features/subscription/subscription-usage-design.md。
- 日志查看器吸附跟随:日志查看器接入与用量窗口同源的吸附 + 移动跟随逻辑,新建或调整大小的日志窗口默认吸附主窗右侧、高度与本体一致,主窗拖动时 60fps 合帧跟随,松手后停止;窗口始终独立可缩放,分隔条拖拽改为 pointer + rAF(关 transition)消除卡顿。
- 内置补丁(内核补丁 / 小插件):随 dsh-xlink 发布包捆绑的自研内核补丁与小插件(
src-tauri/resources/patches/<id>/,发布时进入 app 资源目录,与社区插件不同、无需第三方信任),默认不生效。设置页里的应用入口已隐藏:最新内核已经包含相关修复,不再需要手动打补丁;后端的patch_status/patch_apply/patch_revert与plugins/patches.rs仍在,用于旧内核上的撤销。下面这段说的是那套机制本身。应用前自动备份被覆盖的原文件到~/.dsh-xlink/dsh/desktop/patches/backups/,撤销时从备份还原,备份丢失时以内容 SHA-256 校验兜底,绝不盲目覆盖或删除。支持copy(新增 / 覆盖文件)与replace(精确字符串替换)两种文件操作,目标路径严格限制在内核目录内,可按minKernelVersion/maxKernelVersion声明适用内核版本范围。当补丁功能被官方内核采纳后,可通过supersededSinceKernelVersion字段声明「从该内核版本起已被官方取代」,UI 把对应卡片折叠为「已并入官方内核」(删除线 + 默认收起 + 应用按钮禁用),用户可手动展开查看。应用记录持久化在~/.dsh-xlink/dsh/desktop/patches/state.json,按「补丁 × 内核版本」隔离;工作台运行期间禁止操作。dsh-file-perf(dsh@引用性能修复)已被官方 0.1.2-alpha.2 起直接采纳,卡片折叠为「已并入官方内核」,旧内核上的已应用记录仍可撤销。设计文档见 docs/features/extensions/patch-management.md。
按内核族命名空间隔离,统一在 ~/.dsh-xlink/ 下:
- 外壳数据(已装内核
kernels/、活动指针active.txt、补丁patches/、隔离记录quarantine.json等):~/.dsh-xlink/dsh/desktop/(release 壳)或~/.dsh-xlink/dsh/desktop-dev/(dev 壳)。将来接入新内核族(如 mcode)会得到各自独立的~/.dsh-xlink/mcode/desktop[-dev]/。可用DSH_XLINK_HOME重定向整个根目录,DSH_DESKTOP_DATA_DIR完整覆盖外壳数据目录。 - 外壳自身日志与每壳设置(release / dev 分槽):
~/.dsh-xlink/shell/<release|dev>/(logs/、settings.json、ui-state.json)。 - 多内核相关(实例
kernels/<族>/instances/<id>/、中央插件库plugins/dsh/(dev 壳为plugins/dsh-dev/)、技能库skills/):权威布局见 docs/architecture/architecture.md §「多内核改造后的实际数据布局」。已安装内核仍在上一条的desktop[-dev]/kernels/<版本>/下,kernels/<族>/versions/是为多内核备好但尚未启用的位置,实机不存在。 - 内核自身数据(会话、凭据、配置、profile):实例内核 home
~/.dsh-xlink/kernels/dsh/instances/<id>/home/,启动内核时外壳以DSH_HOME环境变量注入,内核进程的全部用户数据都落在这里,不再使用~/.dsh。 - 本地记忆:
kernels/<族>/instances/<id>/memory/<profile>/memory.json(0600,原子替换),导出的一次性 Markdown 快照在同目录的exports/下。它属于实例而不是外壳:按实例隔离,两壳各持一份(release / dev 的默认实例不同)。 - dev 壳与 release 壳各有各的默认实例:release 用
default,dev 用default-dev(首次启动时自动建立),端口也分开(3090 / 3091),两套环境可以同时跑。分家的原因:共用一个实例时,dev 换一次内核版本或改一次插件接线就会重写共享的 profile 接线,dev 更新中央库里的插件源码还会被 link 物化直接送到 release 正在跑的内核上,release 的工作台会当场崩掉。代价是 dev 实例初始是干净的(看不到 release 的会话历史与第三方插件,需要的话在插件页点「同步」把中央库的插件物化过去)。两个壳若仍指向同一实例且那个内核还活着,插件与内核版本变更会被拒绝并告诉你先停哪一边。
从 v0.2.x 升级:平铺的
~/.dsh-xlink/desktop[-dev]/会在新版首次启动时自动整体搬进~/.dsh-xlink/dsh/;搬迁失败时继续使用旧目录,数据不会丢失。更早版本(元数据在系统应用数据目录或~/.dsh/desktop/)的数据不再被读取,如需保留请手动移入上述外壳数据目录。内核数据的一次性搬迁:旧版外壳不注入
DSH_HOME,内核把会话、凭据、profile 写在~/.dsh。新版首次启动会把其中内核拥有的数据(profiles/、sessions/、storages/、synapse/、attachments/、logs/、.credentials.yaml、settings.yaml*等)并入实例内核 home。已有迁移标记也会按版本补跑;若活动settings.yaml缺失,会从settings.yaml.imported复制恢复,归档保留。目标已有的同名文件继续优先,中断后下次启动自动续跑。~/.dsh里外壳拥有的旧目录(desktop/、plugins/、skills*等)不在搬迁清单内,原样保留。
前提:Rust 工具链(含 cargo)、Node.js ^22.19 || >=24(与内核 engines 一致);scripts/install.mjs 会自动检测 pnpm,缺失时回退到 npm。
# 安装 Tauri CLI(自动检测 pnpm,缺失时回退到 npm)
npm run deps
# 开发运行(需先安装内核,见「使用」)
npm run dev
# 5174 也被占用时再换一个(占用者常常是本机另一个工程的 dev server)
npm run dev 5190
# 本机当前架构构建
npm run build
# 指定目标平台
npm run build:mac-intel # x86_64-apple-darwin(Intel Mac)
npm run build:win # x86_64-pc-windows-msvc
# 日常开发:按改动范围跑相关测试;静态检查不编译 Rust
npm run check:static
# 前端、插件或构建脚本的完整检查(包含静态检查、测试、UI 构建与产物预算)
npm run check:js
# Rust 格式、单测与 Clippy;与持续集成共用
npm run check:rust:ci
# 发布前完整跑一次,另含 Rust release 编译检查
npm run check日常迭代只验证改动涉及的部分:界面改动跑相关 ui/test/*.test.js 与 build:ui;
Rust 改动跑相关单测,按需做编译或 Clippy 检查;内置插件改动先跑 prep:builtin,
再跑对应插件测试与 check:builtin。同一代码状态通过后不因准备提交而重跑。
持续集成保留全套检查;发布平台构建负责验证 release 产物,Windows 单测独立保留。
代码按职责组织,新增逻辑先复用现有组件、store 与服务;出现独立职责或相同语义的重复时,
在本次改动内提取共享实现。不设文件或全仓行数上限,不为凑行数压缩排版或强拆组件。
npm run check:duplicates 保留重复代码检测,界面产物体积预算不变。
本机需要控制 target 体积时,将个人 Cargo 配置放在仓库根目录的 .cargo/config.toml
(已忽略,不提交)。Cargo 从启动目录向上找配置;只放在 src-tauri/.cargo/ 时,
根目录的 cargo … --manifest-path src-tauri/Cargo.toml 不会读取它,两种入口可能生成
不同配置的产物。可为 dev/test 使用 debug = "line-tables-only",并将第三方依赖的
debug 设为 false,保留本项目回溯行号并减少调试信息;增量编译继续保留。
改配置不会自动回收旧产物,不要为了日常提交反复清空 target。
build 与 dev 会先跑 npm run prep:builtin,从 plugins/openai-oauth/ 生成随包交付的资源目录。全新 checkout 上直接跑 cargo 会因为缺这个目录而停在 resource path 'resources/builtin-plugins' doesn't exist,所以那条生成步骤不能跳。
根目录的 pnpm-workspace.yaml 让 pnpm 把本项目当独立根处理,直接跑 pnpm install 或 npm install 也行。产物位于 src-tauri/target/release/bundle/(macOS 为 .dmg,Windows 为 NSIS 安装包 .exe)。
仓库根目录就是桌面项目本体:独立 pnpm 根、独立的 Tauri / Vue / 文档 / 发布配置,不加入任何上级 workspace。GitHub 仓库在 July-X/dsh-xlink。
- 启动桌面应用,打开管理面板。在「设置 → 外观」选择浅色、深色或跟随系统,也可用侧栏底部的主题按钮按「浅色 → 深色 → 跟随系统 → 浅色」循环切换。跟随系统会解除当前窗口的原生外观覆盖并响应系统配色变化,打开深色工作台不会覆盖管理面板的系统配色,已打开的壳窗口同步更新。工作台自己的明暗由内核「设置 → 通用设置 → 外观」决定(浅色 / 深色 / 跟随系统,与内核官方桌面壳一致):选跟随系统时窗口外观不设覆盖、页内系统配色查询照常响应,选固定档时壳把原生标题栏同步成同一档。主面板及日志、模型用量、套餐用量窗口统一按 R12 圆角裁切,窗口外四角保持透明。
- Node.js 环境:概览页「当前内核」的 Node.js 行显示实时检测结果,刚装完 Node 可点同排「重新检测」刷新(只探测本机环境、不改设置)。不满足要求时点同排「自动安装」自动下载官方 Node.js 到数据目录(首次启动检测不到时会弹窗询问,点「帮我安装」同效),或手动安装 Node 22.19+、在
<data_dir>/settings.json的node_path里手动指定路径。nvm 管理的 Node 会被自动发现。 - 内核更新:应用启动时会扫描并列出本地已安装版本,进入「内核版本」页即可在左侧备用版本中切换。只有工作台已停止时才能切换;工作台启动或运行期间请先在「概览」页点击「关闭工作台」。「官方版本」栏标题右侧那枚刷新图标只从 npm 拉发布列表,再选择未安装的版本点「安装」。应用启动时会自动静默拉一次这份列表(失败不打扰,也不影响已有列表),发现比已装版本更新的内核时会提示一句;列表随时可再点那枚图标刷新。安装通过 pnpm 执行,进度面板会实时滚动 pnpm 日志;pnpm 未安装时按提示
npm install -g pnpm或在设置中指定 pnpm 路径。首次安装会自动成为活动版本,但不会启动内核;安装完成后请在「概览」页点击「启动工作台」。之后安装的版本不会覆盖当前活动版本,可随时在「已安装」列表中「切换」或「删除」。 - (可选)插件 → 在「已安装」右栏的「插件中心」里搜索(关键词回车提交)、按分类浏览、按 Star / 更新时间排序后一键安装,「显示更多」位于结果滚动区域末尾;也可切换右栏的「手动安装」页签,填写 npm 包名(如
@ace-zone/dsh-market)/ GitHub 仓库 URL 安装。手动输入回车同样遵守「预检 / 直装」开关。安装前自动校验插件是否符合 dsh 规范(package.json /dsh.bundle.patch/ 入口文件),安装完成后重启工作台(关闭后重新启动)生效。若诊断确认已安装插件导致启动失败,事故或诊断页面提供「移除并清理」,会删除本地插件文件和接线,但保留诊断日志。点「同步内核」会对所有已安装内核重新物化中央插件库,并清除外壳标记的已删除插件残留。进入「内核版本」页后,每个已安装版本旁的信息图标可悬停查看该版本实际物化的插件、版本和链接 / 拷贝模式。 - (可选)旧内核上的补丁撤销:设置页的应用入口已经隐藏(最新内核自带相应修复),只有当你还在跑一个需要打补丁的旧内核时才有得用。补丁随当前 dsh-xlink 版本捆绑,来自本应用发布方,与社区插件不同;应用前自动备份被覆盖的原文件、随时可撤销,状态与备份记录在
~/.dsh-xlink/dsh/desktop/patches/(dev 壳为~/.dsh-xlink/dsh/desktop-dev/patches/)。工作台运行期间不能操作,请先关闭工作台;切换内核版本后需对新的活动版本重新应用。补丁与适用内核版本详见 docs/features/extensions/patch-management.md。 - 在「概览」页点击「启动工作台」:自动拉起内核、等待就绪后校验当前内核的工作台地址,再打开工作台窗口进入 Harness 界面;启动失败会自动弹出事故面板和内核日志。「关闭工作台」会同时关闭工作台窗口并停止内核。工作台窗口的系统关闭按钮(macOS 交通灯红灯 / Windows ×)始终可用,只收起窗口,内核与任务继续在后台运行;内核运行中收起窗口后,随时可用「打开工作台窗口」重新打开。工作台窗口会自动进行健康自检,发现白屏、运行时错误或未处理的 Promise 异常时,事故面板会展示异常类型 / 消息 / 堆栈与页面地址,并标注归类(「疑似插件问题」「疑似内核问题」「前端 bundle 异常」「运行环境问题」「暂未能归因」)。插件问题可重新启用或移除;内核问题可先停止工作台,再打开日志并切换 / 重装版本;「运行环境问题」(端口被占用、数据目录不可写、磁盘已满等)指向设置页与日志,面板按钮会直接去设置页。工作台窗口侧栏头部右侧(品牌 logo 旁)悬浮着一个灯泡拉绳小挂件:点击(拉动)它,灯泡点亮的同时桌面端管理面板会归位到点击位置附近并提到当前桌面上方,方便随手操作;若灯泡闪红,说明与桌面壳的通信失败,可查看工作台 DevTools 控制台。
- 「打开官方对话」:在「概览」页点击此按钮即可拉起独立的官方对话窗口(顶部条带 chrome-row 官方品牌蓝
#4D6BFE、拉绳挂件挂页签栏右侧 12 px;区别于工作台窗口的 Gitea 绿色 212 px 偏移),固定排布 DeepSeek / MiniMax 两个页签;本机 Codex 登录可用时末尾追加 ChatGPT 页签。页签表在开窗那一刻求值一次,窗口开着期间不再变化。窗口已开时按钮变为「关闭官方对话」并销毁当前窗口。 - (可选)侧栏「系统」组 → 数据迁移:从旧版 dsh home 布局搬到新多实例布局,嵌入式 4 步向导。凭据与会话首版不纳入迁移,冲突策略默认
SkipIfNewer,旧源永不被删除。已迁移的用户不再看到启动弹窗,随时可从侧栏重新进入回查最近一次迁移。这个功能已定在 v0.6.0 之后整体移除。 - 首次使用时在 Harness 的设置页配置 DeepSeek(
DEEPSEEK_API_KEY等)即可开始对话。
.
├── package.json # 脚本与前端依赖;build / check / dev 等入口都在这
├── pnpm-workspace.yaml # 独立 pnpm 根(放行 esbuild)
├── vite.config.mjs # 管理面板 dev server 与构建
├── AGENTS.md # 仓库级开发约定,改代码前必读
│ ├── ui/AGENTS.md # 前端分支细则
│ └── src-tauri/AGENTS.md # 后端分支细则
├── ui/ # 管理面板前端(Vue 3 + Element Plus,Vite 构建)
│ ├── index.html # SPA 入口(加载 src/main.js)
│ ├── public/ # 静态资源:whale-icon.png、header-ribbons.svg,
│ │ # 以及 npm / DeepSeek / MiniMax / 智谱 / OpenAI 的本地矢量 logo
│ ├── src/
│ │ ├── App.vue # 外壳:窗口路由、全局横幅、事故面板、迁移提示
│ │ ├── main.js # 入口
│ │ ├── store.js # 全局状态与动作
│ │ ├── theme.css # 设计变量与全局样式
│ │ ├── shell/ # 概览 / 设置 / 侧栏 / 标题栏 / 进度 / 副窗壳,
│ │ │ # 加 bridge.js、loading.js、progress.js、async.js 等基础设施
│ │ ├── kernel/ # 内核版本页、发布列表、实例 store
│ │ ├── plugins/ # 插件面板、预检对话框、内嵌插件、内核补丁
│ │ ├── skills/ # 技能面板
│ │ ├── diagnostics/ # 诊断塔、二分面板、环境回退点、启动 / 运行诊断
│ │ ├── incidents/ # 事故面板与通知
│ │ ├── usage/ # 模型用量独立窗口
│ │ ├── subscription/ # 套餐用量窗口、Codex 额度许可、分区错误提示
│ │ ├── logs/ # 日志弹层与独立窗口
│ │ ├── official-chat/ # 官方对话页签栏
│ │ └── migration/ # 数据迁移向导(v0.6.0 之后整体移除)
│ ├── test/ # 50 个 node:test 文件、467 个用例(设计对齐、模板绑定、交互语义)
│ └── dist/ # vite build 产物(tauri.conf.json 的 frontendDist)
├── src-tauri/ # Tauri v2 Rust 壳
│ ├── tauri.conf.json # frontendDist → ../ui/dist;resources 捆绑 patches/
│ ├── Cargo.toml / Cargo.lock / build.rs
│ ├── capabilities/ # 各窗口的访问权限(面板 / 工作台 / 日志 / 用量 /
│ │ # 套餐 / 官方对话,各自一份)
│ ├── permissions/ # 本地 IPC 命令白名单
│ ├── icons/ # 应用图标集(由 assets/ 母版生成)
│ ├── gen/ examples/ # Tauri 生成物与示例程序
│ ├── resources/
│ │ ├── patches/dsh-file-perf/ # 内置内核补丁的清单与载荷
│ │ └── builtin-plugins/openai-oauth/ # 构建期由 npm run prep:builtin 从
│ │ # plugins/openai-oauth/ 生成,不入库
│ └── src/ # 110 个 .rs,根目录三个 + 12 个子系统目录
│ ├── lib.rs / main.rs # 入口与装配(含退出时回收内核、清理预检残留)
│ ├── commands.rs # Tauri 命令面(插件 / 技能 / 补丁 / 迁移 / 预检 / 窗口)
│ ├── diskusage.rs # 磁盘用量统计(四类分组,只读)
│ ├── shell/ # 21 个:路径解析、实例注册表、设置、进程、常驻、托盘、窗口
│ ├── kernel/ # 10 个:安装、生命周期、适配器、依赖钉版、接线
│ ├── plugins/ # 14 个:中央库、物化、接线、预检、沙盒、补丁、隔离
│ │ └── builtin/ # 内置插件登记表、物化、接线、上游同步(N 个)
│ ├── skills/ # 5 个:中央库、frontmatter 校验、同名遮蔽处理
│ ├── diagnostics/ # 13 个:启动 / 运行诊断、看门狗、快照、恢复、二分
│ ├── harness/ # 6 个:工作台与官方对话窗口、草稿、图片、品牌线脚本
│ ├── notify/ # 4 个:事件流订阅、未读角标、通知通道判定、回到工作台
│ ├── openai/ # 13 个:SIWC 登录、JWK、令牌库、模型目录、推理请求
│ ├── usage/ # 9 个:本地 token 账目、云端套餐额度、Codex 额度、凭据
│ ├── pkg/ # 7 个:插件与技能共用的取源层(registry / 解包 / 代理 / 更新)
│ ├── node/ # 3 个:Node 与 pnpm 检测、托管 Node 安装
│ └── migration/ # 4 个:迁移向导与历史会话找回(v0.6.0 之后整体移除)
├── plugins/openai-oauth/ # 内置 OpenAI 插件源码(host / client / locales / test)
├── plugins/ponytail/ # 内置 Ponytail 适配层(上游内容运行时拉取,不在仓库)
├── scripts/ # 构建与门禁脚本,作用见下表
├── docs/ # 32 篇文档:architecture / features / operations /
│ │ # 31 篇文档 + README 索引,另有 images/
├── assets/ # 全仓库图标母版
│ ├── whale-icon.svg # 完整细节母版(黑鲸 + 红眼,用于 ≥128px)
│ ├── whale-icon-small.svg # 小尺寸母版(红眼夸大版,用于 ≤64px)
│ ├── whale-head.svg # 托盘 / 角标专用母版
│ └── whale-icon-512.png # 512px 位图(脚本从 whale-icon.svg 渲染)
└── .github/workflows/ # desktop-ci.yml(质量门禁)/ desktop-release.yml(发布)
scripts/ 按用途分四类:
| 脚本 | 作用 |
|---|---|
install.mjs |
依赖安装,pnpm 优先、缺失回退 npm |
dev.mjs |
把 vite 端口与 tauri devUrl 收敛到一处,npm run dev 5190 改的就是它 |
prepare-builtin-plugins.mjs |
从 plugins/openai-oauth/ 生成随包交付的资源目录(--check 供门禁用) |
check-invariants.mjs |
命令注册 / capability / 三处版本一致 / CSS 变量等不变量 |
check-code-duplicates.mjs |
检查生产代码重复块,不限制文件或全仓行数 |
check-ui-bindings.mjs |
校验 SFC 模板里的标识符能解析到真实绑定 |
check-ui-bundle-budget.mjs |
JS / CSS 产物预算,本地与 CI 调同一份判据 |
check-signing-keys.mjs |
校验更新签名的私钥与 updater 公钥成对 |
build-icons.sh |
从双 SVG 母版生成 Tauri 与面板图标 |
generate-updater-manifest.mjs / normalize-release-assets.mjs |
发布制品与 latest.json 处理 |
verify-dsh-file-perf.mjs / smoke-pullstring.mjs |
内置补丁与拉绳脚本的只读验证与冒烟 |
工作流:.github/workflows/desktop-release.yml
- 支持平台:Intel macOS(
macos-15-intel,.dmg)+ Windows x86_64(windows-latest,NSIS.exe) - 触发方式:
- 手动在 Actions 页从
main触发workflow_dispatch(使用当前package.json版本,推荐,后续版本可复用 Rust 编译缓存) - 推送 tag:先同步
package.json、src-tauri/tauri.conf.json与src-tauri/Cargo.toml三处version,再git tag desktop-v<version>并推送(Cargo.toml那处是CARGO_PKG_VERSION的来源,会被当作对外 User-Agent,preflight 会校验三处一致)
- 手动在 Actions 页从
- 发布来源限定为
main分支,产物发布为正式 release,不是 draft 或 prerelease。 - 发布前质量门禁:UI 回归测试与生产构建、JavaScript 700 kB / CSS 256 kB bundle 预算、Rust
cargo test、cargo fmt --check和cargo clippy -D warnings全部通过后才允许发布。 - 发布提速:预检通过后,质量门禁与 Intel macOS、Windows 两个构建 job 并行运行;平台 job 只上传 Actions artifact,全部成功后由独立的 publish job 一次性创建正式 Release 与
latest.json。max-parallel: 2、pnpm store、Cargo registry 和按平台隔离的 Cargo target 都启用缓存,Rust release 使用 thin LTO 与 16 个 codegen units。缓存只在main分支保存,手动发布可跨版本复用;直接推送新 tag 通常会冷启动。详细时序与排障见docs/operations/release.md。
GitHub Actions 首次建立缓存时仍会经历冷启动;runner 排队、缓存服务和网络波动也不属于 workflow 可控的构建时间。
签名说明:当前产物未做代码签名,Windows SmartScreen 与 macOS Gatekeeper 可能给出警告。加入签名(Apple Developer ID / Windows 代码签名证书 + 对应 secrets)后再去掉相关提示。
| 症状 | 排查 |
|---|---|
WebviewWindowBuilder 创建工作台窗口卡死 |
Tauri 2.x 在同步命令里创建 webview 窗口会死锁(Windows 100%;macOS/Linux 部分情况下也慢)。本项目 open_harness 是 async 命令,窗口创建包在 commands.rs::blocking 里交给 spawn_blocking,主线程不参与。新增类似命令请保持同样模式。 |
macOS 启动后访问 http://127.0.0.1:3090(dev 壳为 3091)失败 |
Tauri 2.x 默认 WKWebView 已允许本地环回访问,不需要 NSAppTransportSecurity 例外;本项目移除了该字段,依赖平台默认值。 |
编辑器 / IDE 报 capabilities/default.json 找不到 $schema |
schema 文件在首次 tauri build 后由 tauri-build 生成;本项目移除了硬编码 $schema 引用,避免初次克隆时编辑器红字。 |
| 升级后「已安装」列表为空 | 外壳元数据在 ~/.dsh-xlink/dsh/desktop/(v0.2.x 平铺目录会自动搬入);按上文「数据目录」提示确认目录位置,或重新安装内核。 |
性能问题:
- 管理面板状态采样在
v0.5.0之前默认开启,日志在「系统健康 → 日志系统」里,文件名<构建>-perf-status-<日期>.log(release 壳为release-perf-status-…,dev 壳为dev-perf-status-…),可按source=poll/refresh聚合total_us与各分段耗时;v0.5.0及之后默认关闭,可用DSH_XLINK_PERF=1开启、DSH_XLINK_PERF=0关闭。 - 工作台与官方对话的顶部品牌线采用静态渲染,不会在空闲时保持 WebKit 帧循环。安装包含
src-tauri/src/harness/titlebar-pulse.js修改的桌面壳后,需要完全退出并重新启动应用,再重新打开工作台;已存在的 WebView 不会自动替换初始化脚本。 dsh-personal-center是第三方可选插件。桌面宠物的统计接口会同步读取并解压全部历史会话;会话较多时可能造成明显的 Node 磁盘 / CPU 阻塞。遇到周期性卡顿时,在个人配置中关闭桌面宠物和「会话状态」,需要统计时再手动打开 Token 用量页面。patchReload: live会启用 client-HMR 的 500 ms bundlestat轮询。日常使用可改为startup并在 profile patch 中禁用client-hmr;需要调试 client plugin 时再恢复live,删除该禁用项。
- Node 运行时:当前按需托管安装到数据目录(自动检测 → 一键装);后续可考虑随发布包捆绑 Node sidecar(体积 +40 MB / 平台)。
- pnpm 依赖:内核安装依赖用户环境中的 pnpm(未捆绑)。找不到时壳会问要不要跑一次
npm install -g pnpm,也可以在设置里手动指定路径;后续可评估corepack或 sidecar 方式随应用分发。 - 端口冲突:若 3090(dev 壳为 3091,以设置页显示为准)已被其他进程占用,先停止外部服务,或在设置页改用其它端口。「工作台运行期间不能改端口」,需先关闭工作台再保存。
- 安全:应用通过 Webview 加载本地
http://127.0.0.1的 Harness 页面并暴露版本管理命令。@deepseek-ai命名空间限制只覆盖内核与托管 Node 两条路径(包名在kernel/lifecycle.rs硬编码、托管 Node 版本与 SHA-256 硬编码),不覆盖插件与技能,plugins/center.rs/skills/manage.rs对 npm 包名只做字符类校验,lodash、@attacker/backdoor都能安装。插件和技能是第三方内容 / 任意代码,安装前请自行确认来源;社区目录条目保留「未验证」标记。npm 包解包拒绝绝对路径、父级路径、符号链接、硬链接和特殊文件,并限制条目数与展开体积。外壳自己下载的 tarball 一律逐字节校验:优先用 registry 元数据的dist.integrity(SRI,取最强且受支持的 sha512 / sha256),只有它没有可用摘要时才回退到老 packument 的dist.shasum(sha1),两条都没有则拒绝安装。镜像(默认 npmmirror)只影响取源,不影响信任判定;DSH_NPM_REGISTRY目前接受http://,部署到不可信网络时请自行确认。 - 插件链接模式:依赖文件系统符号链接支持。普通 Windows 账户建目录链接需要开发者模式(没开时
symlink_dir报os error 1314,壳会直接把这条确定性失败提示出来——重试不会好,开了开发者模式再启动即可);开着开发者模式时,若安全软件等外部因素瞬时拒绝建链,壳会自动重试,仍失败才降级为复制模式并在行内显示「复制」徽标。内嵌插件的@deepseek-aipeer 链接没有降级路径(Node 按真实路径解析 import,复制过去的那份在自己的目录里解析不到依赖),建不出来时工作台不会启动——按提示重试或重启应用即可,日志里能看到具体路径。 - 自动更新:桌面端使用
tauri-plugin-updater下载并校验签名。检查更新与下载更新都优先走本机系统代理(先读HTTP_PROXY/HTTPS_PROXY/ALL_PROXY环境变量,再读 Windows「Internet Settings」注册表 / macOS 系统网络设置),代理连不上时自动改走直连,因此开着代理、但代理软件此刻没运行时不会把更新检查堵死。失败提示会列出本次试过的每一条路。Windows 更新重启后,管理面板完成首次状态刷新即会清理更新前的旧安装目录、快捷方式和 updater 临时目录;清理失败会保留标记,并在下次启动重试。



