feat: AI 对话支持 A2UI 表单/审查/图表与 Excel 读取
This commit is contained in:
@@ -60,6 +60,7 @@ interface AiConfigData {
|
||||
enabled: boolean;
|
||||
supportsVision: boolean;
|
||||
timeoutMs: number;
|
||||
reasoningEffort: string | null;
|
||||
verified: boolean;
|
||||
lastTestedAt: string | null;
|
||||
lastTestLatencyMs: number | null;
|
||||
@@ -99,6 +100,7 @@ interface FormValues {
|
||||
defaultModel: string;
|
||||
timeoutMs: number;
|
||||
supportsVision: boolean;
|
||||
reasoningEffort: string;
|
||||
}
|
||||
|
||||
const DEFAULT_FORM_VALUES: FormValues = {
|
||||
@@ -108,6 +110,7 @@ const DEFAULT_FORM_VALUES: FormValues = {
|
||||
defaultModel: '',
|
||||
timeoutMs: 30000,
|
||||
supportsVision: false,
|
||||
reasoningEffort: '',
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -171,6 +174,7 @@ const AiConfigPage: React.FC = () => {
|
||||
defaultModel: res.data.defaultModel ?? '',
|
||||
timeoutMs: res.data.timeoutMs,
|
||||
supportsVision: res.data.supportsVision,
|
||||
reasoningEffort: res.data.reasoningEffort ?? '',
|
||||
};
|
||||
form.setFieldsValue(initial);
|
||||
setFormValues(initial);
|
||||
@@ -252,7 +256,8 @@ const AiConfigPage: React.FC = () => {
|
||||
// Validate fields (for UI error display) — actual values come from state
|
||||
await form.validateFields(['provider', 'baseUrl', 'timeoutMs']);
|
||||
|
||||
const { provider, baseUrl, defaultModel, apiKey, timeoutMs, supportsVision } = formValues;
|
||||
const { provider, baseUrl, defaultModel, apiKey, timeoutMs, supportsVision, reasoningEffort } =
|
||||
formValues;
|
||||
|
||||
if (provider === 'OPENAI_COMPATIBLE' && !baseUrl) {
|
||||
message.error('OPENAI_COMPATIBLE 模式必须填写 Base URL');
|
||||
@@ -270,6 +275,7 @@ const AiConfigPage: React.FC = () => {
|
||||
enabled: true,
|
||||
supportsVision,
|
||||
timeoutMs,
|
||||
reasoningEffort: reasoningEffort || null,
|
||||
};
|
||||
|
||||
if (apiKey && apiKey !== '••••') {
|
||||
@@ -308,11 +314,12 @@ const AiConfigPage: React.FC = () => {
|
||||
setTesting(true);
|
||||
setTestResult(null);
|
||||
|
||||
const { provider, baseUrl, defaultModel, apiKey, timeoutMs } = formValues;
|
||||
const { provider, baseUrl, defaultModel, apiKey, timeoutMs, reasoningEffort } = formValues;
|
||||
const body: Record<string, unknown> = { provider, timeoutMs };
|
||||
if (baseUrl) body.baseUrl = baseUrl;
|
||||
if (defaultModel) body.defaultModel = defaultModel;
|
||||
if (apiKey && apiKey !== '••••') body.apiKey = apiKey;
|
||||
if (reasoningEffort) body.reasoningEffort = reasoningEffort;
|
||||
|
||||
const res = await api.post<TestResult>('/ai/config/test', body);
|
||||
setTestResult(res);
|
||||
@@ -582,6 +589,25 @@ const AiConfigPage: React.FC = () => {
|
||||
<Switch disabled={!canWrite} checkedChildren="已启用" unCheckedChildren="未启用" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="reasoningEffort"
|
||||
label="推理强度 (reasoning_effort)"
|
||||
extra="OpenAI o 系列等支持该参数的模型生效;DeepSeek 官方接口不支持,选择后也不会发送。"
|
||||
preserve
|
||||
>
|
||||
<Select
|
||||
disabled={!canWrite}
|
||||
size="large"
|
||||
options={[
|
||||
{ value: '', label: '不设置(跟随模型默认)' },
|
||||
{ value: 'low', label: '低 (low)' },
|
||||
{ value: 'medium', label: '中 (medium)' },
|
||||
{ value: 'high', label: '高 (high)' },
|
||||
{ value: 'xhigh', label: '极高 (xhigh)' },
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{config?.verified && (
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Tag icon={<CheckCircleOutlined />} color="success">
|
||||
|
||||
Reference in New Issue
Block a user