# dsh-jace-remote **Repository Path**: SapientialM/dsh-jace-remote ## Basic Information - **Project Name**: dsh-jace-remote - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-12 - **Last Updated**: 2026-09-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # dsh-jace-remote > 给 **dsh web** 加一个局域网入口:手机/平板/另一台电脑在同一 Wi-Fi 下,输入本机显示的 **4 位配对码**,之后就能像本机一样使用 dsh web。 > 设计文档见 [`DESIGN.md`](DESIGN.md)。 **npm**:[`dsh-jace-remote`](https://www.npmjs.com/package/dsh-jace-remote) `0.2.0` · **dsh**:`0.1.5-rc.1`(实测) · **License**:MIT · **仓库**:[gitee.com/SapientialM/dsh-jace-remote](https://gitee.com/SapientialM/dsh-jace-remote) ```bash # 一行装进 dsh(标准 Cordis bundle:同时带 Node 半边 + 设置页 client 半边) dsh plugin --profile web add dsh-jace-remote ``` ## 兼容性 | 项 | 值 | |---|---| | 实测 dsh 版本 | **`0.1.5-rc.1`**(`dsh --version`;同批子包 0.1.5-rc.2) | | 依赖的 dsh 内部契约 | Cordis bundle 装载(`dsh.bundle.patch`)、`ctx.webServer.register`、`ctx.slots.register` 的 `settings.section` slot、client seed 表(`react` 等) | | Node | `>= 22` | | 其它版本 | 未验证。dsh 升级后若 slot 名 / 服务名 / loader 行为有变,`client` 半边或网关可能失效——按下方「验证装载」清单重跑一遍即可 | > 本项目按 `dsh 0.1.5-rc.1` 的插件契约开发;契约调研记录见 `DESIGN.md` §6。 ## 它做什么 ``` 手机 (192.168.x.x) 本机 Mac │ http://<本机IP>:3081/ │ ├── 未配对 → 配对页(输入 4 位码) │ └── 已配对 → dsh-jace-remote 网关 ──────▶ dsh web (127.0.0.1:3080) · HTTP / SSE / WebSocket 全透传 · 上游认证由网关内部完成 · 设置页内置 “jace remote” 栏目显示配对码 ``` > 文档中的 IP 一律是占位符(`<本机IP>` / `192.168.x.x`),实际地址以设置页 `jace remote` 栏目或启动日志为准。 - **动态 4 位码**:默认 5 分钟轮换、一次性使用;每 IP 10 分钟内 5 次失败即限速。 - **设备会话**:配对成功签发 HttpOnly cookie,默认 7 天(滑动续期),可列出/撤销。 - **零依赖**:只用 Node 内置模块(http/net/crypto/fs)。 - **仅私网**:只接受 RFC1918 / 回环来源,拒绝其它源地址。 ## 安装 / 卸载(标准 Cordis bundle) 本包是**标准 dsh Cordis bundle**: `package.json` 里 `dsh.bundle.patch → ./cordis.patch.yml`,包内 patch 用**包名**插入 `id: jace-remote` 行。 把它装进 profile 后,`dsh plugin` 会把 `dsh-jace-remote` 追加进该 profile 的 `dsh.profile.bundles`,由 loader 作为一层 bundle 应用。 ```bash # ✅ 方式一(推荐,已发布到 npm):直接从 registry 装 dsh plugin --profile web add dsh-jace-remote # 方式二(本地开发/改代码):同步源码到 profile 树内,再执行 dsh plugin add node scripts/install.mjs --profile web # 查看装载状态(bundles / dependency / 插件目录) node scripts/install.mjs --profile web --print-config # 卸载(两种方式通用) dsh plugin --profile web remove dsh-jace-remote # 或 node scripts/install.mjs --uninstall --profile web # 校验组合树确实带上了这一层 dsh --profile web --dump-config | grep -A3 'jace-remote' # 期望: # == dsh-jace-remote 然后 - id: jace-remote / name: dsh-jace-remote ... ``` > **装完需要重启 `dsh web`**:Node 半边与 client 半边都属于模块代码,本 profile 的 cordis `hmr` 行是 disabled,只有 `cordis.patch.yml` 的配置改动能热生效。 > **为什么脚本要先把源码拷进 `$DSH_HOME/profiles//plugins/`**: > 本包 `import '@deepseek-ai/dsh-tools'` 等,Node ESM 按 **realpath** 解析模块。若用 > `dsh plugin add /外部目录`,pnpm 只建 symlink,realpath 落在 profile 树外 → 父级回退链 > 找不到 `@deepseek-ai/*` → `ERR_MODULE_NOT_FOUND`(`NODE_OPTIONS=--preserve-symlinks` 对 ESM 无效)。 > 放进 profile 树内后,`profiles/web/node_modules → profiles/node_modules` 回退链可正常解析。 配置覆盖:在该 profile 的 `cordis.patch.yml` 里按**同一个 row id** 写(注意 patch 整块替换 config,需重述要保留的键): ```yaml - id: jace-remote config: enabled: true port: 3081 codeTtlSeconds: 300 sessionTtlHours: 168 maxAttemptsPerWindow: 5 rateWindowMinutes: 10 logCodes: true allowPrivateOnly: true bindHost: 0.0.0.0 stateFile: '' ``` ## 使用 1. 手机连同一个 Wi-Fi,浏览器打开局域网地址(默认 `http://<本机IP>:3081/`)。 2. 页面要求输入 4 位配对码。获取方式(任选): - **dsh web → 设置 → `jace remote` 栏目**(推荐,见下节) - 本机终端里 dsh web 的日志:`pairing code 8539 (expires in 04:59)` - 问本机 agent:「配对码多少」(工具 `jace_remote_code`) - 读文件:`~/.dsh/jace-remote/pairing.json` 3. 配对成功后即可正常使用;之后 7 天内无需再输码。 ### 设置页栏目:jace remote(client 半边) dsh web 的「设置」里会多出一节 **jace remote**(order 50,排在 models/plugins 之后),显示: - **当前 4 位配对码** + 剩余有效秒数(每 5 秒自动刷新) - 局域网地址、网关运行状态(端口) - 已配对设备列表(设备名 / IP / 最后活跃) 实现:`lib/client.js`(无需构建,直接是 ModuleLoader 工厂格式,`ctx.slots.register` 到 `settings.section`); 数据来自同源 `GET /__jace/remote/status`(由 Node 半边挂在 dsh webServer 上)。 局域网里**已配对**的设备也能看到这一节;**未配对**设备访问该接口会被网关拒绝(拿不到码)。 > ⚠️ **client 半边与 Node 路由的改动需要重启 `dsh web` 才生效**(本 profile 的 cordis `hmr` 行是 disabled, > 只有 `cordis.patch.yml` 的配置改动能热生效;模块代码不会热重载)。 ### agent 工具 | 工具 | 作用 | |---|---| | `jace_remote_code` | 当前配对码 + 局域网地址 + 网关状态 | | `jace_remote_devices` | 列出已配对设备(id / 名称 / IP / 最后活跃 / 过期) | | `jace_remote_revoke` | 按 id 撤销设备 | | `jace_remote_panic` | 紧急关闭网关(立即断开所有已配对设备) | ## 配置 在 `$DSH_HOME/profiles//cordis.patch.yml` 里按**同一个 row id** 覆盖(patch 是**整块替换 config**,要重述想保留的键;若文件里是 `[]` 占位,直接替换成下面的列表): ```yaml - id: jace-remote config: enabled: true bindHost: 0.0.0.0 port: 3081 codeTtlSeconds: 300 # 配对码有效期 sessionTtlHours: 168 # 设备会话有效期(滑动) maxAttemptsPerWindow: 5 # 每 IP 失败上限 rateWindowMinutes: 10 # 限速窗口 logCodes: true # 是否把码打到 dsh 日志 allowPrivateOnly: true # 仅私网来源 stateFile: '' # 空 = ~/.dsh/jace-remote/state.json ``` ## ⚠️ 安全须知(务必读) 1. **这是完整的 RCE 入口**:能打开 dsh web 就等于能在这台 Mac 上跑任意命令(agent 有 shell/文件权限)。 2. **4 位码是弱口令**:靠"5 分钟轮换 + 一次性 + 每 IP 限速 + 仅私网"兜底,只适用于**可信局域网**。 3. **不要在公共/咖啡厅/访客 Wi-Fi 开启**;建议同时打开 macOS 防火墙(当前系统默认是关闭的)。 4. 不用时:`jace_remote_panic` 或 `--disable` 重装。 5. 不监听公网、不做 NAT 穿透。真要外网访问请用 Tailscale / WireGuard 等 overlay。 6. 状态文件权限 0600,只存 device token 的 **sha256 哈希**;日志不打印 token 原文。 ## 开发 ```bash npm test # 单元测试(配对/限速/设备会话)+ 网关冒烟(假上游,含 WS 101) node scripts/install.mjs --profile jaceremote-dev --port 3088 # 装到测试 profile 联调 ``` > 联调**不要重启正在承载你对话的 web profile**;用独立 profile + 独立端口(见 DESIGN.md §8)。 ## 发布(维护者) ```bash # 1) 改版本号(语义化)+ 提交推送 npm version patch # 或 minor / major git push origin main --tags # 2) 发布到 npm(账号 agrinjpg;发布需带 Bypass 2FA 的 granular token,见 ~/.npmrc) npm publish # 3) 校验 npm view dsh-jace-remote version ``` > npm 现在不允许用旧式 token 发布:报 `403 ... granular access token with bypass 2fa` 时, > 去 npmjs.com → Access Tokens → 生成 **Granular Access Token** 并勾选 **Bypass 2FA**, > 然后 `npm config set //registry.npmjs.org/:_authToken=`。 > 本地 `.npmrc` 已在 `.gitignore` 中,token 不会入库。 ## 目录 ``` src/index.js 插件入口(Config / inject / apply / agent 工具 / 设置页状态路由) src/gateway.js 局域网网关:配对页、HTTP/SSE 反代、WS 透传、私网校验 src/pairing.js 4 位码生成/轮换/限速(纯逻辑) src/devices.js 设备 token 签发/校验/撤销 + state.json src/upstream.js 用 launch token 换 dsh 会话 cookie(上游认证) src/html/ 配对页 lib/client.js client 半边:设置页新增 “jace remote” 栏目(ModuleLoader 工厂格式) cordis.patch.yml bundle 层 patch(以包名 insert 出 id: jace-remote) scripts/install.mjs 安装/卸载到 profile test/ 单元 + 冒烟测试 ``` ## License [MIT](LICENSE) © 2026 cm