Source adapters now produce CatalogFragmentV1 instead of full CatalogSnapshotV1 objects. Fragments are assembled into snapshots at the sync boundary via createCatalogSnapshotV1FromFragments, keeping import metadata separate from catalog data. This prepares the IR pipeline for multi-fragment catalog composition.
Unified · Split
| @@ -1650,6 +1650,15 @@ export const createCatalogSnapshotV1 = (input: { · 1649 unmodified lines | |||
| 1650 | }; | 1650 | }; |
| 1651 | }; | 1651 | }; |
| 1652 | 1652 | ||
| 1653 | export const createCatalogSnapshotV1FromFragments = (input: { | ||
| 1654 | import: ImportMetadata; | ||
| 1655 | fragments: readonly CatalogFragmentV1[]; | ||
| 1656 | }) => | ||
| 1657 | createCatalogSnapshotV1({ | ||
| 1658 | import: input.import, | ||
| 1659 | catalog: mergeCatalogFragments(input.fragments), | ||
| 1660 | }); | ||
| 1661 | |||
| 1653 | export const mergeCatalogFragments = (fragments: readonly CatalogFragmentV1[]): CatalogV1 => { | 1662 | export const mergeCatalogFragments = (fragments: readonly CatalogFragmentV1[]): CatalogV1 => { |
| 1654 | const catalog = emptyCatalog(); | 1663 | const catalog = emptyCatalog(); |
| 1655 | const seenByCollection = new Map<string, string>(); | 1664 | const seenByCollection = new Map<string, string>(); |
| @@ -20,8 +20,9 @@ import { · 19 unmodified lines | |||
| 20 | } from "./local-source-artifacts"; | 20 | } from "./local-source-artifacts"; |
| 21 | import type { ResolvedLocalWorkspaceContext } from "./local-config"; | 21 | import type { ResolvedLocalWorkspaceContext } from "./local-config"; |
| 22 | import { | 22 | import { |
| 23 | createGraphqlCatalogSnapshot, | 23 | createCatalogImportMetadata, |
| 24 | createOpenApiCatalogSnapshot, | 24 | createGraphqlCatalogFragment, |
| 25 | createOpenApiCatalogFragment, | ||
| 25 | } from "./source-catalog-snapshot"; | 26 | } from "./source-catalog-snapshot"; |
| 26 | 27 | ||
| 27 | const makeContext = (): ResolvedLocalWorkspaceContext => { | 28 | const makeContext = (): ResolvedLocalWorkspaceContext => { |
| @@ -33,6 +34,7 @@ const makeContext = (): ResolvedLocalWorkspaceContext => { · 5 unmodified lines | |||
| 33 | configDirectory: join(workspaceRoot, ".executor"), | 34 | configDirectory: join(workspaceRoot, ".executor"), |
| 34 | projectConfigPath: join(workspaceRoot, ".executor", "executor.jsonc"), | 35 | projectConfigPath: join(workspaceRoot, ".executor", "executor.jsonc"), |
| 35 | homeConfigPath: join(workspaceRoot, ".executor-home.jsonc"), | 36 | homeConfigPath: join(workspaceRoot, ".executor-home.jsonc"), |
| 37 | homeStateDirectory: join(workspaceRoot, ".executor-home-state"), | ||
| 36 | artifactsDirectory: join(workspaceRoot, ".executor", "artifacts"), | 38 | artifactsDirectory: join(workspaceRoot, ".executor", "artifacts"), |
| 37 | stateDirectory: join(workspaceRoot, ".executor", "state"), | 39 | stateDirectory: join(workspaceRoot, ".executor", "state"), |
| 38 | }; | 40 | }; |
| @@ -63,7 +65,7 @@ const makeSource = (): Source => ({ · 24 unmodified lines | |||
| 63 | 65 | ||
| 64 | const makeArtifact = () => { | 66 | const makeArtifact = () => { |
| 65 | const source = makeSource(); | 67 | const source = makeSource(); |
| 66 | const snapshot = createOpenApiCatalogSnapshot({ | 68 | const fragment = createOpenApiCatalogFragment({ |
| 67 | source, | 69 | source, |
| 68 | documents: [{ | 70 | documents: [{ |
| 69 | documentKind: "openapi", | 71 | documentKind: "openapi", |
| @@ -77,7 +79,11 @@ const makeArtifact = () => { · 7 unmodified lines | |||
| 77 | return buildLocalSourceArtifact({ | 79 | return buildLocalSourceArtifact({ |
| 78 | source, | 80 | source, |
| 79 | syncResult: { | 81 | syncResult: { |
| 80 | snapshot, | 82 | fragment, |
| 83 | importMetadata: createCatalogImportMetadata({ | ||
| 84 | source, | ||
| 85 | adapterKey: "openapi", | ||
| 86 | }), | ||
| 81 | sourceHash: source.sourceHash, | 87 | sourceHash: source.sourceHash, |
| 82 | }, | 88 | }, |
| 83 | }); | 89 | }); |
| @@ -92,7 +98,7 @@ const makeGraphqlArtifact = () => { · 8 unmodified lines | |||
| 92 | defaultHeaders: null, | 98 | defaultHeaders: null, |
| 93 | }, | 99 | }, |
| 94 | }; | 100 | }; |
| 95 | const snapshot = createGraphqlCatalogSnapshot({ | 101 | const fragment = createGraphqlCatalogFragment({ |
| 96 | source, | 102 | source, |
| 97 | documents: [{ | 103 | documents: [{ |
| 98 | documentKind: "graphql_introspection", | 104 | documentKind: "graphql_introspection", |
| @@ -128,7 +134,11 @@ const makeGraphqlArtifact = () => { · 29 unmodified lines | |||
| 128 | return buildLocalSourceArtifact({ | 134 | return buildLocalSourceArtifact({ |
| 129 | source, | 135 | source, |
| 130 | syncResult: { | 136 | syncResult: { |
| 131 | snapshot, | 137 | fragment, |
| 138 | importMetadata: createCatalogImportMetadata({ | ||
| 139 | source, | ||
| 140 | adapterKey: "graphql", | ||
| 141 | }), | ||
| 132 | sourceHash: source.sourceHash, | 142 | sourceHash: source.sourceHash, |
| 133 | }, | 143 | }, |
| 134 | }); | 144 | }); |
| @@ -16,10 +16,15 @@ import * as Schema from "effect/Schema"; · 15 unmodified lines | |||
| 16 | import { decodeCatalogSnapshotV1 } from "../ir/catalog"; | 16 | import { decodeCatalogSnapshotV1 } from "../ir/catalog"; |
| 17 | import { | 17 | import { |
| 18 | CatalogSnapshotV1Schema, | 18 | CatalogSnapshotV1Schema, |
| 19 | type CatalogSnapshotV1, | ||
| 19 | type NativeBlob, | 20 | type NativeBlob, |
| 20 | type SourceDocument, | 21 | type SourceDocument, |
| 21 | } from "../ir/model"; | 22 | } from "../ir/model"; |
| 22 | import type { SourceCatalogSyncResult } from "./source-catalog-support"; | 23 | import { |
| 24 | contentHash, | ||
| 25 | snapshotFromSourceCatalogSyncResult, | ||
| 26 | type SourceCatalogSyncResult, | ||
| 27 | } from "./source-catalog-support"; | ||
| 23 | import type { ResolvedLocalWorkspaceContext } from "./local-config"; | 28 | import type { ResolvedLocalWorkspaceContext } from "./local-config"; |
| 24 | import { | 29 | import { |
| 25 | LocalFileSystemError, | 30 | LocalFileSystemError, |
| @@ -30,8 +35,6 @@ import { · 4 unmodified lines | |||
| 30 | createSourceCatalogRevisionRecord, | 35 | createSourceCatalogRevisionRecord, |
| 31 | stableSourceCatalogId, | 36 | stableSourceCatalogId, |
| 32 | } from "./source-definitions"; | 37 | } from "./source-definitions"; |
| 33 | import { contentHash } from "./source-catalog-support"; | ||
| 34 | |||
| 35 | const LOCAL_SOURCE_ARTIFACT_VERSION = 3 as const; | 38 | const LOCAL_SOURCE_ARTIFACT_VERSION = 3 as const; |
| 36 | 39 | ||
| 37 | export const LocalSourceArtifactSchema = Schema.Struct({ | 40 | export const LocalSourceArtifactSchema = Schema.Struct({ |
| @@ -155,10 +158,10 @@ const hydrateArtifactSourceDocuments = (input: { · 117 unmodified lines | |||
| 155 | return nextArtifact; | 158 | return nextArtifact; |
| 156 | }; | 159 | }; |
| 157 | 160 | ||
| 158 | const snapshotHash = (snapshot: SourceCatalogSyncResult["snapshot"]): string => | 161 | const snapshotHash = (snapshot: CatalogSnapshotV1): string => |
| 159 | contentHash(JSON.stringify(snapshot)); | 162 | contentHash(JSON.stringify(snapshot)); |
| 160 | 163 | ||
| 161 | const importMetadataHash = (snapshot: SourceCatalogSyncResult["snapshot"]): string => | 164 | const importMetadataHash = (snapshot: { import: SourceCatalogSyncResult["importMetadata"] }): string => |
| 162 | contentHash(JSON.stringify(snapshot.import)); | 165 | contentHash(JSON.stringify(snapshot.import)); |
| 163 | 166 | ||
| 164 | export const buildLocalSourceArtifact = (input: { | 167 | export const buildLocalSourceArtifact = (input: { |
| @@ -167,13 +170,14 @@ export const buildLocalSourceArtifact = (input: { · 2 unmodified lines | |||
| 167 | }): LocalSourceArtifact => { | 170 | }): LocalSourceArtifact => { |
| 168 | const catalogId: SourceCatalogId = stableSourceCatalogId(input.source); | 171 | const catalogId: SourceCatalogId = stableSourceCatalogId(input.source); |
| 169 | const generatedAt = Date.now(); | 172 | const generatedAt = Date.now(); |
| 170 | const importHash = importMetadataHash(input.syncResult.snapshot); | 173 | const snapshot = snapshotFromSourceCatalogSyncResult(input.syncResult); |
| 171 | const hash = snapshotHash(input.syncResult.snapshot); | 174 | const importHash = importMetadataHash(snapshot); |
| 175 | const hash = snapshotHash(snapshot); | ||
| 172 | const revision = createSourceCatalogRevisionRecord({ | 176 | const revision = createSourceCatalogRevisionRecord({ |
| 173 | source: input.source, | 177 | source: input.source, |
| 174 | catalogId, | 178 | catalogId, |
| 175 | revisionNumber: 1, | 179 | revisionNumber: 1, |
| 176 | importMetadataJson: JSON.stringify(input.syncResult.snapshot.import), | 180 | importMetadataJson: JSON.stringify(snapshot.import), |
| 177 | importMetadataHash: importHash, | 181 | importMetadataHash: importHash, |
| 178 | snapshotHash: hash, | 182 | snapshotHash: hash, |
| 179 | }); | 183 | }); |
| @@ -184,7 +188,7 @@ export const buildLocalSourceArtifact = (input: { · 4 unmodified lines | |||
| 184 | catalogId, | 188 | catalogId, |
| 185 | generatedAt, | 189 | generatedAt, |
| 186 | revision, | 190 | revision, |
| 187 | snapshot: input.syncResult.snapshot, | 191 | snapshot, |
| 188 | }; | 192 | }; |
| 189 | }; | 193 | }; |
| 190 | 194 | ||
| @@ -6,6 +6,7 @@ import { SourceIdSchema } from "#schema"; · 5 unmodified lines | |||
| 6 | import * as Effect from "effect/Effect"; | 6 | import * as Effect from "effect/Effect"; |
| 7 | 7 | ||
| 8 | import { googleDiscoverySourceAdapter } from "./google-discovery"; | 8 | import { googleDiscoverySourceAdapter } from "./google-discovery"; |
| 9 | import { snapshotFromSourceCatalogSyncResult } from "../source-catalog-support"; | ||
| 9 | import { createSourceFromPayload } from "../source-definitions"; | 10 | import { createSourceFromPayload } from "../source-definitions"; |
| 10 | 11 | ||
| 11 | const fetchLiveDiscoveryDocument = async (): Promise<string> => { | 12 | const fetchLiveDiscoveryDocument = async (): Promise<string> => { |
| @@ -102,12 +103,14 @@ describe("google discovery source adapter", () => { · 90 unmodified lines | |||
| 102 | }), | 103 | }), |
| 103 | }), | 104 | }), |
| 104 | ); | 105 | ); |
| 106 | const snapshot = snapshotFromSourceCatalogSyncResult(syncResult); | ||
| 105 | 107 | ||
| 106 | expect(Object.values(syncResult.snapshot.catalog.documents)[0]?.kind).toBe("google-discovery"); | 108 | expect(syncResult.fragment.version).toBe("ir.v1.fragment"); |
| 107 | expect(Object.keys(syncResult.snapshot.catalog.resources)).not.toHaveLength(0); | 109 | expect(Object.values(snapshot.catalog.documents)[0]?.kind).toBe("google-discovery"); |
| 108 | expect(Object.keys(syncResult.snapshot.catalog.capabilities).length).toBeGreaterThan(50); | 110 | expect(Object.keys(snapshot.catalog.resources)).not.toHaveLength(0); |
| 111 | expect(Object.keys(snapshot.catalog.capabilities).length).toBeGreaterThan(50); | ||
| 109 | expect( | 112 | expect( |
| 110 | Object.values(syncResult.snapshot.catalog.capabilities).some((capability) => | 113 | Object.values(snapshot.catalog.capabilities).some((capability) => |
| 111 | capability.surface.toolPath.join(".") === "google.sheets.spreadsheets.values.get" | 114 | capability.surface.toolPath.join(".") === "google.sheets.spreadsheets.values.get" |
| 112 | ), | 115 | ), |
| 113 | ).toBe(true); | 116 | ).toBe(true); |
| @@ -15,9 +15,11 @@ import * as Effect from "effect/Effect"; · 14 unmodified lines | |||
| 15 | import * as Schema from "effect/Schema"; | 15 | import * as Schema from "effect/Schema"; |
| 16 | 16 | ||
| 17 | import { | 17 | import { |
| 18 | createGoogleDiscoveryCatalogSnapshot, | 18 | createCatalogImportMetadata, |
| 19 | createGoogleDiscoveryCatalogFragment, | ||
| 19 | type GoogleDiscoveryCatalogOperationInput, | 20 | type GoogleDiscoveryCatalogOperationInput, |
| 20 | } from "../source-catalog-snapshot"; | 21 | } from "../source-catalog-snapshot"; |
| 22 | import { createSourceCatalogSyncResult } from "../source-catalog-support"; | ||
| 21 | import type { SourceAdapter } from "./types"; | 23 | import type { SourceAdapter } from "./types"; |
| 22 | import { | 24 | import { |
| 23 | ConnectHttpAuthSchema, | 25 | ConnectHttpAuthSchema, |
| @@ -336,8 +338,8 @@ export const googleDiscoverySourceAdapter: SourceAdapter = { · 312 unmodified lines | |||
| 336 | const definitions = compileGoogleDiscoveryToolDefinitions(manifest); | 338 | const definitions = compileGoogleDiscoveryToolDefinitions(manifest); |
| 337 | const now = Date.now(); | 339 | const now = Date.now(); |
| 338 | 340 | ||
| 339 | return { | 341 | return createSourceCatalogSyncResult({ |
| 340 | snapshot: createGoogleDiscoveryCatalogSnapshot({ | 342 | fragment: createGoogleDiscoveryCatalogFragment({ |
| 341 | source, | 343 | source, |
| 342 | documents: [{ | 344 | documents: [{ |
| 343 | documentKind: "google_discovery", | 345 | documentKind: "google_discovery", |
| @@ -352,8 +354,12 @@ export const googleDiscoverySourceAdapter: SourceAdapter = { · 8 unmodified lines | |||
| 352 | }) | 354 | }) |
| 353 | ), | 355 | ), |
| 354 | }), | 356 | }), |
| 357 | importMetadata: createCatalogImportMetadata({ | ||
| 358 | source, | ||
| 359 | adapterKey: "google_discovery", | ||
| 360 | }), | ||
| 355 | sourceHash: manifest.sourceHash, | 361 | sourceHash: manifest.sourceHash, |
| 356 | }; | 362 | }); |
| 357 | }), | 363 | }), |
| 358 | getOauth2SetupConfig: ({ source }) => googleDiscoveryOauth2SetupConfig(source), | 364 | getOauth2SetupConfig: ({ source }) => googleDiscoveryOauth2SetupConfig(source), |
| 359 | normalizeOauthClientInput: (input) => | 365 | normalizeOauthClientInput: (input) => |
| @@ -16,9 +16,11 @@ import * as Effect from "effect/Effect"; · 15 unmodified lines | |||
| 16 | import * as Schema from "effect/Schema"; | 16 | import * as Schema from "effect/Schema"; |
| 17 | 17 | ||
| 18 | import { | 18 | import { |
| 19 | createGraphqlCatalogSnapshot, | 19 | createCatalogImportMetadata, |
| 20 | createGraphqlCatalogFragment, | ||
| 20 | type GraphqlCatalogOperationInput, | 21 | type GraphqlCatalogOperationInput, |
| 21 | } from "../source-catalog-snapshot"; | 22 | } from "../source-catalog-snapshot"; |
| 23 | import { createSourceCatalogSyncResult } from "../source-catalog-support"; | ||
| 22 | import type { SourceAdapter } from "./types"; | 24 | import type { SourceAdapter } from "./types"; |
| 23 | import { | 25 | import { |
| 24 | ConnectHttpAuthSchema, | 26 | ConnectHttpAuthSchema, |
| @@ -327,8 +329,8 @@ export const graphqlSourceAdapter: SourceAdapter = { · 302 unmodified lines | |||
| 327 | }), | 329 | }), |
| 328 | ); | 330 | ); |
| 329 | const now = Date.now(); | 331 | const now = Date.now(); |
| 330 | const snapshot = yield* Effect.sync(() => | 332 | const fragment = yield* Effect.sync(() => |
| 331 | createGraphqlCatalogSnapshot({ | 333 | createGraphqlCatalogFragment({ |
| 332 | source, | 334 | source, |
| 333 | documents: [{ | 335 | documents: [{ |
| 334 | documentKind: "graphql_introspection", | 336 | documentKind: "graphql_introspection", |
| @@ -347,10 +349,14 @@ export const graphqlSourceAdapter: SourceAdapter = { · 12 unmodified lines | |||
| 347 | }), | 349 | }), |
| 348 | ); | 350 | ); |
| 349 | 351 | ||
| 350 | return { | 352 | return createSourceCatalogSyncResult({ |
| 351 | snapshot, | 353 | fragment, |
| 354 | importMetadata: createCatalogImportMetadata({ | ||
| 355 | source, | ||
| 356 | adapterKey: "graphql", | ||
| 357 | }), | ||
| 352 | sourceHash: manifest.sourceHash, | 358 | sourceHash: manifest.sourceHash, |
| 353 | }; | 359 | }); |
| 354 | }).pipe( | 360 | }).pipe( |
| 355 | Effect.withSpan("graphql.syncCatalog", { | 361 | Effect.withSpan("graphql.syncCatalog", { |
| 356 | attributes: { | 362 | attributes: { |
| @@ -2,6 +2,8 @@ import * as Effect from "effect/Effect"; · 1 unmodified line | |||
| 2 | import * as Schema from "effect/Schema"; | 2 | import * as Schema from "effect/Schema"; |
| 3 | import type { Source } from "#schema"; | 3 | import type { Source } from "#schema"; |
| 4 | 4 | ||
| 5 | import { createCatalogImportMetadata } from "../source-catalog-snapshot"; | ||
| 6 | import { createSourceCatalogSyncResult } from "../source-catalog-support"; | ||
| 5 | import type { SourceAdapter } from "./types"; | 7 | import type { SourceAdapter } from "./types"; |
| 6 | import { | 8 | import { |
| 7 | decodeBindingConfig, | 9 | decodeBindingConfig, |
| @@ -99,28 +101,19 @@ export const internalSourceAdapter: SourceAdapter = { · 91 unmodified lines | |||
| 99 | }; | 101 | }; |
| 100 | }), | 102 | }), |
| 101 | shouldAutoProbe: () => false, | 103 | shouldAutoProbe: () => false, |
| 102 | syncCatalog: () => Effect.succeed({ | 104 | syncCatalog: ({ source }) => |
| 103 | snapshot: { | 105 | Effect.succeed(createSourceCatalogSyncResult({ |
| 104 | version: "ir.v1.snapshot", | 106 | fragment: { |
| 105 | import: { | 107 | version: "ir.v1.fragment", |
| 106 | sourceKind: "custom", | 108 | }, |
| 107 | adapterKey: "internal", | 109 | importMetadata: { |
| 110 | ...createCatalogImportMetadata({ | ||
| 111 | source, | ||
| 112 | adapterKey: "internal", | ||
| 113 | }), | ||
| 108 | importerVersion: "ir.v1.internal", | 114 | importerVersion: "ir.v1.internal", |
| 109 | importedAt: new Date().toISOString(), | ||
| 110 | sourceConfigHash: "internal", | 115 | sourceConfigHash: "internal", |
| 111 | }, | 116 | }, |
| 112 | catalog: { | 117 | sourceHash: null, |
| 113 | version: "ir.v1", | 118 | })), |
| 114 | documents: {}, | ||
| 115 | resources: {}, | ||
| 116 | scopes: {}, | ||
| 117 | symbols: {}, | ||
| 118 | capabilities: {}, | ||
| 119 | executables: {}, | ||
| 120 | responseSets: {}, | ||
| 121 | diagnostics: {}, | ||
| 122 | }, | ||
| 123 | }, | ||
| 124 | sourceHash: null, | ||
| 125 | }), | ||
| 126 | }; | 119 | }; |
| @@ -26,6 +26,7 @@ import { · 25 unmodified lines | |||
| 26 | expandCatalogToolByPath, | 26 | expandCatalogToolByPath, |
| 27 | type LoadedSourceCatalog, | 27 | type LoadedSourceCatalog, |
| 28 | } from "../source-catalog-runtime"; | 28 | } from "../source-catalog-runtime"; |
| 29 | import { snapshotFromSourceCatalogSyncResult } from "../source-catalog-support"; | ||
| 29 | import { createSourceFromPayload } from "../source-definitions"; | 30 | import { createSourceFromPayload } from "../source-definitions"; |
| 30 | import { mcpSourceAdapter } from "./mcp"; | 31 | import { mcpSourceAdapter } from "./mcp"; |
| 31 | 32 | ||
| @@ -252,13 +253,14 @@ describe("mcp source adapter", () => { · 220 unmodified lines | |||
| 252 | cookies: {}, | 253 | cookies: {}, |
| 253 | bodyValues: {}, | 254 | bodyValues: {}, |
| 254 | expiresAt: null, | 255 | expiresAt: null, |
| 255 | refreshAfter: null, | 256 | refreshAfter: null, |
| 256 | }), | 257 | }), |
| 257 | }); | 258 | }); |
| 259 | const snapshot = snapshotFromSourceCatalogSyncResult(syncResult); | ||
| 258 | 260 | ||
| 259 | const capability = Object.values(syncResult.snapshot.catalog.capabilities)[0]!; | 261 | const capability = Object.values(snapshot.catalog.capabilities)[0]!; |
| 260 | const executable = Object.values(syncResult.snapshot.catalog.executables)[0]!; | 262 | const executable = Object.values(snapshot.catalog.executables)[0]!; |
| 261 | const document = Object.values(syncResult.snapshot.catalog.documents)[0]!; | 263 | const document = Object.values(snapshot.catalog.documents)[0]!; |
| 262 | const rawManifest = document.native?.[0]?.value; | 264 | const rawManifest = document.native?.[0]?.value; |
| 263 | 265 | ||
| 264 | expect(capability.surface.title).toBe("Read File"); | 266 | expect(capability.surface.title).toBe("Read File"); |
| @@ -339,14 +341,15 @@ describe("mcp source adapter", () => { · 74 unmodified lines | |||
| 339 | cookies: {}, | 341 | cookies: {}, |
| 340 | bodyValues: {}, | 342 | bodyValues: {}, |
| 341 | expiresAt: null, | 343 | expiresAt: null, |
| 342 | refreshAfter: null, | 344 | refreshAfter: null, |
| 343 | }), | 345 | }), |
| 344 | }); | 346 | }); |
| 347 | const snapshot = snapshotFromSourceCatalogSyncResult(syncResult); | ||
| 345 | 348 | ||
| 346 | const tool = yield* expandCatalogToolByPath({ | 349 | const tool = yield* expandCatalogToolByPath({ |
| 347 | catalogs: [makeLoadedCatalog({ | 350 | catalogs: [makeLoadedCatalog({ |
| 348 | source, | 351 | source, |
| 349 | snapshot: syncResult.snapshot, | 352 | snapshot, |
| 350 | })], | 353 | })], |
| 351 | path: "mcp.demo.read_file", | 354 | path: "mcp.demo.read_file", |
| 352 | }); | 355 | }); |
| @@ -19,11 +19,13 @@ import * as Effect from "effect/Effect"; · 18 unmodified lines | |||
| 19 | import * as Schema from "effect/Schema"; | 19 | import * as Schema from "effect/Schema"; |
| 20 | 20 | ||
| 21 | import { | 21 | import { |
| 22 | createMcpCatalogSnapshot, | 22 | createCatalogImportMetadata, |
| 23 | createMcpCatalogFragment, | ||
| 23 | type McpCatalogOperationInput, | 24 | type McpCatalogOperationInput, |
| 24 | } from "../source-catalog-snapshot"; | 25 | } from "../source-catalog-snapshot"; |
| 25 | import { | 26 | import { |
| 26 | contentHash, | 27 | contentHash, |
| 28 | createSourceCatalogSyncResult, | ||
| 27 | type SourceCatalogSyncResult, | 29 | type SourceCatalogSyncResult, |
| 28 | } from "../source-catalog-support"; | 30 | } from "../source-catalog-support"; |
| 29 | import { namespaceFromSourceName } from "../source-names"; | 31 | import { namespaceFromSourceName } from "../source-names"; |
| @@ -160,8 +162,8 @@ export const catalogSyncResultFromMcpManifest = (input: { · 130 unmodified lines | |||
| 160 | const manifestJson = JSON.stringify(input.manifest); | 162 | const manifestJson = JSON.stringify(input.manifest); |
| 161 | const manifestHash = contentHash(manifestJson); | 163 | const manifestHash = contentHash(manifestJson); |
| 162 | 164 | ||
| 163 | return { | 165 | return createSourceCatalogSyncResult({ |
| 164 | snapshot: createMcpCatalogSnapshot({ | 166 | fragment: createMcpCatalogFragment({ |
| 165 | source: input.source, | 167 | source: input.source, |
| 166 | documents: [{ | 168 | documents: [{ |
| 167 | documentKind: "mcp_manifest", | 169 | documentKind: "mcp_manifest", |
| @@ -176,8 +178,12 @@ export const catalogSyncResultFromMcpManifest = (input: { · 8 unmodified lines | |||
| 176 | }) | 178 | }) |
| 177 | ), | 179 | ), |
| 178 | }), | 180 | }), |
| 181 | importMetadata: createCatalogImportMetadata({ | ||
| 182 | source: input.source, | ||
| 183 | adapterKey: "mcp", | ||
| 184 | }), | ||
| 179 | sourceHash: manifestHash, | 185 | sourceHash: manifestHash, |
| 180 | }; | 186 | }); |
| 181 | }; | 187 | }; |
| 182 | 188 | ||
| 183 | export const mcpSourceAdapter: SourceAdapter = { | 189 | export const mcpSourceAdapter: SourceAdapter = { |
| @@ -20,9 +20,11 @@ import * as Effect from "effect/Effect"; · 19 unmodified lines | |||
| 20 | import * as Schema from "effect/Schema"; | 20 | import * as Schema from "effect/Schema"; |
| 21 | 21 | ||
| 22 | import { | 22 | import { |
| 23 | createOpenApiCatalogSnapshot, | 23 | createCatalogImportMetadata, |
| 24 | createOpenApiCatalogFragment, | ||
| 24 | type OpenApiCatalogOperationInput, | 25 | type OpenApiCatalogOperationInput, |
| 25 | } from "../source-catalog-snapshot"; | 26 | } from "../source-catalog-snapshot"; |
| 27 | import { createSourceCatalogSyncResult } from "../source-catalog-support"; | ||
| 26 | import type { SourceAdapter } from "./types"; | 28 | import type { SourceAdapter } from "./types"; |
| 27 | import { | 29 | import { |
| 28 | ConnectHttpAuthSchema, | 30 | ConnectHttpAuthSchema, |
| @@ -299,8 +301,8 @@ export const openApiSourceAdapter: SourceAdapter = { · 270 unmodified lines | |||
| 299 | const definitions = compileOpenApiToolDefinitions(manifest); | 301 | const definitions = compileOpenApiToolDefinitions(manifest); |
| 300 | const now = Date.now(); | 302 | const now = Date.now(); |
| 301 | 303 | ||
| 302 | return { | 304 | return createSourceCatalogSyncResult({ |
| 303 | snapshot: createOpenApiCatalogSnapshot({ | 305 | fragment: createOpenApiCatalogFragment({ |
| 304 | source, | 306 | source, |
| 305 | documents: [{ | 307 | documents: [{ |
| 306 | documentKind: "openapi", | 308 | documentKind: "openapi", |
| @@ -314,7 +316,11 @@ export const openApiSourceAdapter: SourceAdapter = { · 7 unmodified lines | |||
| 314 | refHintTable: manifest.refHintTable, | 316 | refHintTable: manifest.refHintTable, |
| 315 | })), | 317 | })), |
| 316 | }), | 318 | }), |
| 319 | importMetadata: createCatalogImportMetadata({ | ||
| 320 | source, | ||
| 321 | adapterKey: "openapi", | ||
| 322 | }), | ||
| 317 | sourceHash: manifest.sourceHash, | 323 | sourceHash: manifest.sourceHash, |
| 318 | }; | 324 | }); |
| 319 | }), | 325 | }), |
| 320 | }; | 326 | }; |
| @@ -14,8 +14,7 @@ import type { · 13 unmodified lines | |||
| 14 | import type { Source } from "#schema"; | 14 | import type { Source } from "#schema"; |
| 15 | 15 | ||
| 16 | import { | 16 | import { |
| 17 | createCatalogSnapshotV1, | 17 | createCatalogSnapshotV1FromFragments, |
| 18 | createEmptyCatalogV1, | ||
| 19 | } from "../ir/catalog"; | 18 | } from "../ir/catalog"; |
| 20 | import { | 19 | import { |
| 21 | CapabilityIdSchema, | 20 | CapabilityIdSchema, |
| @@ -36,8 +35,8 @@ import { · 14 unmodified lines | |||
| 36 | import type { | 35 | import type { |
| 37 | AuthRequirement, | 36 | AuthRequirement, |
| 38 | Capability, | 37 | Capability, |
| 38 | CatalogFragmentV1, | ||
| 39 | CatalogSnapshotV1, | 39 | CatalogSnapshotV1, |
| 40 | CatalogV1, | ||
| 41 | ContentSpec, | 40 | ContentSpec, |
| 42 | DocumentationBlock, | 41 | DocumentationBlock, |
| 43 | EffectKind, | 42 | EffectKind, |
| @@ -63,6 +62,18 @@ import { namespaceFromSourceName } from "./source-names"; · 19 unmodified lines | |||
| 63 | 62 | ||
| 64 | type JsonSchema = boolean | Record<string, unknown>; | 63 | type JsonSchema = boolean | Record<string, unknown>; |
| 65 | 64 | ||
| 65 | type CatalogFragmentBuilder = { | ||
| 66 | version: "ir.v1.fragment"; | ||
| 67 | documents: NonNullable<CatalogFragmentV1["documents"]>; | ||
| 68 | resources: NonNullable<CatalogFragmentV1["resources"]>; | ||
| 69 | scopes: NonNullable<CatalogFragmentV1["scopes"]>; | ||
| 70 | symbols: NonNullable<CatalogFragmentV1["symbols"]>; | ||
| 71 | capabilities: NonNullable<CatalogFragmentV1["capabilities"]>; | ||
| 72 | executables: NonNullable<CatalogFragmentV1["executables"]>; | ||
| 73 | responseSets: NonNullable<CatalogFragmentV1["responseSets"]>; | ||
| 74 | diagnostics: NonNullable<CatalogFragmentV1["diagnostics"]>; | ||
| 75 | }; | ||
| 76 | |||
| 66 | export type CatalogSourceDocumentInput = { | 77 | export type CatalogSourceDocumentInput = { |
| 67 | documentKind: string; | 78 | documentKind: string; |
| 68 | documentKey: string; | 79 | documentKey: string; |
| @@ -262,8 +273,37 @@ const importMetadataFor = (input: { · 193 unmodified lines | |||
| 262 | }), | 273 | }), |
| 263 | }); | 274 | }); |
| 264 | 275 | ||
| 276 | export const createCatalogImportMetadata = (input: { | ||
| 277 | source: Source; | ||
| 278 | adapterKey: string; | ||
| 279 | }) => importMetadataFor(input); | ||
| 280 | |||
| 281 | const createEmptyCatalogFragment = (): CatalogFragmentBuilder => ({ | ||
| 282 | version: "ir.v1.fragment", | ||
| 283 | documents: {}, | ||
| 284 | resources: {}, | ||
| 285 | scopes: {}, | ||
| 286 | symbols: {}, | ||
| 287 | capabilities: {}, | ||
| 288 | executables: {}, | ||
| 289 | responseSets: {}, | ||
| 290 | diagnostics: {}, | ||
| 291 | }); | ||
| 292 | |||
| 293 | const finalizeCatalogFragment = (fragment: CatalogFragmentBuilder): CatalogFragmentV1 => ({ | ||
| 294 | version: "ir.v1.fragment", | ||
| 295 | ...(Object.keys(fragment.documents).length > 0 ? { documents: fragment.documents } : {}), | ||
| 296 | ...(Object.keys(fragment.resources).length > 0 ? { resources: fragment.resources } : {}), | ||
| 297 | ...(Object.keys(fragment.scopes).length > 0 ? { scopes: fragment.scopes } : {}), | ||
| 298 | ...(Object.keys(fragment.symbols).length > 0 ? { symbols: fragment.symbols } : {}), | ||
| 299 | ...(Object.keys(fragment.capabilities).length > 0 ? { capabilities: fragment.capabilities } : {}), | ||
| 300 | ...(Object.keys(fragment.executables).length > 0 ? { executables: fragment.executables } : {}), | ||
| 301 | ...(Object.keys(fragment.responseSets).length > 0 ? { responseSets: fragment.responseSets } : {}), | ||
| 302 | ...(Object.keys(fragment.diagnostics).length > 0 ? { diagnostics: fragment.diagnostics } : {}), | ||
| 303 | }); | ||
| 304 | |||
| 265 | const addDiagnostic = ( | 305 | const addDiagnostic = ( |
| 266 | catalog: CatalogV1, | 306 | catalog: CatalogFragmentBuilder, |
| 267 | input: Omit<ImportDiagnostic, "id">, | 307 | input: Omit<ImportDiagnostic, "id">, |
| 268 | ) => { | 308 | ) => { |
| 269 | const id = DiagnosticIdSchema.make(`diag_${stableHash(input)}`); | 309 | const id = DiagnosticIdSchema.make(`diag_${stableHash(input)}`); |
| @@ -310,7 +350,7 @@ const docsFrom = (input: { · 40 unmodified lines | |||
| 310 | }; | 350 | }; |
| 311 | 351 | ||
| 312 | const createJsonSchemaImporter = (input: { | 352 | const createJsonSchemaImporter = (input: { |
| 313 | catalog: CatalogV1; | 353 | catalog: CatalogFragmentBuilder; |
| 314 | source: Source; | 354 | source: Source; |
| 315 | resourceId: ReturnType<typeof ResourceIdSchema.make>; | 355 | resourceId: ReturnType<typeof ResourceIdSchema.make>; |
| 316 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 356 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| @@ -800,7 +840,7 @@ const createJsonSchemaImporter = (input: { · 483 unmodified lines | |||
| 800 | }; | 840 | }; |
| 801 | 841 | ||
| 802 | const exampleSymbolFromValue = (input: { | 842 | const exampleSymbolFromValue = (input: { |
| 803 | catalog: CatalogV1; | 843 | catalog: CatalogFragmentBuilder; |
| 804 | source: Source; | 844 | source: Source; |
| 805 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 845 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 806 | pointer: string; | 846 | pointer: string; |
| @@ -886,7 +926,7 @@ const preferredResponseContentTypes = ( · 79 unmodified lines | |||
| 886 | }; | 926 | }; |
| 887 | 927 | ||
| 888 | const createServiceScope = (input: { | 928 | const createServiceScope = (input: { |
| 889 | catalog: CatalogV1; | 929 | catalog: CatalogFragmentBuilder; |
| 890 | source: Source; | 930 | source: Source; |
| 891 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 931 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 892 | defaults?: Scope["defaults"]; | 932 | defaults?: Scope["defaults"]; |
| @@ -936,7 +976,7 @@ const googleDiscoveryServerSpecs = ( · 43 unmodified lines | |||
| 936 | }; | 976 | }; |
| 937 | 977 | ||
| 938 | const createOperationScope = (input: { | 978 | const createOperationScope = (input: { |
| 939 | catalog: CatalogV1; | 979 | catalog: CatalogFragmentBuilder; |
| 940 | source: Source; | 980 | source: Source; |
| 941 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 981 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 942 | parentScopeId: ReturnType<typeof ScopeIdSchema.make>; | 982 | parentScopeId: ReturnType<typeof ScopeIdSchema.make>; |
| @@ -967,7 +1007,7 @@ const createOperationScope = (input: { · 24 unmodified lines | |||
| 967 | }; | 1007 | }; |
| 968 | 1008 | ||
| 969 | const responseSetFromSingleResponse = (input: { | 1009 | const responseSetFromSingleResponse = (input: { |
| 970 | catalog: CatalogV1; | 1010 | catalog: CatalogFragmentBuilder; |
| 971 | responseId: ReturnType<typeof ResponseSymbolIdSchema.make>; | 1011 | responseId: ReturnType<typeof ResponseSymbolIdSchema.make>; |
| 972 | provenance: ProvenanceRef[]; | 1012 | provenance: ProvenanceRef[]; |
| 973 | traits?: ResponseSet["variants"][number]["traits"]; | 1013 | traits?: ResponseSet["variants"][number]["traits"]; |
| @@ -993,7 +1033,7 @@ const responseSetFromSingleResponse = (input: { · 19 unmodified lines | |||
| 993 | }; | 1033 | }; |
| 994 | 1034 | ||
| 995 | const responseSetFromVariants = (input: { | 1035 | const responseSetFromVariants = (input: { |
| 996 | catalog: CatalogV1; | 1036 | catalog: CatalogFragmentBuilder; |
| 997 | variants: ResponseSet["variants"]; | 1037 | variants: ResponseSet["variants"]; |
| 998 | provenance: ProvenanceRef[]; | 1038 | provenance: ProvenanceRef[]; |
| 999 | }) => { | 1039 | }) => { |
| @@ -1038,7 +1078,7 @@ const statusMatchFromHttpStatusCode = ( · 38 unmodified lines | |||
| 1038 | }; | 1078 | }; |
| 1039 | 1079 | ||
| 1040 | const ensureOpenApiSecuritySchemeSymbol = (input: { | 1080 | const ensureOpenApiSecuritySchemeSymbol = (input: { |
| 1041 | catalog: CatalogV1; | 1081 | catalog: CatalogFragmentBuilder; |
| 1042 | source: Source; | 1082 | source: Source; |
| 1043 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 1083 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 1044 | schemeName: string; | 1084 | schemeName: string; |
| @@ -1147,7 +1187,7 @@ const ensureOpenApiSecuritySchemeSymbol = (input: { · 102 unmodified lines | |||
| 1147 | }; | 1187 | }; |
| 1148 | 1188 | ||
| 1149 | const openApiAuthRequirementToIr = (input: { | 1189 | const openApiAuthRequirementToIr = (input: { |
| 1150 | catalog: CatalogV1; | 1190 | catalog: CatalogFragmentBuilder; |
| 1151 | source: Source; | 1191 | source: Source; |
| 1152 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 1192 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 1153 | authRequirement: OpenApiToolProviderData["authRequirement"] | undefined; | 1193 | authRequirement: OpenApiToolProviderData["authRequirement"] | undefined; |
| @@ -1199,7 +1239,7 @@ const openApiAuthRequirementToIr = (input: { · 45 unmodified lines | |||
| 1199 | }; | 1239 | }; |
| 1200 | 1240 | ||
| 1201 | const contentSpecsFromOpenApiContents = (input: { | 1241 | const contentSpecsFromOpenApiContents = (input: { |
| 1202 | catalog: CatalogV1; | 1242 | catalog: CatalogFragmentBuilder; |
| 1203 | source: Source; | 1243 | source: Source; |
| 1204 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 1244 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 1205 | importer: JsonSchemaImporter; | 1245 | importer: JsonSchemaImporter; |
| @@ -1239,7 +1279,7 @@ const contentSpecsFromOpenApiContents = (input: { · 33 unmodified lines | |||
| 1239 | }); | 1279 | }); |
| 1240 | 1280 | ||
| 1241 | const createOpenApiHeaderSymbol = (input: { | 1281 | const createOpenApiHeaderSymbol = (input: { |
| 1242 | catalog: CatalogV1; | 1282 | catalog: CatalogFragmentBuilder; |
| 1243 | source: Source; | 1283 | source: Source; |
| 1244 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 1284 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 1245 | importer: JsonSchemaImporter; | 1285 | importer: JsonSchemaImporter; |
| @@ -1307,7 +1347,7 @@ const createOpenApiHeaderSymbol = (input: { · 61 unmodified lines | |||
| 1307 | }; | 1347 | }; |
| 1308 | 1348 | ||
| 1309 | const createHttpCapabilityFromOpenApi = (input: { | 1349 | const createHttpCapabilityFromOpenApi = (input: { |
| 1310 | catalog: CatalogV1; | 1350 | catalog: CatalogFragmentBuilder; |
| 1311 | source: Source; | 1351 | source: Source; |
| 1312 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 1352 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 1313 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; | 1353 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; |
| @@ -1714,7 +1754,7 @@ const createHttpCapabilityFromOpenApi = (input: { · 400 unmodified lines | |||
| 1714 | }; | 1754 | }; |
| 1715 | 1755 | ||
| 1716 | const createHttpCapabilityFromGoogleDiscovery = (input: { | 1756 | const createHttpCapabilityFromGoogleDiscovery = (input: { |
| 1717 | catalog: CatalogV1; | 1757 | catalog: CatalogFragmentBuilder; |
| 1718 | source: Source; | 1758 | source: Source; |
| 1719 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 1759 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 1720 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; | 1760 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; |
| @@ -1927,7 +1967,7 @@ const createHttpCapabilityFromGoogleDiscovery = (input: { · 206 unmodified lines | |||
| 1927 | }; | 1967 | }; |
| 1928 | 1968 | ||
| 1929 | const createGraphqlCapability = (input: { | 1969 | const createGraphqlCapability = (input: { |
| 1930 | catalog: CatalogV1; | 1970 | catalog: CatalogFragmentBuilder; |
| 1931 | source: Source; | 1971 | source: Source; |
| 1932 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 1972 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 1933 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; | 1973 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; |
| @@ -2047,7 +2087,7 @@ const createGraphqlCapability = (input: { · 113 unmodified lines | |||
| 2047 | }; | 2087 | }; |
| 2048 | 2088 | ||
| 2049 | const createMcpCapability = (input: { | 2089 | const createMcpCapability = (input: { |
| 2050 | catalog: CatalogV1; | 2090 | catalog: CatalogFragmentBuilder; |
| 2051 | source: Source; | 2091 | source: Source; |
| 2052 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 2092 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 2053 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; | 2093 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; |
| @@ -2147,19 +2187,18 @@ const createMcpCapability = (input: { · 93 unmodified lines | |||
| 2147 | } satisfies Capability; | 2187 | } satisfies Capability; |
| 2148 | }; | 2188 | }; |
| 2149 | 2189 | ||
| 2150 | const buildCatalogSnapshot = (input: { | 2190 | const buildCatalogFragment = (input: { |
| 2151 | source: Source; | 2191 | source: Source; |
| 2152 | adapterKey: string; | ||
| 2153 | documents: readonly CatalogSourceDocumentInput[]; | 2192 | documents: readonly CatalogSourceDocumentInput[]; |
| 2154 | serviceScopeDefaults?: Scope["defaults"]; | 2193 | serviceScopeDefaults?: Scope["defaults"]; |
| 2155 | registerOperations: (context: { | 2194 | registerOperations: (context: { |
| 2156 | catalog: CatalogV1; | 2195 | catalog: CatalogFragmentBuilder; |
| 2157 | documentId: ReturnType<typeof DocumentIdSchema.make>; | 2196 | documentId: ReturnType<typeof DocumentIdSchema.make>; |
| 2158 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; | 2197 | serviceScopeId: ReturnType<typeof ScopeIdSchema.make>; |
| 2159 | importer: JsonSchemaImporter; | 2198 | importer: JsonSchemaImporter; |
| 2160 | }) => void; | 2199 | }) => void; |
| 2161 | }): CatalogSnapshotV1 => { | 2200 | }): CatalogFragmentV1 => { |
| 2162 | const catalog = createEmptyCatalogV1(); | 2201 | const catalog = createEmptyCatalogFragment(); |
| 2163 | const documents = input.documents.length > 0 | 2202 | const documents = input.documents.length > 0 |
| 2164 | ? input.documents | 2203 | ? input.documents |
| 2165 | : [{ | 2204 | : [{ |
| @@ -2237,19 +2276,14 @@ const buildCatalogSnapshot = (input: { · 71 unmodified lines | |||
| 2237 | }); | 2276 | }); |
| 2238 | importer.finalize(); | 2277 | importer.finalize(); |
| 2239 | 2278 | ||
| 2240 | const snapshot = createCatalogSnapshotV1({ | 2279 | return finalizeCatalogFragment(catalog); |
| 2241 | import: importMetadataFor(input), | ||
| 2242 | catalog, | ||
| 2243 | }); | ||
| 2244 | |||
| 2245 | return snapshot; | ||
| 2246 | }; | 2280 | }; |
| 2247 | 2281 | ||
| 2248 | export const createOpenApiCatalogSnapshot = (input: { | 2282 | export const createOpenApiCatalogFragment = (input: { |
| 2249 | source: Source; | 2283 | source: Source; |
| 2250 | documents: readonly CatalogSourceDocumentInput[]; | 2284 | documents: readonly CatalogSourceDocumentInput[]; |
| 2251 | operations: readonly OpenApiCatalogOperationInput[]; | 2285 | operations: readonly OpenApiCatalogOperationInput[]; |
| 2252 | }): CatalogSnapshotV1 => { | 2286 | }): CatalogFragmentV1 => { |
| 2253 | const rootSchema = (() => { | 2287 | const rootSchema = (() => { |
| 2254 | const primaryDocumentText = input.documents[0]?.contentText; | 2288 | const primaryDocumentText = input.documents[0]?.contentText; |
| 2255 | if (!primaryDocumentText) { | 2289 | if (!primaryDocumentText) { |
| @@ -2263,9 +2297,8 @@ export const createOpenApiCatalogSnapshot = (input: { · 7 unmodified lines | |||
| 2263 | } | 2297 | } |
| 2264 | })(); | 2298 | })(); |
| 2265 | 2299 | ||
| 2266 | return buildCatalogSnapshot({ | 2300 | return buildCatalogFragment({ |
| 2267 | source: input.source, | 2301 | source: input.source, |
| 2268 | adapterKey: "openapi", | ||
| 2269 | documents: input.documents, | 2302 | documents: input.documents, |
| 2270 | serviceScopeDefaults: (() => { | 2303 | serviceScopeDefaults: (() => { |
| 2271 | const documentServers = openApiServerSpecs( | 2304 | const documentServers = openApiServerSpecs( |
| @@ -2292,14 +2325,26 @@ export const createOpenApiCatalogSnapshot = (input: { · 20 unmodified lines | |||
| 2292 | }); | 2325 | }); |
| 2293 | }; | 2326 | }; |
| 2294 | 2327 | ||
| 2295 | export const createGoogleDiscoveryCatalogSnapshot = (input: { | 2328 | export const createOpenApiCatalogSnapshot = (input: { |
| 2296 | source: Source; | 2329 | source: Source; |
| 2297 | documents: readonly CatalogSourceDocumentInput[]; | 2330 | documents: readonly CatalogSourceDocumentInput[]; |
| 2298 | operations: readonly GoogleDiscoveryCatalogOperationInput[]; | 2331 | operations: readonly OpenApiCatalogOperationInput[]; |
| 2299 | }): CatalogSnapshotV1 => | 2332 | }): CatalogSnapshotV1 => |
| 2300 | buildCatalogSnapshot({ | 2333 | createCatalogSnapshotV1FromFragments({ |
| 2334 | import: createCatalogImportMetadata({ | ||
| 2335 | source: input.source, | ||
| 2336 | adapterKey: "openapi", | ||
| 2337 | }), | ||
| 2338 | fragments: [createOpenApiCatalogFragment(input)], | ||
| 2339 | }); | ||
| 2340 | |||
| 2341 | export const createGoogleDiscoveryCatalogFragment = (input: { | ||
| 2342 | source: Source; | ||
| 2343 | documents: readonly CatalogSourceDocumentInput[]; | ||
| 2344 | operations: readonly GoogleDiscoveryCatalogOperationInput[]; | ||
| 2345 | }): CatalogFragmentV1 => | ||
| 2346 | buildCatalogFragment({ | ||
| 2301 | source: input.source, | 2347 | source: input.source, |
| 2302 | adapterKey: "google_discovery", | ||
| 2303 | documents: input.documents, | 2348 | documents: input.documents, |
| 2304 | serviceScopeDefaults: (() => { | 2349 | serviceScopeDefaults: (() => { |
| 2305 | const servers = googleDiscoveryServerSpecs(input.operations[0]); | 2350 | const servers = googleDiscoveryServerSpecs(input.operations[0]); |
| @@ -2319,14 +2364,26 @@ export const createGoogleDiscoveryCatalogSnapshot = (input: { · 13 unmodified lines | |||
| 2319 | }, | 2364 | }, |
| 2320 | }); | 2365 | }); |
| 2321 | 2366 | ||
| 2322 | export const createGraphqlCatalogSnapshot = (input: { | 2367 | export const createGoogleDiscoveryCatalogSnapshot = (input: { |
| 2323 | source: Source; | 2368 | source: Source; |
| 2324 | documents: readonly CatalogSourceDocumentInput[]; | 2369 | documents: readonly CatalogSourceDocumentInput[]; |
| 2325 | operations: readonly GraphqlCatalogOperationInput[]; | 2370 | operations: readonly GoogleDiscoveryCatalogOperationInput[]; |
| 2326 | }): CatalogSnapshotV1 => | 2371 | }): CatalogSnapshotV1 => |
| 2327 | buildCatalogSnapshot({ | 2372 | createCatalogSnapshotV1FromFragments({ |
| 2373 | import: createCatalogImportMetadata({ | ||
| 2374 | source: input.source, | ||
| 2375 | adapterKey: "google_discovery", | ||
| 2376 | }), | ||
| 2377 | fragments: [createGoogleDiscoveryCatalogFragment(input)], | ||
| 2378 | }); | ||
| 2379 | |||
| 2380 | export const createGraphqlCatalogFragment = (input: { | ||
| 2381 | source: Source; | ||
| 2382 | documents: readonly CatalogSourceDocumentInput[]; | ||
| 2383 | operations: readonly GraphqlCatalogOperationInput[]; | ||
| 2384 | }): CatalogFragmentV1 => | ||
| 2385 | buildCatalogFragment({ | ||
| 2328 | source: input.source, | 2386 | source: input.source, |
| 2329 | adapterKey: "graphql", | ||
| 2330 | documents: input.documents, | 2387 | documents: input.documents, |
| 2331 | registerOperations: ({ catalog, documentId, serviceScopeId, importer }) => { | 2388 | registerOperations: ({ catalog, documentId, serviceScopeId, importer }) => { |
| 2332 | for (const operation of input.operations) { | 2389 | for (const operation of input.operations) { |
| @@ -2342,14 +2399,26 @@ export const createGraphqlCatalogSnapshot = (input: { · 9 unmodified lines | |||
| 2342 | }, | 2399 | }, |
| 2343 | }); | 2400 | }); |
| 2344 | 2401 | ||
| 2345 | export const createMcpCatalogSnapshot = (input: { | 2402 | export const createGraphqlCatalogSnapshot = (input: { |
| 2346 | source: Source; | 2403 | source: Source; |
| 2347 | documents: readonly CatalogSourceDocumentInput[]; | 2404 | documents: readonly CatalogSourceDocumentInput[]; |
| 2348 | operations: readonly McpCatalogOperationInput[]; | 2405 | operations: readonly GraphqlCatalogOperationInput[]; |
| 2349 | }): CatalogSnapshotV1 => | 2406 | }): CatalogSnapshotV1 => |
| 2350 | buildCatalogSnapshot({ | 2407 | createCatalogSnapshotV1FromFragments({ |
| 2408 | import: createCatalogImportMetadata({ | ||
| 2409 | source: input.source, | ||
| 2410 | adapterKey: "graphql", | ||
| 2411 | }), | ||
| 2412 | fragments: [createGraphqlCatalogFragment(input)], | ||
| 2413 | }); | ||
| 2414 | |||
| 2415 | export const createMcpCatalogFragment = (input: { | ||
| 2416 | source: Source; | ||
| 2417 | documents: readonly CatalogSourceDocumentInput[]; | ||
| 2418 | operations: readonly McpCatalogOperationInput[]; | ||
| 2419 | }): CatalogFragmentV1 => | ||
| 2420 | buildCatalogFragment({ | ||
| 2351 | source: input.source, | 2421 | source: input.source, |
| 2352 | adapterKey: "mcp", | ||
| 2353 | documents: input.documents, | 2422 | documents: input.documents, |
| 2354 | registerOperations: ({ catalog, documentId, serviceScopeId, importer }) => { | 2423 | registerOperations: ({ catalog, documentId, serviceScopeId, importer }) => { |
| 2355 | for (const operation of input.operations) { | 2424 | for (const operation of input.operations) { |
| @@ -2364,3 +2433,16 @@ export const createMcpCatalogSnapshot = (input: { · 8 unmodified lines | |||
| 2364 | } | 2433 | } |
| 2365 | }, | 2434 | }, |
| 2366 | }); | 2435 | }); |
| 2436 | |||
| 2437 | export const createMcpCatalogSnapshot = (input: { | ||
| 2438 | source: Source; | ||
| 2439 | documents: readonly CatalogSourceDocumentInput[]; | ||
| 2440 | operations: readonly McpCatalogOperationInput[]; | ||
| 2441 | }): CatalogSnapshotV1 => | ||
| 2442 | createCatalogSnapshotV1FromFragments({ | ||
| 2443 | import: createCatalogImportMetadata({ | ||
| 2444 | source: input.source, | ||
| 2445 | adapterKey: "mcp", | ||
| 2446 | }), | ||
| 2447 | fragments: [createMcpCatalogFragment(input)], | ||
| 2448 | }); | ||
| @@ -1,5 +1,10 @@ | |||
| 1 | import { sha256Hex } from "@executor/codemode-core"; | 1 | import { sha256Hex } from "@executor/codemode-core"; |
| 2 | import type { CatalogSnapshotV1 } from "../ir/model"; | 2 | import { createCatalogSnapshotV1FromFragments } from "../ir/catalog"; |
| 3 | import type { | ||
| 4 | CatalogFragmentV1, | ||
| 5 | CatalogSnapshotV1, | ||
| 6 | ImportMetadata, | ||
| 7 | } from "../ir/model"; | ||
| 3 | 8 | ||
| 4 | export const normalizeSearchText = ( | 9 | export const normalizeSearchText = ( |
| 5 | ...parts: ReadonlyArray<string | null | undefined> | 10 | ...parts: ReadonlyArray<string | null | undefined> |
| @@ -13,6 +18,19 @@ export const normalizeSearchText = ( · 7 unmodified lines | |||
| 13 | export const contentHash = (value: string): string => sha256Hex(value); | 18 | export const contentHash = (value: string): string => sha256Hex(value); |
| 14 | 19 | ||
| 15 | export type SourceCatalogSyncResult = { | 20 | export type SourceCatalogSyncResult = { |
| 16 | snapshot: CatalogSnapshotV1; | 21 | fragment: CatalogFragmentV1; |
| 22 | importMetadata: ImportMetadata; | ||
| 17 | sourceHash: string | null; | 23 | sourceHash: string | null; |
| 18 | }; | 24 | }; |
| 25 | |||
| 26 | export const createSourceCatalogSyncResult = ( | ||
| 27 | input: SourceCatalogSyncResult, | ||
| 28 | ): SourceCatalogSyncResult => input; | ||
| 29 | |||
| 30 | export const snapshotFromSourceCatalogSyncResult = ( | ||
| 31 | syncResult: SourceCatalogSyncResult, | ||
| 32 | ): CatalogSnapshotV1 => | ||
| 33 | createCatalogSnapshotV1FromFragments({ | ||
| 34 | import: syncResult.importMetadata, | ||
| 35 | fragments: [syncResult.fragment], | ||
| 36 | }); | ||
| @@ -31,6 +31,7 @@ import { · 30 unmodified lines | |||
| 31 | catalogSyncResultFromMcpManifest, | 31 | catalogSyncResultFromMcpManifest, |
| 32 | } from "./source-adapters/mcp"; | 32 | } from "./source-adapters/mcp"; |
| 33 | import { SecretMaterialResolverService } from "./secret-material-providers"; | 33 | import { SecretMaterialResolverService } from "./secret-material-providers"; |
| 34 | import { snapshotFromSourceCatalogSyncResult } from "./source-catalog-support"; | ||
| 34 | import { | 35 | import { |
| 35 | refreshSourceTypeDeclarationInBackground, | 36 | refreshSourceTypeDeclarationInBackground, |
| 36 | } from "./source-type-declarations"; | 37 | } from "./source-type-declarations"; |
| @@ -139,6 +140,7 @@ const syncSourceCatalogWithDeps = ( · 102 unmodified lines | |||
| 139 | actorAccountId: input.actorAccountId, | 140 | actorAccountId: input.actorAccountId, |
| 140 | }), | 141 | }), |
| 141 | }); | 142 | }); |
| 143 | const snapshot = snapshotFromSourceCatalogSyncResult(syncResult); | ||
| 142 | yield* deps.sourceArtifactStore.write({ | 144 | yield* deps.sourceArtifactStore.write({ |
| 143 | context: workspaceContext, | 145 | context: workspaceContext, |
| 144 | sourceId: input.source.id, | 146 | sourceId: input.source.id, |
| @@ -172,7 +174,7 @@ const syncSourceCatalogWithDeps = ( · 27 unmodified lines | |||
| 172 | refreshSourceTypeDeclarationInBackground({ | 174 | refreshSourceTypeDeclarationInBackground({ |
| 173 | context: workspaceContext, | 175 | context: workspaceContext, |
| 174 | source: input.source, | 176 | source: input.source, |
| 175 | snapshot: syncResult.snapshot, | 177 | snapshot, |
| 176 | }); | 178 | }); |
| 177 | }); | 179 | }); |
| 178 | }).pipe( | 180 | }).pipe( |
| @@ -203,6 +205,7 @@ const persistMcpCatalogSnapshotFromManifestWithDeps = ( · 24 unmodified lines | |||
| 203 | endpoint: input.source.endpoint, | 205 | endpoint: input.source.endpoint, |
| 204 | manifest: input.manifest, | 206 | manifest: input.manifest, |
| 205 | }); | 207 | }); |
| 208 | const snapshot = snapshotFromSourceCatalogSyncResult(syncResult); | ||
| 206 | 209 | ||
| 207 | yield* deps.sourceArtifactStore.write({ | 210 | yield* deps.sourceArtifactStore.write({ |
| 208 | context: workspaceContext, | 211 | context: workspaceContext, |
| @@ -217,7 +220,7 @@ const persistMcpCatalogSnapshotFromManifestWithDeps = ( · 8 unmodified lines | |||
| 217 | refreshSourceTypeDeclarationInBackground({ | 220 | refreshSourceTypeDeclarationInBackground({ |
| 218 | context: workspaceContext, | 221 | context: workspaceContext, |
| 219 | source: input.source, | 222 | source: input.source, |
| 220 | snapshot: syncResult.snapshot, | 223 | snapshot, |
| 221 | }); | 224 | }); |
| 222 | }); | 225 | }); |
| 223 | }); | 226 | }); |