diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..a9af001 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,26 @@ +# DSHWatch 脚本 + +## 启动中继服务器 + +Linux/macOS: + + bash scripts/start.sh + +Windows: + + scripts\start.bat + +(首次会复制 config.example.json 到 config.json,请改 token。) + +## 把 dsh-watch 插件接进 DSH profile + + node scripts/setup-plugin.mjs desktop + node scripts/setup-plugin.mjs web + +脚本会:在 profile 的 package.json 加 link 依赖 + bundles 列表,并创建 node_modules/dsh-watch 链接。 +然后重启 DSH,并在 profile 的 cordis.patch.yml 里给 dsh-watch 配 mode/serverUrl/userId/token。 + +## 说明 + +- keystore.properties / keystore/ 不进 git。 +- 手表 rpk 与手机 APK 需同一套签名(包名 com.dshwatch.app)。 diff --git a/scripts/setup-plugin.mjs b/scripts/setup-plugin.mjs new file mode 100644 index 0000000..7cb57d2 --- /dev/null +++ b/scripts/setup-plugin.mjs @@ -0,0 +1,56 @@ +#!/usr/bin/env node +// DSHWatch: wire the dsh-watch plugin into a DSH profile (web or desktop). +// Usage: node setup-plugin.mjs [profile] [pluginPath] +// node setup-plugin.mjs desktop +// node setup-plugin.mjs web D:/project/DeepSeek_Harness_Watch/dsh-watch + +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import { execFileSync } from 'node:child_process'; +import { fileURLToPath } from 'node:url'; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const profile = process.argv[2] || 'desktop'; +const defaultPlugin = path.resolve(here, '..', '..', 'dsh-watch'); +const pluginPath = path.resolve(process.argv[3] || defaultPlugin); + +const dshHome = process.env.DSH_HOME || path.join(os.homedir(), '.dsh'); +const profileDir = path.join(dshHome, 'profiles', profile); +const pkgPath = path.join(profileDir, 'package.json'); + +if (!fs.existsSync(pkgPath)) { + console.error('[setup-plugin] profile not found:', pkgPath); + process.exit(1); +} + +const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); +const depKey = 'dsh-watch'; +const depValue = 'link:' + pluginPath; + +pkg.dependencies = pkg.dependencies || {}; +if (pkg.dependencies[depKey] !== depValue) pkg.dependencies[depKey] = depValue; + +pkg.dsh = pkg.dsh || {}; +pkg.dsh.profile = pkg.dsh.profile || {}; +pkg.dsh.profile.bundles = pkg.dsh.profile.bundles || []; +if (!pkg.dsh.profile.bundles.includes(depKey)) pkg.dsh.profile.bundles.push(depKey); + +fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n'); + +// Create node_modules link so the loader can resolve it without a full pnpm install. +const nm = path.join(profileDir, 'node_modules'); +const link = path.join(nm, depKey); +fs.mkdirSync(nm, { recursive: true }); +if (!fs.existsSync(link)) { + try { + fs.symlinkSync(pluginPath, link, 'junction'); + } catch (e) { + // fall back to copy-ish behavior message + console.error('[setup-plugin] could not link, will need pnpm install:', e.message); + } +} + +console.log('[setup-plugin] wired dsh-watch into profile=' + profile); +console.log('[setup-plugin] plugin = ' + pluginPath); +console.log('[setup-plugin] next: restart DSH, then configure mode/userId/token in profile cordis.patch.yml'); diff --git a/scripts/start.bat b/scripts/start.bat new file mode 100644 index 0000000..cef2693 --- /dev/null +++ b/scripts/start.bat @@ -0,0 +1,8 @@ +@echo off +cd /d "%~dp0\.." +if not exist config.json ( + copy config.example.json config.json >nul + echo created config.json from example; edit token first. +) +call npm install --no-audit --no-fund +node server.js diff --git a/scripts/start.sh b/scripts/start.sh new file mode 100644 index 0000000..e564627 --- /dev/null +++ b/scripts/start.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Start DSHWatch relay broker +set -e +cd "$(dirname "$0")/.." +if [ ! -f config.json ]; then + cp config.example.json config.json + echo "created config.json from example; edit token first." >&2 +fi +npm install --no-audit --no-fund +node server.js