UNPKG

trellis

Version:

Agentic State Engine — event-sourced causal graph with branching, decision traces, and realtime sync for AI-native applications

148 lines (144 loc) 4.47 kB
import { loadVmConfig } from "./chunk-UZRUP7QW.js"; import { readConfig } from "./chunk-JA7AIHRK.js"; // src/mcp/gateway-config.ts import { existsSync, readFileSync, writeFileSync } from "fs"; import { join, resolve } from "path"; var GATEWAY_CONFIG_FILE = ".trellis-mcp-gateway.json"; function gatewayConfigPath(dir = ".") { return resolve(join(dir, GATEWAY_CONFIG_FILE)); } function readGatewayConfig(dir = ".") { const path = gatewayConfigPath(dir); if (!existsSync(path)) return null; try { return JSON.parse(readFileSync(path, "utf8")); } catch { throw new Error(`Failed to parse ${path}: invalid JSON`); } } function writeGatewayConfig(config, dir = ".") { writeFileSync( gatewayConfigPath(dir), JSON.stringify(config, null, 2) + "\n", "utf8" ); } // src/mcp/room-registry.ts import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs"; import { resolve as resolve2 } from "path"; function normalizeBaseUrl(url) { return url.replace(/\/$/, ""); } function roomMcpPathForUrl(baseUrl) { const env = process.env.TRELLIS_MCP_PATH?.trim(); if (env) return env.startsWith("/") ? env : `/${env}`; try { const host = new URL(baseUrl).hostname; if (/\.sprites\.app$/i.test(host)) return "/trellis/mcp"; } catch { } return "/mcp"; } function toMcpUrl(base) { const trimmed = normalizeBaseUrl(base); if (trimmed.endsWith("/mcp") || trimmed.endsWith("/trellis/mcp")) { return trimmed; } return `${trimmed}${roomMcpPathForUrl(trimmed)}`; } function parseRegistryJson(raw, source) { try { const data = JSON.parse(raw); const rooms = Array.isArray(data) ? data : data.rooms ?? []; return rooms.filter((r) => r.name && r.url).map((r) => ({ name: r.name, url: normalizeBaseUrl(r.url), mcpUrl: toMcpUrl(normalizeBaseUrl(r.url)), apiKey: r.apiKey, source, deployedAt: r.deployedAt, active: r.active })); } catch { return []; } } function listRegisteredRooms(opts = {}) { const configDir = opts.configDir ?? "."; const byUrl = /* @__PURE__ */ new Map(); const envRooms = process.env.TRELLIS_MCP_GATEWAY_ROOMS?.trim(); if (envRooms) { for (const room of parseRegistryJson(envRooms, "env")) { byUrl.set(room.url, room); } } const registryPath = process.env.TRELLIS_ROOM_REGISTRY?.trim() ?? resolve2(configDir, ".trellis-rooms.json"); if (existsSync2(registryPath)) { try { const raw = readFileSync2(registryPath, "utf8"); for (const room of parseRegistryJson(raw, "registry")) { byUrl.set(room.url, room); } } catch { } } const vm = loadVmConfig(); for (const [name, sprite] of Object.entries(vm.sprites)) { if (!sprite.hasTrellis && !sprite.apiKey) continue; const url = normalizeBaseUrl(sprite.url); byUrl.set(url, { name, url, mcpUrl: toMcpUrl(url), apiKey: sprite.apiKey, source: "vm", active: vm.activeSprite === name }); } const dbConfig = readConfig(configDir); if (dbConfig?.mode === "remote" && dbConfig.url) { const url = normalizeBaseUrl(dbConfig.url); const name = dbConfig.spriteName ?? url.replace(/^https?:\/\//, "").split(".")[0]; if (!byUrl.has(url)) { byUrl.set(url, { name, url, mcpUrl: toMcpUrl(url), apiKey: dbConfig.apiKey, source: "project", deployedAt: dbConfig.deployedAt, active: true }); } } return [...byUrl.values()].sort((a, b) => a.name.localeCompare(b.name)); } function getRegisteredRoom(nameOrUrl, opts) { const needle = nameOrUrl.trim().toLowerCase(); const rooms = listRegisteredRooms(opts); return rooms.find( (r) => r.name.toLowerCase() === needle || r.url.toLowerCase() === needle || r.mcpUrl.toLowerCase() === needle || normalizeBaseUrl(needle).endsWith(r.name.toLowerCase()) ) ?? null; } function gatewayPublicUrl(opts) { const fromConfig = readGatewayConfig(opts?.configDir ?? ".")?.publicUrl?.trim(); if (fromConfig) return fromConfig.replace(/\/$/, ""); if (opts?.gatewayPublicUrl?.trim()) { return opts.gatewayPublicUrl.trim().replace(/\/$/, ""); } const env = process.env.TRELLIS_MCP_GATEWAY_PUBLIC_URL?.trim(); if (env) return env.replace(/\/$/, ""); return "https://mcp.trellis.computer"; } export { gatewayConfigPath, writeGatewayConfig, roomMcpPathForUrl, listRegisteredRooms, getRegisteredRoom, gatewayPublicUrl };