Menu
popagent
publicLatest change 4565eb356975518dfc0202eab29b56dff51e8f71 - add deterministic agent health validation by AkurAI Build
import { isAbsolute, posix } from "node:path";
import { z } from "zod";
import { codeIntelligence, type CodeIntelligenceService } from "./code-intelligence";
import { agentWorkspaces, type AgentWorkspaceStore } from "./agent-workspaces";
const relativePathSchema = z.string().trim().min(1).max(1_024).refine((value) => {
const normalized = posix.normalize(value.replaceAll("\\", "/"));
return !isAbsolute(normalized) && normalized !== ".." && !normalized.startsWith("../");
}, "Path must be repository-relative");
const impactInputSchema = z.object({
paths: z.array(relativePathSchema).max(8).default([]),
}).strict();
type Service = Pick<CodeIntelligenceService, "codeContext" | "symbolContext" | "changeImpact">;
type WorkspaceStore = Pick<AgentWorkspaceStore, "get">;
type RouteRequest = Request & { params: { id: string } };
type RouteHandler = (request: RouteRequest) => Promise<Response>;
export function createCodeIntelligenceRoutes(options: {
workspaceStore?: WorkspaceStore;
service?: Service;
} = {}): Record<string, RouteHandler> {
const workspaceStore = options.workspaceStore ?? agentWorkspaces;
const service = options.service ?? codeIntelligence;
async function workspaceExists(id: string): Promise<boolean> {
return Boolean(await workspaceStore.get(id));
}
return {
"/api/workspaces/:id/code-context": async (request) => {
if (!(await workspaceExists(request.params.id))) {
return Response.json({ error: "Workspace not found" }, { status: 404 });
}
const url = new URL(request.url);
const input = z.object({
query: z.string().trim().min(1).max(2_000),
limit: z.coerce.number().int().min(1).max(20).default(8),
}).safeParse({
query: url.searchParams.get("q") ?? "",
limit: url.searchParams.get("limit") ?? undefined,
});
if (!input.success) return Response.json({ error: "Invalid code context query", issues: input.error.issues }, { status: 400 });
try {
return Response.json(await service.codeContext(request.params.id, input.data.query, input.data.limit));
} catch (error) {
return Response.json({ error: error instanceof Error ? error.message : String(error) }, { status: 503 });
}
},
"/api/workspaces/:id/symbol-context": async (request) => {
if (!(await workspaceExists(request.params.id))) {
return Response.json({ error: "Workspace not found" }, { status: 404 });
}
const url = new URL(request.url);
const input = z.object({
symbol: z.string().trim().min(1).max(512),
filePath: relativePathSchema.optional(),
}).safeParse({
symbol: url.searchParams.get("symbol") ?? "",
filePath: url.searchParams.get("filePath") ?? undefined,
});
if (!input.success) return Response.json({ error: "Invalid symbol context query", issues: input.error.issues }, { status: 400 });
try {
return Response.json(await service.symbolContext(
request.params.id,
input.data.symbol,
input.data.filePath,
));
} catch (error) {
return Response.json({ error: error instanceof Error ? error.message : String(error) }, { status: 503 });
}
},
"/api/workspaces/:id/change-impact": async (request) => {
if (!(await workspaceExists(request.params.id))) {
return Response.json({ error: "Workspace not found" }, { status: 404 });
}
const input = impactInputSchema.safeParse(await request.json().catch(() => undefined));
if (!input.success) return Response.json({ error: "Invalid change impact request", issues: input.error.issues }, { status: 400 });
try {
return Response.json(await service.changeImpact(request.params.id, input.data.paths));
} catch (error) {
return Response.json({ error: error instanceof Error ? error.message : String(error) }, { status: 503 });
}
},
};
}