ai-chatbot/lib/canvas/agent-operation-route.ts

130 lines
3.4 KiB
TypeScript

import { ZodError } from "zod";
import {
canApplyCanvasAgentMutations,
type CanvasAgentFeatureFlags,
} from "@/lib/canvas/agent-feature-flags";
import {
CanvasAgentMutationError,
type CanvasOperationResult,
} from "@/lib/canvas/agent-mutations";
import { parseCanvasAgentOperationRequestBody } from "@/lib/canvas/agent-operation-request";
import type { CanvasOperationPlan } from "@/types/canvas/agent-protocol";
export type CanvasAgentOperationRouteBody =
| {
success: true;
data: CanvasOperationResult;
}
| {
success: false;
error: string;
code?: string;
writebackMode?: CanvasAgentFeatureFlags["writebackMode"];
details?: unknown;
};
export type CanvasAgentOperationRouteResponse = {
status: number;
body: CanvasAgentOperationRouteBody;
};
export async function handleCanvasAgentOperationRouteRequest(params: {
userId?: string | null;
projectId: string;
rawBody?: unknown;
readBody?: () => Promise<unknown>;
features: CanvasAgentFeatureFlags;
applyOperation: (input: {
userId: string;
projectId: string;
plan: CanvasOperationPlan;
}) => Promise<CanvasOperationResult>;
logger?: Pick<Console, "error">;
}): Promise<CanvasAgentOperationRouteResponse> {
const userId = String(params.userId || "").trim();
if (!userId) {
return {
status: 401,
body: { success: false, error: "未登录" },
};
}
if (!canApplyCanvasAgentMutations(params.features)) {
return {
status: 409,
body: {
success: false,
error: "当前画布 Agent 写回处于灰度保护,未修改画布",
code: "CANVAS_AGENT_WRITEBACK_DISABLED",
writebackMode: params.features.writebackMode,
},
};
}
try {
const rawBody = params.readBody ? await params.readBody() : params.rawBody;
const body = parseCanvasAgentOperationRequestBody(rawBody);
const planProjectId = String(body.operationPlan.projectId || "").trim();
if (planProjectId && planProjectId !== params.projectId) {
return {
status: 400,
body: {
success: false,
error: "operation projectId 与请求项目不一致",
code: "CANVAS_AGENT_PROJECT_MISMATCH",
},
};
}
const operationPlan: CanvasOperationPlan = {
...body.operationPlan,
projectId: planProjectId || params.projectId,
};
const result = await params.applyOperation({
userId,
projectId: params.projectId,
plan: operationPlan,
});
return {
status: 200,
body: {
success: true,
data: result,
},
};
} catch (error) {
if (error instanceof CanvasAgentMutationError) {
return {
status: error.status,
body: {
success: false,
error: error.message,
code: error.code,
},
};
}
if (error instanceof ZodError) {
return {
status: 400,
body: {
success: false,
error: "请求参数无效",
details: error.flatten(),
},
};
}
if (error instanceof SyntaxError) {
return {
status: 400,
body: { success: false, error: "请求 JSON 无效" },
};
}
params.logger?.error("[CanvasAgentOperations] apply operation failed:", error);
return {
status: 500,
body: { success: false, error: "执行画布操作失败" },
};
}
}