fix(design): preserve command outcome certainty

This commit is contained in:
2026-09-03 18:25:06 +08:00
parent 4d8b19eeb5
commit a16dfd0d6f
15 changed files with 576 additions and 23 deletions

View File

@@ -134,6 +134,97 @@ describe('V2 Living Form store', () => {
expect(useImageWorkspaceStore.getState().pendingOperations).toEqual({});
});
it('settles a definitive reasoner failure without losing the chat draft', async () => {
const source = await loadedStore();
useImageWorkspaceStore.getState().setChatDraft('画一只会做饭的机器人');
submitCommandMock.mockImplementationOnce(async () => {
source.emit('design.assistant.delta', {
id: 'session-1:7',
type: 'design.assistant.delta',
workspaceId: 'workspace-1',
directionId: 'direction-1',
clientOperationId: 'operation-1',
directionRevision: 4,
chunkIndex: 0,
delta: '正在整理',
});
throw new ImageWorkspaceApiError(
502,
'design_reasoner_invalid',
'AI 没有整理好这次想法,请再试一次',
'definitive_failure',
);
});
await expect(useImageWorkspaceStore.getState().sendChat()).rejects.toMatchObject({
status: 502,
code: 'design_reasoner_invalid',
});
expect(useImageWorkspaceStore.getState()).toMatchObject({
chatDraft: '画一只会做饭的机器人',
error: 'AI 没有整理好这次想法,请再试一次',
});
expect(useImageWorkspaceStore.getState().pendingOperations).toEqual({});
expect(useImageWorkspaceStore.getState().assistantStreams).toEqual({});
});
it('settles any Main-confirmed terminal run without an error-code allowlist', async () => {
await loadedStore();
submitCommandMock.mockRejectedValueOnce(new ImageWorkspaceApiError(
422,
'policy_blocked',
'当前内容不符合创作安全规则',
'definitive_failure',
));
await expect(useImageWorkspaceStore.getState().requestQuote()).rejects.toMatchObject({
code: 'policy_blocked',
commandOutcome: 'definitive_failure',
});
expect(useImageWorkspaceStore.getState().pendingOperations).toEqual({});
expect(useImageWorkspaceStore.getState().error).toBe('当前内容不符合创作安全规则');
});
it('keeps the accepted command identity when polling auth expires', async () => {
const source = await loadedStore();
useImageWorkspaceStore.getState().setChatDraft('画一只会做饭的机器人');
submitCommandMock.mockImplementationOnce(async () => {
source.emit('design.assistant.delta', {
id: 'session-1:7',
type: 'design.assistant.delta',
workspaceId: 'workspace-1',
directionId: 'direction-1',
clientOperationId: 'operation-1',
directionRevision: 4,
chunkIndex: 0,
delta: '正在整理',
});
throw new ImageWorkspaceApiError(
401,
'AUTH_EXPIRED',
'登录状态已失效,请重新登录',
'unknown',
);
});
await expect(useImageWorkspaceStore.getState().sendChat()).rejects.toMatchObject({
status: 401,
code: 'AUTH_EXPIRED',
commandOutcome: 'unknown',
});
expect(useImageWorkspaceStore.getState().chatDraft).toBe('画一只会做饭的机器人');
expect(useImageWorkspaceStore.getState().pendingOperations['operation-1']).toMatchObject({
id: 'operation-1',
status: 'unknown',
});
expect(useImageWorkspaceStore.getState().assistantStreams).toEqual({
'operation-1': '正在整理',
});
});
it('expires quote blockers only after the canonical Specification changes', async () => {
await loadedStore();
const blocker = {