- commit
- d1f0624
- parent
- 8fe3836
- author
- im_wower
- date
- 2026-03-28 00:11:45 +0800 CST
docs(claude): BUG-021 buffered SSE full_text metadata pollution
1 files changed,
+61,
-0
1@@ -0,0 +1,61 @@
2+# BUG-021: buffered SSE full_text 拼接混入元数据
3+
4+> 提交者:Claude(新手测试)
5+> 日期:2026-03-27
6+
7+## 现象
8+
9+通过 buffered 模式请求 Claude completion 时,返回的结构化响应 `full_text` 字段混入了 SSE 元数据:
10+
11+```
12+full_text: " 成功completionchatcompl_014ZVw...stop_sequence\n\nHuman:..."
13+```
14+
15+期望只有 `" 成功"`。
16+
17+## 根因
18+
19+`local-api.ts` 的 `extractBufferedSseTextFragments` 函数:
20+
21+```typescript
22+const directKeys = ["text", "value", "content", "message", "markdown", "completion"];
23+const directValues = directKeys.flatMap(...);
24+
25+if (directValues.length > 0) {
26+ return directValues;
27+}
28+
29+// 当 directKeys 没找到值时,fallback 递归所有字段
30+return Object.values(value).flatMap((entry) => extractBufferedSseTextFragments(entry));
31+```
32+
33+Claude 的 SSE 最后一个事件的 `completion` 字段可能是空字符串 `""`,空字符串被过滤掉后 `directValues.length === 0`,触发 fallback,把 `type: "completion"`、`id: "chatcompl_xxx"`、`stop: "\n\nHuman:"`、`log_id`、`messageLimit` 里的所有字符串值都递归提取出来。
34+
35+## 修复
36+
37+去掉 fallback,只从 directKeys 提取,找不到就返回空:
38+
39+```typescript
40+function extractBufferedSseTextFragments(value) {
41+ // ...
42+ const directValues = directKeys.flatMap(...);
43+ return directValues; // 不要 fallback 到 Object.values
44+}
45+```
46+
47+或者在 Claude 场景下只提取 `completion` 字段值不为空字符串的事件。
48+
49+## 严重度
50+
51+Medium — 功能可用但 full_text 不干净,影响 BAA 指令系统从 full_text 中提取 baa 块的准确性
52+
53+## 复现
54+
55+```bash
56+curl -s https://conductor.makefile.so/v1/browser/request \
57+ -X POST -H "Content-Type: application/json" \
58+ -H "Authorization: Bearer $TOKEN" \
59+ -d '{"platform":"claude","path":"/api/organizations/{org}/chat_conversations/{conv}/completion","method":"POST","responseMode":"buffered","body":{"prompt":"回复两个字:成功",...}}'
60+```
61+
62+返回的 `response.full_text` 包含非 completion 内容。