/** * 附件里的表先替模型拆好 —— **数格子是能算的事,不该问 LLM**。 * * 实测同一行栽过两次:BOM 上白纸黑字写着「Антенна · 浙江嘉康 · (空) EAU」, * 模型拆出来是「集成电路 · (空) · 30000」—— 品类错了、制造商丢了、年用量凭空多一个。 * 连着两个制表符是中间那一格空着,而它把右边的值往前挪了。 */ import { describe, expect, it } from 'vitest'; import { attachmentPart, sheetRows, withSheetRows } from '../agent-runner.ts'; const BOM = [ 'Itelma Code\tPN\tКатегория\tПроизводитель\tAnalog\tСертификация\tEAU (k)\tTarget price', '4-02-01812\tTVM6C160K203R\tВаристор\tThinking Electronic\t\tAEC-Q200\t30\t', '9-00-00251\tDAG2400L321504XZB01-R0\tАнтенна\t浙江嘉康\t\t\t\t', ].join('\n'); describe('制表符表 → 逐行对象', () => { it('键就是表头,空格子就是空串 —— 不往前挪', () => { const rows = sheetRows(BOM); expect(rows).toHaveLength(2); expect(rows?.[1]).toEqual({ 'Itelma Code': '9-00-00251', PN: 'DAG2400L321504XZB01-R0', 'Категория': 'Антенна', 'Производитель': '浙江嘉康', Analog: '', 'Сертификация': '', 'EAU (k)': '', 'Target price': '', }); }); it('**行尾连续制表符是末尾几列都空**,不是这一行到此为止', () => { const rows = sheetRows(BOM); expect(Object.keys(rows?.[1] ?? {})).toHaveLength(8); }); it('列数不齐就不认这张表 —— 半张读歪的表比没有更坏', () => { expect(sheetRows('A\tB\tC\n1\t2')).toBeUndefined(); }); it('不成表的文本不认(只有表头 / 单列)', () => { expect(sheetRows('就一行字')).toBeUndefined(); expect(sheetRows('A\tB')).toBeUndefined(); expect(sheetRows('一列\n值1\n值2')).toBeUndefined(); }); it('表头有空列名就按位置补 —— 键不许是空串', () => { expect(sheetRows('A\t\nx\ty')?.[0]).toEqual({ A: 'x', 列2: 'y' }); }); }); describe('附件旁边多给一份拆好的行', () => { it('读得出表就换成 rows —— **原文换下来**,两份并排会把这一段撑爆', () => { const out = withSheetRows({ attachments: [{ name: 'bom.xlsx', text: BOM }] }); const one = (out['attachments'] as Array>)[0]!; expect(one['text']).toBeUndefined(); expect((one['rows'] as unknown[]).length).toBe(2); // 换下来了要说一声,别让人以为附件读空了 expect(String(one['sheet'])).toContain('已拆成 2 行'); }); /* * 附件**单独成段**:它是这一单的料本身,混进按字符截的整表段里会被砍掉 —— * 实测加了 rows 之后三轮里那一行照错不误,因为它压根没进提示词。 */ it('附件自成一段,不跟整表挤在一起', () => { const seg = attachmentPart({ attachments: [{ name: 'bom.xlsx', text: BOM }] }); expect(seg).toContain('随件附件'); expect(seg).toContain('DAG2400L321504XZB01-R0'); }); it('没有附件就不摆这一段 —— 空标题只占位置', () => { expect(attachmentPart({})).toBe(''); expect(attachmentPart({ attachments: [] })).toBe(''); }); it('读不出表就一个字不动', () => { const scope = { attachments: [{ name: 'a.pdf', note: '这类文件读不出文本' }] }; expect(withSheetRows(scope)).toEqual(scope); }); it('没有附件的单原样返回 —— 不平白多一个键', () => { const scope = { subject: 'x' }; expect(withSheetRows(scope)).toBe(scope); }); });