baa-conductor

git clone 

baa-conductor / bugs / archive
im_wower  ·  2026-03-28

BUG-021-buffered-sse-fulltext-metadata-pollution.md

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