Unified · Split
| @@ -0,0 +1,5 @@ | ||
| 1 | +--- | |
| 2 | +"executor": patch | |
| 3 | +--- | |
| 4 | + | |
| 5 | +Avoid ever building a full schema workspace catalog during tool description, and resolve schemaful tool details through direct one-tool lookup instead. | |
| @@ -125,7 +125,7 @@ describe("scope source catalog", () => { · 124 unmodified lines | ||
| 125 | 125 | ]); |
| 126 | 126 | })); |
| 127 | 127 | |
| 128 | − it.effect("reuses a lean shared catalog for repeated no-schema search and lookup calls", () => | |
| 128 | + it.effect("reuses the lean shared catalog for repeated search, list, and no-schema lookup calls", () => | |
| 129 | 129 | Effect.gen(function* () { |
| 130 | 130 | const loadWorkspaceSourceCatalogToolIndexCalls: Array<undefined> = []; |
| 131 | 131 | |
| @@ -195,6 +195,11 @@ describe("scope source catalog", () => { · 63 unmodified lines | ||
| 195 | 195 | limit: 20, |
| 196 | 196 | includeSchemas: false, |
| 197 | 197 | }); |
| 198 | + const listedWithSchemas = yield* catalog.listTools({ | |
| 199 | + query: "GitHub list repository issues", | |
| 200 | + limit: 20, | |
| 201 | + includeSchemas: true, | |
| 202 | + }); | |
| 198 | 203 | |
| 199 | 204 | expect(hits).toHaveLength(1); |
| 200 | 205 | expect(hits[0]?.path).toBe("github.issues.list"); |
| @@ -202,6 +207,115 @@ describe("scope source catalog", () => { · 1 unmodified line | ||
| 202 | 207 | expect(first?.contract?.inputTypePreview).toBeUndefined(); |
| 203 | 208 | expect(second?.contract?.outputTypePreview).toBeUndefined(); |
| 204 | 209 | expect(listed).toHaveLength(1); |
| 210 | + expect(listedWithSchemas).toHaveLength(1); | |
| 211 | + expect(listedWithSchemas[0]?.contract?.inputSchema).toBeUndefined(); | |
| 205 | 212 | expect(loadWorkspaceSourceCatalogToolIndexCalls).toHaveLength(1); |
| 206 | 213 | })); |
| 214 | + | |
| 215 | + it.effect("loads schemaful tool descriptions through direct tool lookup instead of a shared schema catalog", () => | |
| 216 | + Effect.gen(function* () { | |
| 217 | + const loadWorkspaceSourceCatalogToolIndexCalls: Array<undefined> = []; | |
| 218 | + const loadWorkspaceSourceCatalogToolByPathCalls: Array<{ | |
| 219 | + path: string; | |
| 220 | + includeSchemas: boolean; | |
| 221 | + }> = []; | |
| 222 | + | |
| 223 | + const catalog = createScopeSourceCatalog({ | |
| 224 | + scopeId: "ws_test" as any, | |
| 225 | + actorScopeId: "acc_test" as any, | |
| 226 | + sourceCatalogStore: { | |
| 227 | + loadWorkspaceSourceCatalogs: () => Effect.die("unexpected catalog load"), | |
| 228 | + loadWorkspaceSourceCatalogToolIndex: () => { | |
| 229 | + loadWorkspaceSourceCatalogToolIndexCalls.push(undefined); | |
| 230 | + | |
| 231 | + return Effect.succeed([{ | |
| 232 | + path: "github.issues.list", | |
| 233 | + searchNamespace: "github.issues", | |
| 234 | + searchText: "github issues list repository issues", | |
| 235 | + source: { | |
| 236 | + enabled: true, | |
| 237 | + status: "connected", | |
| 238 | + }, | |
| 239 | + sourceRecord: {}, | |
| 240 | + capabilityId: "cap_1", | |
| 241 | + executableId: "exec_1", | |
| 242 | + capability: { | |
| 243 | + surface: { | |
| 244 | + title: "List Repository Issues", | |
| 245 | + }, | |
| 246 | + }, | |
| 247 | + executable: { | |
| 248 | + display: { | |
| 249 | + leaf: "list", | |
| 250 | + }, | |
| 251 | + }, | |
| 252 | + descriptor: { | |
| 253 | + path: "github.issues.list", | |
| 254 | + sourceKey: "github", | |
| 255 | + description: "List issues for a repository", | |
| 256 | + interaction: "auto", | |
| 257 | + }, | |
| 258 | + projectedCatalog: {}, | |
| 259 | + }] as any); | |
| 260 | + }, | |
| 261 | + loadWorkspaceSourceCatalogToolByPath: (input: { | |
| 262 | + path: string; | |
| 263 | + includeSchemas: boolean; | |
| 264 | + }) => { | |
| 265 | + loadWorkspaceSourceCatalogToolByPathCalls.push(input); | |
| 266 | + | |
| 267 | + return Effect.succeed({ | |
| 268 | + path: "github.issues.list", | |
| 269 | + searchNamespace: "github.issues", | |
| 270 | + searchText: "github issues list repository issues", | |
| 271 | + source: { | |
| 272 | + enabled: true, | |
| 273 | + status: "connected", | |
| 274 | + }, | |
| 275 | + sourceRecord: {}, | |
| 276 | + capabilityId: "cap_1", | |
| 277 | + executableId: "exec_1", | |
| 278 | + capability: { | |
| 279 | + surface: { | |
| 280 | + title: "List Repository Issues", | |
| 281 | + }, | |
| 282 | + }, | |
| 283 | + executable: { | |
| 284 | + display: { | |
| 285 | + leaf: "list", | |
| 286 | + }, | |
| 287 | + }, | |
| 288 | + descriptor: { | |
| 289 | + path: "github.issues.list", | |
| 290 | + sourceKey: "github", | |
| 291 | + description: "List issues for a repository", | |
| 292 | + interaction: "auto", | |
| 293 | + contract: { | |
| 294 | + inputSchema: { type: "object" }, | |
| 295 | + }, | |
| 296 | + }, | |
| 297 | + projectedCatalog: {}, | |
| 298 | + } as any); | |
| 299 | + }, | |
| 300 | + } as any, | |
| 301 | + scopeConfigStore: noopScopeConfigStore, | |
| 302 | + scopeStateStore: noopScopeStateStore, | |
| 303 | + sourceArtifactStore: noopSourceArtifactStore, | |
| 304 | + runtimeLocalScope: null, | |
| 305 | + }); | |
| 306 | + | |
| 307 | + const described = yield* catalog.getToolByPath({ | |
| 308 | + path: "github.issues.list" as any, | |
| 309 | + includeSchemas: true, | |
| 310 | + }); | |
| 311 | + | |
| 312 | + expect(described?.contract?.inputSchema).toEqual({ type: "object" }); | |
| 313 | + expect(loadWorkspaceSourceCatalogToolIndexCalls).toHaveLength(0); | |
| 314 | + expect(loadWorkspaceSourceCatalogToolByPathCalls).toEqual([{ | |
| 315 | + scopeId: "ws_test", | |
| 316 | + actorScopeId: "acc_test", | |
| 317 | + path: "github.issues.list", | |
| 318 | + includeSchemas: true, | |
| 319 | + }]); | |
| 320 | + })); | |
| 207 | 321 | }); |
| @@ -13,8 +13,6 @@ import { · 12 unmodified lines | ||
| 13 | 13 | RuntimeSourceCatalogStoreService, |
| 14 | 14 | type LoadedSourceCatalogToolIndexEntry, |
| 15 | 15 | catalogToolCatalogEntry, |
| 16 | − expandCatalogTools, | |
| 17 | − loadedSourceCatalogToolIndexEntryFromLoadedTool, | |
| 18 | 16 | } from "../../catalog/source/runtime"; |
| 19 | 17 | import type { |
| 20 | 18 | RuntimeLocalScopeState, |
| @@ -130,40 +128,21 @@ export const loadWorkspaceCatalogTools = (input: { · 109 unmodified lines | ||
| 130 | 128 | scopeId: Source["scopeId"]; |
| 131 | 129 | actorScopeId: ScopeId; |
| 132 | 130 | sourceCatalogStore: Effect.Effect.Success<typeof RuntimeSourceCatalogStoreService>; |
| 133 | − includeSchemas: boolean; | |
| 134 | 131 | }): Effect.Effect< |
| 135 | 132 | readonly LoadedSourceCatalogToolIndexEntry[], |
| 136 | 133 | Error, |
| 137 | 134 | ScopeStorageServices |
| 138 | 135 | > => |
| 139 | − input.includeSchemas | |
| 140 | − ? Effect.gen(function* () { | |
| 141 | − const catalogs = yield* input.sourceCatalogStore.loadWorkspaceSourceCatalogs({ | |
| 142 | − scopeId: input.scopeId, | |
| 143 | − actorScopeId: input.actorScopeId, | |
| 144 | − }); | |
| 145 | − const tools = yield* expandCatalogTools({ | |
| 146 | − catalogs, | |
| 147 | − includeSchemas: true, | |
| 148 | − includeTypePreviews: true, | |
| 149 | − }); | |
| 150 | − | |
| 151 | − return tools | |
| 152 | − .map(loadedSourceCatalogToolIndexEntryFromLoadedTool) | |
| 153 | − .filter( | |
| 154 | − (tool) => tool.source.enabled && tool.source.status === "connected", | |
| 155 | − ); | |
| 156 | − }) | |
| 157 | − : Effect.map( | |
| 158 | − input.sourceCatalogStore.loadWorkspaceSourceCatalogToolIndex({ | |
| 159 | − scopeId: input.scopeId, | |
| 160 | − actorScopeId: input.actorScopeId, | |
| 161 | − }), | |
| 162 | − (tools) => | |
| 163 | − tools.filter( | |
| 164 | − (tool) => tool.source.enabled && tool.source.status === "connected", | |
| 165 | − ), | |
| 166 | − ); | |
| 136 | + Effect.map( | |
| 137 | + input.sourceCatalogStore.loadWorkspaceSourceCatalogToolIndex({ | |
| 138 | + scopeId: input.scopeId, | |
| 139 | + actorScopeId: input.actorScopeId, | |
| 140 | + }), | |
| 141 | + (tools) => | |
| 142 | + tools.filter( | |
| 143 | + (tool) => tool.source.enabled && tool.source.status === "connected", | |
| 144 | + ), | |
| 145 | + ); | |
| 167 | 146 | |
| 168 | 147 | export const loadWorkspaceCatalogToolByPath = (input: { |
| 169 | 148 | scopeId: Source["scopeId"]; |
| @@ -332,13 +311,12 @@ export const createScopeSourceCatalog = (input: { · 162 unmodified lines | ||
| 332 | 311 | const provideWorkspaceStorage = <A, E, R>(effect: Effect.Effect<A, E, R>) => |
| 333 | 312 | effect.pipe(Effect.provide(scopeStorageLayer)); |
| 334 | 313 | |
| 335 | − const buildSharedCatalog = (includeSchemas: boolean) => | |
| 314 | + const buildSharedCatalog = () => | |
| 336 | 315 | provideWorkspaceStorage(Effect.gen(function* () { |
| 337 | 316 | const catalogTools = yield* loadWorkspaceCatalogTools({ |
| 338 | 317 | scopeId: input.scopeId, |
| 339 | 318 | actorScopeId: input.actorScopeId, |
| 340 | 319 | sourceCatalogStore: input.sourceCatalogStore, |
| 341 | − includeSchemas, | |
| 342 | 320 | }); |
| 343 | 321 | |
| 344 | 322 | return createToolCatalogFromEntries({ |
| @@ -352,15 +330,9 @@ export const createScopeSourceCatalog = (input: { · 7 unmodified lines | ||
| 352 | 330 | })); |
| 353 | 331 | |
| 354 | 332 | const leanSharedCatalog = Effect.runSync( |
| 355 | − Effect.cached(buildSharedCatalog(false)), | |
| 356 | − ); | |
| 357 | − const schemaSharedCatalog = Effect.runSync( | |
| 358 | − Effect.cached(buildSharedCatalog(true)), | |
| 333 | + Effect.cached(buildSharedCatalog()), | |
| 359 | 334 | ); |
| 360 | 335 | |
| 361 | − const createSharedCatalog = (includeSchemas: boolean): Effect.Effect<ToolCatalog, Error, never> => | |
| 362 | − includeSchemas ? schemaSharedCatalog : leanSharedCatalog; | |
| 363 | − | |
| 364 | 336 | return { |
| 365 | 337 | listNamespaces: ({ limit }) => |
| 366 | 338 | provideRuntimeLocalScope( |
| @@ -375,14 +347,14 @@ export const createScopeSourceCatalog = (input: { · 8 unmodified lines | ||
| 375 | 347 | input.runtimeLocalScope, |
| 376 | 348 | ), |
| 377 | 349 | |
| 378 | − listTools: ({ namespace, query, limit, includeSchemas = false }) => | |
| 350 | + listTools: ({ namespace, query, limit }) => | |
| 379 | 351 | provideRuntimeLocalScope( |
| 380 | − Effect.flatMap(createSharedCatalog(includeSchemas), (catalog) => | |
| 352 | + Effect.flatMap(leanSharedCatalog, (catalog) => | |
| 381 | 353 | catalog.listTools({ |
| 382 | 354 | ...(namespace !== undefined ? { namespace } : {}), |
| 383 | 355 | ...(query !== undefined ? { query } : {}), |
| 384 | 356 | limit, |
| 385 | − includeSchemas, | |
| 357 | + includeSchemas: false, | |
| 386 | 358 | }), |
| 387 | 359 | ), |
| 388 | 360 | input.runtimeLocalScope, |
| @@ -390,15 +362,26 @@ export const createScopeSourceCatalog = (input: { · 1 unmodified line | ||
| 390 | 362 | |
| 391 | 363 | getToolByPath: ({ path, includeSchemas }) => |
| 392 | 364 | provideRuntimeLocalScope( |
| 393 | − Effect.flatMap(createSharedCatalog(includeSchemas), (catalog) => | |
| 394 | − catalog.getToolByPath({ path, includeSchemas }), | |
| 395 | − ), | |
| 365 | + includeSchemas | |
| 366 | + ? Effect.map( | |
| 367 | + provideWorkspaceStorage(loadWorkspaceCatalogToolByPath({ | |
| 368 | + scopeId: input.scopeId, | |
| 369 | + actorScopeId: input.actorScopeId, | |
| 370 | + sourceCatalogStore: input.sourceCatalogStore, | |
| 371 | + path, | |
| 372 | + includeSchemas: true, | |
| 373 | + })), | |
| 374 | + (tool) => tool?.descriptor ?? null, | |
| 375 | + ) | |
| 376 | + : Effect.flatMap(leanSharedCatalog, (catalog) => | |
| 377 | + catalog.getToolByPath({ path, includeSchemas: false }) | |
| 378 | + ), | |
| 396 | 379 | input.runtimeLocalScope, |
| 397 | 380 | ), |
| 398 | 381 | |
| 399 | 382 | searchTools: ({ query, namespace, limit }) => |
| 400 | 383 | provideRuntimeLocalScope( |
| 401 | − Effect.flatMap(createSharedCatalog(false), (catalog) => | |
| 384 | + Effect.flatMap(leanSharedCatalog, (catalog) => | |
| 402 | 385 | catalog.searchTools({ |
| 403 | 386 | query, |
| 404 | 387 | ...(namespace !== undefined ? { namespace } : {}), |