@xmanrui/dsh-im 0.11.0 → 0.13.0

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.
Files changed (32) hide show
  1. package/README.en.md +71 -37
  2. package/README.md +73 -39
  3. package/lib/client.js +2 -2
  4. package/lib/index.js +134 -124
  5. package/package.json +31 -2
  6. package/plugin-src/client/i18n.js +1 -1
  7. package/plugin-src/client/index.js +1 -1
  8. package/plugin-src/host/channels/dingtalk/production.mjs +7 -0
  9. package/plugin-src/host/channels/feishu/production.mjs +7 -0
  10. package/plugin-src/host/channels/qq/production.mjs +7 -0
  11. package/plugin-src/host/channels/shared/production.mjs +7 -0
  12. package/plugin-src/host/channels/slack/production.mjs +7 -0
  13. package/plugin-src/host/channels/wecom/production.mjs +7 -0
  14. package/plugin-src/host/channels/weixin/production.mjs +7 -0
  15. package/plugin-src/host/channels/whatsapp/production.mjs +7 -0
  16. package/plugin-src/host/harness-session-coordinator.mjs +134 -0
  17. package/scripts/verify-package.mjs +34 -0
  18. package/src/channels/dingtalk/dingtalk-bridge.mjs +82 -0
  19. package/src/channels/discord/discord-api.mjs +1 -1
  20. package/src/channels/feishu/bridge.mjs +82 -0
  21. package/src/channels/qq/qq-bridge.mjs +85 -0
  22. package/src/channels/shared/bot-workspace-store.mjs +45 -1
  23. package/src/channels/shared/control-command.mjs +84 -0
  24. package/src/channels/shared/harness-approval.mjs +4 -0
  25. package/src/channels/shared/harness-client.mjs +336 -29
  26. package/src/channels/shared/model-command.mjs +352 -0
  27. package/src/channels/shared/session-binding-lock.mjs +40 -0
  28. package/src/channels/shared/text-harness-bridge.mjs +82 -0
  29. package/src/channels/shared/workspace-session.mjs +21 -9
  30. package/src/channels/wecom/wecom-bridge.mjs +76 -0
  31. package/src/channels/weixin/weixin-api.mjs +1 -1
  32. package/src/channels/weixin/weixin-bridge.mjs +82 -0
package/README.en.md CHANGED
@@ -3,12 +3,26 @@
3
3
  ---
4
4
 
5
5
  <div align="center">
6
- <p><strong>Connect IM bots to DeepSeek Harness with ease</strong></p>
6
+ <p><strong>DeepSeek Harness, always within reach</strong></p>
7
7
 
8
8
  <p>
9
+ <img src="https://dsh-im-random-badge.xmanrui-dsh-im.workers.dev" alt="滑动变祖器:今天是梁子或今天是梁圣(随机)">
9
10
  <a href="LICENSE"><img src="https://img.shields.io/github/license/xmanrui/dsh-im" alt="MIT license"></a>
10
11
  <img src="https://img.shields.io/badge/agent-DeepSeek%20Harness-5865f2" alt="DeepSeek Harness">
11
- <img src="https://dsh-im-random-badge.xmanrui-dsh-im.workers.dev" alt="滑动变祖器:今天是梁子或今天是梁圣(随机)">
12
+ <a href="https://dshfind.com/zh/plugins/xmanrui/dsh-im?ref=badge"><img src="https://dshfind.com/api/badge/xmanrui/dsh-im?lang=zh" alt="dshfind"></a>
13
+ <a href="https://dshfind.com/zh/plugins/xmanrui/dsh-im"><img src="https://img.shields.io/badge/dshfind-%E5%88%86%E7%B1%BB%E7%AC%AC%E4%B8%80-d97706" alt="dshfind: 分类第一"></a>
14
+ </p>
15
+
16
+ <p>
17
+ <img src="https://img.shields.io/badge/%E5%BE%AE%E4%BF%A1-07C160?logo=wechat&amp;logoColor=white" alt="微信">
18
+ <img src="https://img.shields.io/badge/%E9%A3%9E%E4%B9%A6-3370FF?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTcuMiA0LjVoNy42YzEuMiAwIDIuMS41NSAyLjcgMS41OCAxLjA1IDEuOCAxLjU1IDMuNDUgMS41OCA0Ljk1LTIuMDQtLjYyLTQuMi0uMTUtNi4yMiAxLjQ1QzExLjMgOS43IDkuNDIgNy4wNCA3LjIgNC41WiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0xMC44IDEzLjU1YzMuMy0yLjkzIDUuNzItNC4yNCA5LjQ3LTIuNTItMS4yIDEuNDUtMi4yNyA0LjE4LTMuODYgNS40My0xLjY3IDEuMzEtMy45LjUtNS42MS0uNjR2LTIuMjdaIi8%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTQuNCA4LjM1YzMuNDcgMy42MSA3LjI1IDYuMSAxMC4zMyA1LjcgMS4wNi0uMTQgMi4yLS43MiAzLjQtMS43Mi0xLjA0IDIuNjUtMi42IDQuOC01LjA2IDYtMi40NiAxLjItNS41Ni41Mi03LjQyLS43MkEyLjc2IDIuNzYgMCAwIDEgNC40IDE1LjNWOC4zNVoiLz48L3N2Zz4%3D" alt="飞书">
19
+ <img src="https://img.shields.io/badge/%E9%92%89%E9%92%89-1677FF?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0OCA0OCI%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTM3LjA1IDIyLjc4M2MtNi43NTgtNS4yMTYtMTQuMzc4LTEyLjEyOC0yMi43My0xOS41MzgtLjY1NS0uNTg1LTEuMjQyLS4zNTQtMS41MzYuNDItMS44OCA0Ljk3My0uMDU4IDkuMzg2IDIuODg5IDExLjkzMnM3LjM2OCA0LjkxMiAxMC4wNTggNi4xNTVjLjEwNS4wNDkuMDEzLjIwMy0uMDkzLjE2My00Ljk1My0yLjE4Mi04LjM5Ny0zLjc2NS0xMy4wNy03LjM2OC0uNDk3LS4zODgtMS4wMS0uMjQyLTEuMDcuNTIxLS4zODQgNC43NDggMi42NTcgOC40ODMgNi4wNTggOS43NDUgMi4xLjc4MSA0LjM5OCAxLjIxMiA2LjUzIDEuNDc0LjEwOS4wMTUuMDg0LjE3OC0uMDI3LjE3OC0yLjc0Ny4wMS02LjA1OC0uNjU0LTguOTM1LTEuNzUxLS42MDYtLjIzMy0uODE4LjI1LS43MjIuNjMzLjQ5MSAyLjAwOCAyLjk3NCA1LjA3NiA2LjkyNiA1LjczYTEyIDEyIDAgMCAwIDIuMjI4LjExNWMuMTY0IDAgLjIwOC4wODkuMTU0LjIxN3EtMi42ODUgNC42LTIuODAzIDQuNzk3Yy0uMDkxLjE1Mi0uMDM2LjI3NS4xNTYuMjc1aDMuNTQzYy4xNjQgMCAuMjY0LjEwNi4xOC4yNDZsLTQuOTU4IDguMTk2Yy0uMTkxLjMyOC4wMzUuNTY1LjM5NS4zMDFzMTUuMjEyLTExLjEzMyAxNS42MzYtMTEuNDQ4Yy4xOTUtLjE0Mi4xNDgtLjMyNy0uMTI0LS4zMjdoLTMuMThjLS4yMDYgMC0uMjUyLS4xNC0uMTExLS4yOC4xNC0uMTQxIDMuNjAyLTMuNTk0IDQuODM3LTQuODg4IDEuMjgzLTEuMzUgMS45MzgtMy44MjUtLjIzMS01LjQ5OCIvPjwvc3ZnPg%3D%3D" alt="钉钉">
20
+ <img src="https://img.shields.io/badge/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1-3370FF?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIuMzUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTTE3LjcgMTQuNWMxLjA1LTEuMTIgMS42NS0yLjUyIDEuNjUtNC4wMyAwLTMuODItMy41OC02LjkyLTgtNi45MnMtOCAzLjEtOCA2LjkyIDMuNTggNi45MiA4IDYuOTJjMS4xNyAwIDIuMjgtLjIyIDMuMjgtLjYyIi8%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE2LjEgMTUuMTVjLjctLjcgMS44My0uNyAyLjUzIDBzLjcgMS44MyAwIDIuNTMtMS44My43LTIuNTMgMC0uNy0xLjgzIDAtMi41M1pNMTkuMjUgMTMuNDVhMS4zNiAxLjM2IDAgMSAxIDEuOTIgMS45MiAxLjM2IDEuMzYgMCAwIDEtMS45Mi0xLjkyWk0xOS41NSAxOC4wNWExLjE2IDEuMTYgMCAxIDEgMS42NCAxLjY0IDEuMTYgMS4xNiAwIDAgMS0xLjY0LTEuNjRaTTE1LjI1IDE4Ljc1YS45Mi45MiAwIDEgMSAxLjMgMS4zLjkyLjkyIDAgMCAxLTEuMy0xLjNaIi8%2BPC9zdmc%2B" alt="企业微信">
21
+ <img src="https://img.shields.io/badge/QQ-1EBAFC?logo=qq&amp;logoColor=white" alt="QQ">
22
+ <img src="https://img.shields.io/badge/Slack-4A154B?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTYgMTVhMiAyIDAgMSAxLTItMmgydjJabTEgMGEyIDIgMCAxIDEgNCAwdjVhMiAyIDAgMSAxLTQgMHYtNVptMi04YTIgMiAwIDEgMSAyLTJ2Mkg5Wm0wIDFhMiAyIDAgMSAxIDAgNEg0YTIgMiAwIDEgMSAwLTRoNVptOCAyYTIgMiAwIDEgMSAyIDJoLTJ2LTJabS0xIDBhMiAyIDAgMSAxLTQgMFY1YTIgMiAwIDEgMSA0IDB2NVptLTIgOGEyIDIgMCAxIDEtMiAydi0yaDJabTAtMWEyIDIgMCAxIDEgMC00aDVhMiAyIDAgMSAxIDAgNGgtNVoiLz48L3N2Zz4%3D" alt="Slack">
23
+ <img src="https://img.shields.io/badge/Telegram-26A5E4?logo=telegram&amp;logoColor=white" alt="Telegram">
24
+ <img src="https://img.shields.io/badge/Discord-5865F2?logo=discord&amp;logoColor=white" alt="Discord">
25
+ <img src="https://img.shields.io/badge/WhatsApp-25D366?logo=whatsapp&amp;logoColor=white" alt="WhatsApp">
12
26
  </p>
13
27
 
14
28
  <p><a href="README.md">简体中文</a> · <strong>English</strong></p>
@@ -18,7 +32,7 @@
18
32
 
19
33
  ## Introduction
20
34
 
21
- Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest, or entering existing bot credentials. One plugin and one settings entry provide unified management for Feishu, WeChat, DingTalk, WeCom, QQ, Slack, Telegram, Discord, and WhatsApp bots. It also supports switching workspaces and rebinding sessions.
35
+ Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest, or entering existing bot credentials. One plugin and one settings entry provide unified management for Feishu, WeChat, DingTalk, WeCom, QQ, Slack, Telegram, Discord, and WhatsApp. **Every channel supports multiple bots**, each with independent connection state, workspace, and session bindings. It also supports switching workspaces and rebinding sessions.
22
36
 
23
37
  ## Interface
24
38
 
@@ -26,15 +40,17 @@ Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest
26
40
 
27
41
  ## Built-in channels
28
42
 
29
- - Feishu: create a bot by QR code or bind an existing bot with App ID + App Secret, then send and receive messages over a persistent connection.
30
- - WeChat: bind a WeChat bot by scanning a QR code, then send and receive messages through Tencent iLink long polling.
31
- - DingTalk: create a bot by QR code or bind an existing bot with Client ID + Client Secret, receive messages through DingTalk Stream, and stream Harness replies through AI Cards.
32
- - WeCom: create an intelligent bot by QR code or bind an existing bot with Bot ID + Secret, receive messages over the official WebSocket connection, and natively show a thinking state, tool progress, and streaming replies.
33
- - QQ: create a bot by QR code or bind an existing bot with AppID + AppSecret, receive messages over a WebSocket connection, stream private-chat replies with a native typing indicator, and reply in groups when mentioned.
34
- - Slack: use the bundled App Manifest to create and configure an app, enter its Bot Token (`xoxb-`) and App Token (`xapp-`), receive events over Socket Mode, reply directly in DMs and only when mentioned in channels, and prefer Slack's native streaming-message API for Harness output.
35
- - Telegram: bind a BotFather-created bot with its Bot Token, receive messages through Bot API long polling, reply directly in private chats, require a mention or reply in groups, and stream Harness output by editing the reply.
36
- - Discord: bind a Developer Portal bot with its Bot Token, receive events through Gateway v10, reply directly in DMs, require a mention in server channels, and stream Harness output by editing the reply.
37
- - WhatsApp: scan a QR code to link a WhatsApp device, receive messages over WhatsApp Web, show a native read receipt and typing indicator, and then send the final Harness answer.
43
+ | Channel | Setup | Messaging and replies |
44
+ | --- | --- | --- |
45
+ | Feishu | Create a bot by QR code, or bind one with App ID + App Secret | Persistent connection for incoming messages; streaming cards show thinking, tool progress, and replies |
46
+ | WeChat | Scan a QR code to bind a WeChat bot | Tencent iLink long polling for sending and receiving messages |
47
+ | DingTalk | Create a bot by QR code, or bind one with Client ID + Client Secret | DingTalk Stream connection; streaming replies through AI Cards |
48
+ | WeCom | Create an intelligent bot by QR code, or bind one with Bot ID + Secret | Official WebSocket connection; native thinking state, tool progress, and streaming replies |
49
+ | QQ | Create a bot with mobile QQ QR scanning, or bind one with AppID + AppSecret | WebSocket connection; native typing and streaming replies in private chats, replies when mentioned in groups |
50
+ | Slack | Create an app from the bundled App Manifest, then enter a Bot Token (`xoxb-`) and App Token (`xapp-`) | Socket Mode connection; direct DM replies, mention-only channel replies, and preferred native streaming API |
51
+ | Telegram | Enter a Bot Token generated by @BotFather | Bot API long polling; direct private replies, mention-or-reply group handling, and streaming through message edits |
52
+ | Discord | Enter a Bot Token generated in the Developer Portal | Gateway v10 connection; direct DM replies, mention-only server replies, and streaming through message edits |
53
+ | WhatsApp | Scan a QR code with mobile WhatsApp to link a device | WhatsApp Web connection; read receipt and typing indicator followed by the final answer |
38
54
 
39
55
  Other IM platforms can be added through the same channel-adapter structure.
40
56
 
@@ -42,52 +58,61 @@ All nine built-in channels can send JPEG, PNG, and WebP images, plus GIFs sent a
42
58
 
43
59
  ## Installation
44
60
 
45
- ```sh
46
- npx -y github:xmanrui/dsh-im install
47
- ```
48
-
49
- Alternatively, install it directly from npm:
61
+ Install the published stable release from npm (recommended):
50
62
 
51
63
  ```sh
52
- dsh plugin --profile web add @xmanrui/dsh-im
64
+ dsh plugin --profile web add -w @xmanrui/dsh-im
53
65
  ```
54
66
 
55
- Restart `dsh web`, then open **Settings → Plugins → IM Bot**. The installer replaces directly installed `dsh-feishu`, `dsh-weixin`, and `dsh-dingtalk` entries in the profile with `dsh-im` without deleting channel data.
56
-
57
- Feishu, QQ, DingTalk, and WeCom each provide two entry points. The blue **QR access** action uses the platform QR flow; the key-marked, outlined **Manual access** action immediately to its right connects an existing bot application. Feishu and QQ use App ID + App Secret and AppID + AppSecret respectively, DingTalk uses Client ID + Client Secret, and WeCom uses Bot ID + Secret. Secrets are sent only to the local Harness Host and stored through its protected credential provider; status responses and bot lists never return them.
58
-
59
- Telegram and Discord do not provide an official QR flow for creating bots, so their pages expose only the key-marked **Manual access** action and request a Bot Token. Generate the Telegram token with BotFather; an existing webhook must be removed by its current service before Bot API long polling can receive updates. Generate the Discord token on the Developer Portal's Bot page, invite the bot to the target server, and grant View Channel, Send Messages, and Read Message History. The plugin reads DMs and server messages that explicitly mention the bot, so it does not request the privileged Message Content intent.
67
+ Restart `dsh web`, then open **Settings → Plugins → IM Bot**.
60
68
 
61
- Slack provides Manifest-assisted creation with dual-Token access. Choose **Start setup**, copy the bundled App Manifest, open Slack's create page, and select **From a manifest**. Under **Basic Information → App-Level Tokens**, generate an App Token with `connections:write`; then install the app to the workspace under **OAuth & Permissions** to obtain the Bot Token. The plugin validates both Tokens before opening Socket Mode. Slack has no official QR-based bot-creation flow. Image access uses the Manifest's `files:read` scope; Slack Apps installed before this upgrade must be reinstalled or reauthorized to receive it. Both Tokens are sent only to the local Harness Host and stored through its protected credential provider; status responses and bot lists never return them.
69
+ To try the latest code before it is published to npm, use the GitHub-source installer instead:
62
70
 
63
- WhatsApp exposes only **QR access**. On the phone, open **WhatsApp → Settings → Linked devices → Link a device**, then scan the QR code shown by Harness. No Meta console, Cloud API, Webhook, Phone Number ID, or Access Token is required. Linked-device state stays under `~/.dsh/integrations/dsh-whatsapp/auth`; the browser receives only the one-time QR code and redacted account status. Personal accounts can use WhatsApp's **Message yourself** chat directly; the plugin suppresses only its own exact reply message IDs to prevent reply loops.
64
-
65
- Use a dedicated WhatsApp number for the bot when possible. Linking a personal account makes DMs sent to that account eligible Harness input; group messages trigger only when they mention or reply to the linked account. Limit the number to trusted contacts, and remove the device from both Harness and the phone's **Linked devices** list when it is no longer used.
66
-
67
- For DingTalk QR binding, scan with an account that belongs to an enterprise or organization and can create bots, then choose **Create a new bot** on the authorization page. If DingTalk reports that the account has not joined an organization, create one or switch to an account that has, then scan again. There is no second local sender-approval flow: the bot's DingTalk visibility is its inbound access scope, so restrict it to trusted organizations, groups, or members. Image downloads add no separate scope, but they depend on the bot's existing **企业内机器人发送消息权限** permission. A manually bound app without that permission can receive an image callback but cannot exchange it for a temporary download URL.
68
-
69
- For WeCom QR binding, scan with an account that belongs to an enterprise and can create or manage bots, then confirm creation of the intelligent bot in the mobile app. This creates a WeCom intelligent bot; it does not sign the plugin into a personal WeChat account. For both QR and credential binding, restrict the bot's WeCom visibility to trusted enterprise members and group chats.
70
-
71
- QQ QR binding uses Tencent's official QQBot v2 flow. Tencent's default authorization page labels the integration as a third-party bot. Scanning creates a QQ Open Platform bot; it does not give the plugin direct control of a personal QQ account. QR binding accepts only the scanner's messages. Manual credentials cannot identify a scanner, so the bot's QQ Open Platform visibility becomes its inbound access scope.
71
+ ```sh
72
+ npx -y github:xmanrui/dsh-im install
73
+ ```
72
74
 
73
- Feishu QR binding records the scanner as an allowed user. Manual credentials cannot identify a scanner, so the Feishu application's visibility becomes its inbound access scope. Restrict the application to trusted tenants, groups, or members. Reading user-sent images requires the tenant scope `im:message:readonly`. Newly QR-created apps request it automatically; apps created before this upgrade must add the scope in the Feishu developer console, publish a version, and complete any required administrator approval.
75
+ A GitHub-source installation fetches and builds a Git dependency directly. With pnpm 10 or newer, the profile may first need an `allowBuilds` entry in `pnpm-workspace.yaml`. Most users should prefer the stable npm release.
74
76
 
75
- Each bot maintains an independent Harness workspace. A newly connected bot records the Harness Host process's current working directory (`process.cwd()`) as its default; the path is persisted and does not change when the Host is later restarted from another directory. Every bot card shows the current path and lets it be edited.
77
+ After installation, follow the built-in instructions on each channel page to scan a QR code or enter credentials. Secrets and Tokens are sent only to the local Harness Host and stored through its protected credential provider; status responses and bot lists never return them.
76
78
 
77
- When a channel does not explicitly configure `agentPreset`, each new IM session inherits the Harness-wide `agent-presets.default`. Harness reads that default whenever it creates a session, so changing the setting affects only sessions created afterwards; existing sessions and sessions bound with `/session` keep their own preset. An explicit channel `agentPreset` always takes precedence for newly created sessions.
79
+ | Default behavior | Description |
80
+ | --- | --- |
81
+ | Bot workspace | Each bot stores its workspace independently. New bots start with the Host's current working directory, which can later be changed from the bot card. |
82
+ | Agent Preset | New Sessions inherit Harness's `agent-presets.default` unless the channel explicitly overrides it. Later changes do not affect existing Sessions. |
78
83
 
79
84
  ## Bot commands
80
85
 
81
86
  | Command | Description |
82
87
  | --- | --- |
88
+ | `/help` | Show the commands and usage supported by the bot. |
89
+ | `/new` | Unbind the current chat so its next ordinary message starts a new Harness Session. |
90
+ | `/status` | Check the connection between the current bot and DeepSeek Harness. |
91
+ | `/models` | List every currently configured model with a number. |
92
+ | `/model` | Show the model used by the Session bound to this chat. |
93
+ | `/model <number or provider/model-id>` | Switch the model for the Session bound to this chat. |
94
+ | `/stop` | Immediately stop this chat's running task while preserving work that has not started. |
95
+ | `/steer <additional instruction>` | Inject an additional instruction into this chat's running task. |
83
96
  | `/compact` | Immediately compact older context in the Session bound to the current chat. |
84
97
  | `/workspace <absolute workspace path>` | Switch the current bot's Harness workspace. |
85
98
  | `/workspacelist` | List workspace absolute paths that still exist on the current Harness Host. |
86
99
  | `/sessionlist [workspace number or absolute path]` | List every registered session ID and title in the selected workspace; omit the argument to use the current workspace. |
87
100
  | `/session <Session ID>` | Bind the current chat to an existing Harness session. |
101
+ | Interactive question | Reply with an option number, option label, or custom text; separate multiple choices with commas. |
102
+ | Remote approval | Reply with `批准` / `拒绝` / `同意` / `不同意` / `yes` / `no`. |
103
+
104
+ Example: send `/models`, then `/model 2` to switch to the second model in the list. Other examples: `/help`, `/new`, `/status`, `/model deepseek-official/deepseek-v4-pro`, `/steer inspect only the configuration file`, `/stop`, `/compact`, `/workspace /Users/alice/projects/my-app`, `/sessionlist 2`, `/sessionlist /Users/alice/projects/my-app`, or `/session session-id`
88
105
 
89
- Examples: `/compact`, `/workspace /Users/alice/projects/my-app`, `/sessionlist 2`, `/sessionlist /Users/alice/projects/my-app`, or `/session session-id`
106
+ ### Command details
90
107
 
108
+ - `/help` takes no arguments and never creates a Session. It returns the complete command list supported by the current bot.
109
+ - `/status` takes no arguments, never prompts the model, and does not change the Session binding. It confirms that the current bot can reach DeepSeek Harness.
110
+ - `/new` only removes the current chat's saved dsh-im Session binding; it never deletes, empties, or archives the old Session. The next ordinary message creates and binds a new Session in the current workspace. If a task is running or waiting for a question or approval, finish the interaction or use `/stop` before `/new`.
111
+ - `/models` takes no arguments and never creates a Session. It assigns a number to every currently configured Harness model and also shows its stable, copyable `provider/model-id`. If one provider fails, models from the remaining providers are still shown.
112
+ - Bare `/model` only displays the current Session model. A model can be selected by the number or exact full ID returned by `/models`, for example `/model 2`. When the chat has no Session yet, a valid switch creates and binds a blank Session without prompting the model. The switch affects only that Session; Harness also attempts to save it as the default for future Sessions, while other existing Sessions remain unchanged.
113
+ - A model cannot be switched while a task is running or waiting for an approval or question answer. Wait for it to finish or use `/stop` first. A Session containing images cannot switch to a model that does not accept image input.
114
+ - `/stop` and `/steer` control only a running task started by this chat. Even when multiple chats bind the same Session, they do not intentionally control another chat's task. `/stop` does not delete the Session or its history, preserves queued work that has not started, and is safe to repeat.
115
+ - `/steer` accepts text only, including multiple lines. It neither creates another Session nor starts a second task. Send an ordinary message when no task is running; while an approval or question is pending, answer it first or use `/stop`.
91
116
  - `/compact` acts only on the Harness Session already bound to the current chat and is never sent to the model. The bot reports the applicable status when the chat has no Session yet, the Session is generating a reply, or there is no compactable history.
92
117
  - The path must be an existing absolute directory. The bot returns an actionable error and the correct usage when validation fails.
93
118
  - `/workspacelist` takes no arguments. It combines the Harness global registry with the current bot's path. When that current path still exists and is safe to display, it appears first and is marked as current. Any listed path can be copied directly into `/workspace`.
@@ -103,6 +128,15 @@ Examples: `/compact`, `/workspace /Users/alice/projects/my-app`, `/sessionlist 2
103
128
  - A successful switch clears only the current bot's old Harness session mappings and does not affect other bots.
104
129
  - The new workspace applies to subsequent messages; a reply that has already started generating is allowed to finish.
105
130
 
131
+ ## Other features
132
+
133
+ - **Image understanding**: all nine built-in channels can send JPEG, PNG, WebP, and GIF files sent as images to Harness, with an optional text description. Each image is limited to 5 MB, and all images in one message are limited to 20 MB in total.
134
+ - **Switch workspaces from a bot card**: every bot card on the settings page shows its current Harness workspace. Enter an existing absolute directory path directly or open the directory picker. Switching clears only that bot's old chat mappings; it never deletes, empties, or archives old Sessions. Replies already in progress may finish, while later messages use the new workspace.
135
+ - **Check the connection and send a test message**: when a bot is online, clicking **Check connection** verifies the platform connection and sends a “DeepSeek Harness connection test succeeded” message to the bot's most recently remembered direct conversation; WhatsApp uses the account's self-chat. The test neither creates a Harness Session nor invokes the model. The bot must have received at least one direct message before it has a remembered test target; otherwise the page reports that no test conversation is available yet.
136
+ - **Retry a connection or remove an integration**: when a bot is offline, its card action changes to **Retry connection**. Use **Remove integration** when the bot is no longer needed. Each action affects only the selected bot and leaves other bots and channels unchanged.
137
+ - **Manage multiple bots independently**: a channel can have multiple connected bots. Credentials, connection state, workspace, and chat-to-Session mappings are kept separately for every bot, so card actions do not affect sibling bots.
138
+ - **Streaming replies and progress**: the plugin uses each platform's available capabilities to show thinking state, tool progress, and incremental answers. Platforms without a native streaming API complete replies through message edits, card updates, or a final message.
139
+
106
140
  ## Design
107
141
 
108
142
  - Registers a single **IM Bot** settings page in Harness.
package/README.md CHANGED
@@ -3,13 +3,27 @@
3
3
  ---
4
4
 
5
5
  <div align="center">
6
- <p><strong>让聊天机器人轻松接入 DeepSeek Harness</strong></p>
7
- <p><strong>Connect IM bots to DeepSeek Harness with ease</strong></p>
6
+ <p><strong>让 DeepSeek Harness 触手可及</strong></p>
7
+ <p><strong>DeepSeek Harness, always within reach</strong></p>
8
8
 
9
9
  <p>
10
+ <img src="https://dsh-im-random-badge.xmanrui-dsh-im.workers.dev" alt="滑动变祖器:今天是梁子或今天是梁圣(随机)">
10
11
  <a href="LICENSE"><img src="https://img.shields.io/github/license/xmanrui/dsh-im" alt="MIT 许可证"></a>
11
12
  <img src="https://img.shields.io/badge/agent-DeepSeek%20Harness-5865f2" alt="DeepSeek Harness">
12
- <img src="https://dsh-im-random-badge.xmanrui-dsh-im.workers.dev" alt="滑动变祖器:今天是梁子或今天是梁圣(随机)">
13
+ <a href="https://dshfind.com/zh/plugins/xmanrui/dsh-im?ref=badge"><img src="https://dshfind.com/api/badge/xmanrui/dsh-im?lang=zh" alt="dshfind"></a>
14
+ <a href="https://dshfind.com/zh/plugins/xmanrui/dsh-im"><img src="https://img.shields.io/badge/dshfind-%E5%88%86%E7%B1%BB%E7%AC%AC%E4%B8%80-d97706" alt="dshfind: 分类第一"></a>
15
+ </p>
16
+
17
+ <p>
18
+ <img src="https://img.shields.io/badge/%E5%BE%AE%E4%BF%A1-07C160?logo=wechat&amp;logoColor=white" alt="微信">
19
+ <img src="https://img.shields.io/badge/%E9%A3%9E%E4%B9%A6-3370FF?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTcuMiA0LjVoNy42YzEuMiAwIDIuMS41NSAyLjcgMS41OCAxLjA1IDEuOCAxLjU1IDMuNDUgMS41OCA0Ljk1LTIuMDQtLjYyLTQuMi0uMTUtNi4yMiAxLjQ1QzExLjMgOS43IDkuNDIgNy4wNCA3LjIgNC41WiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0xMC44IDEzLjU1YzMuMy0yLjkzIDUuNzItNC4yNCA5LjQ3LTIuNTItMS4yIDEuNDUtMi4yNyA0LjE4LTMuODYgNS40My0xLjY3IDEuMzEtMy45LjUtNS42MS0uNjR2LTIuMjdaIi8%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTQuNCA4LjM1YzMuNDcgMy42MSA3LjI1IDYuMSAxMC4zMyA1LjcgMS4wNi0uMTQgMi4yLS43MiAzLjQtMS43Mi0xLjA0IDIuNjUtMi42IDQuOC01LjA2IDYtMi40NiAxLjItNS41Ni41Mi03LjQyLS43MkEyLjc2IDIuNzYgMCAwIDEgNC40IDE1LjNWOC4zNVoiLz48L3N2Zz4%3D" alt="飞书">
20
+ <img src="https://img.shields.io/badge/%E9%92%89%E9%92%89-1677FF?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0OCA0OCI%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTM3LjA1IDIyLjc4M2MtNi43NTgtNS4yMTYtMTQuMzc4LTEyLjEyOC0yMi43My0xOS41MzgtLjY1NS0uNTg1LTEuMjQyLS4zNTQtMS41MzYuNDItMS44OCA0Ljk3My0uMDU4IDkuMzg2IDIuODg5IDExLjkzMnM3LjM2OCA0LjkxMiAxMC4wNTggNi4xNTVjLjEwNS4wNDkuMDEzLjIwMy0uMDkzLjE2My00Ljk1My0yLjE4Mi04LjM5Ny0zLjc2NS0xMy4wNy03LjM2OC0uNDk3LS4zODgtMS4wMS0uMjQyLTEuMDcuNTIxLS4zODQgNC43NDggMi42NTcgOC40ODMgNi4wNTggOS43NDUgMi4xLjc4MSA0LjM5OCAxLjIxMiA2LjUzIDEuNDc0LjEwOS4wMTUuMDg0LjE3OC0uMDI3LjE3OC0yLjc0Ny4wMS02LjA1OC0uNjU0LTguOTM1LTEuNzUxLS42MDYtLjIzMy0uODE4LjI1LS43MjIuNjMzLjQ5MSAyLjAwOCAyLjk3NCA1LjA3NiA2LjkyNiA1LjczYTEyIDEyIDAgMCAwIDIuMjI4LjExNWMuMTY0IDAgLjIwOC4wODkuMTU0LjIxN3EtMi42ODUgNC42LTIuODAzIDQuNzk3Yy0uMDkxLjE1Mi0uMDM2LjI3NS4xNTYuMjc1aDMuNTQzYy4xNjQgMCAuMjY0LjEwNi4xOC4yNDZsLTQuOTU4IDguMTk2Yy0uMTkxLjMyOC4wMzUuNTY1LjM5NS4zMDFzMTUuMjEyLTExLjEzMyAxNS42MzYtMTEuNDQ4Yy4xOTUtLjE0Mi4xNDgtLjMyNy0uMTI0LS4zMjdoLTMuMThjLS4yMDYgMC0uMjUyLS4xNC0uMTExLS4yOC4xNC0uMTQxIDMuNjAyLTMuNTk0IDQuODM3LTQuODg4IDEuMjgzLTEuMzUgMS45MzgtMy44MjUtLjIzMS01LjQ5OCIvPjwvc3ZnPg%3D%3D" alt="钉钉">
21
+ <img src="https://img.shields.io/badge/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1-3370FF?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIuMzUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTTE3LjcgMTQuNWMxLjA1LTEuMTIgMS42NS0yLjUyIDEuNjUtNC4wMyAwLTMuODItMy41OC02LjkyLTgtNi45MnMtOCAzLjEtOCA2LjkyIDMuNTggNi45MiA4IDYuOTJjMS4xNyAwIDIuMjgtLjIyIDMuMjgtLjYyIi8%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE2LjEgMTUuMTVjLjctLjcgMS44My0uNyAyLjUzIDBzLjcgMS44MyAwIDIuNTMtMS44My43LTIuNTMgMC0uNy0xLjgzIDAtMi41M1pNMTkuMjUgMTMuNDVhMS4zNiAxLjM2IDAgMSAxIDEuOTIgMS45MiAxLjM2IDEuMzYgMCAwIDEtMS45Mi0xLjkyWk0xOS41NSAxOC4wNWExLjE2IDEuMTYgMCAxIDEgMS42NCAxLjY0IDEuMTYgMS4xNiAwIDAgMS0xLjY0LTEuNjRaTTE1LjI1IDE4Ljc1YS45Mi45MiAwIDEgMSAxLjMgMS4zLjkyLjkyIDAgMCAxLTEuMy0xLjNaIi8%2BPC9zdmc%2B" alt="企业微信">
22
+ <img src="https://img.shields.io/badge/QQ-1EBAFC?logo=qq&amp;logoColor=white" alt="QQ">
23
+ <img src="https://img.shields.io/badge/Slack-4A154B?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI%2BPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTYgMTVhMiAyIDAgMSAxLTItMmgydjJabTEgMGEyIDIgMCAxIDEgNCAwdjVhMiAyIDAgMSAxLTQgMHYtNVptMi04YTIgMiAwIDEgMSAyLTJ2Mkg5Wm0wIDFhMiAyIDAgMSAxIDAgNEg0YTIgMiAwIDEgMSAwLTRoNVptOCAyYTIgMiAwIDEgMSAyIDJoLTJ2LTJabS0xIDBhMiAyIDAgMSAxLTQgMFY1YTIgMiAwIDEgMSA0IDB2NVptLTIgOGEyIDIgMCAxIDEtMiAydi0yaDJabTAtMWEyIDIgMCAxIDEgMC00aDVhMiAyIDAgMSAxIDAgNGgtNVoiLz48L3N2Zz4%3D" alt="Slack">
24
+ <img src="https://img.shields.io/badge/Telegram-26A5E4?logo=telegram&amp;logoColor=white" alt="Telegram">
25
+ <img src="https://img.shields.io/badge/Discord-5865F2?logo=discord&amp;logoColor=white" alt="Discord">
26
+ <img src="https://img.shields.io/badge/WhatsApp-25D366?logo=whatsapp&amp;logoColor=white" alt="WhatsApp">
13
27
  </p>
14
28
 
15
29
  <p><strong>简体中文</strong> · <a href="README.en.md">English</a></p>
@@ -19,9 +33,9 @@
19
33
 
20
34
  ## 简介
21
35
 
22
- 通过扫码、App Manifest 或已有机器人凭据把 IM 机器人接入 DeepSeek Harness。一个插件、一个设置入口,统一管理飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord 和 WhatsApp 机器人。支持切换工作区和重新绑定会话。
36
+ 通过扫码、App Manifest 或已有机器人凭据把 IM 机器人接入 DeepSeek Harness。一个插件、一个设置入口,统一管理飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord 和 WhatsApp。**每个渠道都支持接入多个机器人**,各机器人的连接状态、工作区和会话绑定彼此独立。支持切换工作区和重新绑定会话。
23
37
 
24
- Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest, or entering existing bot credentials. One plugin and one settings entry provide unified management for Feishu, WeChat, DingTalk, WeCom, QQ, Slack, Telegram, Discord, and WhatsApp bots. It also supports switching workspaces and rebinding sessions.
38
+ Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest, or entering existing bot credentials. One plugin and one settings entry provide unified management for Feishu, WeChat, DingTalk, WeCom, QQ, Slack, Telegram, Discord, and WhatsApp. **Every channel supports multiple bots**, each with independent connection state, workspace, and session bindings. It also supports switching workspaces and rebinding sessions.
25
39
 
26
40
  ## 界面
27
41
 
@@ -29,15 +43,17 @@ Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest
29
43
 
30
44
  ## 当前内置渠道
31
45
 
32
- - 飞书:扫码创建机器人,或使用已有 App ID + App Secret 绑定机器人,使用长连接收发消息;
33
- - 微信:扫码绑定微信机器人,使用腾讯 iLink 长轮询收发消息;
34
- - 钉钉:扫码创建机器人,或使用已有 Client ID + Client Secret 绑定机器人,使用钉钉 Stream 长连接收消息,并通过 AI Card 流式显示 Harness 回答。
35
- - 企业微信:使用企业微信 App 扫码创建智能机器人,或使用已有 Bot ID + Secret 绑定机器人,通过官方 WebSocket 长连接收消息,原生显示“正在思考中”、工具执行进度和流式回答。
36
- - QQ:使用手机 QQ 扫码创建机器人,或使用已有 AppID + AppSecret 绑定机器人,通过 WebSocket 长连接收消息;私聊支持原生“正在输入”和流式回答,群聊在机器人被 @ 后回复。
37
- - Slack:使用预置 App Manifest 辅助创建并配置应用,再填写 Bot Token(`xoxb-`)与 App Token(`xapp-`),通过 Socket Mode 长连接收消息;私聊直接回复,频道仅在机器人被 @ 时响应,并优先使用 Slack 官方流式消息 API 显示 Harness 回答。
38
- - Telegram:使用 @BotFather 生成的 Bot Token 接入机器人,通过官方 Bot API 长轮询收消息;私聊直接回复,群聊仅在机器人被提及或收到对机器人消息的回复时响应,并通过编辑消息流式显示 Harness 回答。
39
- - Discord:使用 Developer Portal 生成的 Bot Token 接入机器人,通过 Gateway v10 长连接收消息;私信直接回复,服务器频道仅在机器人被提及时响应,并通过编辑消息流式显示 Harness 回答。
40
- - WhatsApp:使用手机 WhatsApp 扫码关联设备,通过 WhatsApp Web 长连接收消息;收到消息后显示已读和“正在输入”,再发送 Harness 的最终回答。
46
+ | 渠道 | 接入方式 | 消息与回复 |
47
+ | --- | --- | --- |
48
+ | 飞书 | 扫码创建机器人,或使用 App ID + App Secret 手动绑定 | 长连接接收消息;通过飞书流式卡片显示思考、工具进度和回答 |
49
+ | 微信 | 使用微信扫码绑定机器人 | 腾讯 iLink 长轮询收发消息 |
50
+ | 钉钉 | 扫码创建机器人,或使用 Client ID + Client Secret 手动绑定 | 钉钉 Stream 长连接;通过 AI Card 流式显示回答 |
51
+ | 企业微信 | 使用企业微信 App 扫码创建智能机器人,或使用 Bot ID + Secret 手动绑定 | 官方 WebSocket 长连接;原生显示“正在思考中”、工具执行进度和流式回答 |
52
+ | QQ | 使用手机 QQ 扫码创建机器人,或使用 AppID + AppSecret 手动绑定 | WebSocket 长连接;私聊显示“正在输入”和流式回答,群聊被 @ 后回复 |
53
+ | Slack | 使用预置 App Manifest 创建应用,再填写 Bot Token(`xoxb-`)和 App Token(`xapp-`) | Socket Mode 长连接;私聊直接回复,频道被 @ 后响应,优先使用官方流式消息 API |
54
+ | Telegram | 使用 @BotFather 生成的 Bot Token | Bot API 长轮询;私聊直接回复,群聊被提及或收到对机器人消息的回复时响应,通过编辑消息流式显示回答 |
55
+ | Discord | 使用 Developer Portal 生成的 Bot Token | Gateway v10 长连接;私信直接回复,服务器频道被提及时响应,通过编辑消息流式显示回答 |
56
+ | WhatsApp | 使用手机 WhatsApp 扫码关联设备 | WhatsApp Web 长连接;显示已读和“正在输入”,再发送最终回答 |
41
57
 
42
58
  其他 IM 平台可继续按同一渠道适配器结构接入。
43
59
 
@@ -45,52 +61,61 @@ Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest
45
61
 
46
62
  ## 安装
47
63
 
48
- ```sh
49
- npx -y github:xmanrui/dsh-im install
50
- ```
51
-
52
- 也可以直接从 npm 安装:
64
+ 推荐从 npm 安装已发布的稳定版本:
53
65
 
54
66
  ```sh
55
- dsh plugin --profile web add @xmanrui/dsh-im
67
+ dsh plugin --profile web add -w @xmanrui/dsh-im
56
68
  ```
57
69
 
58
- 重启 `dsh web`,然后打开「设置 → 插件 → IM机器人」。安装器会用 `dsh-im` 替换 profile 中直接安装的 `dsh-feishu`、`dsh-weixin` 和 `dsh-dingtalk`,但不删除任何渠道数据;原有渠道凭据和扫码绑定会继续使用。
59
-
60
- 飞书、QQ、钉钉和企业微信页面都提供两种入口:带二维码图标的蓝色「扫码接入机器人」按钮走平台官方扫码流程,右侧带钥匙图标的白色描边「手动接入」按钮连接已经创建的机器人应用。飞书和 QQ 分别填写 App ID + App Secret、AppID + AppSecret;钉钉填写官方 Client ID + Client Secret;企业微信填写官方 Bot ID + Secret。Secret 只提交给本机 Harness Host,并写入受保护的凭据存储;状态接口和机器人列表不会回传 Secret。
61
-
62
- Telegram 和 Discord 没有官方扫码创建机器人流程,因此页面只显示带钥匙图标的「手动接入」入口,并只要求 Bot Token。Telegram Token 由 @BotFather 生成;若该机器人已经配置 Webhook,需要先由原服务移除 Webhook,Bot API 长轮询才能接管消息。Discord Token 来自 Developer Portal 的 Bot 页面;还需把机器人邀请到目标服务器,并授予查看频道、发送消息和读取历史消息权限。本插件只读取私信和明确提及机器人的服务器消息,因此不要求 Message Content 特权 Intent。
70
+ 重启 `dsh web`,然后打开「设置 → 插件 → IM机器人」。
63
71
 
64
- Slack 页面提供 Manifest 辅助创建与双 Token 接入。点击「开始接入」,复制页面提供的 App Manifest,再打开 Slack 创建页并选择 **From a manifest**;创建后在 **Basic Information → App-Level Tokens** 生成包含 `connections:write` 的 App Token,并在 **OAuth & Permissions** 将应用安装到工作区以取得 Bot Token。插件会验证两个 Token,再通过 Socket Mode 建立连接;Slack 没有官方扫码创建机器人流程。图片读取使用 Manifest 中的 `files:read`;升级前已安装的 Slack App 需要重新安装或重新授权,才能获得该权限。两个 Token 只提交到本机 Harness Host 并写入受保护的凭据存储,状态接口和机器人列表不会回传 Token。
72
+ 如需试用尚未发布到 npm 的最新代码,可以改用 GitHub 源安装器:
65
73
 
66
- WhatsApp 页面只显示「扫码接入机器人」。打开手机 WhatsApp 的「设置 → 已关联设备 → 关联设备」,扫描 Harness 页面中的二维码即可,不需要 Meta 控制台、Cloud API、Webhook、Phone Number ID 或 Access Token。关联设备状态只保存在本机 `~/.dsh/integrations/dsh-whatsapp/auth`,浏览器只会收到一次性二维码和脱敏后的账号状态。个人账号可在 WhatsApp 的「给自己发消息」会话中直接使用;插件按消息 ID 过滤自己的回复,避免形成回复循环。
67
-
68
- 建议为机器人准备独立 WhatsApp 号码。关联个人常用账号会让发给该账号的私聊消息成为 Harness 输入;群聊只有明确提及该账号或回复该账号消息时才会触发。请只把机器人号码开放给可信联系人,并在不再使用时同时从 Harness 和手机「已关联设备」中移除。
69
-
70
- 钉钉扫码接入时,请使用已加入企业/组织且有权创建机器人的钉钉账号扫描页面二维码,再在钉钉授权页点击「一键创建新机器人」。若提示“该账号还未加入组织”,请先创建组织或换用已加入组织的账号后重新扫码。插件不设置本机二次批准流程,钉钉中的机器人可见范围就是入站访问范围,请只开放给信任的组织、群或成员。图片下载不会新增独立权限,但依赖机器人已有的“企业内机器人发送消息权限”;手动绑定的已有应用若未开启该权限,可以收到图片回调,但无法换取临时下载地址。
71
-
72
- 企业微信扫码接入时,请使用已加入企业且具有机器人创建或管理权限的企业微信账号,并在手机端确认创建智能机器人。扫码创建的是企业微信智能机器人,不是让插件直接登录个人微信账号。无论扫码还是凭据绑定,企业微信中的机器人可见范围就是入站访问范围,请只开放给信任的企业成员和群聊。
73
-
74
- QQ 扫码接入使用腾讯 QQBot v2 官方流程。默认腾讯授权页会把接入方显示为“第三方机器人”;扫码成功后创建的是 QQ 开放平台机器人,并不是让插件直接控制个人 QQ 账号。扫码绑定只接受扫码者的消息;手动凭据无法识别扫码人,因此使用 QQ 开放平台中的机器人可见范围作为入站访问范围。
74
+ ```sh
75
+ npx -y github:xmanrui/dsh-im install
76
+ ```
75
77
 
76
- 飞书扫码绑定会把扫码者作为允许使用者;手动凭据同样无法识别扫码人,因此使用飞书应用的可见范围作为入站访问范围。请在飞书开放平台中只向信任的租户、群或成员开放应用。读取用户发送的图片需要租户权限 `im:message:readonly`;新扫码创建的应用会申请该权限,升级前已存在的应用需要在飞书开放平台手动添加权限、发布版本并完成必要的管理员审批。
78
+ GitHub 源安装会直接拉取并构建 Git 依赖;pnpm 10 及以上版本可能要求先在 profile 的 `pnpm-workspace.yaml` 中允许该依赖执行构建脚本。普通用户建议优先使用 npm 稳定版。
77
79
 
78
- 每个机器人维护独立的 Harness 工作区。新接入机器人会把 Harness Host 进程当时的工作目录(`process.cwd()`)记录为默认值;该路径会持久化,不会因为以后从其他目录重启 Host 而改变。设置页的机器人卡片会显示当前路径,并可直接修改。
80
+ 安装后,在对应渠道页面按照内置引导完成扫码或凭据配置。所有 Secret Token 只提交给本机 Harness Host,并写入受保护的凭据存储;状态接口和机器人列表不会回传这些凭据。
79
81
 
80
- 渠道没有显式配置 `agentPreset` 时,新建的 IM 会话继承 Harness 的 `agent-presets.default` 全局默认值。Harness 会在每次创建会话时读取该默认值,因此修改设置只影响之后创建的新会话;已有会话以及通过 `/session` 绑定的会话保持自身 preset。渠道显式配置的 `agentPreset` 始终优先。
82
+ | 默认行为 | 说明 |
83
+ | --- | --- |
84
+ | 机器人工作区 | 每个机器人独立保存工作区。新机器人默认使用 Host 当时的工作目录;之后可在机器人卡片中修改。 |
85
+ | Agent Preset | 新会话默认继承 Harness 的 `agent-presets.default`;渠道显式配置优先,已有会话不受后续修改影响。 |
81
86
 
82
87
  ## 机器人命令
83
88
 
84
89
  | 命令 | 作用 |
85
90
  | --- | --- |
91
+ | `/help` | 显示机器人支持的命令和用法。 |
92
+ | `/new` | 解除当前聊天的会话绑定,让下一条普通消息开启全新 Harness 会话。 |
93
+ | `/status` | 检查当前机器人与 DeepSeek Harness 的连接状态。 |
94
+ | `/models` | 按序号列出当前配置的全部可用模型。 |
95
+ | `/model` | 查看当前聊天绑定会话正在使用的模型。 |
96
+ | `/model <序号或 Provider/模型ID>` | 切换当前聊天绑定会话的模型。 |
97
+ | `/stop` | 立即停止当前聊天正在运行的任务,并保留尚未开始的排队消息。 |
98
+ | `/steer <补充指令>` | 把补充指令立即加入当前聊天正在运行的任务。 |
86
99
  | `/compact` | 立即压缩当前聊天绑定会话的较早上下文。 |
87
100
  | `/workspace <工作区绝对路径>` | 切换当前机器人的 Harness 工作区。 |
88
101
  | `/workspacelist` | 列出当前 Harness Host 上仍然存在的工作区绝对路径。 |
89
102
  | `/sessionlist [工作区序号或绝对路径]` | 列出指定工作区登记的所有会话 ID 和标题;省略参数时使用当前工作区。 |
90
103
  | `/session <Session ID>` | 将当前聊天绑定到指定的已有 Harness 会话。 |
104
+ | 交互式提问 | 回复选项序号、选项文字或自定义文字;多选时用逗号分隔。 |
105
+ | 远程审批 | 回复 `批准` / `拒绝` / `同意` / `不同意` / `yes` / `no`。 |
106
+
107
+ 示例:先发送 `/models`,再发送 `/model 2` 切换到列表中的第 2 个模型。其他命令示例:`/help`、`/new`、`/status`、`/model deepseek-official/deepseek-v4-pro`、`/steer 只检查配置文件`、`/stop`、`/compact`、`/workspace /Users/alice/projects/my-app`、`/sessionlist 2`、`/sessionlist /Users/alice/projects/my-app` 或 `/session session-id`
91
108
 
92
- 示例:`/compact`、`/workspace /Users/alice/projects/my-app`、`/sessionlist 2`、`/sessionlist /Users/alice/projects/my-app` 或 `/session session-id`
109
+ ### 命令说明
93
110
 
111
+ - `/help` 不需要参数,也不会创建会话;它会返回当前机器人支持的完整命令列表。
112
+ - `/status` 不需要参数,也不会向模型发送消息或改变会话绑定;它用于确认当前机器人能够连接 DeepSeek Harness。
113
+ - `/new` 只解除当前聊天在 dsh-im 中保存的会话绑定,不会删除、清空或归档旧 Session。下一条普通消息会在当前工作区创建并绑定一个新 Session。任务正在运行或等待问题、审批时,应先完成交互或使用 `/stop`,再使用 `/new`。
114
+ - `/models` 不需要参数,也不会创建会话。它为 Harness 当前配置的全部可用模型分配序号,同时显示可稳定复制的 `Provider/模型ID`;某个 Provider 查询失败时,其他 Provider 的结果仍会显示。
115
+ - `/model` 不带参数时只查看当前会话模型;带参数时接受 `/models` 列出的序号或完整模型 ID,例如 `/model 2`。完整 ID 必须精确匹配。聊天尚无会话时,有效的切换命令会创建并绑定一个空白会话,但不会触发模型回复。切换只影响当前会话;Harness 还会尝试把它保存为以后新会话的默认模型,已有其他会话不受影响。
116
+ - 正在运行任务或等待审批、问题回答时不能切换模型;请等待完成,或先使用 `/stop`。含图片的会话无法切换到不支持图片输入的模型。
117
+ - `/stop` 和 `/steer` 只控制当前聊天自己发起的运行任务,即使多个聊天绑定同一个 Session,也不会有意控制其他聊天的任务。`/stop` 不删除会话或历史,并保留尚未开始的排队消息;重复发送是安全的。
118
+ - `/steer` 只接受文字,可包含多行;它不会创建新会话或第二个任务。没有运行任务时请直接发送普通消息;等待审批或问题回答时请先处理交互,或使用 `/stop`。
94
119
  - `/compact` 只作用于当前聊天已经绑定的 Harness 会话,不会把命令发送给模型。当前聊天尚未创建会话、会话正在生成回复或没有可压缩历史时,机器人会直接返回对应状态。
95
120
  - 只接受已经存在的绝对目录;路径无效时机器人会返回具体提示和正确用法。
96
121
  - `/workspacelist` 不需要参数。它合并 Harness 全局登记项与当前机器人的路径;当前路径仍存在且可安全显示时会排在首位并标记为“当前”。结果可直接复制到 `/workspace` 命令。
@@ -106,6 +131,15 @@ QQ 扫码接入使用腾讯 QQBot v2 官方流程。默认腾讯授权页会把
106
131
  - 切换成功后只清除当前机器人的旧 Harness 会话映射,不影响其他机器人。
107
132
  - 新工作区对后续消息生效;已经开始生成的回复会继续完成。
108
133
 
134
+ ## 其它功能
135
+
136
+ - **图片识别**:九个内置渠道都可以把 JPEG、PNG、WebP,以及以图片文件方式发送的 GIF 交给 Harness;图片可以附带文字说明。单张图片上限为 5 MB,单条消息中的图片总大小上限为 20 MB。
137
+ - **在机器人卡片切换工作区**:设置页中的每张机器人卡片都会显示当前 Harness 工作区。可以直接填写已有目录的绝对路径,也可以打开目录选择器。切换只清除该机器人的旧聊天映射,不会删除、清空或归档旧 Session;已经开始的回复可以继续完成,后续消息使用新工作区。
138
+ - **检查连接并发送测试消息**:机器人在线时,点击卡片上的「检查连接」会检查平台连接,并向该机器人最近记录的私聊发送一条“DeepSeek Harness 连接测试成功”消息;WhatsApp 会发送到账号自聊。测试消息不会创建 Harness Session,也不会调用模型。机器人必须至少收到过一条私聊才能记住测试目标,否则页面会提示尚无可用的测试会话。
139
+ - **重试连接和移除接入**:机器人离线时,卡片上的操作会变为「重试连接」;不再使用时可以点击「移除接入」。这些操作都只作用于所选机器人,不影响其他机器人或渠道。
140
+ - **多机器人独立管理**:同一渠道可以接入多个机器人。每个机器人分别保存凭据、连接状态、工作区和聊天会话映射,卡片上的工作区、连接检查、重试和移除操作互不影响。
141
+ - **流式回复和进度提示**:插件会按各平台能力显示正在思考、工具执行和逐步生成的回答;不支持原生流式接口的平台会通过编辑消息、卡片更新或最终消息完成回复。
142
+
109
143
  ## 设计
110
144
 
111
145
  - Harness 中只注册一个「IM机器人」设置页;
package/lib/client.js CHANGED
@@ -383,7 +383,7 @@ var EN = Object.freeze({
383
383
  "IM\u673A\u5668\u4EBA": "IM bots",
384
384
  "IM\u673A\u5668\u4EBA\u8BBE\u7F6E": "IM bot settings",
385
385
  "IM \u6E20\u9053": "IM channels",
386
- "\u8BA9\u804A\u5929\u673A\u5668\u4EBA\u8F7B\u677E\u63A5\u5165 DeepSeek Harness": "Connect IM bots to DeepSeek Harness with ease",
386
+ "\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA": "DeepSeek Harness, always within reach",
387
387
  "\u5E2E\u52A9\u4E0E\u53CD\u9988 \xB7 \u524D\u5F80 GitHub": "Help & feedback \xB7 Open GitHub",
388
388
  "\u5FAE\u4FE1": "WeChat",
389
389
  "\u98DE\u4E66": "Feishu",
@@ -8607,7 +8607,7 @@ function IMSettingsTab({
8607
8607
  width: 48,
8608
8608
  height: 48
8609
8609
  }),
8610
- h2("p", null, "\u8BA9\u804A\u5929\u673A\u5668\u4EBA\u8F7B\u677E\u63A5\u5165 DeepSeek Harness")
8610
+ h2("p", null, "\u8BA9 DeepSeek Harness \u89E6\u624B\u53EF\u53CA")
8611
8611
  ),
8612
8612
  h2(
8613
8613
  "span",