import { optionsResponse, notFoundResponse } from '../utils/cors' import { handleHistory } from './history' import { handleConfig, handleHealth } from './config' import { handleWebMCPToken, handleWebMCPRequestToken } from './webmcp' import { handleComponents, handleComponentById, handleComponentUsage } from './components' import { handleThemes, handleActiveTheme, handleDesignTokens, handleThemeById, handleThemeExport } from './themes' import { handleCanvas, handleCanvasById, handleToolbarCanvas, handleDefaultCanvas, handleCanvasComponents, handleCanvasComponentById } from './canvas' import { handleGiteaRepo, handleGiteaTree, handleGiteaFile } from './gitea' import { handleTables, handleStats, handleTableSchema, handleTableData, handleQuery } from './database' import { handleWhisperRoutes } from './whisper' import { handleRecordingsRoutes } from './recordings' import { handleClaudeStatus } from './claude-status' import { handleClaudeHook } from './claude-hook' import { handleClaudePermission, handleClaudePermissionRespond, handleClaudePermissionList } from './claude-permission' import { handleSnapshots, handleSnapshotById } from './snapshots' import { handleGitStatus, handleGitDiff, handleGitLog, handleGitLogCommit, handleGitCompare, handleGitBranches, handleGitCurrentBranch, handleGitTree, handleGitFile } from './git' import { handleAgents, handleAgentsFile, handleAgentsConfig, handleAgentsKnownTools, handleAgentsSkills, handleAgentsPlugins, handleAgentsMcpJson, handleAgentsConfigPermissions, handleAgentsConfigHooks, handleAgentsConfigMcp } from './agents' export async function handleRequest(req: Request): Promise { const url = new URL(req.url) const path = url.pathname // CORS preflight if (req.method === 'OPTIONS') { return optionsResponse() } // Health if (path === '/api/health') { return handleHealth() } // History if (path === '/api/history') { const res = await handleHistory(req, url) if (res) return res } // Config if (path === '/api/config') { const res = await handleConfig(req, url) if (res) return res } // WebMCP Token (for polling - legacy) if (path === '/api/webmcp-token') { const res = await handleWebMCPToken(req) if (res) return res } // WebMCP Request Token (direct request to WebMCP server) if (path === '/api/webmcp-request-token') { const res = await handleWebMCPRequestToken(req) if (res) return res } // Claude Code status (thinking/idle) if (path === '/api/claude-status') { const res = await handleClaudeStatus(req) if (res) return res } // Claude Code hook (rich stdin data forwarding) if (path === '/api/claude-hook') { const res = await handleClaudeHook(req) if (res) return res } // Claude Code permission request/respond if (path === '/api/claude-permission') { if (req.method === 'GET') { const res = await handleClaudePermissionList(req) if (res) return res } else { const res = await handleClaudePermission(req) if (res) return res } } if (path === '/api/claude-permission-respond') { const res = await handleClaudePermissionRespond(req) if (res) return res } // Components if (path === '/api/components') { const res = await handleComponents(req) if (res) return res } // Component usage const componentUsageMatch = path.match(/^\/api\/components\/([^/]+)\/usage$/) if (componentUsageMatch && req.method === 'GET') { return handleComponentUsage(componentUsageMatch[1]) } // Component by ID if (path.startsWith('/api/components/') && !path.includes('/usage')) { const id = path.split('/').pop()! const res = await handleComponentById(req, id) if (res) return res } // Themes if (path === '/api/themes') { const res = await handleThemes(req) if (res) return res } if (path === '/api/themes/active') { return handleActiveTheme() } if (path === '/api/design-tokens') { return handleDesignTokens() } // Theme export if (path.startsWith('/api/themes/export/')) { const id = path.split('/').pop()! if (req.method === 'GET') { return handleThemeExport(id) } } // Theme by ID if (path.startsWith('/api/themes/') && !path.includes('/active') && !path.includes('/export')) { const pathParts = path.split('/') const id = pathParts[3] const action = pathParts[4] const res = await handleThemeById(req, id, action) if (res) return res } // Canvas toolbar if (path === '/api/canvas/toolbar') { return handleToolbarCanvas() } // Canvas default if (path === '/api/canvas/default') { return handleDefaultCanvas() } // Canvas list/create if (path === '/api/canvas') { const res = await handleCanvas(req) if (res) return res } // Canvas components const canvasComponentsMatch = path.match(/^\/api\/canvas\/([^/]+)\/components\/?$/) if (canvasComponentsMatch) { const res = await handleCanvasComponents(req, canvasComponentsMatch[1]) if (res) return res } // Canvas component by ID const canvasComponentMatch = path.match(/^\/api\/canvas\/([^/]+)\/components\/([^/]+)$/) if (canvasComponentMatch) { const res = await handleCanvasComponentById(req, canvasComponentMatch[1], canvasComponentMatch[2]) if (res) return res } // Canvas by ID if (path.startsWith('/api/canvas/') && !path.includes('/components')) { const pathParts = path.split('/') const id = pathParts[3] const action = pathParts[4] const res = await handleCanvasById(req, id, action) if (res) return res } // Snapshots if (path === '/api/snapshots') { const res = await handleSnapshots(req) if (res) return res } if (path.startsWith('/api/snapshots/')) { const id = path.split('/').pop()! const res = await handleSnapshotById(req, id) if (res) return res } // Gitea if (path === '/api/gitea/repo' && req.method === 'POST') { return handleGiteaRepo(req) } if (path === '/api/gitea/tree' && req.method === 'POST') { return handleGiteaTree(req) } if (path === '/api/gitea/file' && req.method === 'POST') { return handleGiteaFile(req) } // Database Explorer if (path === '/api/database/tables') { return handleTables() } if (path === '/api/database/stats') { return handleStats() } // Table schema const tableSchemaMatch = path.match(/^\/api\/database\/tables\/([^/]+)\/schema$/) if (tableSchemaMatch && req.method === 'GET') { return handleTableSchema(decodeURIComponent(tableSchemaMatch[1])) } // Table data const tableDataMatch = path.match(/^\/api\/database\/tables\/([^/]+)\/data$/) if (tableDataMatch && req.method === 'GET') { return handleTableData(decodeURIComponent(tableDataMatch[1]), url) } // Database query if (path === '/api/database/query' && req.method === 'POST') { return handleQuery(req) } // Whisper (GPU speech-to-text) if (path.startsWith('/api/whisper/')) { const res = await handleWhisperRoutes(req) if (res) return res } // Voice recordings (for training custom models) if (path.startsWith('/api/recordings')) { const res = await handleRecordingsRoutes(req) if (res) return res } // Git if (path === '/api/git/status' && req.method === 'GET') { return handleGitStatus() } if (path === '/api/git/diff' && req.method === 'GET') { return handleGitDiff(url) } if (path === '/api/git/log' && req.method === 'GET') { return handleGitLog(url) } const gitLogCommitMatch = path.match(/^\/api\/git\/log\/([a-f0-9]+)$/) if (gitLogCommitMatch && req.method === 'GET') { return handleGitLogCommit(gitLogCommitMatch[1]) } if (path === '/api/git/compare' && req.method === 'POST') { return handleGitCompare(req) } if (path === '/api/git/branches' && req.method === 'GET') { return handleGitBranches() } if (path === '/api/git/branch/current' && req.method === 'GET') { return handleGitCurrentBranch() } if (path === '/api/git/tree' && req.method === 'GET') { return handleGitTree(url) } if (path === '/api/git/file' && req.method === 'GET') { return handleGitFile(url) } // Agents if (path === '/api/agents' && req.method === 'GET') { return handleAgents(req) } if (path === '/api/agents/config' && req.method === 'GET') { const res = await handleAgentsConfig(req, url) if (res) return res } if (path === '/api/agents/known-tools' && req.method === 'GET') { const res = await handleAgentsKnownTools(req) if (res) return res } if (path === '/api/agents/skills' && req.method === 'GET') { const res = await handleAgentsSkills(req, url) if (res) return res } if (path === '/api/agents/plugins' && req.method === 'GET') { const res = await handleAgentsPlugins(req) if (res) return res } if (path === '/api/agents/mcp-json' && req.method === 'GET') { const res = await handleAgentsMcpJson(req) if (res) return res } if (path === '/api/agents/config/permissions' && req.method === 'POST') { const res = await handleAgentsConfigPermissions(req) if (res) return res } if (path === '/api/agents/config/hooks' && req.method === 'POST') { const res = await handleAgentsConfigHooks(req) if (res) return res } if (path === '/api/agents/config/mcp' && req.method === 'POST') { const res = await handleAgentsConfigMcp(req) if (res) return res } if (path === '/api/agents/file') { const res = await handleAgentsFile(req, url) if (res) return res } return notFoundResponse() }