@xmanrui/dsh-im 4.4.0 → 4.5.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.
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/lib/client.js +26 -9
- package/lib/index.js +229 -226
- package/package.json +1 -1
- package/plugin-src/client/context-enhancement.js +19 -5
- package/plugin-src/client/i18n.js +5 -1
- package/plugin-src/host/modern-harness-api.mjs +3 -0
- package/src/channels/dingtalk/dingtalk-bridge.mjs +9 -3
- package/src/channels/feishu/bridge.mjs +19 -2
- package/src/channels/feishu/feishu-cards.mjs +2 -2
- package/src/channels/feishu/feishu-channel.mjs +36 -6
- package/src/channels/qq/qq-bridge.mjs +8 -3
- package/src/channels/shared/bot-workspace-store.mjs +5 -0
- package/src/channels/shared/context-enhancement.mjs +9 -4
- package/src/channels/shared/harness-client.mjs +6 -0
- package/src/channels/shared/i18n-en/feishu.mjs +3 -3
- package/src/channels/shared/i18n-en/shared-a.mjs +2 -1
- package/src/channels/shared/i18n-en/shared-b.mjs +6 -3
- package/src/channels/shared/session-title.mjs +74 -0
- package/src/channels/shared/text-harness-bridge.mjs +7 -2
- package/src/channels/shared/workspace-command.mjs +16 -4
- package/src/channels/shared/workspace-session.mjs +28 -2
- package/src/channels/telegram/telegram-runtime.mjs +1 -0
- package/src/channels/wecom/wecom-bridge.mjs +6 -2
- package/src/channels/weixin/weixin-bridge.mjs +8 -3
package/README.en.md
CHANGED
|
@@ -202,7 +202,7 @@ Do not modify the same profile through a terminal or plugin market during instal
|
|
|
202
202
|
| `/cancel` | Cancel batch input and discard its collected messages. |
|
|
203
203
|
| `/repair` | In a Feishu direct chat, incrementally repair the card callback and permissions required for media and the native Slash Command panel. |
|
|
204
204
|
| `/compact` | Immediately compact older context in the Session bound to the current chat. |
|
|
205
|
-
| `/workspace <absolute
|
|
205
|
+
| `/workspace <workspace index or absolute path>` | Switch the current bot's Harness workspace by `/workspacelist` index or absolute path. |
|
|
206
206
|
| `/workspacelist` | List workspace absolute paths that still exist on the current Harness Host. |
|
|
207
207
|
| `/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. |
|
|
208
208
|
| `/session <Session ID>` | Bind the current chat to an existing Harness session. |
|
|
@@ -236,7 +236,7 @@ If the Slack desktop app has no native Slash Command registered with the same na
|
|
|
236
236
|
- Feishu `/repair` is available only in a direct chat and follows the current bot's channel access policy just like every other command; the plugin defines no separate administrator role. It incrementally adds the currently missing `card.action.trigger`, `im:message:readonly`, `im:resource`, `application:app_slash_command:read`, and `application:app_slash_command:write`, while the confirmation page shows only items the app is currently missing. The authorization page must be opened by an account that can access the target app in Feishu Open Platform. Bare `/repair` starts repair; if an older attempt is still awaiting authorization, it invalidates that one-time link before generating a new one. Use `/repair qr` for the current link's QR code, `/repair status` to inspect the attempt, `/repair verify` to refresh verification, and `/repair cancel` to cancel it; none of these four supplemental commands starts another authorization. Once Feishu has accepted the update and the bot is waiting for the test-button callback, a second repair is not started concurrently.
|
|
237
237
|
- `/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.
|
|
238
238
|
- The path must be an existing absolute directory. The bot returns an actionable error and the correct usage when validation fails.
|
|
239
|
-
- `/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.
|
|
239
|
+
- `/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. `/workspace N` switches using the freshly resolved list order at execution time; absolute paths remain supported.
|
|
240
240
|
- `/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.
|
|
241
241
|
- 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`.
|
|
242
242
|
- `/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.
|
package/README.md
CHANGED
|
@@ -205,7 +205,7 @@ dsh plugin --profile web add -w --save-exact @xmanrui/dsh-im@3.1.0 --registry=ht
|
|
|
205
205
|
| `/cancel` | 取消批量输入并丢弃已收集的消息。 |
|
|
206
206
|
| `/repair` | 在飞书私聊中增量修复卡片回调,并补全媒体与原生 Slash Command 面板所需的权限。 |
|
|
207
207
|
| `/compact` | 立即压缩当前聊天绑定会话的较早上下文。 |
|
|
208
|
-
| `/workspace
|
|
208
|
+
| `/workspace <工作区序号或绝对路径>` | 按 `/workspacelist` 序号或绝对路径切换当前机器人的 Harness 工作区。 |
|
|
209
209
|
| `/workspacelist` | 列出当前 Harness Host 上仍然存在的工作区绝对路径。 |
|
|
210
210
|
| `/sessionlist [工作区序号或绝对路径]`、`/sessions [...]` | 两个等价命令;列出指定工作区登记的所有会话 ID 和标题,省略参数时使用当前工作区。 |
|
|
211
211
|
| `/session <Session ID>` | 将当前聊天绑定到指定的已有 Harness 会话。 |
|
|
@@ -239,7 +239,7 @@ Slack 桌面端若未注册同名的原生 Slash Command,会拦截直接以 `/
|
|
|
239
239
|
- 飞书 `/repair` 仅在私聊中可用,并与其他命令一样只服从当前飞书机器人的渠道访问策略;插件不另行区分管理员和普通用户。它增量补全当前缺少的 `card.action.trigger`、`im:message:readonly`、`im:resource`、`application:app_slash_command:read` 和 `application:app_slash_command:write`,确认页只显示当前应用缺少的项。授权页必须由在飞书开放平台中有权访问目标应用的账号打开。普通 `/repair` 会启动修复;若旧任务仍在等待授权,会先作废旧的一次性链接再生成新链接。发送 `/repair qr` 获取当前链接的二维码,`/repair status` 查询当前任务,`/repair verify` 重新查询验证状态,`/repair cancel` 取消任务;这四个补充命令均不会另起授权。平台已接受更新、正在等待测试按钮回调时,不会并发启动第二次修复。
|
|
240
240
|
- `/compact` 只作用于当前聊天已经绑定的 Harness 会话,不会把命令发送给模型。当前聊天尚未创建会话、会话正在生成回复或没有可压缩历史时,机器人会直接返回对应状态。
|
|
241
241
|
- 只接受已经存在的绝对目录;路径无效时机器人会返回具体提示和正确用法。
|
|
242
|
-
- `/workspacelist` 不需要参数。它合并 Harness
|
|
242
|
+
- `/workspacelist` 不需要参数。它合并 Harness 全局登记项与当前机器人的路径;当前路径仍存在且可安全显示时会排在首位并标记为“当前”。`/workspace N` 会在执行时按最新列表顺序切换,也可继续使用绝对路径。
|
|
243
243
|
- `/sessionlist` 和 `/sessions` 完全等价。数字参数按命令执行时与 `/workspacelist` 相同的最新顺序解析;也可使用绝对路径直接指定工作区。结果会回显最终选中的路径。
|
|
244
244
|
- 两个会话列表命令都会列出该工作区登记的所有会话。已归档会话会标记为“已归档”;空白会话和子代理会话在它们归属该工作区时也会列出;没有标题的会话显示为“暂无标题”。结果中的 ID 可直接用于 `/session Session ID`。
|
|
245
245
|
- `/session` 只接受一个由 `/sessionlist` 获得的 Session ID。它不会新建会话或立即向模型发送消息;绑定成功后,当前聊天的后续消息会继续该会话。普通归档会话可以绑定但不会自动取消归档,子代理会话不能绑定。
|
package/lib/client.js
CHANGED
|
@@ -571,7 +571,7 @@ var React23 = __toESM(require("react"), 1);
|
|
|
571
571
|
// package.json
|
|
572
572
|
var package_default = {
|
|
573
573
|
name: "@xmanrui/dsh-im",
|
|
574
|
-
version: "4.
|
|
574
|
+
version: "4.5.0",
|
|
575
575
|
description: "\u628A\u4E5D\u79CD IM \u673A\u5668\u4EBA\u548C\u516C\u7F51 AI Office \u63A5\u5165\u672C\u673A DeepSeek Harness\u3002 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
|
|
576
576
|
keywords: [
|
|
577
577
|
"deepseek-harness",
|
|
@@ -1122,6 +1122,10 @@ var EN = Object.freeze({
|
|
|
1122
1122
|
"\u67E5\u770B\u7FA4\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E": "View group sender name field details",
|
|
1123
1123
|
"\u67E5\u770B\u79C1\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E": "View direct sender name field details",
|
|
1124
1124
|
"\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u53D1\u9001\u8005\u6635\u79F0\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C<dsh_im_source> \u4E2D\u4E5F\u4F1A\u7701\u7565 senderName\u3002": "This field is not available on every channel. If the current message has no sender name, <dsh_im_source> omits senderName even when the field is selected.",
|
|
1125
|
+
"\u4F1A\u8BDD\u6807\u9898": "Conversation title",
|
|
1126
|
+
"\u67E5\u770B\u7FA4\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E": "View group conversation title field details",
|
|
1127
|
+
"\u67E5\u770B\u79C1\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E": "View direct conversation title field details",
|
|
1128
|
+
"\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u9489\u9489\u7FA4\u804A\u4F1A\u5E26\u4E0A\u7FA4\u540D\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u4F1A\u8BDD\u6807\u9898\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C<dsh_im_source> \u4E2D\u4E5F\u4F1A\u7701\u7565 conversationTitle\u3002": "This field is not available on every channel. DingTalk group chats include the group name. If the current message has no conversation title, <dsh_im_source> omits conversationTitle even when the field is selected.",
|
|
1125
1129
|
"\u673A\u5668\u4EBA\u6807\u8BC6": "Bot ID",
|
|
1126
1130
|
"\u589E\u5F3A\u63D0\u793A\u8BCD": "Guidance",
|
|
1127
1131
|
"\u67E5\u770B\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E": "View guidance instructions",
|
|
@@ -1149,7 +1153,7 @@ var EN = Object.freeze({
|
|
|
1149
1153
|
"\u4E0A\u4E0B\u6587\u589E\u5F3A\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not save context enhancement. Try again.",
|
|
1150
1154
|
"\u8BF7\u63D0\u4EA4\u5B8C\u6574\u7684\u4E0A\u4E0B\u6587\u589E\u5F3A\u8BBE\u7F6E\u3002": "Submit the complete context enhancement settings.",
|
|
1151
1155
|
"\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002": "Group and direct switches must be booleans.",
|
|
1152
|
-
"\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\
|
|
1156
|
+
"\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u516D\u4E2A\u5B57\u6BB5\u3002": "Source fields must be chosen from the six defined fields.",
|
|
1153
1157
|
"\u4FDD\u5B58\u4E2D\u2026": "Saving\u2026",
|
|
1154
1158
|
"\u672A\u8BBE\u7F6E": "Not set",
|
|
1155
1159
|
"\u5DE5\u4F5C\u533A\u4FEE\u6539\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002": "Could not update the workspace. Try again.",
|
|
@@ -2075,6 +2079,7 @@ var CONTEXT_ENHANCEMENT_FIELDS = Object.freeze([
|
|
|
2075
2079
|
"conversationType",
|
|
2076
2080
|
"senderId",
|
|
2077
2081
|
"senderName",
|
|
2082
|
+
"conversationTitle",
|
|
2078
2083
|
"botId"
|
|
2079
2084
|
]);
|
|
2080
2085
|
var CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH = 8e3;
|
|
@@ -2114,7 +2119,7 @@ function validateContextEnhancementScope(input) {
|
|
|
2114
2119
|
throw invalidConfig("\u7FA4\u804A\u548C\u79C1\u804A\u5F00\u5173\u5FC5\u987B\u662F\u5E03\u5C14\u503C\u3002");
|
|
2115
2120
|
}
|
|
2116
2121
|
if (!Array.isArray(fields) || ![...fields].every((field) => CONTEXT_ENHANCEMENT_FIELDS.includes(field))) {
|
|
2117
|
-
throw invalidConfig("\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\
|
|
2122
|
+
throw invalidConfig("\u6765\u6E90\u5B57\u6BB5\u53EA\u80FD\u9009\u62E9\u5DF2\u5B9A\u4E49\u7684\u516D\u4E2A\u5B57\u6BB5\u3002");
|
|
2118
2123
|
}
|
|
2119
2124
|
if (typeof guidance !== "string" || guidance.length > CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH) {
|
|
2120
2125
|
throw invalidConfig(`\u589E\u5F3A\u63D0\u793A\u8BCD\u4E0D\u5F97\u8D85\u8FC7 ${CONTEXT_ENHANCEMENT_GUIDANCE_MAX_LENGTH} \u4E2A\u5B57\u7B26\u3002`);
|
|
@@ -2895,14 +2900,26 @@ var FIELD_LABELS = Object.freeze({
|
|
|
2895
2900
|
conversationType: "\u4F1A\u8BDD\u7C7B\u578B",
|
|
2896
2901
|
senderId: "\u53D1\u9001\u8005\u6807\u8BC6",
|
|
2897
2902
|
senderName: "\u53D1\u9001\u8005\u6635\u79F0",
|
|
2903
|
+
conversationTitle: "\u4F1A\u8BDD\u6807\u9898",
|
|
2898
2904
|
botId: "\u673A\u5668\u4EBA\u6807\u8BC6"
|
|
2899
2905
|
});
|
|
2906
|
+
var FIELD_HELP = Object.freeze({
|
|
2907
|
+
senderName: Object.freeze({
|
|
2908
|
+
labelKey: "senderNameHelpLabel",
|
|
2909
|
+
text: "\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u53D1\u9001\u8005\u6635\u79F0\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C<dsh_im_source> \u4E2D\u4E5F\u4F1A\u7701\u7565 senderName\u3002"
|
|
2910
|
+
}),
|
|
2911
|
+
conversationTitle: Object.freeze({
|
|
2912
|
+
labelKey: "conversationTitleHelpLabel",
|
|
2913
|
+
text: "\u8BE5\u5B57\u6BB5\u4E0D\u662F\u6BCF\u4E2A\u6E20\u9053\u90FD\u80FD\u63D0\u4F9B\u3002\u9489\u9489\u7FA4\u804A\u4F1A\u5E26\u4E0A\u7FA4\u540D\u3002\u5F53\u524D\u6D88\u606F\u6CA1\u6709\u4F1A\u8BDD\u6807\u9898\u65F6\uFF0C\u5373\u4F7F\u5DF2\u9009\u62E9\u8BE5\u5B57\u6BB5\uFF0C<dsh_im_source> \u4E2D\u4E5F\u4F1A\u7701\u7565 conversationTitle\u3002"
|
|
2914
|
+
})
|
|
2915
|
+
});
|
|
2900
2916
|
var SCOPE_COPY = Object.freeze({
|
|
2901
2917
|
group: Object.freeze({
|
|
2902
2918
|
title: "\u7FA4\u804A",
|
|
2903
2919
|
enable: "\u542F\u7528",
|
|
2904
2920
|
fieldsHelpLabel: "\u67E5\u770B\u7FA4\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E",
|
|
2905
2921
|
senderNameHelpLabel: "\u67E5\u770B\u7FA4\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E",
|
|
2922
|
+
conversationTitleHelpLabel: "\u67E5\u770B\u7FA4\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E",
|
|
2906
2923
|
guidanceLabel: "\u589E\u5F3A\u63D0\u793A\u8BCD",
|
|
2907
2924
|
guidanceHelpLabel: "\u67E5\u770B\u7FA4\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E",
|
|
2908
2925
|
guidanceUsage: "\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528\u5F53\u524D\u7FA4\u804A\u6D88\u606F\u7684 <dsh_im_source> \u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002",
|
|
@@ -2913,6 +2930,7 @@ var SCOPE_COPY = Object.freeze({
|
|
|
2913
2930
|
enable: "\u542F\u7528",
|
|
2914
2931
|
fieldsHelpLabel: "\u67E5\u770B\u79C1\u804A\u6765\u6E90\u5B57\u6BB5\u8BF4\u660E",
|
|
2915
2932
|
senderNameHelpLabel: "\u67E5\u770B\u79C1\u804A\u53D1\u9001\u8005\u6635\u79F0\u5B57\u6BB5\u8BF4\u660E",
|
|
2933
|
+
conversationTitleHelpLabel: "\u67E5\u770B\u79C1\u804A\u4F1A\u8BDD\u6807\u9898\u5B57\u6BB5\u8BF4\u660E",
|
|
2916
2934
|
guidanceLabel: "\u589E\u5F3A\u63D0\u793A\u8BCD",
|
|
2917
2935
|
guidanceHelpLabel: "\u67E5\u770B\u79C1\u804A\u589E\u5F3A\u63D0\u793A\u8BCD\u4F7F\u7528\u8BF4\u660E",
|
|
2918
2936
|
guidanceUsage: "\u7528\u4E8E\u544A\u8BC9\u6A21\u578B\u5982\u4F55\u4F7F\u7528\u5F53\u524D\u79C1\u804A\u6D88\u606F\u7684 <dsh_im_source> \u6765\u6E90\u5B57\u6BB5\u3002\u53EA\u586B\u5199\u6B63\u6587\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u6DFB\u52A0 <dsh_im_source_guidance> \u6210\u5BF9\u6807\u7B7E\u3002",
|
|
@@ -2953,7 +2971,6 @@ function ContextEnhancementScopeEditor({
|
|
|
2953
2971
|
const copy = SCOPE_COPY[kind];
|
|
2954
2972
|
const unavailableId = `${idPrefix}-${kind}-unavailable`;
|
|
2955
2973
|
const fieldsHelpId = `${idPrefix}-${kind}-fields-help`;
|
|
2956
|
-
const senderNameHelpId = `${idPrefix}-${kind}-sender-name-help`;
|
|
2957
2974
|
const guidanceId = `${idPrefix}-${kind}-guidance`;
|
|
2958
2975
|
const guidanceHelpId = `${idPrefix}-${kind}-guidance-help`;
|
|
2959
2976
|
const disabled = busy || !supported;
|
|
@@ -3030,21 +3047,21 @@ function ContextEnhancementScopeEditor({
|
|
|
3030
3047
|
"span",
|
|
3031
3048
|
{ className: "dim-contextFieldText" },
|
|
3032
3049
|
h2("label", { className: "dim-contextFieldName", htmlFor: fieldId }, FIELD_LABELS[field]),
|
|
3033
|
-
field
|
|
3050
|
+
FIELD_HELP[field] ? h2(
|
|
3034
3051
|
"span",
|
|
3035
3052
|
{ className: "dim-contextHelp dim-contextFieldHelp" },
|
|
3036
3053
|
h2("button", {
|
|
3037
3054
|
type: "button",
|
|
3038
3055
|
className: "dim-contextHelpButton dim-contextFieldHelpButton",
|
|
3039
3056
|
disabled,
|
|
3040
|
-
"aria-label": copy.
|
|
3041
|
-
"aria-describedby":
|
|
3057
|
+
"aria-label": copy[FIELD_HELP[field].labelKey],
|
|
3058
|
+
"aria-describedby": `${idPrefix}-${kind}-${field}-help`
|
|
3042
3059
|
}, h2("span", { "aria-hidden": "true" }, "?")),
|
|
3043
3060
|
h2("span", {
|
|
3044
|
-
id:
|
|
3061
|
+
id: `${idPrefix}-${kind}-${field}-help`,
|
|
3045
3062
|
className: "dim-contextTooltip dim-contextFieldTooltip",
|
|
3046
3063
|
role: "tooltip"
|
|
3047
|
-
},
|
|
3064
|
+
}, FIELD_HELP[field].text)
|
|
3048
3065
|
) : null,
|
|
3049
3066
|
h2("label", { className: "dim-contextFieldKey", htmlFor: fieldId }, field)
|
|
3050
3067
|
)
|