mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 00:33:20 +08:00
Merge pull request #60 from LAN-SHH/fix/qq-c2c-markdown-replies
fix(qq): deliver C2C replies as markdown
This commit is contained in:
commit
8f03c66775
3 changed files with 8 additions and 53 deletions
File diff suppressed because one or more lines are too long
|
|
@ -776,16 +776,8 @@ export class QqHarnessBridge {
|
||||||
const content = hasImages
|
const content = hasImages
|
||||||
? await promptContentForMessage(promptMessage, { signal: this.#signal })
|
? await promptContentForMessage(promptMessage, { signal: this.#signal })
|
||||||
: undefined;
|
: undefined;
|
||||||
// QQ C2C keeps one stream bubble. Progress is collected but never submitted:
|
// QQ stream_messages can acknowledge a final frame without rendering it in
|
||||||
// some clients reject replacing an already visible stream frame, which would
|
// some C2C clients. Standard Markdown delivery is the reliable reply path.
|
||||||
// otherwise leave a stale progress bubble plus a separate fallback answer.
|
|
||||||
if (message.kind === 'c2c' && target?.msgId && typeof this.#bot.openStream === 'function') {
|
|
||||||
try {
|
|
||||||
stream = this.#bot.openStream({ target });
|
|
||||||
} catch (error) {
|
|
||||||
this.#logger.warn?.('[dsh-im:qq] unable to start a QQ stream; using markdown fallback:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const toolErrors = [];
|
const toolErrors = [];
|
||||||
let answer;
|
let answer;
|
||||||
let artifacts = [];
|
let artifacts = [];
|
||||||
|
|
|
||||||
|
|
@ -808,18 +808,14 @@ test('QQ remembers any authorized private inbound as a connection-test target',
|
||||||
assert.equal(sent.length, 2);
|
assert.equal(sent.length, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('QQ private messages produce one final stream bubble', async () => {
|
test('QQ private messages deliver the final answer as Markdown without opening a stream', async () => {
|
||||||
const sent = [];
|
const sent = [];
|
||||||
const frames = [];
|
let streamCalls = 0;
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
const bridge = new QqHarnessBridge({
|
const bridge = new QqHarnessBridge({
|
||||||
bot: {
|
bot: {
|
||||||
sendText: async (_target, text) => sent.push(text),
|
sendText: async (_target, text) => sent.push(text),
|
||||||
openStream: () => ({
|
openStream: () => { streamCalls += 1; },
|
||||||
update: async (text) => frames.push(text),
|
|
||||||
complete: async () => frames.push('DONE'),
|
|
||||||
cancel() {},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
ownerUserOpenid: 'owner-openid',
|
ownerUserOpenid: 'owner-openid',
|
||||||
harness: {
|
harness: {
|
||||||
|
|
@ -843,45 +839,12 @@ test('QQ private messages produce one final stream bubble', async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await bridge.accept(message());
|
await bridge.accept(message());
|
||||||
assert.deepEqual(frames, ['最终回答', 'DONE']);
|
assert.deepEqual(sent, ['最终回答']);
|
||||||
assert.deepEqual(sent, []);
|
assert.equal(streamCalls, 0);
|
||||||
assert.equal(seen.has('msg-1'), true);
|
assert.equal(seen.has('msg-1'), true);
|
||||||
assert.equal(bridge.status.messagesReplied, 1);
|
assert.equal(bridge.status.messagesReplied, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('QQ does not duplicate a visible private answer when stream completion fails', async () => {
|
|
||||||
const frames = [];
|
|
||||||
const sent = [];
|
|
||||||
const bridge = new QqHarnessBridge({
|
|
||||||
bot: {
|
|
||||||
sendText: async (_target, text) => sent.push(text),
|
|
||||||
openStream: () => ({
|
|
||||||
update: async (text) => frames.push(text),
|
|
||||||
complete: async () => { throw new Error('already submitted'); },
|
|
||||||
cancel() {},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
ownerUserOpenid: 'owner-openid',
|
|
||||||
harness: {
|
|
||||||
sessionExists: async () => true,
|
|
||||||
ask: async () => '最终回答',
|
|
||||||
},
|
|
||||||
state: {
|
|
||||||
hasSeen: () => false,
|
|
||||||
markSeen: async () => {},
|
|
||||||
sessionFor: () => 'session-stream-complete-failure',
|
|
||||||
setSession: async () => {},
|
|
||||||
clearSession: async () => {},
|
|
||||||
},
|
|
||||||
logger: { warn() {}, error() {} },
|
|
||||||
});
|
|
||||||
|
|
||||||
await bridge.accept(message({ messageId: 'msg-stream-complete-failure' }));
|
|
||||||
assert.deepEqual(frames, ['最终回答']);
|
|
||||||
assert.deepEqual(sent, []);
|
|
||||||
assert.equal(bridge.status.messagesReplied, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('QQ group messages suppress every successful progress update', async () => {
|
test('QQ group messages suppress every successful progress update', async () => {
|
||||||
const sent = [];
|
const sent = [];
|
||||||
let streamCalls = 0;
|
let streamCalls = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue