feat: AI 对话支持 A2UI 表单/审查/图表与 Excel 读取
This commit is contained in:
@@ -54,6 +54,9 @@ export class AiConfig {
|
||||
@Column({ name: 'timeout_ms', type: 'int', default: 30000 })
|
||||
timeoutMs: number;
|
||||
|
||||
@Column({ name: 'reasoning_effort', type: 'varchar', length: 20, nullable: true })
|
||||
reasoningEffort: string | null;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
verified: boolean;
|
||||
|
||||
|
||||
@@ -482,6 +482,7 @@ export class AiConfigService {
|
||||
enabled: config.enabled,
|
||||
supportsVision: config.supportsVision,
|
||||
timeoutMs: config.timeoutMs,
|
||||
reasoningEffort: config.reasoningEffort ?? null,
|
||||
verified: config.verified,
|
||||
lastTestedAt: config.lastTestedAt?.toISOString() ?? null,
|
||||
lastTestLatencyMs: config.lastTestLatencyMs ?? null,
|
||||
@@ -511,6 +512,10 @@ export class AiConfigService {
|
||||
config.timeoutMs = dto.timeoutMs;
|
||||
}
|
||||
|
||||
if (dto.reasoningEffort !== undefined) {
|
||||
config.reasoningEffort = dto.reasoningEffort || null;
|
||||
}
|
||||
|
||||
// Handle apiKey — empty/undefined = keep existing
|
||||
if (dto.apiKey !== undefined && dto.apiKey !== '') {
|
||||
const { ciphertext, iv, authTag } = encrypt(dto.apiKey);
|
||||
@@ -848,6 +853,7 @@ export class AiConfigService {
|
||||
timeoutMs: config.timeoutMs,
|
||||
enabled: config.enabled,
|
||||
supportsVision: config.supportsVision,
|
||||
reasoningEffort: config.reasoningEffort ?? null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import { AiProvider } from '../ai-config.entity';
|
||||
|
||||
const PROVIDERS = [AiProvider.OPENAI, AiProvider.DEEPSEEK, AiProvider.OPENAI_COMPATIBLE] as const;
|
||||
export const REASONING_EFFORT_LEVELS = ['none', 'low', 'medium', 'high', 'xhigh'] as const;
|
||||
|
||||
const DEFAULT_BASE_URLS: Record<AiProvider, string> = {
|
||||
[AiProvider.OPENAI]: 'https://api.openai.com/v1',
|
||||
@@ -51,6 +52,10 @@ export class SaveAiConfigDto {
|
||||
@Min(1000)
|
||||
@Max(120000)
|
||||
timeoutMs?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsIn(REASONING_EFFORT_LEVELS)
|
||||
reasoningEffort?: string | null;
|
||||
}
|
||||
|
||||
/** DTO for POST /api/ai/config/test — all fields optional, validate only when provided */
|
||||
@@ -76,6 +81,10 @@ export class TestAiConfigDto {
|
||||
@Min(1000)
|
||||
@Max(120000)
|
||||
timeoutMs?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsIn(REASONING_EFFORT_LEVELS)
|
||||
reasoningEffort?: string | null;
|
||||
}
|
||||
|
||||
/** Response shape for GET /api/ai/config — NEVER includes plaintext key */
|
||||
@@ -91,6 +100,7 @@ export interface AiConfigResponseDto {
|
||||
enabled: boolean;
|
||||
supportsVision: boolean;
|
||||
timeoutMs: number;
|
||||
reasoningEffort: string | null;
|
||||
verified: boolean;
|
||||
lastTestedAt: string | null;
|
||||
lastTestLatencyMs: number | null;
|
||||
@@ -117,6 +127,7 @@ export interface AiRuntimeConfig {
|
||||
timeoutMs: number;
|
||||
enabled: boolean;
|
||||
supportsVision: boolean;
|
||||
reasoningEffort: string | null;
|
||||
}
|
||||
|
||||
/** DTO for POST /api/ai/config/models — fetch available model list from provider */
|
||||
|
||||
Reference in New Issue
Block a user