feat: v0.8.2 安全纵深补全 · 协议保真 · 断链修复 — 图片SSRF/根MEMORY.md保护根治 · Anthropic thinking回传+pause_turn续传 · 2523 用例全量回归 + E2E 扩充
CI / 类型检查 + Lint + 单元测试 (push) Failing after 9m45s
CI / 全量测试 (Electron ABI) (push) Failing after 6m28s
CI / 产物编译验证 (push) Successful in 11m18s

This commit is contained in:
2026-09-08 14:30:27 +08:00
parent 69776e447f
commit 4cd6e997b5
86 changed files with 4303 additions and 956 deletions
@@ -710,3 +710,51 @@ describe('parseOpenAICompatibleResponse — 补充形态', () => {
expect(result.toolCalls![0].id).toBeUndefined();
});
});
describe('parseSSEStream — v0.8.2 P2-6 MiMo 联网搜索引用回填', () => {
it('message.annotations 引用以 TEXT_DELTA 回填正文(DONE 前)', async () => {
const events = await collect(
makeStream([
'data: {"choices":[{"delta":{"content":"今天的新闻"}}],"annotations":[]}\n\n',
'data: {"choices":[{"delta":{},"finish_reason":null}],"annotations":[{"title":"科技日报","url":"https://news.example.com/a","site_name":"example"}]}\n\n',
'data: {"choices":[{"delta":{},"finish_reason":"stop"}]}\n\n',
'data: [DONE]\n\n',
]),
);
const citation = events.filter(
(e) => e.type === MetonaStreamEventType.TEXT_DELTA && String(e.delta).includes('References'),
);
expect(citation).toHaveLength(1);
expect(String(citation[0].delta)).toContain('https://news.example.com/a');
expect(String(citation[0].delta)).toContain('科技日报');
// 引用块必须在 DONE 之前
expect(events.indexOf(citation[0])).toBeLessThan(
events.findIndex((e) => e.type === MetonaStreamEventType.DONE),
);
});
it('按 url 去重;非流式路径同样回填', async () => {
const events = await collect(
makeStream([
'data: {"annotations":[{"title":"a","url":"https://x.example/1"},{"title":"a-dup","url":"https://x.example/1"}]}\n\n',
'data: [DONE]\n\n',
]),
);
const citation = events.find(
(e) => e.type === MetonaStreamEventType.TEXT_DELTA && String(e.delta).includes('References'),
);
expect(citation).toBeDefined();
expect(String(citation!.delta).match(/https:\/\/x.example\/1/g)).toHaveLength(1);
const res = parseOpenAICompatibleResponse({
choices: [
{
message: { content: 'answer', annotations: [{ title: 'b', url: 'https://x.example/2' }] },
},
],
usage: {},
});
expect(res.content).toContain('answer');
expect(res.content).toContain('https://x.example/2');
});
});