Feature: 远程设置

September 18, 2026 · View on GitHub

FieldValue
idremote-settings
statusactive
last verified2026-09-18 — 装机「开启远程→未响应」修复:主进程 loadServerApi 窄化为 pairing-offer.js + relay-device-credential-store.js(原 barrel ~3 万模块同步加载冻结主线程);DSH_VENDOR_PACKAGES 改镜像 + parity 测试。dshd-remote 36 pass、dshd-daemon-runner/remote-epipe/stdio-guard/lan/ipc 80 pass、ui-settings-remote 45/45、check:governance 6/6、npm run pack(80.7MiB runtime、sqlite ABI probe、daemon probe、skip compose)、打包布局窄入口 import+铸码 68ms、真实 Electron qa:remote 双冷启动 11/11(含 cold.openShowsQr)。此前:2026-09-11 — rc.1 后 dsh-im 各 channel 的 caller-scoped webServer 注入已修复;dsh-im check 19 pass / 1 skip、官方 remote specs、真实 source smoke 与 package dry-run 通过。再前:2026-09-08 — 默认服务器切到 ayase.cn:443 + TLS,公网 SPA 切到 https://ayase.cn/dshd/;旧内置 IP 精确迁移、自定义服务器保留。VPS relay 容器 healthy / 0 restart,nginx live 与候选配置通过;Node 远程聚焦 92 pass / 0 fail / 1 环境 skip,设置 UI 10/10,公网目录一致性通过,真实 daemon + 公网 relay + 公网 SPA E2E 10/10。未执行真机相机、Android WebView 或正式安装包升级验收。

User paths

当前可用: REMOTE_FEATURE_ENABLED=true;远程是否开启仍由用户控制。

  1. 设置 → 「远程」(remote)→ 网关:选 局域网 / 服务器(文案区分;扫码传输都经中继);中继主机默认内置 ayase.cn:443,使用 TLS。无宿主令牌墙
  2. 设置 → 「远程」→ 消息渠道:桌面内置 @xmanrui/dsh-im 完整 IM UI(九渠 + AI Office);无商店品牌头。
  3. 侧栏底部手机图标打开配对弹窗:开关 → 中继状态;中继已连接才显示扫码二维码 / 复制链接 / 刷新配对码 → 已配对设备 / 重命名 / 解除配对。

Invariants

  • 全部 IM 渠道访问同进程本机 Harness 时通过 harness-auth-transport.mjs 复用 connection.authenticatedUrl / authorizeIndex 换取 Cookie,覆盖 HTTP 与事件 WebSocket;不读取签名密钥、不取消鉴权、不向自定义外部地址或重定向发送本机凭据。旧版无认证 API 保持原行为。

  • 检测到 typertGateway.wireStream 时使用 harness-modern-transport.mjs:旧点式 RPC 映射到当前 Remote API;健康检查取 $events ready,工作区/历史取真实 baseline/snapshot;prompt 的 requestId 保持原 RPC 归属;审批/问答经 $events/result 回传,停止不能越过原 IM 会话的所有权。不得只让健康检查变绿、继续调用已移除的接口。飞书 SDK 补丁先归一 CRLF,仍逐个严格检查源码片段。

  • 连接方式文案为「局域网 / 服务器」;未设置时默认服务器(内部值 relay),局域网仅在明确选择 lan 时使用。既有显式选择保留,不自动开启远程。

  • 新安装与空配置使用 ayase.cn:443 + TLS。升级时,只有精确匹配旧内置中继 125.124.85.212:8411 的保存值迁移到新默认;其他自定义中继地址及其 TLS 选择保持不变。旧内置公网页 override http://125.124.85.212:3389/dshd 清回默认解析,使二维码落到新公网页。

  • 停放开关: src/main/config.js REMOTE_FEATURE_ENABLED。false 时 preload 不暴露 getRemote/saveRemote/rotateRemoteToken/unbindRemoteDevice/renameRemoteDeviceui-settings-remote 不注册侧栏与设置入口;normalizeRemoteConfigremoteEnabled 钉死为 false;IPC shell:save-remote 无法打开。解禁只翻这一处(window argv --dshd-remote-feature 跟它走)。

  • 配对协议 = dshd offer(实现为 vendored ChisaCode offer v2):全量 createChisaCodeDaemon 跑在 dshd-daemon-runner.mjs 子进程(禁止回迁主进程);主进程 DshdRemote 只是进程管理面 + file-backed 配对/快照;QR appBaseUrl:局域网 = preferredLanIp():3180,服务器 = DEFAULT_PUBLIC_APP_BASE_URLhttps://ayase.cn/dshd/),禁止把中继 /ws 当 SPA。用户可见文案称 dshd daemon / dshd 配对,不出现 ChisaCode 品牌名。

  • 主进程窄 importloadServerApi 只引 pairing-offer.js + relay-device-credential-store.js 两个兄弟模块并镜像 DSH_VENDOR_PACKAGES(parity 测试钉住 vendored 源);exports.js 全量 barrel(数万模块,ESM 同步加载会冻结主线程)只允许经 launch file 进 daemon 子进程。

  • daemon 子进程契约:runner 在 asarUnpack;stdout 只有 JSON 行(控制行 + pino json);stdin stop 与 stdin 关闭都必须优雅停(孤儿零容忍);意外退出必须落 snapshot.error 并保留弹窗重试;不做自动退避重启循环(对齐上游)。

  • DSHD_ 命名桥*:桌面对外只有 DSHD_CHISACODE_HOME(打包需 DSHD_ALLOW_ENV_HOME=1,同 dsh-home 守卫)与 DSHD_DSH_VENDOR_DIRCHISACODE_* 只允许出现在 daemon 子进程 env 注入处,主进程自身 env 与 PTY / dsh web 子进程永不携带;字面量 DSHD_HOME 属 dsh-home 卡,不可占用。DEEPSEEK 凭据只经 official-deepseek-env 白名单入子进程 env,launch JSON 永不含密钥。

  • snapshot.relayConnected / relayError 反映真实 relay control;未连接时弹窗明示且不展示配对码。

  • 源码启动若缺 dist 会构建 ChisaCode server;pack/dist 额外组装并验证 production daemon 依赖,禁止靠构建机残留产物。

  • 侧栏 QR 仅客户端 qrSvg(pairingUrl)includeQr: false)。

  • 服务器中继禁止 chisacode.sh / 上游 account_id。AGPL:AGPL-SHIPPING.md。内置 ayase.cn:443TLS 传输默认,不可作 SPA;公网 SPA 由同域 nginx 提供 https://ayase.cn/dshd/,中继只占精确 /ws/health 路由。

  • 粘性:deviceSecret 直至用户解除配对;刷新 QR 只换短期 pairing token。

  • 设备名(2026-09-04 起): 配对 hello 的 relayDeviceAuth.deviceName(append-only 协议字段,trim 后 1–120)是客户端自报的设备名——手机配对页从 UA 派生(iPhone · iOS 18.2 / Android 15 · Pixel 8 / 电脑,兜底 设备,见 mobile/web/chisacode/session.js#deviceNameFromUa),daemon 存为 device label(旧客户端兜底 relay-pair)。改名走 IPC shell:rename-remote-deviceDshdRemote.renameDeviceRelayDeviceCredentialStore.renameDevice(文件落盘、幂等、封顶 120、拒绝已吊销);两条标签写入路径(签发/改名)都归一 120 预算——DeviceRecordSchema 在加载时封顶 label,超长持久化标签会让整个 store 文件加载失败。存量 relay-pair 行不自动改,用户手动改名即迁移。fork 合同见 vendor/chisacode-remote/DESKTOP-FORK.md

  • dsh-im 桌面内置:insert 在自有 overlay desktop-plugins/dsh-im/desktop-dsh-im.patch.yml--patch 叠加(full+skip);cordis.patch.yml 不写受管块(只 strip 迁移);禁插件 / Recovery 不可关(IPC 返回 desktop-builtin,config 归一化剔除别名);vendor 运行时缺损 fail start(skip 修不了)。

  • 渠道主操作 36px(飞书扫码无 size=small)。

  • 断管不崩:vendored resolveDshVendorDirexecSync 必须携带显式 stdio(tripwire 在 remote-epipe.test.js);主进程 stdout/stderr 常驻 stdio-guard(断管类流错误吞掉,uncaughtException 仅吞断管写入、其余复刻 Electron 默认对话框)。

  • 弹窗失败态可见:启动中 startingHint;持久失败人话(端口占用 / 通用);On 对 !listening 或无 pairingUrl 可重试;打开弹窗立刻 refresh 且缺码时至多一次 sync 自愈;弹窗无 raw relay code、无裸 #offer= 文本;HarnessController 关停走 stopDaemon(),引导期 sync 失败必进 dsh 日志。

  • qa:remote 必含 cold.openShowsQr / cold.noBareOfferText / cold.copyAndRotateControls;第二 Electron 冷 boot(DSH_QA_REMOTE=cold,开窗前禁止 setRemote);QR 只认 [data-dsh-remote-qr];中继未连时这三条断言「无码 + 无复制/刷新 + 有 status」。prestart-ensure 校验 copyLink / data-dsh-remote-copy-link

  • 桌面 harness 完备(12 个 dsh vendor 包均有 lib/index.js)时才向子进程注入 CHISACODE_DSH_VENDOR_DIR;优先级 DSHD_DSH_VENDOR_DIR > 继承的 CHISACODE_DSH_VENDOR_DIR > 完备自带目录 > 不设(子进程内保留已加固的 npm 全局回退)。

  • dsh-acp-demo shim 仅在 harness acp-demo 构建产物存在时物化(<home>/bin,prepend 子进程 PATH);产物缺失时 provider 如实显示不可用,禁止伪造可用性。

Allowed touch

  • vendor/chisacode-remote/src/main/dshd-remote.jssrc/main/dshd-daemon-runner.mjssrc/main/index.jssrc/main/mobile-web-server.jssrc/main/stdio-guard.js
  • vendor/deepseek-harness/packages/client/ui-settings-remote/
  • src/main/remote-patch.jsconfig.jssrc/shared/lan.jsipc.js / preload Remote IPC
  • src/main/dsh-im-desktop.jsharness-controller.jsplugin-forensics.js
  • vendor/dsh-im/、本卡、mobile-remote_kill-http-remote

Do not touch

  • 自研中继冒充移植;daemon/hello 切片
  • 恢复 HTTP 宿主令牌墙
  • 把中继 IP 填进 remoteAppBaseUrl / QR 落地
  • 把 dsh-im 退回可禁用户插件

Gates

KindWhat
IMnpm --prefix vendor/dsh-im run test:desktopDSH_IM_LIVE_TEST=1 node --test vendor/dsh-im/host-protocol-live.test.mjsnode vendor/dsh-im/plugin-src/host/build.mjs;真实平台账号收发不以模拟测试代替
Automateddshd-remote.test.jsdshd-daemon-runner.test.js(runner 协议 + dist-gated 真实 daemon 端到端);remote-epipe.test.jsstdio-guard.test.jslan.test.js;dsh-im-desktop / skip-compose;ui-settings-remote specs;mobile/web/chisacode/session.test.js(配对 deviceName 上报)
Manual中继已连接 → 扫码配对 → sticky 重连 → 解除;Windows 打包机:子进程隔离下配对 + 强杀主进程无孤儿 daemon;dev 机(harness 已构建):手机端 dsh provider 建会话

Sources