feat(qq): render answers as markdown

Deliver final Harness answers to QQ as msg_type=2 markdown so bold,
headings, code blocks, lists, and tables render natively in QQ.

- add markdown-reply.mjs: chunk long answers at code-fence/table
  boundaries (4500-char limit) and send each chunk with a unique
  msg_seq to avoid passive-reply dedup (40054005)
- fall back to plain text per chunk when the platform rejects
  markdown, so bots without markdown capability keep working
- route the non-stream final answer path in qq-bridge through the
  markdown sender; streaming replies already use markdown content
  type, and command/notice texts stay plain
This commit is contained in:
jonah.fu 2026-08-23 21:59:06 +08:00
parent 29bcb67a64
commit 81884173df
5 changed files with 493 additions and 124 deletions

View file

@ -37,6 +37,7 @@ import {
mergeDeliveryReceipts,
providerMessageIdsFor,
} from '../shared/semantic/delivery.mjs';
import { sendMarkdownReply } from './markdown-reply.mjs';
const INTERACTION_RESOLVED_TEXT = '这个问题已在其他客户端处理,无需再次回答。';
const DEFAULT_FILE_UPLOAD_TIMEOUT_MS = 120_000;
@ -661,11 +662,13 @@ export class QqHarnessBridge {
}
}
if (!streamFinished) {
const sent = await this.#bot.sendText(target, displayAnswer);
const deliveries = await sendMarkdownReply(this.#bot, target, displayAnswer, {
logger: this.#logger,
});
textReceipt = createDeliveryReceipt({
deliveryId: messageId,
presentation: 'qq-text',
providerMessageIds: providerMessageIdsFor(sent),
providerMessageIds: deliveries.flatMap((delivery) => providerMessageIdsFor(delivery)),
});
}
} catch (error) {