import { createServer, } from "node:http"; import type { AddressInfo, } from "node:net"; import { FileSystem, } from "@effect/platform"; import { NodeFileSystem, } from "@effect/platform-node"; import { describe, expect, it, } from "@effect/vitest"; import * as Effect from "effect/Effect"; import { createLocalExecutorEffect, } from "@executor/platform-sdk-file/effect"; import { ExecutionIdSchema, } from "../../schema"; import { RuntimeExecutionResolverService, } from "../execution/scope/environment"; import { openApiSdkPlugin, } from "../../../../../../plugins/openapi/sdk"; import { localSecretStoreSdkPlugin, } from "../../../../../../plugins/local-secret-store/sdk"; const staticOpenApiDocument = JSON.stringify({ openapi: "3.1.0", info: { title: "Demo API", version: "1.0.0", }, servers: [ { url: "https://api.example.test", }, ], paths: { "/widgets": { get: { operationId: "listWidgets", responses: { "200": { description: "ok", }, }, }, }, }, }); const startStaticSpecServer = async () => { let lastAuthorizationHeader: string | null = null; const server = createServer((request, response) => { if (request.url === "/openapi.json") { response.writeHead(200, { "content-type": "application/json; charset=utf-8", }); response.end(staticOpenApiDocument); return; } if (request.url === "/widgets") { lastAuthorizationHeader = request.headers.authorization ?? null; response.writeHead(200, { "content-type": "application/json; charset=utf-8", }); response.end(JSON.stringify([{ id: "widget_1" }])); return; } { response.writeHead(404); response.end("Not Found"); } }); await new Promise((resolve, reject) => { server.once("error", reject); server.listen(0, "127.0.0.1", () => { server.off("error", reject); resolve(); }); }); const address = server.address(); if (!address || typeof address === "string") { server.close(); throw new Error("Failed to determine OpenAPI test server address."); } return { baseUrl: `http://127.0.0.1:${(address as AddressInfo).port}`, specUrl: `http://127.0.0.1:${(address as AddressInfo).port}/openapi.json`, lastAuthorizationHeader: () => lastAuthorizationHeader, close: () => new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }), }; }; const resolveExecutionEnvironment = (executor: { scopeId: string; actorScopeId: string; runtime: { runtimeLayer: any; }; }) => Effect.gen(function* () { const resolver = yield* RuntimeExecutionResolverService; return yield* resolver({ scopeId: executor.scopeId, actorScopeId: executor.actorScopeId, executionId: ExecutionIdSchema.make("exec_executor_tools_test"), }); }).pipe(Effect.provide(executor.runtime.runtimeLayer)); describe("executor internal tools", () => { it.scoped("registers plugin-owned executor.openapi tools and delegates generic remove through them", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const workspaceRoot = yield* fs.makeTempDirectory({ prefix: "executor-internal-tools-", }); const stored = new Map>(); const specServer = yield* Effect.acquireRelease( Effect.tryPromise({ try: () => startStaticSpecServer(), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)), }), (server) => Effect.promise(() => server.close()).pipe(Effect.orDie), ); const executor = yield* Effect.acquireRelease( createLocalExecutorEffect({ localDataDir: ":memory:", workspaceRoot, plugins: [ openApiSdkPlugin({ storage: { get: ({ sourceId }) => Effect.succeed((stored.get(sourceId) as any) ?? null), put: ({ sourceId, value }) => Effect.sync(() => { stored.set(sourceId, value as any); }), remove: ({ sourceId }) => Effect.sync(() => { stored.delete(sourceId); }), }, }), ] as const, }), (openedExecutor) => Effect.promise(() => openedExecutor.close()).pipe( Effect.orDie, Effect.zipRight( fs.remove(workspaceRoot, { recursive: true, force: true, }), ), ), ); const environment = yield* resolveExecutionEnvironment(executor); expect(environment.catalog).toBeDefined(); const createTool = yield* environment.catalog!.getToolByPath({ path: "executor.openapi.createSource", includeSchemas: false, }); const previewTool = yield* environment.catalog!.getToolByPath({ path: "executor.openapi.previewDocument", includeSchemas: false, }); expect(createTool?.path).toBe("executor.openapi.createSource"); expect(previewTool?.path).toBe("executor.openapi.previewDocument"); const preview = yield* environment.toolInvoker.invoke({ path: "executor.openapi.previewDocument", args: { specUrl: specServer.specUrl, }, }); expect(preview).toMatchObject({ title: "Demo API", operationCount: 1, }); const created = yield* environment.toolInvoker.invoke({ path: "executor.openapi.createSource", args: { name: "Demo API", specUrl: specServer.specUrl, baseUrl: null, auth: { kind: "none", }, }, }); expect((created as { kind: string }).kind).toBe("openapi"); expect(stored.has((created as { id: string }).id)).toBe(true); const removed = yield* environment.toolInvoker.invoke({ path: "executor.sources.remove", args: { sourceId: (created as { id: string }).id, }, }); expect(removed).toEqual({ removed: true, }); expect(stored.has((created as { id: string }).id)).toBe(false); }).pipe(Effect.provide(NodeFileSystem.layer)), ); it.scoped("invokes persisted OpenAPI source tools outside the runtime layer", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const workspaceRoot = yield* fs.makeTempDirectory({ prefix: "executor-openapi-source-tools-", }); const stored = new Map>(); const specServer = yield* Effect.acquireRelease( Effect.tryPromise({ try: () => startStaticSpecServer(), catch: (cause) => cause instanceof Error ? cause : new Error(String(cause)), }), (server) => Effect.promise(() => server.close()).pipe(Effect.orDie), ); const executor = yield* Effect.acquireRelease( createLocalExecutorEffect({ localDataDir: ":memory:", workspaceRoot, plugins: [ localSecretStoreSdkPlugin, openApiSdkPlugin({ storage: { get: ({ sourceId }) => Effect.succeed((stored.get(sourceId) as any) ?? null), put: ({ sourceId, value }) => Effect.sync(() => { stored.set(sourceId, value as any); }), remove: ({ sourceId }) => Effect.sync(() => { stored.delete(sourceId); }), }, }), ] as const, }), (openedExecutor) => Effect.promise(() => openedExecutor.close()).pipe( Effect.orDie, Effect.zipRight( fs.remove(workspaceRoot, { recursive: true, force: true, }), ), ), ); const tokenRef = yield* executor.secrets.create({ name: "OpenAPI Token", purpose: "auth_material", value: "token-from-secret-store", }).pipe(Effect.map((secret) => ({ secretId: secret.id }))); const environment = yield* resolveExecutionEnvironment(executor); const created = yield* environment.toolInvoker.invoke({ path: "executor.openapi.createSource", args: { name: "Demo API", specUrl: specServer.specUrl, baseUrl: specServer.baseUrl, auth: { kind: "bearer", tokenSecretRef: tokenRef, headerName: null, prefix: null, }, }, }); expect((created as { kind: string }).kind).toBe("openapi"); const response = yield* environment.toolInvoker.invoke({ path: "demo-api.widgets.listWidgets", args: {}, }); expect(response).toMatchObject({ data: [{ id: "widget_1" }], error: null, status: 200, }); expect(specServer.lastAuthorizationHeader()).toBe("Bearer token-from-secret-store"); const executed = yield* environment.executor.execute( 'return await tools["demo-api.widgets.listWidgets"]({ limit: 100 });', environment.toolInvoker, ); expect(executed).toMatchObject({ result: { data: [{ id: "widget_1" }], error: null, status: 200, }, }); }).pipe(Effect.provide(NodeFileSystem.layer)), ); });