History

Move control tools under executor namespace (#756)

Rhys Sullivan committed 6 months ago

Commit 65bd2ff1 parent d80571124 files · +329 −200Browse files

Showing the changes to packages/plugins/openapi/src (2 of 24 files). Show all

Unified · Split

2 files
  1. packages/plugins/openapi/src/sdk/plugin.test.ts +30 −9
  2. packages/plugins/openapi/src/sdk/plugin.ts +26 −46
packages/plugins/openapi/src/sdk/plugin.test.ts+30−9
@@ -212,7 +212,7 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 211 unmodified lines
212 }),212 }),
213 );213 );
214 214
215 it.effect("registers static openapi control tools", () =>215 it.effect("registers static openapi executor tools", () =>
216 Effect.gen(function* () {216 Effect.gen(function* () {
217 const httpClient = yield* HttpClient.HttpClient;217 const httpClient = yield* HttpClient.HttpClient;
218 const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient);218 const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient);
@@ -228,12 +228,12 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 9 unmodified lines
228 228
229 const tools = yield* executor.tools.list();229 const tools = yield* executor.tools.list();
230 const ids = tools.map((t) => t.id);230 const ids = tools.map((t) => t.id);
231 expect(ids).toContain("openapi.previewSpec");231 expect(ids).toContain("executor.openapi.previewSpec");
232 expect(ids).toContain("openapi.addSource");232 expect(ids).toContain("executor.openapi.addSource");
233 }),233 }),
234 );234 );
235 235
236 it.effect("lists openapi as a static runtime source", () =>236 it.effect("lists executor as the static runtime source", () =>
237 Effect.gen(function* () {237 Effect.gen(function* () {
238 const httpClient = yield* HttpClient.HttpClient;238 const httpClient = yield* HttpClient.HttpClient;
239 const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient);239 const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient);
@@ -248,7 +248,8 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 8 unmodified lines
248 );248 );
249 249
250 const sources = yield* executor.sources.list();250 const sources = yield* executor.sources.list();
251 const control = sources.find((s) => s.id === "openapi");251 expect(sources.find((s) => s.id === "openapi")).toBeUndefined();
252 const control = sources.find((s) => s.id === "executor");
252 expect(control).toBeDefined();253 expect(control).toBeDefined();
253 expect(control!.runtime).toBe(true);254 expect(control!.runtime).toBe(true);
254 expect(control!.canRemove).toBe(false);255 expect(control!.canRemove).toBe(false);
@@ -270,7 +271,7 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 15 unmodified lines
270 );271 );
271 272
272 const result = (yield* executor.tools.invoke(273 const result = (yield* executor.tools.invoke(
273 "openapi.previewSpec",274 "executor.openapi.previewSpec",
274 { spec: specJson },275 { spec: specJson },
275 autoApprove,276 autoApprove,
276 )) as { operationCount: number };277 )) as { operationCount: number };
@@ -279,6 +280,26 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 2 unmodified lines
279 }),280 }),
280 );281 );
281 282
283 it.effect("describes static addSource parameters from Standard Schema", () =>
284 Effect.gen(function* () {
285 const executor = yield* createExecutor(
286 makeTestConfig({
287 plugins: [openApiPlugin(), memorySecretsPlugin()] as const,
288 }),
289 );
290
291 const schema = yield* executor.tools.schema("executor.openapi.addSource");
292
293 expect(schema).not.toBeNull();
294 expect(schema!.inputTypeScript).toContain("scope: string");
295 expect(schema!.inputTypeScript).toContain("spec: string");
296 expect(
297 (schema!.inputSchema as { properties?: Record<string, unknown> }).properties,
298 ).toHaveProperty("credentialTargetScope");
299 expect(schema!.inputTypeScript).not.toBe("Record<string, unknown>");
300 }),
301 );
302
282 it.effect("invokes static addSource through executor.tools.invoke", () =>303 it.effect("invokes static addSource through executor.tools.invoke", () =>
283 Effect.gen(function* () {304 Effect.gen(function* () {
284 const httpClient = yield* HttpClient.HttpClient;305 const httpClient = yield* HttpClient.HttpClient;
@@ -300,7 +321,7 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 15 unmodified lines
300 );321 );
301 322
302 const result = (yield* executor.tools.invoke(323 const result = (yield* executor.tools.invoke(
303 "openapi.addSource",324 "executor.openapi.addSource",
304 { scope: String(orgScope), spec: specJson, namespace: "runtime" },325 { scope: String(orgScope), spec: specJson, namespace: "runtime" },
305 autoApprove,326 autoApprove,
306 )) as { sourceId: string; toolCount: number };327 )) as { sourceId: string; toolCount: number };
@@ -322,7 +343,7 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 15 unmodified lines
322 343
323 const declined = yield* executor.tools344 const declined = yield* executor.tools
324 .invoke(345 .invoke(
325 "openapi.addSource",346 "executor.openapi.addSource",
326 { scope: TEST_SCOPE, spec: specJson, namespace: "runtime_declined" },347 { scope: TEST_SCOPE, spec: specJson, namespace: "runtime_declined" },
327 { onElicitation: () => Effect.succeed({ action: "decline" as const }) },348 { onElicitation: () => Effect.succeed({ action: "decline" as const }) },
328 )349 )
@@ -825,7 +846,7 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 496 unmodified lines
825 846
826 const remaining = yield* executor.tools.list();847 const remaining = yield* executor.tools.list();
827 const ids = remaining.map((t) => t.id).sort();848 const ids = remaining.map((t) => t.id).sort();
828 expect(ids).toEqual(["openapi.addSource", "openapi.previewSpec"]);849 expect(ids).toEqual(["executor.openapi.addSource", "executor.openapi.previewSpec"]);
829 }),850 }),
830 );851 );
831 852
packages/plugins/openapi/src/sdk/plugin.ts+26−46
@@ -8,6 +8,7 @@ import { · 7 unmodified lines
8 SourceDetectionResult,8 SourceDetectionResult,
9 StorageError,9 StorageError,
10 definePlugin,10 definePlugin,
11 tool,
11 resolveSecretBackedMap,12 resolveSecretBackedMap,
12 type CredentialBindingRef,13 type CredentialBindingRef,
13 type PluginCtx,14 type PluginCtx,
@@ -169,7 +170,6 @@ const PreviewSpecInputSchema = Schema.Struct({ · 155 unmodified lines
169 }),170 }),
170 ),171 ),
171});172});
172type PreviewSpecInput = typeof PreviewSpecInputSchema.Type;
173 173
174const OpenApiHeaderInputSchema = Schema.Union([HeaderValueSchema, ConfiguredHeaderValueSchema]);174const OpenApiHeaderInputSchema = Schema.Union([HeaderValueSchema, ConfiguredHeaderValueSchema]);
175const OpenApiOAuthInputSchema = OAuth2SourceConfig;175const OpenApiOAuthInputSchema = OAuth2SourceConfig;
@@ -191,7 +191,21 @@ const AddSourceInputSchema = Schema.Struct({ · 15 unmodified lines
191 }),191 }),
192 ),192 ),
193});193});
194type AddSourceInput = typeof AddSourceInputSchema.Type;194
195const AddSourceOutputSchema = Schema.Struct({
196 sourceId: Schema.String,
197 toolCount: Schema.Number,
198});
199
200const PreviewSpecInputStandardSchema = Schema.toStandardSchemaV1(
201 Schema.toStandardJSONSchemaV1(PreviewSpecInputSchema),
202);
203const AddSourceInputStandardSchema = Schema.toStandardSchemaV1(
204 Schema.toStandardJSONSchemaV1(AddSourceInputSchema),
205);
206const AddSourceOutputStandardSchema = Schema.toStandardSchemaV1(
207 Schema.toStandardJSONSchemaV1(AddSourceOutputSchema),
208);
195 209
196// ---------------------------------------------------------------------------210// ---------------------------------------------------------------------------
197// Helpers211// Helpers
@@ -1172,60 +1186,26 @@ export const openApiPlugin = definePlugin((options?: OpenApiPluginOptions) => { · 974 unmodified lines
1172 staticSources: (self) => [1186 staticSources: (self) => [
1173 {1187 {
1174 id: "openapi",1188 id: "openapi",
1175 kind: "control",1189 kind: "executor",
1176 name: "OpenAPI",1190 name: "OpenAPI",
1177 tools: [1191 tools: [
1178 {1192 tool({
1179 name: "previewSpec",1193 name: "previewSpec",
1180 description: "Preview an OpenAPI document before adding it as a source",1194 description: "Preview an OpenAPI document before adding it as a source",
1181 inputSchema: {1195 inputSchema: PreviewSpecInputStandardSchema,
1182 type: "object",1196 execute: (input) => self.previewSpec(input),
1183 properties: {1197 }),
1184 spec: { type: "string" },1198 tool({
1185 specFetchCredentials: { type: "object" },
1186 },
1187 required: ["spec"],
1188 },
1189 handler: ({ args }) => self.previewSpec(args as PreviewSpecInput),
1190 },
1191 {
1192 name: "addSource",1199 name: "addSource",
1193 description: "Add an OpenAPI source and register its operations as tools",1200 description: "Add an OpenAPI source and register its operations as tools",
1194 annotations: {1201 annotations: {
1195 requiresApproval: true,1202 requiresApproval: true,
1196 approvalDescription: "Add an OpenAPI source",1203 approvalDescription: "Add an OpenAPI source",
1197 },1204 },
1198 inputSchema: {1205 inputSchema: AddSourceInputStandardSchema,
1199 type: "object",1206 outputSchema: AddSourceOutputStandardSchema,
1200 properties: {1207 execute: (input) => self.addSpec(input),
1201 scope: { type: "string" },1208 }),
1202 spec: { type: "string" },
1203 name: { type: "string" },
1204 baseUrl: { type: "string" },
1205 namespace: { type: "string" },
1206 headers: { type: "object" },
1207 queryParams: { type: "object" },
1208 oauth2: { type: "object" },
1209 credentialTargetScope: { type: "string" },
1210 specFetchCredentials: { type: "object" },
1211 },
1212 required: ["scope", "spec"],
1213 },
1214 outputSchema: {
1215 type: "object",
1216 properties: {
1217 sourceId: { type: "string" },
1218 toolCount: { type: "number" },
1219 },
1220 required: ["sourceId", "toolCount"],
1221 },
1222 handler: ({ args }) =>
1223 Effect.gen(function* () {
1224 const input: AddSourceInput =
1225 yield* Schema.decodeUnknownEffect(AddSourceInputSchema)(args);
1226 return yield* self.addSpec(input);
1227 }),
1228 },
1229 ],1209 ],
1230 },1210 },
1231 ],1211 ],