@xmanrui/dsh-im 3.1.0 → 3.2.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 +15 -0
- package/README.md +15 -0
- package/lib/client.js +1653 -333
- package/lib/index.js +235 -223
- package/package.json +5 -1
- package/plugin-src/client/channels/dingtalk/api.js +3 -0
- package/plugin-src/client/channels/dingtalk/index.js +18 -5
- package/plugin-src/client/channels/feishu/api.js +3 -0
- package/plugin-src/client/channels/feishu/index.js +18 -5
- package/plugin-src/client/channels/qq/api.js +3 -0
- package/plugin-src/client/channels/qq/index.js +13 -0
- package/plugin-src/client/channels/shared/token-api.js +3 -0
- package/plugin-src/client/channels/shared/token-channel.js +13 -1
- package/plugin-src/client/channels/wecom/api.js +3 -0
- package/plugin-src/client/channels/wecom/index.js +13 -0
- package/plugin-src/client/channels/weixin/api.js +3 -0
- package/plugin-src/client/channels/weixin/index.js +19 -5
- package/plugin-src/client/channels/whatsapp/api.js +3 -0
- package/plugin-src/client/channels/whatsapp/index.js +13 -0
- package/plugin-src/client/context-enhancement.js +275 -0
- package/plugin-src/client/i18n.js +54 -3
- package/plugin-src/client/styles.js +78 -0
- package/plugin-src/client/update-panel.js +108 -7
- package/plugin-src/host/channels/dingtalk/production.mjs +1 -0
- package/plugin-src/host/channels/dingtalk/rpc.mjs +11 -0
- package/plugin-src/host/channels/feishu/production.mjs +3 -0
- package/plugin-src/host/channels/feishu/rpc.mjs +13 -0
- package/plugin-src/host/channels/qq/production.mjs +1 -0
- package/plugin-src/host/channels/qq/rpc.mjs +11 -0
- package/plugin-src/host/channels/shared/context-enhancement-rpc.mjs +17 -0
- package/plugin-src/host/channels/shared/production.mjs +1 -0
- package/plugin-src/host/channels/shared/rpc.mjs +9 -0
- package/plugin-src/host/channels/shared/workspace-rpc.mjs +1 -0
- package/plugin-src/host/channels/slack/production.mjs +1 -0
- package/plugin-src/host/channels/slack/rpc.mjs +10 -0
- package/plugin-src/host/channels/wecom/production.mjs +1 -0
- package/plugin-src/host/channels/wecom/rpc.mjs +11 -0
- package/plugin-src/host/channels/weixin/production.mjs +1 -0
- package/plugin-src/host/channels/weixin/rpc.mjs +11 -0
- package/plugin-src/host/channels/whatsapp/production.mjs +1 -0
- package/plugin-src/host/channels/whatsapp/rpc.mjs +11 -0
- package/plugin-src/host/update-runtime.mjs +3 -2
- package/plugin-src/host/update-service.mjs +2 -0
- package/scripts/verify-package.mjs +15 -2
- package/src/channels/dingtalk/dingtalk-api.mjs +39 -16
- package/src/channels/dingtalk/dingtalk-bridge.mjs +52 -23
- package/src/channels/dingtalk/dingtalk-runtime.mjs +20 -1
- package/src/channels/discord/discord-runtime.mjs +18 -4
- package/src/channels/feishu/bridge.mjs +20 -4
- package/src/channels/feishu/feishu-channel.mjs +100 -44
- package/src/channels/feishu/feishu-runtime.mjs +4 -0
- package/src/channels/qq/qq-bridge.mjs +20 -4
- package/src/channels/qq/qq-runtime.mjs +4 -0
- package/src/channels/shared/bot-workspace-store.mjs +103 -6
- package/src/channels/shared/context-enhancement.mjs +135 -0
- package/src/channels/shared/i18n-en/feishu.mjs +2 -0
- package/src/channels/shared/text-harness-bridge.mjs +19 -4
- package/src/channels/slack/slack-runtime.mjs +4 -0
- package/src/channels/telegram/telegram-runtime.mjs +24 -2
- package/src/channels/wecom/wecom-bridge.mjs +18 -3
- package/src/channels/wecom/wecom-runtime.mjs +4 -0
- package/src/channels/weixin/weixin-bridge.mjs +19 -4
- package/src/channels/weixin/weixin-runtime.mjs +4 -0
- package/src/channels/whatsapp/whatsapp-runtime.mjs +5 -0
|
@@ -3,6 +3,7 @@ import { randomInt } from 'node:crypto';
|
|
|
3
3
|
import { createEditableMessageStream, splitMessageText } from '../shared/editable-message-stream.mjs';
|
|
4
4
|
import { createTextDeliveryBlock } from '../shared/semantic/delivery.mjs';
|
|
5
5
|
import { t } from '../shared/i18n.mjs';
|
|
6
|
+
import { captureContextEnhancement } from '../shared/context-enhancement.mjs';
|
|
6
7
|
import { COMMANDS_MENU_BUTTON, TelegramApi } from './telegram-api.mjs';
|
|
7
8
|
import { createTelegramBridgeStatus, TelegramHarnessBridge } from './telegram-bridge.mjs';
|
|
8
9
|
import {
|
|
@@ -159,6 +160,11 @@ export function normalizeTelegramUpdate(update, {
|
|
|
159
160
|
return {
|
|
160
161
|
messageId: String(update.update_id),
|
|
161
162
|
senderId: String(senderId),
|
|
163
|
+
contextSource: () => ({
|
|
164
|
+
senderName: [message.from?.first_name, message.from?.last_name]
|
|
165
|
+
.filter((value) => typeof value === 'string' && value.trim())
|
|
166
|
+
.map((value) => value.trim()).join(' ') || message.from?.username,
|
|
167
|
+
}),
|
|
162
168
|
senderIsBot: message.from?.is_bot === true,
|
|
163
169
|
kind: direct ? 'direct' : 'group',
|
|
164
170
|
conversationId: messageThreadId === undefined
|
|
@@ -659,6 +665,7 @@ export class TelegramRuntime {
|
|
|
659
665
|
#token;
|
|
660
666
|
#harness;
|
|
661
667
|
#state;
|
|
668
|
+
#contextEnhancement;
|
|
662
669
|
#logger;
|
|
663
670
|
#replyTimeoutMs;
|
|
664
671
|
#createApi;
|
|
@@ -676,6 +683,7 @@ export class TelegramRuntime {
|
|
|
676
683
|
token,
|
|
677
684
|
harness,
|
|
678
685
|
state,
|
|
686
|
+
contextEnhancement,
|
|
679
687
|
logger = console,
|
|
680
688
|
replyTimeoutMs = 600_000,
|
|
681
689
|
createApi = (options) => new TelegramApi(options),
|
|
@@ -687,6 +695,7 @@ export class TelegramRuntime {
|
|
|
687
695
|
this.#token = token;
|
|
688
696
|
this.#harness = harness;
|
|
689
697
|
this.#state = state;
|
|
698
|
+
this.#contextEnhancement = contextEnhancement;
|
|
690
699
|
this.#logger = logger;
|
|
691
700
|
this.#replyTimeoutMs = replyTimeoutMs;
|
|
692
701
|
this.#createApi = createApi;
|
|
@@ -758,6 +767,7 @@ export class TelegramRuntime {
|
|
|
758
767
|
bot: client,
|
|
759
768
|
harness: this.#harness,
|
|
760
769
|
state: this.#state,
|
|
770
|
+
contextEnhancement: this.#contextEnhancement,
|
|
761
771
|
status: this.#status,
|
|
762
772
|
logger: this.#logger,
|
|
763
773
|
replyTimeoutMs: this.#replyTimeoutMs,
|
|
@@ -798,7 +808,19 @@ export class TelegramRuntime {
|
|
|
798
808
|
while (!signal.aborted) {
|
|
799
809
|
const updates = await this.#api.getUpdates({ offset: cursor, timeout: 25, signal });
|
|
800
810
|
this.#status.lastCheckedAt = Date.now();
|
|
801
|
-
|
|
811
|
+
if (signal.aborted) return;
|
|
812
|
+
// All updates have arrived together; cursor persistence must not move the
|
|
813
|
+
// settings boundary for the later messages in this received batch.
|
|
814
|
+
const received = updates.map((update) => {
|
|
815
|
+
const chatType = update?.message?.chat?.type;
|
|
816
|
+
return {
|
|
817
|
+
update,
|
|
818
|
+
contextSnapshot: captureContextEnhancement(this.#contextEnhancement,
|
|
819
|
+
chatType === 'private' ? 'direct'
|
|
820
|
+
: chatType === 'group' || chatType === 'supergroup' ? 'group' : null),
|
|
821
|
+
};
|
|
822
|
+
});
|
|
823
|
+
for (const { update, contextSnapshot } of received) {
|
|
802
824
|
if (signal.aborted) return;
|
|
803
825
|
const message = normalizeTelegramUpdate(update, {
|
|
804
826
|
botId: this.#config.platformId,
|
|
@@ -810,7 +832,7 @@ export class TelegramRuntime {
|
|
|
810
832
|
accessMode: this.#accessMode,
|
|
811
833
|
allowedPrivateUserIds: this.#allowedPrivateUserIds,
|
|
812
834
|
})) {
|
|
813
|
-
void this.#bridge.accept(message).catch((error) => {
|
|
835
|
+
void this.#bridge.accept(message, { contextSnapshot }).catch((error) => {
|
|
814
836
|
if (signal.aborted) return;
|
|
815
837
|
this.#logger.error?.(
|
|
816
838
|
`[dsh-im:telegram] bot ${this.#config.botId} message handling failed:`,
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from '../shared/preset-command.mjs';
|
|
28
28
|
import { runWorkspaceCommand } from '../shared/workspace-command.mjs';
|
|
29
29
|
import { askInWorkspaceSession } from '../shared/workspace-session.mjs';
|
|
30
|
+
import { captureContextEnhancement, enhanceContextContent } from '../shared/context-enhancement.mjs';
|
|
30
31
|
import {
|
|
31
32
|
hasInboundImages,
|
|
32
33
|
ImagePromptError,
|
|
@@ -488,6 +489,7 @@ export class WecomHarnessBridge {
|
|
|
488
489
|
#client;
|
|
489
490
|
#harness;
|
|
490
491
|
#state;
|
|
492
|
+
#contextEnhancement;
|
|
491
493
|
#status;
|
|
492
494
|
#logger;
|
|
493
495
|
#replyTimeoutMs;
|
|
@@ -497,7 +499,8 @@ export class WecomHarnessBridge {
|
|
|
497
499
|
#queues = new Map();
|
|
498
500
|
#pendingInteractions = new Map();
|
|
499
501
|
#interactionKeys = new Map();
|
|
500
|
-
|
|
502
|
+
// Keep the accepted configuration through the existing queue/reply lifecycle.
|
|
503
|
+
#acceptedMessageIds = new Map();
|
|
501
504
|
#approvalTasks = new Set();
|
|
502
505
|
#commandTasks = new Set();
|
|
503
506
|
#approvals;
|
|
@@ -508,6 +511,7 @@ export class WecomHarnessBridge {
|
|
|
508
511
|
client,
|
|
509
512
|
harness,
|
|
510
513
|
state,
|
|
514
|
+
contextEnhancement,
|
|
511
515
|
status = createWecomBridgeStatus(),
|
|
512
516
|
logger = console,
|
|
513
517
|
replyTimeoutMs = 600_000,
|
|
@@ -525,6 +529,7 @@ export class WecomHarnessBridge {
|
|
|
525
529
|
this.#client = client;
|
|
526
530
|
this.#harness = harness;
|
|
527
531
|
this.#state = state;
|
|
532
|
+
this.#contextEnhancement = contextEnhancement;
|
|
528
533
|
this.#status = status;
|
|
529
534
|
this.#logger = logger;
|
|
530
535
|
this.#replyTimeoutMs = replyTimeoutMs;
|
|
@@ -552,7 +557,10 @@ export class WecomHarnessBridge {
|
|
|
552
557
|
|| this.#acceptedMessageIds.has(messageId)) return Promise.resolve();
|
|
553
558
|
|
|
554
559
|
const key = conversationKey(frame);
|
|
555
|
-
this.#acceptedMessageIds.
|
|
560
|
+
this.#acceptedMessageIds.set(messageId, captureContextEnhancement(
|
|
561
|
+
this.#contextEnhancement,
|
|
562
|
+
body.chattype === 'single' ? 'direct' : 'group',
|
|
563
|
+
));
|
|
556
564
|
if (body.chattype === 'single') {
|
|
557
565
|
rememberConnectionTestTarget(this.#state, { chatId });
|
|
558
566
|
}
|
|
@@ -948,9 +956,16 @@ export class WecomHarnessBridge {
|
|
|
948
956
|
this.#logger.warn?.('[dsh-im:wecom] unable to start a stream; using an active reply:', error);
|
|
949
957
|
}
|
|
950
958
|
|
|
951
|
-
|
|
959
|
+
let content = hasImages
|
|
952
960
|
? await promptContentForMessage(message, { signal: this.#signal })
|
|
953
961
|
: undefined;
|
|
962
|
+
const snapshot = this.#acceptedMessageIds.get(messageId);
|
|
963
|
+
if (snapshot) {
|
|
964
|
+
content = enhanceContextContent(content ?? text, snapshot, () => ({
|
|
965
|
+
channel: 'wecom',
|
|
966
|
+
senderId,
|
|
967
|
+
}));
|
|
968
|
+
}
|
|
954
969
|
await this.#state.markSeen(messageId);
|
|
955
970
|
promptRecorded = true;
|
|
956
971
|
const { answer, artifacts = [] } = await askInWorkspaceSession({
|
|
@@ -28,6 +28,7 @@ export class WecomRuntime {
|
|
|
28
28
|
#secret;
|
|
29
29
|
#harness;
|
|
30
30
|
#state;
|
|
31
|
+
#contextEnhancement;
|
|
31
32
|
#logger;
|
|
32
33
|
#replyTimeoutMs;
|
|
33
34
|
#connectTimeoutMs;
|
|
@@ -45,6 +46,7 @@ export class WecomRuntime {
|
|
|
45
46
|
secret,
|
|
46
47
|
harness,
|
|
47
48
|
state,
|
|
49
|
+
contextEnhancement,
|
|
48
50
|
logger = console,
|
|
49
51
|
replyTimeoutMs = 600_000,
|
|
50
52
|
connectTimeoutMs = 20_000,
|
|
@@ -58,6 +60,7 @@ export class WecomRuntime {
|
|
|
58
60
|
this.#secret = secret;
|
|
59
61
|
this.#harness = harness;
|
|
60
62
|
this.#state = state;
|
|
63
|
+
this.#contextEnhancement = contextEnhancement;
|
|
61
64
|
this.#logger = logger;
|
|
62
65
|
this.#replyTimeoutMs = replyTimeoutMs;
|
|
63
66
|
this.#connectTimeoutMs = connectTimeoutMs;
|
|
@@ -107,6 +110,7 @@ export class WecomRuntime {
|
|
|
107
110
|
client,
|
|
108
111
|
harness: this.#harness,
|
|
109
112
|
state: this.#state,
|
|
113
|
+
contextEnhancement: this.#contextEnhancement,
|
|
110
114
|
status: this.#status,
|
|
111
115
|
logger: this.#logger,
|
|
112
116
|
replyTimeoutMs: this.#replyTimeoutMs,
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
} from '../shared/preset-command.mjs';
|
|
34
34
|
import { runWorkspaceCommand } from '../shared/workspace-command.mjs';
|
|
35
35
|
import { askInWorkspaceSession } from '../shared/workspace-session.mjs';
|
|
36
|
+
import { captureContextEnhancement, enhanceContextContent } from '../shared/context-enhancement.mjs';
|
|
36
37
|
import {
|
|
37
38
|
hasInboundImages,
|
|
38
39
|
imagePromptDiagnostic,
|
|
@@ -258,6 +259,7 @@ export class WeixinHarnessBridge {
|
|
|
258
259
|
#ownerUserId;
|
|
259
260
|
#harness;
|
|
260
261
|
#state;
|
|
262
|
+
#contextEnhancement;
|
|
261
263
|
#status;
|
|
262
264
|
#logger;
|
|
263
265
|
#replyTimeoutMs;
|
|
@@ -267,7 +269,8 @@ export class WeixinHarnessBridge {
|
|
|
267
269
|
#queues = new Map();
|
|
268
270
|
#pendingInteractions = new Map();
|
|
269
271
|
#interactionKeys = new Map();
|
|
270
|
-
|
|
272
|
+
// Keep the accepted configuration through the existing queue/reply lifecycle.
|
|
273
|
+
#acceptedMessageIds = new Map();
|
|
271
274
|
#approvalTasks = new Set();
|
|
272
275
|
#commandTasks = new Set();
|
|
273
276
|
#approvals;
|
|
@@ -288,6 +291,7 @@ export class WeixinHarnessBridge {
|
|
|
288
291
|
ownerUserId,
|
|
289
292
|
harness,
|
|
290
293
|
state,
|
|
294
|
+
contextEnhancement,
|
|
291
295
|
status = createWeixinBridgeStatus(),
|
|
292
296
|
logger = console,
|
|
293
297
|
replyTimeoutMs = 600_000,
|
|
@@ -307,6 +311,7 @@ export class WeixinHarnessBridge {
|
|
|
307
311
|
this.#ownerUserId = ownerUserId;
|
|
308
312
|
this.#harness = harness;
|
|
309
313
|
this.#state = state;
|
|
314
|
+
this.#contextEnhancement = contextEnhancement;
|
|
310
315
|
this.#status = status;
|
|
311
316
|
this.#logger = logger;
|
|
312
317
|
this.#replyTimeoutMs = replyTimeoutMs;
|
|
@@ -327,7 +332,10 @@ export class WeixinHarnessBridge {
|
|
|
327
332
|
const sender = nonEmptyString(message?.from_user_id);
|
|
328
333
|
if (!messageId || !sender || this.#state.hasSeen(messageId)
|
|
329
334
|
|| this.#acceptedMessageIds.has(messageId)) return Promise.resolve();
|
|
330
|
-
this.#acceptedMessageIds.
|
|
335
|
+
this.#acceptedMessageIds.set(messageId, captureContextEnhancement(
|
|
336
|
+
this.#contextEnhancement,
|
|
337
|
+
'direct',
|
|
338
|
+
));
|
|
331
339
|
if (sender === this.#ownerUserId) {
|
|
332
340
|
rememberConnectionTestTarget(this.#state, { toUserId: sender });
|
|
333
341
|
}
|
|
@@ -650,16 +658,23 @@ export class WeixinHarnessBridge {
|
|
|
650
658
|
let artifacts = [];
|
|
651
659
|
await this.#startTyping(sender, contextToken);
|
|
652
660
|
try {
|
|
653
|
-
|
|
661
|
+
let content = hasImages
|
|
654
662
|
? await promptContentForMessage(promptMessage, { signal: this.#signal })
|
|
655
663
|
: undefined;
|
|
664
|
+
const snapshot = this.#acceptedMessageIds.get(messageId);
|
|
665
|
+
if (snapshot) {
|
|
666
|
+
content = enhanceContextContent(content ?? text, snapshot, () => ({
|
|
667
|
+
channel: 'weixin',
|
|
668
|
+
senderId: sender,
|
|
669
|
+
}));
|
|
670
|
+
}
|
|
656
671
|
await this.#state.markSeen(messageId);
|
|
657
672
|
promptRecorded = true;
|
|
658
673
|
({ answer, artifacts = [] } = await askInWorkspaceSession({
|
|
659
674
|
harness: this.#harness,
|
|
660
675
|
state: this.#state,
|
|
661
676
|
key,
|
|
662
|
-
...(
|
|
677
|
+
...(content !== undefined ? { content } : { text }),
|
|
663
678
|
createOptions: { signal: this.#signal },
|
|
664
679
|
existsOptions: { signal: this.#signal },
|
|
665
680
|
askOptions: {
|
|
@@ -108,6 +108,7 @@ export class WeixinRuntime {
|
|
|
108
108
|
#token;
|
|
109
109
|
#harness;
|
|
110
110
|
#state;
|
|
111
|
+
#contextEnhancement;
|
|
111
112
|
#logger;
|
|
112
113
|
#replyTimeoutMs;
|
|
113
114
|
#maxMessageChars;
|
|
@@ -124,6 +125,7 @@ export class WeixinRuntime {
|
|
|
124
125
|
token,
|
|
125
126
|
harness,
|
|
126
127
|
state,
|
|
128
|
+
contextEnhancement,
|
|
127
129
|
logger = console,
|
|
128
130
|
replyTimeoutMs = 600_000,
|
|
129
131
|
maxMessageChars = DEFAULT_WEIXIN_MAX_MESSAGE_CHARS,
|
|
@@ -137,6 +139,7 @@ export class WeixinRuntime {
|
|
|
137
139
|
this.#token = token;
|
|
138
140
|
this.#harness = harness;
|
|
139
141
|
this.#state = state;
|
|
142
|
+
this.#contextEnhancement = contextEnhancement;
|
|
140
143
|
this.#logger = logger;
|
|
141
144
|
this.#replyTimeoutMs = replyTimeoutMs;
|
|
142
145
|
this.#maxMessageChars = maxMessageChars;
|
|
@@ -178,6 +181,7 @@ export class WeixinRuntime {
|
|
|
178
181
|
ownerUserId: this.#config.ownerUserId,
|
|
179
182
|
harness: this.#harness,
|
|
180
183
|
state: this.#state,
|
|
184
|
+
contextEnhancement: this.#contextEnhancement,
|
|
181
185
|
status: this.#status,
|
|
182
186
|
logger: this.#logger,
|
|
183
187
|
replyTimeoutMs: this.#replyTimeoutMs,
|
|
@@ -234,6 +234,7 @@ export function normalizeWhatsappMessage(message, accountJid, {
|
|
|
234
234
|
messageId: `${remoteJid}:${messageId}`,
|
|
235
235
|
providerMessageId: messageId,
|
|
236
236
|
senderId: senderJid,
|
|
237
|
+
contextSource: () => ({ senderName: message.pushName }),
|
|
237
238
|
senderAlternateId: typeof senderAlternateJid === 'string' ? senderAlternateJid : '',
|
|
238
239
|
senderIsBot: false,
|
|
239
240
|
kind: group ? 'group' : 'direct',
|
|
@@ -536,6 +537,7 @@ export class WhatsappRuntime {
|
|
|
536
537
|
#authDir;
|
|
537
538
|
#harness;
|
|
538
539
|
#state;
|
|
540
|
+
#contextEnhancement;
|
|
539
541
|
#logger;
|
|
540
542
|
#replyTimeoutMs;
|
|
541
543
|
#connectTimeoutMs;
|
|
@@ -555,6 +557,7 @@ export class WhatsappRuntime {
|
|
|
555
557
|
authDir,
|
|
556
558
|
harness,
|
|
557
559
|
state,
|
|
560
|
+
contextEnhancement,
|
|
558
561
|
logger = console,
|
|
559
562
|
replyTimeoutMs = 600_000,
|
|
560
563
|
connectTimeoutMs = 30_000,
|
|
@@ -568,6 +571,7 @@ export class WhatsappRuntime {
|
|
|
568
571
|
this.#authDir = authDir;
|
|
569
572
|
this.#harness = harness;
|
|
570
573
|
this.#state = state;
|
|
574
|
+
this.#contextEnhancement = contextEnhancement;
|
|
571
575
|
this.#logger = logger;
|
|
572
576
|
this.#replyTimeoutMs = replyTimeoutMs;
|
|
573
577
|
this.#connectTimeoutMs = connectTimeoutMs;
|
|
@@ -673,6 +677,7 @@ export class WhatsappRuntime {
|
|
|
673
677
|
bot: client,
|
|
674
678
|
harness: this.#harness,
|
|
675
679
|
state: this.#state,
|
|
680
|
+
contextEnhancement: this.#contextEnhancement,
|
|
676
681
|
status: this.#status,
|
|
677
682
|
logger: this.#logger,
|
|
678
683
|
replyTimeoutMs: this.#replyTimeoutMs,
|