@xmanrui/dsh-im 4.0.0 → 4.1.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 (74) hide show
  1. package/PROACTIVE_DELIVERY.en.md +321 -0
  2. package/PROACTIVE_DELIVERY.md +321 -0
  3. package/README.en.md +11 -5
  4. package/README.md +11 -5
  5. package/lib/client.js +1200 -110
  6. package/lib/index.js +229 -229
  7. package/package.json +4 -1
  8. package/plugin-src/client/channel-card-meta.js +44 -0
  9. package/plugin-src/client/channels/dingtalk/index.js +16 -8
  10. package/plugin-src/client/channels/feishu/index.js +17 -9
  11. package/plugin-src/client/channels/qq/index.js +16 -8
  12. package/plugin-src/client/channels/shared/token-channel.js +16 -8
  13. package/plugin-src/client/channels/wecom/index.js +16 -8
  14. package/plugin-src/client/channels/weixin/index.js +16 -8
  15. package/plugin-src/client/channels/whatsapp/index.js +16 -8
  16. package/plugin-src/client/delivery-settings.js +749 -0
  17. package/plugin-src/client/i18n.js +82 -0
  18. package/plugin-src/client/index.js +59 -22
  19. package/plugin-src/client/styles.js +72 -0
  20. package/plugin-src/host/channels/dingtalk/index.mjs +3 -0
  21. package/plugin-src/host/channels/dingtalk/production.mjs +4 -0
  22. package/plugin-src/host/channels/discord/index.mjs +6 -1
  23. package/plugin-src/host/channels/feishu/index.mjs +3 -0
  24. package/plugin-src/host/channels/feishu/production.mjs +4 -0
  25. package/plugin-src/host/channels/qq/index.mjs +6 -1
  26. package/plugin-src/host/channels/qq/production.mjs +2 -0
  27. package/plugin-src/host/channels/shared/production.mjs +7 -0
  28. package/plugin-src/host/channels/slack/index.mjs +6 -1
  29. package/plugin-src/host/channels/slack/production.mjs +4 -0
  30. package/plugin-src/host/channels/telegram/index.mjs +6 -1
  31. package/plugin-src/host/channels/wecom/index.mjs +6 -1
  32. package/plugin-src/host/channels/wecom/production.mjs +4 -0
  33. package/plugin-src/host/channels/weixin/index.mjs +3 -0
  34. package/plugin-src/host/channels/weixin/production.mjs +4 -0
  35. package/plugin-src/host/channels/whatsapp/index.mjs +6 -1
  36. package/plugin-src/host/channels/whatsapp/production.mjs +4 -0
  37. package/plugin-src/host/delivery-adapter.mjs +179 -0
  38. package/plugin-src/host/delivery-http.mjs +132 -0
  39. package/plugin-src/host/delivery-rpc.mjs +158 -0
  40. package/plugin-src/host/delivery-service.mjs +224 -0
  41. package/plugin-src/host/delivery-suggestions.mjs +135 -0
  42. package/plugin-src/host/index.mjs +32 -5
  43. package/scripts/verify-package.mjs +3 -0
  44. package/src/channels/dingtalk/dingtalk-api.mjs +33 -0
  45. package/src/channels/dingtalk/dingtalk-bridge.mjs +2 -2
  46. package/src/channels/dingtalk/dingtalk-controller.mjs +14 -0
  47. package/src/channels/dingtalk/dingtalk-runtime.mjs +39 -0
  48. package/src/channels/discord/discord-runtime.mjs +16 -0
  49. package/src/channels/feishu/bridge.mjs +4 -4
  50. package/src/channels/feishu/feishu-cards.mjs +4 -4
  51. package/src/channels/feishu/feishu-runtime.mjs +35 -0
  52. package/src/channels/feishu/multi-bot-controller.mjs +15 -0
  53. package/src/channels/qq/qq-bridge.mjs +2 -2
  54. package/src/channels/qq/qq-controller.mjs +14 -0
  55. package/src/channels/qq/qq-runtime.mjs +23 -0
  56. package/src/channels/shared/bot-workspace-store.mjs +192 -6
  57. package/src/channels/shared/i18n-en/feishu.mjs +6 -2
  58. package/src/channels/shared/i18n-en/shared-a.mjs +4 -0
  59. package/src/channels/shared/preset-command.mjs +2 -2
  60. package/src/channels/shared/text-harness-bridge.mjs +7 -2
  61. package/src/channels/shared/token-bot-controller.mjs +16 -0
  62. package/src/channels/shared/workspace-command.mjs +1 -1
  63. package/src/channels/slack/slack-controller.mjs +14 -0
  64. package/src/channels/slack/slack-runtime.mjs +24 -0
  65. package/src/channels/telegram/telegram-runtime.mjs +26 -0
  66. package/src/channels/wecom/state-store.mjs +4 -0
  67. package/src/channels/wecom/wecom-bridge.mjs +2 -2
  68. package/src/channels/wecom/wecom-controller.mjs +14 -0
  69. package/src/channels/wecom/wecom-runtime.mjs +21 -0
  70. package/src/channels/weixin/weixin-bridge.mjs +2 -2
  71. package/src/channels/weixin/weixin-controller.mjs +14 -0
  72. package/src/channels/weixin/weixin-runtime.mjs +24 -0
  73. package/src/channels/whatsapp/whatsapp-controller.mjs +14 -0
  74. package/src/channels/whatsapp/whatsapp-runtime.mjs +19 -0
package/README.en.md CHANGED
@@ -130,6 +130,12 @@ Use the proxy URL required by your network and restart the Host after changing i
130
130
  | Agent Preset | Each bot can choose an Agent Preset on its settings card. When none is chosen, new Sessions follow the Host's `agent-presets.default`. A channel-level `config.agentPreset` is only the default for later new bots on that channel. Changing the preset never modifies or clears existing Sessions; if the current chat already has a Session, send `/new` and then a regular message to create one with the new selection. |
131
131
  | Context enhancement | Open settings from a bot card to enable groups and DMs independently. Both switches default to off, including for existing bots after an upgrade. |
132
132
 
133
+ ### Proactive delivery
134
+
135
+ All nine IM channels can proactively send text through a stable `botId + targetId` pair. Bot settings support choosing a known conversation or entering a target manually, testing the current route before saving, and copying call parameters. HTTP POST, same-Host plugins, and Connection RPC share the same target configuration and delivery core.
136
+
137
+ See the [Proactive Delivery Guide](PROACTIVE_DELIVERY.en.md) ([简体中文](PROACTIVE_DELIVERY.md)) for setup steps, native fields for all nine channels, complete call examples, management endpoints, error codes, and troubleshooting.
138
+
133
139
  ### Context enhancement
134
140
 
135
141
  Open **Context enhancement** on a bot card to choose conversation scopes, source fields and guidance, then **Save**. The five available fields are `channel`, `conversationType`, `senderId`, `senderName` and `botId`; only `senderId` is selected by default. Only selected values already available in the incoming message are included; no platform profile API is queried. Weixin currently supports DMs only.
@@ -181,7 +187,7 @@ Do not modify the same profile through a terminal or plugin market during instal
181
187
  | `/reasoning` | Show the current Session model and reasoning effort. |
182
188
  | `/reasoning <number or effort ID>` | Switch the current model's reasoning effort. |
183
189
  | `/reasoning --default` | Restore the current model's default reasoning effort. |
184
- | `/presetlist` | List the Host's currently available Agent Presets, marking the Host default and this bot's selection. |
190
+ | `/presetlist`, `/presets` | Equivalent aliases that list the Host's currently available Agent Presets, marking the Host default and this bot's selection. |
185
191
  | `/preset` | Show this bot's Agent Preset setting for new Sessions. |
186
192
  | `/preset <number or Preset ID>` | Set this bot's Agent Preset; use `/preset id:<ID>` for a numeric ID. |
187
193
  | `/preset --default` | Clear this bot's explicit selection so later new Sessions follow the Host default. |
@@ -194,7 +200,7 @@ Do not modify the same profile through a terminal or plugin market during instal
194
200
  | `/compact` | Immediately compact older context in the Session bound to the current chat. |
195
201
  | `/workspace <absolute workspace path>` | Switch the current bot's Harness workspace. |
196
202
  | `/workspacelist` | List workspace absolute paths that still exist on the current Harness Host. |
197
- | `/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. |
203
+ | `/sessionlist [workspace number or absolute path]`, `/sessions [...]` | Equivalent aliases that list every registered session ID and title in the selected workspace; omit the argument to use the current workspace. |
198
204
  | `/session <Session ID>` | Bind the current chat to an existing Harness session. |
199
205
  | `/history [count]` | Preview recent messages from the bound Session in a direct chat; defaults to 3, capped at 5. |
200
206
  | Interactive question | Reply with an option number, option label, or custom text; separate multiple choices with commas. |
@@ -214,7 +220,7 @@ If the Slack desktop app has no native Slash Command registered with the same na
214
220
  - Bare `/model` shows the current Session model and reasoning effort. With arguments, it accepts a number from `/models` or an exact full model ID, followed optionally by an exact reasoning effort ID published in that target model's metadata, for example `/model 2 max`. When the effort is omitted, Harness resolves the target model's current default. If the chat has no Session yet, a valid switch creates and binds a blank Session without prompting the model.
215
221
  - `/reasoninglist` and `/reasonings` are equivalent. They list the efforts from the current model's metadata and mark the current and default values. `/reasoning` shows the current value; `/reasoning <number or effort ID>` accepts a listed number or an exact metadata ID; `/reasoning --default` lets Harness resolve the current model's default again. Every `/reasoning...` command requires an existing Session and never creates one or prompts the model.
216
222
  - The model or reasoning effort cannot be changed while a task is running or waiting for an approval or question answer. Wait for it to finish or use `/stop` first. A change takes effect on the next model request and keeps Harness's default-saving semantics: Harness attempts to save the accepted model and effort as the default selection for future Sessions, while other existing Sessions remain unchanged. A Session containing images cannot switch to a model that does not accept image input.
217
- - `/presetlist` takes no arguments and never creates a Session. It reads the Host's currently available Agent Presets every time, showing their names, stable IDs, the Host default, and this bot's selection. A selected Preset that has been deleted or become broken is retained and marked unavailable instead of being cleared automatically. Only safe names and IDs are shown; paths, errors, and other Host internals are never exposed.
223
+ - `/presetlist` and `/presets` are equivalent. They take no arguments and never create a Session. Each reads the Host's currently available Agent Presets, showing their names, stable IDs, the Host default, and this bot's selection. A selected Preset that has been deleted or become broken is retained and marked unavailable instead of being cleared automatically. Only safe names and IDs are shown; paths, errors, and other Host internals are never exposed.
218
224
  - Bare `/preset` shows this bot's setting for future new Sessions; it does not inspect or change the current Session. With an argument, it accepts a number from the most recent `/presetlist` in this chat or an exact ID; use `/preset id:<ID>` for a numeric ID. A numbered selection resolves the ID from that displayed list and then validates it against the latest Host catalog, asking for a fresh list if it has changed.
219
225
  - `/preset --default` clears this bot's explicit override so future Sessions resolve the Host default when they are created. Explicitly selecting an ID that currently matches the Host default pins that ID instead. Following the Host default remains available even while the catalog cannot be read.
220
226
  - An Agent Preset change is bot-wide: it affects future new Sessions in every chat for this bot, but never modifies, stops, unbinds, or rebuilds an existing Session and never runs `/new` automatically. If this chat already has a Session, ordinary messages keep using it; the first ordinary message after `/new` creates a Session with the new setting. Presets can still be queried or changed while a task is running or awaiting interaction because the command does not touch that Session.
@@ -225,8 +231,8 @@ If the Slack desktop app has no native Slash Command registered with the same na
225
231
  - `/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.
226
232
  - The path must be an existing absolute directory. The bot returns an actionable error and the correct usage when validation fails.
227
233
  - `/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`.
228
- - A numeric `/sessionlist` argument uses the same freshly resolved order as `/workspacelist` at command execution time. An absolute path can also select a workspace directly, and the result echoes the resolved path.
229
- - `/sessionlist` includes every session registered to the selected workspace. Archived sessions are marked as archived; blank and subagent sessions are included when they belong to that workspace; sessions without a title are shown as `No title yet`. Any listed ID can be passed directly to `/session Session ID`.
234
+ - `/sessionlist` and `/sessions` are equivalent. A numeric argument uses the same freshly resolved order as `/workspacelist` at command execution time. An absolute path can also select a workspace directly, and the result echoes the resolved path.
235
+ - Both session-list aliases include every session registered to the selected workspace. Archived sessions are marked as archived; blank and subagent sessions are included when they belong to that workspace; sessions without a title are shown as `No title yet`. Any listed ID can be passed directly to `/session Session ID`.
230
236
  - `/session` accepts exactly one Session ID obtained from `/sessionlist`. It neither creates a session nor immediately prompts the model; later messages in the current chat continue the bound session. Regular archived sessions can be bound without being unarchived, while subagent sessions cannot be bound.
231
237
  - `/history` works identically in direct chats on all nine channels. It only reads the Session already bound to this chat: it never creates a Session, prompts the model, or interrupts running tasks or pending interactions. It returns the latest 3 messages by default. `/history N` accepts a positive integer, caps values above 5 at 5, and returns fewer when fewer are available. Zero, negative, fractional, nonnumeric, and multiple arguments show usage; commands with images or files are rejected. While collecting batch input, use `/send` or `/cancel` first.
232
238
  - A user message or a final assistant reply counts as one history item, not one turn or day. The latest N items are displayed oldest first. Tool events, reasoning, injected content, and unfinished assistant output are omitted; old attachments are not downloaded or resent. Long text is marked as truncated, with at most 3 text segments per reply and no automatic pagination. After binding a Session, send `/history` manually; binding never replays history automatically. Message text may still contain sensitive information from the original conversation, so expose the bot only to trusted users.
package/README.md CHANGED
@@ -133,6 +133,12 @@ dsh web
133
133
  | Agent Preset | 每个机器人可在设置页卡片中选择 Agent Preset。未选择时跟随 Host 的 `agent-presets.default`;渠道级 `config.agentPreset` 只作为该渠道之后新接入机器人的默认值。切换不会修改或清空已有会话;若当前聊天已有会话,需先发送 `/new`,再发送一条普通消息,才会按新选择创建会话。 |
134
134
  | 上下文增强 | 从机器人卡片打开设置,分别决定群聊、私聊是否增强;两个开关默认均关闭,旧机器人升级后也不会自动开启。 |
135
135
 
136
+ ### 主动投递
137
+
138
+ 九个 IM 渠道都可以使用稳定的 `botId + targetId` 主动发送文字消息。机器人设置页支持从已聊会话选择或手工填写目标、保存前测试当前路由,以及复制调用参数;HTTP POST、同 Host 插件和 Connection RPC 共用同一目标配置与投递核心。
139
+
140
+ 设置步骤、九渠道字段、完整调用示例、管理端点、错误码与排错说明请查看[《主动投递使用指南》](PROACTIVE_DELIVERY.md)([English](PROACTIVE_DELIVERY.en.md))。
141
+
136
142
  ### 上下文增强
137
143
 
138
144
  点击机器人卡片中的「上下文增强」,设置群聊/私聊范围、来源字段和增强提示词,点击「保存」后生效。五个可选字段为 `channel`、`conversationType`、`senderId`、`senderName`、`botId`,默认只选择 `senderId`;只发送勾选且当前消息已有的值,不查询平台 API 补全。微信当前只支持私聊。
@@ -184,7 +190,7 @@ dsh plugin --profile web add -w --save-exact @xmanrui/dsh-im@3.1.0 --registry=ht
184
190
  | `/reasoning` | 查看当前会话的模型和推理等级。 |
185
191
  | `/reasoning <序号或等级ID>` | 切换当前模型的推理等级。 |
186
192
  | `/reasoning --default` | 恢复当前模型的默认推理等级。 |
187
- | `/presetlist` | 按序号列出 Host 当前可用的 Agent Preset,并标记 Host 默认项和当前机器人的选择。 |
193
+ | `/presetlist`、`/presets` | 两个等价命令;按序号列出 Host 当前可用的 Agent Preset,并标记 Host 默认项和当前机器人的选择。 |
188
194
  | `/preset` | 查看当前机器人的新会话 Agent Preset 设置。 |
189
195
  | `/preset <序号或 Preset ID>` | 设置当前机器人的 Agent Preset;纯数字 ID 使用 `/preset id:<ID>`。 |
190
196
  | `/preset --default` | 清除当前机器人的显式选择,让后续新 Session 跟随 Host 默认。 |
@@ -197,7 +203,7 @@ dsh plugin --profile web add -w --save-exact @xmanrui/dsh-im@3.1.0 --registry=ht
197
203
  | `/compact` | 立即压缩当前聊天绑定会话的较早上下文。 |
198
204
  | `/workspace <工作区绝对路径>` | 切换当前机器人的 Harness 工作区。 |
199
205
  | `/workspacelist` | 列出当前 Harness Host 上仍然存在的工作区绝对路径。 |
200
- | `/sessionlist [工作区序号或绝对路径]` | 列出指定工作区登记的所有会话 ID 和标题;省略参数时使用当前工作区。 |
206
+ | `/sessionlist [工作区序号或绝对路径]`、`/sessions [...]` | 两个等价命令;列出指定工作区登记的所有会话 ID 和标题,省略参数时使用当前工作区。 |
201
207
  | `/session <Session ID>` | 将当前聊天绑定到指定的已有 Harness 会话。 |
202
208
  | `/history [数量]` | 在私聊中查看当前绑定会话的最近历史消息,默认 3 条,最多 5 条。 |
203
209
  | 交互式提问 | 回复选项序号、选项文字或自定义文字;多选时用逗号分隔。 |
@@ -217,7 +223,7 @@ Slack 桌面端若未注册同名的原生 Slash Command,会拦截直接以 `/
217
223
  - `/model` 不带参数时查看当前会话的模型和推理等级;带参数时接受 `/models` 列出的序号或精确完整模型 ID,并可追加目标模型元数据公布的精确推理等级 ID,例如 `/model 2 max`。省略推理等级时,由 Harness 解析目标模型的当前默认值。聊天尚无会话时,有效的切换命令会创建并绑定一个空白会话,但不会触发模型回复。
218
224
  - `/reasoninglist` 和 `/reasonings` 完全等价,按当前模型的元数据列出可选推理等级并标记当前值和默认值。`/reasoning` 查看当前值;`/reasoning <序号或等级ID>` 接受列表序号或元数据中的精确 ID;`/reasoning --default` 让 Harness 重新采用当前模型的默认推理等级。所有 `/reasoning...` 命令都要求当前聊天已有 Session,不会自行创建 Session 或触发模型回复。
219
225
  - 正在运行任务或等待审批、问题回答时不能修改模型或推理等级;请等待完成,或先使用 `/stop`。修改从下一次模型请求起生效,并沿用 Harness 的默认保存语义:Harness 会尝试把已接受的模型和推理等级保存为以后新会话的默认选择,已有其他会话不受影响。含图片的会话无法切换到不支持图片输入的模型。
220
- - `/presetlist` 不需要参数,也不会创建会话。它每次都读取 Host 当前可用的 Agent Preset,显示名称、稳定 ID、Host 默认项和当前机器人的选择;已删除或损坏的当前选择会保留并标记为“已不可用”,不会被自动清除。列表只公开安全的名称和 ID,不公开 Preset 路径、错误或其他 Host 内部字段。
226
+ - `/presetlist` `/presets` 完全等价,不需要参数,也不会创建会话。它们每次都读取 Host 当前可用的 Agent Preset,显示名称、稳定 ID、Host 默认项和当前机器人的选择;已删除或损坏的当前选择会保留并标记为“已不可用”,不会被自动清除。列表只公开安全的名称和 ID,不公开 Preset 路径、错误或其他 Host 内部字段。
221
227
  - `/preset` 不带参数时查看当前机器人的“新会话设置”,不是查看或修改当前 Session。带参数时接受最近一次 `/presetlist` 在当前聊天中显示的序号或完整 ID;纯数字 ID 使用 `/preset id:<ID>`。选择序号时会先按该次列表解析 ID,再用 Host 最新目录复验,目录已经变化时会要求重新列出。
222
228
  - `/preset --default` 清除当前机器人的显式覆盖值,让以后新建的 Session 在创建时跟随 Host 当前默认;显式选择一个恰好等于 Host 默认的 ID 则会固定该 ID。目录暂时不可读时仍可恢复为跟随 Host 默认。
223
229
  - Agent Preset 修改是机器人级配置,会影响该机器人所有聊天以后创建的新 Session,但不会修改、停止、解绑或重建已有 Session,也不会自动执行 `/new`。若当前聊天已有会话,继续发送消息仍使用原 Session;发送 `/new` 后的下一条普通消息才会按新设置创建 Session。任务正在运行或等待交互时也可查询或修改 Preset,因为命令不会触碰当前 Session。
@@ -228,8 +234,8 @@ Slack 桌面端若未注册同名的原生 Slash Command,会拦截直接以 `/
228
234
  - `/compact` 只作用于当前聊天已经绑定的 Harness 会话,不会把命令发送给模型。当前聊天尚未创建会话、会话正在生成回复或没有可压缩历史时,机器人会直接返回对应状态。
229
235
  - 只接受已经存在的绝对目录;路径无效时机器人会返回具体提示和正确用法。
230
236
  - `/workspacelist` 不需要参数。它合并 Harness 全局登记项与当前机器人的路径;当前路径仍存在且可安全显示时会排在首位并标记为“当前”。结果可直接复制到 `/workspace` 命令。
231
- - `/sessionlist` 的数字参数按命令执行时与 `/workspacelist` 相同的最新顺序解析;也可使用绝对路径直接指定工作区。结果会回显最终选中的路径。
232
- - `/sessionlist` 会列出该工作区登记的所有会话。已归档会话会标记为“已归档”;空白会话和子代理会话在它们归属该工作区时也会列出;没有标题的会话显示为“暂无标题”。结果中的 ID 可直接用于 `/session Session ID`。
237
+ - `/sessionlist` `/sessions` 完全等价。数字参数按命令执行时与 `/workspacelist` 相同的最新顺序解析;也可使用绝对路径直接指定工作区。结果会回显最终选中的路径。
238
+ - 两个会话列表命令都会列出该工作区登记的所有会话。已归档会话会标记为“已归档”;空白会话和子代理会话在它们归属该工作区时也会列出;没有标题的会话显示为“暂无标题”。结果中的 ID 可直接用于 `/session Session ID`。
233
239
  - `/session` 只接受一个由 `/sessionlist` 获得的 Session ID。它不会新建会话或立即向模型发送消息;绑定成功后,当前聊天的后续消息会继续该会话。普通归档会话可以绑定但不会自动取消归档,子代理会话不能绑定。
234
240
  - `/history` 在九个渠道的私聊中统一可用,只读取当前聊天已经绑定的会话,不新建会话、不调用模型,也不影响正在运行的任务或待处理交互。默认返回最近 3 条;`/history N` 接受正整数,超过 5 自动按 5 条处理,数量不足时返回实际条数。零、负数、小数、非数字和多个参数会提示用法,附带图片或文件时会拒绝处理;批量输入收集中请先 `/send` 或 `/cancel`。
235
241
  - 历史预览中,一条用户消息或一条助手最终回复各算一条,不按轮次或天数计数。先取最新 N 条,再按从旧到新的顺序显示;不展示工具、推理、注入内容或尚未完成的助手片段,不下载或重发历史附件。长正文会截断并注明,全部结果最多发送 3 段文字,不自动翻页。绑定会话后可手动发送 `/history`,不会自动重发历史。正文仍可能包含会话原有的敏感信息,请只向可信用户开放机器人。