@xmanrui/dsh-im 4.2.0 → 4.2.1
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/THIRD_PARTY_NOTICES.md +25 -1
- package/lib/client.js +3 -2
- package/lib/index.js +171 -171
- package/package.json +3 -2
- package/plugin-src/host/build.mjs +1 -0
- package/scripts/verify-package.mjs +5 -0
- package/src/channels/telegram/telegram-api.mjs +5 -1
- package/src/channels/telegram/telegram-http.mjs +21 -0
- package/src/channels/telegram/telegram-runtime.mjs +20 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmanrui/dsh-im",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.1",
|
|
4
4
|
"description": "把九种 IM 机器人和公网 AI Office 接入本机 DeepSeek Harness。 Connect nine IM channels and a public AI Office to a local DeepSeek Harness.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -99,7 +99,8 @@
|
|
|
99
99
|
"@tencent-connect/qqbot-nodejs": "1.0.4",
|
|
100
100
|
"@wecom/aibot-node-sdk": "1.0.7",
|
|
101
101
|
"dingtalk-stream": "2.1.4",
|
|
102
|
-
"qrcode": "1.5.4"
|
|
102
|
+
"qrcode": "1.5.4",
|
|
103
|
+
"undici": "7.29.0"
|
|
103
104
|
},
|
|
104
105
|
"devDependencies": {
|
|
105
106
|
"@deepseek-ai/cordis": "4.0.1",
|
|
@@ -52,6 +52,7 @@ const required = [
|
|
|
52
52
|
'src/channels/slack/slack-runtime.mjs',
|
|
53
53
|
'src/channels/wecom/wecom-runtime.mjs',
|
|
54
54
|
'src/channels/telegram/telegram-runtime.mjs',
|
|
55
|
+
'src/channels/telegram/telegram-http.mjs',
|
|
55
56
|
'src/channels/discord/discord-runtime.mjs',
|
|
56
57
|
'src/channels/whatsapp/whatsapp-runtime.mjs',
|
|
57
58
|
'src/channels/whatsapp/whatsapp-web-session.mjs',
|
|
@@ -198,6 +199,7 @@ const directDependencies = {
|
|
|
198
199
|
'@tencent-connect/qqbot-nodejs': '1.0.4',
|
|
199
200
|
'@wecom/aibot-node-sdk': '1.0.7',
|
|
200
201
|
qrcode: '1.5.4',
|
|
202
|
+
undici: '7.29.0',
|
|
201
203
|
};
|
|
202
204
|
for (const [name, version] of Object.entries(directDependencies)) {
|
|
203
205
|
if (manifest.dependencies?.[name] !== version) {
|
|
@@ -226,6 +228,9 @@ if (manifest.bin?.['dsh-im'] !== 'bin/dsh-im.mjs') {
|
|
|
226
228
|
if (/(?:from\s*|import\s*\(|require\s*\()\s*["'](?:@larksuiteoapi\/node-sdk|@whiskeysockets\/baileys|https-proxy-agent|protobufjs)(?:\/[^"']*)?["']/.test(host)) {
|
|
227
229
|
throw new Error('host bundle must not import a bundled SDK, proxy agent, or protobufjs at runtime');
|
|
228
230
|
}
|
|
231
|
+
if (!/(?:from\s*|import\s*\()\s*["']undici["']/.test(host)) {
|
|
232
|
+
throw new Error('host bundle must retain undici as an external runtime dependency');
|
|
233
|
+
}
|
|
229
234
|
if ((executable.mode & 0o111) === 0) throw new Error('dsh-im CLI is not executable');
|
|
230
235
|
if (/private-bot-token|must-be-rolled-back|DEEPSEEK_API_KEY=/.test(client + host)) {
|
|
231
236
|
throw new Error('built artifacts contain a test or environment secret marker');
|
|
@@ -105,19 +105,23 @@ export const COMMANDS_MENU_BUTTON = Object.freeze({ type: 'commands' });
|
|
|
105
105
|
export class TelegramApi {
|
|
106
106
|
#token;
|
|
107
107
|
#fetch;
|
|
108
|
+
#FormDataImpl;
|
|
108
109
|
#baseUrl;
|
|
109
110
|
#fileUploadTimeoutMs;
|
|
110
111
|
|
|
111
112
|
constructor({
|
|
112
113
|
token,
|
|
113
114
|
fetchImpl = fetch,
|
|
115
|
+
FormDataImpl = globalThis.FormData,
|
|
114
116
|
baseUrl = DEFAULT_BASE_URL,
|
|
115
117
|
fileUploadTimeoutMs = DEFAULT_FILE_UPLOAD_TIMEOUT_MS,
|
|
116
118
|
}) {
|
|
117
119
|
if (!validTelegramToken(token)) throw new TypeError('Telegram Bot Token is invalid');
|
|
118
120
|
if (typeof fetchImpl !== 'function') throw new TypeError('TelegramApi requires fetch');
|
|
121
|
+
if (typeof FormDataImpl !== 'function') throw new TypeError('TelegramApi requires FormData');
|
|
119
122
|
this.#token = token.trim();
|
|
120
123
|
this.#fetch = fetchImpl;
|
|
124
|
+
this.#FormDataImpl = FormDataImpl;
|
|
121
125
|
this.#baseUrl = new URL(baseUrl);
|
|
122
126
|
this.#fileUploadTimeoutMs = positiveTimeout(fileUploadTimeoutMs, 'fileUploadTimeoutMs');
|
|
123
127
|
}
|
|
@@ -273,7 +277,7 @@ export class TelegramApi {
|
|
|
273
277
|
|| !Buffer.isBuffer(file.bytes)) {
|
|
274
278
|
throw new TypeError(`A Telegram ${mediaLabel} is required`);
|
|
275
279
|
}
|
|
276
|
-
const payload = new
|
|
280
|
+
const payload = new this.#FormDataImpl();
|
|
277
281
|
payload.append('chat_id', String(chatId));
|
|
278
282
|
payload.append(
|
|
279
283
|
fieldName,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EnvHttpProxyAgent,
|
|
3
|
+
FormData as UndiciFormData,
|
|
4
|
+
fetch as undiciFetch,
|
|
5
|
+
} from 'undici';
|
|
6
|
+
|
|
7
|
+
const TELEGRAM_CONNECTIONS = 4;
|
|
8
|
+
|
|
9
|
+
export function createTelegramHttpTransport() {
|
|
10
|
+
const dispatcher = new EnvHttpProxyAgent({ connections: TELEGRAM_CONNECTIONS });
|
|
11
|
+
let destroyed = false;
|
|
12
|
+
return {
|
|
13
|
+
fetchImpl: (url, options = {}) => undiciFetch(url, { ...options, dispatcher }),
|
|
14
|
+
FormDataImpl: UndiciFormData,
|
|
15
|
+
async destroy() {
|
|
16
|
+
if (destroyed) return;
|
|
17
|
+
destroyed = true;
|
|
18
|
+
await dispatcher.destroy();
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -5,6 +5,7 @@ import { createTextDeliveryBlock } from '../shared/semantic/delivery.mjs';
|
|
|
5
5
|
import { t } from '../shared/i18n.mjs';
|
|
6
6
|
import { captureContextEnhancement } from '../shared/context-enhancement.mjs';
|
|
7
7
|
import { COMMANDS_MENU_BUTTON, TelegramApi } from './telegram-api.mjs';
|
|
8
|
+
import { createTelegramHttpTransport } from './telegram-http.mjs';
|
|
8
9
|
import { createTelegramBridgeStatus, TelegramHarnessBridge } from './telegram-bridge.mjs';
|
|
9
10
|
import {
|
|
10
11
|
splitTelegramRegularText,
|
|
@@ -671,9 +672,11 @@ export class TelegramRuntime {
|
|
|
671
672
|
#logger;
|
|
672
673
|
#replyTimeoutMs;
|
|
673
674
|
#createApi;
|
|
675
|
+
#createHttpTransport;
|
|
674
676
|
#accessMode;
|
|
675
677
|
#allowedPrivateUserIds;
|
|
676
678
|
#status = createTelegramRuntimeStatus();
|
|
679
|
+
#httpTransport = null;
|
|
677
680
|
#api = null;
|
|
678
681
|
#bridge = null;
|
|
679
682
|
#abortController = null;
|
|
@@ -689,6 +692,7 @@ export class TelegramRuntime {
|
|
|
689
692
|
logger = console,
|
|
690
693
|
replyTimeoutMs = 600_000,
|
|
691
694
|
createApi = (options) => new TelegramApi(options),
|
|
695
|
+
createHttpTransport = createTelegramHttpTransport,
|
|
692
696
|
}) {
|
|
693
697
|
if (!config || !token || !harness || !state) {
|
|
694
698
|
throw new TypeError('TelegramRuntime requires config, token, Harness, and state');
|
|
@@ -701,6 +705,7 @@ export class TelegramRuntime {
|
|
|
701
705
|
this.#logger = logger;
|
|
702
706
|
this.#replyTimeoutMs = replyTimeoutMs;
|
|
703
707
|
this.#createApi = createApi;
|
|
708
|
+
this.#createHttpTransport = createHttpTransport;
|
|
704
709
|
const accessPolicy = normalizeTelegramAccessPolicy(config);
|
|
705
710
|
this.#accessMode = accessPolicy.accessMode;
|
|
706
711
|
this.#allowedPrivateUserIds = new Set(accessPolicy.allowedUsers);
|
|
@@ -762,9 +767,15 @@ export class TelegramRuntime {
|
|
|
762
767
|
|
|
763
768
|
const controller = new AbortController();
|
|
764
769
|
this.#abortController = controller;
|
|
765
|
-
const api = this.#createApi({ token: this.#token });
|
|
766
|
-
this.#api = api;
|
|
767
770
|
try {
|
|
771
|
+
const transport = this.#createHttpTransport();
|
|
772
|
+
this.#httpTransport = transport;
|
|
773
|
+
const api = this.#createApi({
|
|
774
|
+
token: this.#token,
|
|
775
|
+
fetchImpl: transport.fetchImpl,
|
|
776
|
+
FormDataImpl: transport.FormDataImpl,
|
|
777
|
+
});
|
|
778
|
+
this.#api = api;
|
|
768
779
|
const bot = await api.getMe({ signal: controller.signal });
|
|
769
780
|
if (String(bot?.id ?? '') !== this.#config.platformId || bot?.is_bot !== true) {
|
|
770
781
|
throw new Error('Telegram token identity does not match the saved bot');
|
|
@@ -878,9 +889,11 @@ export class TelegramRuntime {
|
|
|
878
889
|
async stop() {
|
|
879
890
|
const pollTask = this.#pollTask;
|
|
880
891
|
const bridge = this.#bridge;
|
|
892
|
+
const httpTransport = this.#httpTransport;
|
|
881
893
|
this.#abortController?.abort();
|
|
882
894
|
this.#abortController = null;
|
|
883
895
|
this.#pollTask = null;
|
|
896
|
+
this.#httpTransport = null;
|
|
884
897
|
this.#api = null;
|
|
885
898
|
this.#bridge = null;
|
|
886
899
|
await Promise.race([
|
|
@@ -891,6 +904,11 @@ export class TelegramRuntime {
|
|
|
891
904
|
bridge?.waitForIdle() ?? Promise.resolve(),
|
|
892
905
|
new Promise((resolve) => setTimeout(resolve, 2_000)),
|
|
893
906
|
]);
|
|
907
|
+
try {
|
|
908
|
+
await httpTransport?.destroy();
|
|
909
|
+
} catch {
|
|
910
|
+
this.#logger.warn?.('[dsh-im:telegram] Telegram HTTP transport cleanup failed');
|
|
911
|
+
}
|
|
894
912
|
this.#status.ready = false;
|
|
895
913
|
this.#status.connectionState = 'idle';
|
|
896
914
|
return this.status;
|