import * as http from "node:http"; import { readExpectedToken, requireBearer } from "./auth.js"; import { readJsonBody } from "./httpUtil.js"; const HOST = process.env.ORCHESTRATOR_HOST ?? "127.0.0.1"; const PORT = Number(process.env.ORCHESTRATOR_PORT ?? "37145"); type RouteTarget = "ollama" | "anythingllm" | "service" | "ia_dev"; type Resolution = { resolved: boolean; target?: RouteTarget; action?: string; upstream?: { method: string; url: string; headersHint: string[] }; reason?: string; }; const ollamaBase = (): string => (process.env.OLLAMA_URL ?? "http://127.0.0.1:11434").replace(/\/+$/, ""); const anythingLlmBase = (): string => (process.env.ANYTHINGLLM_BASE_URL ?? "").replace(/\/+$/, ""); const reposDevtoolsUrl = (): string => (process.env.REPOS_DEVTOOLS_URL ?? "http://127.0.0.1:37140").replace(/\/+$/, ""); const regexSearchUrl = (): string => (process.env.REGEX_SEARCH_URL ?? "http://127.0.0.1:37143").replace(/\/+$/, ""); const langextractUrl = (): string => (process.env.LANGEXTRACT_URL ?? "http://127.0.0.1:37141").replace(/\/+$/, ""); const localOfficeUrl = (): string => (process.env.LOCAL_OFFICE_URL ?? "http://127.0.0.1:8000").replace(/\/+$/, ""); const iaDevGatewayUrl = (): string => (process.env.IA_DEV_GATEWAY_URL ?? "http://127.0.0.1:37144").replace(/\/+$/, ""); const toolsBridgeUrl = (): string => (process.env.TOOLS_BRIDGE_URL ?? "http://127.0.0.1:37147").replace(/\/+$/, ""); const resolveIntent = (intent: string): Resolution => { switch (intent) { case "code.complete": case "chat.local": return { resolved: true, target: "ollama", action: "generate", upstream: { method: "POST", url: `${ollamaBase()}/api/generate`, headersHint: ["Content-Type"] }, }; case "rag.query": return { resolved: true, target: "anythingllm", action: "workspace_chat", upstream: { method: "POST", url: anythingLlmBase() ? `${anythingLlmBase()}/api/v1/workspace/...` : "configure ANYTHINGLLM_BASE_URL", headersHint: ["Authorization", "Content-Type"], }, }; case "git.clone": return { resolved: true, target: "service", action: "repos_clone", upstream: { method: "POST", url: `${reposDevtoolsUrl()}/repos-clone`, headersHint: ["Authorization", "Content-Type"] }, }; case "search.regex": return { resolved: true, target: "service", action: "regex_search", upstream: { method: "POST", url: `${regexSearchUrl()}/search`, headersHint: ["Authorization", "Content-Type"] }, }; case "extract.entities": return { resolved: true, target: "service", action: "langextract", upstream: { method: "POST", url: `${langextractUrl()}/extract`, headersHint: ["Authorization", "Content-Type"] }, }; case "doc.office.upload": return { resolved: true, target: "service", action: "local_office_documents", upstream: { method: "POST", url: `${localOfficeUrl()}/documents`, headersHint: ["X-API-Key", "Content-Type"] }, }; case "agent.run": return { resolved: true, target: "ia_dev", action: "post_run", upstream: { method: "POST", url: `${iaDevGatewayUrl()}/v1/runs`, headersHint: ["Authorization", "Content-Type"] }, }; case "tools.registry": return { resolved: true, target: "service", action: "tools_bridge_registry", upstream: { method: "GET", url: `${toolsBridgeUrl()}/v1/registry`, headersHint: ["Authorization"], }, }; case "tools.carbonyl.plan": return { resolved: true, target: "service", action: "tools_carbonyl_open_plan", upstream: { method: "POST", url: `${toolsBridgeUrl()}/v1/carbonyl/open-plan`, headersHint: ["Authorization", "Content-Type"], }, }; case "tools.pageindex.run": return { resolved: true, target: "service", action: "tools_pageindex_run", upstream: { method: "POST", url: `${toolsBridgeUrl()}/v1/pageindex/run`, headersHint: ["Authorization", "Content-Type"], }, }; case "tools.chandra.ocr": return { resolved: true, target: "service", action: "tools_chandra_ocr", upstream: { method: "POST", url: `${toolsBridgeUrl()}/v1/chandra/ocr`, headersHint: ["Authorization", "Content-Type"], }, }; default: return { resolved: false, reason: `Unknown intent: ${intent}` }; } }; const json = (res: http.ServerResponse, status: number, body: unknown): void => { res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" }); res.end(JSON.stringify(body)); }; const isRecord = (v: unknown): v is Record => typeof v === "object" && v !== null && !Array.isArray(v); const timeline: { at: string; type: string; summary: string; runId?: string; projectId?: string }[] = []; const main = (): void => { const token = readExpectedToken(); if (token.length === 0) { console.error("smart-ide-orchestrator: set ORCHESTRATOR_TOKEN (non-empty secret)."); process.exit(1); } const server = http.createServer((req, res) => { void (async () => { try { const url = new URL(req.url ?? "/", `http://${HOST}`); const p = url.pathname; if (req.method === "GET" && (p === "/health" || p === "/health/")) { json(res, 200, { status: "ok" }); return; } if (req.method === "GET" && p === "/v1/timeline") { if (!requireBearer(req, res, token)) { return; } json(res, 200, { items: timeline.slice(-100) }); return; } if (req.method === "POST" && p === "/v1/route") { if (!requireBearer(req, res, token)) { return; } const body = await readJsonBody(req); if (!isRecord(body) || typeof body.intent !== "string") { json(res, 422, { error: "Missing intent (string)" }); return; } const dryRun = body.dryRun === true; const r = resolveIntent(body.intent); if (!r.resolved) { json(res, 200, { resolved: false, reason: r.reason }); return; } if (dryRun) { json(res, 200, { resolved: true, target: r.target, action: r.action, upstream: r.upstream, }); return; } json(res, 200, { resolved: true, target: r.target, action: r.action, upstream: r.upstream, note: "Use POST /v1/execute to forward (stub)", }); return; } if (req.method === "POST" && p === "/v1/execute") { if (!requireBearer(req, res, token)) { return; } const body = await readJsonBody(req); if (!isRecord(body) || typeof body.intent !== "string") { json(res, 422, { error: "Missing intent (string)" }); return; } const r = resolveIntent(body.intent); if (!r.resolved) { json(res, 422, { error: r.reason }); return; } timeline.push({ at: new Date().toISOString(), type: "execute", summary: `${body.intent} -> ${r.target}/${r.action}`, projectId: typeof body.projectId === "string" ? body.projectId : undefined, }); json(res, 200, { ok: true, forwarded: false, message: "Stub: call upstream yourself or extend orchestrator with fetch() and service tokens.", resolution: r, }); return; } json(res, 404, { error: "Not found" }); } catch (e) { const msg = e instanceof Error ? e.message : String(e); json(res, 400, { error: msg }); } })(); }); server.listen(PORT, HOST, () => { console.error(`smart-ide-orchestrator listening on http://${HOST}:${PORT}`); }); }; main();