@sweetoburrito/backstage-plugin-ai-assistant-backend 0.13.0 → 0.14.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.
Files changed (39) hide show
  1. package/dist/plugin.cjs.js +25 -41
  2. package/dist/plugin.cjs.js.map +1 -1
  3. package/dist/services/agent/helpers/message-parser.cjs.js +31 -0
  4. package/dist/services/agent/helpers/message-parser.cjs.js.map +1 -0
  5. package/dist/services/agent/helpers/tool-filter.cjs.js +13 -0
  6. package/dist/services/agent/helpers/tool-filter.cjs.js.map +1 -0
  7. package/dist/services/agent/index.cjs.js +140 -0
  8. package/dist/services/agent/index.cjs.js.map +1 -0
  9. package/dist/services/callbacks.cjs.js +23 -9
  10. package/dist/services/callbacks.cjs.js.map +1 -1
  11. package/dist/services/chat.cjs.js +90 -253
  12. package/dist/services/chat.cjs.js.map +1 -1
  13. package/dist/services/conversation.cjs.js +133 -0
  14. package/dist/services/conversation.cjs.js.map +1 -0
  15. package/dist/services/mcp/index.cjs.js +37 -24
  16. package/dist/services/mcp/index.cjs.js.map +1 -1
  17. package/dist/services/model.cjs.js +45 -0
  18. package/dist/services/model.cjs.js.map +1 -0
  19. package/dist/services/router/agent.cjs.js +68 -0
  20. package/dist/services/router/agent.cjs.js.map +1 -0
  21. package/dist/services/router/chat.cjs.js +8 -13
  22. package/dist/services/router/chat.cjs.js.map +1 -1
  23. package/dist/services/router/index.cjs.js +4 -0
  24. package/dist/services/router/index.cjs.js.map +1 -1
  25. package/dist/services/router/models.cjs.js +2 -2
  26. package/dist/services/router/models.cjs.js.map +1 -1
  27. package/dist/services/router/settings/index.cjs.js +0 -3
  28. package/dist/services/router/settings/index.cjs.js.map +1 -1
  29. package/dist/services/router/summary.cjs.js +5 -3
  30. package/dist/services/router/summary.cjs.js.map +1 -1
  31. package/dist/services/router/tools.cjs.js +21 -0
  32. package/dist/services/router/tools.cjs.js.map +1 -0
  33. package/dist/services/summarizer.cjs.js +47 -28
  34. package/dist/services/summarizer.cjs.js.map +1 -1
  35. package/dist/services/tools.cjs.js +65 -0
  36. package/dist/services/tools.cjs.js.map +1 -0
  37. package/dist/services/user-settings.cjs.js +15 -0
  38. package/dist/services/user-settings.cjs.js.map +1 -1
  39. package/package.json +5 -3
@@ -1,51 +1,56 @@
1
1
  'use strict';
2
2
 
3
+ var backendPluginApi = require('@backstage/backend-plugin-api');
4
+ var index = require('./agent/index.cjs.js');
3
5
  var prompts = require('../constants/prompts.cjs.js');
4
6
  var prompts$1 = require('@langchain/core/prompts');
7
+ var uuid = require('uuid');
5
8
 
6
9
  const createSummarizerService = async ({
7
10
  config,
8
- models,
9
- callback
11
+ agent,
12
+ auth
10
13
  }) => {
11
- const summaryModelId = config.getOptionalString("aiAssistant.conversation.summaryModel") ?? models[0].id;
14
+ const summaryModelId = config.getOptionalString(
15
+ "aiAssistant.conversation.summaryModel"
16
+ );
12
17
  const conversationSummaryPrompt = config.getOptionalString("aiAssistant.conversation.summaryPrompt") ?? prompts.DEFAULT_CONVERSATION_SUMMARY_PROMPT;
13
- const model = models.find((m) => m.id === summaryModelId);
14
- if (!model) {
15
- throw new Error(`Summary model with id ${summaryModelId} not found`);
16
- }
17
- const llm = model.chatModel;
18
18
  const summaryPromptTemplate = prompts$1.PromptTemplate.fromTemplate(`
19
19
  PURPOSE:
20
20
  {summaryPrompt}
21
21
 
22
22
  Summarize the following content in {length}.
23
-
24
- Content:
25
- {content}
26
23
  `);
27
- const summarize = async (content, summaryPrompt = prompts.DEFAULT_SUMMARY_PROMPT, length = "as few words as possible") => {
24
+ const summarize = async ({
25
+ content,
26
+ length = "as few words as possible",
27
+ prompt: summaryPrompt = prompts.DEFAULT_SUMMARY_PROMPT
28
+ }) => {
28
29
  const prompt = await summaryPromptTemplate.format({
29
30
  summaryPrompt,
30
31
  content,
31
32
  length
32
33
  });
33
- const { callbacks } = await callback.getChainCallbacks({
34
- conversationId: "summarizer",
35
- userId: "system",
36
- modelId: summaryModelId
37
- });
38
- const { metadata } = await callback.getChainMetadata({
39
- conversationId: "summarizer",
40
- userId: "system",
41
- modelId: summaryModelId
42
- });
43
- const { text } = await llm.invoke(prompt, {
44
- callbacks,
45
- runName: "summarizer",
46
- metadata
34
+ const credentials = await auth.getOwnServiceCredentials();
35
+ const messages = await agent.prompt({
36
+ messages: [{ role: "system", content, score: 0, metadata: {} }],
37
+ metadata: {
38
+ conversationId: "summarizer",
39
+ userId: "system:summarizer",
40
+ runId: uuid.v4(),
41
+ runName: "summarizer"
42
+ },
43
+ systemPrompt: prompt,
44
+ modelId: summaryModelId,
45
+ credentials,
46
+ tools: []
47
47
  });
48
- return text.trim();
48
+ const aiMessages = messages.filter((m) => m.role === "ai");
49
+ if (aiMessages.length === 0) {
50
+ throw new Error("Failed to summarize content");
51
+ }
52
+ const response = messages.pop();
53
+ return response.content.trim();
49
54
  };
50
55
  const summarizeConversation = async ({ messages, length = "as few words as possible" }) => {
51
56
  const conversationMessages = messages.filter(
@@ -60,6 +65,20 @@ const createSummarizerService = async ({
60
65
  };
61
66
  return { summarizeConversation, summarize };
62
67
  };
68
+ const summarizerServiceRef = backendPluginApi.createServiceRef({
69
+ id: "ai-assistant.summarizer-service",
70
+ defaultFactory: async (service) => backendPluginApi.createServiceFactory({
71
+ service,
72
+ deps: {
73
+ config: backendPluginApi.coreServices.rootConfig,
74
+ agent: index.agentServiceRef,
75
+ auth: backendPluginApi.coreServices.auth
76
+ },
77
+ factory: async (options) => {
78
+ return createSummarizerService(options);
79
+ }
80
+ })
81
+ });
63
82
 
64
- exports.createSummarizerService = createSummarizerService;
83
+ exports.summarizerServiceRef = summarizerServiceRef;
65
84
  //# sourceMappingURL=summarizer.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"summarizer.cjs.js","sources":["../../src/services/summarizer.ts"],"sourcesContent":["import { RootConfigService } from '@backstage/backend-plugin-api';\nimport { Model } from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport {\n DEFAULT_CONVERSATION_SUMMARY_PROMPT,\n DEFAULT_SUMMARY_PROMPT,\n} from '../constants/prompts';\nimport { PromptTemplate } from '@langchain/core/prompts';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { CallbackService } from './callbacks';\n\nexport type SummarizerService = {\n summarizeConversation: (options: {\n messages: Message[];\n length?: string;\n }) => Promise<string>;\n\n summarize: (options: {\n content: string;\n prompt?: string;\n length?: string;\n }) => Promise<string>;\n};\n\ntype SummarizerServiceOptions = {\n config: RootConfigService;\n models: Model[];\n callback: CallbackService;\n};\n\nexport const createSummarizerService = async ({\n config,\n models,\n callback,\n}: SummarizerServiceOptions): Promise<SummarizerService> => {\n const summaryModelId =\n config.getOptionalString('aiAssistant.conversation.summaryModel') ??\n models[0].id;\n\n const conversationSummaryPrompt =\n config.getOptionalString('aiAssistant.conversation.summaryPrompt') ??\n DEFAULT_CONVERSATION_SUMMARY_PROMPT;\n\n const model = models.find(m => m.id === summaryModelId);\n\n if (!model) {\n throw new Error(`Summary model with id ${summaryModelId} not found`);\n }\n\n const llm = model.chatModel;\n\n const summaryPromptTemplate = PromptTemplate.fromTemplate(`\n PURPOSE:\n {summaryPrompt}\n\n Summarize the following content in {length}.\n\n Content:\n {content}\n `);\n\n const summarize: SummarizerService['summarize'] = async (\n content,\n summaryPrompt = DEFAULT_SUMMARY_PROMPT,\n length = 'as few words as possible',\n ) => {\n const prompt = await summaryPromptTemplate.format({\n summaryPrompt,\n content,\n length,\n });\n\n const { callbacks } = await callback.getChainCallbacks({\n conversationId: 'summarizer',\n userId: 'system',\n modelId: summaryModelId,\n });\n\n const { metadata } = await callback.getChainMetadata({\n conversationId: 'summarizer',\n userId: 'system',\n modelId: summaryModelId,\n });\n\n const { text } = await llm.invoke(prompt, {\n callbacks,\n runName: 'summarizer',\n metadata,\n });\n\n return text.trim();\n };\n\n const summarizeConversation: SummarizerService['summarizeConversation'] =\n async ({ messages, length = 'as few words as possible' }) => {\n const conversationMessages = messages.filter(\n msg => msg.role === 'ai' || msg.role === 'human',\n );\n\n const conversation = conversationMessages\n .map(msg => `${msg.role}: ${msg.content}`)\n .join('\\n');\n\n return summarize({\n content: conversation,\n prompt: conversationSummaryPrompt,\n length,\n });\n };\n\n return { summarizeConversation, summarize };\n};\n"],"names":["DEFAULT_CONVERSATION_SUMMARY_PROMPT","PromptTemplate","DEFAULT_SUMMARY_PROMPT"],"mappings":";;;;;AA6BO,MAAM,0BAA0B,OAAO;AAAA,EAC5C,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,KAA4D;AAC1D,EAAA,MAAM,iBACJ,MAAA,CAAO,iBAAA,CAAkB,uCAAuC,CAAA,IAChE,MAAA,CAAO,CAAC,CAAA,CAAE,EAAA;AAEZ,EAAA,MAAM,yBAAA,GACJ,MAAA,CAAO,iBAAA,CAAkB,wCAAwC,CAAA,IACjEA,2CAAA;AAEF,EAAA,MAAM,QAAQ,MAAA,CAAO,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,cAAc,CAAA;AAEtD,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,cAAc,CAAA,UAAA,CAAY,CAAA;AAAA,EACrE;AAEA,EAAA,MAAM,MAAM,KAAA,CAAM,SAAA;AAElB,EAAA,MAAM,qBAAA,GAAwBC,yBAAe,YAAA,CAAa;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA,EAAA,CAQzD,CAAA;AAED,EAAA,MAAM,YAA4C,OAChD,OAAA,EACA,aAAA,GAAgBC,8BAAA,EAChB,SAAS,0BAAA,KACN;AACH,IAAA,MAAM,MAAA,GAAS,MAAM,qBAAA,CAAsB,MAAA,CAAO;AAAA,MAChD,aAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,SAAS,iBAAA,CAAkB;AAAA,MACrD,cAAA,EAAgB,YAAA;AAAA,MAChB,MAAA,EAAQ,QAAA;AAAA,MACR,OAAA,EAAS;AAAA,KACV,CAAA;AAED,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,MAAM,SAAS,gBAAA,CAAiB;AAAA,MACnD,cAAA,EAAgB,YAAA;AAAA,MAChB,MAAA,EAAQ,QAAA;AAAA,MACR,OAAA,EAAS;AAAA,KACV,CAAA;AAED,IAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,GAAA,CAAI,OAAO,MAAA,EAAQ;AAAA,MACxC,SAAA;AAAA,MACA,OAAA,EAAS,YAAA;AAAA,MACT;AAAA,KACD,CAAA;AAED,IAAA,OAAO,KAAK,IAAA,EAAK;AAAA,EACnB,CAAA;AAEA,EAAA,MAAM,wBACJ,OAAO,EAAE,QAAA,EAAU,MAAA,GAAS,4BAA2B,KAAM;AAC3D,IAAA,MAAM,uBAAuB,QAAA,CAAS,MAAA;AAAA,MACpC,CAAA,GAAA,KAAO,GAAA,CAAI,IAAA,KAAS,IAAA,IAAQ,IAAI,IAAA,KAAS;AAAA,KAC3C;AAEA,IAAA,MAAM,YAAA,GAAe,oBAAA,CAClB,GAAA,CAAI,CAAA,GAAA,KAAO,CAAA,EAAG,GAAA,CAAI,IAAI,CAAA,EAAA,EAAK,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA,CACxC,KAAK,IAAI,CAAA;AAEZ,IAAA,OAAO,SAAA,CAAU;AAAA,MACf,OAAA,EAAS,YAAA;AAAA,MACT,MAAA,EAAQ,yBAAA;AAAA,MACR;AAAA,KACD,CAAA;AAAA,EACH,CAAA;AAEF,EAAA,OAAO,EAAE,uBAAuB,SAAA,EAAU;AAC5C;;;;"}
1
+ {"version":3,"file":"summarizer.cjs.js","sources":["../../src/services/summarizer.ts"],"sourcesContent":["import {\n coreServices,\n RootConfigService,\n AuthService,\n} from '@backstage/backend-plugin-api';\nimport { AgentService, agentServiceRef } from './agent';\n\nimport {\n DEFAULT_CONVERSATION_SUMMARY_PROMPT,\n DEFAULT_SUMMARY_PROMPT,\n} from '../constants/prompts';\nimport { PromptTemplate } from '@langchain/core/prompts';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport {\n createServiceFactory,\n createServiceRef,\n ServiceRef,\n} from '@backstage/backend-plugin-api';\nimport { v4 as uuid } from 'uuid';\n\nexport type SummarizerService = {\n summarizeConversation: (options: {\n messages: Message[];\n length?: string;\n }) => Promise<string>;\n\n summarize: (options: {\n content: string;\n prompt?: string;\n length?: string;\n }) => Promise<string>;\n};\n\nexport type SummarizerServiceOptions = {\n config: RootConfigService;\n agent: AgentService;\n auth: AuthService;\n};\n\nconst createSummarizerService = async ({\n config,\n agent,\n auth,\n}: SummarizerServiceOptions): Promise<SummarizerService> => {\n const summaryModelId = config.getOptionalString(\n 'aiAssistant.conversation.summaryModel',\n );\n\n const conversationSummaryPrompt =\n config.getOptionalString('aiAssistant.conversation.summaryPrompt') ??\n DEFAULT_CONVERSATION_SUMMARY_PROMPT;\n\n const summaryPromptTemplate = PromptTemplate.fromTemplate(`\n PURPOSE:\n {summaryPrompt}\n\n Summarize the following content in {length}.\n `);\n\n const summarize: SummarizerService['summarize'] = async ({\n content,\n length = 'as few words as possible',\n prompt: summaryPrompt = DEFAULT_SUMMARY_PROMPT,\n }) => {\n const prompt = await summaryPromptTemplate.format({\n summaryPrompt,\n content,\n length,\n });\n\n const credentials = await auth.getOwnServiceCredentials();\n\n const messages = await agent.prompt({\n messages: [{ role: 'system', content, score: 0, metadata: {} }],\n metadata: {\n conversationId: 'summarizer',\n userId: 'system:summarizer',\n runId: uuid(),\n runName: 'summarizer',\n },\n systemPrompt: prompt,\n modelId: summaryModelId,\n credentials,\n tools: [],\n });\n\n const aiMessages = messages.filter(m => m.role === 'ai');\n\n if (aiMessages.length === 0) {\n throw new Error('Failed to summarize content');\n }\n\n const response = messages.pop()!;\n\n return response.content.trim();\n };\n\n const summarizeConversation: SummarizerService['summarizeConversation'] =\n async ({ messages, length = 'as few words as possible' }) => {\n const conversationMessages = messages.filter(\n msg => msg.role === 'ai' || msg.role === 'human',\n );\n\n const conversation = conversationMessages\n .map(msg => `${msg.role}: ${msg.content}`)\n .join('\\n');\n\n return summarize({\n content: conversation,\n prompt: conversationSummaryPrompt,\n length,\n });\n };\n\n return { summarizeConversation, summarize };\n};\n\nexport const summarizerServiceRef: ServiceRef<\n SummarizerService,\n 'plugin',\n 'singleton'\n> = createServiceRef<SummarizerService>({\n id: 'ai-assistant.summarizer-service',\n defaultFactory: async service =>\n createServiceFactory({\n service,\n deps: {\n config: coreServices.rootConfig,\n agent: agentServiceRef,\n auth: coreServices.auth,\n },\n factory: async options => {\n return createSummarizerService(options);\n },\n }),\n});\n"],"names":["DEFAULT_CONVERSATION_SUMMARY_PROMPT","PromptTemplate","DEFAULT_SUMMARY_PROMPT","uuid","createServiceRef","createServiceFactory","coreServices","agentServiceRef"],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ var backendPluginApi = require('@backstage/backend-plugin-api');
4
+ var index = require('./mcp/index.cjs.js');
5
+ var tools = require('@langchain/core/tools');
6
+
7
+ const createToolsService = async ({
8
+ mcp,
9
+ auth
10
+ }) => {
11
+ const tools$1 = [];
12
+ const coreTools = [];
13
+ const registerTools = async (providers) => {
14
+ tools$1.push(...providers);
15
+ };
16
+ const registerCoreTools = async (providers) => {
17
+ coreTools.push(...providers.map((tool) => ({ ...tool, provider: "core" })));
18
+ };
19
+ const getAvailableUserTools = async ({
20
+ credentials
21
+ }) => {
22
+ const mcpTools = await mcp.getTools(credentials);
23
+ const availableTools = tools$1.concat(mcpTools).concat(coreTools).map((tool) => ({
24
+ name: tool.name,
25
+ provider: tool.provider,
26
+ description: tool.description
27
+ }));
28
+ return availableTools;
29
+ };
30
+ const getPrincipalTools = async ({
31
+ credentials,
32
+ filter = () => true
33
+ }) => {
34
+ const isUser = auth.isPrincipal(credentials, "user");
35
+ if (!isUser) {
36
+ return tools$1.filter(filter).map((t) => new tools.DynamicStructuredTool(t));
37
+ }
38
+ const mcpTools = await mcp.getTools(credentials);
39
+ const userTools = tools$1.concat(mcpTools);
40
+ const allTools = userTools.filter(filter).concat(coreTools.filter(filter));
41
+ return allTools.map((t) => new tools.DynamicStructuredTool(t));
42
+ };
43
+ return {
44
+ registerTools,
45
+ registerCoreTools,
46
+ getAvailableUserTools,
47
+ getPrincipalTools
48
+ };
49
+ };
50
+ const toolsServiceRef = backendPluginApi.createServiceRef({
51
+ id: "ai-assistant.tools-service",
52
+ defaultFactory: async (service) => backendPluginApi.createServiceFactory({
53
+ service,
54
+ deps: {
55
+ mcp: index.mcpServiceRef,
56
+ auth: backendPluginApi.coreServices.auth
57
+ },
58
+ factory: async (options) => {
59
+ return createToolsService(options);
60
+ }
61
+ })
62
+ });
63
+
64
+ exports.toolsServiceRef = toolsServiceRef;
65
+ //# sourceMappingURL=tools.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.cjs.js","sources":["../../src/services/tools.ts"],"sourcesContent":["import {\n BackstageCredentials,\n coreServices,\n createServiceFactory,\n createServiceRef,\n ServiceRef,\n AuthService,\n} from '@backstage/backend-plugin-api';\nimport {\n Tool,\n EnabledTool,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { McpService, mcpServiceRef } from './mcp';\nimport { DynamicStructuredTool } from '@langchain/core/tools';\n\nexport type ToolsService = {\n registerTools: (tools: Tool[]) => void;\n registerCoreTools: (tools: Tool[]) => void;\n getAvailableUserTools: (options: {\n credentials: BackstageCredentials;\n }) => Promise<EnabledTool[]>;\n getPrincipalTools: (options: {\n credentials: BackstageCredentials;\n filter?: (tool: Tool) => boolean;\n }) => Promise<DynamicStructuredTool[]>;\n};\n\nexport type CreateToolsServiceOptions = {\n mcp: McpService;\n auth: AuthService;\n};\n\nconst createToolsService = async ({\n mcp,\n auth,\n}: CreateToolsServiceOptions): Promise<ToolsService> => {\n const tools: Tool[] = [];\n const coreTools: Tool[] = [];\n\n const registerTools: ToolsService['registerTools'] = async providers => {\n tools.push(...providers);\n };\n\n const registerCoreTools: ToolsService['registerCoreTools'] =\n async providers => {\n coreTools.push(...providers.map(tool => ({ ...tool, provider: 'core' })));\n };\n\n const getAvailableUserTools: ToolsService['getAvailableUserTools'] = async ({\n credentials,\n }) => {\n const mcpTools = await mcp.getTools(credentials);\n\n const availableTools: EnabledTool[] = tools\n .concat(mcpTools)\n .concat(coreTools)\n .map(tool => ({\n name: tool.name,\n provider: tool.provider,\n description: tool.description,\n }));\n\n return availableTools;\n };\n\n const getPrincipalTools: ToolsService['getPrincipalTools'] = async ({\n credentials,\n filter = () => true,\n }) => {\n const isUser = auth.isPrincipal(credentials, 'user');\n\n if (!isUser) {\n return tools.filter(filter).map(t => new DynamicStructuredTool(t));\n }\n\n const mcpTools = await mcp.getTools(credentials);\n\n const userTools = tools.concat(mcpTools);\n\n const allTools: Tool[] = userTools\n .filter(filter)\n .concat(coreTools.filter(filter));\n return allTools.map(t => new DynamicStructuredTool(t));\n };\n\n return {\n registerTools,\n registerCoreTools,\n getAvailableUserTools,\n getPrincipalTools,\n };\n};\n\nexport const toolsServiceRef: ServiceRef<ToolsService, 'plugin', 'singleton'> =\n createServiceRef<ToolsService>({\n id: 'ai-assistant.tools-service',\n defaultFactory: async service =>\n createServiceFactory({\n service,\n deps: {\n mcp: mcpServiceRef,\n auth: coreServices.auth,\n },\n factory: async options => {\n return createToolsService(options);\n },\n }),\n });\n"],"names":["tools","DynamicStructuredTool","createServiceRef","createServiceFactory","mcpServiceRef","coreServices"],"mappings":";;;;;;AAgCA,MAAM,qBAAqB,OAAO;AAAA,EAChC,GAAA;AAAA,EACA;AACF,CAAA,KAAwD;AACtD,EAAA,MAAMA,UAAgB,EAAC;AACvB,EAAA,MAAM,YAAoB,EAAC;AAE3B,EAAA,MAAM,aAAA,GAA+C,OAAM,SAAA,KAAa;AACtE,IAAAA,OAAA,CAAM,IAAA,CAAK,GAAG,SAAS,CAAA;AAAA,EACzB,CAAA;AAEA,EAAA,MAAM,iBAAA,GACJ,OAAM,SAAA,KAAa;AACjB,IAAA,SAAA,CAAU,IAAA,CAAK,GAAG,SAAA,CAAU,GAAA,CAAI,CAAA,IAAA,MAAS,EAAE,GAAG,IAAA,EAAM,QAAA,EAAU,MAAA,EAAO,CAAE,CAAC,CAAA;AAAA,EAC1E,CAAA;AAEF,EAAA,MAAM,wBAA+D,OAAO;AAAA,IAC1E;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,QAAA,CAAS,WAAW,CAAA;AAE/C,IAAA,MAAM,cAAA,GAAgCA,QACnC,MAAA,CAAO,QAAQ,EACf,MAAA,CAAO,SAAS,CAAA,CAChB,GAAA,CAAI,CAAA,IAAA,MAAS;AAAA,MACZ,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,aAAa,IAAA,CAAK;AAAA,KACpB,CAAE,CAAA;AAEJ,IAAA,OAAO,cAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,oBAAuD,OAAO;AAAA,IAClE,WAAA;AAAA,IACA,SAAS,MAAM;AAAA,GACjB,KAAM;AACJ,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,WAAA,EAAa,MAAM,CAAA;AAEnD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,OAAOA,OAAA,CAAM,OAAO,MAAM,CAAA,CAAE,IAAI,CAAA,CAAA,KAAK,IAAIC,2BAAA,CAAsB,CAAC,CAAC,CAAA;AAAA,IACnE;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,QAAA,CAAS,WAAW,CAAA;AAE/C,IAAA,MAAM,SAAA,GAAYD,OAAA,CAAM,MAAA,CAAO,QAAQ,CAAA;AAEvC,IAAA,MAAM,QAAA,GAAmB,UACtB,MAAA,CAAO,MAAM,EACb,MAAA,CAAO,SAAA,CAAU,MAAA,CAAO,MAAM,CAAC,CAAA;AAClC,IAAA,OAAO,SAAS,GAAA,CAAI,CAAA,CAAA,KAAK,IAAIC,2BAAA,CAAsB,CAAC,CAAC,CAAA;AAAA,EACvD,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,aAAA;AAAA,IACA,iBAAA;AAAA,IACA,qBAAA;AAAA,IACA;AAAA,GACF;AACF,CAAA;AAEO,MAAM,kBACXC,iCAAA,CAA+B;AAAA,EAC7B,EAAA,EAAI,4BAAA;AAAA,EACJ,cAAA,EAAgB,OAAM,OAAA,KACpBC,qCAAA,CAAqB;AAAA,IACnB,OAAA;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,GAAA,EAAKC,mBAAA;AAAA,MACL,MAAMC,6BAAA,CAAa;AAAA,KACrB;AAAA,IACA,OAAA,EAAS,OAAM,OAAA,KAAW;AACxB,MAAA,OAAO,mBAAmB,OAAO,CAAA;AAAA,IACnC;AAAA,GACD;AACL,CAAC;;;;"}
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var backendPluginApi = require('@backstage/backend-plugin-api');
3
4
  var userSettingsStore = require('../database/user-settings-store.cjs.js');
4
5
 
5
6
  const createUserSettingsService = async ({
@@ -29,6 +30,20 @@ const createUserSettingsService = async ({
29
30
  deleteSettingsForType
30
31
  };
31
32
  };
33
+ const userSettingsServiceRef = backendPluginApi.createServiceRef({
34
+ id: "ai-assistant.user-settings-service",
35
+ defaultFactory: async (service) => backendPluginApi.createServiceFactory({
36
+ service,
37
+ deps: {
38
+ userInfo: backendPluginApi.coreServices.userInfo,
39
+ database: backendPluginApi.coreServices.database
40
+ },
41
+ factory: async (options) => {
42
+ return createUserSettingsService(options);
43
+ }
44
+ })
45
+ });
32
46
 
33
47
  exports.createUserSettingsService = createUserSettingsService;
48
+ exports.userSettingsServiceRef = userSettingsServiceRef;
34
49
  //# sourceMappingURL=user-settings.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"user-settings.cjs.js","sources":["../../src/services/user-settings.ts"],"sourcesContent":["import {\n BackstageCredentials,\n DatabaseService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { UserSettingsStore } from '../database/user-settings-store';\n\ntype CreateUserSettingsServiceOptions = {\n userInfo: UserInfoService;\n database: DatabaseService;\n};\n\nexport type UserSettingsService = {\n getSettingsForType: (\n credentials: BackstageCredentials,\n type: string,\n ) => Promise<Record<string, unknown>>;\n setSettingsForType: (\n credentials: BackstageCredentials,\n type: string,\n settings: Record<string, unknown>,\n ) => Promise<void>;\n deleteSettingsForType: (\n credentials: BackstageCredentials,\n type: string,\n ) => Promise<void>;\n};\n\nexport const createUserSettingsService = async ({\n userInfo,\n database,\n}: CreateUserSettingsServiceOptions): Promise<UserSettingsService> => {\n const userSettingsStore = await UserSettingsStore.fromConfig({ database });\n\n const getSettingsForType: UserSettingsService['getSettingsForType'] = async (\n credentials,\n type,\n ) => {\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n const settings = await userSettingsStore.getUserSettingsByType(\n userEntityRef,\n type,\n );\n\n return settings ?? {};\n };\n\n const setSettingsForType: UserSettingsService['setSettingsForType'] = async (\n credentials,\n type,\n settings,\n ) => {\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n await userSettingsStore.setUserSettings(userEntityRef, type, settings);\n };\n\n const deleteSettingsForType: UserSettingsService['deleteSettingsForType'] =\n async (credentials, type) => {\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n await userSettingsStore.deleteUserSettings(userEntityRef, type);\n };\n\n return {\n getSettingsForType,\n setSettingsForType,\n deleteSettingsForType,\n };\n};\n"],"names":["userSettingsStore","UserSettingsStore"],"mappings":";;;;AA4BO,MAAM,4BAA4B,OAAO;AAAA,EAC9C,QAAA;AAAA,EACA;AACF,CAAA,KAAsE;AACpE,EAAA,MAAMA,sBAAoB,MAAMC,mCAAA,CAAkB,UAAA,CAAW,EAAE,UAAU,CAAA;AAEzE,EAAA,MAAM,kBAAA,GAAgE,OACpE,WAAA,EACA,IAAA,KACG;AACH,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAChE,IAAA,MAAM,QAAA,GAAW,MAAMD,mBAAA,CAAkB,qBAAA;AAAA,MACvC,aAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,YAAY,EAAC;AAAA,EACtB,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAgE,OACpE,WAAA,EACA,IAAA,EACA,QAAA,KACG;AACH,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAChE,IAAA,MAAMA,mBAAA,CAAkB,eAAA,CAAgB,aAAA,EAAe,IAAA,EAAM,QAAQ,CAAA;AAAA,EACvE,CAAA;AAEA,EAAA,MAAM,qBAAA,GACJ,OAAO,WAAA,EAAa,IAAA,KAAS;AAC3B,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAChE,IAAA,MAAMA,mBAAA,CAAkB,kBAAA,CAAmB,aAAA,EAAe,IAAI,CAAA;AAAA,EAChE,CAAA;AAEF,EAAA,OAAO;AAAA,IACL,kBAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"user-settings.cjs.js","sources":["../../src/services/user-settings.ts"],"sourcesContent":["import {\n createServiceFactory,\n createServiceRef,\n coreServices,\n} from '@backstage/backend-plugin-api';\n\nimport type {\n ServiceRef,\n BackstageCredentials,\n DatabaseService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\n\nimport { UserSettingsStore } from '../database/user-settings-store';\n\ntype CreateUserSettingsServiceOptions = {\n userInfo: UserInfoService;\n database: DatabaseService;\n};\n\nexport type UserSettingsService = {\n getSettingsForType: (\n credentials: BackstageCredentials,\n type: string,\n ) => Promise<Record<string, unknown>>;\n setSettingsForType: (\n credentials: BackstageCredentials,\n type: string,\n settings: Record<string, unknown>,\n ) => Promise<void>;\n deleteSettingsForType: (\n credentials: BackstageCredentials,\n type: string,\n ) => Promise<void>;\n};\n\nexport const createUserSettingsService = async ({\n userInfo,\n database,\n}: CreateUserSettingsServiceOptions): Promise<UserSettingsService> => {\n const userSettingsStore = await UserSettingsStore.fromConfig({ database });\n\n const getSettingsForType: UserSettingsService['getSettingsForType'] = async (\n credentials,\n type,\n ) => {\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n const settings = await userSettingsStore.getUserSettingsByType(\n userEntityRef,\n type,\n );\n\n return settings ?? {};\n };\n\n const setSettingsForType: UserSettingsService['setSettingsForType'] = async (\n credentials,\n type,\n settings,\n ) => {\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n await userSettingsStore.setUserSettings(userEntityRef, type, settings);\n };\n\n const deleteSettingsForType: UserSettingsService['deleteSettingsForType'] =\n async (credentials, type) => {\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n await userSettingsStore.deleteUserSettings(userEntityRef, type);\n };\n\n return {\n getSettingsForType,\n setSettingsForType,\n deleteSettingsForType,\n };\n};\n\nexport const userSettingsServiceRef: ServiceRef<\n UserSettingsService,\n 'plugin',\n 'singleton'\n> = createServiceRef<UserSettingsService>({\n id: 'ai-assistant.user-settings-service',\n defaultFactory: async service =>\n createServiceFactory({\n service,\n deps: {\n userInfo: coreServices.userInfo,\n database: coreServices.database,\n },\n factory: async options => {\n return createUserSettingsService(options);\n },\n }),\n});\n"],"names":["userSettingsStore","UserSettingsStore","createServiceRef","createServiceFactory","coreServices"],"mappings":";;;;;AAoCO,MAAM,4BAA4B,OAAO;AAAA,EAC9C,QAAA;AAAA,EACA;AACF,CAAA,KAAsE;AACpE,EAAA,MAAMA,sBAAoB,MAAMC,mCAAA,CAAkB,UAAA,CAAW,EAAE,UAAU,CAAA;AAEzE,EAAA,MAAM,kBAAA,GAAgE,OACpE,WAAA,EACA,IAAA,KACG;AACH,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAChE,IAAA,MAAM,QAAA,GAAW,MAAMD,mBAAA,CAAkB,qBAAA;AAAA,MACvC,aAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,YAAY,EAAC;AAAA,EACtB,CAAA;AAEA,EAAA,MAAM,kBAAA,GAAgE,OACpE,WAAA,EACA,IAAA,EACA,QAAA,KACG;AACH,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAChE,IAAA,MAAMA,mBAAA,CAAkB,eAAA,CAAgB,aAAA,EAAe,IAAA,EAAM,QAAQ,CAAA;AAAA,EACvE,CAAA;AAEA,EAAA,MAAM,qBAAA,GACJ,OAAO,WAAA,EAAa,IAAA,KAAS;AAC3B,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAChE,IAAA,MAAMA,mBAAA,CAAkB,kBAAA,CAAmB,aAAA,EAAe,IAAI,CAAA;AAAA,EAChE,CAAA;AAEF,EAAA,OAAO;AAAA,IACL,kBAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACF;AACF;AAEO,MAAM,yBAITE,iCAAA,CAAsC;AAAA,EACxC,EAAA,EAAI,oCAAA;AAAA,EACJ,cAAA,EAAgB,OAAM,OAAA,KACpBC,qCAAA,CAAqB;AAAA,IACnB,OAAA;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,UAAUC,6BAAA,CAAa,QAAA;AAAA,MACvB,UAAUA,6BAAA,CAAa;AAAA,KACzB;AAAA,IACA,OAAA,EAAS,OAAM,OAAA,KAAW;AACxB,MAAA,OAAO,0BAA0B,OAAO,CAAA;AAAA,IAC1C;AAAA,GACD;AACL,CAAC;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sweetoburrito/backstage-plugin-ai-assistant-backend",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",
@@ -43,8 +43,8 @@
43
43
  "@langchain/langgraph": "^0.4.9",
44
44
  "@langchain/mcp-adapters": "^1.0.0",
45
45
  "@langchain/textsplitters": "^0.1.0",
46
- "@sweetoburrito/backstage-plugin-ai-assistant-common": "^0.7.0",
47
- "@sweetoburrito/backstage-plugin-ai-assistant-node": "^0.8.0",
46
+ "@sweetoburrito/backstage-plugin-ai-assistant-common": "^0.8.0",
47
+ "@sweetoburrito/backstage-plugin-ai-assistant-node": "^0.9.0",
48
48
  "express": "^4.17.1",
49
49
  "express-promise-router": "^4.1.0",
50
50
  "knex": "^3.1.0",
@@ -60,6 +60,7 @@
60
60
  "@backstage/plugin-events-backend": "backstage:^",
61
61
  "@backstage/plugin-signals-backend": "backstage:^",
62
62
  "@backstage/types": "backstage:^",
63
+ "@drodil/backstage-plugin-qeta-backend": "^3.46.0",
63
64
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-callback-provider-langfuse": "workspace:^",
64
65
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-embeddings-provider-azure-open-ai": "workspace:^",
65
66
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-embeddings-provider-ollama": "workspace:^",
@@ -70,6 +71,7 @@
70
71
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-google-vertex-ai": "workspace:^",
71
72
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-ollama": "workspace:^",
72
73
  "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-tool-provider-backstage": "workspace:^",
74
+ "@sweetoburrito/backstage-plugin-qeta-backend-module-ai-assistant": "workspace:^",
73
75
  "@types/express": "^4.0.0",
74
76
  "@types/supertest": "^2.0.12",
75
77
  "supertest": "^6.2.4"