From d53daf7d26a3971388f63cd43946f1f4674b68bf Mon Sep 17 00:00:00 2001 From: oliver Date: Sat, 5 Sep 2026 15:02:54 +0800 Subject: [PATCH] Rebrand as dsh-im-ops fork of xmanrui/dsh-im@4.9.1. Keep all IM channels; rename package/cordis id for local profile install without colliding with the community plugin. Document fork intent in FORK.md. Co-authored-by: Cursor --- FORK.md | 43 +++++++++++++++++++ README.md | 2 +- cordis.patch.yml | 4 +- package.json | 19 ++++---- plugin-src/client/build.mjs | 2 +- plugin-src/client/channels/dingtalk/styles.js | 2 +- plugin-src/client/channels/discord/styles.js | 2 +- plugin-src/client/channels/feishu/styles.js | 2 +- plugin-src/client/channels/qq/styles.js | 2 +- plugin-src/client/channels/slack/styles.js | 2 +- plugin-src/client/channels/telegram/styles.js | 2 +- plugin-src/client/channels/wecom/styles.js | 2 +- plugin-src/client/channels/weixin/styles.js | 2 +- plugin-src/client/channels/whatsapp/styles.js | 2 +- plugin-src/client/styles.js | 2 +- plugin-src/client/update-panel.js | 4 +- plugin-src/host/update-runtime.mjs | 2 +- plugin-src/host/update-service.mjs | 2 +- 18 files changed, 70 insertions(+), 28 deletions(-) create mode 100644 FORK.md diff --git a/FORK.md b/FORK.md new file mode 100644 index 0000000..954a35d --- /dev/null +++ b/FORK.md @@ -0,0 +1,43 @@ +# dsh-im-ops(运维 fork) + +本仓库是 [`@xmanrui/dsh-im@4.9.1`](https://github.com/xmanrui/dsh-im) 的 **完整 fork**(九渠道 + AI Office 均保留),用于 Netx / 运维场景下自控: + +- 访问控制(入站白名单 / 群策略) +- 会话策略(例如群聊拆个人 Session) +- 通告 / 投递默认与文案 + +上游 remote 名为 `upstream`。不要与社区包 `@xmanrui/dsh-im` 同时装进同一 profile。 + +## 与已删除的薄壳 `ops-im` 的关系 + +曾尝试只做 `ops_im__send` 适配层;因 **入站权限/会话仍在 dsh-im**,无法满足所有权诉求,已删除该薄仓库,改为本 fork。 + +## 安装(替换社区 im) + +```powershell +# 若已安装社区包,先从 profile 移除 @xmanrui/dsh-im +cd D:\project\chatgpt\dsh-im-ops +npm install +npm run build +dsh plugin --profile web add -w "D:\project\chatgpt\dsh-im-ops" +# 重启 dsh web +``` + +包名:`dsh-im-ops@4.9.1-ops.0`(cordis id:`dsh-im-ops`)。 + +扫码态一般仍在 `~/.dsh/integrations/…`;换包后若异常,在 IM 设置里重新关联设备。 + +## 第一刀改动方向(尚未改业务逻辑) + +1. WhatsApp / 通用 access mode:运维友好的默认与设置文案 +2. 群 Session key:对齐 oclaw `user_in_chat`(可配置) +3. 投递默认目标 / 与 netxops 协作说明 + +业务改动前先 `npm run build` 冒烟扫码与私聊。 + +## 同步上游 + +```powershell +git fetch upstream --tags +git merge v4.9.x # 或 cherry-pick;冲突自行解决后再 build +``` diff --git a/README.md b/README.md index c9af3ee..f65a535 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

+> **Fork:** dsh-im-ops — ops-owned fork of [@xmanrui/dsh-im@4.9.1](https://github.com/xmanrui/dsh-im). See [FORK.md](FORK.md). Do not install alongside the community package.\n\n

DSH-IM — Connecting DeepSeek Harness   DSH-IM phone logo

diff --git a/cordis.patch.yml b/cordis.patch.yml index 6798e9a..0ed36bb 100644 --- a/cordis.patch.yml +++ b/cordis.patch.yml @@ -1,3 +1,3 @@ - insert: - - id: xmanrui-dsh-im - name: '@xmanrui/dsh-im' + - id: dsh-im-ops + name: dsh-im-ops diff --git a/package.json b/package.json index f74ea77..957ecff 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "@xmanrui/dsh-im", - "version": "4.9.1", - "description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.", + "name": "dsh-im-ops", + "version": "4.9.1-ops.0", + "description": "Ops fork of dsh-im (all channels kept). Based on @xmanrui/dsh-im@4.9.1 — access/session policies owned here.", "keywords": [ "deepseek-harness", "dsh", @@ -20,7 +20,9 @@ "telegram", "discord", "whatsapp", - "ai-office" + "ai-office", + "ops", + "fork" ], "author": "xmanrui (https://github.com/xmanrui)", "contributors": [ @@ -41,14 +43,11 @@ "type": "module", "repository": { "type": "git", - "url": "git+https://github.com/xmanrui/dsh-im.git" + "url": "git+https://github.com/hansjone/dsh-im-ops.git" }, - "homepage": "https://github.com/xmanrui/dsh-im#readme", + "homepage": "https://github.com/hansjone/dsh-im-ops#readme", "bugs": { - "url": "https://github.com/xmanrui/dsh-im/issues" - }, - "publishConfig": { - "access": "public" + "url": "https://github.com/hansjone/dsh-im-ops/issues" }, "bin": { "dsh-im": "bin/dsh-im.mjs" diff --git a/plugin-src/client/build.mjs b/plugin-src/client/build.mjs index 5b53de7..8e2c519 100644 --- a/plugin-src/client/build.mjs +++ b/plugin-src/client/build.mjs @@ -7,7 +7,7 @@ import { build } from 'esbuild'; const sourceDirectory = dirname(fileURLToPath(import.meta.url)); const packageRoot = resolve(sourceDirectory, '../..'); const outputPath = resolve(packageRoot, 'lib/client.js'); -const loaderId = process.env.DSH_IM_CLIENT_ID ?? '@xmanrui/dsh-im'; +const loaderId = process.env.DSH_IM_CLIENT_ID ?? 'dsh-im-ops'; const result = await build({ entryPoints: [resolve(sourceDirectory, 'index.js')], diff --git a/plugin-src/client/channels/dingtalk/styles.js b/plugin-src/client/channels/dingtalk/styles.js index 189b84d..b9479f6 100644 --- a/plugin-src/client/channels/dingtalk/styles.js +++ b/plugin-src/client/channels/dingtalk/styles.js @@ -128,7 +128,7 @@ export function installDingtalkStyles() { const existing = document.querySelector(`style[data-plugin-css="${DINGTALK_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = DINGTALK_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/channels/discord/styles.js b/plugin-src/client/channels/discord/styles.js index 9a67dd2..dd4f3a1 100644 --- a/plugin-src/client/channels/discord/styles.js +++ b/plugin-src/client/channels/discord/styles.js @@ -11,7 +11,7 @@ export function installDiscordStyles() { const existing = document.querySelector(`style[data-plugin-css="${DISCORD_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = DISCORD_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/channels/feishu/styles.js b/plugin-src/client/channels/feishu/styles.js index ba000da..67b0303 100644 --- a/plugin-src/client/channels/feishu/styles.js +++ b/plugin-src/client/channels/feishu/styles.js @@ -562,7 +562,7 @@ export function installFeishuStyles() { } const style = document.createElement("style"); - style.dataset.plugin = "@xmanrui/dsh-im"; + style.dataset.plugin = "dsh-im-ops"; style.dataset.pluginCss = FEISHU_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/channels/qq/styles.js b/plugin-src/client/channels/qq/styles.js index 6131c08..af465e8 100644 --- a/plugin-src/client/channels/qq/styles.js +++ b/plugin-src/client/channels/qq/styles.js @@ -11,7 +11,7 @@ export function installQqStyles() { const existing = document.querySelector(`style[data-plugin-css="${QQ_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = QQ_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/channels/slack/styles.js b/plugin-src/client/channels/slack/styles.js index 388141f..8173254 100644 --- a/plugin-src/client/channels/slack/styles.js +++ b/plugin-src/client/channels/slack/styles.js @@ -26,7 +26,7 @@ export function installSlackStyles() { const existing = document.querySelector(`style[data-plugin-css="${SLACK_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = SLACK_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/channels/telegram/styles.js b/plugin-src/client/channels/telegram/styles.js index 9c9c6bb..e6cd34f 100644 --- a/plugin-src/client/channels/telegram/styles.js +++ b/plugin-src/client/channels/telegram/styles.js @@ -11,7 +11,7 @@ export function installTelegramStyles() { const existing = document.querySelector(`style[data-plugin-css="${TELEGRAM_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = TELEGRAM_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/channels/wecom/styles.js b/plugin-src/client/channels/wecom/styles.js index 1406c54..5871ee1 100644 --- a/plugin-src/client/channels/wecom/styles.js +++ b/plugin-src/client/channels/wecom/styles.js @@ -11,7 +11,7 @@ export function installWecomStyles() { const existing = document.querySelector(`style[data-plugin-css="${WECOM_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = WECOM_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/channels/weixin/styles.js b/plugin-src/client/channels/weixin/styles.js index 152e2c0..fa07a82 100644 --- a/plugin-src/client/channels/weixin/styles.js +++ b/plugin-src/client/channels/weixin/styles.js @@ -107,7 +107,7 @@ export function installWeixinStyles() { const existing = document.querySelector(`style[data-plugin-css="${WEIXIN_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = WEIXIN_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/channels/whatsapp/styles.js b/plugin-src/client/channels/whatsapp/styles.js index 338f042..524733f 100644 --- a/plugin-src/client/channels/whatsapp/styles.js +++ b/plugin-src/client/channels/whatsapp/styles.js @@ -11,7 +11,7 @@ export function installWhatsappStyles() { const existing = document.querySelector(`style[data-plugin-css="${WHATSAPP_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = WHATSAPP_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/styles.js b/plugin-src/client/styles.js index 90a5e9c..0e3a08b 100644 --- a/plugin-src/client/styles.js +++ b/plugin-src/client/styles.js @@ -543,7 +543,7 @@ export function installImStyles() { const existing = document.querySelector(`style[data-plugin-css="${IM_STYLE_ID}"]`); if (existing) return () => {}; const style = document.createElement('style'); - style.dataset.plugin = '@xmanrui/dsh-im'; + style.dataset.plugin = 'dsh-im-ops'; style.dataset.pluginCss = IM_STYLE_ID; style.textContent = CSS; document.head.appendChild(style); diff --git a/plugin-src/client/update-panel.js b/plugin-src/client/update-panel.js index 5e95e8b..b0432ac 100644 --- a/plugin-src/client/update-panel.js +++ b/plugin-src/client/update-panel.js @@ -109,7 +109,7 @@ function manualUpdateCommand(snapshot) { ? [...targets, snapshot.runningVersion, snapshot.installedVersion] .filter(validVersion).sort(compareVersionsDescending)[0] : 'latest'; - return `dsh plugin --profile ${profileArgument} add -w @xmanrui/dsh-im@${version}`; + return `dsh plugin --profile ${profileArgument} add -w dsh-im-ops@${version}`; } function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) { @@ -167,7 +167,7 @@ function ManualUpdateCommand({ command, disabled, sourceInstall, desktop }) { : h(React.Fragment, null, h('rect', { x: 7, y: 7, width: 10, height: 11, rx: 1.5 }), h('path', { d: 'M5 13H3.5A1.5 1.5 0 0 1 2 11.5v-8A1.5 1.5 0 0 1 3.5 2h8A1.5 1.5 0 0 1 13 3.5V5' }))))), - command.endsWith('@xmanrui/dsh-im@latest') ? h('p', { className: 'dim-updateManualHint' }, + command.endsWith('dsh-im-ops@latest') ? h('p', { className: 'dim-updateManualHint' }, '尚未确认目标版本,此命令安装执行时 npm 的 latest 版本。') : null, h('p', { className: 'dim-updateManualHint' }, desktop ? '请在当前 Desktop 的内置终端执行,完成后手动重启。' diff --git a/plugin-src/host/update-runtime.mjs b/plugin-src/host/update-runtime.mjs index 243b38d..1e0589e 100644 --- a/plugin-src/host/update-runtime.mjs +++ b/plugin-src/host/update-runtime.mjs @@ -6,7 +6,7 @@ import { fileURLToPath } from 'node:url'; import semver from 'semver'; -export const PACKAGE_NAME = '@xmanrui/dsh-im'; +export const PACKAGE_NAME = 'dsh-im-ops'; export const NPM_REGISTRY = 'https://registry.npmjs.org/'; const INSTALL_TIMEOUT_MS = 15 * 60_000; diff --git a/plugin-src/host/update-service.mjs b/plugin-src/host/update-service.mjs index a7c9ed9..1e80a84 100644 --- a/plugin-src/host/update-service.mjs +++ b/plugin-src/host/update-service.mjs @@ -51,7 +51,7 @@ export async function fetchNpmRelease(fetchImpl = globalThis.fetch, timeoutMs = const integrity = value.dist?.integrity; if (tarball.origin !== new URL(NPM_REGISTRY).origin || tarball.username || tarball.password || tarball.search || tarball.hash - || tarball.pathname !== `/@xmanrui/dsh-im/-/dsh-im-${version}.tgz` + || tarball.pathname !== `/dsh-im-ops/-/dsh-im-${version}.tgz` || typeof integrity !== 'string' || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(integrity)) { throw updateError('invalid-release'); }