@xmanrui/dsh-im 4.36.1 → 4.38.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 +14 -2
- package/README.md +13 -1
- package/assets/logo-plugin-message-link-gradient.webp +0 -0
- package/lib/client.js +417 -189
- package/lib/index.js +317 -316
- package/package.json +2 -2
- package/plugin-src/client/bot-general-settings.js +120 -0
- package/plugin-src/client/channels/dingtalk/api.js +3 -1
- package/plugin-src/client/channels/feishu/api.js +6 -2
- package/plugin-src/client/channels/qq/api.js +3 -1
- package/plugin-src/client/channels/shared/token-api.js +3 -1
- package/plugin-src/client/channels/wecom/api.js +3 -1
- package/plugin-src/client/channels/wecom-app/api.js +3 -1
- package/plugin-src/client/channels/weixin/api.js +3 -1
- package/plugin-src/client/channels/whatsapp/api.js +3 -1
- package/plugin-src/client/delivery-settings.js +5 -1
- package/plugin-src/client/i18n.js +14 -0
- package/plugin-src/client/styles.js +19 -0
- package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
- package/plugin-src/host/channels/email/rpc.mjs +1 -0
- package/plugin-src/host/channels/feishu/production.mjs +1 -0
- package/plugin-src/host/channels/feishu/rpc.mjs +31 -0
- package/plugin-src/host/channels/imessage/rpc.mjs +1 -0
- package/plugin-src/host/channels/matrix/rpc.mjs +10 -0
- package/plugin-src/host/channels/qq/rpc.mjs +11 -0
- package/plugin-src/host/channels/shared/rpc.mjs +9 -0
- package/plugin-src/host/channels/slack/rpc.mjs +10 -0
- package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
- package/plugin-src/host/channels/wecom-app/rpc.mjs +10 -0
- package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
- package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
- package/scripts/verify-package.mjs +11 -6
- package/src/channels/dingtalk/dingtalk-bridge.mjs +31 -2
- package/src/channels/dingtalk/dingtalk-menu.mjs +1 -1
- package/src/channels/dingtalk/dingtalk-runtime.mjs +2 -1
- package/src/channels/discord/discord-runtime.mjs +3 -1
- package/src/channels/feishu/bridge.mjs +91 -15
- package/src/channels/feishu/feishu-cards.mjs +16 -11
- package/src/channels/feishu/feishu-runtime.mjs +10 -1
- package/src/channels/feishu/multi-bot-controller.mjs +18 -0
- package/src/channels/feishu/plugin-config-store.mjs +2 -1
- package/src/channels/feishu/slash-command-panel.mjs +1 -0
- package/src/channels/feishu/step-push-mode.mjs +21 -0
- package/src/channels/matrix/matrix-crypto.mjs +19 -5
- package/src/channels/qq/qq-bridge.mjs +40 -2
- package/src/channels/qq/qq-menu.mjs +2 -2
- package/src/channels/shared/bot-workspace-store.mjs +69 -1
- package/src/channels/shared/busy-message-dispatcher.mjs +94 -0
- package/src/channels/shared/clear-command.mjs +85 -0
- package/src/channels/shared/command-catalog.mjs +3 -0
- package/src/channels/shared/command-permission.mjs +2 -0
- package/src/channels/shared/control-command.mjs +20 -11
- package/src/channels/shared/harness-approval.mjs +102 -2
- package/src/channels/shared/i18n-en/feishu.mjs +6 -4
- package/src/channels/shared/i18n-en/qq.mjs +2 -1
- package/src/channels/shared/i18n-en/shared-b.mjs +27 -0
- package/src/channels/shared/i18n-en/shared-c.mjs +4 -0
- package/src/channels/shared/message-mode.mjs +19 -0
- package/src/channels/shared/text-harness-bridge.mjs +48 -5
- package/src/channels/wecom/wecom-bridge.mjs +26 -2
- package/src/channels/wecom/wecom-cards.mjs +1 -1
- package/src/channels/wecom-app/wecom-app-bridge.mjs +26 -2
- package/src/channels/weixin/weixin-bridge.mjs +22 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SET_MESSAGE_MODE_ENDPOINT, validMessageModePayload } from '../../../../src/channels/shared/message-mode.mjs';
|
|
1
2
|
import { createConnectionDiagnostics, diagnosticRpcResult } from '../../../../src/channels/shared/connection-error.mjs';
|
|
2
3
|
import { SET_ALIAS_ENDPOINT, validAliasPayload } from './bot-alias-rpc.mjs';
|
|
3
4
|
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
@@ -26,6 +27,7 @@ export const TOKEN_BOT_ENDPOINTS = Object.freeze({
|
|
|
26
27
|
setModel: SET_MODEL_ENDPOINT,
|
|
27
28
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
28
29
|
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
30
|
+
setBusyMessageMode: SET_MESSAGE_MODE_ENDPOINT,
|
|
29
31
|
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
|
30
32
|
setAlias: SET_ALIAS_ENDPOINT,
|
|
31
33
|
setThinkingTraces: SET_THINKING_TRACES_ENDPOINT,
|
|
@@ -87,6 +89,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
87
89
|
return validAgentPresetPayload(payload)
|
|
88
90
|
? null : '请选择 Agent Preset。';
|
|
89
91
|
}
|
|
92
|
+
if (endpoint === TOKEN_BOT_ENDPOINTS.setBusyMessageMode) {
|
|
93
|
+
return validMessageModePayload(payload)
|
|
94
|
+
? null : '请提交有效的消息处理方式。';
|
|
95
|
+
}
|
|
90
96
|
if (endpoint === TOKEN_BOT_ENDPOINTS.setContextEnhancement) {
|
|
91
97
|
return validContextEnhancementPayload(payload)
|
|
92
98
|
? null : '请提交有效的上下文增强设置。';
|
|
@@ -188,6 +194,9 @@ export function createTokenBotRpcHandler(controller, { channel }) {
|
|
|
188
194
|
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setModel) {
|
|
189
195
|
if (typeof controller.updateModel !== 'function') throw new Error('Model update is unavailable');
|
|
190
196
|
value = await controller.updateModel(payload.botId, payload.model);
|
|
197
|
+
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setBusyMessageMode) {
|
|
198
|
+
if (typeof controller.updateBusyMessageMode !== 'function') throw new Error('Message mode update is unavailable');
|
|
199
|
+
value = await controller.updateBusyMessageMode(payload.botId, payload.busyMessageMode);
|
|
191
200
|
} else if (endpoint === TOKEN_BOT_ENDPOINTS.setContextEnhancement) {
|
|
192
201
|
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
193
202
|
value = await controller.updateContextEnhancement(payload.botId, payload.config);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SET_MESSAGE_MODE_ENDPOINT, validMessageModePayload } from '../../../../src/channels/shared/message-mode.mjs';
|
|
1
2
|
import { createConnectionDiagnostics, diagnosticRpcResult } from '../../../../src/channels/shared/connection-error.mjs';
|
|
2
3
|
import { SET_ALIAS_ENDPOINT, validAliasPayload } from '../shared/bot-alias-rpc.mjs';
|
|
3
4
|
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
@@ -26,6 +27,7 @@ export const SLACK_ENDPOINTS = Object.freeze({
|
|
|
26
27
|
setModel: SET_MODEL_ENDPOINT,
|
|
27
28
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
28
29
|
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
30
|
+
setBusyMessageMode: SET_MESSAGE_MODE_ENDPOINT,
|
|
29
31
|
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
|
30
32
|
setAlias: SET_ALIAS_ENDPOINT,
|
|
31
33
|
});
|
|
@@ -88,6 +90,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
88
90
|
return validAgentPresetPayload(payload)
|
|
89
91
|
? null : '请选择 Agent Preset。';
|
|
90
92
|
}
|
|
93
|
+
if (endpoint === SLACK_ENDPOINTS.setBusyMessageMode) {
|
|
94
|
+
return validMessageModePayload(payload)
|
|
95
|
+
? null : '请提交有效的消息处理方式。';
|
|
96
|
+
}
|
|
91
97
|
if (endpoint === SLACK_ENDPOINTS.setContextEnhancement) {
|
|
92
98
|
return validContextEnhancementPayload(payload)
|
|
93
99
|
? null : '请提交有效的上下文增强设置。';
|
|
@@ -184,6 +190,10 @@ export function createSlackRpcHandler(controller) {
|
|
|
184
190
|
if (typeof controller.updateModel !== 'function') throw new Error('Model update is unavailable');
|
|
185
191
|
value = await controller.updateModel(payload.botId, payload.model);
|
|
186
192
|
}
|
|
193
|
+
else if (endpoint === SLACK_ENDPOINTS.setBusyMessageMode) {
|
|
194
|
+
if (typeof controller.updateBusyMessageMode !== 'function') throw new Error('Message mode update is unavailable');
|
|
195
|
+
value = await controller.updateBusyMessageMode(payload.botId, payload.busyMessageMode);
|
|
196
|
+
}
|
|
187
197
|
else if (endpoint === SLACK_ENDPOINTS.setContextEnhancement) {
|
|
188
198
|
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
189
199
|
value = await controller.updateContextEnhancement(payload.botId, payload.config);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SET_MESSAGE_MODE_ENDPOINT, validMessageModePayload } from '../../../../src/channels/shared/message-mode.mjs';
|
|
1
2
|
import { createConnectionDiagnostics, diagnosticRpcResult } from '../../../../src/channels/shared/connection-error.mjs';
|
|
2
3
|
import { SET_ALIAS_ENDPOINT, validAliasPayload } from '../shared/bot-alias-rpc.mjs';
|
|
3
4
|
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
@@ -26,6 +27,7 @@ export const WECOM_ENDPOINTS = Object.freeze({
|
|
|
26
27
|
setModel: SET_MODEL_ENDPOINT,
|
|
27
28
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
28
29
|
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
30
|
+
setBusyMessageMode: SET_MESSAGE_MODE_ENDPOINT,
|
|
29
31
|
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
|
30
32
|
setAlias: SET_ALIAS_ENDPOINT,
|
|
31
33
|
});
|
|
@@ -89,6 +91,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
89
91
|
return validAgentPresetPayload(payload)
|
|
90
92
|
? null : '请选择 Agent Preset。';
|
|
91
93
|
}
|
|
94
|
+
if (endpoint === WECOM_ENDPOINTS.setBusyMessageMode) {
|
|
95
|
+
return validMessageModePayload(payload)
|
|
96
|
+
? null : '请提交有效的消息处理方式。';
|
|
97
|
+
}
|
|
92
98
|
if (endpoint === WECOM_ENDPOINTS.setContextEnhancement) {
|
|
93
99
|
return validContextEnhancementPayload(payload)
|
|
94
100
|
? null : '请提交有效的上下文增强设置。';
|
|
@@ -204,6 +210,11 @@ export function createWecomRpcHandler(controller, { encodeQr = qrDataUrl } = {})
|
|
|
204
210
|
await controller.updateModel(payload.botId, payload.model),
|
|
205
211
|
cachedEncode,
|
|
206
212
|
);
|
|
213
|
+
} else if (endpoint === WECOM_ENDPOINTS.setBusyMessageMode) {
|
|
214
|
+
if (typeof controller.updateBusyMessageMode !== 'function') throw new Error('Message mode update is unavailable');
|
|
215
|
+
value = await controller.updateBusyMessageMode(
|
|
216
|
+
payload.botId, payload.busyMessageMode, (status) => publicStatus(status, cachedEncode),
|
|
217
|
+
);
|
|
207
218
|
} else if (endpoint === WECOM_ENDPOINTS.setContextEnhancement) {
|
|
208
219
|
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
209
220
|
value = await controller.updateContextEnhancement(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SET_MESSAGE_MODE_ENDPOINT, validMessageModePayload } from '../../../../src/channels/shared/message-mode.mjs';
|
|
1
2
|
import { createConnectionDiagnostics, diagnosticRpcResult } from '../../../../src/channels/shared/connection-error.mjs';
|
|
2
3
|
import { SET_ALIAS_ENDPOINT, validAliasPayload } from '../shared/bot-alias-rpc.mjs';
|
|
3
4
|
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
@@ -24,6 +25,7 @@ export const WECOM_APP_ENDPOINTS = Object.freeze({
|
|
|
24
25
|
setModel: SET_MODEL_ENDPOINT,
|
|
25
26
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
26
27
|
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
28
|
+
setBusyMessageMode: SET_MESSAGE_MODE_ENDPOINT,
|
|
27
29
|
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
|
28
30
|
setAlias: SET_ALIAS_ENDPOINT,
|
|
29
31
|
});
|
|
@@ -110,6 +112,9 @@ function payloadFailure(endpoint, payload) {
|
|
|
110
112
|
if (endpoint === WECOM_APP_ENDPOINTS.setAgentPreset) {
|
|
111
113
|
return validAgentPresetPayload(payload) ? null : '请选择 Agent Preset。';
|
|
112
114
|
}
|
|
115
|
+
if (endpoint === WECOM_APP_ENDPOINTS.setBusyMessageMode) {
|
|
116
|
+
return validMessageModePayload(payload) ? null : '请提交有效的消息处理方式。';
|
|
117
|
+
}
|
|
113
118
|
if (endpoint === WECOM_APP_ENDPOINTS.setContextEnhancement) {
|
|
114
119
|
return validContextEnhancementPayload(payload) ? null : '请提交有效的上下文增强设置。';
|
|
115
120
|
}
|
|
@@ -191,6 +196,11 @@ export function createWecomAppRpcHandler(controller) {
|
|
|
191
196
|
} else if (endpoint === WECOM_APP_ENDPOINTS.setModel) {
|
|
192
197
|
if (typeof controller.updateModel !== 'function') throw new Error('Model update is unavailable');
|
|
193
198
|
value = await publicStatus(await controller.updateModel(payload.botId, payload.model));
|
|
199
|
+
} else if (endpoint === WECOM_APP_ENDPOINTS.setBusyMessageMode) {
|
|
200
|
+
if (typeof controller.updateBusyMessageMode !== 'function') throw new Error('Message mode update is unavailable');
|
|
201
|
+
value = await controller.updateBusyMessageMode(
|
|
202
|
+
payload.botId, payload.busyMessageMode, (status) => publicStatus(status),
|
|
203
|
+
);
|
|
194
204
|
} else if (endpoint === WECOM_APP_ENDPOINTS.setContextEnhancement) {
|
|
195
205
|
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
196
206
|
value = await controller.updateContextEnhancement(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SET_MESSAGE_MODE_ENDPOINT, validMessageModePayload } from '../../../../src/channels/shared/message-mode.mjs';
|
|
1
2
|
import { SET_ALIAS_ENDPOINT, validAliasPayload } from '../shared/bot-alias-rpc.mjs';
|
|
2
3
|
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
3
4
|
import QRCode from 'qrcode';
|
|
@@ -32,6 +33,7 @@ export const WEIXIN_ENDPOINTS = Object.freeze({
|
|
|
32
33
|
setModel: SET_MODEL_ENDPOINT,
|
|
33
34
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
34
35
|
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
36
|
+
setBusyMessageMode: SET_MESSAGE_MODE_ENDPOINT,
|
|
35
37
|
setAccessPolicy: SET_ACCESS_POLICY_ENDPOINT,
|
|
36
38
|
setAlias: SET_ALIAS_ENDPOINT,
|
|
37
39
|
});
|
|
@@ -95,6 +97,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
95
97
|
return validAgentPresetPayload(payload)
|
|
96
98
|
? null : '请选择 Agent Preset。';
|
|
97
99
|
}
|
|
100
|
+
if (endpoint === WEIXIN_ENDPOINTS.setBusyMessageMode) {
|
|
101
|
+
return validMessageModePayload(payload)
|
|
102
|
+
? null : '请提交有效的消息处理方式。';
|
|
103
|
+
}
|
|
98
104
|
if (endpoint === WEIXIN_ENDPOINTS.setContextEnhancement) {
|
|
99
105
|
return validContextEnhancementPayload(payload)
|
|
100
106
|
? null : '请提交有效的上下文增强设置。';
|
|
@@ -235,6 +241,11 @@ export function createWeixinRpcHandler(controller, { encodeQr = qrDataUrl, logge
|
|
|
235
241
|
await controller.updateModel(payload.botId, payload.model),
|
|
236
242
|
cachedEncode,
|
|
237
243
|
);
|
|
244
|
+
} else if (endpoint === WEIXIN_ENDPOINTS.setBusyMessageMode) {
|
|
245
|
+
if (typeof controller.updateBusyMessageMode !== 'function') throw new Error('Message mode update is unavailable');
|
|
246
|
+
value = await controller.updateBusyMessageMode(
|
|
247
|
+
payload.botId, payload.busyMessageMode, (status) => publicStatus(status, cachedEncode),
|
|
248
|
+
);
|
|
238
249
|
} else if (endpoint === WEIXIN_ENDPOINTS.setContextEnhancement) {
|
|
239
250
|
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
240
251
|
value = await controller.updateContextEnhancement(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SET_MESSAGE_MODE_ENDPOINT, validMessageModePayload } from '../../../../src/channels/shared/message-mode.mjs';
|
|
1
2
|
import { createConnectionDiagnostics, diagnosticRpcResult } from '../../../../src/channels/shared/connection-error.mjs';
|
|
2
3
|
import { SET_ALIAS_ENDPOINT, validAliasPayload } from '../shared/bot-alias-rpc.mjs';
|
|
3
4
|
import { registerManagementRpc } from '../../../management-rpc.mjs';
|
|
@@ -25,6 +26,7 @@ export const WHATSAPP_ENDPOINTS = Object.freeze({
|
|
|
25
26
|
setModel: SET_MODEL_ENDPOINT,
|
|
26
27
|
setAgentPreset: SET_AGENT_PRESET_ENDPOINT,
|
|
27
28
|
setContextEnhancement: SET_CONTEXT_ENHANCEMENT_ENDPOINT,
|
|
29
|
+
setBusyMessageMode: SET_MESSAGE_MODE_ENDPOINT,
|
|
28
30
|
});
|
|
29
31
|
export const WHATSAPP_RPC_ENDPOINTS = Object.freeze(Object.values(WHATSAPP_ENDPOINTS));
|
|
30
32
|
|
|
@@ -79,6 +81,10 @@ function payloadFailure(endpoint, payload) {
|
|
|
79
81
|
return validAgentPresetPayload(payload)
|
|
80
82
|
? null : '请选择 Agent Preset。';
|
|
81
83
|
}
|
|
84
|
+
if (endpoint === WHATSAPP_ENDPOINTS.setBusyMessageMode) {
|
|
85
|
+
return validMessageModePayload(payload)
|
|
86
|
+
? null : '请提交有效的消息处理方式。';
|
|
87
|
+
}
|
|
82
88
|
if (endpoint === WHATSAPP_ENDPOINTS.setContextEnhancement) {
|
|
83
89
|
return validContextEnhancementPayload(payload)
|
|
84
90
|
? null : '请提交有效的上下文增强设置。';
|
|
@@ -192,6 +198,11 @@ export function createWhatsappRpcHandler(controller, { encodeQr = qrDataUrl } =
|
|
|
192
198
|
await controller.updateModel(payload.botId, payload.model),
|
|
193
199
|
cachedEncode,
|
|
194
200
|
);
|
|
201
|
+
} else if (endpoint === WHATSAPP_ENDPOINTS.setBusyMessageMode) {
|
|
202
|
+
if (typeof controller.updateBusyMessageMode !== 'function') throw new Error('Message mode update is unavailable');
|
|
203
|
+
value = await controller.updateBusyMessageMode(
|
|
204
|
+
payload.botId, payload.busyMessageMode, (status) => publicStatus(status, cachedEncode),
|
|
205
|
+
);
|
|
195
206
|
} else if (endpoint === WHATSAPP_ENDPOINTS.setContextEnhancement) {
|
|
196
207
|
if (typeof controller.updateContextEnhancement !== 'function') throw new Error('Context enhancement update is unavailable');
|
|
197
208
|
value = await controller.updateContextEnhancement(
|
|
@@ -148,27 +148,32 @@ if (client.includes('settings.plugins.tab') || clientSources.includes('settings.
|
|
|
148
148
|
}
|
|
149
149
|
// Connections still have no channel-enable toggle. Checkable inputs are owned
|
|
150
150
|
// only by the shared context editor, the saved-target Session sync row, the
|
|
151
|
-
// email settings,
|
|
151
|
+
// email settings, the Telegram thinking-traces block, and Feishu panel settings.
|
|
152
152
|
// The context editor contains one switch template and one mapped field-input
|
|
153
153
|
// template; the delivery target adds one ordinary checkbox template; the
|
|
154
|
-
// Telegram thinking-traces block adds one ordinary checkbox template.
|
|
154
|
+
// Telegram thinking-traces block adds one ordinary checkbox template. General
|
|
155
|
+
// settings adds one mapped switch template for the two Feishu panel preferences.
|
|
155
156
|
const contextEditorSource = await readFile(resolve(root, 'plugin-src/client/context-enhancement.js'), 'utf8');
|
|
156
157
|
const deliverySettingsSource = await readFile(resolve(root, 'plugin-src/client/delivery-settings.js'), 'utf8');
|
|
157
158
|
const emailSettingsSource = await readFile(resolve(root, 'plugin-src/client/channels/email/index.js'), 'utf8');
|
|
158
159
|
const thinkingTracesSource = await readFile(resolve(root, 'plugin-src/client/channels/telegram/thinking-traces.js'), 'utf8');
|
|
160
|
+
const botGeneralSettingsSource = await readFile(resolve(root, 'plugin-src/client/bot-general-settings.js'), 'utf8');
|
|
159
161
|
const otherClientSources = clientSources
|
|
160
162
|
.replace(contextEditorSource, '')
|
|
161
163
|
.replace(deliverySettingsSource, '')
|
|
162
164
|
.replace(emailSettingsSource, '')
|
|
163
|
-
.replace(thinkingTracesSource, '')
|
|
165
|
+
.replace(thinkingTracesSource, '')
|
|
166
|
+
.replace(botGeneralSettingsSource, '');
|
|
164
167
|
if (/role:\s*["']switch|type:\s*["']checkbox/.test(otherClientSources)
|
|
165
168
|
|| (deliverySettingsSource.match(/type:\s*["']checkbox["']/g) ?? []).length !== 1
|
|
166
169
|
|| /role:\s*["']switch["']/u.test(deliverySettingsSource)
|
|
167
170
|
|| (thinkingTracesSource.match(/type:\s*["']checkbox["']/g) ?? []).length !== 1
|
|
168
171
|
|| /role:\s*["']switch["']/u.test(thinkingTracesSource)
|
|
169
|
-
|| (
|
|
170
|
-
|| (
|
|
171
|
-
|
|
172
|
+
|| (botGeneralSettingsSource.match(/type:\s*["']checkbox["']/g) ?? []).length !== 1
|
|
173
|
+
|| (botGeneralSettingsSource.match(/role:\s*["']switch["']/g) ?? []).length !== 1
|
|
174
|
+
|| (client.match(/role:\s*["']switch["']/g) ?? []).length !== 2
|
|
175
|
+
|| (client.match(/type:\s*["']checkbox["']/g) ?? []).length !== 5) {
|
|
176
|
+
throw new Error('checkable inputs must be limited to context enhancement, Session sync, email settings, Telegram thinking traces, and Feishu panel settings');
|
|
172
177
|
}
|
|
173
178
|
for (const marker of ['bot.context-enhancement.set', '<dsh_im_source>', '<dsh_im_source_guidance>']) {
|
|
174
179
|
if (!host.includes(marker) || !client.includes(marker)) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BusyMessageDispatcher, canAutomaticallySteer } from '../shared/busy-message-dispatcher.mjs';
|
|
1
2
|
import { createDeferredDeliveryCoordinator, deferredOutcomeText } from '../shared/deferred-delivery-coordinator.mjs';
|
|
2
3
|
import {
|
|
3
4
|
DINGTALK_DONE_REACTION_NAME,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
} from '../shared/harness-question.mjs';
|
|
16
17
|
import { HarnessApprovalQueue } from '../shared/harness-approval.mjs';
|
|
17
18
|
import { runCompactCommand } from '../shared/compact-command.mjs';
|
|
19
|
+
import { isClearCommand, runClearCommand } from '../shared/clear-command.mjs';
|
|
18
20
|
import { isHistoryCommand, runHistoryCommand } from '../shared/history-command.mjs';
|
|
19
21
|
import {
|
|
20
22
|
isControlCommand,
|
|
@@ -87,6 +89,7 @@ const HELP_TEXT_LINES = [
|
|
|
87
89
|
'/m 或 /menu 打开下拉操作菜单',
|
|
88
90
|
'/new 开启一个全新会话',
|
|
89
91
|
'/compact 压缩当前会话的较早上下文',
|
|
92
|
+
'/clear 清空当前会话上下文(保留 Session 绑定和历史记录)',
|
|
90
93
|
'/history [数量] 查看最近历史消息(默认 3 条,最多 5 条)',
|
|
91
94
|
'/workspace 工作区序号或绝对路径 切换工作区',
|
|
92
95
|
'/workspacelist 列出工作区绝对路径',
|
|
@@ -539,6 +542,7 @@ export class DingtalkHarnessBridge {
|
|
|
539
542
|
#maxMessageChars;
|
|
540
543
|
#signal;
|
|
541
544
|
#queues = new Map();
|
|
545
|
+
#busyMessages = new BusyMessageDispatcher();
|
|
542
546
|
#pendingInteractions = new Map();
|
|
543
547
|
#interactionKeys = new Map();
|
|
544
548
|
#interactionTasks = new Set();
|
|
@@ -597,7 +601,7 @@ export class DingtalkHarnessBridge {
|
|
|
597
601
|
return structuredClone(this.#status);
|
|
598
602
|
}
|
|
599
603
|
|
|
600
|
-
accept(message, { contextSnapshot } = {}) {
|
|
604
|
+
accept(message, { contextSnapshot, busyMessageMode } = {}) {
|
|
601
605
|
if (this.#signal?.aborted) return Promise.resolve();
|
|
602
606
|
const messageId = nonEmptyString(message?.msgId);
|
|
603
607
|
const sender = senderStaffId(message);
|
|
@@ -716,6 +720,7 @@ export class DingtalkHarnessBridge {
|
|
|
716
720
|
const commandRunner = isDingtalkMenuCommand(commandText)
|
|
717
721
|
&& !hasInboundFiles(promptMessage) && !hasInboundImages(promptMessage)
|
|
718
722
|
? async () => { await this.#showMenu(message, key); }
|
|
723
|
+
: isClearCommand(commandText) ? runClearCommand
|
|
719
724
|
: isHistoryCommand(commandText) ? runHistoryCommand
|
|
720
725
|
: hasInboundFiles(promptMessage) ? null : isControlCommand(commandText)
|
|
721
726
|
? runControlCommand
|
|
@@ -834,7 +839,28 @@ export class DingtalkHarnessBridge {
|
|
|
834
839
|
pending.queue = current;
|
|
835
840
|
return finish(current);
|
|
836
841
|
}
|
|
837
|
-
return finish(this.#
|
|
842
|
+
return finish(this.#busyMessages.dispatch({
|
|
843
|
+
key, messageId, text: commandText, mode: busyMessageMode,
|
|
844
|
+
onFailure: (error) => this.#finishStatusReaction(statusReaction,
|
|
845
|
+
this.#signal?.aborted || error?.code === 'turn-stopped' ? 'clear' : 'error'),
|
|
846
|
+
eligible: () => Boolean(sessionWebhook) && addressed && String(message.msgtype).toLowerCase() === 'text'
|
|
847
|
+
&& !hasInboundImages(promptMessage) && !hasInboundFiles(promptMessage)
|
|
848
|
+
&& !hasReplyReference(promptMessage) && !isDingtalkMenuCommand(commandText)
|
|
849
|
+
&& canAutomaticallySteer(this.#accessPolicy, conversationType, sender),
|
|
850
|
+
harness: this.#harness, state: this.#state, status: this.#status,
|
|
851
|
+
signal: this.#signal, control: { owner: this, key }, logger: this.#logger,
|
|
852
|
+
acceptedMessageIds: this.#acceptedMessageIds,
|
|
853
|
+
pendingInteraction: () => this.#pendingInteractions.has(key) || this.#approvals.hasPending(key),
|
|
854
|
+
enhancement: {
|
|
855
|
+
snapshot: this.#acceptedMessageIds.get(messageId),
|
|
856
|
+
source: () => ({ channel: 'dingtalk', senderId: sender, senderName: message.senderNick,
|
|
857
|
+
conversationTitle: message.conversationTitle, chatId: message.conversationId }),
|
|
858
|
+
},
|
|
859
|
+
isQueued: () => this.#queues.has(key),
|
|
860
|
+
enqueue: (options) => this.#enqueueMessage(message, messageId, sender, key, { ...options, statusReaction }),
|
|
861
|
+
send: (reply) => sessionWebhook && addressed
|
|
862
|
+
? this.#send(sessionWebhook, reply, this.#atUsersFor(message)) : Promise.resolve(),
|
|
863
|
+
}));
|
|
838
864
|
}
|
|
839
865
|
|
|
840
866
|
async #showMenu(message, key) {
|
|
@@ -933,6 +959,7 @@ export class DingtalkHarnessBridge {
|
|
|
933
959
|
result = { message: helpText() };
|
|
934
960
|
} else {
|
|
935
961
|
result = await runWorkspaceCommand(command, this.#harness, key)
|
|
962
|
+
?? await runClearCommand(command, this.#harness, this.#state, key, options)
|
|
936
963
|
?? await runCompactCommand(command, this.#harness, this.#state, key, options)
|
|
937
964
|
?? await runControlCommand(command, this.#harness, this.#state, key, options)
|
|
938
965
|
?? await runHistoryCommand(command, this.#harness, this.#state, key, options)
|
|
@@ -1133,6 +1160,7 @@ export class DingtalkHarnessBridge {
|
|
|
1133
1160
|
}
|
|
1134
1161
|
|
|
1135
1162
|
async waitForIdle() {
|
|
1163
|
+
await this.#busyMessages.whenIdle();
|
|
1136
1164
|
await Promise.allSettled([
|
|
1137
1165
|
...this.#queues.values(),
|
|
1138
1166
|
...[...this.#pendingInteractions.values()].flatMap((pending) => (
|
|
@@ -1162,6 +1190,7 @@ export class DingtalkHarnessBridge {
|
|
|
1162
1190
|
hasFiles: hasInboundFiles(prompt),
|
|
1163
1191
|
pendingInteraction: this.#pendingInteractions.has(key)
|
|
1164
1192
|
|| this.#approvals.hasPending(key),
|
|
1193
|
+
busy: this.#queues.has(key) || this.#batchInputs.status(key).phase !== 'idle',
|
|
1165
1194
|
control: { owner: this, key },
|
|
1166
1195
|
deferredDelivery: this.#deferred,
|
|
1167
1196
|
enhancement: captureContextEnhancementSource(
|
|
@@ -5,7 +5,7 @@ import { t } from '../shared/i18n.mjs';
|
|
|
5
5
|
export const DINGTALK_MENU_TEMPLATE_ID = '9ca31362-e5b3-409c-a694-6993706a6004.schema';
|
|
6
6
|
export const DINGTALK_CARD_TOPIC = '/v1.0/card/instances/callback';
|
|
7
7
|
export const DINGTALK_MENU_BUTTONS = Object.freeze({
|
|
8
|
-
new: '/new', history: '/history', stop: '/stop', compact: '/compact',
|
|
8
|
+
new: '/new', history: '/history', stop: '/stop', compact: '/compact', clear: '/clear',
|
|
9
9
|
status: '/status', help: '/help',
|
|
10
10
|
});
|
|
11
11
|
|
|
@@ -311,6 +311,7 @@ export class DingtalkRuntime {
|
|
|
311
311
|
} catch {
|
|
312
312
|
// Optional settings failures leave the original message path active.
|
|
313
313
|
}
|
|
314
|
+
const busyMessageMode = this.#harness.currentBusyMessageMode?.() ?? 'queue';
|
|
314
315
|
const task = Promise.resolve().then(async () => {
|
|
315
316
|
if (this.#bridge !== bridge) return;
|
|
316
317
|
let message;
|
|
@@ -330,7 +331,7 @@ export class DingtalkRuntime {
|
|
|
330
331
|
get botId() { return contextEnhancement?.botId; },
|
|
331
332
|
}, message.conversationType === '1' || message.conversationType === 1 ? 'direct'
|
|
332
333
|
: message.conversationType === '2' || message.conversationType === 2 ? 'group' : null);
|
|
333
|
-
await bridge.accept(message, { contextSnapshot });
|
|
334
|
+
await bridge.accept(message, { contextSnapshot, busyMessageMode });
|
|
334
335
|
}).catch(() => {
|
|
335
336
|
if (signal.aborted || this.#bridge !== bridge) return;
|
|
336
337
|
this.#status.lastError = t('钉钉消息处理失败。');
|
|
@@ -876,13 +876,14 @@ export class DiscordRuntime {
|
|
|
876
876
|
this.#contextEnhancement,
|
|
877
877
|
message.guild_id ? 'group' : 'direct',
|
|
878
878
|
);
|
|
879
|
+
const busyMessageMode = this.#harness.currentBusyMessageMode?.() ?? 'queue';
|
|
879
880
|
const pendingRoute = resolveDiscordMessageRoute(message, this.#config.platformId, {
|
|
880
881
|
api: this.#api,
|
|
881
882
|
channel: this.#channels.get(String(message.channel_id)),
|
|
882
883
|
signal: this.#abortController?.signal,
|
|
883
884
|
onChannel: (resolved) => this.#rememberChannel(resolved),
|
|
884
885
|
});
|
|
885
|
-
route = { pendingRoute, contextSnapshot };
|
|
886
|
+
route = { pendingRoute, contextSnapshot, busyMessageMode };
|
|
886
887
|
this.#routing.set(messageId, route);
|
|
887
888
|
void pendingRoute.finally(() => {
|
|
888
889
|
if (this.#routing.get(messageId) === route) this.#routing.delete(messageId);
|
|
@@ -893,6 +894,7 @@ export class DiscordRuntime {
|
|
|
893
894
|
if (normalized) {
|
|
894
895
|
await bridge.accept(normalized, {
|
|
895
896
|
contextSnapshot: route.contextSnapshot,
|
|
897
|
+
busyMessageMode: route.busyMessageMode,
|
|
896
898
|
...(accessDecision ? { accessDecision } : {}),
|
|
897
899
|
});
|
|
898
900
|
}
|