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

@@ -254,6 +254,77 @@ describe('Works Square V2 Design Workspace adapter', () => {
);
});
it('projects an invalid reasoner result as a safe actionable message', async () => {
const fetchMock = vi.fn(async (input: string | URL) => {
const url = String(input);
if (url.endsWith('/commands')) {
return jsonResponse({ run_id: 'run-1', status: 'queued', error: null });
}
if (url.endsWith('/runs/run-1')) {
return jsonResponse({
run_id: 'run-1',
status: 'failed',
error: {
code: 'design_reasoner_invalid',
message: 'Design guidance returned an invalid result',
retryable: false,
},
});
}
throw new Error(`Unexpected URL: ${url}`);
});
const module = new WorksSquareDesignWorkspace({
apiBaseUrl: 'https://works.example',
fetchImpl: fetchMock as unknown as typeof fetch,
});
await expect(module.submitCommand({
kind: 'apply_input',
workspaceId: 'workspace-1',
sessionId: 'session-1',
expectedDirectionRevision: 4,
clientOperationId: 'operation-chat-1',
input: { kind: 'chat', message: '画一只会做饭的机器人' },
})).rejects.toMatchObject({
status: 502,
code: 'design_reasoner_invalid',
message: 'AI 没有整理好这次想法,请再试一次',
commandOutcome: 'definitive_failure',
} satisfies Partial<DesignWorkspaceModuleError>);
});
it('marks polling auth failure as unknown after the command was accepted', async () => {
getTokenMock
.mockResolvedValueOnce('access-token')
.mockResolvedValueOnce('access-token')
.mockResolvedValueOnce(null);
const fetchMock = vi.fn(async (input: string | URL) => {
const url = String(input);
if (url.endsWith('/commands')) {
return jsonResponse({ run_id: 'run-1', status: 'queued', error: null });
}
if (url.endsWith('/runs/run-1')) return jsonResponse({ detail: 'expired' }, 401);
throw new Error(`Unexpected URL: ${url}`);
});
const module = new WorksSquareDesignWorkspace({
apiBaseUrl: 'https://works.example',
fetchImpl: fetchMock as unknown as typeof fetch,
});
await expect(module.submitCommand({
kind: 'apply_input',
workspaceId: 'workspace-1',
sessionId: 'session-1',
expectedDirectionRevision: 4,
clientOperationId: 'operation-chat-1',
input: { kind: 'chat', message: '画一只会做饭的机器人' },
})).rejects.toMatchObject({
status: 401,
code: 'AUTH_EXPIRED',
commandOutcome: 'unknown',
} satisfies Partial<DesignWorkspaceModuleError>);
});
it('resumes the V2 event stream from the supplied sequence and normalizes deltas', async () => {
const socket = createSocket();
let streamUrl = '';