OpenAPI and GraphQL plugins now register their runtime tools under a single "built-in" source instead of separate executor.openapi / executor.graphql sources. Tool names are namespaced (openapi.addSource, graphql.addSource) so the tree UI nests them properly.
Unified · Split
| @@ -47,9 +47,9 @@ describe("SDK Executor", () => { · 46 unmodified lines | |||
| 47 | const sources = makeInMemorySourceRegistry(); | 47 | const sources = makeInMemorySourceRegistry(); |
| 48 | 48 | ||
| 49 | yield* sources.registerRuntime(new Source({ | 49 | yield* sources.registerRuntime(new Source({ |
| 50 | id: "executor.openapi", | 50 | id: "built-in", |
| 51 | name: "OpenAPI", | 51 | name: "Built In", |
| 52 | kind: "openapi", | 52 | kind: "built-in", |
| 53 | runtime: true, | 53 | runtime: true, |
| 54 | canRemove: false, | 54 | canRemove: false, |
| 55 | canRefresh: false, | 55 | canRefresh: false, |
| @@ -72,7 +72,7 @@ describe("SDK Executor", () => { · 16 unmodified lines | |||
| 72 | }); | 72 | }); |
| 73 | 73 | ||
| 74 | expect((yield* sources.list()).map((source) => source.id)).toEqual([ | 74 | expect((yield* sources.list()).map((source) => source.id)).toEqual([ |
| 75 | "executor.openapi", | 75 | "built-in", |
| 76 | "vercel", | 76 | "vercel", |
| 77 | ]); | 77 | ]); |
| 78 | }), | 78 | }), |
| @@ -153,12 +153,15 @@ describe("graphqlPlugin", () => { · 152 unmodified lines | |||
| 153 | ); | 153 | ); |
| 154 | 154 | ||
| 155 | const sources = await Effect.runPromise(executor.sources.list()); | 155 | const sources = await Effect.runPromise(executor.sources.list()); |
| 156 | // 1 user source + 1 runtime source (executor.graphql) | 156 | // 1 user source + 1 built-in runtime source |
| 157 | const gqlSources = sources.filter((s) => s.kind === "graphql"); | 157 | const gqlSources = sources.filter((s) => s.kind === "graphql"); |
| 158 | expect(gqlSources).toHaveLength(2); | 158 | expect(gqlSources).toHaveLength(1); |
| 159 | const userSource = gqlSources.find((s) => s.id === "my_gql"); | 159 | const userSource = gqlSources.find((s) => s.id === "my_gql"); |
| 160 | expect(userSource).toBeDefined(); | 160 | expect(userSource).toBeDefined(); |
| 161 | expect(userSource!.canRemove).toBe(true); | 161 | expect(userSource!.canRemove).toBe(true); |
| 162 | const builtIn = sources.find((s) => s.id === "built-in"); | ||
| 163 | expect(builtIn).toBeDefined(); | ||
| 164 | expect(builtIn!.runtime).toBe(true); | ||
| 162 | 165 | ||
| 163 | await Effect.runPromise(executor.close()); | 166 | await Effect.runPromise(executor.close()); |
| 164 | }); | 167 | }); |
| @@ -371,13 +371,14 @@ export const graphqlPlugin = (options?: { · 370 unmodified lines | |||
| 371 | sources: ctx.sources, | 371 | sources: ctx.sources, |
| 372 | pluginKey: "graphql", | 372 | pluginKey: "graphql", |
| 373 | source: { | 373 | source: { |
| 374 | id: "executor.graphql", | 374 | id: "built-in", |
| 375 | name: "GraphQL", | 375 | name: "Built In", |
| 376 | kind: "built-in", | ||
| 376 | }, | 377 | }, |
| 377 | tools: [ | 378 | tools: [ |
| 378 | runtimeTool({ | 379 | runtimeTool({ |
| 379 | id: "executor.graphql.addSource", | 380 | id: "graphql.addSource", |
| 380 | name: "addSource", | 381 | name: "graphql.addSource", |
| 381 | description: | 382 | description: |
| 382 | "Add a GraphQL endpoint and register its operations as tools", | 383 | "Add a GraphQL endpoint and register its operations as tools", |
| 383 | inputSchema: AddSourceInputSchema, | 384 | inputSchema: AddSourceInputSchema, |
| @@ -128,7 +128,7 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 127 unmodified lines | |||
| 128 | }), | 128 | }), |
| 129 | ); | 129 | ); |
| 130 | 130 | ||
| 131 | it.effect("registers runtime executor.openapi tools", () => | 131 | it.effect("registers runtime openapi tools under built-in source", () => |
| 132 | Effect.gen(function* () { | 132 | Effect.gen(function* () { |
| 133 | const httpClient = yield* HttpClient.HttpClient; | 133 | const httpClient = yield* HttpClient.HttpClient; |
| 134 | const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient); | 134 | const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient); |
| @@ -143,12 +143,12 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 8 unmodified lines | |||
| 143 | 143 | ||
| 144 | const tools = yield* executor.tools.list(); | 144 | const tools = yield* executor.tools.list(); |
| 145 | const ids = tools.map((t) => t.id); | 145 | const ids = tools.map((t) => t.id); |
| 146 | expect(ids).toContain("executor.openapi.previewSpec"); | 146 | expect(ids).toContain("openapi.previewSpec"); |
| 147 | expect(ids).toContain("executor.openapi.addSource"); | 147 | expect(ids).toContain("openapi.addSource"); |
| 148 | }), | 148 | }), |
| 149 | ); | 149 | ); |
| 150 | 150 | ||
| 151 | it.effect("lists executor.openapi as a runtime source", () => | 151 | it.effect("lists built-in as a runtime source", () => |
| 152 | Effect.gen(function* () { | 152 | Effect.gen(function* () { |
| 153 | const httpClient = yield* HttpClient.HttpClient; | 153 | const httpClient = yield* HttpClient.HttpClient; |
| 154 | const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient); | 154 | const clientLayer = Layer.succeed(HttpClient.HttpClient, httpClient); |
| @@ -164,9 +164,9 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 9 unmodified lines | |||
| 164 | const sources = yield* executor.sources.list(); | 164 | const sources = yield* executor.sources.list(); |
| 165 | 165 | ||
| 166 | expect(sources).toContainEqual(expect.objectContaining({ | 166 | expect(sources).toContainEqual(expect.objectContaining({ |
| 167 | id: "executor.openapi", | 167 | id: "built-in", |
| 168 | name: "OpenAPI", | 168 | name: "Built In", |
| 169 | kind: "openapi", | 169 | kind: "built-in", |
| 170 | runtime: true, | 170 | runtime: true, |
| 171 | canRemove: false, | 171 | canRemove: false, |
| 172 | canRefresh: false, | 172 | canRefresh: false, |
| @@ -239,7 +239,7 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 66 unmodified lines | |||
| 239 | ); | 239 | ); |
| 240 | 240 | ||
| 241 | const result = yield* executor.tools.invoke( | 241 | const result = yield* executor.tools.invoke( |
| 242 | "executor.openapi.previewSpec", | 242 | "openapi.previewSpec", |
| 243 | { spec: specJson }, | 243 | { spec: specJson }, |
| 244 | autoApprove, | 244 | autoApprove, |
| 245 | ); | 245 | ); |
| @@ -263,7 +263,7 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 17 unmodified lines | |||
| 263 | ); | 263 | ); |
| 264 | 264 | ||
| 265 | const result = yield* executor.tools.invoke( | 265 | const result = yield* executor.tools.invoke( |
| 266 | "executor.openapi.addSource", | 266 | "openapi.addSource", |
| 267 | { spec: specJson, namespace: "runtime" }, | 267 | { spec: specJson, namespace: "runtime" }, |
| 268 | autoApprove, | 268 | autoApprove, |
| 269 | ); | 269 | ); |
| @@ -459,8 +459,8 @@ layer(TestLayer)("OpenAPI Plugin", (it) => { · 189 unmodified lines | |||
| 459 | 459 | ||
| 460 | const remaining = yield* executor.tools.list(); | 460 | const remaining = yield* executor.tools.list(); |
| 461 | expect(remaining.map((tool) => tool.id)).toEqual([ | 461 | expect(remaining.map((tool) => tool.id)).toEqual([ |
| 462 | "executor.openapi.previewSpec", | 462 | "openapi.previewSpec", |
| 463 | "executor.openapi.addSource", | 463 | "openapi.addSource", |
| 464 | ]); | 464 | ]); |
| 465 | }), | 465 | }), |
| 466 | ); | 466 | ); |
| @@ -295,13 +295,14 @@ export const openApiPlugin = (options?: { · 294 unmodified lines | |||
| 295 | sources: ctx.sources, | 295 | sources: ctx.sources, |
| 296 | pluginKey: "openapi", | 296 | pluginKey: "openapi", |
| 297 | source: { | 297 | source: { |
| 298 | id: "executor.openapi", | 298 | id: "built-in", |
| 299 | name: "OpenAPI", | 299 | name: "Built In", |
| 300 | kind: "built-in", | ||
| 300 | }, | 301 | }, |
| 301 | tools: [ | 302 | tools: [ |
| 302 | runtimeTool({ | 303 | runtimeTool({ |
| 303 | id: "executor.openapi.previewSpec", | 304 | id: "openapi.previewSpec", |
| 304 | name: "previewSpec", | 305 | name: "openapi.previewSpec", |
| 305 | description: | 306 | description: |
| 306 | "Preview an OpenAPI document before adding it as a source", | 307 | "Preview an OpenAPI document before adding it as a source", |
| 307 | inputSchema: PreviewSpecInputSchema, | 308 | inputSchema: PreviewSpecInputSchema, |
| @@ -309,8 +310,8 @@ export const openApiPlugin = (options?: { · 1 unmodified line | |||
| 309 | handler: ({ spec }: PreviewSpecInput) => previewSpec(spec), | 310 | handler: ({ spec }: PreviewSpecInput) => previewSpec(spec), |
| 310 | }), | 311 | }), |
| 311 | runtimeTool({ | 312 | runtimeTool({ |
| 312 | id: "executor.openapi.addSource", | 313 | id: "openapi.addSource", |
| 313 | name: "addSource", | 314 | name: "openapi.addSource", |
| 314 | description: | 315 | description: |
| 315 | "Add an OpenAPI source and register its operations as tools", | 316 | "Add an OpenAPI source and register its operations as tools", |
| 316 | inputSchema: AddSourceInputSchema, | 317 | inputSchema: AddSourceInputSchema, |
| @@ -217,8 +217,8 @@ describe("Real specs: Cloudflare API", () => { · 216 unmodified lines | |||
| 217 | 217 | ||
| 218 | const remaining = yield* executor.tools.list(); | 218 | const remaining = yield* executor.tools.list(); |
| 219 | expect(remaining.map((tool) => tool.id)).toEqual([ | 219 | expect(remaining.map((tool) => tool.id)).toEqual([ |
| 220 | "executor.openapi.previewSpec", | 220 | "openapi.previewSpec", |
| 221 | "executor.openapi.addSource", | 221 | "openapi.addSource", |
| 222 | ]); | 222 | ]); |
| 223 | }), | 223 | }), |
| 224 | ); | 224 | ); |