feat(coding): add conversation archive and first-message titles

This commit is contained in:
2026-09-20 12:43:51 +08:00
parent d61226532a
commit fd0293fe3d
22 changed files with 698 additions and 69 deletions

View File

@@ -0,0 +1,24 @@
import { describe, expect, it } from 'vitest';
import { firstMessageTitle } from '../../electron/coding-runtime/conversation-title';
import type { ConversationMessageNode } from '../../shared/coding-conversation-contracts';
function message(text: string, overrides: Partial<ConversationMessageNode> = {}): ConversationMessageNode {
return { kind: 'message', id: 'user', role: 'user', status: 'complete',
blocks: [{ kind: 'text', id: 'text', status: 'complete', text }], ...overrides };
}
describe('first user message title', () => {
it('uses the first line, collapses whitespace, and bounds long text by characters', () => {
expect(firstMessageTitle(message(' 做一个 登录页\n支持短信登录'))).toBe('做一个 登录页');
expect(firstMessageTitle(message('🦊'.repeat(40)))).toBe('🦊'.repeat(32));
});
it('ignores optimistic, assistant, command and empty content', () => {
expect(firstMessageTitle(message('draft', { status: 'optimistic' }))).toBeNull();
expect(firstMessageTitle(message('reply', { role: 'assistant' }))).toBeNull();
expect(firstMessageTitle(message('/compact'))).toBeNull();
expect(firstMessageTitle(message(' '))).toBeNull();
});
it('names image-only conversations without inspecting the attachment', () => {
expect(firstMessageTitle(message('', { blocks: [{ kind: 'image', id: 'img', attachmentId: 'attachment', mime: 'image/png' }] }))).toBe('附件对话');
});
});