@sweetoburrito/backstage-plugin-ai-assistant-backend 0.0.0-snapshot-20251114135736 → 0.0.0-snapshot-20251118091900

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,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const DEFAULT_SUMMARY_PROMPT = "Summarize this conversation in a concise manner. The summary should capture the main points. Return the summary only, without any additional text. Do not include any introductions or other part of the conversation that doesn't contribute to the summary or form part of the overall conversation as part of the summary.";
3
+ const DEFAULT_CONVERSATION_SUMMARY_PROMPT = "Summarize this conversation in a concise manner. The summary should capture the main points. Return the summary only, without any additional text. Do not include any introductions or other part of the conversation that doesn't contribute to the summary or form part of the overall conversation as part of the summary.";
4
+ const DEFAULT_SUMMARY_PROMPT = "Summarize the following content in a concise manner. The summary should capture the main points. Return the summary only, without any additional text. Do not include any introductions or other part of the content that doesn't contribute to the summary.";
4
5
  const DEFAULT_IDENTITY_PROMPT = `
5
6
  You are a helpful assistant that answers questions based on provided context from various documents. The context may come from sources such as internal wikis, code repositories, technical documentation, or other structured or unstructured data.
6
7
  `;
@@ -35,6 +36,7 @@ TOOL USAGE GUIDELINES:
35
36
  - If a tool fails, try an alternative approach before using another tool
36
37
  `;
37
38
 
39
+ exports.DEFAULT_CONVERSATION_SUMMARY_PROMPT = DEFAULT_CONVERSATION_SUMMARY_PROMPT;
38
40
  exports.DEFAULT_FORMATTING_PROMPT = DEFAULT_FORMATTING_PROMPT;
39
41
  exports.DEFAULT_IDENTITY_PROMPT = DEFAULT_IDENTITY_PROMPT;
40
42
  exports.DEFAULT_SUMMARY_PROMPT = DEFAULT_SUMMARY_PROMPT;
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.cjs.js","sources":["../../src/constants/prompts.ts"],"sourcesContent":["export const DEFAULT_SUMMARY_PROMPT =\n \"Summarize this conversation in a concise manner. The summary should capture the main points. Return the summary only, without any additional text. Do not include any introductions or other part of the conversation that doesn't contribute to the summary or form part of the overall conversation as part of the summary.\";\n\nexport const DEFAULT_IDENTITY_PROMPT = `\nYou are a helpful assistant that answers questions based on provided context from various documents. The context may come from sources such as internal wikis, code repositories, technical documentation, or other structured or unstructured data.\n`;\n\nexport const DEFAULT_FORMATTING_PROMPT = `\nCRITICAL FORMATTING RULES - MUST ALWAYS FOLLOW:\n1. **ALWAYS use proper markdown formatting in ALL responses**\n2. **NEVER output plain URLs** - ALWAYS convert them to clickable markdown links using [description](url) syntax\n3. **For images, ALWAYS use markdown image syntax**: ![alt text](image-url)\n4. **For all URLs, ALWAYS format as**: [descriptive text](url) - never just paste the raw URL\n5. Use headings (##, ###), bullet points, numbered lists, and **bold**/*italic* text appropriately\n6. Format code with backticks: \\`inline code\\` or \\`\\`\\`language for code blocks\n7. Structure responses clearly with proper spacing and organization\n`;\n\nexport const DEFAULT_SYSTEM_PROMPT = `\nContent Rules:\n1. Always base your answers on the provided context. Do not make up information.\n2. When relevant, cite or reference the source information provided in the context.\n3. Maintain a professional, friendly, and helpful tone.\n4. Return only the relevant information without any filler or unnecessary details.\n5. If you don't know the answer, admit it and suggest ways to find the information.\n6. **Actively use available tools** to enhance your responses\n7. Adapt your approach based on the specific tools and capabilities available in the current session\n8. When you do not have the information needed to answer, use the tools provided to gather more context before responding.\n`;\n\nexport const DEFAULT_TOOL_GUIDELINE = `\nTOOL USAGE GUIDELINES:\n- Only use tools when explicitly needed to answer the user's question\n- Read tool descriptions carefully before using them\n- If you can answer without tools, do so\n- IMPORTANT: When using tools, always explain why you're using each tool\n- Use tools in logical sequence, not randomly\n- If a tool fails, try an alternative approach before using another tool\n`;\n"],"names":[],"mappings":";;AAAO,MAAM,sBAAA,GACX;AAEK,MAAM,uBAAA,GAA0B;AAAA;AAAA;AAIhC,MAAM,yBAAA,GAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWlC,MAAM,qBAAA,GAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAY9B,MAAM,sBAAA,GAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;;;"}
1
+ {"version":3,"file":"prompts.cjs.js","sources":["../../src/constants/prompts.ts"],"sourcesContent":["export const DEFAULT_CONVERSATION_SUMMARY_PROMPT =\n \"Summarize this conversation in a concise manner. The summary should capture the main points. Return the summary only, without any additional text. Do not include any introductions or other part of the conversation that doesn't contribute to the summary or form part of the overall conversation as part of the summary.\";\n\nexport const DEFAULT_SUMMARY_PROMPT =\n \"Summarize the following content in a concise manner. The summary should capture the main points. Return the summary only, without any additional text. Do not include any introductions or other part of the content that doesn't contribute to the summary.\";\n\nexport const DEFAULT_IDENTITY_PROMPT = `\nYou are a helpful assistant that answers questions based on provided context from various documents. The context may come from sources such as internal wikis, code repositories, technical documentation, or other structured or unstructured data.\n`;\n\nexport const DEFAULT_FORMATTING_PROMPT = `\nCRITICAL FORMATTING RULES - MUST ALWAYS FOLLOW:\n1. **ALWAYS use proper markdown formatting in ALL responses**\n2. **NEVER output plain URLs** - ALWAYS convert them to clickable markdown links using [description](url) syntax\n3. **For images, ALWAYS use markdown image syntax**: ![alt text](image-url)\n4. **For all URLs, ALWAYS format as**: [descriptive text](url) - never just paste the raw URL\n5. Use headings (##, ###), bullet points, numbered lists, and **bold**/*italic* text appropriately\n6. Format code with backticks: \\`inline code\\` or \\`\\`\\`language for code blocks\n7. Structure responses clearly with proper spacing and organization\n`;\n\nexport const DEFAULT_SYSTEM_PROMPT = `\nContent Rules:\n1. Always base your answers on the provided context. Do not make up information.\n2. When relevant, cite or reference the source information provided in the context.\n3. Maintain a professional, friendly, and helpful tone.\n4. Return only the relevant information without any filler or unnecessary details.\n5. If you don't know the answer, admit it and suggest ways to find the information.\n6. **Actively use available tools** to enhance your responses\n7. Adapt your approach based on the specific tools and capabilities available in the current session\n8. When you do not have the information needed to answer, use the tools provided to gather more context before responding.\n`;\n\nexport const DEFAULT_TOOL_GUIDELINE = `\nTOOL USAGE GUIDELINES:\n- Only use tools when explicitly needed to answer the user's question\n- Read tool descriptions carefully before using them\n- If you can answer without tools, do so\n- IMPORTANT: When using tools, always explain why you're using each tool\n- Use tools in logical sequence, not randomly\n- If a tool fails, try an alternative approach before using another tool\n`;\n"],"names":[],"mappings":";;AAAO,MAAM,mCAAA,GACX;AAEK,MAAM,sBAAA,GACX;AAEK,MAAM,uBAAA,GAA0B;AAAA;AAAA;AAIhC,MAAM,yBAAA,GAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWlC,MAAM,qBAAA,GAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAY9B,MAAM,sBAAA,GAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;;;;"}
@@ -12,6 +12,7 @@ var searchKnowledge = require('./services/tools/searchKnowledge.cjs.js');
12
12
  var pluginCatalogNode = require('@backstage/plugin-catalog-node');
13
13
  var mcp = require('./services/mcp.cjs.js');
14
14
  var callbacks = require('./services/callbacks.cjs.js');
15
+ var summarizer = require('./services/summarizer.cjs.js');
15
16
 
16
17
  const aiAssistantPlugin = backendPluginApi.createBackendPlugin({
17
18
  pluginId: "ai-assistant",
@@ -75,7 +76,7 @@ const aiAssistantPlugin = backendPluginApi.createBackendPlugin({
75
76
  auth: backendPluginApi.coreServices.auth
76
77
  },
77
78
  async init(options) {
78
- const { httpRouter, database } = options;
79
+ const { httpRouter, database, config } = options;
79
80
  const client = await database.getClient();
80
81
  await migrations.applyDatabaseMigrations(client);
81
82
  const vectorStore = await pgVectorStore.PgVectorStore.fromConfig(options);
@@ -94,14 +95,22 @@ const aiAssistantPlugin = backendPluginApi.createBackendPlugin({
94
95
  const callback = await callbacks.createCallbackService({
95
96
  callbacks: callbacks$1
96
97
  });
98
+ const summarizer$1 = await summarizer.createSummarizerService({
99
+ config,
100
+ models,
101
+ callback
102
+ });
97
103
  const chat$1 = await chat.createChatService({
98
104
  ...options,
99
105
  models,
100
106
  tools,
101
107
  mcp: mcp$1,
102
- callback
108
+ callback,
109
+ summarizer: summarizer$1
103
110
  });
104
- httpRouter.use(await index.createRouter({ ...options, chat: chat$1, mcp: mcp$1 }));
111
+ httpRouter.use(
112
+ await index.createRouter({ ...options, chat: chat$1, mcp: mcp$1, summarizer: summarizer$1 })
113
+ );
105
114
  dataIngestionPipeline.start();
106
115
  }
107
116
  });
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './services/router';\nimport {\n dataIngestorExtensionPoint,\n EmbeddingsProvider,\n embeddingsProviderExtensionPoint,\n Ingestor,\n Model,\n modelProviderExtensionPoint,\n Tool,\n toolExtensionPoint,\n callbackProviderExtensionPoint,\n CallbackProvider,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { createDataIngestionPipeline } from './services/ingestor';\nimport { createChatService } from './services/chat';\nimport { applyDatabaseMigrations } from './database/migrations';\nimport { PgVectorStore } from './database';\nimport { signalsServiceRef } from '@backstage/plugin-signals-node';\nimport { createSearchKnowledgeTool } from './services/tools/searchKnowledge';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\nimport { createMcpService } from './services/mcp';\n\nimport { createCallbackService } from './services/callbacks';\n/**\n * aiAssistantPlugin backend plugin\n *\n * @public\n */\n\nexport const aiAssistantPlugin = createBackendPlugin({\n pluginId: 'ai-assistant',\n register(env) {\n const ingestors: Ingestor[] = [];\n const models: Model[] = [];\n const tools: Tool[] = [];\n const callbacks: CallbackProvider[] = [];\n\n let embeddingsProvider: EmbeddingsProvider;\n\n env.registerExtensionPoint(dataIngestorExtensionPoint, {\n registerIngestor: ingestor => {\n const existingIngestor = ingestors.find(i => i.id === ingestor.id);\n if (existingIngestor) {\n throw new Error(\n `Ingestor with id ${ingestor.id} is already registered.`,\n );\n }\n ingestors.push(ingestor);\n },\n });\n\n env.registerExtensionPoint(embeddingsProviderExtensionPoint, {\n register: provider => {\n embeddingsProvider = provider;\n },\n });\n\n env.registerExtensionPoint(modelProviderExtensionPoint, {\n register: model => {\n const existingModel = models.find(m => m.id === model.id);\n if (existingModel) {\n throw new Error(`Model with id ${model.id} is already registered.`);\n }\n models.push(model);\n },\n });\n\n env.registerExtensionPoint(toolExtensionPoint, {\n register: tool => {\n const existingTool = tools.find(t => t.name === tool.name);\n if (existingTool) {\n throw new Error(`Tool with name ${tool.name} is already registered.`);\n }\n tools.push(tool);\n },\n });\n\n env.registerExtensionPoint(callbackProviderExtensionPoint, {\n register: callbackProvider => {\n callbacks.push(callbackProvider);\n },\n });\n\n env.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n database: coreServices.database,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n scheduler: coreServices.scheduler,\n httpAuth: coreServices.httpAuth,\n userInfo: coreServices.userInfo,\n signals: signalsServiceRef,\n catalog: catalogServiceRef,\n cache: coreServices.cache,\n auth: coreServices.auth,\n },\n\n async init(options) {\n const { httpRouter, database } = options;\n\n const client = await database.getClient();\n\n await applyDatabaseMigrations(client);\n\n const vectorStore = await PgVectorStore.fromConfig(options);\n\n if (!embeddingsProvider) {\n throw new Error('No Embeddings Provider was registered.');\n }\n\n vectorStore.connectEmbeddings(await embeddingsProvider.getEmbeddings());\n\n const dataIngestionPipeline = createDataIngestionPipeline({\n ...options,\n vectorStore,\n ingestors,\n });\n\n const mcp = await createMcpService(options);\n\n const searchKnowledgeTool = createSearchKnowledgeTool({ vectorStore });\n tools.push(searchKnowledgeTool);\n\n const callback = await createCallbackService({\n callbacks,\n });\n\n const chat = await createChatService({\n ...options,\n models,\n tools,\n mcp,\n callback,\n });\n\n httpRouter.use(await createRouter({ ...options, chat, mcp }));\n dataIngestionPipeline.start();\n },\n });\n },\n});\n"],"names":["createBackendPlugin","callbacks","dataIngestorExtensionPoint","embeddingsProviderExtensionPoint","modelProviderExtensionPoint","toolExtensionPoint","callbackProviderExtensionPoint","coreServices","signalsServiceRef","catalogServiceRef","applyDatabaseMigrations","PgVectorStore","createDataIngestionPipeline","mcp","createMcpService","createSearchKnowledgeTool","createCallbackService","chat","createChatService","createRouter"],"mappings":"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"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './services/router';\nimport {\n dataIngestorExtensionPoint,\n EmbeddingsProvider,\n embeddingsProviderExtensionPoint,\n Ingestor,\n Model,\n modelProviderExtensionPoint,\n Tool,\n toolExtensionPoint,\n callbackProviderExtensionPoint,\n CallbackProvider,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { createDataIngestionPipeline } from './services/ingestor';\nimport { createChatService } from './services/chat';\nimport { applyDatabaseMigrations } from './database/migrations';\nimport { PgVectorStore } from './database';\nimport { signalsServiceRef } from '@backstage/plugin-signals-node';\nimport { createSearchKnowledgeTool } from './services/tools/searchKnowledge';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\nimport { createMcpService } from './services/mcp';\nimport { createCallbackService } from './services/callbacks';\nimport { createSummarizerService } from './services/summarizer';\n/**\n * aiAssistantPlugin backend plugin\n *\n * @public\n */\n\nexport const aiAssistantPlugin = createBackendPlugin({\n pluginId: 'ai-assistant',\n register(env) {\n const ingestors: Ingestor[] = [];\n const models: Model[] = [];\n const tools: Tool[] = [];\n const callbacks: CallbackProvider[] = [];\n\n let embeddingsProvider: EmbeddingsProvider;\n\n env.registerExtensionPoint(dataIngestorExtensionPoint, {\n registerIngestor: ingestor => {\n const existingIngestor = ingestors.find(i => i.id === ingestor.id);\n if (existingIngestor) {\n throw new Error(\n `Ingestor with id ${ingestor.id} is already registered.`,\n );\n }\n ingestors.push(ingestor);\n },\n });\n\n env.registerExtensionPoint(embeddingsProviderExtensionPoint, {\n register: provider => {\n embeddingsProvider = provider;\n },\n });\n\n env.registerExtensionPoint(modelProviderExtensionPoint, {\n register: model => {\n const existingModel = models.find(m => m.id === model.id);\n if (existingModel) {\n throw new Error(`Model with id ${model.id} is already registered.`);\n }\n models.push(model);\n },\n });\n\n env.registerExtensionPoint(toolExtensionPoint, {\n register: tool => {\n const existingTool = tools.find(t => t.name === tool.name);\n if (existingTool) {\n throw new Error(`Tool with name ${tool.name} is already registered.`);\n }\n tools.push(tool);\n },\n });\n\n env.registerExtensionPoint(callbackProviderExtensionPoint, {\n register: callbackProvider => {\n callbacks.push(callbackProvider);\n },\n });\n\n env.registerInit({\n deps: {\n httpRouter: coreServices.httpRouter,\n database: coreServices.database,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n scheduler: coreServices.scheduler,\n httpAuth: coreServices.httpAuth,\n userInfo: coreServices.userInfo,\n signals: signalsServiceRef,\n catalog: catalogServiceRef,\n cache: coreServices.cache,\n auth: coreServices.auth,\n },\n\n async init(options) {\n const { httpRouter, database, config } = options;\n\n const client = await database.getClient();\n\n await applyDatabaseMigrations(client);\n\n const vectorStore = await PgVectorStore.fromConfig(options);\n\n if (!embeddingsProvider) {\n throw new Error('No Embeddings Provider was registered.');\n }\n\n vectorStore.connectEmbeddings(await embeddingsProvider.getEmbeddings());\n\n const dataIngestionPipeline = createDataIngestionPipeline({\n ...options,\n vectorStore,\n ingestors,\n });\n\n const mcp = await createMcpService(options);\n\n const searchKnowledgeTool = createSearchKnowledgeTool({ vectorStore });\n tools.push(searchKnowledgeTool);\n\n const callback = await createCallbackService({\n callbacks,\n });\n\n const summarizer = await createSummarizerService({\n config,\n models,\n callback,\n });\n\n const chat = await createChatService({\n ...options,\n models,\n tools,\n mcp,\n callback,\n summarizer,\n });\n\n httpRouter.use(\n await createRouter({ ...options, chat, mcp, summarizer }),\n );\n dataIngestionPipeline.start();\n },\n });\n },\n});\n"],"names":["createBackendPlugin","callbacks","dataIngestorExtensionPoint","embeddingsProviderExtensionPoint","modelProviderExtensionPoint","toolExtensionPoint","callbackProviderExtensionPoint","coreServices","signalsServiceRef","catalogServiceRef","applyDatabaseMigrations","PgVectorStore","createDataIngestionPipeline","mcp","createMcpService","createSearchKnowledgeTool","createCallbackService","summarizer","createSummarizerService","chat","createChatService","createRouter"],"mappings":"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"}
@@ -6,7 +6,6 @@ var backstagePluginAiAssistantNode = require('@sweetoburrito/backstage-plugin-ai
6
6
  var tools = require('@langchain/core/tools');
7
7
  var prebuilt = require('@langchain/langgraph/prebuilt');
8
8
  var prompts$1 = require('@langchain/core/prompts');
9
- var summarizer = require('./summarizer.cjs.js');
10
9
  var uuid = require('uuid');
11
10
 
12
11
  const createChatService = async ({
@@ -21,7 +20,8 @@ const createChatService = async ({
21
20
  auth,
22
21
  mcp,
23
22
  userInfo,
24
- callback
23
+ callback,
24
+ summarizer
25
25
  }) => {
26
26
  logger.info(`Available models: ${models.map((m) => m.id).join(", ")}`);
27
27
  logger.info(`Available tools: ${tools$1.map((t) => t.name).join(", ")}`);
@@ -35,11 +35,6 @@ ${formattingPrompt}
35
35
  ${contentPrompt}`;
36
36
  const toolGuideline = config.getOptionalString("aiAssistant.prompt.toolGuideline") || prompts.DEFAULT_TOOL_GUIDELINE;
37
37
  const chatStore$1 = await chatStore.ChatStore.fromConfig({ database });
38
- const summarizer$1 = await summarizer.createSummarizerService({
39
- config,
40
- models,
41
- callback
42
- });
43
38
  const systemPromptTemplate = prompts$1.SystemMessagePromptTemplate.fromTemplate(`
44
39
  PURPOSE:
45
40
  {basePrompt}
@@ -88,7 +83,10 @@ ${contentPrompt}`;
88
83
  chatStore$1.addChatMessage(messages, userRef, conversationId);
89
84
  return;
90
85
  }
91
- const summary = await summarizer$1.summarize(recentMessages, "25 characters");
86
+ const summary = await summarizer.summarizeConversation({
87
+ messages: recentMessages,
88
+ length: "25 characters"
89
+ });
92
90
  conversation.title = summary;
93
91
  chatStore$1.updateConversation(conversation);
94
92
  chatStore$1.addChatMessage(messages, userRef, conversationId);
@@ -124,8 +122,9 @@ ${contentPrompt}`;
124
122
  const user = await backstagePluginAiAssistantNode.getUser(cache, userEntityRef, credentials, catalog);
125
123
  const mcpTools = await mcp.getTools(userCredentials);
126
124
  const agentTools = tools$1.map((tool) => new tools.DynamicStructuredTool(tool)).concat(mcpTools.map((tool) => new tools.DynamicStructuredTool(tool)));
125
+ const messagesWithoutSystem = messages.filter((m) => m.role !== "system");
127
126
  addMessages(
128
- messages,
127
+ messagesWithoutSystem,
129
128
  userEntityRef,
130
129
  conversationId,
131
130
  recentConversationMessages
@@ -1 +1 @@
1
- {"version":3,"file":"chat.cjs.js","sources":["../../src/services/chat.ts"],"sourcesContent":["import { CatalogService } from '@backstage/plugin-catalog-node';\nimport {\n LoggerService,\n RootConfigService,\n DatabaseService,\n AuthService,\n} from '@backstage/backend-plugin-api';\nimport { ChatStore } from '../database/chat-store';\nimport {\n Conversation,\n Message,\n JsonObject,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { SignalsService } from '@backstage/plugin-signals-node';\nimport {\n DEFAULT_FORMATTING_PROMPT,\n DEFAULT_IDENTITY_PROMPT,\n DEFAULT_SYSTEM_PROMPT,\n DEFAULT_TOOL_GUIDELINE,\n} from '../constants/prompts';\nimport {\n Tool,\n Model,\n getUser,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { DynamicStructuredTool } from '@langchain/core/tools';\nimport { createReactAgent } from '@langchain/langgraph/prebuilt';\nimport { SystemMessagePromptTemplate } from '@langchain/core/prompts';\nimport { createSummarizerService } from './summarizer';\nimport { v4 as uuid } from 'uuid';\nimport type {\n BackstageCredentials,\n CacheService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { AIMessage, ToolMessage } from '@langchain/core/messages';\nimport { McpService } from './mcp';\nimport { CallbackService } from './callbacks';\n\nexport type ChatServiceOptions = {\n models: Model[];\n tools: Tool[];\n logger: LoggerService;\n config: RootConfigService;\n database: DatabaseService;\n signals: SignalsService;\n catalog: CatalogService;\n cache: CacheService;\n auth: AuthService;\n mcp: McpService;\n userInfo: UserInfoService;\n callback: CallbackService;\n};\n\ntype PromptOptions = {\n modelId: string;\n messages: Message[];\n conversationId: string;\n stream?: boolean;\n userCredentials: BackstageCredentials;\n};\n\ntype GetConversationOptions = {\n conversationId: string;\n userEntityRef: string;\n};\n\ntype GetConversationsOptions = {\n userEntityRef: string;\n};\n\n// Helper type for messages with required fields except traceId which remains optional\ntype MessageWithRequiredFields = Required<Omit<Message, 'traceId'>> &\n Pick<Message, 'traceId'>;\n\nexport type ChatService = {\n prompt: (options: PromptOptions) => Promise<MessageWithRequiredFields[]>;\n getAvailableModels: () => Promise<string[]>;\n getConversation: (\n options: GetConversationOptions,\n ) => Promise<MessageWithRequiredFields[]>;\n getConversations: (\n options: GetConversationsOptions,\n ) => Promise<Conversation[]>;\n addMessages: (\n messages: Message[],\n userRef: string,\n conversationId: string,\n recentConversationMessages?: Message[],\n ) => Promise<void>;\n scoreMessage: (messageId: string, score: number) => Promise<void>;\n};\n\nexport const createChatService = async ({\n models,\n tools,\n logger,\n database,\n signals,\n config,\n catalog,\n cache,\n auth,\n mcp,\n userInfo,\n callback,\n}: ChatServiceOptions): Promise<ChatService> => {\n logger.info(`Available models: ${models.map(m => m.id).join(', ')}`);\n logger.info(`Available tools: ${tools.map(t => t.name).join(', ')}`);\n\n const identityPrompt =\n config.getOptionalString('aiAssistant.prompt.identity') ||\n DEFAULT_IDENTITY_PROMPT;\n\n const formattingPrompt =\n config.getOptionalString('aiAssistant.prompt.formatting') ||\n DEFAULT_FORMATTING_PROMPT;\n\n const contentPrompt =\n config.getOptionalString('aiAssistant.prompt.content') ||\n DEFAULT_SYSTEM_PROMPT;\n\n const combinedBasePrompt = `${identityPrompt}\\n\\n${formattingPrompt}\\n\\n${contentPrompt}`;\n\n const toolGuideline =\n config.getOptionalString('aiAssistant.prompt.toolGuideline') ||\n DEFAULT_TOOL_GUIDELINE;\n\n const chatStore = await ChatStore.fromConfig({ database });\n const summarizer = await createSummarizerService({\n config,\n models,\n callback,\n });\n\n const systemPromptTemplate = SystemMessagePromptTemplate.fromTemplate(`\n PURPOSE:\n {basePrompt}\n\n TOOL USAGE GUIDELINES:\n {toolGuideline}\n\n Available tools:\n {toolList}\n\n Calling User:\n {user}\n\n Context:\n {context}`);\n\n const addMessages: ChatService['addMessages'] = async (\n messages,\n userRef,\n conversationId,\n recentConversationMessages,\n ) => {\n // If we have recentConversationMessages, use them; otherwise, fetch the last 5 messages\n const recentMessages =\n recentConversationMessages ||\n (await chatStore.getChatMessages(conversationId, userRef, 5, ['tool']));\n\n const conversationSize = (recentMessages?.length ?? 0) + messages.length;\n\n if (recentMessages.length === 0) {\n const conversation: Conversation = {\n id: conversationId,\n title: 'New Conversation',\n userRef,\n };\n chatStore.createConversation(conversation);\n chatStore.addChatMessage(messages, userRef, conversationId);\n\n signals.publish({\n channel: `ai-assistant.chat.conversation-details-update`,\n message: { conversation },\n recipients: {\n type: 'user',\n entityRef: userRef,\n },\n });\n return;\n }\n\n if (conversationSize < 5) {\n chatStore.addChatMessage(messages, userRef, conversationId);\n return;\n }\n\n const conversation = await chatStore.getConversation(\n conversationId,\n userRef,\n );\n\n if (conversation.title !== 'New Conversation') {\n chatStore.addChatMessage(messages, userRef, conversationId);\n return;\n }\n\n const summary = await summarizer.summarize(recentMessages, '25 characters');\n\n conversation.title = summary;\n\n chatStore.updateConversation(conversation);\n chatStore.addChatMessage(messages, userRef, conversationId);\n\n signals.publish({\n channel: `ai-assistant.chat.conversation-details-update`,\n message: { conversation },\n recipients: {\n type: 'user',\n entityRef: userRef,\n },\n });\n };\n\n const prompt: ChatService['prompt'] = async ({\n conversationId,\n messages,\n modelId,\n stream = true,\n userCredentials,\n }: PromptOptions) => {\n const model = models.find(m => m.id === modelId)?.chatModel;\n\n if (!model) {\n throw new Error(`Model with id ${modelId} not found`);\n }\n\n const { userEntityRef } = await userInfo.getUserInfo(userCredentials);\n\n const streamFn = async () => {\n const recentConversationMessages = await chatStore.getChatMessages(\n conversationId,\n userEntityRef,\n 10,\n ['tool'],\n );\n\n const credentials = await auth.getOwnServiceCredentials();\n const user = await getUser(cache, userEntityRef, credentials, catalog);\n\n const mcpTools = await mcp.getTools(userCredentials);\n\n const agentTools = tools\n .map(tool => new DynamicStructuredTool(tool))\n .concat(mcpTools.map(tool => new DynamicStructuredTool(tool)));\n\n addMessages(\n messages,\n userEntityRef,\n conversationId,\n recentConversationMessages,\n );\n\n const systemPrompt = await systemPromptTemplate.formatMessages({\n basePrompt: combinedBasePrompt,\n toolGuideline,\n toolList: agentTools\n .map(tool => `- ${tool.name}: ${tool.description}`)\n .join('\\n'),\n context: `none`,\n user,\n });\n\n const agent = createReactAgent({\n llm: model,\n tools: agentTools,\n prompt: systemPrompt[0].text,\n });\n\n const { callbacks } = await callback.getChainCallbacks({\n conversationId,\n userId: userEntityRef,\n modelId,\n });\n\n const { metadata: promptMetadata } = await callback.getChainMetadata({\n conversationId,\n userId: userEntityRef,\n modelId,\n });\n\n const traceId = uuid();\n\n const promptStream = await agent.stream(\n {\n messages: [...recentConversationMessages, ...messages],\n },\n {\n streamMode: ['values'],\n runName: 'ai-assistant-chat',\n runId: traceId,\n metadata: promptMetadata,\n callbacks,\n },\n );\n\n const responseMessages: MessageWithRequiredFields[] = [];\n\n for await (const [, chunk] of promptStream) {\n const { messages: promptMessages } = chunk;\n\n const newMessages: MessageWithRequiredFields[] = promptMessages\n .filter(\n m =>\n responseMessages.findIndex(\n rm => m.id === rm.metadata.langGraphId,\n ) === -1,\n )\n .filter(\n m =>\n recentConversationMessages.findIndex(rm => rm.id === m.id) === -1,\n )\n .filter(m => m.getType() !== 'human')\n .map(m => {\n const id = uuid();\n const role = m.getType();\n const content =\n typeof m.content === 'string'\n ? m.content\n : JSON.stringify(m.content);\n\n const metadata: JsonObject = {\n langGraphId: m.id ?? '',\n };\n\n if (role === 'ai') {\n const aiMessage = m as AIMessage;\n metadata.toolCalls = aiMessage.tool_calls || [];\n metadata.finishReason =\n aiMessage.response_metadata.finish_reason || undefined;\n metadata.modelName =\n aiMessage.response_metadata.model_name || undefined;\n }\n\n if (role === 'tool') {\n const toolMessage = m as ToolMessage;\n metadata.name = toolMessage.name || '';\n }\n\n return {\n id,\n role,\n content,\n metadata,\n score: 0,\n traceId: traceId,\n };\n });\n\n // Simulate streaming until langchain messages error is better understood\n for await (const m of newMessages) {\n const words = m.content.split(' ');\n const chunkSize = 5; // Send 5 words at a time\n let messageBuilder = '';\n\n for (let i = 0; i < words.length; i += chunkSize) {\n const wordChunk = words.slice(i, i + chunkSize).join(' ');\n messageBuilder = messageBuilder.concat(wordChunk).concat(' ');\n m.content = messageBuilder;\n\n await new Promise(resolve => setTimeout(resolve, 50));\n\n signals.publish({\n channel: `ai-assistant.chat.conversation-stream:${conversationId}`,\n message: { messages: [m] },\n recipients: {\n type: 'user',\n entityRef: userEntityRef,\n },\n });\n }\n }\n\n responseMessages.push(...newMessages);\n }\n\n addMessages(responseMessages, userEntityRef, conversationId, [\n ...recentConversationMessages,\n ...messages,\n ]);\n\n return responseMessages;\n };\n\n const result = streamFn();\n\n return stream ? [] : result;\n };\n\n const getAvailableModels: ChatService['getAvailableModels'] = async () => {\n return models.map(x => x.id);\n };\n\n const getConversation: ChatService['getConversation'] = async (\n options: GetConversationOptions,\n ) => {\n const { conversationId, userEntityRef } = options;\n\n const conversation = await chatStore.getChatMessages(\n conversationId,\n userEntityRef,\n );\n\n return conversation;\n };\n\n const getConversations: ChatService['getConversations'] = async ({\n userEntityRef,\n }: GetConversationsOptions) => {\n const conversations = await chatStore.getConversations(userEntityRef);\n\n return conversations;\n };\n\n const scoreMessage: ChatService['scoreMessage'] = async (\n messageId: string,\n score: number,\n ) => {\n const message = await chatStore.getMessageById(messageId);\n\n if (!message) {\n throw new Error(`Message with id ${messageId} not found`);\n }\n\n const updatedMessage: Required<Message> = {\n ...message,\n score,\n };\n\n chatStore.updateMessage(updatedMessage);\n\n callback.handleScoreCallbacks({\n name: 'helpfulness',\n message: updatedMessage,\n });\n };\n\n return {\n prompt,\n getAvailableModels,\n getConversation,\n getConversations,\n addMessages,\n scoreMessage,\n };\n};\n"],"names":["tools","DEFAULT_IDENTITY_PROMPT","DEFAULT_FORMATTING_PROMPT","DEFAULT_SYSTEM_PROMPT","DEFAULT_TOOL_GUIDELINE","chatStore","ChatStore","summarizer","createSummarizerService","SystemMessagePromptTemplate","conversation","getUser","DynamicStructuredTool","createReactAgent","uuid"],"mappings":";;;;;;;;;;;AA6FO,MAAM,oBAAoB,OAAO;AAAA,EACtC,MAAA;AAAA,SACAA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,KAAgD;AAC9C,EAAA,MAAA,CAAO,IAAA,CAAK,CAAA,kBAAA,EAAqB,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,EAAE,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AACnE,EAAA,MAAA,CAAO,IAAA,CAAK,CAAA,iBAAA,EAAoBA,OAAA,CAAM,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,IAAI,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAEnE,EAAA,MAAM,cAAA,GACJ,MAAA,CAAO,iBAAA,CAAkB,6BAA6B,CAAA,IACtDC,+BAAA;AAEF,EAAA,MAAM,gBAAA,GACJ,MAAA,CAAO,iBAAA,CAAkB,+BAA+B,CAAA,IACxDC,iCAAA;AAEF,EAAA,MAAM,aAAA,GACJ,MAAA,CAAO,iBAAA,CAAkB,4BAA4B,CAAA,IACrDC,6BAAA;AAEF,EAAA,MAAM,kBAAA,GAAqB,GAAG,cAAc;;AAAA,EAAO,gBAAgB;;AAAA,EAAO,aAAa,CAAA,CAAA;AAEvF,EAAA,MAAM,aAAA,GACJ,MAAA,CAAO,iBAAA,CAAkB,kCAAkC,CAAA,IAC3DC,8BAAA;AAEF,EAAA,MAAMC,cAAY,MAAMC,mBAAA,CAAU,UAAA,CAAW,EAAE,UAAU,CAAA;AACzD,EAAA,MAAMC,YAAA,GAAa,MAAMC,kCAAA,CAAwB;AAAA,IAC/C,MAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACD,CAAA;AAED,EAAA,MAAM,oBAAA,GAAuBC,sCAA4B,YAAA,CAAa;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA;;AAAA;AAAA,aAAA,CAc1D,CAAA;AAEZ,EAAA,MAAM,WAAA,GAA0C,OAC9C,QAAA,EACA,OAAA,EACA,gBACA,0BAAA,KACG;AAEH,IAAA,MAAM,cAAA,GACJ,0BAAA,IACC,MAAMJ,WAAA,CAAU,eAAA,CAAgB,gBAAgB,OAAA,EAAS,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEvE,IAAA,MAAM,gBAAA,GAAA,CAAoB,cAAA,EAAgB,MAAA,IAAU,CAAA,IAAK,QAAA,CAAS,MAAA;AAElE,IAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAAG;AAC/B,MAAA,MAAMK,aAAAA,GAA6B;AAAA,QACjC,EAAA,EAAI,cAAA;AAAA,QACJ,KAAA,EAAO,kBAAA;AAAA,QACP;AAAA,OACF;AACA,MAAAL,WAAA,CAAU,mBAAmBK,aAAY,CAAA;AACzC,MAAAL,WAAA,CAAU,cAAA,CAAe,QAAA,EAAU,OAAA,EAAS,cAAc,CAAA;AAE1D,MAAA,OAAA,CAAQ,OAAA,CAAQ;AAAA,QACd,OAAA,EAAS,CAAA,6CAAA,CAAA;AAAA,QACT,OAAA,EAAS,EAAE,YAAA,EAAAK,aAAAA,EAAa;AAAA,QACxB,UAAA,EAAY;AAAA,UACV,IAAA,EAAM,MAAA;AAAA,UACN,SAAA,EAAW;AAAA;AACb,OACD,CAAA;AACD,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,mBAAmB,CAAA,EAAG;AACxB,MAAAL,WAAA,CAAU,cAAA,CAAe,QAAA,EAAU,OAAA,EAAS,cAAc,CAAA;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,YAAA,GAAe,MAAMA,WAAA,CAAU,eAAA;AAAA,MACnC,cAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,IAAI,YAAA,CAAa,UAAU,kBAAA,EAAoB;AAC7C,MAAAA,WAAA,CAAU,cAAA,CAAe,QAAA,EAAU,OAAA,EAAS,cAAc,CAAA;AAC1D,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,MAAME,YAAA,CAAW,SAAA,CAAU,gBAAgB,eAAe,CAAA;AAE1E,IAAA,YAAA,CAAa,KAAA,GAAQ,OAAA;AAErB,IAAAF,WAAA,CAAU,mBAAmB,YAAY,CAAA;AACzC,IAAAA,WAAA,CAAU,cAAA,CAAe,QAAA,EAAU,OAAA,EAAS,cAAc,CAAA;AAE1D,IAAA,OAAA,CAAQ,OAAA,CAAQ;AAAA,MACd,OAAA,EAAS,CAAA,6CAAA,CAAA;AAAA,MACT,OAAA,EAAS,EAAE,YAAA,EAAa;AAAA,MACxB,UAAA,EAAY;AAAA,QACV,IAAA,EAAM,MAAA;AAAA,QACN,SAAA,EAAW;AAAA;AACb,KACD,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,SAAgC,OAAO;AAAA,IAC3C,cAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA,GAAS,IAAA;AAAA,IACT;AAAA,GACF,KAAqB;AACnB,IAAA,MAAM,QAAQ,MAAA,CAAO,IAAA,CAAK,OAAK,CAAA,CAAE,EAAA,KAAO,OAAO,CAAA,EAAG,SAAA;AAElD,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,OAAO,CAAA,UAAA,CAAY,CAAA;AAAA,IACtD;AAEA,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,eAAe,CAAA;AAEpE,IAAA,MAAM,WAAW,YAAY;AAC3B,MAAA,MAAM,0BAAA,GAA6B,MAAMA,WAAA,CAAU,eAAA;AAAA,QACjD,cAAA;AAAA,QACA,aAAA;AAAA,QACA,EAAA;AAAA,QACA,CAAC,MAAM;AAAA,OACT;AAEA,MAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,wBAAA,EAAyB;AACxD,MAAA,MAAM,OAAO,MAAMM,sCAAA,CAAQ,KAAA,EAAO,aAAA,EAAe,aAAa,OAAO,CAAA;AAErE,MAAA,MAAM,QAAA,GAAW,MAAM,GAAA,CAAI,QAAA,CAAS,eAAe,CAAA;AAEnD,MAAA,MAAM,aAAaX,OAAA,CAChB,GAAA,CAAI,CAAA,IAAA,KAAQ,IAAIY,4BAAsB,IAAI,CAAC,CAAA,CAC3C,MAAA,CAAO,SAAS,GAAA,CAAI,CAAA,IAAA,KAAQ,IAAIA,2BAAA,CAAsB,IAAI,CAAC,CAAC,CAAA;AAE/D,MAAA,WAAA;AAAA,QACE,QAAA;AAAA,QACA,aAAA;AAAA,QACA,cAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,MAAM,YAAA,GAAe,MAAM,oBAAA,CAAqB,cAAA,CAAe;AAAA,QAC7D,UAAA,EAAY,kBAAA;AAAA,QACZ,aAAA;AAAA,QACA,QAAA,EAAU,UAAA,CACP,GAAA,CAAI,CAAA,IAAA,KAAQ,CAAA,EAAA,EAAK,IAAA,CAAK,IAAI,CAAA,EAAA,EAAK,IAAA,CAAK,WAAW,CAAA,CAAE,CAAA,CACjD,KAAK,IAAI,CAAA;AAAA,QACZ,OAAA,EAAS,CAAA,IAAA,CAAA;AAAA,QACT;AAAA,OACD,CAAA;AAED,MAAA,MAAM,QAAQC,yBAAA,CAAiB;AAAA,QAC7B,GAAA,EAAK,KAAA;AAAA,QACL,KAAA,EAAO,UAAA;AAAA,QACP,MAAA,EAAQ,YAAA,CAAa,CAAC,CAAA,CAAE;AAAA,OACzB,CAAA;AAED,MAAA,MAAM,EAAE,SAAA,EAAU,GAAI,MAAM,SAAS,iBAAA,CAAkB;AAAA,QACrD,cAAA;AAAA,QACA,MAAA,EAAQ,aAAA;AAAA,QACR;AAAA,OACD,CAAA;AAED,MAAA,MAAM,EAAE,QAAA,EAAU,cAAA,EAAe,GAAI,MAAM,SAAS,gBAAA,CAAiB;AAAA,QACnE,cAAA;AAAA,QACA,MAAA,EAAQ,aAAA;AAAA,QACR;AAAA,OACD,CAAA;AAED,MAAA,MAAM,UAAUC,OAAA,EAAK;AAErB,MAAA,MAAM,YAAA,GAAe,MAAM,KAAA,CAAM,MAAA;AAAA,QAC/B;AAAA,UACE,QAAA,EAAU,CAAC,GAAG,0BAAA,EAA4B,GAAG,QAAQ;AAAA,SACvD;AAAA,QACA;AAAA,UACE,UAAA,EAAY,CAAC,QAAQ,CAAA;AAAA,UACrB,OAAA,EAAS,mBAAA;AAAA,UACT,KAAA,EAAO,OAAA;AAAA,UACP,QAAA,EAAU,cAAA;AAAA,UACV;AAAA;AACF,OACF;AAEA,MAAA,MAAM,mBAAgD,EAAC;AAEvD,MAAA,WAAA,MAAiB,GAAG,KAAK,CAAA,IAAK,YAAA,EAAc;AAC1C,QAAA,MAAM,EAAE,QAAA,EAAU,cAAA,EAAe,GAAI,KAAA;AAErC,QAAA,MAAM,cAA2C,cAAA,CAC9C,MAAA;AAAA,UACC,OACE,gBAAA,CAAiB,SAAA;AAAA,YACf,CAAA,EAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAA,CAAG,QAAA,CAAS;AAAA,WAC7B,KAAM;AAAA,SACV,CACC,MAAA;AAAA,UACC,CAAA,CAAA,KACE,2BAA2B,SAAA,CAAU,CAAA,EAAA,KAAM,GAAG,EAAA,KAAO,CAAA,CAAE,EAAE,CAAA,KAAM;AAAA,SACnE,CACC,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAQ,KAAM,OAAO,CAAA,CACnC,GAAA,CAAI,CAAA,CAAA,KAAK;AACR,UAAA,MAAM,KAAKA,OAAA,EAAK;AAChB,UAAA,MAAM,IAAA,GAAO,EAAE,OAAA,EAAQ;AACvB,UAAA,MAAM,OAAA,GACJ,OAAO,CAAA,CAAE,OAAA,KAAY,QAAA,GACjB,EAAE,OAAA,GACF,IAAA,CAAK,SAAA,CAAU,CAAA,CAAE,OAAO,CAAA;AAE9B,UAAA,MAAM,QAAA,GAAuB;AAAA,YAC3B,WAAA,EAAa,EAAE,EAAA,IAAM;AAAA,WACvB;AAEA,UAAA,IAAI,SAAS,IAAA,EAAM;AACjB,YAAA,MAAM,SAAA,GAAY,CAAA;AAClB,YAAA,QAAA,CAAS,SAAA,GAAY,SAAA,CAAU,UAAA,IAAc,EAAC;AAC9C,YAAA,QAAA,CAAS,YAAA,GACP,SAAA,CAAU,iBAAA,CAAkB,aAAA,IAAiB,MAAA;AAC/C,YAAA,QAAA,CAAS,SAAA,GACP,SAAA,CAAU,iBAAA,CAAkB,UAAA,IAAc,MAAA;AAAA,UAC9C;AAEA,UAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,YAAA,MAAM,WAAA,GAAc,CAAA;AACpB,YAAA,QAAA,CAAS,IAAA,GAAO,YAAY,IAAA,IAAQ,EAAA;AAAA,UACtC;AAEA,UAAA,OAAO;AAAA,YACL,EAAA;AAAA,YACA,IAAA;AAAA,YACA,OAAA;AAAA,YACA,QAAA;AAAA,YACA,KAAA,EAAO,CAAA;AAAA,YACP;AAAA,WACF;AAAA,QACF,CAAC,CAAA;AAGH,QAAA,WAAA,MAAiB,KAAK,WAAA,EAAa;AACjC,UAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA;AACjC,UAAA,MAAM,SAAA,GAAY,CAAA;AAClB,UAAA,IAAI,cAAA,GAAiB,EAAA;AAErB,UAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ,KAAK,SAAA,EAAW;AAChD,YAAA,MAAM,SAAA,GAAY,MAAM,KAAA,CAAM,CAAA,EAAG,IAAI,SAAS,CAAA,CAAE,KAAK,GAAG,CAAA;AACxD,YAAA,cAAA,GAAiB,cAAA,CAAe,MAAA,CAAO,SAAS,CAAA,CAAE,OAAO,GAAG,CAAA;AAC5D,YAAA,CAAA,CAAE,OAAA,GAAU,cAAA;AAEZ,YAAA,MAAM,IAAI,OAAA,CAAQ,CAAA,OAAA,KAAW,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AAEpD,YAAA,OAAA,CAAQ,OAAA,CAAQ;AAAA,cACd,OAAA,EAAS,yCAAyC,cAAc,CAAA,CAAA;AAAA,cAChE,OAAA,EAAS,EAAE,QAAA,EAAU,CAAC,CAAC,CAAA,EAAE;AAAA,cACzB,UAAA,EAAY;AAAA,gBACV,IAAA,EAAM,MAAA;AAAA,gBACN,SAAA,EAAW;AAAA;AACb,aACD,CAAA;AAAA,UACH;AAAA,QACF;AAEA,QAAA,gBAAA,CAAiB,IAAA,CAAK,GAAG,WAAW,CAAA;AAAA,MACtC;AAEA,MAAA,WAAA,CAAY,gBAAA,EAAkB,eAAe,cAAA,EAAgB;AAAA,QAC3D,GAAG,0BAAA;AAAA,QACH,GAAG;AAAA,OACJ,CAAA;AAED,MAAA,OAAO,gBAAA;AAAA,IACT,CAAA;AAEA,IAAA,MAAM,SAAS,QAAA,EAAS;AAExB,IAAA,OAAO,MAAA,GAAS,EAAC,GAAI,MAAA;AAAA,EACvB,CAAA;AAEA,EAAA,MAAM,qBAAwD,YAAY;AACxE,IAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,EAAE,CAAA;AAAA,EAC7B,CAAA;AAEA,EAAA,MAAM,eAAA,GAAkD,OACtD,OAAA,KACG;AACH,IAAA,MAAM,EAAE,cAAA,EAAgB,aAAA,EAAc,GAAI,OAAA;AAE1C,IAAA,MAAM,YAAA,GAAe,MAAMT,WAAA,CAAU,eAAA;AAAA,MACnC,cAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,YAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,mBAAoD,OAAO;AAAA,IAC/D;AAAA,GACF,KAA+B;AAC7B,IAAA,MAAM,aAAA,GAAgB,MAAMA,WAAA,CAAU,gBAAA,CAAiB,aAAa,CAAA;AAEpE,IAAA,OAAO,aAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,YAAA,GAA4C,OAChD,SAAA,EACA,KAAA,KACG;AACH,IAAA,MAAM,OAAA,GAAU,MAAMA,WAAA,CAAU,cAAA,CAAe,SAAS,CAAA;AAExD,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,SAAS,CAAA,UAAA,CAAY,CAAA;AAAA,IAC1D;AAEA,IAAA,MAAM,cAAA,GAAoC;AAAA,MACxC,GAAG,OAAA;AAAA,MACH;AAAA,KACF;AAEA,IAAAA,WAAA,CAAU,cAAc,cAAc,CAAA;AAEtC,IAAA,QAAA,CAAS,oBAAA,CAAqB;AAAA,MAC5B,IAAA,EAAM,aAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,kBAAA;AAAA,IACA,eAAA;AAAA,IACA,gBAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"chat.cjs.js","sources":["../../src/services/chat.ts"],"sourcesContent":["import { CatalogService } from '@backstage/plugin-catalog-node';\nimport {\n LoggerService,\n RootConfigService,\n DatabaseService,\n AuthService,\n} from '@backstage/backend-plugin-api';\nimport { ChatStore } from '../database/chat-store';\nimport {\n Conversation,\n Message,\n JsonObject,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { SignalsService } from '@backstage/plugin-signals-node';\nimport {\n DEFAULT_FORMATTING_PROMPT,\n DEFAULT_IDENTITY_PROMPT,\n DEFAULT_SYSTEM_PROMPT,\n DEFAULT_TOOL_GUIDELINE,\n} from '../constants/prompts';\nimport {\n Tool,\n Model,\n getUser,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { DynamicStructuredTool } from '@langchain/core/tools';\nimport { createReactAgent } from '@langchain/langgraph/prebuilt';\nimport { SystemMessagePromptTemplate } from '@langchain/core/prompts';\nimport { SummarizerService } from './summarizer';\nimport { v4 as uuid } from 'uuid';\nimport type {\n BackstageCredentials,\n CacheService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\nimport { AIMessage, ToolMessage } from '@langchain/core/messages';\nimport { McpService } from './mcp';\nimport { CallbackService } from './callbacks';\n\nexport type ChatServiceOptions = {\n models: Model[];\n tools: Tool[];\n logger: LoggerService;\n config: RootConfigService;\n database: DatabaseService;\n signals: SignalsService;\n catalog: CatalogService;\n cache: CacheService;\n auth: AuthService;\n mcp: McpService;\n userInfo: UserInfoService;\n callback: CallbackService;\n summarizer: SummarizerService;\n};\n\ntype PromptOptions = {\n modelId: string;\n messages: Message[];\n conversationId: string;\n stream?: boolean;\n userCredentials: BackstageCredentials;\n};\n\ntype GetConversationOptions = {\n conversationId: string;\n userEntityRef: string;\n};\n\ntype GetConversationsOptions = {\n userEntityRef: string;\n};\n\n// Helper type for messages with required fields except traceId which remains optional\ntype MessageWithRequiredFields = Required<Omit<Message, 'traceId'>> &\n Pick<Message, 'traceId'>;\n\nexport type ChatService = {\n prompt: (options: PromptOptions) => Promise<MessageWithRequiredFields[]>;\n getAvailableModels: () => Promise<string[]>;\n getConversation: (\n options: GetConversationOptions,\n ) => Promise<MessageWithRequiredFields[]>;\n getConversations: (\n options: GetConversationsOptions,\n ) => Promise<Conversation[]>;\n addMessages: (\n messages: Message[],\n userRef: string,\n conversationId: string,\n recentConversationMessages?: Message[],\n ) => Promise<void>;\n scoreMessage: (messageId: string, score: number) => Promise<void>;\n};\n\nexport const createChatService = async ({\n models,\n tools,\n logger,\n database,\n signals,\n config,\n catalog,\n cache,\n auth,\n mcp,\n userInfo,\n callback,\n summarizer,\n}: ChatServiceOptions): Promise<ChatService> => {\n logger.info(`Available models: ${models.map(m => m.id).join(', ')}`);\n logger.info(`Available tools: ${tools.map(t => t.name).join(', ')}`);\n\n const identityPrompt =\n config.getOptionalString('aiAssistant.prompt.identity') ||\n DEFAULT_IDENTITY_PROMPT;\n\n const formattingPrompt =\n config.getOptionalString('aiAssistant.prompt.formatting') ||\n DEFAULT_FORMATTING_PROMPT;\n\n const contentPrompt =\n config.getOptionalString('aiAssistant.prompt.content') ||\n DEFAULT_SYSTEM_PROMPT;\n\n const combinedBasePrompt = `${identityPrompt}\\n\\n${formattingPrompt}\\n\\n${contentPrompt}`;\n\n const toolGuideline =\n config.getOptionalString('aiAssistant.prompt.toolGuideline') ||\n DEFAULT_TOOL_GUIDELINE;\n\n const chatStore = await ChatStore.fromConfig({ database });\n\n const systemPromptTemplate = SystemMessagePromptTemplate.fromTemplate(`\n PURPOSE:\n {basePrompt}\n\n TOOL USAGE GUIDELINES:\n {toolGuideline}\n\n Available tools:\n {toolList}\n\n Calling User:\n {user}\n\n Context:\n {context}`);\n\n const addMessages: ChatService['addMessages'] = async (\n messages,\n userRef,\n conversationId,\n recentConversationMessages,\n ) => {\n // If we have recentConversationMessages, use them; otherwise, fetch the last 5 messages\n const recentMessages =\n recentConversationMessages ||\n (await chatStore.getChatMessages(conversationId, userRef, 5, ['tool']));\n\n const conversationSize = (recentMessages?.length ?? 0) + messages.length;\n\n if (recentMessages.length === 0) {\n const conversation: Conversation = {\n id: conversationId,\n title: 'New Conversation',\n userRef,\n };\n chatStore.createConversation(conversation);\n chatStore.addChatMessage(messages, userRef, conversationId);\n\n signals.publish({\n channel: `ai-assistant.chat.conversation-details-update`,\n message: { conversation },\n recipients: {\n type: 'user',\n entityRef: userRef,\n },\n });\n return;\n }\n\n if (conversationSize < 5) {\n chatStore.addChatMessage(messages, userRef, conversationId);\n return;\n }\n\n const conversation = await chatStore.getConversation(\n conversationId,\n userRef,\n );\n\n if (conversation.title !== 'New Conversation') {\n chatStore.addChatMessage(messages, userRef, conversationId);\n return;\n }\n\n const summary = await summarizer.summarizeConversation({\n messages: recentMessages,\n length: '25 characters',\n });\n\n conversation.title = summary;\n\n chatStore.updateConversation(conversation);\n chatStore.addChatMessage(messages, userRef, conversationId);\n\n signals.publish({\n channel: `ai-assistant.chat.conversation-details-update`,\n message: { conversation },\n recipients: {\n type: 'user',\n entityRef: userRef,\n },\n });\n };\n\n const prompt: ChatService['prompt'] = async ({\n conversationId,\n messages,\n modelId,\n stream = true,\n userCredentials,\n }: PromptOptions) => {\n const model = models.find(m => m.id === modelId)?.chatModel;\n\n if (!model) {\n throw new Error(`Model with id ${modelId} not found`);\n }\n\n const { userEntityRef } = await userInfo.getUserInfo(userCredentials);\n\n const streamFn = async () => {\n const recentConversationMessages = await chatStore.getChatMessages(\n conversationId,\n userEntityRef,\n 10,\n ['tool'],\n );\n\n const credentials = await auth.getOwnServiceCredentials();\n const user = await getUser(cache, userEntityRef, credentials, catalog);\n\n const mcpTools = await mcp.getTools(userCredentials);\n\n const agentTools = tools\n .map(tool => new DynamicStructuredTool(tool))\n .concat(mcpTools.map(tool => new DynamicStructuredTool(tool)));\n\n const messagesWithoutSystem = messages.filter(m => m.role !== 'system');\n\n addMessages(\n messagesWithoutSystem,\n userEntityRef,\n conversationId,\n recentConversationMessages,\n );\n\n const systemPrompt = await systemPromptTemplate.formatMessages({\n basePrompt: combinedBasePrompt,\n toolGuideline,\n toolList: agentTools\n .map(tool => `- ${tool.name}: ${tool.description}`)\n .join('\\n'),\n context: `none`,\n user,\n });\n\n const agent = createReactAgent({\n llm: model,\n tools: agentTools,\n prompt: systemPrompt[0].text,\n });\n\n const { callbacks } = await callback.getChainCallbacks({\n conversationId,\n userId: userEntityRef,\n modelId,\n });\n\n const { metadata: promptMetadata } = await callback.getChainMetadata({\n conversationId,\n userId: userEntityRef,\n modelId,\n });\n\n const traceId = uuid();\n\n const promptStream = await agent.stream(\n {\n messages: [...recentConversationMessages, ...messages],\n },\n {\n streamMode: ['values'],\n runName: 'ai-assistant-chat',\n runId: traceId,\n metadata: promptMetadata,\n callbacks,\n },\n );\n\n const responseMessages: MessageWithRequiredFields[] = [];\n\n for await (const [, chunk] of promptStream) {\n const { messages: promptMessages } = chunk;\n\n const newMessages: MessageWithRequiredFields[] = promptMessages\n .filter(\n m =>\n responseMessages.findIndex(\n rm => m.id === rm.metadata.langGraphId,\n ) === -1,\n )\n .filter(\n m =>\n recentConversationMessages.findIndex(rm => rm.id === m.id) === -1,\n )\n .filter(m => m.getType() !== 'human')\n .map(m => {\n const id = uuid();\n const role = m.getType();\n const content =\n typeof m.content === 'string'\n ? m.content\n : JSON.stringify(m.content);\n\n const metadata: JsonObject = {\n langGraphId: m.id ?? '',\n };\n\n if (role === 'ai') {\n const aiMessage = m as AIMessage;\n metadata.toolCalls = aiMessage.tool_calls || [];\n metadata.finishReason =\n aiMessage.response_metadata.finish_reason || undefined;\n metadata.modelName =\n aiMessage.response_metadata.model_name || undefined;\n }\n\n if (role === 'tool') {\n const toolMessage = m as ToolMessage;\n metadata.name = toolMessage.name || '';\n }\n\n return {\n id,\n role,\n content,\n metadata,\n score: 0,\n traceId: traceId,\n };\n });\n\n // Simulate streaming until langchain messages error is better understood\n for await (const m of newMessages) {\n const words = m.content.split(' ');\n const chunkSize = 5; // Send 5 words at a time\n let messageBuilder = '';\n\n for (let i = 0; i < words.length; i += chunkSize) {\n const wordChunk = words.slice(i, i + chunkSize).join(' ');\n messageBuilder = messageBuilder.concat(wordChunk).concat(' ');\n m.content = messageBuilder;\n\n await new Promise(resolve => setTimeout(resolve, 50));\n\n signals.publish({\n channel: `ai-assistant.chat.conversation-stream:${conversationId}`,\n message: { messages: [m] },\n recipients: {\n type: 'user',\n entityRef: userEntityRef,\n },\n });\n }\n }\n\n responseMessages.push(...newMessages);\n }\n\n addMessages(responseMessages, userEntityRef, conversationId, [\n ...recentConversationMessages,\n ...messages,\n ]);\n\n return responseMessages;\n };\n\n const result = streamFn();\n\n return stream ? [] : result;\n };\n\n const getAvailableModels: ChatService['getAvailableModels'] = async () => {\n return models.map(x => x.id);\n };\n\n const getConversation: ChatService['getConversation'] = async (\n options: GetConversationOptions,\n ) => {\n const { conversationId, userEntityRef } = options;\n\n const conversation = await chatStore.getChatMessages(\n conversationId,\n userEntityRef,\n );\n\n return conversation;\n };\n\n const getConversations: ChatService['getConversations'] = async ({\n userEntityRef,\n }: GetConversationsOptions) => {\n const conversations = await chatStore.getConversations(userEntityRef);\n\n return conversations;\n };\n\n const scoreMessage: ChatService['scoreMessage'] = async (\n messageId: string,\n score: number,\n ) => {\n const message = await chatStore.getMessageById(messageId);\n\n if (!message) {\n throw new Error(`Message with id ${messageId} not found`);\n }\n\n const updatedMessage: Required<Message> = {\n ...message,\n score,\n };\n\n chatStore.updateMessage(updatedMessage);\n\n callback.handleScoreCallbacks({\n name: 'helpfulness',\n message: updatedMessage,\n });\n };\n\n return {\n prompt,\n getAvailableModels,\n getConversation,\n getConversations,\n addMessages,\n scoreMessage,\n };\n};\n"],"names":["tools","DEFAULT_IDENTITY_PROMPT","DEFAULT_FORMATTING_PROMPT","DEFAULT_SYSTEM_PROMPT","DEFAULT_TOOL_GUIDELINE","chatStore","ChatStore","SystemMessagePromptTemplate","conversation","getUser","DynamicStructuredTool","createReactAgent","uuid"],"mappings":"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"}
@@ -6,6 +6,7 @@ var chat = require('./chat.cjs.js');
6
6
  var models = require('./models.cjs.js');
7
7
  var rootHttpRouter = require('@backstage/backend-defaults/rootHttpRouter');
8
8
  var mcp = require('./mcp.cjs.js');
9
+ var summary = require('./summary.cjs.js');
9
10
 
10
11
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
11
12
 
@@ -18,6 +19,7 @@ async function createRouter(options) {
18
19
  router.use("/chat", await chat.createChatRouter(options));
19
20
  router.use("/models", await models.createModelRouter(options));
20
21
  router.use("/mcp", await mcp.createMcpRouter(options));
22
+ router.use("/summary", await summary.createSummaryRouter(options));
21
23
  const middleware = rootHttpRouter.MiddlewareFactory.create(options);
22
24
  router.use(middleware.error());
23
25
  return router;
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../../../src/services/router/index.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { createChatRouter, ChatRouterOptions } from './chat';\nimport { createModelRouter } from './models';\nimport {\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { createMcpRouter, McpRouterOptions } from './mcp';\n\nexport type RouterOptions = ChatRouterOptions &\n McpRouterOptions & {\n config: RootConfigService;\n logger: LoggerService;\n };\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = Router();\n router.use(express.json());\n\n router.use('/chat', await createChatRouter(options));\n router.use('/models', await createModelRouter(options));\n router.use('/mcp', await createMcpRouter(options));\n\n const middleware = MiddlewareFactory.create(options);\n\n router.use(middleware.error());\n\n return router;\n}\n"],"names":["Router","express","createChatRouter","createModelRouter","createMcpRouter","MiddlewareFactory"],"mappings":";;;;;;;;;;;;;;AAiBA,eAAsB,aACpB,OAAA,EACyB;AACzB,EAAA,MAAM,SAASA,uBAAA,EAAO;AACtB,EAAA,MAAA,CAAO,GAAA,CAAIC,wBAAA,CAAQ,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,MAAMC,qBAAA,CAAiB,OAAO,CAAC,CAAA;AACnD,EAAA,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,MAAMC,wBAAA,CAAkB,OAAO,CAAC,CAAA;AACtD,EAAA,MAAA,CAAO,GAAA,CAAI,MAAA,EAAQ,MAAMC,mBAAA,CAAgB,OAAO,CAAC,CAAA;AAEjD,EAAA,MAAM,UAAA,GAAaC,gCAAA,CAAkB,MAAA,CAAO,OAAO,CAAA;AAEnD,EAAA,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,KAAA,EAAO,CAAA;AAE7B,EAAA,OAAO,MAAA;AACT;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../../../src/services/router/index.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { createChatRouter, ChatRouterOptions } from './chat';\nimport { createModelRouter } from './models';\nimport {\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\nimport { createMcpRouter, McpRouterOptions } from './mcp';\nimport { SummaryRouterOptions, createSummaryRouter } from './summary';\n\nexport type RouterOptions = ChatRouterOptions &\n SummaryRouterOptions &\n McpRouterOptions & {\n config: RootConfigService;\n logger: LoggerService;\n };\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const router = Router();\n router.use(express.json());\n\n router.use('/chat', await createChatRouter(options));\n router.use('/models', await createModelRouter(options));\n router.use('/mcp', await createMcpRouter(options));\n router.use('/summary', await createSummaryRouter(options));\n\n const middleware = MiddlewareFactory.create(options);\n\n router.use(middleware.error());\n\n return router;\n}\n"],"names":["Router","express","createChatRouter","createModelRouter","createMcpRouter","createSummaryRouter","MiddlewareFactory"],"mappings":";;;;;;;;;;;;;;;AAmBA,eAAsB,aACpB,OAAA,EACyB;AACzB,EAAA,MAAM,SAASA,uBAAA,EAAO;AACtB,EAAA,MAAA,CAAO,GAAA,CAAIC,wBAAA,CAAQ,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAA,CAAO,GAAA,CAAI,OAAA,EAAS,MAAMC,qBAAA,CAAiB,OAAO,CAAC,CAAA;AACnD,EAAA,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,MAAMC,wBAAA,CAAkB,OAAO,CAAC,CAAA;AACtD,EAAA,MAAA,CAAO,GAAA,CAAI,MAAA,EAAQ,MAAMC,mBAAA,CAAgB,OAAO,CAAC,CAAA;AACjD,EAAA,MAAA,CAAO,GAAA,CAAI,UAAA,EAAY,MAAMC,2BAAA,CAAoB,OAAO,CAAC,CAAA;AAEzD,EAAA,MAAM,UAAA,GAAaC,gCAAA,CAAkB,MAAA,CAAO,OAAO,CAAA;AAEnD,EAAA,MAAA,CAAO,GAAA,CAAI,UAAA,CAAW,KAAA,EAAO,CAAA;AAE7B,EAAA,OAAO,MAAA;AACT;;;;"}
@@ -0,0 +1,56 @@
1
+ 'use strict';
2
+
3
+ var Router = require('express-promise-router');
4
+ var validation = require('./middleware/validation.cjs.js');
5
+ var z = require('zod');
6
+
7
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
8
+
9
+ var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
10
+ var z__default = /*#__PURE__*/_interopDefaultCompat(z);
11
+
12
+ async function createSummaryRouter(options) {
13
+ const { summarizer } = options;
14
+ const router = Router__default.default();
15
+ const contentSchema = z__default.default.object({
16
+ content: z__default.default.string(),
17
+ length: z__default.default.string().optional()
18
+ });
19
+ router.post(
20
+ "/content",
21
+ validation.validation(contentSchema, "body"),
22
+ async (req, res) => {
23
+ const { content, length } = req.body;
24
+ const summary = await summarizer.summarize({
25
+ content,
26
+ length
27
+ });
28
+ res.json({ summary });
29
+ }
30
+ );
31
+ const conversationSchema = z__default.default.object({
32
+ messages: z__default.default.array(
33
+ z__default.default.object({
34
+ role: z__default.default.string(),
35
+ content: z__default.default.string()
36
+ })
37
+ ),
38
+ length: z__default.default.string().optional()
39
+ });
40
+ router.post(
41
+ "/conversation",
42
+ validation.validation(conversationSchema, "body"),
43
+ async (req, res) => {
44
+ const { messages, length } = req.body;
45
+ const summary = await summarizer.summarizeConversation({
46
+ messages,
47
+ length
48
+ });
49
+ res.json({ summary });
50
+ }
51
+ );
52
+ return router;
53
+ }
54
+
55
+ exports.createSummaryRouter = createSummaryRouter;
56
+ //# sourceMappingURL=summary.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.cjs.js","sources":["../../../src/services/router/summary.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { SummarizerService } from '../summarizer';\nimport { validation } from './middleware/validation';\nimport z from 'zod';\n\nexport type SummaryRouterOptions = {\n summarizer: SummarizerService;\n};\n\nexport async function createSummaryRouter(\n options: SummaryRouterOptions,\n): Promise<express.Router> {\n const { summarizer } = options;\n\n const router = Router();\n\n const contentSchema = z.object({\n content: z.string(),\n length: z.string().optional(),\n });\n\n router.post(\n '/content',\n validation(contentSchema, 'body'),\n async (req, res) => {\n const { content, length } = req.body;\n\n const summary = await summarizer.summarize({\n content,\n length,\n });\n res.json({ summary });\n },\n );\n\n const conversationSchema = z.object({\n messages: z.array(\n z.object({\n role: z.string(),\n content: z.string(),\n }),\n ),\n length: z.string().optional(),\n });\n\n router.post(\n '/conversation',\n validation(conversationSchema, 'body'),\n async (req, res) => {\n const { messages, length } = req.body;\n const summary = await summarizer.summarizeConversation({\n messages,\n length,\n });\n res.json({ summary });\n },\n );\n\n return router;\n}\n"],"names":["Router","z","validation"],"mappings":";;;;;;;;;;;AAUA,eAAsB,oBACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,YAAW,GAAI,OAAA;AAEvB,EAAA,MAAM,SAASA,uBAAA,EAAO;AAEtB,EAAA,MAAM,aAAA,GAAgBC,mBAAE,MAAA,CAAO;AAAA,IAC7B,OAAA,EAASA,mBAAE,MAAA,EAAO;AAAA,IAClB,MAAA,EAAQA,kBAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAAS,GAC7B,CAAA;AAED,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,UAAA;AAAA,IACAC,qBAAA,CAAW,eAAe,MAAM,CAAA;AAAA,IAChC,OAAO,KAAK,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAO,GAAI,GAAA,CAAI,IAAA;AAEhC,MAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,SAAA,CAAU;AAAA,QACzC,OAAA;AAAA,QACA;AAAA,OACD,CAAA;AACD,MAAA,GAAA,CAAI,IAAA,CAAK,EAAE,OAAA,EAAS,CAAA;AAAA,IACtB;AAAA,GACF;AAEA,EAAA,MAAM,kBAAA,GAAqBD,mBAAE,MAAA,CAAO;AAAA,IAClC,UAAUA,kBAAA,CAAE,KAAA;AAAA,MACVA,mBAAE,MAAA,CAAO;AAAA,QACP,IAAA,EAAMA,mBAAE,MAAA,EAAO;AAAA,QACf,OAAA,EAASA,mBAAE,MAAA;AAAO,OACnB;AAAA,KACH;AAAA,IACA,MAAA,EAAQA,kBAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAAS,GAC7B,CAAA;AAED,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,eAAA;AAAA,IACAC,qBAAA,CAAW,oBAAoB,MAAM,CAAA;AAAA,IACrC,OAAO,KAAK,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,QAAA,EAAU,MAAA,EAAO,GAAI,GAAA,CAAI,IAAA;AACjC,MAAA,MAAM,OAAA,GAAU,MAAM,UAAA,CAAW,qBAAA,CAAsB;AAAA,QACrD,QAAA;AAAA,QACA;AAAA,OACD,CAAA;AACD,MAAA,GAAA,CAAI,IAAA,CAAK,EAAE,OAAA,EAAS,CAAA;AAAA,IACtB;AAAA,GACF;AAEA,EAAA,OAAO,MAAA;AACT;;;;"}
@@ -9,34 +9,26 @@ const createSummarizerService = async ({
9
9
  callback
10
10
  }) => {
11
11
  const summaryModelId = config.getOptionalString("aiAssistant.conversation.summaryModel") ?? models[0].id;
12
- const summaryPrompt = config.getOptionalString("aiAssistant.conversation.summaryPrompt") ?? prompts.DEFAULT_SUMMARY_PROMPT;
12
+ const conversationSummaryPrompt = config.getOptionalString("aiAssistant.conversation.summaryPrompt") ?? prompts.DEFAULT_CONVERSATION_SUMMARY_PROMPT;
13
13
  const model = models.find((m) => m.id === summaryModelId);
14
14
  if (!model) {
15
15
  throw new Error(`Summary model with id ${summaryModelId} not found`);
16
16
  }
17
17
  const llm = model.chatModel;
18
- const chatPromptTemplate = prompts$1.ChatPromptTemplate.fromMessages([
19
- prompts$1.SystemMessagePromptTemplate.fromTemplate(`
20
- PURPOSE:
21
- {summaryPrompt}
18
+ const summaryPromptTemplate = prompts$1.PromptTemplate.fromTemplate(`
19
+ PURPOSE:
20
+ {summaryPrompt}
22
21
 
23
- Please summarize the following conversation in {summaryLength}.
24
- `),
25
- prompts$1.HumanMessagePromptTemplate.fromTemplate(`
26
- Conversation:
27
- {conversation}
22
+ Summarize the following content in {length}.
28
23
 
29
- Please provide a summary of this conversation.
30
- `)
31
- ]);
32
- const summarize = async (messages, summaryLength = "as few words as possible") => {
33
- const conversationMessages = messages.filter(
34
- (msg) => msg.role === "ai" || msg.role === "human"
35
- );
36
- const prompt = await chatPromptTemplate.formatMessages({
24
+ Content:
25
+ {content}
26
+ `);
27
+ const summarize = async (content, summaryPrompt = prompts.DEFAULT_SUMMARY_PROMPT, length = "as few words as possible") => {
28
+ const prompt = await summaryPromptTemplate.format({
37
29
  summaryPrompt,
38
- summaryLength,
39
- conversation: conversationMessages.map((msg) => `${msg.role}: ${msg.content}`).join("\n")
30
+ content,
31
+ length
40
32
  });
41
33
  const { callbacks } = await callback.getChainCallbacks({
42
34
  conversationId: "summarizer",
@@ -55,7 +47,18 @@ const createSummarizerService = async ({
55
47
  });
56
48
  return text.trim();
57
49
  };
58
- return { summarize };
50
+ const summarizeConversation = async ({ messages, length = "as few words as possible" }) => {
51
+ const conversationMessages = messages.filter(
52
+ (msg) => msg.role === "ai" || msg.role === "human"
53
+ );
54
+ const conversation = conversationMessages.map((msg) => `${msg.role}: ${msg.content}`).join("\n");
55
+ return summarize({
56
+ content: conversation,
57
+ prompt: conversationSummaryPrompt,
58
+ length
59
+ });
60
+ };
61
+ return { summarizeConversation, summarize };
59
62
  };
60
63
 
61
64
  exports.createSummarizerService = createSummarizerService;
@@ -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 { DEFAULT_SUMMARY_PROMPT } from '../constants/prompts';\nimport {\n SystemMessagePromptTemplate,\n HumanMessagePromptTemplate,\n ChatPromptTemplate,\n} from '@langchain/core/prompts';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { CallbackService } from './callbacks';\n\ntype SummarizerService = {\n summarize: (\n conversationMessages: Message[],\n summaryLength?: 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 summaryPrompt =\n config.getOptionalString('aiAssistant.conversation.summaryPrompt') ??\n DEFAULT_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 chatPromptTemplate = ChatPromptTemplate.fromMessages([\n SystemMessagePromptTemplate.fromTemplate(`\n PURPOSE:\n {summaryPrompt}\n\n Please summarize the following conversation in {summaryLength}.\n `),\n HumanMessagePromptTemplate.fromTemplate(`\n Conversation:\n {conversation}\n\n Please provide a summary of this conversation.\n `),\n ]);\n\n const summarize: SummarizerService['summarize'] = async (\n messages,\n summaryLength = 'as few words as possible',\n ) => {\n const conversationMessages = messages.filter(\n msg => msg.role === 'ai' || msg.role === 'human',\n );\n\n const prompt = await chatPromptTemplate.formatMessages({\n summaryPrompt,\n summaryLength,\n conversation: conversationMessages\n .map(msg => `${msg.role}: ${msg.content}`)\n .join('\\n'),\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 return { summarize };\n};\n"],"names":["DEFAULT_SUMMARY_PROMPT","ChatPromptTemplate","SystemMessagePromptTemplate","HumanMessagePromptTemplate"],"mappings":";;;;;AAwBO,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,aAAA,GACJ,MAAA,CAAO,iBAAA,CAAkB,wCAAwC,CAAA,IACjEA,8BAAA;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,kBAAA,GAAqBC,6BAAmB,YAAA,CAAa;AAAA,IACzDC,sCAA4B,YAAA,CAAa;AAAA;AAAA;;AAAA;AAAA,IAAA,CAKxC,CAAA;AAAA,IACDC,qCAA2B,YAAA,CAAa;AAAA;AAAA;;AAAA;AAAA,IAAA,CAKvC;AAAA,GACF,CAAA;AAED,EAAA,MAAM,SAAA,GAA4C,OAChD,QAAA,EACA,aAAA,GAAgB,0BAAA,KACb;AACH,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,MAAA,GAAS,MAAM,kBAAA,CAAmB,cAAA,CAAe;AAAA,MACrD,aAAA;AAAA,MACA,aAAA;AAAA,MACA,YAAA,EAAc,oBAAA,CACX,GAAA,CAAI,CAAA,GAAA,KAAO,CAAA,EAAG,GAAA,CAAI,IAAI,CAAA,EAAA,EAAK,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA,CACxC,KAAK,IAAI;AAAA,KACb,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,OAAO,EAAE,SAAA,EAAU;AACrB;;;;"}
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;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sweetoburrito/backstage-plugin-ai-assistant-backend",
3
- "version": "0.0.0-snapshot-20251114135736",
3
+ "version": "0.0.0-snapshot-20251118091900",
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.0.0-snapshot-20251114135736",
47
- "@sweetoburrito/backstage-plugin-ai-assistant-node": "0.0.0-snapshot-20251114135736",
46
+ "@sweetoburrito/backstage-plugin-ai-assistant-common": "0.0.0-snapshot-20251118091900",
47
+ "@sweetoburrito/backstage-plugin-ai-assistant-node": "0.0.0-snapshot-20251118091900",
48
48
  "express": "^4.17.1",
49
49
  "express-promise-router": "^4.1.0",
50
50
  "knex": "^3.1.0",