@sweetoburrito/backstage-plugin-ai-assistant-backend 0.8.0 → 0.10.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"searchKnowledge.cjs.js","sources":["../../../src/services/tools/searchKnowledge.ts"],"sourcesContent":["import {\n createAssistantTool,\n Tool,\n VectorStore,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport z from 'zod';\n\ntype CreateSearchKnowledgeToolOptions = {\n vectorStore: VectorStore;\n};\n\nexport const createSearchKnowledgeTool = ({\n vectorStore,\n}: CreateSearchKnowledgeToolOptions): Tool => {\n const knowledgeTool = createAssistantTool({\n tool: {\n name: 'searchKnowledge',\n description: `Search the internal knowledge base containing company specific information.\n\nUse this tool when users ask about:\n- General questions about the company or internal information\n\nDo NOT use for general knowledge that doesn't require company-specific information.`,\n schema: z.object({\n query: z.string().describe('The query to search for.'),\n filter: z\n .object({\n source: z.string().optional().describe('Source to filter by.'),\n id: z.string().optional().describe('ID to filter by.'),\n })\n .optional()\n .describe('Filters to apply to the search.'),\n amount: z\n .number()\n .min(1)\n .optional()\n .describe('The number of results to return.'),\n }),\n func: async ({ query, filter, amount }) => {\n const results = await vectorStore.similaritySearch(\n query,\n filter,\n amount,\n );\n if (results.length === 0) {\n return 'No relevant information found.';\n }\n return results.map(r => r.content).join('\\n---\\n');\n },\n },\n });\n\n return knowledgeTool;\n};\n"],"names":["createAssistantTool","z"],"mappings":";;;;;;;;;AAWO,MAAM,4BAA4B,CAAC;AAAA,EACxC;AACF,CAAA,KAA8C;AAC5C,EAAA,MAAM,gBAAgBA,kDAAA,CAAoB;AAAA,IACxC,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,iBAAA;AAAA,MACN,WAAA,EAAa,CAAA;;AAAA;AAAA;;AAAA,mFAAA,CAAA;AAAA,MAMb,MAAA,EAAQC,mBAAE,MAAA,CAAO;AAAA,QACf,KAAA,EAAOA,kBAAA,CAAE,MAAA,EAAO,CAAE,SAAS,0BAA0B,CAAA;AAAA,QACrD,MAAA,EAAQA,mBACL,MAAA,CAAO;AAAA,UACN,QAAQA,kBAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,SAAS,sBAAsB,CAAA;AAAA,UAC7D,IAAIA,kBAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,SAAS,kBAAkB;AAAA,SACtD,CAAA,CACA,QAAA,EAAS,CACT,SAAS,iCAAiC,CAAA;AAAA,QAC7C,MAAA,EAAQA,kBAAA,CACL,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,QAAA,EAAS,CACT,QAAA,CAAS,kCAAkC;AAAA,OAC/C,CAAA;AAAA,MACD,MAAM,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,QAAO,KAAM;AACzC,QAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,gBAAA;AAAA,UAChC,KAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,UAAA,OAAO,gCAAA;AAAA,QACT;AACA,QAAA,OAAO,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA,CAAE,KAAK,SAAS,CAAA;AAAA,MACnD;AAAA;AACF,GACD,CAAA;AAED,EAAA,OAAO,aAAA;AACT;;;;"}
1
+ {"version":3,"file":"searchKnowledge.cjs.js","sources":["../../../src/services/tools/searchKnowledge.ts"],"sourcesContent":["import {\n createAssistantTool,\n Tool,\n VectorStore,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport z from 'zod';\n\ntype CreateSearchKnowledgeToolOptions = {\n vectorStore: VectorStore;\n};\n\nexport const createSearchKnowledgeTool = ({\n vectorStore,\n}: CreateSearchKnowledgeToolOptions): Tool => {\n const knowledgeTool = createAssistantTool({\n tool: {\n name: 'search-knowledge-base',\n description: `Search the internal knowledge base containing company specific information.\n\nUse this tool when users ask about:\n- General questions about the company or internal information\n\nDo NOT use for general knowledge that doesn't require company-specific information.`,\n schema: z.object({\n query: z.string().describe('The query to search for.'),\n filter: z\n .object({\n source: z.string().optional().describe('Source to filter by.'),\n id: z.string().optional().describe('ID to filter by.'),\n })\n .optional()\n .describe('Filters to apply to the search.'),\n amount: z\n .number()\n .min(1)\n .optional()\n .describe('The number of results to return.'),\n }),\n func: async ({ query, filter, amount }) => {\n const results = await vectorStore.similaritySearch(\n query,\n filter,\n amount,\n );\n if (results.length === 0) {\n return 'No relevant information found.';\n }\n return results.map(r => r.content).join('\\n---\\n');\n },\n },\n });\n\n return knowledgeTool;\n};\n"],"names":["createAssistantTool","z"],"mappings":";;;;;;;;;AAWO,MAAM,4BAA4B,CAAC;AAAA,EACxC;AACF,CAAA,KAA8C;AAC5C,EAAA,MAAM,gBAAgBA,kDAAA,CAAoB;AAAA,IACxC,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,uBAAA;AAAA,MACN,WAAA,EAAa,CAAA;;AAAA;AAAA;;AAAA,mFAAA,CAAA;AAAA,MAMb,MAAA,EAAQC,mBAAE,MAAA,CAAO;AAAA,QACf,KAAA,EAAOA,kBAAA,CAAE,MAAA,EAAO,CAAE,SAAS,0BAA0B,CAAA;AAAA,QACrD,MAAA,EAAQA,mBACL,MAAA,CAAO;AAAA,UACN,QAAQA,kBAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,SAAS,sBAAsB,CAAA;AAAA,UAC7D,IAAIA,kBAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAAE,SAAS,kBAAkB;AAAA,SACtD,CAAA,CACA,QAAA,EAAS,CACT,SAAS,iCAAiC,CAAA;AAAA,QAC7C,MAAA,EAAQA,kBAAA,CACL,MAAA,EAAO,CACP,GAAA,CAAI,CAAC,CAAA,CACL,QAAA,EAAS,CACT,QAAA,CAAS,kCAAkC;AAAA,OAC/C,CAAA;AAAA,MACD,MAAM,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,QAAO,KAAM;AACzC,QAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,gBAAA;AAAA,UAChC,KAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,UAAA,OAAO,gCAAA;AAAA,QACT;AACA,QAAA,OAAO,QAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA,CAAE,KAAK,SAAS,CAAA;AAAA,MACnD;AAAA;AACF,GACD,CAAA;AAED,EAAA,OAAO,aAAA;AACT;;;;"}
@@ -0,0 +1,42 @@
1
+ const mcpConfigTable = 'user_mcp_config';
2
+
3
+ /**
4
+ *
5
+ * @param {import('knex').knex} knex
6
+ */
7
+
8
+ exports.down = async knex => {
9
+ const hasMcpConfigTable = await knex.schema.hasTable(mcpConfigTable);
10
+
11
+ if (hasMcpConfigTable) {
12
+ await knex.schema.dropTable(mcpConfigTable);
13
+ }
14
+ };
15
+
16
+ /**
17
+ *
18
+ * @param {import('knex').knex} knex
19
+ */
20
+
21
+ exports.up = async knex => {
22
+ await knex.schema.createTable(mcpConfigTable, table => {
23
+ table
24
+ .uuid('id')
25
+ .primary()
26
+ .notNullable()
27
+ .defaultTo(knex.raw('gen_random_uuid()'));
28
+ table
29
+ .text('userRef')
30
+ .notNullable()
31
+ .comment('Reference to the user who sent the message');
32
+ table
33
+ .text('name')
34
+ .notNullable()
35
+ .comment('Name of the MCP server configuration');
36
+ table
37
+ .text('encryptedOptions')
38
+ .notNullable()
39
+ .comment('Encrypted MCP server configuration');
40
+ table.timestamps(true, true);
41
+ });
42
+ };
@@ -0,0 +1,52 @@
1
+ /**
2
+ *
3
+ * @param {import('knex').knex} knex
4
+ */
5
+
6
+ exports.down = async knex => {
7
+ const hasScoreColumn = await knex.schema.hasColumn('message', 'score');
8
+ const hasTraceIdColumn = await knex.schema.hasColumn('message', 'trace_id');
9
+
10
+ if (hasScoreColumn || hasTraceIdColumn) {
11
+ await knex.schema.alterTable('message', table => {
12
+ if (hasScoreColumn) {
13
+ table.dropColumn('score');
14
+ }
15
+ if (hasTraceIdColumn) {
16
+ table.dropColumn('trace_id');
17
+ }
18
+ });
19
+ }
20
+ };
21
+
22
+ /**
23
+ *
24
+ * @param {import('knex').knex} knex
25
+ */
26
+
27
+ exports.up = async knex => {
28
+ const hasScoreColumn = await knex.schema.hasColumn('message', 'score');
29
+ const hasTraceIdColumn = await knex.schema.hasColumn('message', 'trace_id');
30
+
31
+ if (!hasScoreColumn || !hasTraceIdColumn) {
32
+ await knex.schema.alterTable('message', table => {
33
+ if (!hasScoreColumn) {
34
+ table
35
+ .float('score')
36
+ .nullable()
37
+ .defaultTo(0)
38
+ .comment(
39
+ 'User feedback score for the message: 0 = no feedback, 1 = helpful, -1 = not helpful',
40
+ );
41
+ }
42
+ if (!hasTraceIdColumn) {
43
+ table
44
+ .string('trace_id')
45
+ .nullable()
46
+ .comment(
47
+ 'Langfuse trace ID for the message, used for scoring and observability',
48
+ );
49
+ }
50
+ });
51
+ }
52
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sweetoburrito/backstage-plugin-ai-assistant-backend",
3
- "version": "0.8.0",
3
+ "version": "0.10.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",
@@ -41,9 +41,10 @@
41
41
  "@backstage/plugin-signals-node": "backstage:^",
42
42
  "@langchain/core": "^0.3.72",
43
43
  "@langchain/langgraph": "^0.4.9",
44
+ "@langchain/mcp-adapters": "^1.0.0",
44
45
  "@langchain/textsplitters": "^0.1.0",
45
- "@sweetoburrito/backstage-plugin-ai-assistant-common": "^0.5.0",
46
- "@sweetoburrito/backstage-plugin-ai-assistant-node": "^0.5.1",
46
+ "@sweetoburrito/backstage-plugin-ai-assistant-common": "^0.6.0",
47
+ "@sweetoburrito/backstage-plugin-ai-assistant-node": "^0.6.0",
47
48
  "express": "^4.17.1",
48
49
  "express-promise-router": "^4.1.0",
49
50
  "knex": "^3.1.0",
@@ -59,13 +60,16 @@
59
60
  "@backstage/plugin-events-backend": "backstage:^",
60
61
  "@backstage/plugin-signals-backend": "backstage:^",
61
62
  "@backstage/types": "backstage:^",
63
+ "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-callback-provider-langfuse": "workspace:^",
62
64
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-embeddings-provider-azure-open-ai": "workspace:^",
63
65
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-embeddings-provider-ollama": "workspace:^",
64
66
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-ingestor-azure-devops": "workspace:^",
65
67
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-ingestor-catalog": "workspace:^",
66
68
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-ingestor-github": "workspace:^",
67
69
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-azure-ai": "workspace:^",
70
+ "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-google-vertex-ai": "workspace:^",
68
71
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-ollama": "workspace:^",
72
+ "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-tool-provider-backstage": "workspace:^",
69
73
  "@types/express": "^4.0.0",
70
74
  "@types/supertest": "^2.0.12",
71
75
  "supertest": "^6.2.4"