@sweetoburrito/backstage-plugin-ai-assistant-backend-module-ingestor-catalog 0.0.0-snapshot-20251029150521

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # @sweetoburrito/backstage-plugin-ai-assistant-backend-module-ingestor-catalog
2
+
3
+ The ingestor-catalog backend module for the ai-assistant plugin.
4
+
5
+ _This plugin was created through the Backstage CLI_
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ const MODULE_ID = "catalog";
4
+
5
+ exports.MODULE_ID = MODULE_ID;
6
+ //# sourceMappingURL=module.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.cjs.js","sources":["../../src/constants/module.ts"],"sourcesContent":["export const MODULE_ID = 'catalog';\n"],"names":[],"mappings":";;AAAO,MAAM,SAAA,GAAY;;;;"}
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var module$1 = require('./module.cjs.js');
6
+
7
+
8
+
9
+ exports.default = module$1.aiAssistantModuleIngestorCatalog;
10
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -0,0 +1,5 @@
1
+ import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
2
+
3
+ declare const aiAssistantModuleIngestorCatalog: _backstage_backend_plugin_api.BackendFeature;
4
+
5
+ export { aiAssistantModuleIngestorCatalog as default };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ var backendPluginApi = require('@backstage/backend-plugin-api');
4
+ var backstagePluginAiAssistantNode = require('@sweetoburrito/backstage-plugin-ai-assistant-node');
5
+ var index = require('./services/ingestor/index.cjs.js');
6
+
7
+ const aiAssistantModuleIngestorCatalog = backendPluginApi.createBackendModule({
8
+ pluginId: "ai-assistant",
9
+ moduleId: "ingestor-catalog",
10
+ register(reg) {
11
+ reg.registerInit({
12
+ deps: {
13
+ dataIngestor: backstagePluginAiAssistantNode.dataIngestorExtensionPoint,
14
+ auth: backendPluginApi.coreServices.auth,
15
+ discovery: backendPluginApi.coreServices.discovery
16
+ },
17
+ async init(options) {
18
+ const { dataIngestor } = options;
19
+ dataIngestor.registerIngestor(await index.createCatalogIngestor(options));
20
+ }
21
+ });
22
+ }
23
+ });
24
+
25
+ exports.aiAssistantModuleIngestorCatalog = aiAssistantModuleIngestorCatalog;
26
+ //# sourceMappingURL=module.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.cjs.js","sources":["../src/module.ts"],"sourcesContent":["import {\n coreServices,\n createBackendModule,\n} from '@backstage/backend-plugin-api';\nimport { dataIngestorExtensionPoint } from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { createCatalogIngestor } from './services/ingestor';\n\nexport const aiAssistantModuleIngestorCatalog = createBackendModule({\n pluginId: 'ai-assistant',\n moduleId: 'ingestor-catalog',\n register(reg) {\n reg.registerInit({\n deps: {\n dataIngestor: dataIngestorExtensionPoint,\n auth: coreServices.auth,\n discovery: coreServices.discovery,\n },\n async init(options) {\n const { dataIngestor } = options;\n dataIngestor.registerIngestor(await createCatalogIngestor(options));\n },\n });\n },\n});\n"],"names":["createBackendModule","dataIngestorExtensionPoint","coreServices","createCatalogIngestor"],"mappings":";;;;;;AAOO,MAAM,mCAAmCA,oCAAA,CAAoB;AAAA,EAClE,QAAA,EAAU,cAAA;AAAA,EACV,QAAA,EAAU,kBAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,YAAA,EAAcC,yDAAA;AAAA,QACd,MAAMC,6BAAA,CAAa,IAAA;AAAA,QACnB,WAAWA,6BAAA,CAAa;AAAA,OAC1B;AAAA,MACA,MAAM,KAAK,OAAA,EAAS;AAClB,QAAA,MAAM,EAAE,cAAa,GAAI,OAAA;AACzB,QAAA,YAAA,CAAa,gBAAA,CAAiB,MAAMC,2BAAA,CAAsB,OAAO,CAAC,CAAA;AAAA,MACpE;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ var module$1 = require('../../../constants/module.cjs.js');
4
+
5
+ function mapEntityToEmbeddingDoc(entity) {
6
+ const ns = entity.metadata.namespace || "default";
7
+ const id = `${entity.kind.toLowerCase()}:${ns}/${entity.metadata.name}`;
8
+ const parts = [];
9
+ if (entity.metadata.title) {
10
+ parts.push(
11
+ `${entity.kind} "${entity.metadata.title}" (${entity.metadata.name})`
12
+ );
13
+ } else {
14
+ parts.push(`${entity.kind} "${entity.metadata.name}"`);
15
+ }
16
+ if (entity.metadata.description) {
17
+ parts.push(`Description: ${entity.metadata.description}.`);
18
+ }
19
+ if (entity.spec) {
20
+ for (const [key, value] of Object.entries(entity.spec)) {
21
+ if (typeof value === "string") {
22
+ parts.push(`${key}: ${value}`);
23
+ } else if (Array.isArray(value)) {
24
+ parts.push(`${key}: ${value.join(", ")}`);
25
+ } else if (typeof value === "object" && value !== null) {
26
+ for (const [k, v] of Object.entries(value)) {
27
+ if (typeof v === "string") {
28
+ parts.push(`${k}: ${v}`);
29
+ }
30
+ }
31
+ }
32
+ }
33
+ }
34
+ if (entity.relations?.length) {
35
+ const relationText = entity.relations.map((r) => `${r.type} \u2192 ${r.targetRef}`).join("; ");
36
+ parts.push(`Relations: ${relationText}`);
37
+ }
38
+ return {
39
+ metadata: {
40
+ source: module$1.MODULE_ID,
41
+ id,
42
+ kind: entity.kind,
43
+ namespace: ns,
44
+ name: entity.metadata.name,
45
+ uid: entity.metadata.uid
46
+ },
47
+ content: parts.join("\n")
48
+ };
49
+ }
50
+
51
+ exports.mapEntityToEmbeddingDoc = mapEntityToEmbeddingDoc;
52
+ //# sourceMappingURL=entity-to-embedding-doc.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-to-embedding-doc.cjs.js","sources":["../../../../src/services/ingestor/helpers/entity-to-embedding-doc.ts"],"sourcesContent":["import { Entity } from '@backstage/catalog-model';\nimport { EmbeddingDocument } from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { MODULE_ID } from '../../../constants/module';\n\nexport function mapEntityToEmbeddingDoc(entity: Entity): EmbeddingDocument {\n const ns = entity.metadata.namespace || 'default';\n const id = `${entity.kind.toLowerCase()}:${ns}/${entity.metadata.name}`;\n\n // Build content string (natural language summary)\n const parts: string[] = [];\n\n // Title & description\n if (entity.metadata.title) {\n parts.push(\n `${entity.kind} \"${entity.metadata.title}\" (${entity.metadata.name})`,\n );\n } else {\n parts.push(`${entity.kind} \"${entity.metadata.name}\"`);\n }\n\n if (entity.metadata.description) {\n parts.push(`Description: ${entity.metadata.description}.`);\n }\n\n // Spec (flatten key fields if present)\n if (entity.spec) {\n for (const [key, value] of Object.entries(entity.spec)) {\n if (typeof value === 'string') {\n parts.push(`${key}: ${value}`);\n } else if (Array.isArray(value)) {\n parts.push(`${key}: ${value.join(', ')}`);\n } else if (typeof value === 'object' && value !== null) {\n for (const [k, v] of Object.entries(value)) {\n if (typeof v === 'string') {\n parts.push(`${k}: ${v}`);\n }\n }\n }\n }\n }\n\n // Relations (express in plain text)\n if (entity.relations?.length) {\n const relationText = entity.relations\n .map(r => `${r.type} → ${r.targetRef}`)\n .join('; ');\n parts.push(`Relations: ${relationText}`);\n }\n\n return {\n metadata: {\n source: MODULE_ID,\n id,\n kind: entity.kind,\n namespace: ns,\n name: entity.metadata.name,\n uid: entity.metadata.uid!,\n },\n content: parts.join('\\n'),\n };\n}\n"],"names":["MODULE_ID"],"mappings":";;;;AAIO,SAAS,wBAAwB,MAAA,EAAmC;AACzE,EAAA,MAAM,EAAA,GAAK,MAAA,CAAO,QAAA,CAAS,SAAA,IAAa,SAAA;AACxC,EAAA,MAAM,EAAA,GAAK,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,WAAA,EAAa,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,EAAI,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,CAAA;AAGrE,EAAA,MAAM,QAAkB,EAAC;AAGzB,EAAA,IAAI,MAAA,CAAO,SAAS,KAAA,EAAO;AACzB,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,EAAA,EAAK,MAAA,CAAO,SAAS,KAAK,CAAA,GAAA,EAAM,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,CAAA;AAAA,KACpE;AAAA,EACF,CAAA,MAAO;AACL,IAAA,KAAA,CAAM,IAAA,CAAK,GAAG,MAAA,CAAO,IAAI,KAAK,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EACvD;AAEA,EAAA,IAAI,MAAA,CAAO,SAAS,WAAA,EAAa;AAC/B,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAgB,MAAA,CAAO,QAAA,CAAS,WAAW,CAAA,CAAA,CAAG,CAAA;AAAA,EAC3D;AAGA,EAAA,IAAI,OAAO,IAAA,EAAM;AACf,IAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,EAAG;AACtD,MAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,EAAA,EAAK,KAAK,CAAA,CAAE,CAAA;AAAA,MAC/B,CAAA,MAAA,IAAW,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC/B,QAAA,KAAA,CAAM,IAAA,CAAK,GAAG,GAAG,CAAA,EAAA,EAAK,MAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,MAC1C,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,IAAY,UAAU,IAAA,EAAM;AACtD,QAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC1C,UAAA,IAAI,OAAO,MAAM,QAAA,EAAU;AACzB,YAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,CAAC,CAAA,EAAA,EAAK,CAAC,CAAA,CAAE,CAAA;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,MAAA,CAAO,WAAW,MAAA,EAAQ;AAC5B,IAAA,MAAM,YAAA,GAAe,MAAA,CAAO,SAAA,CACzB,GAAA,CAAI,OAAK,CAAA,EAAG,CAAA,CAAE,IAAI,CAAA,QAAA,EAAM,CAAA,CAAE,SAAS,CAAA,CAAE,CAAA,CACrC,KAAK,IAAI,CAAA;AACZ,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,YAAY,CAAA,CAAE,CAAA;AAAA,EACzC;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU;AAAA,MACR,MAAA,EAAQA,kBAAA;AAAA,MACR,EAAA;AAAA,MACA,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,SAAA,EAAW,EAAA;AAAA,MACX,IAAA,EAAM,OAAO,QAAA,CAAS,IAAA;AAAA,MACtB,GAAA,EAAK,OAAO,QAAA,CAAS;AAAA,KACvB;AAAA,IACA,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,IAAI;AAAA,GAC1B;AACF;;;;"}
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ var entityToEmbeddingDoc = require('./helpers/entity-to-embedding-doc.cjs.js');
4
+ var module$1 = require('../../constants/module.cjs.js');
5
+
6
+ const MAX_RESULTS = 50;
7
+ const createCatalogIngestor = async ({
8
+ auth,
9
+ discovery
10
+ }) => {
11
+ const ingestCatalogBatch = async (saveDocumentsBatch, cursor) => {
12
+ const baseUrl = await discovery.getBaseUrl("catalog");
13
+ const credentials = await auth.getOwnServiceCredentials();
14
+ const { token } = await auth.getPluginRequestToken({
15
+ onBehalfOf: credentials,
16
+ targetPluginId: "catalog"
17
+ });
18
+ const params = new URLSearchParams();
19
+ if (cursor) {
20
+ params.set("cursor", cursor);
21
+ }
22
+ params.set("limit", MAX_RESULTS.toString());
23
+ const response = await fetch(
24
+ `${baseUrl}/entities/by-query?${params.toString()}`,
25
+ {
26
+ headers: {
27
+ Authorization: `Bearer ${token}`
28
+ }
29
+ }
30
+ );
31
+ if (!response.ok) {
32
+ return;
33
+ }
34
+ const data = await response.json();
35
+ const entities = data.items;
36
+ const nextCursor = data.pageInfo?.nextCursor;
37
+ const documents = entities.map(
38
+ entityToEmbeddingDoc.mapEntityToEmbeddingDoc
39
+ );
40
+ await saveDocumentsBatch(documents);
41
+ if (!nextCursor) {
42
+ return;
43
+ }
44
+ await ingestCatalogBatch(saveDocumentsBatch, nextCursor);
45
+ };
46
+ const ingest = async ({ saveDocumentsBatch }) => {
47
+ await ingestCatalogBatch(saveDocumentsBatch);
48
+ };
49
+ return {
50
+ id: module$1.MODULE_ID,
51
+ ingest
52
+ };
53
+ };
54
+
55
+ exports.createCatalogIngestor = createCatalogIngestor;
56
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../../../src/services/ingestor/index.ts"],"sourcesContent":["import {\n EmbeddingDocument,\n Ingestor,\n IngestorOptions,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { AuthService, DiscoveryService } from '@backstage/backend-plugin-api';\nimport { Entity } from '@backstage/catalog-model';\nimport { mapEntityToEmbeddingDoc } from './helpers/entity-to-embedding-doc';\nimport { MODULE_ID } from '../../constants/module';\n\ntype CatalogIngestorOptions = {\n auth: AuthService;\n discovery: DiscoveryService;\n};\n\nconst MAX_RESULTS = 50;\n\nexport const createCatalogIngestor = async ({\n auth,\n discovery,\n}: CatalogIngestorOptions): Promise<Ingestor> => {\n const ingestCatalogBatch = async (\n saveDocumentsBatch: IngestorOptions['saveDocumentsBatch'],\n cursor?: string,\n ) => {\n const baseUrl = await discovery.getBaseUrl('catalog');\n\n const credentials = await auth.getOwnServiceCredentials();\n const { token } = await auth.getPluginRequestToken({\n onBehalfOf: credentials,\n targetPluginId: 'catalog',\n });\n\n const params = new URLSearchParams();\n if (cursor) {\n params.set('cursor', cursor);\n }\n\n params.set('limit', MAX_RESULTS.toString());\n\n const response = await fetch(\n `${baseUrl}/entities/by-query?${params.toString()}`,\n {\n headers: {\n Authorization: `Bearer ${token}`,\n },\n },\n );\n\n if (!response.ok) {\n return;\n }\n\n const data = await response.json();\n\n const entities = data.items as Entity[];\n const nextCursor = data.pageInfo?.nextCursor;\n\n const documents: EmbeddingDocument[] = entities.map(\n mapEntityToEmbeddingDoc,\n );\n\n await saveDocumentsBatch(documents);\n\n if (!nextCursor) {\n return;\n }\n\n await ingestCatalogBatch(saveDocumentsBatch, nextCursor);\n };\n\n const ingest: Ingestor['ingest'] = async ({ saveDocumentsBatch }) => {\n await ingestCatalogBatch(saveDocumentsBatch);\n };\n\n return {\n id: MODULE_ID,\n ingest,\n };\n};\n"],"names":["mapEntityToEmbeddingDoc","MODULE_ID"],"mappings":";;;;;AAeA,MAAM,WAAA,GAAc,EAAA;AAEb,MAAM,wBAAwB,OAAO;AAAA,EAC1C,IAAA;AAAA,EACA;AACF,CAAA,KAAiD;AAC/C,EAAA,MAAM,kBAAA,GAAqB,OACzB,kBAAA,EACA,MAAA,KACG;AACH,IAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,UAAA,CAAW,SAAS,CAAA;AAEpD,IAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,wBAAA,EAAyB;AACxD,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,KAAK,qBAAA,CAAsB;AAAA,MACjD,UAAA,EAAY,WAAA;AAAA,MACZ,cAAA,EAAgB;AAAA,KACjB,CAAA;AAED,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,EAAgB;AACnC,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,GAAA,CAAI,UAAU,MAAM,CAAA;AAAA,IAC7B;AAEA,IAAA,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,WAAA,CAAY,QAAA,EAAU,CAAA;AAE1C,IAAA,MAAM,WAAW,MAAM,KAAA;AAAA,MACrB,CAAA,EAAG,OAAO,CAAA,mBAAA,EAAsB,MAAA,CAAO,UAAU,CAAA,CAAA;AAAA,MACjD;AAAA,QACE,OAAA,EAAS;AAAA,UACP,aAAA,EAAe,UAAU,KAAK,CAAA;AAAA;AAChC;AACF,KACF;AAEA,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,IAAA,MAAM,WAAW,IAAA,CAAK,KAAA;AACtB,IAAA,MAAM,UAAA,GAAa,KAAK,QAAA,EAAU,UAAA;AAElC,IAAA,MAAM,YAAiC,QAAA,CAAS,GAAA;AAAA,MAC9CA;AAAA,KACF;AAEA,IAAA,MAAM,mBAAmB,SAAS,CAAA;AAElC,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,kBAAA,CAAmB,oBAAoB,UAAU,CAAA;AAAA,EACzD,CAAA;AAEA,EAAA,MAAM,MAAA,GAA6B,OAAO,EAAE,kBAAA,EAAmB,KAAM;AACnE,IAAA,MAAM,mBAAmB,kBAAkB,CAAA;AAAA,EAC7C,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,EAAA,EAAIC,kBAAA;AAAA,IACJ;AAAA,GACF;AACF;;;;"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-ingestor-catalog",
3
+ "version": "0.0.0-snapshot-20251029150521",
4
+ "license": "Apache-2.0",
5
+ "description": "The ingestor-catalog backend module for the ai-assistant plugin.",
6
+ "main": "dist/index.cjs.js",
7
+ "types": "dist/index.d.ts",
8
+ "publishConfig": {
9
+ "access": "public",
10
+ "main": "dist/index.cjs.js",
11
+ "types": "dist/index.d.ts"
12
+ },
13
+ "backstage": {
14
+ "role": "backend-plugin-module",
15
+ "pluginId": "ai-assistant",
16
+ "pluginPackage": "@sweetoburrito/backstage-plugin-ai-assistant-backend",
17
+ "features": {
18
+ ".": "@backstage/BackendFeature"
19
+ }
20
+ },
21
+ "scripts": {
22
+ "start": "backstage-cli package start",
23
+ "build": "backstage-cli package build",
24
+ "lint": "backstage-cli package lint",
25
+ "test": "backstage-cli package test",
26
+ "clean": "backstage-cli package clean",
27
+ "prepack": "backstage-cli package prepack",
28
+ "postpack": "backstage-cli package postpack"
29
+ },
30
+ "dependencies": {
31
+ "@backstage/backend-plugin-api": "backstage:^",
32
+ "@backstage/catalog-model": "backstage:^",
33
+ "@backstage/plugin-catalog-node": "backstage:^",
34
+ "@sweetoburrito/backstage-plugin-ai-assistant-node": "0.0.0-snapshot-20251029150521"
35
+ },
36
+ "devDependencies": {
37
+ "@backstage/backend-defaults": "backstage:^",
38
+ "@backstage/backend-test-utils": "backstage:^",
39
+ "@backstage/cli": "backstage:^",
40
+ "@backstage/plugin-catalog-backend": "backstage:^"
41
+ },
42
+ "files": [
43
+ "dist"
44
+ ],
45
+ "typesVersions": {
46
+ "*": {
47
+ "package.json": [
48
+ "package.json"
49
+ ]
50
+ }
51
+ }
52
+ }