mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-16 15:10:45 +08:00
fix(weixin): chunk long replies for iLink limits
This commit is contained in:
parent
dea9a8f2d1
commit
868372fb04
5 changed files with 36 additions and 4 deletions
|
|
@ -46,7 +46,7 @@ Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest
|
||||||
| Channel | Setup | Messaging and replies |
|
| Channel | Setup | Messaging and replies |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Feishu | Create a bot by QR code, or bind one with App ID + App Secret | Persistent connection for incoming messages; streaming cards show thinking, tool progress, and replies |
|
| Feishu | Create a bot by QR code, or bind one with App ID + App Secret | Persistent connection for incoming messages; streaming cards show thinking, tool progress, and replies |
|
||||||
| WeChat | Scan a QR code to bind a WeChat bot | Tencent iLink long polling for sending and receiving messages |
|
| WeChat | Scan a QR code to bind a WeChat bot | Tencent iLink long polling for sending and receiving messages; long replies are sent in 1,800-character chunks |
|
||||||
| DingTalk | Create a bot by QR code, or bind one with Client ID + Client Secret | DingTalk Stream connection; streaming replies through AI Cards |
|
| DingTalk | Create a bot by QR code, or bind one with Client ID + Client Secret | DingTalk Stream connection; streaming replies through AI Cards |
|
||||||
| WeCom | Create an intelligent bot by QR code, or bind one with Bot ID + Secret | Official WebSocket connection; native thinking state, tool progress, and streaming replies |
|
| WeCom | Create an intelligent bot by QR code, or bind one with Bot ID + Secret | Official WebSocket connection; native thinking state, tool progress, and streaming replies |
|
||||||
| QQ | Create a bot with mobile QQ QR scanning, or bind one with AppID + AppSecret | WebSocket connection; private chats show typing and receive one Markdown reply, while mentioned group chats receive only the final answer |
|
| QQ | Create a bot with mobile QQ QR scanning, or bind one with AppID + AppSecret | WebSocket connection; private chats show typing and receive one Markdown reply, while mentioned group chats receive only the final answer |
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ Connect IM bots to DeepSeek Harness by scanning a QR code, using an App Manifest
|
||||||
| 渠道 | 接入方式 | 消息与回复 |
|
| 渠道 | 接入方式 | 消息与回复 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| 飞书 | 扫码创建机器人,或使用 App ID + App Secret 手动绑定 | 长连接接收消息;通过飞书流式卡片显示思考、工具进度和回答 |
|
| 飞书 | 扫码创建机器人,或使用 App ID + App Secret 手动绑定 | 长连接接收消息;通过飞书流式卡片显示思考、工具进度和回答 |
|
||||||
| 微信 | 使用微信扫码绑定机器人 | 腾讯 iLink 长轮询收发消息 |
|
| 微信 | 使用微信扫码绑定机器人 | 腾讯 iLink 长轮询收发消息;长回复会按 1,800 字符分段发送 |
|
||||||
| 钉钉 | 扫码创建机器人,或使用 Client ID + Client Secret 手动绑定 | 钉钉 Stream 长连接;通过 AI Card 流式显示回答 |
|
| 钉钉 | 扫码创建机器人,或使用 Client ID + Client Secret 手动绑定 | 钉钉 Stream 长连接;通过 AI Card 流式显示回答 |
|
||||||
| 企业微信 | 使用企业微信 App 扫码创建智能机器人,或使用 Bot ID + Secret 手动绑定 | 官方 WebSocket 长连接;原生显示“正在思考中”、工具执行进度和流式回答 |
|
| 企业微信 | 使用企业微信 App 扫码创建智能机器人,或使用 Bot ID + Secret 手动绑定 | 官方 WebSocket 长连接;原生显示“正在思考中”、工具执行进度和流式回答 |
|
||||||
| QQ | 使用手机 QQ 扫码创建机器人,或使用 AppID + AppSecret 手动绑定 | WebSocket 长连接;私聊显示“正在输入”并以单条 Markdown 回复,群聊被 @ 后只发送最终答案 |
|
| QQ | 使用手机 QQ 扫码创建机器人,或使用 AppID + AppSecret 手动绑定 | WebSocket 长连接;私聊显示“正在输入”并以单条 Markdown 回复,群聊被 @ 后只发送最终答案 |
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -184,7 +184,7 @@ export class WeixinHarnessBridge {
|
||||||
status = createWeixinBridgeStatus(),
|
status = createWeixinBridgeStatus(),
|
||||||
logger = console,
|
logger = console,
|
||||||
replyTimeoutMs = 600_000,
|
replyTimeoutMs = 600_000,
|
||||||
maxMessageChars = 4_000,
|
maxMessageChars = 1_800,
|
||||||
signal,
|
signal,
|
||||||
}) {
|
}) {
|
||||||
if (!api || typeof api.sendText !== 'function') throw new TypeError('Weixin API is required');
|
if (!api || typeof api.sendText !== 'function') throw new TypeError('Weixin API is required');
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,38 @@ test('Weixin bridge hands a native file source to the current Harness turn', asy
|
||||||
assert.deepEqual(sent, ['文件已收到']);
|
assert.deepEqual(sent, ['文件已收到']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Weixin splits long replies below the iLink text limit', async () => {
|
||||||
|
const fixture = stateFixture();
|
||||||
|
fixture.sessions.set('p2p:owner-user', 'session-long-reply');
|
||||||
|
const chunks = [];
|
||||||
|
const answer = '答案'.repeat(1_000);
|
||||||
|
const bridge = new WeixinHarnessBridge({
|
||||||
|
api: {
|
||||||
|
sendText: async ({ text }) => {
|
||||||
|
chunks.push(text);
|
||||||
|
return { messageId: `weixin-long-${chunks.length}` };
|
||||||
|
},
|
||||||
|
},
|
||||||
|
baseUrl: 'https://ilinkai.weixin.qq.com',
|
||||||
|
token: 'token',
|
||||||
|
ownerUserId: 'owner-user',
|
||||||
|
harness: {
|
||||||
|
sessionExists: async () => true,
|
||||||
|
ask: async () => answer,
|
||||||
|
},
|
||||||
|
state: fixture.state,
|
||||||
|
});
|
||||||
|
|
||||||
|
const receipt = await bridge.accept(message('weixin-long-reply', '生成一段长回答'));
|
||||||
|
|
||||||
|
assert.ok(chunks.length > 1);
|
||||||
|
assert.ok(chunks.every((chunk) => chunk.length <= 1_800));
|
||||||
|
assert.equal(chunks.join(''), answer);
|
||||||
|
assert.equal(receipt.providerMessageIds.length, chunks.length);
|
||||||
|
assert.equal(bridge.status.messagesReplied, 1);
|
||||||
|
assert.equal(bridge.status.lastMessageError, null);
|
||||||
|
});
|
||||||
|
|
||||||
test('Weixin starts a native-file download before an earlier queued turn finishes', async () => {
|
test('Weixin starts a native-file download before an earlier queued turn finishes', async () => {
|
||||||
const fixture = stateFixture();
|
const fixture = stateFixture();
|
||||||
fixture.sessions.set('p2p:owner-user', 'session-prefetch-file');
|
fixture.sessions.set('p2p:owner-user', 'session-prefetch-file');
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue