@xmanrui/dsh-im 4.35.1 → 4.36.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/PROACTIVE_DELIVERY.en.md +50 -0
- package/PROACTIVE_DELIVERY.md +22 -0
- package/README.en.md +3 -1
- package/README.md +3 -1
- package/lib/client.js +4 -3
- package/lib/index.js +309 -309
- package/package.json +3 -3
- package/plugin-src/host/channels/dingtalk/production.mjs +1 -1
- package/plugin-src/host/channels/feishu/production.mjs +4 -2
- package/plugin-src/host/channels/matrix/production.mjs +1 -1
- package/plugin-src/host/channels/qq/production.mjs +1 -1
- package/plugin-src/host/channels/shared/production.mjs +1 -1
- package/plugin-src/host/channels/slack/production.mjs +1 -1
- package/plugin-src/host/channels/wecom/production.mjs +1 -1
- package/plugin-src/host/channels/wecom-app/production.mjs +1 -1
- package/plugin-src/host/channels/weixin/production.mjs +1 -1
- package/plugin-src/host/channels/whatsapp/production.mjs +1 -1
- package/plugin-src/host/delivery-adapter.mjs +60 -12
- package/plugin-src/host/delivery-service.mjs +127 -1
- package/plugin-src/host/delivery-suggestions.mjs +2 -1
- package/plugin-src/host/harness-connection.mjs +3 -7
- package/plugin-src/host/index.mjs +5 -2
- package/plugin-src/host/modern-harness-api.mjs +139 -4
- package/src/channels/dingtalk/dingtalk-bridge.mjs +6 -0
- package/src/channels/dingtalk/dingtalk-controller.mjs +14 -0
- package/src/channels/dingtalk/dingtalk-runtime.mjs +10 -0
- package/src/channels/discord/discord-runtime.mjs +13 -0
- package/src/channels/feishu/bridge.mjs +30 -13
- package/src/channels/feishu/external-consumer.mjs +118 -0
- package/src/channels/feishu/feishu-runtime.mjs +72 -3
- package/src/channels/feishu/history-reader.mjs +92 -0
- package/src/channels/feishu/multi-bot-controller.mjs +130 -2
- package/src/channels/feishu/nearby-history.mjs +72 -0
- package/src/channels/feishu/plugin-config-store.mjs +1 -0
- package/src/channels/matrix/matrix-controller.mjs +9 -0
- package/src/channels/matrix/matrix-runtime.mjs +14 -0
- package/src/channels/qq/qq-bridge.mjs +6 -0
- package/src/channels/qq/qq-controller.mjs +14 -0
- package/src/channels/qq/qq-runtime.mjs +10 -0
- package/src/channels/shared/harness-approval.mjs +84 -7
- package/src/channels/shared/harness-client.mjs +36 -32
- package/src/channels/shared/i18n-en/shared-c.mjs +3 -0
- package/src/channels/shared/text-harness-bridge.mjs +6 -0
- package/src/channels/shared/token-bot-controller.mjs +16 -0
- package/src/channels/slack/manifest.mjs +1 -0
- package/src/channels/slack/slack-api.mjs +7 -0
- package/src/channels/slack/slack-controller.mjs +14 -0
- package/src/channels/slack/slack-runtime.mjs +12 -0
- package/src/channels/telegram/telegram-runtime.mjs +10 -0
- package/src/channels/wecom/wecom-bridge.mjs +6 -0
- package/src/channels/wecom/wecom-controller.mjs +14 -0
- package/src/channels/wecom/wecom-runtime.mjs +10 -0
- package/src/channels/wecom-app/wecom-app-bridge.mjs +6 -0
- package/src/channels/wecom-app/wecom-app-controller.mjs +14 -0
- package/src/channels/wecom-app/wecom-app-runtime.mjs +10 -0
- package/src/channels/weixin/weixin-bridge.mjs +6 -0
- package/src/channels/weixin/weixin-controller.mjs +14 -0
- package/src/channels/weixin/weixin-runtime.mjs +10 -0
- package/src/channels/whatsapp/whatsapp-controller.mjs +14 -0
- package/src/channels/whatsapp/whatsapp-runtime.mjs +10 -0
|
@@ -70,6 +70,9 @@ export default {
|
|
|
70
70
|
'已批准,仅对本次操作有效。':
|
|
71
71
|
'Approved — valid for this operation only.',
|
|
72
72
|
'已拒绝此次操作。': 'This operation was rejected.',
|
|
73
|
+
'机器人端无法处理这次审批,请到 Web 查看。': 'The bot cannot handle this approval. Please check the Web interface.',
|
|
74
|
+
'未找到可处理端,本次操作未获批准。': 'No approval interface is available. This operation was not approved.',
|
|
75
|
+
'有操作在等待审批:{tool},请到 Web 处理。': 'An operation is awaiting approval: {tool}. Please handle it in the Web interface.',
|
|
73
76
|
'无法完整展示这次操作,已安全拒绝此次审批。':
|
|
74
77
|
'The operation could not be displayed in full, so this approval was safely rejected.',
|
|
75
78
|
'审批提交失败,请重新回复「批准」或「拒绝」。':
|
|
@@ -1381,6 +1381,12 @@ export class TextHarnessBridge {
|
|
|
1381
1381
|
});
|
|
1382
1382
|
}
|
|
1383
1383
|
|
|
1384
|
+
async presentSessionSyncApproval(interaction, context, options = {}) {
|
|
1385
|
+
return this.#approvals.handleSessionSyncRequested(interaction, context, {
|
|
1386
|
+
...options, runtimeSignal: this.#signal ?? options.runtimeSignal, accessPolicy: this.#accessPolicy,
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1384
1390
|
async #handleInteraction(interaction, {
|
|
1385
1391
|
key,
|
|
1386
1392
|
actor,
|
|
@@ -247,6 +247,22 @@ export class TokenBotController {
|
|
|
247
247
|
});
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
async presentSessionSyncApproval(botId, target, interaction, options = {}) {
|
|
251
|
+
const config = this.#configStore.get(botId);
|
|
252
|
+
if (!config) throw new Error(`Unknown ${this.#descriptor.label} bot`);
|
|
253
|
+
return this.#withBotTransition(botId, async () => {
|
|
254
|
+
const runtime = this.#runtimes.get(botId);
|
|
255
|
+
if (!runtime?.status?.ready || typeof runtime.presentSessionSyncApproval !== 'function') {
|
|
256
|
+
const error = new Error(t('{label}机器人尚未连接', {
|
|
257
|
+
label: this.#descriptor.label,
|
|
258
|
+
}));
|
|
259
|
+
error.code = 'bot-not-connected';
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
return runtime.presentSessionSyncApproval(target, interaction, options);
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
250
266
|
async deleteBot(botId) {
|
|
251
267
|
const warnings = [];
|
|
252
268
|
const config = this.#configStore.get(botId);
|
|
@@ -234,6 +234,13 @@ export class SlackApi {
|
|
|
234
234
|
});
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
async conversationInfo({ channelId, signal } = {}) {
|
|
238
|
+
const value = await this.#request('conversations.info', {
|
|
239
|
+
tokenKind: 'bot', signal, body: { channel: slackId(channelId, 'channel id') },
|
|
240
|
+
});
|
|
241
|
+
return value.channel;
|
|
242
|
+
}
|
|
243
|
+
|
|
237
244
|
async fileInfo({ fileId, signal } = {}) {
|
|
238
245
|
const value = await this.#request('files.info', {
|
|
239
246
|
tokenKind: 'bot',
|
|
@@ -207,6 +207,20 @@ export class SlackController {
|
|
|
207
207
|
});
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
+
async presentSessionSyncApproval(botId, target, interaction, options = {}) {
|
|
211
|
+
const config = this.#configStore.get(botId);
|
|
212
|
+
if (!config) throw new Error('Unknown Slack bot');
|
|
213
|
+
return this.#withBotTransition(botId, async () => {
|
|
214
|
+
const runtime = this.#runtimes.get(botId);
|
|
215
|
+
if (!runtime?.status?.ready || typeof runtime.presentSessionSyncApproval !== 'function') {
|
|
216
|
+
const error = new Error(t('Slack机器人尚未连接'));
|
|
217
|
+
error.code = 'bot-not-connected';
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
return runtime.presentSessionSyncApproval(target, interaction, options);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
210
224
|
async deleteBot(botId) {
|
|
211
225
|
const warnings = [];
|
|
212
226
|
const config = this.#configStore.get(botId);
|
|
@@ -473,6 +473,18 @@ export class SlackRuntime {
|
|
|
473
473
|
return this.#bridge.sendConnectionTest(text);
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
+
async presentSessionSyncApproval(target, interaction, options = {}) {
|
|
477
|
+
if (!this.#status.ready || !this.#bridge) return false;
|
|
478
|
+
const channelId = target?.route?.channelId;
|
|
479
|
+
const channel = await this.#api.conversationInfo({ channelId, signal: options.signal });
|
|
480
|
+
const actor = channel?.is_im === true && typeof channel.user === 'string' ? channel.user : '';
|
|
481
|
+
if (!actor) return false;
|
|
482
|
+
return this.#bridge.presentSessionSyncApproval(interaction, {
|
|
483
|
+
key: options.key, actor, validate: options.validate,
|
|
484
|
+
send: (text) => this.sendProactiveText(target, text),
|
|
485
|
+
}, options);
|
|
486
|
+
}
|
|
487
|
+
|
|
476
488
|
async sendProactiveText(target, text, options = {}) {
|
|
477
489
|
if (!this.#status.ready || !this.#bridge) {
|
|
478
490
|
const error = new Error('Slack bot is not connected');
|
|
@@ -1171,6 +1171,16 @@ export class TelegramRuntime {
|
|
|
1171
1171
|
return this.#bridge.sendConnectionTest(text);
|
|
1172
1172
|
}
|
|
1173
1173
|
|
|
1174
|
+
async presentSessionSyncApproval(target, interaction, options = {}) {
|
|
1175
|
+
if (!this.#status.ready || !this.#bridge) return false;
|
|
1176
|
+
const actor = typeof target?.route?.chatId === 'string' ? target.route.chatId.trim() : '';
|
|
1177
|
+
if (!actor) return false;
|
|
1178
|
+
return this.#bridge.presentSessionSyncApproval(interaction, {
|
|
1179
|
+
key: options.key, actor, validate: options.validate,
|
|
1180
|
+
send: (text) => this.sendProactiveText(target, text),
|
|
1181
|
+
}, options);
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1174
1184
|
async sendProactiveText(target, text, options = {}) {
|
|
1175
1185
|
if (!this.#status.ready || !this.#bridge) {
|
|
1176
1186
|
const error = new Error('Telegram bot is not connected');
|
|
@@ -1668,6 +1668,12 @@ export class WecomHarnessBridge {
|
|
|
1668
1668
|
}
|
|
1669
1669
|
}
|
|
1670
1670
|
|
|
1671
|
+
async presentSessionSyncApproval(interaction, context, options = {}) {
|
|
1672
|
+
return this.#approvals.handleSessionSyncRequested(interaction, context, {
|
|
1673
|
+
...options, runtimeSignal: this.#signal, accessPolicy: this.#accessPolicy,
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1671
1677
|
async #handleInteraction(interaction, {
|
|
1672
1678
|
key,
|
|
1673
1679
|
actor,
|
|
@@ -281,6 +281,20 @@ export class WecomController {
|
|
|
281
281
|
});
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
+
async presentSessionSyncApproval(botId, target, interaction, options = {}) {
|
|
285
|
+
const config = this.#configStore.get(botId);
|
|
286
|
+
if (!config) throw new Error('Unknown Enterprise WeChat bot');
|
|
287
|
+
return this.#withBotTransition(botId, async () => {
|
|
288
|
+
const runtime = this.#runtimes.get(botId);
|
|
289
|
+
if (!runtime?.status?.ready || typeof runtime.presentSessionSyncApproval !== 'function') {
|
|
290
|
+
const error = new Error(t('企业微信连接当前离线'));
|
|
291
|
+
error.code = 'bot-not-connected';
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
return runtime.presentSessionSyncApproval(target, interaction, options);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
284
298
|
async deleteBot(botId) {
|
|
285
299
|
const warnings = [];
|
|
286
300
|
const config = this.#configStore.get(botId);
|
|
@@ -230,6 +230,16 @@ export class WecomRuntime {
|
|
|
230
230
|
});
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
async presentSessionSyncApproval(target, interaction, options = {}) {
|
|
234
|
+
if (!this.#status.ready || !this.#bridge) return false;
|
|
235
|
+
const actor = typeof target?.route?.chatId === 'string' ? target.route.chatId.trim() : '';
|
|
236
|
+
if (!actor) return false;
|
|
237
|
+
return this.#bridge.presentSessionSyncApproval(interaction, {
|
|
238
|
+
key: options.key, actor, validate: options.validate,
|
|
239
|
+
send: (text) => this.sendProactiveText(target, text),
|
|
240
|
+
}, options);
|
|
241
|
+
}
|
|
242
|
+
|
|
233
243
|
async sendProactiveText(target, text, { signal } = {}) {
|
|
234
244
|
const chatId = typeof target?.route?.chatId === 'string'
|
|
235
245
|
? target.route.chatId.trim() : '';
|
|
@@ -855,6 +855,12 @@ export class WecomAppBridge {
|
|
|
855
855
|
}
|
|
856
856
|
}
|
|
857
857
|
|
|
858
|
+
async presentSessionSyncApproval(interaction, context, options = {}) {
|
|
859
|
+
return this.#approvals.handleSessionSyncRequested(interaction, context, {
|
|
860
|
+
...options, runtimeSignal: this.#signal, accessPolicy: this.#accessPolicy,
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
|
|
858
864
|
async #handleInteraction(interaction, { key, actor }) {
|
|
859
865
|
if (interaction?.kind === 'approval') {
|
|
860
866
|
return this.#approvals.handleRequested(interaction, {
|
|
@@ -290,6 +290,20 @@ export class WecomAppController {
|
|
|
290
290
|
});
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
+
async presentSessionSyncApproval(botId, target, interaction, options = {}) {
|
|
294
|
+
const config = this.#configStore.get(botId);
|
|
295
|
+
if (!config) throw new Error('Unknown Enterprise WeChat app bot');
|
|
296
|
+
return this.#withBotTransition(botId, async () => {
|
|
297
|
+
const runtime = this.#runtimes.get(botId);
|
|
298
|
+
if (!runtime?.status?.ready || typeof runtime.presentSessionSyncApproval !== 'function') {
|
|
299
|
+
const error = new Error(t('企业微信应用当前离线'));
|
|
300
|
+
error.code = 'bot-not-connected';
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
return runtime.presentSessionSyncApproval(target, interaction, options);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
293
307
|
async deleteBot(botId) {
|
|
294
308
|
const warnings = [];
|
|
295
309
|
const config = this.#configStore.get(botId);
|
|
@@ -193,6 +193,16 @@ export class WecomAppRuntime {
|
|
|
193
193
|
});
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
async presentSessionSyncApproval(target, interaction, options = {}) {
|
|
197
|
+
if (!this.#started || !this.#bridge) return false;
|
|
198
|
+
const actor = typeof target?.route?.chatId === 'string' ? target.route.chatId.trim() : '';
|
|
199
|
+
if (!actor) return false;
|
|
200
|
+
return this.#bridge.presentSessionSyncApproval(interaction, {
|
|
201
|
+
key: options.key, actor, validate: options.validate,
|
|
202
|
+
send: (text) => this.sendProactiveText(target, text),
|
|
203
|
+
}, options);
|
|
204
|
+
}
|
|
205
|
+
|
|
196
206
|
async sendProactiveText(target, text, { signal } = {}) {
|
|
197
207
|
const chatId = typeof target?.route?.chatId === 'string' ? target.route.chatId.trim() : '';
|
|
198
208
|
if ((target?.kind !== 'user') || !chatId) {
|
|
@@ -1102,6 +1102,12 @@ export class WeixinHarnessBridge {
|
|
|
1102
1102
|
}
|
|
1103
1103
|
}
|
|
1104
1104
|
|
|
1105
|
+
async presentSessionSyncApproval(interaction, context, options = {}) {
|
|
1106
|
+
return this.#approvals.handleSessionSyncRequested(interaction, context, {
|
|
1107
|
+
...options, runtimeSignal: this.#signal, accessPolicy: this.#accessPolicy,
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1105
1111
|
async #handleInteraction(interaction, {
|
|
1106
1112
|
key,
|
|
1107
1113
|
actor,
|
|
@@ -289,6 +289,20 @@ export class WeixinController {
|
|
|
289
289
|
});
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
+
async presentSessionSyncApproval(botId, target, interaction, options = {}) {
|
|
293
|
+
const config = this.#configStore.get(botId);
|
|
294
|
+
if (!config) throw new Error('Unknown Weixin account');
|
|
295
|
+
return this.#withBotTransition(botId, async () => {
|
|
296
|
+
const runtime = this.#runtimes.get(botId);
|
|
297
|
+
if (!runtime?.status?.ready || typeof runtime.presentSessionSyncApproval !== 'function') {
|
|
298
|
+
const error = new Error(t('微信连接当前离线'));
|
|
299
|
+
error.code = 'bot-not-connected';
|
|
300
|
+
throw error;
|
|
301
|
+
}
|
|
302
|
+
return runtime.presentSessionSyncApproval(target, interaction, options);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
292
306
|
async deleteBot(botId) {
|
|
293
307
|
const config = this.#configStore.get(botId);
|
|
294
308
|
if (!config) throw weixinStageError('workspace-bot-not-found', undefined, 'account.remove');
|
|
@@ -392,6 +392,16 @@ export class WeixinRuntime {
|
|
|
392
392
|
return result;
|
|
393
393
|
}
|
|
394
394
|
|
|
395
|
+
async presentSessionSyncApproval(target, interaction, options = {}) {
|
|
396
|
+
if (!this.#status.ready || !this.#bridge) return false;
|
|
397
|
+
const actor = typeof target?.route?.toUserId === 'string' ? target.route.toUserId.trim() : '';
|
|
398
|
+
if (!actor) return false;
|
|
399
|
+
return this.#bridge.presentSessionSyncApproval(interaction, {
|
|
400
|
+
key: options.key, actor, validate: options.validate,
|
|
401
|
+
send: (text) => this.sendProactiveText(target, text),
|
|
402
|
+
}, options);
|
|
403
|
+
}
|
|
404
|
+
|
|
395
405
|
async sendProactiveText(target, text, { signal } = {}) {
|
|
396
406
|
const toUserId = typeof target?.route?.toUserId === 'string'
|
|
397
407
|
? target.route.toUserId.trim() : '';
|
|
@@ -248,6 +248,20 @@ export class WhatsappController {
|
|
|
248
248
|
});
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
async presentSessionSyncApproval(botId, target, interaction, options = {}) {
|
|
252
|
+
const config = this.#configStore.get(botId);
|
|
253
|
+
if (!config) throw new Error('Unknown WhatsApp bot');
|
|
254
|
+
return this.#withBotTransition(botId, async () => {
|
|
255
|
+
const runtime = this.#runtimes.get(botId);
|
|
256
|
+
if (!runtime?.status?.ready || typeof runtime.presentSessionSyncApproval !== 'function') {
|
|
257
|
+
const error = new Error(t('WhatsApp机器人尚未连接'));
|
|
258
|
+
error.code = 'bot-not-connected';
|
|
259
|
+
throw error;
|
|
260
|
+
}
|
|
261
|
+
return runtime.presentSessionSyncApproval(target, interaction, options);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
|
|
251
265
|
async setAccessPolicy(botId, value) {
|
|
252
266
|
if (this.#closed) throw new Error('WhatsApp controller is closed');
|
|
253
267
|
const accessPolicy = normalizeWhatsappAccessPolicy(value);
|
|
@@ -876,6 +876,16 @@ export class WhatsappRuntime {
|
|
|
876
876
|
return { sent: true };
|
|
877
877
|
}
|
|
878
878
|
|
|
879
|
+
async presentSessionSyncApproval(target, interaction, options = {}) {
|
|
880
|
+
if (!this.#status.ready || !this.#bridge) return false;
|
|
881
|
+
const actor = typeof target?.route?.jid === 'string' ? target.route.jid.trim() : '';
|
|
882
|
+
if (!actor) return false;
|
|
883
|
+
return this.#bridge.presentSessionSyncApproval(interaction, {
|
|
884
|
+
key: options.key, actor, validate: options.validate,
|
|
885
|
+
send: (text) => this.sendProactiveText(target, text),
|
|
886
|
+
}, options);
|
|
887
|
+
}
|
|
888
|
+
|
|
879
889
|
async sendProactiveText(target, text, { signal } = {}) {
|
|
880
890
|
const jid = typeof target?.route?.jid === 'string' ? target.route.jid.trim() : '';
|
|
881
891
|
const validUser = target?.kind === 'user'
|