mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
refactor(gateway): dedupe agents server-method handlers
This commit is contained in:
@@ -120,6 +120,43 @@ type ResolvedAgentWorkspaceFilePath =
|
||||
reason: string;
|
||||
};
|
||||
|
||||
type ResolvedWorkspaceFilePath = Exclude<ResolvedAgentWorkspaceFilePath, { kind: "invalid" }>;
|
||||
|
||||
function resolveNotFoundWorkspaceFilePathResult(params: {
|
||||
error: unknown;
|
||||
allowMissing: boolean;
|
||||
requestPath: string;
|
||||
ioPath: string;
|
||||
workspaceReal: string;
|
||||
}): Extract<ResolvedAgentWorkspaceFilePath, { kind: "missing" | "invalid" }> | undefined {
|
||||
if (!isNotFoundPathError(params.error)) {
|
||||
return undefined;
|
||||
}
|
||||
if (params.allowMissing) {
|
||||
return {
|
||||
kind: "missing",
|
||||
requestPath: params.requestPath,
|
||||
ioPath: params.ioPath,
|
||||
workspaceReal: params.workspaceReal,
|
||||
};
|
||||
}
|
||||
return { kind: "invalid", requestPath: params.requestPath, reason: "file not found" };
|
||||
}
|
||||
|
||||
function resolveWorkspaceFilePathResultOrThrow(params: {
|
||||
error: unknown;
|
||||
allowMissing: boolean;
|
||||
requestPath: string;
|
||||
ioPath: string;
|
||||
workspaceReal: string;
|
||||
}): Extract<ResolvedAgentWorkspaceFilePath, { kind: "missing" | "invalid" }> {
|
||||
const notFoundResult = resolveNotFoundWorkspaceFilePathResult(params);
|
||||
if (notFoundResult) {
|
||||
return notFoundResult;
|
||||
}
|
||||
throw params.error;
|
||||
}
|
||||
|
||||
async function resolveWorkspaceRealPath(workspaceDir: string): Promise<string> {
|
||||
try {
|
||||
return await fs.realpath(workspaceDir);
|
||||
@@ -151,17 +188,21 @@ async function resolveAgentWorkspaceFilePath(params: {
|
||||
};
|
||||
}
|
||||
|
||||
const notFoundContext = {
|
||||
allowMissing: params.allowMissing,
|
||||
requestPath,
|
||||
workspaceReal,
|
||||
} as const;
|
||||
|
||||
let candidateLstat: Awaited<ReturnType<typeof fs.lstat>>;
|
||||
try {
|
||||
candidateLstat = await fs.lstat(candidatePath);
|
||||
} catch (err) {
|
||||
if (isNotFoundPathError(err)) {
|
||||
if (params.allowMissing) {
|
||||
return { kind: "missing", requestPath, ioPath: candidatePath, workspaceReal };
|
||||
}
|
||||
return { kind: "invalid", requestPath, reason: "file not found" };
|
||||
}
|
||||
throw err;
|
||||
return resolveWorkspaceFilePathResultOrThrow({
|
||||
error: err,
|
||||
...notFoundContext,
|
||||
ioPath: candidatePath,
|
||||
});
|
||||
}
|
||||
|
||||
if (candidateLstat.isSymbolicLink()) {
|
||||
@@ -169,25 +210,21 @@ async function resolveAgentWorkspaceFilePath(params: {
|
||||
try {
|
||||
targetReal = await fs.realpath(candidatePath);
|
||||
} catch (err) {
|
||||
if (isNotFoundPathError(err)) {
|
||||
if (params.allowMissing) {
|
||||
return { kind: "missing", requestPath, ioPath: candidatePath, workspaceReal };
|
||||
}
|
||||
return { kind: "invalid", requestPath, reason: "file not found" };
|
||||
}
|
||||
throw err;
|
||||
return resolveWorkspaceFilePathResultOrThrow({
|
||||
error: err,
|
||||
...notFoundContext,
|
||||
ioPath: candidatePath,
|
||||
});
|
||||
}
|
||||
let targetStat: Awaited<ReturnType<typeof fs.stat>>;
|
||||
try {
|
||||
targetStat = await fs.stat(targetReal);
|
||||
} catch (err) {
|
||||
if (isNotFoundPathError(err)) {
|
||||
if (params.allowMissing) {
|
||||
return { kind: "missing", requestPath, ioPath: targetReal, workspaceReal };
|
||||
}
|
||||
return { kind: "invalid", requestPath, reason: "file not found" };
|
||||
}
|
||||
throw err;
|
||||
return resolveWorkspaceFilePathResultOrThrow({
|
||||
error: err,
|
||||
...notFoundContext,
|
||||
ioPath: targetReal,
|
||||
});
|
||||
}
|
||||
if (!targetStat.isFile()) {
|
||||
return { kind: "invalid", requestPath, reason: "path is not a regular file" };
|
||||
@@ -328,6 +365,25 @@ function resolveOptionalStringParam(value: unknown): string | undefined {
|
||||
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
||||
}
|
||||
|
||||
function respondInvalidMethodParams(respond: RespondFn, method: string, errors: unknown): void {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
`invalid ${method} params: ${formatValidationErrors(errors)}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function isConfiguredAgent(cfg: ReturnType<typeof loadConfig>, agentId: string): boolean {
|
||||
return findAgentEntryIndex(listAgentEntries(cfg), agentId) >= 0;
|
||||
}
|
||||
|
||||
function respondAgentNotFound(respond: RespondFn, agentId: string): void {
|
||||
respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, `agent "${agentId}" not found`));
|
||||
}
|
||||
|
||||
async function moveToTrashBestEffort(pathname: string): Promise<void> {
|
||||
if (!pathname) {
|
||||
return;
|
||||
@@ -356,10 +412,7 @@ async function resolveWorkspaceFilePathOrRespond(params: {
|
||||
respond: RespondFn;
|
||||
workspaceDir: string;
|
||||
name: string;
|
||||
}): Promise<
|
||||
| Exclude<Awaited<ReturnType<typeof resolveAgentWorkspaceFilePath>>, { kind: "invalid" }>
|
||||
| undefined
|
||||
> {
|
||||
}): Promise<ResolvedWorkspaceFilePath | undefined> {
|
||||
const resolvedPath = await resolveAgentWorkspaceFilePath({
|
||||
workspaceDir: params.workspaceDir,
|
||||
name: params.name,
|
||||
@@ -490,27 +543,14 @@ export const agentsHandlers: GatewayRequestHandlers = {
|
||||
},
|
||||
"agents.update": async ({ params, respond }) => {
|
||||
if (!validateAgentsUpdateParams(params)) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
`invalid agents.update params: ${formatValidationErrors(
|
||||
validateAgentsUpdateParams.errors,
|
||||
)}`,
|
||||
),
|
||||
);
|
||||
respondInvalidMethodParams(respond, "agents.update", validateAgentsUpdateParams.errors);
|
||||
return;
|
||||
}
|
||||
|
||||
const cfg = loadConfig();
|
||||
const agentId = normalizeAgentId(String(params.agentId ?? ""));
|
||||
if (findAgentEntryIndex(listAgentEntries(cfg), agentId) < 0) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(ErrorCodes.INVALID_REQUEST, `agent "${agentId}" not found`),
|
||||
);
|
||||
if (!isConfiguredAgent(cfg, agentId)) {
|
||||
respondAgentNotFound(respond, agentId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -549,16 +589,7 @@ export const agentsHandlers: GatewayRequestHandlers = {
|
||||
},
|
||||
"agents.delete": async ({ params, respond }) => {
|
||||
if (!validateAgentsDeleteParams(params)) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
`invalid agents.delete params: ${formatValidationErrors(
|
||||
validateAgentsDeleteParams.errors,
|
||||
)}`,
|
||||
),
|
||||
);
|
||||
respondInvalidMethodParams(respond, "agents.delete", validateAgentsDeleteParams.errors);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -572,12 +603,8 @@ export const agentsHandlers: GatewayRequestHandlers = {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (findAgentEntryIndex(listAgentEntries(cfg), agentId) < 0) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(ErrorCodes.INVALID_REQUEST, `agent "${agentId}" not found`),
|
||||
);
|
||||
if (!isConfiguredAgent(cfg, agentId)) {
|
||||
respondAgentNotFound(respond, agentId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -631,16 +658,7 @@ export const agentsHandlers: GatewayRequestHandlers = {
|
||||
},
|
||||
"agents.files.get": async ({ params, respond }) => {
|
||||
if (!validateAgentsFilesGetParams(params)) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
`invalid agents.files.get params: ${formatValidationErrors(
|
||||
validateAgentsFilesGetParams.errors,
|
||||
)}`,
|
||||
),
|
||||
);
|
||||
respondInvalidMethodParams(respond, "agents.files.get", validateAgentsFilesGetParams.errors);
|
||||
return;
|
||||
}
|
||||
const resolved = resolveAgentWorkspaceFileOrRespondError(params, respond);
|
||||
@@ -691,16 +709,7 @@ export const agentsHandlers: GatewayRequestHandlers = {
|
||||
},
|
||||
"agents.files.set": async ({ params, respond }) => {
|
||||
if (!validateAgentsFilesSetParams(params)) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
`invalid agents.files.set params: ${formatValidationErrors(
|
||||
validateAgentsFilesSetParams.errors,
|
||||
)}`,
|
||||
),
|
||||
);
|
||||
respondInvalidMethodParams(respond, "agents.files.set", validateAgentsFilesSetParams.errors);
|
||||
return;
|
||||
}
|
||||
const resolved = resolveAgentWorkspaceFileOrRespondError(params, respond);
|
||||
|
||||
Reference in New Issue
Block a user