import assert from 'node:assert/strict'; import test from 'node:test'; import { buildContextPrefix, buildMindSpaceChatContext, formatContextChip, mindspaceChatContextInternals, } from './mindspace-chat-context.mjs'; const sampleSpace = { id: 'space-1', name: '我的空间', categories: [ { code: 'oa', name: 'OA 工作区', itemCount: 12 }, { code: 'draft', name: '页面草稿', itemCount: 5 }, ], }; const sampleCategory = { id: 'cat-oa', code: 'oa', name: 'OA 工作区', itemCount: 12, }; const samplePage = { id: 'page-1', title: '项目周报', summary: '本周项目进展与风险汇总', status: 'draft', versionNo: 3, categoryCode: 'draft', templateId: 'report', contentFormat: 'markdown', pageType: 'article', content: '# 周报\n\n- 完成 A 模块\n- 风险:进度偏紧', }; test('buildMindSpaceChatContext resolves home, category, and page views', () => { const home = buildMindSpaceChatContext({ space: sampleSpace, ownerUsername: 'john', selectedCategory: null, selectedPageId: null, pages: [samplePage], route: '/space', }); assert.equal(home.view, 'home'); assert.equal(home.ownerUsername, 'john'); assert.equal(home.homeCategories?.length, 2); assert.equal(home.recentPages?.[0]?.title, '项目周报'); const category = buildMindSpaceChatContext({ space: sampleSpace, selectedCategory: sampleCategory, selectedPageId: null, pages: [], assets: [ { id: 'asset-1', displayName: 'report.xlsx', mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', }, ], route: '/space?category=oa', }); assert.equal(category.view, 'category'); assert.deepEqual(category.category?.assets, [ { id: 'asset-1', displayName: 'report.xlsx', mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', }, ]); const page = buildMindSpaceChatContext({ space: sampleSpace, selectedCategory: null, selectedPageId: 'page-1', pages: [samplePage], pageLive: { page: samplePage, title: '项目周报(编辑中)', summary: samplePage.summary, content: samplePage.content, }, route: '/space/page/page-1', }); assert.equal(page.view, 'page'); assert.equal(page.page.title, '项目周报(编辑中)'); assert.match(page.page.contentExcerpt ?? '', /完成 A 模块/); assert.equal(page.category?.code, 'draft'); }); test('buildContextPrefix includes page excerpt and location hint', () => { const prefix = buildContextPrefix( buildMindSpaceChatContext({ space: sampleSpace, ownerUsername: 'john', selectedCategory: null, selectedPageId: 'page-1', pages: [samplePage], pageLive: { page: samplePage, title: samplePage.title, summary: samplePage.summary, content: samplePage.content, }, route: '/space/page/page-1', }), ); assert.match(prefix, /- 账号:john/); assert.match(prefix, /- 页面摘要:本周项目进展与风险汇总/); assert.match(prefix, /- 页面模板:分析报告/); assert.match(prefix, /- 当前正文摘录/); assert.match(prefix, /完成 A 模块/); assert.match(prefix, /【定位说明】/); assert.match(prefix, /指代「这个页面」「改这里」时默认指该页面/); assert.match(prefix, /\n---\n\n$/); }); test('buildContextPrefix lists category assets on category view', () => { const prefix = buildContextPrefix( buildMindSpaceChatContext({ space: sampleSpace, selectedCategory: sampleCategory, selectedPageId: null, pages: [], assets: [{ id: 'asset-1', displayName: 'report.xlsx', mimeType: 'text/csv' }], route: '/space?category=oa', }), ); assert.match(prefix, /- 分类:OA 工作区(oa,共 12 项)/); assert.match(prefix, /report\.xlsx(id: asset-1/); assert.match(prefix, /指代「这里的文件」时默认指该分类下的资料/); }); test('formatContextChip prefers page, then category with count, then space name', () => { assert.equal( formatContextChip({ spaceName: '我的空间', view: 'page', route: '/space/page/page-1', page: { id: 'page-1', title: '项目周报', versionNo: 3 }, }), '项目周报 · v3', ); assert.equal( formatContextChip({ spaceName: '我的空间', view: 'category', route: '/space?category=oa', category: { code: 'oa', name: 'OA 工作区', itemCount: 12 }, }), 'OA 工作区 · 12 项', ); }); test('excerptContent strips html and truncates long text', () => { const html = '
正文内容
'; assert.equal( mindspaceChatContextInternals.excerptContent(html, 'html'), '标题 正文内容', ); assert.equal( mindspaceChatContextInternals.excerptContent('a'.repeat(20), 'markdown', 10), `${'a'.repeat(9)}…`, ); });