Files
pikasTech-HWLAB/internal/dev-entrypoint/cloud-web-routes.mjs
T
2026-06-04 15:44:07 +08:00

111 lines
4.0 KiB
JavaScript

const GET_PROXY_PREFIXES = Object.freeze(["/v1/"]);
const GET_PROXY_ROUTES = new Set(["/v1", "/auth/session"]);
const POST_PROXY_ROUTES = new Set([
"/auth/login",
"/auth/logout",
"/json-rpc",
"/v1/agent/chat",
"/v1/agent/chat/cancel",
"/v1/agent/chat/steer",
"/v1/agent/sessions",
"/v1/m3/io",
"/v1/skills/uploads"
]);
const PUBLIC_PROXY_ROUTES = new Set([
"GET /auth/session",
"POST /auth/login",
"POST /auth/logout",
"POST /v1/agent/chat",
"POST /v1/agent/chat/cancel",
"POST /v1/agent/chat/steer"
]);
export function cloudWebProxyRoutePolicy(method, pathname) {
const normalizedMethod = normalizeMethod(method);
const normalizedPath = normalizePathname(pathname);
const routeKey = `${normalizedMethod} ${normalizedPath}`;
const proxy = isCloudApiProxyRoute(normalizedMethod, normalizedPath);
const publicRoute = proxy && (
PUBLIC_PROXY_ROUTES.has(routeKey) ||
isPublicCodeAgentPollRoute(normalizedMethod, normalizedPath)
);
return {
proxy,
authRequired: proxy && !publicRoute,
publicRoute,
routeKey
};
}
export function isCloudApiProxyRoute(method, pathname) {
const normalizedMethod = normalizeMethod(method);
const normalizedPath = normalizePathname(pathname);
if (normalizedMethod === "GET") {
return GET_PROXY_ROUTES.has(normalizedPath) ||
GET_PROXY_PREFIXES.some((prefix) => normalizedPath.startsWith(prefix));
}
if (normalizedMethod === "POST") {
return POST_PROXY_ROUTES.has(normalizedPath) ||
isApiKeyWriteProxyRoute(normalizedMethod, normalizedPath) ||
normalizedPath.startsWith("/v1/rpc/") ||
normalizedPath.startsWith("/v1/agent/sessions/") ||
isDevicePodPostProxyRoute(normalizedPath) ||
isWorkbenchWorkspaceWriteProxyRoute(normalizedMethod, normalizedPath);
}
if (normalizedMethod === "PATCH" || normalizedMethod === "PUT") {
return isWorkbenchWorkspaceWriteProxyRoute(normalizedMethod, normalizedPath) || isAgentConversationWriteProxyRoute(normalizedMethod, normalizedPath);
}
if (normalizedMethod === "DELETE") {
return isApiKeyWriteProxyRoute(normalizedMethod, normalizedPath) ||
isAgentConversationWriteProxyRoute(normalizedMethod, normalizedPath);
}
return false;
}
function isApiKeyWriteProxyRoute(method, pathname) {
if (pathname === "/v1/api-keys" && method === "POST") return true;
if (!pathname.startsWith("/v1/api-keys/")) return false;
if (method === "DELETE") return true;
if (method !== "POST") return false;
return pathname.endsWith("/regenerate");
}
function isDevicePodPostProxyRoute(pathname) {
const parts = pathname.split("/").filter(Boolean);
if (parts.length < 4 || parts[0] !== "v1" || parts[1] !== "device-pods") return false;
if (parts.length === 4 && parts[3] === "jobs") return true;
if (parts.length === 6 && parts[3] === "jobs" && parts[5] === "cancel") return true;
return false;
}
function isWorkbenchWorkspaceWriteProxyRoute(method, pathname) {
const parts = pathname.split("/").filter(Boolean);
if (parts.length < 4 || parts[0] !== "v1" || parts[1] !== "workbench" || parts[2] !== "workspace") return false;
if ((method === "PATCH" || method === "PUT") && parts.length === 4) return true;
if (method === "POST" && parts.length === 5) return parts[4] === "select-conversation" || parts[4] === "reset";
return false;
}
function isAgentConversationWriteProxyRoute(method, pathname) {
const parts = pathname.split("/").filter(Boolean);
if (parts.length !== 4 || parts[0] !== "v1" || parts[1] !== "agent" || parts[2] !== "conversations") return false;
return ["PUT", "PATCH", "DELETE"].includes(method);
}
function isPublicCodeAgentPollRoute(method, pathname) {
return method === "GET" && (
pathname.startsWith("/v1/agent/chat/result/") ||
pathname.startsWith("/v1/agent/chat/trace/")
);
}
function normalizeMethod(method) {
return String(method || "GET").trim().toUpperCase() || "GET";
}
function normalizePathname(pathname) {
const value = String(pathname || "/").trim();
if (!value || value[0] !== "/") return "/";
return value.replace(/\/+$/u, "") || "/";
}