@lijian-ui/dsh-im-gateway 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md ADDED
@@ -0,0 +1,183 @@
1
+ # @lijian-ui/dsh-im-gateway
2
+
3
+ English | [简体中文](./README.md)
4
+
5
+ > A multi-channel IM gateway plugin for **DeepSeek Harness (dsh)** — connect DingTalk, QQ and WeChat (iLink) bots to your harness agent, with QR-scan binding and streaming replies.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@lijian-ui/dsh-im-gateway)](https://www.npmjs.com/package/@lijian-ui/dsh-im-gateway)
8
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
9
+
10
+ ---
11
+
12
+ ## Features
13
+
14
+ - **Unified gateway service** — one plugin, three channels. Every channel routes through a single `ctx.imGateway` core: session management, slash commands, streaming, status broadcast.
15
+ - **DingTalk** — outbound WebSocket stream connection, group + single chats, @-mention filtering, **AI card streaming** (real-time incremental replies), slash commands.
16
+ - **QQ** — WebSocket gateway (official `qqbot-nodejs` SDK), private (c2c) + group chats, **QR-scan bot binding** (no manual console setup), **streaming messages** (c2c).
17
+ - **WeChat (iLink)** — official iLink long-poll protocol, **QR-scan login + pairing code**, single-chat only, media (AES-128-ECB CDN) in/out.
18
+ - **Multi-bot instances** — the same channel type can appear many times (e.g. two DingTalk bots), each with its own credentials.
19
+ - **Built-in slash commands** — `/help`, `/model`, `/status`, `/new`, `/reset`, `/stop` … (see below).
20
+ - **Settings UI** — a full web settings page ("IM 通道") rendered inside the official dsh web UI; QR-scan binding happens right there.
21
+ - **Streaming replies** — DingTalk AI Card, QQ stream_messages; plain-text fallback when a channel doesn't support streaming.
22
+
23
+ ---
24
+
25
+ ## Installation
26
+
27
+ Requires DeepSeek Harness (dsh) — the plugin is a standard **dsh bundle** and installs through the official plugin channel.
28
+
29
+ ### From npm (recommended)
30
+
31
+ ```bash
32
+ dsh plugin --profile web add @lijian-ui/dsh-im-gateway
33
+ ```
34
+
35
+ The npm package ships pre-built `lib/` — **no build authorization needed** (`allowBuilds` is not required).
36
+
37
+ ### From tarball
38
+
39
+ ```bash
40
+ npm pack @lijian-ui/dsh-im-gateway
41
+ dsh plugin --profile web add ./dsh-im-gateway-0.1.0.tgz
42
+ ```
43
+
44
+ ### From GitHub
45
+
46
+ ```bash
47
+ dsh plugin --profile web add github:lijian-ui/dsh-im-gateway
48
+ ```
49
+
50
+ > Git installs fetch **source**, so the first install requires approving the package's `prepare` build script (pnpm ≥ 10). Add the package key to the profile's `pnpm-workspace.yaml` → `allowBuilds` when prompted. Prefer npm/tarball to skip this.
51
+
52
+ ### Verify installation
53
+
54
+ ```bash
55
+ dsh --profile web --dump-config # should show a "# == @lijian-ui/dsh-im-gateway" config layer
56
+ dsh --profile web # open Settings → "IM 通道" in the browser
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Quick Start
62
+
63
+ 1. Open the dsh web UI → **Settings → IM 通道**.
64
+ 2. Click **添加通道** (Add channel).
65
+ 3. Pick a channel type:
66
+ - **QQ**: click **扫码登录** → scan with mobile QQ → credentials auto-fill → save.
67
+ - **个人微信** (WeChat): click **扫码登录** → scan with mobile WeChat → (enter the pairing code if asked) → credentials auto-fill → save.
68
+ - **钉钉** (DingTalk): fill in AppKey / AppSecret manually (or edit the config file) → save.
69
+ 4. Message your bot from the IM client — replies stream back in real time.
70
+
71
+ > Config is stored under `~/.dsh/settings.yaml` (`im-gateway.channels`). Saving from the UI **hot-reloads** the channels (no restart needed).
72
+
73
+ ---
74
+
75
+ ## Slash Commands
76
+
77
+ Sent to the bot in any IM channel:
78
+
79
+ | Command | Description |
80
+ | --- | --- |
81
+ | `/help` | List available commands |
82
+ | `/model` | List models with emoji numbers; `/model 1` or `/model <name>` to switch (no session yet → sets default for next conversation) |
83
+ | `/status` | Channel / cwd / current model / agent state |
84
+ | `/new` `/reset` `/clear` | Start a fresh conversation |
85
+ | `/stop` | Abort the current reply |
86
+
87
+ ---
88
+
89
+ ## Configuration
90
+
91
+ Everything is editable from the settings UI; the underlying schema lives in `~/.dsh/settings.yaml`:
92
+
93
+ ```yaml
94
+ im-gateway:
95
+ channels:
96
+ - id: dingtalk-main
97
+ type: dingtalk
98
+ name: 主机器人
99
+ enabled: true
100
+ config:
101
+ clientId: "..."
102
+ clientSecret: "..."
103
+ # callbackBaseUrl, appId, botAppId, baseUrl, botId, cdnBaseUrl, pollIntervalMs...
104
+ ```
105
+
106
+ | Field | Applies to | Meaning |
107
+ | --- | --- | --- |
108
+ | `clientId` / `clientSecret` | dingtalk | DingTalk app key / secret (Stream mode) |
109
+ | `appId` / `clientSecret` | qq | QQ Open Platform credentials (QR-bound) |
110
+ | `token` / `botId` / `baseUrl` / `cdnBaseUrl` | weixin | iLink credentials (QR-bound) |
111
+ | `enabled` | all | Whether this instance connects |
112
+
113
+ ---
114
+
115
+ ## Architecture
116
+
117
+ ```
118
+ IM client ──► channel adapter (dingtalk / qq / weixin)
119
+ │ ImInboundMessage
120
+ ▼
121
+ ctx.imGateway (core)
122
+ │ ensureSession → agent.followup
123
+ ▼
124
+ dsh harness agent (LLM loop)
125
+ │ session events (turn/start, assistant/chunk, tool/call, turn/end)
126
+ ▼
127
+ streaming reply → adapter.beginStream/streamText/endStream
128
+ │ (AI Card / stream_messages / plain text fallback)
129
+ ▼
130
+ IM client
131
+ ```
132
+
133
+ - **Host half** (node): `src/index.ts` (apply), `src/gateway/` (core + slash commands), `src/channels/` (dingtalk / qq / weixin + protocol helpers), `src/remote.ts` (Typert RPC for the settings UI), `src/sync.ts` (channel reload on config save).
134
+ - **Client half** (browser): `src/client/` — settings page "IM 通道" (add/edit modal + QR-scan login + status dots).
135
+ - **Multi-bot**: `channels` is an array; the same `type` may appear multiple times.
136
+
137
+ ### Extension points
138
+
139
+ Third parties can register their own channel without forking:
140
+
141
+ ```ts
142
+ import { ImChannelAdapter } from '@lijian-ui/dsh-im-gateway' // peerDependency on the core
143
+
144
+ class MyChannelAdapter implements ImChannelAdapter { /* ... */ }
145
+ ctx.imGateway.registerChannel(myAdapter)
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Development
151
+
152
+ ```bash
153
+ git clone https://github.com/lijian-ui/dsh-im-gateway.git
154
+ cd dsh-im-gateway
155
+ npm install
156
+ npm run build # tsdown → lib/
157
+ npm run watch # rebuild on save
158
+ npm run typecheck
159
+ ```
160
+
161
+ Local link into a dsh profile:
162
+
163
+ ```bash
164
+ dsh plugin --profile web add ./ # install from this directory (link)
165
+ ```
166
+
167
+ > **Windows note**: the dsh subprocess loads `lib/index.js` from `package.json` `main` — after editing `src/`, always `npm run build` then restart the dsh process (its require cache keeps the old module).
168
+
169
+ ---
170
+
171
+ ## Troubleshooting
172
+
173
+ - **No logs from the plugin** — cordis buffers `ctx.logger.*` in memory by default. The plugin registers a console exporter on apply, so logs appear in the dsh subprocess stderr (desktop shells prefix them with `[dsh]`).
174
+ - **QQ client shows "连接中" (connecting) forever** — streaming was opened too early or never closed. This plugin opens the stream on the first assistant text delta and always closes it on `turn/end` (fixed in 0.1.x).
175
+ - **Chat works but replies are not streaming** — the channel fell back to plain text (e.g. QQ group chats don't support `stream_messages`; WeChat has no streaming concept). This is by design.
176
+
177
+ ---
178
+
179
+ ## License
180
+
181
+ MIT © lijian-ui
182
+
183
+ Built for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — independent plugin, not affiliated with or endorsed by DeepSeek.
package/README.md CHANGED
@@ -1,55 +1,55 @@
1
1
  # @lijian-ui/dsh-im-gateway
2
2
 
3
- > Multi-channel IM gateway plugin for **DeepSeek Harness (dsh)** — connect DingTalk, QQ and WeChat (iLink) bots to your harness agent, with QR-scan binding and streaming replies.
4
- >
5
- > 为 DeepSeek Harness 提供多 IM 通道接入的网关插件:钉钉 / QQ / 个人微信,支持扫码绑定与流式回复。
3
+ [English](./README.en.md) | 简体中文
4
+
5
+ > 为 **DeepSeek Harness (dsh)** 提供多 IM 通道接入的网关插件:钉钉 / QQ / 个人微信,支持扫码绑定与流式回复。
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/@lijian-ui/dsh-im-gateway)](https://www.npmjs.com/package/@lijian-ui/dsh-im-gateway)
8
8
  [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
9
9
 
10
10
  ---
11
11
 
12
- ## Features / 功能特性
12
+ ## 功能特性
13
13
 
14
- - **Unified gateway service** — one plugin, three channels. Every channel routes through a single `ctx.imGateway` core: session management, slash commands, streaming, status broadcast.
15
- - **DingTalk (钉钉)** — outbound WebSocket stream connection, group + single chats, @-mention filtering, **AI card streaming** (real-time incremental replies), slash commands.
16
- - **QQ** — WebSocket gateway (official `qqbot-nodejs` SDK), private (c2c) + group chats, **QR-scan bot binding** (no manual console setup), **streaming messages** (c2c).
17
- - **WeChat (个人微信 / iLink)** — official iLink long-poll protocol, **QR-scan login + pairing code**, single-chat only, media (AES-128-ECB CDN) in/out.
18
- - **Multi-bot instances** — the same channel type can appear many times (e.g. two DingTalk bots), each with its own credentials.
19
- - **Built-in slash commands** — `/help`, `/model`, `/status`, `/new`, `/reset`, `/stop` … (see below).
20
- - **Settings UI** — a full web settings page ("IM 通道") rendered inside the official dsh web UI; QR-scan binding happens right there.
21
- - **Streaming replies** — DingTalk AI Card, QQ stream_messages; plain-text fallback when a channel doesn't support streaming.
14
+ - **统一网关服务** — 一个插件、三个通道。所有通道都汇聚到单一的 `ctx.imGateway` 核心:会话管理、斜杠命令、流式回复、状态广播。
15
+ - **钉钉** — 出站 WebSocket 长连接,群聊 + 单聊,@ 提及过滤,**AI 卡片流式输出**(实时增量回复),斜杠命令。
16
+ - **QQ** — WebSocket 网关(官方 `qqbot-nodejs` SDK),私聊(c2c)+ 群聊,**扫码绑定机器人**(免去开放平台手动创建),**流式消息**(c2c)。
17
+ - **个人微信(iLink)** — 官方 iLink 长轮询协议,**扫码登录 + 配对码**,仅单聊,媒体(AES-128-ECB CDN)收发。
18
+ - **多机器人实例** — 同一通道类型可配置多个实例(例如两个钉钉机器人),各自独立凭据。
19
+ - **内置斜杠命令** — `/help`、`/model`、`/status`、`/new`、`/reset`、`/stop` 等(见下文)。
20
+ - **设置页 UI** — 在官方 dsh web UI 内渲染完整的设置页(「IM 通道」),扫码绑定就在这里完成。
21
+ - **流式回复** — 钉钉 AI 卡片、QQ stream_messages;渠道不支持流式时自动回退纯文本。
22
22
 
23
23
  ---
24
24
 
25
- ## Installation / 安装
25
+ ## 安装
26
26
 
27
- Requires DeepSeek Harness (dsh) — the plugin is a standard **dsh bundle** and installs through the official plugin channel.
27
+ 需要 DeepSeek Harness (dsh)——本插件是标准 **dsh bundle**,通过官方插件通道安装。
28
28
 
29
- ### From npm (recommended) / 从 npm 安装(推荐)
29
+ ### 从 npm 安装(推荐)
30
30
 
31
31
  ```bash
32
32
  dsh plugin --profile web add @lijian-ui/dsh-im-gateway
33
33
  ```
34
34
 
35
- The npm package ships pre-built `lib/` — **no build authorization needed** (`allowBuilds` is not required).
35
+ npm 包自带预构建的 `lib/` — **无需构建授权**(不需要 `allowBuilds`)。
36
36
 
37
- ### From tarball / 从 tarball 安装
37
+ ### 从 tarball 安装
38
38
 
39
39
  ```bash
40
40
  npm pack @lijian-ui/dsh-im-gateway
41
41
  dsh plugin --profile web add ./dsh-im-gateway-0.1.0.tgz
42
42
  ```
43
43
 
44
- ### From GitHub / 从 GitHub 安装
44
+ ### 从 GitHub 安装
45
45
 
46
46
  ```bash
47
47
  dsh plugin --profile web add github:lijian-ui/dsh-im-gateway
48
48
  ```
49
49
 
50
- > Git installs fetch **source**, so the first install requires approving the package's `prepare` build script (pnpm ≥ 10). Add the package key to the profile's `pnpm-workspace.yaml` → `allowBuilds` when prompted. Prefer npm/tarball to skip this.
50
+ > Git 安装拉取的是**源码**,首次安装需要批准包的 `prepare` 构建脚本(pnpm ≥ 10)。按提示把包键加进 profile 的 `pnpm-workspace.yaml` → `allowBuilds` 即可。优先用 npm / tarball 方式可跳过此步。
51
51
 
52
- ### Verify / 验证安装
52
+ ### 验证安装
53
53
 
54
54
  ```bash
55
55
  dsh --profile web --dump-config # 应看到 "# == @lijian-ui/dsh-im-gateway" 配置层
@@ -58,37 +58,37 @@ dsh --profile web # 启动后浏览器打开设置 → 「IM
58
58
 
59
59
  ---
60
60
 
61
- ## Quick Start / 快速上手
61
+ ## 快速上手
62
62
 
63
- 1. Open the dsh web UI → **Settings → IM 通道**.
64
- 2. Click **添加通道** (Add channel).
65
- 3. Pick a channel type:
66
- - **QQ**: click **扫码登录** → scan with mobile QQ → credentials auto-fill → save.
67
- - **个人微信**: click **扫码登录** → scan with mobile WeChat → (enter the pairing code if asked) → credentials auto-fill → save.
68
- - **钉钉**: fill in AppKey / AppSecret manually (or edit the config file) → save.
69
- 4. Message your bot from the IM client — replies stream back in real time.
63
+ 1. 打开 dsh web UI → **设置 → IM 通道**。
64
+ 2. 点击**添加通道**。
65
+ 3. 选择通道类型:
66
+ - **QQ**:点击**扫码登录** → 手机 QQ 扫码 → 凭据自动填入 → 保存。
67
+ - **个人微信**:点击**扫码登录** → 手机微信扫码 →(如要求则输入配对码)→ 凭据自动填入 → 保存。
68
+ - **钉钉**:手动填写 AppKey / AppSecret(或直接编辑配置文件)→ 保存。
69
+ 4. 在 IM 客户端给机器人发消息 — 回复实时流式返回。
70
70
 
71
- > Config is stored under `~/.dsh/settings.yaml` (`im-gateway.channels`). Saving from the UI hot-reloads the channels (no restart needed).
71
+ > 配置存储在 `~/.dsh/settings.yaml`(`im-gateway.channels`)。在 UI 保存配置会**热重载**通道(无需重启)。
72
72
 
73
73
  ---
74
74
 
75
- ## Slash Commands / 斜杠命令
75
+ ## 斜杠命令
76
76
 
77
- Sent to the bot in any IM channel:
77
+ 在任何 IM 通道里发给机器人:
78
78
 
79
- | Command | Description |
79
+ | 命令 | 说明 |
80
80
  | --- | --- |
81
- | `/help` | List available commands |
82
- | `/model` | List models with emoji numbers; `/model 1` or `/model <name>` to switch (no session yet → sets default for next conversation) |
83
- | `/status` | Channel / cwd / current model / agent state |
84
- | `/new` `/reset` `/clear` | Start a fresh conversation |
85
- | `/stop` | Abort the current reply |
81
+ | `/help` | 列出可用命令 |
82
+ | `/model` | 用 emoji 编号列出模型;`/model 1` 或 `/model <名称>` 切换(无会话时 → 设为下次会话默认模型) |
83
+ | `/status` | 通道 / cwd / 当前模型 / agent 状态 |
84
+ | `/new` `/reset` `/clear` | 开启全新会话 |
85
+ | `/stop` | 中止当前回复 |
86
86
 
87
87
  ---
88
88
 
89
- ## Configuration / 配置
89
+ ## 配置
90
90
 
91
- Everything is editable from the settings UI; the underlying schema lives in `~/.dsh/settings.yaml`:
91
+ 所有配置都可在设置页编辑;底层 schema 在 `~/.dsh/settings.yaml`:
92
92
 
93
93
  ```yaml
94
94
  im-gateway:
@@ -103,43 +103,43 @@ im-gateway:
103
103
  # callbackBaseUrl, appId, botAppId, baseUrl, botId, cdnBaseUrl, pollIntervalMs...
104
104
  ```
105
105
 
106
- | Field | Applies to | Meaning |
106
+ | 字段 | 适用渠道 | 含义 |
107
107
  | --- | --- | --- |
108
- | `clientId` / `clientSecret` | dingtalk | DingTalk app key / secret (Stream mode) |
109
- | `appId` / `clientSecret` | qq | QQ Open Platform credentials (QR-bound) |
110
- | `token` / `botId` / `baseUrl` / `cdnBaseUrl` | weixin | iLink credentials (QR-bound) |
111
- | `enabled` | all | Whether this instance connects |
108
+ | `clientId` / `clientSecret` | dingtalk | 钉钉应用 key / secret(Stream 模式) |
109
+ | `appId` / `clientSecret` | qq | QQ 开放平台凭据(扫码绑定所得) |
110
+ | `token` / `botId` / `baseUrl` / `cdnBaseUrl` | weixin | iLink 凭据(扫码绑定所得) |
111
+ | `enabled` | 全部 | 该实例是否连接 |
112
112
 
113
113
  ---
114
114
 
115
- ## Architecture / 架构
115
+ ## 架构
116
116
 
117
117
  ```
118
- IM client ──► channel adapter (dingtalk / qq / weixin)
119
- │ ImInboundMessage
120
- ▼
121
- ctx.imGateway (core)
122
- │ ensureSession → agent.followup
123
- ▼
124
- dsh harness agent (LLM loop)
125
- │ session events (turn/start, assistant/chunk, tool/call, turn/end)
126
- ▼
127
- streaming reply → adapter.beginStream/streamText/endStream
128
- │ (AI Card / stream_messages / plain text fallback)
129
- ▼
130
- IM client
118
+ IM 客户端 ──► 通道适配器 (dingtalk / qq / weixin)
119
+ │ ImInboundMessage
120
+ ▼
121
+ ctx.imGateway(核心)
122
+ │ ensureSession → agent.followup
123
+ ▼
124
+ dsh harness agent(LLM 循环)
125
+ │ 会话事件 (turn/start, assistant/chunk, tool/call, turn/end)
126
+ ▼
127
+ 流式回复 → 适配器 beginStream/streamText/endStream
128
+ │ (AI 卡片 / stream_messages / 纯文本回退)
129
+ ▼
130
+ IM 客户端
131
131
  ```
132
132
 
133
- - **Host half** (node): `src/index.ts` (apply), `src/gateway/` (core + slash commands), `src/channels/` (dingtalk / qq / weixin + protocol helpers), `src/remote.ts` (Typert RPC for the settings UI), `src/sync.ts` (channel reload on config save).
134
- - **Client half** (browser): `src/client/` — settings page "IM 通道" (add/edit modal + QR-scan login + status dots).
135
- - **Multi-bot**: `channels` is an array; the same `type` may appear multiple times.
133
+ - **Host 半**(node):`src/index.ts`(apply)、`src/gateway/`(核心 + 斜杠命令)、`src/channels/`(dingtalk / qq / weixin + 协议助手)、`src/remote.ts`(设置页的 Typert RPC)、`src/sync.ts`(保存配置后热重载通道)。
134
+ - **Client 半**(浏览器):`src/client/` — 设置页「IM 通道」(添加/编辑弹窗 + 扫码登录 + 状态点)。
135
+ - **多机器人**:`channels` 是数组,同一 `type` 可多次出现。
136
136
 
137
- ### Extension points / 扩展点
137
+ ### 扩展点
138
138
 
139
- Third parties can register their own channel without forking:
139
+ 第三方可以不 fork 直接注册自己的通道:
140
140
 
141
141
  ```ts
142
- import { ImChannelAdapter } from '@lijian-ui/dsh-im-gateway' // peerDependency on the core
142
+ import { ImChannelAdapter } from '@lijian-ui/dsh-im-gateway' // peerDependency 引用核心
143
143
 
144
144
  class MyChannelAdapter implements ImChannelAdapter { /* ... */ }
145
145
  ctx.imGateway.registerChannel(myAdapter)
@@ -147,37 +147,37 @@ ctx.imGateway.registerChannel(myAdapter)
147
147
 
148
148
  ---
149
149
 
150
- ## Development / 开发
150
+ ## 开发
151
151
 
152
152
  ```bash
153
153
  git clone https://github.com/lijian-ui/dsh-im-gateway.git
154
154
  cd dsh-im-gateway
155
155
  npm install
156
156
  npm run build # tsdown → lib/
157
- npm run watch # rebuild on save
157
+ npm run watch # 保存自动重编译
158
158
  npm run typecheck
159
159
  ```
160
160
 
161
- Local link into a dsh profile:
161
+ 本地 link 进 dsh profile:
162
162
 
163
163
  ```bash
164
164
  dsh plugin --profile web add ./ # 从本目录安装(link)
165
165
  ```
166
166
 
167
- > **Windows note**: the dsh subprocess loads `lib/index.js` from `package.json` `main` — after editing `src/`, always `npm run build` then restart the dsh process (its require cache keeps the old module).
167
+ > **Windows 注意**:dsh 子进程从 `package.json` 的 `main` 加载 `lib/index.js` — 修改 `src/` 后必须 `npm run build` 再重启 dsh 进程(它的 require 缓存会保留旧模块)。
168
168
 
169
169
  ---
170
170
 
171
- ## Troubleshooting / 常见问题
171
+ ## 常见问题
172
172
 
173
- - **No logs from the plugin** — cordis buffers `ctx.logger.*` in memory by default. The plugin registers a console exporter on apply, so logs appear in the dsh subprocess stderr (desktop shells prefix them with `[dsh]`).
174
- - **QQ client shows "连接中" forever** — streaming was opened too early or never closed. This plugin opens the stream on the first assistant text delta and always closes it on `turn/end` (fixed in 0.1.x).
175
- - **Chat works but replies are not streaming** — the channel fell back to plain text (e.g. QQ group chats don't support `stream_messages`; WeChat has no streaming concept). This is by design.
173
+ - **插件没有任何日志** — cordis 默认把 `ctx.logger.*` 缓存进内存。本插件在 apply 时注册了 console exporter,日志会出现在 dsh 子进程 stderr(桌面壳会加 `[dsh]` 前缀)。
174
+ - **QQ 客户端一直显示「连接中」** — 流式开得太早或没收干净。本插件在**第一个文本增量**时才开流,并在 `turn/end` 无条件收流(0.1.x 已修复)。
175
+ - **能对话但不流式** — 渠道回退到了纯文本(例如 QQ 群聊不支持 `stream_messages`;微信本身没有流式概念)。这是设计行为。
176
176
 
177
177
  ---
178
178
 
179
- ## License / 许可
179
+ ## 许可
180
180
 
181
181
  MIT © lijian-ui
182
182
 
183
- Built for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) — independent plugin, not affiliated with or endorsed by DeepSeek. 独立插件,与 DeepSeek 无隶属或背书关系。
183
+ 为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 构建 — 独立插件,与 DeepSeek 无隶属或背书关系。
package/lib/client.js CHANGED
@@ -1,5 +1,5 @@
1
1
  window.__ModuleLoader__.load({
2
- id: "@dsh/im-gateway",
2
+ id: "@lijian-ui/dsh-im-gateway",
3
3
  factory: (require) => {
4
4
  var module = { exports: {} };
5
5
  var exports = module.exports;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lijian-ui/dsh-im-gateway",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Multi-channel IM gateway plugin for DeepSeek Harness (dsh): DingTalk / QQ / WeChat(iLink) with QR-scan binding, streaming replies, and a unified ctx.imGateway service. 为 DeepSeek Harness 提供钉钉/QQ/个人微信多 IM 通道接入。",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,7 @@
22
22
  "lib/**/*.d.ts",
23
23
  "cordis.patch.yml",
24
24
  "README.md",
25
- "README.zh-CN.md",
25
+ "README.en.md",
26
26
  "LICENSE"
27
27
  ],
28
28
  "scripts": {
package/README.zh-CN.md DELETED
@@ -1,207 +0,0 @@
1
- # @lijian-ui/dsh-im-gateway — DeepSeek Harness 多 IM 通道网关插件
2
-
3
- > 把钉钉、QQ、个人微信(iLink)机器人接入 DeepSeek Harness(dsh)的 agent,支持扫码绑定、流式回复、斜杠命令与设置页可视化配置。
4
-
5
- [![npm version](https://img.shields.io/npm/v/@lijian-ui/dsh-im-gateway)](https://www.npmjs.com/package/@lijian-ui/dsh-im-gateway)
6
- [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
-
8
- ---
9
-
10
- ## 一、这是什么
11
-
12
- `@lijian-ui/dsh-im-gateway` 是 **DeepSeek Harness(dsh)官方插件体系**下的一个组合包(bundle):一个统一的核心网关 + 三个渠道适配器,让你在钉钉 / QQ / 微信上跟 harness agent 对话。
13
-
14
- - **一个插件,三种渠道**:所有渠道都走同一个 `ctx.imGateway` 核心(会话管理、斜杠命令、流式回复、状态广播)。
15
- - **扫码绑定,开箱即用**:QQ 和微信不需要去开放平台手动创建机器人——设置页里点「扫码登录」,手机一扫凭据自动填好。
16
- - **流式回复**:钉钉 AI 卡片实时出字、QQ stream_messages 逐字推送;不支持流式的渠道自动降级为整条文本。
17
- - **多机器人实例**:同一个渠道类型可以配多个机器人(比如两个钉钉 bot),各自独立凭据。
18
- - **Web 设置页**:在官方 dsh Web UI 里多出「IM 通道」设置页,扫码、配置、在线状态一目了然。
19
-
20
- ---
21
-
22
- ## 二、功能特性
23
-
24
- ### 钉钉(dingtalk)
25
- - 出站 WebSocket 长连接(官方 Stream 模式),**无需 webhook**
26
- - 单聊 + 群聊;群聊仅响应 @机器人 的消息(防打扰)
27
- - **AI 卡片流式输出**:回复像"打字机"一样实时出字,含工具调用提示、完成动画
28
- - 引用回复 / 图片 / 语音转文字等入站能力
29
-
30
- ### QQ
31
- - 官方 `@tencent-connect/qqbot-nodejs` WebSocket 网关
32
- - 私聊(c2c)+ 群聊(仅 @ 响应)
33
- - **扫码绑定机器人**:`qqbot-connector` 扫码后自动拿到 AppID / AppSecret,免去开放平台手动创建
34
- - **流式消息**(c2c):`stream_messages` 逐字推送;群聊自动降级为普通文本
35
-
36
- ### 个人微信(weixin / iLink)
37
- - 微信官方 iLink 协议(`ilinkai.weixin.qq.com`),纯 fetch 长轮询,无额外依赖
38
- - **扫码登录 + 配对码**:手机微信扫码后按提示输入配对码即完成绑定
39
- - 仅单聊(一个个人微信号绑一个 bot)
40
- - 入站图片 AES-128-ECB 解密、出站媒体上传;文本经流式 Markdown 过滤(微信不渲染 MD)
41
-
42
- ### 通用能力
43
- - **斜杠命令**:`/help` `/model` `/status` `/new` `/reset` `/clear` `/stop`
44
- - **多实例**:`channels` 是数组,同一类型可配多个
45
- - **热更新**:设置页保存后立即重建通道,无需重启
46
- - **状态广播**:设置页每个通道卡片显示在线 / 离线 / 错误状态点
47
- - **模型切换**:`/model` 列出可用模型(emoji 编号),无会话时可设置全局默认模型
48
-
49
- ---
50
-
51
- ## 三、安装
52
-
53
- 需要已安装 DeepSeek Harness(dsh)。本插件是标准 dsh bundle,走官方插件安装通道。
54
-
55
- ### 3.1 从 npm 安装(推荐)
56
-
57
- ```bash
58
- dsh plugin --profile web add @lijian-ui/dsh-im-gateway
59
- ```
60
-
61
- npm 包自带**预构建的 `lib/`**,安装即用——**不需要** `allowBuilds` 构建授权。
62
-
63
- ### 3.2 从 tarball 安装
64
-
65
- ```bash
66
- npm pack @lijian-ui/dsh-im-gateway
67
- dsh plugin --profile web add ./dsh-im-gateway-0.1.0.tgz
68
- ```
69
-
70
- ### 3.3 从 GitHub 安装
71
-
72
- ```bash
73
- dsh plugin --profile web add github:lijian-ui/dsh-im-gateway
74
- ```
75
-
76
- > git 安装拉取的是**源码**,首次安装需要授权 `prepare` 构建脚本(pnpm ≥ 10 默认拒绝)。按提示把包键加进该 profile 的 `pnpm-workspace.yaml` → `allowBuilds` 即可。想跳过授权就用 npm / tarball 方式。
77
-
78
- ### 3.4 验证安装
79
-
80
- ```bash
81
- dsh --profile web --dump-config # 输出里应有 "# == @lijian-ui/dsh-im-gateway" 配置层
82
- dsh --profile web # 启动后浏览器打开设置 → 「IM 通道」
83
- ```
84
-
85
- ---
86
-
87
- ## 四、快速上手
88
-
89
- 1. 启动 dsh,浏览器打开 Web UI → **设置 → IM 通道**。
90
- 2. 点 **添加通道**,选渠道类型:
91
- - **QQ**:点 **扫码登录** → 手机 QQ 扫码 → 凭据自动填入 → 保存。
92
- - **个人微信**:点 **扫码登录** → 手机微信扫码 → (如提示)输入配对码 → 凭据自动填入 → 保存。
93
- - **钉钉**:手动填 AppKey / AppSecret(或直接改配置文件)→ 保存。
94
- 3. 在 IM 客户端给你的机器人发消息——回复实时流式返回。
95
-
96
- > 配置存于 `~/.dsh/settings.yaml` 的 `im-gateway.channels`。设置页保存后**热重载**,无需重启。
97
-
98
- ---
99
-
100
- ## 五、斜杠命令
101
-
102
- 在任意 IM 渠道给机器人发:
103
-
104
- | 命令 | 说明 |
105
- | --- | --- |
106
- | `/help` | 列出可用命令 |
107
- | `/model` | 列出模型(emoji 编号);`/model 1` 或 `/model <名称>` 切换;无会话时设为下次会话的默认模型 |
108
- | `/status` | 渠道 / 工作目录 / 当前模型 / agent 状态 |
109
- | `/new` `/reset` `/clear` | 开启新会话 |
110
- | `/stop` | 中止当前回复 |
111
-
112
- ---
113
-
114
- ## 六、配置
115
-
116
- 优先在设置页编辑;底层存于 `~/.dsh/settings.yaml`:
117
-
118
- ```yaml
119
- im-gateway:
120
- channels:
121
- - id: dingtalk-main
122
- type: dingtalk
123
- name: 主机器人
124
- enabled: true
125
- config:
126
- clientId: "你的 AppKey"
127
- clientSecret: "你的 AppSecret"
128
- ```
129
-
130
- | 字段 | 适用渠道 | 含义 |
131
- | --- | --- | --- |
132
- | `clientId` / `clientSecret` | dingtalk | 钉钉应用凭据(Stream 模式) |
133
- | `appId` / `clientSecret` | qq | QQ 开放平台凭据(扫码绑定自动填) |
134
- | `token` / `botId` / `baseUrl` / `cdnBaseUrl` | weixin | iLink 凭据(扫码绑定自动填) |
135
- | `enabled` | 全部 | 该实例是否启用连接 |
136
-
137
- ---
138
-
139
- ## 七、架构
140
-
141
- ```
142
- IM 客户端 ──► 渠道适配器(dingtalk / qq / weixin)
143
- │ ImInboundMessage
144
- ▼
145
- ctx.imGateway(核心)
146
- │ ensureSession → agent.followup
147
- ▼
148
- dsh harness agent(LLM 循环)
149
- │ 会话事件(turn/start、assistant/chunk、tool/call、turn/end)
150
- ▼
151
- 流式回复 → 适配器 beginStream/streamText/endStream
152
- │ (AI 卡片 / stream_messages / 纯文本降级)
153
- ▼
154
- IM 客户端
155
- ```
156
-
157
- - **Host 半(node)**:`src/index.ts`(apply)、`src/gateway/`(核心 + 斜杠命令)、`src/channels/`(三渠道 + 协议层)、`src/remote.ts`(Typert RPC,供设置页调用)、`src/sync.ts`(配置保存后重建通道)。
158
- - **Client 半(浏览器)**:`src/client/`——设置页「IM 通道」(添加/编辑弹窗、扫码登录、状态点)。
159
- - **多实例**:`channels` 是数组,同一 `type` 可出现多次。
160
-
161
- ### 扩展点
162
-
163
- 第三方无需 fork 即可注册自己的渠道:
164
-
165
- ```ts
166
- import { ImChannelAdapter } from '@lijian-ui/dsh-im-gateway' // peerDependency 引用核心
167
-
168
- class MyChannelAdapter implements ImChannelAdapter { /* ... */ }
169
- ctx.imGateway.registerChannel(myAdapter)
170
- ```
171
-
172
- ---
173
-
174
- ## 八、开发
175
-
176
- ```bash
177
- git clone https://github.com/lijian-ui/dsh-im-gateway.git
178
- cd dsh-im-gateway
179
- npm install
180
- npm run build # tsdown → lib/
181
- npm run watch # 保存即重编译
182
- npm run typecheck
183
- ```
184
-
185
- 本地 link 进 profile:
186
-
187
- ```bash
188
- dsh plugin --profile web add ./ # 从本目录安装(link)
189
- ```
190
-
191
- > **Windows 提醒**:dsh 子进程从 `package.json` 的 `main`(`lib/index.js`)加载,**不直接读 src**。改完 `src/` 必须 `npm run build`,然后**重启 dsh 进程**(require 缓存不会自动刷新)。
192
-
193
- ---
194
-
195
- ## 九、常见问题
196
-
197
- - **看不到插件日志?** cordis 默认把 `ctx.logger.*` 存进内存 buffer 不打印。本插件 apply 时注册了 console exporter,日志会出现在 dsh 子进程 stderr(桌面壳通常带 `[dsh]` 前缀)。
198
- - **QQ 客户端一直"连接中"?** 流式开得太早或没收尾。本插件在第一个 assistant 文本增量时才开流,`turn/end` 时必关流(0.1.x 已修复)。
199
- - **能对话但回复不是流式?** 渠道降级为纯文本了(QQ 群聊不支持 `stream_messages`、微信本身无流式概念)——这是设计行为。
200
-
201
- ---
202
-
203
- ## 十、许可
204
-
205
- MIT © lijian-ui
206
-
207
- 为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 打造的独立插件,与 DeepSeek 官方无隶属或背书关系。