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:
@@ -47,7 +47,7 @@ export async function bootstrap(options: BootstrapOptions, dependencies: Bootstr
|
||||
|
||||
try {
|
||||
logger = await buildLogger(config.logging, options.mode, options.version);
|
||||
} catch (logInitError) {
|
||||
} catch (logInitError: unknown) {
|
||||
createFallback().fatal(
|
||||
`日志初始化失败: ${logInitError instanceof Error ? logInitError.message : String(logInitError)}`,
|
||||
);
|
||||
@@ -83,7 +83,7 @@ export async function bootstrap(options: BootstrapOptions, dependencies: Bootstr
|
||||
staticAssets: options.staticAssets,
|
||||
version: options.version,
|
||||
});
|
||||
} catch (error) {
|
||||
} catch (error: unknown) {
|
||||
if (logger) {
|
||||
logger.fatal({ error: error instanceof Error ? error.message : String(error) }, "启动失败");
|
||||
logger.flush();
|
||||
|
||||
@@ -192,7 +192,7 @@ function validateLoggingConfig(logging: LoggingConfig | undefined, issues: Confi
|
||||
if (bytes <= 0) {
|
||||
issues.push(issue("invalid-value", "server.logging.file.rotation.size", "滚动大小必须为正整数字节数"));
|
||||
}
|
||||
} catch (error) {
|
||||
} catch (error: unknown) {
|
||||
issues.push(
|
||||
issue(
|
||||
"invalid-value",
|
||||
|
||||
@@ -11,4 +11,13 @@ export {
|
||||
} from "./conversations";
|
||||
export { loadMigrationsFromDir, type MigrationRecord } from "./load-migrations";
|
||||
export { runMigrations } from "./migrate";
|
||||
export {
|
||||
createModel,
|
||||
deleteModel,
|
||||
getModel,
|
||||
getModelsByProviderId,
|
||||
getModelWithProvider,
|
||||
listModels,
|
||||
updateModel,
|
||||
} from "./models";
|
||||
export { conversations, messages, projects, schemaMigrations } from "./schema";
|
||||
|
||||
@@ -90,6 +90,38 @@ export function getModelsByProviderId(raw: Database, providerId: string): number
|
||||
return Number(result?.count ?? 0);
|
||||
}
|
||||
|
||||
export function getModelWithProvider(
|
||||
raw: Database,
|
||||
modelId: string,
|
||||
):
|
||||
| { error: string; status: number }
|
||||
| {
|
||||
model: { modelId: string; name: string; providerId: string };
|
||||
provider: { apiKey: string; baseUrl: string; id: string; type: string };
|
||||
} {
|
||||
const db = wrap(raw);
|
||||
const row = db.select().from(models).where(eq(models.id, modelId)).get();
|
||||
|
||||
if (!row) return { error: "模型不存在", status: 404 };
|
||||
|
||||
const providerRow = db.select().from(providers).where(eq(providers.id, row.providerId)).get();
|
||||
if (!providerRow) return { error: "供应商不存在", status: 404 };
|
||||
|
||||
return {
|
||||
model: {
|
||||
modelId: row.modelId,
|
||||
name: row.name,
|
||||
providerId: row.providerId,
|
||||
},
|
||||
provider: {
|
||||
apiKey: providerRow.apiKey,
|
||||
baseUrl: providerRow.baseUrl,
|
||||
id: providerRow.id,
|
||||
type: providerRow.type,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function listModels(
|
||||
raw: Database,
|
||||
options: { keyword?: string; page: number; pageSize: number; providerId?: string },
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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 });
|
||||
}
|
||||
|
||||
|
||||
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user