feat: refine mobile master agent sync and chat rendering

This commit is contained in:
kris
2026-04-18 04:51:50 +08:00
parent e0c0ea1814
commit 449f84fcbc
61 changed files with 7051 additions and 1075 deletions

View File

@@ -0,0 +1,52 @@
import test from "node:test";
import assert from "node:assert/strict";
import path from "node:path";
import { readFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
import { parseChatMarkdown } from "../src/lib/chat-markdown";
const testsDir = path.dirname(fileURLToPath(import.meta.url));
async function readWorkspaceFile(relativePath: string) {
return readFile(path.join(testsDir, "..", relativePath), "utf8");
}
test("parseChatMarkdown recognizes section labels and preserves reading order", () => {
const blocks = parseChatMarkdown(
"项目目标:完成 Boss 真机回归\n当前进度已完成 UI 调整\n下一步推送到 Gitea",
);
assert.equal(blocks.length, 3);
assert.deepEqual(
blocks.map((block) => block.kind),
["label", "label", "label"],
);
assert.equal(blocks[0]?.label, "项目目标");
assert.equal(blocks[0]?.text, "完成 Boss 真机回归");
assert.equal(blocks[1]?.label, "当前进度");
assert.equal(blocks[2]?.label, "下一步");
});
test("parseChatMarkdown keeps bullets, ordered items, quotes, and fenced code distinct", () => {
const blocks = parseChatMarkdown(
"# 标题\n\n- 第一项\n1. 第二项\n> 引用\n```ts\nconst ok = true;\n```",
);
assert.deepEqual(
blocks.map((block) => block.kind),
["heading", "bullet", "ordered", "quote", "code"],
);
assert.equal(blocks[0]?.text, "标题");
assert.equal(blocks[1]?.text, "第一项");
assert.equal(blocks[2]?.order, "1.");
assert.equal(blocks[3]?.text, "引用");
assert.match(blocks[4]?.text ?? "", /const ok = true;/);
});
test("ChatBubble renders parsed markdown blocks instead of raw plain text bodies", async () => {
const source = await readWorkspaceFile("src/components/app-ui.tsx");
assert.match(source, /import \{ parseChatMarkdown(?:, type ChatMarkdownBlock)? \} from "@\/lib\/chat-markdown"/);
assert.match(source, /const blocks = parseChatMarkdown\(body\);/);
assert.match(source, /function ChatBubbleMarkdown/);
});