feat(coding): add conversation archive and first-message titles
This commit is contained in:
@@ -79,6 +79,47 @@ function deferred<T>() {
|
||||
}
|
||||
|
||||
describe('coding workspace store', () => {
|
||||
it('discards a stale list read and refreshes after a manual rename', async () => {
|
||||
const old = conversation('conversation-a', 'agent-a');
|
||||
const stale = deferred<CodingConversationMetadata[]>();
|
||||
const latest = { ...old, title: '手动标题' };
|
||||
const listConversations = vi.fn().mockResolvedValueOnce([old])
|
||||
.mockReturnValueOnce(stale.promise).mockResolvedValue([latest]);
|
||||
const store = createCodingWorkspaceStore({
|
||||
listProjects: async () => ({ projects: [project], activeProjectId: project.id }),
|
||||
getConfig: async () => ({ project, config: config([agent('agent-a')]) }),
|
||||
listConversations, patchConversation: async () => latest,
|
||||
});
|
||||
await store.getState().load();
|
||||
const refresh = store.getState().refreshConversations(project.id);
|
||||
await vi.waitFor(() => expect(listConversations).toHaveBeenCalledTimes(2));
|
||||
await store.getState().patchConversation(old.id, { title: latest.title });
|
||||
stale.resolve([old]);
|
||||
await refresh;
|
||||
expect(store.getState().conversations[0].title).toBe(latest.title);
|
||||
expect(listConversations).toHaveBeenCalledTimes(3);
|
||||
expect(store.getState().loadState).toBe('ready');
|
||||
});
|
||||
|
||||
it('does a follow-up read when metadata changes during an in-flight refresh', async () => {
|
||||
const old = conversation('conversation-a', 'agent-a');
|
||||
const stale = deferred<CodingConversationMetadata[]>();
|
||||
const latest = { ...old, archivedAt: '2026-09-20T00:00:00Z' };
|
||||
const listConversations = vi.fn().mockResolvedValueOnce([old])
|
||||
.mockReturnValueOnce(stale.promise).mockResolvedValue([latest]);
|
||||
const store = createCodingWorkspaceStore({
|
||||
listProjects: async () => ({ projects: [project], activeProjectId: project.id }),
|
||||
getConfig: async () => ({ project, config: config([agent('agent-a')]) }), listConversations,
|
||||
});
|
||||
await store.getState().load();
|
||||
const refresh = store.getState().refreshConversations(project.id);
|
||||
await vi.waitFor(() => expect(listConversations).toHaveBeenCalledTimes(2));
|
||||
const followup = store.getState().refreshConversations(project.id);
|
||||
stale.resolve([old]);
|
||||
await Promise.all([refresh, followup]);
|
||||
expect(store.getState().conversations).toEqual([latest]);
|
||||
});
|
||||
|
||||
it('loads local project metadata and selects the pinned Agent without touching runtime APIs', async () => {
|
||||
const listProjects = vi.fn(async () => ({ projects: [project], activeProjectId: project.id }));
|
||||
const getConfig = vi.fn(async () => ({
|
||||
|
||||
Reference in New Issue
Block a user