agent01 / src /middlewares.ts
Auto Deployer
Add enterprise agents: log/code/reg endpoints
a273844
import { Request, Response, NextFunction } from 'express';
import { MissingMaterialItem } from './models';
export class AppError extends Error {
public statusCode: number;
public errorCode: number;
constructor(message: string, statusCode: number, errorCode: number) {
super(message);
this.statusCode = statusCode;
this.errorCode = errorCode;
Object.setPrototypeOf(this, AppError.prototype);
}
}
export class MissingMaterialError extends AppError {
public missingItems: MissingMaterialItem[];
constructor(missingItems: MissingMaterialItem[]) {
super('need_more_material', 400, 4001);
this.missingItems = missingItems;
Object.setPrototypeOf(this, MissingMaterialError.prototype);
}
}
// 请求日志中间件
export const requestLogger = (req: Request, res: Response, next: NextFunction) => {
const started_at = new Date();
// 拦截 res.send 记录结束时间
const originalSend = res.send;
res.send = function (body: any) {
const ended_at = new Date();
// 提取 case_context
const case_context = req.body?.case_context || req.body;
const case_id = case_context?.case_id || 'unknown';
// 提取 meta 数据和 retry_count
const metadata = case_context?.metadata || {};
const retry_count = metadata.retry_count || req.headers['x-retry-count'] || req.body?.retry_count || 0;
// 解析 agent_name
let agent_name = 'unknown';
if (req.path.includes('peer-reg-summary')) agent_name = 'AGENT-01';
else if (req.path.includes('policy-rewrite')) agent_name = 'AGENT-02';
else if (req.path.includes('compliance-check')) agent_name = 'AGENT-03';
else if (req.path.includes('legal-pack')) agent_name = 'AGENT-04';
else if (req.path.includes('log-analysis')) agent_name = 'LOG_ANALYSIS';
else if (req.path.includes('code-security')) agent_name = 'CODE_SECURITY';
else if (req.path.includes('regulatory-penalty-summary')) agent_name = 'REG_PENALTY_SUMMARY';
const status = res.statusCode >= 400 ? 'failed' : 'success';
const error_code = res.locals.errorCode || 0;
const api_latency_ms = ended_at.getTime() - started_at.getTime();
const llm_latency_ms = res.locals.llm_latency_ms || 0;
// 确保绝对不记录 materials,只输出 meta 数据
console.log(JSON.stringify({
case_id,
retry_count,
agent_name,
metadata,
started_at: started_at.toISOString(),
ended_at: ended_at.toISOString(),
api_latency_ms,
llm_latency_ms,
status,
error_code
}));
return originalSend.call(this, body);
};
next();
};
// 全局错误处理中间件
export const errorHandler = (err: any, req: Request, res: Response, next: NextFunction) => {
let statusCode = 500;
let errorCode = 5000;
let message = 'Internal Server Error';
let extraData: any = null;
if (err instanceof MissingMaterialError) {
statusCode = err.statusCode;
errorCode = err.errorCode;
message = err.message;
extraData = { missing_materials: err.missingItems };
} else if (err instanceof AppError) {
statusCode = err.statusCode;
errorCode = err.errorCode;
message = err.message;
} else if (err.message === 'LLM_INFERENCE_FAILED') {
statusCode = 500;
errorCode = 5001;
message = '智能体推理失败';
} else if (err.message === 'MISSING_MATERIALS') {
statusCode = 400;
errorCode = 4001;
message = 'need_more_material';
} else if (err.message === 'INVALID_FORMAT') {
statusCode = 400;
errorCode = 4002;
message = '输入格式错误';
} else if (err.message === 'MISSING_CONTEXT') {
statusCode = 500;
errorCode = 5002;
message = '外部上下文缺失';
} else if (err.message === 'MISSING_LLM_API_KEY') {
statusCode = 500;
errorCode = 5003;
message = 'LLM密钥未配置';
}
// 记录 errorCode 给 logger 使用
res.locals.errorCode = errorCode;
if (err instanceof MissingMaterialError) {
res.status(statusCode).json({
schema_version: 'v1.0',
error_code: 'need_more_material',
message: message,
...(extraData || {})
});
} else {
res.status(statusCode).json({
error: {
code: errorCode,
message: message,
...(extraData || {})
}
});
}
};