feat: consume server model reasoning capabilities

This commit is contained in:
2026-09-01 14:16:18 +08:00
parent 850947c092
commit ae79361742
20 changed files with 711 additions and 20 deletions

View File

@@ -528,6 +528,61 @@ describe('PI-130 feature-complete Coding UI', () => {
expect(screen.queryByRole('menu', { name: '选择推理强度' })).not.toBeInTheDocument();
});
it('shows the native max thinking level as 最高', async () => {
const { CodingComposerRuntimeControls } = await import('@/pages/Chat/CodingComposerRuntimeControls');
const conversation = {
id: 'conversation-max-thinking',
agentId: 'agent-1',
title: 'Max thinking controls',
archivedAt: null,
unread: false,
createdAt: '2026-08-28T00:00:00.000Z',
updatedAt: '2026-08-28T00:00:00.000Z',
model: { accountId: 'account-1', modelId: 'deepseek-v4-pro', thinkingLevel: 'max' as const },
modelResolution: 'resolved' as const,
};
const snapshot: ConversationSnapshot = {
schemaVersion: 1,
conversation: {
id: conversation.id,
projectId: 'project-1',
agentId: conversation.agentId,
title: conversation.title,
model: {
model: conversation.model,
modelResolution: 'resolved',
availableThinkingLevels: ['off', 'low', 'high', 'max'],
},
},
nodes: [],
run: { status: 'idle' },
queue: { items: [] },
context: { usedTokens: 0, contextWindow: 0, compaction: 'idle' },
pendingInteractions: [],
worker: { status: 'ready', generation: 1 },
cursor: { workerGeneration: 1, seq: 0 },
};
render(
<CodingComposerRuntimeControls
conversation={conversation}
snapshot={snapshot}
onRefresh={vi.fn(async () => undefined)}
/>,
);
const settingsTrigger = screen.getByRole('button', {
name: '模型与思考设置deepseek-v4-pro最高',
});
expect(settingsTrigger).toHaveTextContent('最高');
fireEvent.pointerDown(settingsTrigger, { button: 0, ctrlKey: false });
const thinkingRow = await screen.findByRole('menuitem', { name: '推理强度 最高' });
fireEvent.click(thinkingRow);
expect(screen.getByRole('menuitemradio', { name: '最高' })).toBeInTheDocument();
expect(screen.queryByRole('menuitemradio', { name: '极简' })).not.toBeInTheDocument();
expect(screen.queryByRole('menuitemradio', { name: '中等' })).not.toBeInTheDocument();
});
it('blocks overlapping mutations but keeps abort and recover available while confirmation is uncertain', async () => {
interactionApi.abort.mockResolvedValue(undefined);
const recover = vi.fn(async () => undefined);