History

Use local artifact helpers in server test

Rhys Sullivan committed 8 months ago

Commit e5ac72d1 parent 59179261 file · +68 −108Browse files

Unified · Split

apps/executor/src/server/server.test.ts+68−108
@@ -1,7 +1,5 @@
1import { createServer, type IncomingMessage, type ServerResponse } from "node:http";1import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
2import { createHash, randomUUID } from "node:crypto";2import { randomUUID } from "node:crypto";
3import { mkdir, writeFile } from "node:fs/promises";
4import { join } from "node:path";
5 3
6import {4import {
7 HttpApi,5 HttpApi,
@@ -24,7 +22,6 @@ import { · 16 unmodified lines
24 type ControlPlaneClient,22 type ControlPlaneClient,
25 type ResolveExecutionEnvironment,23 type ResolveExecutionEnvironment,
26 SourceIdSchema,24 SourceIdSchema,
27 SourceRecipeIdSchema,
28 SourceRecipeRevisionIdSchema,25 SourceRecipeRevisionIdSchema,
29} from "@executor/control-plane";26} from "@executor/control-plane";
30import { makeSesExecutor } from "@executor/runtime-ses";27import { makeSesExecutor } from "@executor/runtime-ses";
@@ -41,6 +38,15 @@ import { · 10 unmodified lines
41 seedGithubOpenApiSourceInWorkspace,38 seedGithubOpenApiSourceInWorkspace,
42} from "../cli/dev";39} from "../cli/dev";
43import { createLocalExecutorServer } from "@executor/server";40import { createLocalExecutorServer } from "@executor/server";
41import {
42 buildLocalSourceArtifact,
43 writeLocalSourceArtifact,
44} from "../../../../packages/control-plane/src/runtime/local-source-artifacts";
45import {
46 resolveLocalWorkspaceContext,
47 writeProjectLocalExecutorConfig,
48} from "../../../../packages/control-plane/src/runtime/local-config";
49import { materializationFromMcpManifestEntries } from "../../../../packages/control-plane/src/runtime/source-adapters/mcp";
44 50
45const executionResolver: ResolveExecutionEnvironment = () =>51const executionResolver: ResolveExecutionEnvironment = () =>
46 Effect.succeed({52 Effect.succeed({
@@ -82,17 +88,6 @@ const createIsolatedLocalExecutorServer = ( · 35 unmodified lines
82 };88 };
83 });89 });
84 90
85const stableLocalSourceId = (input: {
86 workspaceRoot: string;
87 configKey: string;
88}) =>
89 SourceIdSchema.make(
90 `src_local_${createHash("sha256")
91 .update(`${input.workspaceRoot}:${input.configKey}`)
92 .digest("hex")
93 .slice(0, 16)}`,
94 );
95
96const writeConfiguredLocalMcpSource = (input: {91const writeConfiguredLocalMcpSource = (input: {
97 workspaceRoot: string;92 workspaceRoot: string;
98 configKey: string;93 configKey: string;
@@ -101,16 +96,58 @@ const writeConfiguredLocalMcpSource = (input: { · 2 unmodified lines
101 namespace?: string;96 namespace?: string;
102}) =>97}) =>
103 Effect.promise(async () => {98 Effect.promise(async () => {
104 const sourceId = stableLocalSourceId({99 const sourceId = SourceIdSchema.make(input.configKey);
100 const context = await resolveLocalWorkspaceContext({
105 workspaceRoot: input.workspaceRoot,101 workspaceRoot: input.workspaceRoot,
106 configKey: input.configKey,
107 });102 });
108 const recipeId = SourceRecipeIdSchema.make(`src_recipe_${sourceId}`);103
109 const recipeRevisionId = SourceRecipeRevisionIdSchema.make(`src_recipe_rev_${sourceId}`);104 await writeProjectLocalExecutorConfig({
110 const now = Date.now();105 context,
111 const manifest = {106 config: {
112 version: 1 as const,107 sources: {
113 tools: [{108 [input.configKey]: {
109 kind: "mcp",
110 name: input.name ?? "Demo",
111 namespace: input.namespace ?? input.configKey,
112 connection: {
113 endpoint: input.endpoint,
114 },
115 binding: {
116 transport: "streamable-http",
117 },
118 },
119 },
120 },
121 });
122
123 const source = {
124 id: sourceId,
125 workspaceId: "ws_local_server_test" as never,
126 name: input.name ?? "Demo",
127 kind: "mcp" as const,
128 endpoint: input.endpoint,
129 status: "connected" as const,
130 enabled: true,
131 namespace: input.namespace ?? input.configKey,
132 bindingVersion: 1,
133 binding: {
134 transport: "streamable-http",
135 queryParams: null,
136 headers: null,
137 },
138 importAuthPolicy: "reuse_runtime" as const,
139 importAuth: { kind: "none" as const },
140 auth: { kind: "none" as const },
141 sourceHash: null,
142 lastError: null,
143 createdAt: Date.now(),
144 updatedAt: Date.now(),
145 };
146
147 const materialization = materializationFromMcpManifestEntries({
148 recipeRevisionId: SourceRecipeRevisionIdSchema.make("src_recipe_rev_materialization"),
149 endpoint: input.endpoint,
150 manifestEntries: [{
114 toolId: "gated_echo",151 toolId: "gated_echo",
115 toolName: "gated_echo",152 toolName: "gated_echo",
116 description: "Asks for approval before echoing a value",153 description: "Asks for approval before echoing a value",
@@ -125,93 +162,16 @@ const writeConfiguredLocalMcpSource = (input: { · 8 unmodified lines
125 additionalProperties: false,162 additionalProperties: false,
126 }),163 }),
127 }],164 }],
128 };165 });
129 const manifestJson = JSON.stringify(manifest);
130 166
131 await mkdir(join(input.workspaceRoot, ".executor", "artifacts", "sources"), {167 await writeLocalSourceArtifact({
132 recursive: true,168 context,
169 sourceId,
170 artifact: buildLocalSourceArtifact({
171 source,
172 materialization,
173 }),
133 });174 });
134 await writeFile(
135 join(input.workspaceRoot, ".executor", "executor.jsonc"),
136 `${JSON.stringify({
137 sources: {
138 [input.configKey]: {
139 kind: "mcp",
140 name: input.name ?? "Demo",
141 namespace: input.namespace ?? input.configKey,
142 connection: {
143 endpoint: input.endpoint,
144 },
145 binding: {
146 transport: "streamable-http",
147 },
148 },
149 },
150 }, null, 2)}\n`,
151 "utf8",
152 );
153 await writeFile(
154 join(input.workspaceRoot, ".executor", "artifacts", "sources", `${input.configKey}.json`),
155 `${JSON.stringify({
156 version: 1,
157 sourceId,
158 configKey: input.configKey,
159 recipeId,
160 generatedAt: now,
161 revision: {
162 id: recipeRevisionId,
163 recipeId,
164 revisionNumber: 1,
165 sourceConfigJson: JSON.stringify({
166 kind: "mcp",
167 endpoint: input.endpoint,
168 transport: "streamable-http",
169 queryParams: null,
170 headers: null,
171 }),
172 manifestJson,
173 manifestHash: null,
174 materializationHash: null,
175 createdAt: now,
176 updatedAt: now,
177 },
178 documents: [{
179 id: `src_recipe_doc_${sourceId}`,
180 recipeRevisionId,
181 documentKind: "mcp_manifest",
182 documentKey: "manifest",
183 contentText: manifestJson,
184 contentHash: `manifest_${sourceId}`,
185 fetchedAt: now,
186 createdAt: now,
187 updatedAt: now,
188 }],
189 schemaBundles: [],
190 operations: [{
191 id: `src_recipe_op_${sourceId}`,
192 recipeRevisionId,
193 operationKey: "gated_echo",
194 transportKind: "mcp",
195 toolId: "gated_echo",
196 title: "gated_echo",
197 description: "Asks for approval before echoing a value",
198 operationKind: "unknown",
199 searchText: "demo.gated_echo gated echo approval",
200 inputSchemaJson: manifest.tools[0]!.inputSchemaJson ?? null,
201 outputSchemaJson: null,
202 providerKind: "mcp",
203 providerDataJson: JSON.stringify({
204 kind: "mcp",
205 toolId: "gated_echo",
206 toolName: "gated_echo",
207 description: "Asks for approval before echoing a value",
208 }),
209 createdAt: now,
210 updatedAt: now,
211 }],
212 }, null, 2)}\n`,
213 "utf8",
214 );
215 });175 });
216 176
217const makeServer = createIsolatedLocalExecutorServer({177const makeServer = createIsolatedLocalExecutorServer({