import { createServer,} from "node:http";import { join,} from "node:path"; import { FileSystem, HttpApi, HttpApiEndpoint, HttpApiGroup, HttpApiSchema, HttpApiBuilder,} from "@effect/platform";import { NodeFileSystem,} from "@effect/platform-node";import { describe, expect, it,} from "@effect/vitest";import { assertTrue,} from "@effect/vitest/utils";import * as Either from "effect/Either";import * as Effect from "effect/Effect";import * as Fiber from "effect/Fiber";import * as Layer from "effect/Layer";import * as Option from "effect/Option";import * as Schema from "effect/Schema"; import { ExecutionIdSchema, ExecutionInteractionIdSchema, type ExecutionInteraction, ProviderAuthGrantIdSchema, SecretMaterialIdSchema, SourceAuthSessionIdSchema, SourceIdSchema, ScopeOauthClientIdSchema,} from "#schema";import type { ToolPath,} from "@executor/codemode-core";import { makeOpenApiTestServer,} from "@executor/effect-test-utils";import { createCatalogImportMetadata,} from "@executor/source-core";import { createGraphqlCatalogFragment,} from "@executor/source-graphql";import { createWorkspaceExecutorAdminToolMap,} from "../../../internal/src/index"; import { type ExecutorRuntime, type ExecutorStateStoreShape, LiveExecutionManagerService, provideExecutorRuntime, RuntimeExecutionResolverService,} from "./index";import { createSourceFromPayload,} from "./sources/source-definitions";import { decodeSourceCredentialSelectionContent,} from "./sources/source-credential-interactions";import { persistSource,} from "./sources/source-store";import { withExecutorApiClient, withExecutorApiRequestHandler,} from "./execution/test-http-client";import { runtimeEffectError,} from "./effect-errors";import { buildLocalSourceArtifact, deriveLocalInstallation, readLocalSourceArtifact, resolveLocalWorkspaceContext, writeLocalExecutorStateSnapshot, writeLocalSourceArtifact, writeProjectLocalExecutorConfig, writeLocalWorkspaceState,} from "../../../sdk-file/src/effect";import { createLocalExecutorRuntime as createExecutorRuntime,} from "../../../sdk-file/src/runtime";import { decodeSourceCredentialInteraction, submitSourceCredentialInteraction,} from "../local/operations"; const makeRuntime = Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const scopeRoot = yield* fs.makeTempDirectoryScoped({ prefix: "executor-runtime-", }); const homeConfigPath = join(scopeRoot, ".executor-home.jsonc"); const homeStateDirectory = join(scopeRoot, ".executor-home-state"); return yield* Effect.acquireRelease( createExecutorRuntime({ workspaceRoot: scopeRoot, homeConfigPath, homeStateDirectory, createInternalToolMap: createWorkspaceExecutorAdminToolMap, }), (runtime) => Effect.promise(() => runtime.close()).pipe(Effect.orDie), );}).pipe(Effect.provide(NodeFileSystem.layer)); const ownerParam = HttpApiSchema.param("owner", Schema.String);const repoParam = HttpApiSchema.param("repo", Schema.String); class RuntimeTestReposApi extends HttpApiGroup.make("repos") .add( HttpApiEndpoint.get("getRepo")`/repos/${ownerParam}/${repoParam}` .addSuccess(Schema.Unknown), ){} class RuntimeTestOpenApi extends HttpApi.make("runtimeTest").add( RuntimeTestReposApi,) {} type GoogleWorkspaceTestServer = { baseUrl: string; tokenEndpoint: string; discoveryUrl: (input: { service: string; version: string; scope: string; }) => string; queueTokenResponse: (response: { access_token: string; refresh_token?: string; expires_in?: number; scope?: string; }) => void; tokenRequests: URLSearchParams[]; discoveryAuthorizations: string[]; close: () => Promise<void>;}; const runtimeTestOpenApiLive = HttpApiBuilder.group( RuntimeTestOpenApi, "repos", (handlers) => handlers.handle("getRepo", ({ path }) => Effect.succeed({ full_name: `${path.owner}/${path.repo}`, private: false, }), ),); const runtimeTestOpenApiLayer = HttpApiBuilder.api(RuntimeTestOpenApi).pipe( Layer.provide(runtimeTestOpenApiLive),); const makeOpenApiSpecServer = makeOpenApiTestServer({ apiLayer: runtimeTestOpenApiLayer,}); const makeGoogleWorkspaceTestServer = Effect.acquireRelease( Effect.promise<GoogleWorkspaceTestServer>( () => new Promise<GoogleWorkspaceTestServer>((resolve, reject) => { const discoveryScopes = new Map<string, string>(); const tokenResponses: Array<{ access_token: string; refresh_token?: string; expires_in?: number; scope?: string; }> = []; const tokenRequests: URLSearchParams[] = []; const discoveryAuthorizations: string[] = []; let baseUrl = ""; const server = createServer(async (request, response) => { const requestUrl = new URL( request.url ?? "/", `http://${request.headers.host ?? "127.0.0.1"}`, ); if ( request.method === "POST" && requestUrl.pathname === "/oauth/token" ) { const chunks: Buffer[] = []; for await (const chunk of request) { chunks.push(Buffer.from(chunk)); } const params = new URLSearchParams( Buffer.concat(chunks).toString("utf8"), ); tokenRequests.push(params); const nextResponse = tokenResponses.shift(); if (!nextResponse) { response.statusCode = 500; response.setHeader("content-type", "application/json"); response.end( JSON.stringify({ error: "missing_token_response", }), ); return; } response.statusCode = 200; response.setHeader("content-type", "application/json"); response.end( JSON.stringify({ token_type: "Bearer", expires_in: 3600, ...nextResponse, }), ); return; } const discoveryMatch = /^\/([^/]+)\/\$discovery\/rest$/.exec( requestUrl.pathname, ); if (request.method === "GET" && discoveryMatch) { const service = discoveryMatch[1]!; const version = requestUrl.searchParams.get("version") ?? "v1"; const authorizationHeader = typeof request.headers.authorization === "string" ? request.headers.authorization : Array.isArray(request.headers.authorization) ? (request.headers.authorization[0] ?? "") : ""; if (authorizationHeader.length > 0) { discoveryAuthorizations.push(authorizationHeader); } const scope = discoveryScopes.get(`${service}:${version}`) ?? `https://example.test/auth/${service}`; response.statusCode = 200; response.setHeader("content-type", "application/json"); response.end( JSON.stringify({ name: service, version, title: `${service} API`, description: `Test ${service} API`, rootUrl: `${baseUrl}/`, servicePath: `${service}/${version}/`, auth: { oauth2: { scopes: { [scope]: { description: `${service} scope`, }, }, }, }, methods: { list: { id: `${service}.list`, path: "items", httpMethod: "GET", response: { $ref: "ListResponse", }, }, }, schemas: { ListResponse: { id: "ListResponse", type: "object", properties: { items: { type: "array", items: { type: "string", }, }, }, }, }, }), ); return; } response.statusCode = 404; response.end(); }); server.once("error", reject); server.listen(0, "127.0.0.1", () => { const address = server.address(); if (!address || typeof address === "string") { reject(new Error("Failed to bind Google workspace test server")); return; } baseUrl = `http://127.0.0.1:${address.port}`; resolve({ baseUrl, tokenEndpoint: `${baseUrl}/oauth/token`, discoveryUrl: ({ service, version, scope }) => { discoveryScopes.set(`${service}:${version}`, scope); return `${baseUrl}/${service}/$discovery/rest?version=${encodeURIComponent(version)}`; }, queueTokenResponse: (tokenResponse) => { tokenResponses.push(tokenResponse); }, tokenRequests, discoveryAuthorizations, close: () => new Promise<void>((closeResolve, closeReject) => { server.close((error) => { if (error) { closeReject(error); return; } closeResolve(); }); }), }); }); }), ), (server) => Effect.promise(() => server.close()).pipe(Effect.orDie),); const upsertLocalSecret = ( runtime: ExecutorRuntime, input: { id: string; name: string; purpose: "oauth_refresh_token" | "oauth_client_info" | "oauth_access_token"; value: string; },) => executorStateForRuntime(runtime).secretMaterials.upsert({ id: SecretMaterialIdSchema.make(input.id), providerId: "local", handle: input.id, name: input.name, purpose: input.purpose, value: input.value, createdAt: Date.now(), updatedAt: Date.now(), }); const executorStateForRuntime = ( runtime: ExecutorRuntime,): ExecutorStateStoreShape => ({ authArtifacts: runtime.storage.auth.artifacts, authLeases: runtime.storage.auth.leases, sourceOauthClients: runtime.storage.auth.sourceOauthClients, scopeOauthClients: runtime.storage.auth.scopeOauthClients, providerAuthGrants: runtime.storage.auth.providerGrants, sourceAuthSessions: runtime.storage.auth.sourceSessions, secretMaterials: runtime.storage.secrets, executions: runtime.storage.executions.runs, executionInteractions: runtime.storage.executions.interactions, executionSteps: runtime.storage.executions.steps,}); const createPersistedGoogleSource = (input: { runtime: ExecutorRuntime; name: string; namespace: string; service: string; version: string; discoveryUrl: string; scopes: ReadonlyArray<string>; auth: | { kind: "none"; } | { kind: "provider_grant_ref"; grantId: ReturnType<typeof ProviderAuthGrantIdSchema.make>; providerKey: string; requiredScopes: ReadonlyArray<string>; headerName: string; prefix: string; };}) => Effect.gen(function* () { const installation = input.runtime.localInstallation; const source = yield* createSourceFromPayload({ scopeId: installation.scopeId, sourceId: SourceIdSchema.make(`src_${crypto.randomUUID()}`), payload: { name: input.name, kind: "google_discovery", endpoint: input.discoveryUrl, namespace: input.namespace, binding: { service: input.service, version: input.version, discoveryUrl: input.discoveryUrl, scopes: [...input.scopes], }, importAuthPolicy: "reuse_runtime", importAuth: { kind: "none" }, auth: input.auth as any, status: "connected", enabled: true, }, now: Date.now(), }); return yield* persistSource(executorStateForRuntime(input.runtime), source, { actorScopeId: installation.actorScopeId, }).pipe((effect) => provideExecutorRuntime(effect, input.runtime)); }); const expectLeft = <A, E>(effect: Effect.Effect<A, E, never>) => Effect.either(effect).pipe( Effect.flatMap((result) => Either.isLeft(result) ? Effect.succeed(result.left) : Effect.fail( runtimeEffectError( "executor-runtime.test", "Expected effect to fail", ), ), ), ); const invokeWorkspaceTool = <A>(input: { runtime: ExecutorRuntime; path: ToolPath; args: unknown;}) => provideExecutorRuntime( Effect.gen(function* () { const installation = input.runtime.localInstallation; const resolveEnvironment = yield* RuntimeExecutionResolverService; const environment = yield* resolveEnvironment({ scopeId: installation.scopeId, actorScopeId: installation.actorScopeId, executionId: ExecutionIdSchema.make(`exec_tool_${crypto.randomUUID()}`), }); return (yield* environment.toolInvoker.invoke({ path: input.path, args: input.args, })) as A; }), input.runtime, ); describe("executor-runtime", () => { it.scoped( "writes local source changes through executor.jsonc", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const scopeRoot = yield* fs.makeTempDirectoryScoped({ prefix: "executor-local-config-runtime-", }); const homeConfigPath = join(scopeRoot, ".executor-home.jsonc"); const homeStateDirectory = join(scopeRoot, ".executor-home-state"); const runtime = yield* Effect.acquireRelease( createExecutorRuntime({ workspaceRoot: scopeRoot, homeConfigPath, homeStateDirectory, }), (createdRuntime) => Effect.promise(() => createdRuntime.close()).pipe(Effect.orDie), ); const openApiServer = yield* makeOpenApiSpecServer; const installation = runtime.localInstallation; const createdSource = yield* withExecutorApiClient( { runtime, actorScopeId: installation.actorScopeId }, (client) => client.sources.create({ path: { workspaceId: installation.scopeId }, payload: { name: "GitHub", kind: "openapi", endpoint: openApiServer.baseUrl, namespace: "github", binding: { specUrl: openApiServer.specUrl, defaultHeaders: null, },Lines 1–500 of 2390. Load more
import { createServer, } from "node:http"; import { join, } from "node:path"; import { FileSystem, HttpApi, HttpApiEndpoint, HttpApiGroup, HttpApiSchema, HttpApiBuilder, } from "@effect/platform"; import { NodeFileSystem, } from "@effect/platform-node"; import { describe, expect, it, } from "@effect/vitest"; import { assertTrue, } from "@effect/vitest/utils"; import * as Either from "effect/Either"; import * as Effect from "effect/Effect"; import * as Fiber from "effect/Fiber"; import * as Layer from "effect/Layer"; import * as Option from "effect/Option"; import * as Schema from "effect/Schema"; import { ExecutionIdSchema, ExecutionInteractionIdSchema, type ExecutionInteraction, ProviderAuthGrantIdSchema, SecretMaterialIdSchema, SourceAuthSessionIdSchema, SourceIdSchema, ScopeOauthClientIdSchema, } from "#schema"; import type { ToolPath, } from "@executor/codemode-core"; import { makeOpenApiTestServer, } from "@executor/effect-test-utils"; import { createCatalogImportMetadata, } from "@executor/source-core"; import { createGraphqlCatalogFragment, } from "@executor/source-graphql"; import { createWorkspaceExecutorAdminToolMap, } from "../../../internal/src/index"; import { type ExecutorRuntime, type ExecutorStateStoreShape, LiveExecutionManagerService, provideExecutorRuntime, RuntimeExecutionResolverService, } from "./index"; import { createSourceFromPayload, } from "./sources/source-definitions"; import { decodeSourceCredentialSelectionContent, } from "./sources/source-credential-interactions"; import { persistSource, } from "./sources/source-store"; import { withExecutorApiClient, withExecutorApiRequestHandler, } from "./execution/test-http-client"; import { runtimeEffectError, } from "./effect-errors"; import { buildLocalSourceArtifact, deriveLocalInstallation, readLocalSourceArtifact, resolveLocalWorkspaceContext, writeLocalExecutorStateSnapshot, writeLocalSourceArtifact, writeProjectLocalExecutorConfig, writeLocalWorkspaceState, } from "../../../sdk-file/src/effect"; import { createLocalExecutorRuntime as createExecutorRuntime, } from "../../../sdk-file/src/runtime"; import { decodeSourceCredentialInteraction, submitSourceCredentialInteraction, } from "../local/operations"; const makeRuntime = Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const scopeRoot = yield* fs.makeTempDirectoryScoped({ prefix: "executor-runtime-", }); const homeConfigPath = join(scopeRoot, ".executor-home.jsonc"); const homeStateDirectory = join(scopeRoot, ".executor-home-state"); return yield* Effect.acquireRelease( createExecutorRuntime({ workspaceRoot: scopeRoot, homeConfigPath, homeStateDirectory, createInternalToolMap: createWorkspaceExecutorAdminToolMap, }), (runtime) => Effect.promise(() => runtime.close()).pipe(Effect.orDie), ); }).pipe(Effect.provide(NodeFileSystem.layer)); const ownerParam = HttpApiSchema.param("owner", Schema.String); const repoParam = HttpApiSchema.param("repo", Schema.String); class RuntimeTestReposApi extends HttpApiGroup.make("repos") .add( HttpApiEndpoint.get("getRepo")`/repos/${ownerParam}/${repoParam}` .addSuccess(Schema.Unknown), ) {} class RuntimeTestOpenApi extends HttpApi.make("runtimeTest").add( RuntimeTestReposApi, ) {} type GoogleWorkspaceTestServer = { baseUrl: string; tokenEndpoint: string; discoveryUrl: (input: { service: string; version: string; scope: string; }) => string; queueTokenResponse: (response: { access_token: string; refresh_token?: string; expires_in?: number; scope?: string; }) => void; tokenRequests: URLSearchParams[]; discoveryAuthorizations: string[]; close: () => Promise<void>; }; const runtimeTestOpenApiLive = HttpApiBuilder.group( RuntimeTestOpenApi, "repos", (handlers) => handlers.handle("getRepo", ({ path }) => Effect.succeed({ full_name: `${path.owner}/${path.repo}`, private: false, }), ), ); const runtimeTestOpenApiLayer = HttpApiBuilder.api(RuntimeTestOpenApi).pipe( Layer.provide(runtimeTestOpenApiLive), ); const makeOpenApiSpecServer = makeOpenApiTestServer({ apiLayer: runtimeTestOpenApiLayer, }); const makeGoogleWorkspaceTestServer = Effect.acquireRelease( Effect.promise<GoogleWorkspaceTestServer>( () => new Promise<GoogleWorkspaceTestServer>((resolve, reject) => { const discoveryScopes = new Map<string, string>(); const tokenResponses: Array<{ access_token: string; refresh_token?: string; expires_in?: number; scope?: string; }> = []; const tokenRequests: URLSearchParams[] = []; const discoveryAuthorizations: string[] = []; let baseUrl = ""; const server = createServer(async (request, response) => { const requestUrl = new URL( request.url ?? "/", `http://${request.headers.host ?? "127.0.0.1"}`, ); if ( request.method === "POST" && requestUrl.pathname === "/oauth/token" ) { const chunks: Buffer[] = []; for await (const chunk of request) { chunks.push(Buffer.from(chunk)); } const params = new URLSearchParams( Buffer.concat(chunks).toString("utf8"), ); tokenRequests.push(params); const nextResponse = tokenResponses.shift(); if (!nextResponse) { response.statusCode = 500; response.setHeader("content-type", "application/json"); response.end( JSON.stringify({ error: "missing_token_response", }), ); return; } response.statusCode = 200; response.setHeader("content-type", "application/json"); response.end( JSON.stringify({ token_type: "Bearer", expires_in: 3600, ...nextResponse, }), ); return; } const discoveryMatch = /^\/([^/]+)\/\$discovery\/rest$/.exec( requestUrl.pathname, ); if (request.method === "GET" && discoveryMatch) { const service = discoveryMatch[1]!; const version = requestUrl.searchParams.get("version") ?? "v1"; const authorizationHeader = typeof request.headers.authorization === "string" ? request.headers.authorization : Array.isArray(request.headers.authorization) ? (request.headers.authorization[0] ?? "") : ""; if (authorizationHeader.length > 0) { discoveryAuthorizations.push(authorizationHeader); } const scope = discoveryScopes.get(`${service}:${version}`) ?? `https://example.test/auth/${service}`; response.statusCode = 200; response.setHeader("content-type", "application/json"); response.end( JSON.stringify({ name: service, version, title: `${service} API`, description: `Test ${service} API`, rootUrl: `${baseUrl}/`, servicePath: `${service}/${version}/`, auth: { oauth2: { scopes: { [scope]: { description: `${service} scope`, }, }, }, }, methods: { list: { id: `${service}.list`, path: "items", httpMethod: "GET", response: { $ref: "ListResponse", }, }, }, schemas: { ListResponse: { id: "ListResponse", type: "object", properties: { items: { type: "array", items: { type: "string", }, }, }, }, }, }), ); return; } response.statusCode = 404; response.end(); }); server.once("error", reject); server.listen(0, "127.0.0.1", () => { const address = server.address(); if (!address || typeof address === "string") { reject(new Error("Failed to bind Google workspace test server")); return; } baseUrl = `http://127.0.0.1:${address.port}`; resolve({ baseUrl, tokenEndpoint: `${baseUrl}/oauth/token`, discoveryUrl: ({ service, version, scope }) => { discoveryScopes.set(`${service}:${version}`, scope); return `${baseUrl}/${service}/$discovery/rest?version=${encodeURIComponent(version)}`; }, queueTokenResponse: (tokenResponse) => { tokenResponses.push(tokenResponse); }, tokenRequests, discoveryAuthorizations, close: () => new Promise<void>((closeResolve, closeReject) => { server.close((error) => { if (error) { closeReject(error); return; } closeResolve(); }); }), }); }); }), ), (server) => Effect.promise(() => server.close()).pipe(Effect.orDie), ); const upsertLocalSecret = ( runtime: ExecutorRuntime, input: { id: string; name: string; purpose: "oauth_refresh_token" | "oauth_client_info" | "oauth_access_token"; value: string; }, ) => executorStateForRuntime(runtime).secretMaterials.upsert({ id: SecretMaterialIdSchema.make(input.id), providerId: "local", handle: input.id, name: input.name, purpose: input.purpose, value: input.value, createdAt: Date.now(), updatedAt: Date.now(), }); const executorStateForRuntime = ( runtime: ExecutorRuntime, ): ExecutorStateStoreShape => ({ authArtifacts: runtime.storage.auth.artifacts, authLeases: runtime.storage.auth.leases, sourceOauthClients: runtime.storage.auth.sourceOauthClients, scopeOauthClients: runtime.storage.auth.scopeOauthClients, providerAuthGrants: runtime.storage.auth.providerGrants, sourceAuthSessions: runtime.storage.auth.sourceSessions, secretMaterials: runtime.storage.secrets, executions: runtime.storage.executions.runs, executionInteractions: runtime.storage.executions.interactions, executionSteps: runtime.storage.executions.steps, }); const createPersistedGoogleSource = (input: { runtime: ExecutorRuntime; name: string; namespace: string; service: string; version: string; discoveryUrl: string; scopes: ReadonlyArray<string>; auth: | { kind: "none"; } | { kind: "provider_grant_ref"; grantId: ReturnType<typeof ProviderAuthGrantIdSchema.make>; providerKey: string; requiredScopes: ReadonlyArray<string>; headerName: string; prefix: string; }; }) => Effect.gen(function* () { const installation = input.runtime.localInstallation; const source = yield* createSourceFromPayload({ scopeId: installation.scopeId, sourceId: SourceIdSchema.make(`src_${crypto.randomUUID()}`), payload: { name: input.name, kind: "google_discovery", endpoint: input.discoveryUrl, namespace: input.namespace, binding: { service: input.service, version: input.version, discoveryUrl: input.discoveryUrl, scopes: [...input.scopes], }, importAuthPolicy: "reuse_runtime", importAuth: { kind: "none" }, auth: input.auth as any, status: "connected", enabled: true, }, now: Date.now(), }); return yield* persistSource(executorStateForRuntime(input.runtime), source, { actorScopeId: installation.actorScopeId, }).pipe((effect) => provideExecutorRuntime(effect, input.runtime)); }); const expectLeft = <A, E>(effect: Effect.Effect<A, E, never>) => Effect.either(effect).pipe( Effect.flatMap((result) => Either.isLeft(result) ? Effect.succeed(result.left) : Effect.fail( runtimeEffectError( "executor-runtime.test", "Expected effect to fail", ), ), ), ); const invokeWorkspaceTool = <A>(input: { runtime: ExecutorRuntime; path: ToolPath; args: unknown; }) => provideExecutorRuntime( Effect.gen(function* () { const installation = input.runtime.localInstallation; const resolveEnvironment = yield* RuntimeExecutionResolverService; const environment = yield* resolveEnvironment({ scopeId: installation.scopeId, actorScopeId: installation.actorScopeId, executionId: ExecutionIdSchema.make(`exec_tool_${crypto.randomUUID()}`), }); return (yield* environment.toolInvoker.invoke({ path: input.path, args: input.args, })) as A; }), input.runtime, ); describe("executor-runtime", () => { it.scoped( "writes local source changes through executor.jsonc", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const scopeRoot = yield* fs.makeTempDirectoryScoped({ prefix: "executor-local-config-runtime-", }); const homeConfigPath = join(scopeRoot, ".executor-home.jsonc"); const homeStateDirectory = join(scopeRoot, ".executor-home-state"); const runtime = yield* Effect.acquireRelease( createExecutorRuntime({ workspaceRoot: scopeRoot, homeConfigPath, homeStateDirectory, }), (createdRuntime) => Effect.promise(() => createdRuntime.close()).pipe(Effect.orDie), ); const openApiServer = yield* makeOpenApiSpecServer; const installation = runtime.localInstallation; const createdSource = yield* withExecutorApiClient( { runtime, actorScopeId: installation.actorScopeId }, (client) => client.sources.create({ path: { workspaceId: installation.scopeId }, payload: { name: "GitHub", kind: "openapi", endpoint: openApiServer.baseUrl, namespace: "github", binding: { specUrl: openApiServer.specUrl, defaultHeaders: null, },