Refactor AI chat: streaming, tool calls, UI polish
All checks were successful
CI / check (pull_request) Successful in 3m25s

This commit is contained in:
2026-07-24 16:27:50 +08:00
parent e605586fc9
commit 8656394b9b
55 changed files with 2774 additions and 460 deletions

View File

@@ -48,6 +48,9 @@ export class AiConfig {
@Column({ type: 'boolean', default: true })
enabled: boolean;
@Column({ name: 'supports_vision', type: 'boolean', default: false })
supportsVision: boolean;
@Column({ name: 'timeout_ms', type: 'int', default: 30000 })
timeoutMs: number;

View File

@@ -480,6 +480,7 @@ export class AiConfigService {
keySource: source,
defaultModel: config.defaultModel ?? null,
enabled: config.enabled,
supportsVision: config.supportsVision,
timeoutMs: config.timeoutMs,
verified: config.verified,
lastTestedAt: config.lastTestedAt?.toISOString() ?? null,
@@ -526,6 +527,18 @@ export class AiConfigService {
config.enabled = true;
}
if (dto.supportsVision !== undefined) {
config.supportsVision = dto.supportsVision;
}
if (dto.enabled === true) {
const { plaintext } = this.resolveApiKey(config);
if (!plaintext) throw new BadRequestException('启用 AI 服务前必须配置 API Key');
if (!config.defaultModel?.trim()) {
throw new BadRequestException('启用 AI 服务前必须配置默认模型');
}
}
return this.repo.save(config);
}
@@ -834,6 +847,7 @@ export class AiConfigService {
defaultModel: config.defaultModel,
timeoutMs: config.timeoutMs,
enabled: config.enabled,
supportsVision: config.supportsVision,
};
}
}

View File

@@ -42,6 +42,10 @@ export class SaveAiConfigDto {
@IsBoolean()
enabled?: boolean;
@IsOptional()
@IsBoolean()
supportsVision?: boolean;
@IsOptional()
@IsInt()
@Min(1000)
@@ -85,6 +89,7 @@ export interface AiConfigResponseDto {
keySource: 'database' | 'environment' | 'none';
defaultModel: string | null;
enabled: boolean;
supportsVision: boolean;
timeoutMs: number;
verified: boolean;
lastTestedAt: string | null;
@@ -111,6 +116,7 @@ export interface AiRuntimeConfig {
defaultModel: string;
timeoutMs: number;
enabled: boolean;
supportsVision: boolean;
}
/** DTO for POST /api/ai/config/models — fetch available model list from provider */