fix: 质量修复 — ESLint 规则 TS6 兼容 + catch 注解 + 空函数体注释化 + 后端架构对齐 + 前端红线修复

- enforce-catch-type: 增加 TSUnknownKeyword 判断,消除28个 TS6 假阳性
- no-empty-function: 统一为注释方案,移除测试/生产分支和 eslint-disable 引导
- logger.ts: 空函数体改为注释说明,删除无用 eslint-disable 指令
- 补充15处 catch 子句 : unknown 类型注解
- 清理7个测试文件失效 eslint-disable 指令
- chat/send.ts: 提取 getModelWithProvider DAO,消除直接 Drizzle 操作
- projects/update.ts: 修复死代码+条件逻辑 bug
- providers/update.ts: 补充至少一个字段校验
- 前端: inline style → CSS className, ProviderFormModal whitespace 校验
- 开发文档: 更新 Zod 使用说明(AI SDK 框架级约束)
This commit is contained in:
2026-06-01 23:11:42 +08:00
parent 0d60120219
commit ab7b7fb189
28 changed files with 124 additions and 83 deletions

View File

@@ -1,21 +1,19 @@
import type Database from "bun:sqlite";
import { createAgentUIStreamResponse, generateText, type UIMessage } from "ai";
import { eq } from "drizzle-orm";
import type { RuntimeMode } from "../../../shared/api";
import type { Logger } from "../../logger";
import { createAlfredAgent } from "../../ai/agents/alfred-agent";
import { buildProviderRegistry } from "../../ai/registry";
import { wrap } from "../../db/connection";
import {
createMessage,
getConversation,
updateConversation,
updateConversationTimestamp,
} from "../../db/conversations";
import { models, providers } from "../../db/schema";
import { getModelWithProvider } from "../../db/models";
import { createApiError, jsonResponse } from "../../helpers";
import { validateIdParam } from "../../middleware";
@@ -29,7 +27,7 @@ export async function handleSendChat(req: Request, db: Database, mode: RuntimeMo
let body: { conversationId?: string; messages?: UIMessage[] };
try {
body = (await req.json()) as typeof body;
} catch (e) {
} catch (e: unknown) {
logger.warn({ error: e instanceof Error ? e.message : String(e) }, "请求 JSON 解析失败");
return jsonResponse(createApiError("Invalid JSON body", 400), { mode, status: 400 });
}
@@ -81,19 +79,13 @@ export async function handleSendChat(req: Request, db: Database, mode: RuntimeMo
let model;
try {
const d = wrap(db);
const modelRow = d.select().from(models).where(eq(models.id, conversation.modelId)).get();
if (!modelRow) {
return jsonResponse(createApiError(`模型不存在: ${conversation.modelId}`, 400), { mode, status: 400 });
}
const providerRow = d.select().from(providers).where(eq(providers.id, modelRow.providerId)).get();
if (!providerRow) {
return jsonResponse(createApiError(`供应商不存在: ${modelRow.providerId}`, 400), { mode, status: 400 });
const result = getModelWithProvider(db, conversation.modelId);
if ("error" in result) {
return jsonResponse(createApiError(result.error, result.status), { mode, status: result.status });
}
const registry = buildProviderRegistry(db);
model = registry.languageModel(`${providerRow.id}:${modelRow.modelId}`);
model = registry.languageModel(`${result.provider.id}:${result.model.modelId}`);
} catch (e: unknown) {
const msg = e instanceof Error ? e.message : String(e);
return jsonResponse(createApiError(`模型初始化失败:${msg}`, 500), { mode, status: 500 });

View File

@@ -25,10 +25,11 @@ export async function handleUpdateProject(
} catch (e: unknown) {
logger.warn({ error: e instanceof Error ? e.message : String(e) }, "请求 JSON 解析失败");
return jsonResponse(createApiError("Invalid JSON body", 400), { mode, status: 400 });
return jsonResponse(createApiError("Invalid JSON body", 400), { mode, status: 400 });
}
if (!body.name && !body.description && body.name !== "" && body.description !== "") {
const hasName = body.name !== undefined && body.name.trim() !== "";
const hasDescription = body.description !== undefined && body.description.trim() !== "";
if (!hasName && !hasDescription) {
return jsonResponse(createApiError("At least one of name or description is required", 400), { mode, status: 400 });
}

View File

@@ -34,6 +34,13 @@ export async function handleUpdateProvider(
});
}
if (body.name === undefined && body.baseUrl === undefined && body.apiKey === undefined && body.type === undefined) {
return jsonResponse(createApiError("至少需要提供 name, baseUrl, apiKey 或 type 中的一个字段", 400), {
mode,
status: 400,
});
}
const result = updateProvider(db, validated.id, body, logger);
if ("error" in result) {
return jsonResponse(createApiError(result.error, result.status), { mode, status: result.status });