feat: 支持 AI 设计项目多会话交互

需求:用户可在同一设计项目中新建和切换会话,任务列表保持项目级共享。

实现:
- 增加会话选择、新建入口及本地数据迁移
- Conversation 独立消息、Brief、Quote 与流式状态
- 保留项目任务并修复 Task revision 与 ABA 异步竞态
- 保持 Enter 发送、Shift+Enter 换行及 IME 保护
This commit is contained in:
2026-08-06 18:22:15 +08:00
parent 4980894017
commit 03dae62cf3
18 changed files with 1810 additions and 702 deletions

View File

@@ -130,6 +130,8 @@ describe('AI design Main route boundary', () => {
const workspace = {
bootstrap: vi.fn().mockResolvedValue(bootstrap),
createWorkspace: vi.fn().mockResolvedValue({ workspaceId: 'workspace-one' }),
createConversation: vi.fn(),
getConversation: vi.fn(),
renameWorkspace: vi.fn(),
getWorkspace: vi.fn(),
submitMessage: vi.fn().mockResolvedValue({ workspaceId: 'workspace/one' }),
@@ -177,12 +179,13 @@ describe('AI design Main route boundary', () => {
}),
messageResponse.res,
new URL(
'http://127.0.0.1/api/works/image-workspace/workspaces/workspace%2Fone/messages',
'http://127.0.0.1/api/works/image-workspace/workspaces/workspace%2Fone/conversations/conversation%2Fone/messages',
),
ctx,
);
expect(workspace.submitMessage).toHaveBeenCalledWith({
workspaceId: 'workspace/one',
conversationId: 'conversation/one',
clientTurnId: 'turn-one',
expectedTurnRevision: 3,
message: '继续编辑',
@@ -221,12 +224,13 @@ describe('AI design Main route boundary', () => {
}),
confirmResponse.res,
new URL(
'http://127.0.0.1/api/works/image-workspace/workspaces/workspace%2Fone/quotes/quote%2Fone/confirm',
'http://127.0.0.1/api/works/image-workspace/workspaces/workspace%2Fone/conversations/conversation%2Fone/quotes/quote%2Fone/confirm',
),
ctx,
);
expect(workspace.confirmGeneration).toHaveBeenCalledWith({
workspaceId: 'workspace/one',
conversationId: 'conversation/one',
quoteId: 'quote/one',
clientTurnId: 'turn-two',
expectedTurnRevision: 4,
@@ -391,6 +395,7 @@ describe('AI design Main route boundary', () => {
generationTask: {
taskId: 'task-live',
workspaceId: 'workspace/one',
conversationId: 'conversation/one',
medium: 'image' as const,
status: 'succeeded' as const,
briefVersion: 1,
@@ -414,7 +419,7 @@ describe('AI design Main route boundary', () => {
request,
response as unknown as ServerResponse,
new URL(
'http://127.0.0.1/api/works/image-workspace/workspaces/workspace%2Fone/events',
'http://127.0.0.1/api/works/image-workspace/workspaces/workspace%2Fone/conversations/conversation%2Fone/events',
),
{ imageWorkspace: { openWorkspaceEvents } } as unknown as HostApiContext,
);
@@ -422,6 +427,7 @@ describe('AI design Main route boundary', () => {
expect(handled).toBe(true);
expect(openWorkspaceEvents).toHaveBeenCalledWith({
workspaceId: 'workspace/one',
conversationId: 'conversation/one',
afterEventId: 'session-one:6',
});
expect(response.statusCode).toBe(200);