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 { handleFsComponents, handleFsComponentByName } from './fs-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' import { handleTranscript, handleTranscriptSessions, handleTranscriptActive, handleClaudeStats, handleClaudeUsage } from './transcript' import { handleTranscriptDebugSessions, handleTranscriptDebugRaw, handleTranscriptDebugSend, handleTranscriptDebugStatus } from './transcript-debug' import { handleHooksApprovalPermission, handleHooksApprovalPlan, handleHooksApprovalRespond, handleHooksApprovalRespondPlan, handleHooksApprovalIgnore, handleHooksApprovalList } from './hooks-approval' 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 } // Filesystem components if (path === '/api/fs-components') { const res = handleFsComponents(req) if (res) return res } if (path.startsWith('/api/fs-components/')) { const folderName = path.split('/').pop()! const res = handleFsComponentByName(req, folderName) 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) } // Claude usage limits (estimated) if (path === '/api/claude-usage') { return handleClaudeUsage() } // Claude stats (global) if (path === '/api/claude-stats') { return handleClaudeStats() } // Transcript if (path === '/api/transcript/active' && req.method === 'GET') { return handleTranscriptActive(req, url) } if (path === '/api/transcript/sessions' && req.method === 'GET') { return handleTranscriptSessions() } if (path === '/api/transcript/latest' && req.method === 'GET') { return handleTranscript(req, url, 'latest') } const transcriptMatch = path.match(/^\/api\/transcript\/([a-f0-9-]+)$/) if (transcriptMatch && req.method === 'GET') { return handleTranscript(req, url, transcriptMatch[1]) } // Transcript Debug if (path === '/api/transcript-debug/sessions' && req.method === 'GET') { return handleTranscriptDebugSessions(url) } if (path === '/api/transcript-debug/send' && req.method === 'POST') { return handleTranscriptDebugSend(req) } if (path === '/api/transcript-debug/status' && req.method === 'GET') { return handleTranscriptDebugStatus(url) } const transcriptDebugRawMatch = path.match(/^\/api\/transcript-debug\/([a-f0-9-]+)\/raw$/) if (transcriptDebugRawMatch && req.method === 'GET') { return handleTranscriptDebugRaw(transcriptDebugRawMatch[1], url) } // Hooks Approval (long-poll for permission/plan decisions) if (path === '/api/hooks-approval') { if (req.method === 'GET') { const res = await handleHooksApprovalList(req) if (res) return res } } if (path === '/api/hooks-approval/permission' && req.method === 'POST') { const res = await handleHooksApprovalPermission(req) if (res) return res } if (path === '/api/hooks-approval/plan' && req.method === 'POST') { const res = await handleHooksApprovalPlan(req) if (res) return res } if (path === '/api/hooks-approval/respond' && req.method === 'POST') { const res = await handleHooksApprovalRespond(req) if (res) return res } if (path === '/api/hooks-approval/respond-plan' && req.method === 'POST') { const res = await handleHooksApprovalRespondPlan(req) if (res) return res } if (path === '/api/hooks-approval/ignore' && req.method === 'POST') { const res = await handleHooksApprovalIgnore(req) if (res) return res } // 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() }