import { existsSync } from "node:fs";import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";import { createServer as createNodeServer, type IncomingMessage, type ServerResponse,} from "node:http";import type { AddressInfo } from "node:net";import { dirname, extname, resolve } from "node:path";import { Readable } from "node:stream";import { HttpApiBuilder, HttpServer } from "@effect/platform";import { createControlPlaneApiLayer, createControlPlaneRuntime, type ResolveExecutionEnvironment, type ResolveSecretMaterial, type ControlPlaneRuntime,} from "@executor/control-plane";import { createExecutorMcpRequestHandler } from "@executor/executor-mcp";import * as Cause from "effect/Cause";import * as Effect from "effect/Effect";import * as Exit from "effect/Exit";import * as Layer from "effect/Layer";import type * as Scope from "effect/Scope"; import { DEFAULT_LEGACY_LOCAL_DATA_DIRS, DEFAULT_LOCAL_DATA_DIR, DEFAULT_SERVER_LOG_FILE, DEFAULT_SERVER_PID_FILE, DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT, EXECUTOR_TRACE_ENABLED_ENV, EXECUTOR_TRACE_OTLP_ENDPOINT_ENV, EXECUTOR_TRACE_OTLP_HTTP_ENDPOINT_ENV, EXECUTOR_TRACE_QUERY_BASE_URL_ENV, EXECUTOR_TRACE_SERVICE_NAME_ENV,} from "./config";import { createLocalTracingRuntimeFromEnv, tracingSearchUrl,} from "./tracing"; export { DEFAULT_EXECUTOR_DATA_DIR, DEFAULT_EXECUTOR_HOME, DEFAULT_LOCAL_DATA_DIR, DEFAULT_SERVER_BASE_URL, DEFAULT_SERVER_LOG_FILE, DEFAULT_SERVER_HOST, DEFAULT_SERVER_PID_FILE, DEFAULT_SERVER_PORT, EXECUTOR_DATA_DIR_ENV, EXECUTOR_HOME_ENV, EXECUTOR_LOCAL_DATA_DIR_ENV, EXECUTOR_SERVER_PID_FILE_ENV, EXECUTOR_SERVER_LOG_FILE_ENV, EXECUTOR_WEB_ASSETS_DIR_ENV, EXECUTOR_TRACE_ENABLED_ENV, EXECUTOR_TRACE_OTLP_ENDPOINT_ENV, EXECUTOR_TRACE_OTLP_HTTP_ENDPOINT_ENV, EXECUTOR_TRACE_QUERY_BASE_URL_ENV, EXECUTOR_TRACE_SERVICE_NAME_ENV, SERVER_POLL_INTERVAL_MS, SERVER_START_TIMEOUT_MS,} from "./config"; type StaticUiOptions = { readonly assetsDir?: string; readonly devServerUrl?: string;}; export type LocalExecutorServer = { readonly runtime: ControlPlaneRuntime; readonly port: number; readonly host: string; readonly baseUrl: string;}; export type StartLocalExecutorServerOptions = { readonly port?: number; readonly host?: string; readonly localDataDir?: string; readonly workspaceRoot?: string; readonly pidFile?: string; readonly executionResolver?: ResolveExecutionEnvironment; readonly resolveSecretMaterial?: ResolveSecretMaterial; readonly ui?: StaticUiOptions;}; export type LocalExecutorRequestHandler = { readonly runtime: ControlPlaneRuntime; readonly handleApiRequest: (request: Request) => Promise<Response>; readonly getBaseUrl: () => string | undefined; readonly setBaseUrl: (baseUrl: string) => void;}; type ControlPlaneWebHandler = ReturnType<typeof HttpApiBuilder.toWebHandler>;type ExecutorMcpHandler = ReturnType<typeof createExecutorMcpRequestHandler>; const disposeRuntime = (runtime: ControlPlaneRuntime) => Effect.tryPromise({ try: () => runtime.close(), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause ?? "runtime close failed")), }).pipe(Effect.orDie); const createRuntime = ( localDataDir: string, getLocalServerBaseUrl: () => string | undefined, options: StartLocalExecutorServerOptions,) => createControlPlaneRuntime({ workspaceRoot: options.workspaceRoot, executionResolver: options.executionResolver, resolveSecretMaterial: options.resolveSecretMaterial, getLocalServerBaseUrl, localDataDir, }).pipe( Effect.mapError((cause) => cause instanceof Error ? cause : new Error(String(cause)), ), ); const moveLegacyLocalDataDir = ( legacyLocalDataDir: string, requestedLocalDataDir: string, ) => Effect.tryPromise({ try: async () => { await mkdir(dirname(requestedLocalDataDir), { recursive: true }); if (existsSync(requestedLocalDataDir)) { const backupPath = `${requestedLocalDataDir}.backup-${Date.now()}`; await rename(requestedLocalDataDir, backupPath); console.warn( `[executor] Backed up unreadable local data dir to: ${backupPath}`, ); } await rename(legacyLocalDataDir, requestedLocalDataDir); console.warn( `[executor] Moved legacy local data dir to: ${requestedLocalDataDir}`, ); }, catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)), }); const createRuntimeWithLegacyMigration = ( requestedLocalDataDir: string, legacyLocalDataDirs: ReadonlyArray<string>, getLocalServerBaseUrl: () => string | undefined, options: StartLocalExecutorServerOptions, ) => Effect.gen(function* () { if ( requestedLocalDataDir !== ":memory:" && !existsSync(requestedLocalDataDir) && legacyLocalDataDirs.length > 0 ) { for (const legacyLocalDataDir of legacyLocalDataDirs) { const legacyExit = yield* Effect.exit( createRuntime(legacyLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isFailure(legacyExit)) { continue; } yield* disposeRuntime(legacyExit.value); const migrationExit = yield* Effect.exit( moveLegacyLocalDataDir(legacyLocalDataDir, requestedLocalDataDir), ); if (Exit.isFailure(migrationExit)) { continue; } const migratedExit = yield* Effect.exit( createRuntime(requestedLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isSuccess(migratedExit)) { return migratedExit.value; } } } const primaryExit = yield* Effect.exit( createRuntime(requestedLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isSuccess(primaryExit)) { return primaryExit.value; } const primaryError = Cause.squash(primaryExit.cause); if (legacyLocalDataDirs.length > 0) { yield* Effect.sync(() => { console.warn( `[executor] Failed to open default local data dir: ${requestedLocalDataDir}`, primaryError instanceof Error ? primaryError.message : String(primaryError), ); }); } for (const legacyLocalDataDir of legacyLocalDataDirs) { const legacyExit = yield* Effect.exit( createRuntime(legacyLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isFailure(legacyExit)) { continue; } yield* disposeRuntime(legacyExit.value); const migrationExit = yield* Effect.exit( moveLegacyLocalDataDir(legacyLocalDataDir, requestedLocalDataDir), ); if (Exit.isFailure(migrationExit)) { continue; } const migratedExit = yield* Effect.exit( createRuntime(requestedLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isSuccess(migratedExit)) { return migratedExit.value; } } return yield* Effect.fail( primaryError instanceof Error ? primaryError : new Error(String(primaryError)), ); }); const createControlPlaneWebHandler = ( runtime: ControlPlaneRuntime, tracingRuntime: ReturnType<typeof createLocalTracingRuntimeFromEnv>,) => Effect.acquireRelease( Effect.sync(() => HttpApiBuilder.toWebHandler( Layer.merge( HttpApiBuilder.middlewareOpenApi({ path: "/v1/openapi.json" }).pipe( Layer.provideMerge( createControlPlaneApiLayer(runtime.runtimeLayer).pipe( Layer.provideMerge(tracingRuntime?.layer ?? Layer.empty), ), ) ), HttpServer.layerContext, ), ), ), (handler: ControlPlaneWebHandler) => Effect.tryPromise({ try: () => handler.dispose(), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause ?? "web handler dispose failed")) }).pipe(Effect.orDie), ); const safeFilePath = (assetsDir: string, pathname: string): string | null => { const target = resolve(assetsDir, `.${pathname}`); const root = resolve(assetsDir); return target.startsWith(root) ? target : null;}; const isRegularFile = async (path: string): Promise<boolean> => { try { return (await stat(path)).isFile(); } catch { return false; }}; const contentTypeByExtension: Record<string, string> = { ".css": "text/css; charset=utf-8", ".gif": "image/gif", ".html": "text/html; charset=utf-8", ".ico": "image/x-icon", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".js": "text/javascript; charset=utf-8", ".json": "application/json; charset=utf-8", ".map": "application/json; charset=utf-8", ".mjs": "text/javascript; charset=utf-8", ".png": "image/png", ".svg": "image/svg+xml", ".txt": "text/plain; charset=utf-8", ".wasm": "application/wasm", ".woff": "font/woff", ".woff2": "font/woff2",}; const contentTypeForPath = (path: string): string => contentTypeByExtension[extname(path).toLowerCase()] ?? "application/octet-stream"; const readResponseFile = async ( path: string, contentType?: string,): Promise<Response> => { const body = await readFile(path); return new Response(body, { headers: { "content-type": contentType ?? contentTypeForPath(path), }, });}; const toWebRequest = (nodeRequest: IncomingMessage): Request => { const host = nodeRequest.headers.host ?? "127.0.0.1"; const url = `http://${host}${nodeRequest.url ?? "/"}`; const headers = new Headers(); for (const [key, value] of Object.entries(nodeRequest.headers)) { if (value === undefined) { continue; } if (Array.isArray(value)) { for (const item of value) { headers.append(key, item); } continue; } headers.set(key, value); } const method = nodeRequest.method ?? "GET"; const requestInit: RequestInit & { duplex?: "half" } = { method, headers, }; if (method !== "GET" && method !== "HEAD") { requestInit.body = Readable.toWeb(nodeRequest) as unknown as BodyInit; requestInit.duplex = "half"; } return new Request(url, requestInit);}; const writeNodeResponse = async ( nodeResponse: ServerResponse, webResponse: Response,): Promise<void> => { nodeResponse.statusCode = webResponse.status; webResponse.headers.forEach((value, key) => { nodeResponse.setHeader(key, value); }); if (!webResponse.body) { nodeResponse.end(); return; } const reader = webResponse.body.getReader(); while (true) { const { done, value } = await reader.read(); if (done) { break; } nodeResponse.write(Buffer.from(value)); } nodeResponse.end();}; const wantsHtml = (request: Request): boolean => request.headers.get("accept")?.includes("text/html") ?? false; const serveUiAsset = async (request: Request, ui: StaticUiOptions): Promise<Response | null> => { const url = new URL(request.url); if (ui.devServerUrl) { const proxyUrl = new URL(`${url.pathname}${url.search}`, ui.devServerUrl); return fetch(new Request(proxyUrl.toString(), request)); } if (!ui.assetsDir) { return null; } const candidatePath = safeFilePath(ui.assetsDir, url.pathname); if (candidatePath && await isRegularFile(candidatePath)) { return readResponseFile(candidatePath); } const shouldServeIndex = url.pathname === "/" || extname(url.pathname).length === 0 || wantsHtml(request); if (!shouldServeIndex) { return null; } const indexPath = resolve(ui.assetsDir, "index.html"); if (!(await isRegularFile(indexPath))) { return null; } return readResponseFile(indexPath, "text/html; charset=utf-8");}; const isApiRequest = (request: Request): boolean => { const pathname = new URL(request.url).pathname; return pathname === "/mcp" || pathname === "/v1" || pathname.startsWith("/v1/");}; export const createLocalExecutorRequestHandler = ( options: StartLocalExecutorServerOptions = {},): Effect.Effect<LocalExecutorRequestHandler, Error, Scope.Scope> => Effect.gen(function* () { const requestedLocalDataDir = options.localDataDir ?? DEFAULT_LOCAL_DATA_DIR; const legacyLocalDataDirs = options.localDataDir === undefined ? DEFAULT_LEGACY_LOCAL_DATA_DIRS.filter((candidate) => existsSync(candidate)) : []; if (requestedLocalDataDir !== ":memory:") { yield* Effect.tryPromise({ try: () => mkdir(dirname(requestedLocalDataDir), { recursive: true }), catch: (cause) => (cause instanceof Error ? cause : new Error(String(cause))), }); } let baseUrlRef: string | undefined; const tracingRuntime = createLocalTracingRuntimeFromEnv(); if (tracingRuntime) { yield* Effect.sync(() => { console.info( `[executor] tracing enabled -> ${tracingSearchUrl({ queryBaseUrl: tracingRuntime.queryBaseUrl, serviceName: tracingRuntime.serviceName, })}`, ); }); } const runtime = yield* Effect.acquireRelease( createRuntimeWithLegacyMigration( requestedLocalDataDir, legacyLocalDataDirs, () => baseUrlRef, options, ), disposeRuntime, ); const apiHandler = yield* createControlPlaneWebHandler(runtime, tracingRuntime); const mcpHandler = yield* Effect.acquireRelease( Effect.sync(() => createExecutorMcpRequestHandler(runtime)), (handler: ExecutorMcpHandler) => Effect.tryPromise({ try: () => handler.close(), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause ?? "mcp handler close failed")), }).pipe(Effect.orDie), ); return { runtime, handleApiRequest: (request) => { const pathname = new URL(request.url).pathname; return pathname === "/mcp" ? mcpHandler.handleRequest(request) : apiHandler.handler(request); }, getBaseUrl: () => baseUrlRef, setBaseUrl: (baseUrl) => { baseUrlRef = baseUrl; }, } satisfies LocalExecutorRequestHandler; }); export const createLocalExecutorServer = ( options: StartLocalExecutorServerOptions = {},): Effect.Effect<LocalExecutorServer, Error, Scope.Scope> => Effect.gen(function* () { const host = options.host ?? DEFAULT_SERVER_HOST; const port = options.port ?? DEFAULT_SERVER_PORT; const requestHandler = yield* createLocalExecutorRequestHandler(options); const server = yield* Effect.acquireRelease( Effect.tryPromise({ try: () => new Promise<ReturnType<typeof createNodeServer>>((resolveServer, reject) => { const server = createNodeServer((nodeRequest, nodeResponse) => { void (async () => { const request = toWebRequest(nodeRequest); const response = isApiRequest(request) ? await requestHandler.handleApiRequest(request) : await serveUiAsset(request, options.ui ?? {}) ?? new Response("Not Found", { status: 404 }); await writeNodeResponse(nodeResponse, response); })().catch((cause) => { nodeResponse.statusCode = 500; nodeResponse.end(cause instanceof Error ? cause.message : String(cause)); }); }); server.once("error", reject); server.listen(port, host, () => { server.off("error", reject); resolveServer(server); }); }), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)), }), (server) => Effect.tryPromise({ try: () =>Lines 1–500 of 575. Load more
import { existsSync } from "node:fs"; import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises"; import { createServer as createNodeServer, type IncomingMessage, type ServerResponse, } from "node:http"; import type { AddressInfo } from "node:net"; import { dirname, extname, resolve } from "node:path"; import { Readable } from "node:stream"; import { HttpApiBuilder, HttpServer } from "@effect/platform"; import { createControlPlaneApiLayer, createControlPlaneRuntime, type ResolveExecutionEnvironment, type ResolveSecretMaterial, type ControlPlaneRuntime, } from "@executor/control-plane"; import { createExecutorMcpRequestHandler } from "@executor/executor-mcp"; import * as Cause from "effect/Cause"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; import * as Layer from "effect/Layer"; import type * as Scope from "effect/Scope"; import { DEFAULT_LEGACY_LOCAL_DATA_DIRS, DEFAULT_LOCAL_DATA_DIR, DEFAULT_SERVER_LOG_FILE, DEFAULT_SERVER_PID_FILE, DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT, EXECUTOR_TRACE_ENABLED_ENV, EXECUTOR_TRACE_OTLP_ENDPOINT_ENV, EXECUTOR_TRACE_OTLP_HTTP_ENDPOINT_ENV, EXECUTOR_TRACE_QUERY_BASE_URL_ENV, EXECUTOR_TRACE_SERVICE_NAME_ENV, } from "./config"; import { createLocalTracingRuntimeFromEnv, tracingSearchUrl, } from "./tracing"; export { DEFAULT_EXECUTOR_DATA_DIR, DEFAULT_EXECUTOR_HOME, DEFAULT_LOCAL_DATA_DIR, DEFAULT_SERVER_BASE_URL, DEFAULT_SERVER_LOG_FILE, DEFAULT_SERVER_HOST, DEFAULT_SERVER_PID_FILE, DEFAULT_SERVER_PORT, EXECUTOR_DATA_DIR_ENV, EXECUTOR_HOME_ENV, EXECUTOR_LOCAL_DATA_DIR_ENV, EXECUTOR_SERVER_PID_FILE_ENV, EXECUTOR_SERVER_LOG_FILE_ENV, EXECUTOR_WEB_ASSETS_DIR_ENV, EXECUTOR_TRACE_ENABLED_ENV, EXECUTOR_TRACE_OTLP_ENDPOINT_ENV, EXECUTOR_TRACE_OTLP_HTTP_ENDPOINT_ENV, EXECUTOR_TRACE_QUERY_BASE_URL_ENV, EXECUTOR_TRACE_SERVICE_NAME_ENV, SERVER_POLL_INTERVAL_MS, SERVER_START_TIMEOUT_MS, } from "./config"; type StaticUiOptions = { readonly assetsDir?: string; readonly devServerUrl?: string; }; export type LocalExecutorServer = { readonly runtime: ControlPlaneRuntime; readonly port: number; readonly host: string; readonly baseUrl: string; }; export type StartLocalExecutorServerOptions = { readonly port?: number; readonly host?: string; readonly localDataDir?: string; readonly workspaceRoot?: string; readonly pidFile?: string; readonly executionResolver?: ResolveExecutionEnvironment; readonly resolveSecretMaterial?: ResolveSecretMaterial; readonly ui?: StaticUiOptions; }; export type LocalExecutorRequestHandler = { readonly runtime: ControlPlaneRuntime; readonly handleApiRequest: (request: Request) => Promise<Response>; readonly getBaseUrl: () => string | undefined; readonly setBaseUrl: (baseUrl: string) => void; }; type ControlPlaneWebHandler = ReturnType<typeof HttpApiBuilder.toWebHandler>; type ExecutorMcpHandler = ReturnType<typeof createExecutorMcpRequestHandler>; const disposeRuntime = (runtime: ControlPlaneRuntime) => Effect.tryPromise({ try: () => runtime.close(), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause ?? "runtime close failed")), }).pipe(Effect.orDie); const createRuntime = ( localDataDir: string, getLocalServerBaseUrl: () => string | undefined, options: StartLocalExecutorServerOptions, ) => createControlPlaneRuntime({ workspaceRoot: options.workspaceRoot, executionResolver: options.executionResolver, resolveSecretMaterial: options.resolveSecretMaterial, getLocalServerBaseUrl, localDataDir, }).pipe( Effect.mapError((cause) => cause instanceof Error ? cause : new Error(String(cause)), ), ); const moveLegacyLocalDataDir = ( legacyLocalDataDir: string, requestedLocalDataDir: string, ) => Effect.tryPromise({ try: async () => { await mkdir(dirname(requestedLocalDataDir), { recursive: true }); if (existsSync(requestedLocalDataDir)) { const backupPath = `${requestedLocalDataDir}.backup-${Date.now()}`; await rename(requestedLocalDataDir, backupPath); console.warn( `[executor] Backed up unreadable local data dir to: ${backupPath}`, ); } await rename(legacyLocalDataDir, requestedLocalDataDir); console.warn( `[executor] Moved legacy local data dir to: ${requestedLocalDataDir}`, ); }, catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)), }); const createRuntimeWithLegacyMigration = ( requestedLocalDataDir: string, legacyLocalDataDirs: ReadonlyArray<string>, getLocalServerBaseUrl: () => string | undefined, options: StartLocalExecutorServerOptions, ) => Effect.gen(function* () { if ( requestedLocalDataDir !== ":memory:" && !existsSync(requestedLocalDataDir) && legacyLocalDataDirs.length > 0 ) { for (const legacyLocalDataDir of legacyLocalDataDirs) { const legacyExit = yield* Effect.exit( createRuntime(legacyLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isFailure(legacyExit)) { continue; } yield* disposeRuntime(legacyExit.value); const migrationExit = yield* Effect.exit( moveLegacyLocalDataDir(legacyLocalDataDir, requestedLocalDataDir), ); if (Exit.isFailure(migrationExit)) { continue; } const migratedExit = yield* Effect.exit( createRuntime(requestedLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isSuccess(migratedExit)) { return migratedExit.value; } } } const primaryExit = yield* Effect.exit( createRuntime(requestedLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isSuccess(primaryExit)) { return primaryExit.value; } const primaryError = Cause.squash(primaryExit.cause); if (legacyLocalDataDirs.length > 0) { yield* Effect.sync(() => { console.warn( `[executor] Failed to open default local data dir: ${requestedLocalDataDir}`, primaryError instanceof Error ? primaryError.message : String(primaryError), ); }); } for (const legacyLocalDataDir of legacyLocalDataDirs) { const legacyExit = yield* Effect.exit( createRuntime(legacyLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isFailure(legacyExit)) { continue; } yield* disposeRuntime(legacyExit.value); const migrationExit = yield* Effect.exit( moveLegacyLocalDataDir(legacyLocalDataDir, requestedLocalDataDir), ); if (Exit.isFailure(migrationExit)) { continue; } const migratedExit = yield* Effect.exit( createRuntime(requestedLocalDataDir, getLocalServerBaseUrl, options), ); if (Exit.isSuccess(migratedExit)) { return migratedExit.value; } } return yield* Effect.fail( primaryError instanceof Error ? primaryError : new Error(String(primaryError)), ); }); const createControlPlaneWebHandler = ( runtime: ControlPlaneRuntime, tracingRuntime: ReturnType<typeof createLocalTracingRuntimeFromEnv>, ) => Effect.acquireRelease( Effect.sync(() => HttpApiBuilder.toWebHandler( Layer.merge( HttpApiBuilder.middlewareOpenApi({ path: "/v1/openapi.json" }).pipe( Layer.provideMerge( createControlPlaneApiLayer(runtime.runtimeLayer).pipe( Layer.provideMerge(tracingRuntime?.layer ?? Layer.empty), ), ) ), HttpServer.layerContext, ), ), ), (handler: ControlPlaneWebHandler) => Effect.tryPromise({ try: () => handler.dispose(), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause ?? "web handler dispose failed")) }).pipe(Effect.orDie), ); const safeFilePath = (assetsDir: string, pathname: string): string | null => { const target = resolve(assetsDir, `.${pathname}`); const root = resolve(assetsDir); return target.startsWith(root) ? target : null; }; const isRegularFile = async (path: string): Promise<boolean> => { try { return (await stat(path)).isFile(); } catch { return false; } }; const contentTypeByExtension: Record<string, string> = { ".css": "text/css; charset=utf-8", ".gif": "image/gif", ".html": "text/html; charset=utf-8", ".ico": "image/x-icon", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".js": "text/javascript; charset=utf-8", ".json": "application/json; charset=utf-8", ".map": "application/json; charset=utf-8", ".mjs": "text/javascript; charset=utf-8", ".png": "image/png", ".svg": "image/svg+xml", ".txt": "text/plain; charset=utf-8", ".wasm": "application/wasm", ".woff": "font/woff", ".woff2": "font/woff2", }; const contentTypeForPath = (path: string): string => contentTypeByExtension[extname(path).toLowerCase()] ?? "application/octet-stream"; const readResponseFile = async ( path: string, contentType?: string, ): Promise<Response> => { const body = await readFile(path); return new Response(body, { headers: { "content-type": contentType ?? contentTypeForPath(path), }, }); }; const toWebRequest = (nodeRequest: IncomingMessage): Request => { const host = nodeRequest.headers.host ?? "127.0.0.1"; const url = `http://${host}${nodeRequest.url ?? "/"}`; const headers = new Headers(); for (const [key, value] of Object.entries(nodeRequest.headers)) { if (value === undefined) { continue; } if (Array.isArray(value)) { for (const item of value) { headers.append(key, item); } continue; } headers.set(key, value); } const method = nodeRequest.method ?? "GET"; const requestInit: RequestInit & { duplex?: "half" } = { method, headers, }; if (method !== "GET" && method !== "HEAD") { requestInit.body = Readable.toWeb(nodeRequest) as unknown as BodyInit; requestInit.duplex = "half"; } return new Request(url, requestInit); }; const writeNodeResponse = async ( nodeResponse: ServerResponse, webResponse: Response, ): Promise<void> => { nodeResponse.statusCode = webResponse.status; webResponse.headers.forEach((value, key) => { nodeResponse.setHeader(key, value); }); if (!webResponse.body) { nodeResponse.end(); return; } const reader = webResponse.body.getReader(); while (true) { const { done, value } = await reader.read(); if (done) { break; } nodeResponse.write(Buffer.from(value)); } nodeResponse.end(); }; const wantsHtml = (request: Request): boolean => request.headers.get("accept")?.includes("text/html") ?? false; const serveUiAsset = async (request: Request, ui: StaticUiOptions): Promise<Response | null> => { const url = new URL(request.url); if (ui.devServerUrl) { const proxyUrl = new URL(`${url.pathname}${url.search}`, ui.devServerUrl); return fetch(new Request(proxyUrl.toString(), request)); } if (!ui.assetsDir) { return null; } const candidatePath = safeFilePath(ui.assetsDir, url.pathname); if (candidatePath && await isRegularFile(candidatePath)) { return readResponseFile(candidatePath); } const shouldServeIndex = url.pathname === "/" || extname(url.pathname).length === 0 || wantsHtml(request); if (!shouldServeIndex) { return null; } const indexPath = resolve(ui.assetsDir, "index.html"); if (!(await isRegularFile(indexPath))) { return null; } return readResponseFile(indexPath, "text/html; charset=utf-8"); }; const isApiRequest = (request: Request): boolean => { const pathname = new URL(request.url).pathname; return pathname === "/mcp" || pathname === "/v1" || pathname.startsWith("/v1/"); }; export const createLocalExecutorRequestHandler = ( options: StartLocalExecutorServerOptions = {}, ): Effect.Effect<LocalExecutorRequestHandler, Error, Scope.Scope> => Effect.gen(function* () { const requestedLocalDataDir = options.localDataDir ?? DEFAULT_LOCAL_DATA_DIR; const legacyLocalDataDirs = options.localDataDir === undefined ? DEFAULT_LEGACY_LOCAL_DATA_DIRS.filter((candidate) => existsSync(candidate)) : []; if (requestedLocalDataDir !== ":memory:") { yield* Effect.tryPromise({ try: () => mkdir(dirname(requestedLocalDataDir), { recursive: true }), catch: (cause) => (cause instanceof Error ? cause : new Error(String(cause))), }); } let baseUrlRef: string | undefined; const tracingRuntime = createLocalTracingRuntimeFromEnv(); if (tracingRuntime) { yield* Effect.sync(() => { console.info( `[executor] tracing enabled -> ${tracingSearchUrl({ queryBaseUrl: tracingRuntime.queryBaseUrl, serviceName: tracingRuntime.serviceName, })}`, ); }); } const runtime = yield* Effect.acquireRelease( createRuntimeWithLegacyMigration( requestedLocalDataDir, legacyLocalDataDirs, () => baseUrlRef, options, ), disposeRuntime, ); const apiHandler = yield* createControlPlaneWebHandler(runtime, tracingRuntime); const mcpHandler = yield* Effect.acquireRelease( Effect.sync(() => createExecutorMcpRequestHandler(runtime)), (handler: ExecutorMcpHandler) => Effect.tryPromise({ try: () => handler.close(), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause ?? "mcp handler close failed")), }).pipe(Effect.orDie), ); return { runtime, handleApiRequest: (request) => { const pathname = new URL(request.url).pathname; return pathname === "/mcp" ? mcpHandler.handleRequest(request) : apiHandler.handler(request); }, getBaseUrl: () => baseUrlRef, setBaseUrl: (baseUrl) => { baseUrlRef = baseUrl; }, } satisfies LocalExecutorRequestHandler; }); export const createLocalExecutorServer = ( options: StartLocalExecutorServerOptions = {}, ): Effect.Effect<LocalExecutorServer, Error, Scope.Scope> => Effect.gen(function* () { const host = options.host ?? DEFAULT_SERVER_HOST; const port = options.port ?? DEFAULT_SERVER_PORT; const requestHandler = yield* createLocalExecutorRequestHandler(options); const server = yield* Effect.acquireRelease( Effect.tryPromise({ try: () => new Promise<ReturnType<typeof createNodeServer>>((resolveServer, reject) => { const server = createNodeServer((nodeRequest, nodeResponse) => { void (async () => { const request = toWebRequest(nodeRequest); const response = isApiRequest(request) ? await requestHandler.handleApiRequest(request) : await serveUiAsset(request, options.ui ?? {}) ?? new Response("Not Found", { status: 404 }); await writeNodeResponse(nodeResponse, response); })().catch((cause) => { nodeResponse.statusCode = 500; nodeResponse.end(cause instanceof Error ? cause.message : String(cause)); }); }); server.once("error", reject); server.listen(port, host, () => { server.off("error", reject); resolveServer(server); }); }), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)), }), (server) => Effect.tryPromise({ try: () =>