import type { HostApiContext } from '../context'; import type { NormalizedHostApiRequest } from '../route-utils'; import { fail, ok, parseJsonBody } from '../route-utils'; import { deleteKnowledgeDoc, listKnowledgeDocs, uploadKnowledgeDoc, isSafeKnowledgeDocName, } from '../../utils/knowledge-docs'; function getDeleteTarget(request: NormalizedHostApiRequest): string | null { const fromQuery = request.url.searchParams.get('name')?.trim() || ''; if (fromQuery) return fromQuery; const body = request.body && typeof request.body === 'string' ? parseJsonBody<{ fileName?: string; name?: string }>(request.body) : (request.body as { fileName?: string; name?: string } | null); const candidate = String(body?.fileName || body?.name || '').trim(); return candidate || null; } export async function handleKnowledgeRoutes( request: NormalizedHostApiRequest, _ctx: HostApiContext, ) { const { pathname, method } = request; if (pathname === '/api/knowledge/docs' && method === 'GET') { try { return ok({ success: true, files: await listKnowledgeDocs(), }); } catch (error) { return fail(500, error instanceof Error ? error.message : String(error)); } } if (pathname === '/api/knowledge/docs' && method === 'POST') { try { const body = parseJsonBody<{ base64?: string; fileName?: string }>(request.body); const fileName = String(body?.fileName || '').trim(); const base64 = String(body?.base64 || '').trim(); if (!fileName) { return fail(400, 'fileName is required'); } if (!base64) { return fail(400, 'base64 is required'); } if (!isSafeKnowledgeDocName(fileName)) { return fail(400, 'Invalid file name'); } return ok({ success: true, file: await uploadKnowledgeDoc({ fileName, base64 }), }); } catch (error) { return fail(500, error instanceof Error ? error.message : String(error)); } } if (method === 'DELETE' && (pathname === '/api/knowledge/docs' || pathname.startsWith('/api/knowledge/docs/'))) { try { const fileName = pathname.startsWith('/api/knowledge/docs/') ? decodeURIComponent(pathname.slice('/api/knowledge/docs/'.length)) : getDeleteTarget(request); if (!fileName) { return fail(400, 'fileName is required'); } if (!isSafeKnowledgeDocName(fileName)) { return fail(400, 'Invalid file name'); } await deleteKnowledgeDoc(fileName); return ok({ success: true }); } catch (error) { return fail(500, error instanceof Error ? error.message : String(error)); } } return null; }