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

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.
@@ -55,9 +55,9 @@ const aiAssistantPlugin = backendPluginApi.createBackendPlugin({
55
55
  tools.push(tool);
56
56
  }
57
57
  });
58
- env.registerExtensionPoint(backstagePluginAiAssistantNode.callbackFactoryExtensionPoint, {
59
- register: (callbackFactory) => {
60
- callbacks$1.push(callbackFactory);
58
+ env.registerExtensionPoint(backstagePluginAiAssistantNode.callbackProviderExtensionPoint, {
59
+ register: (callbackProvider) => {
60
+ callbacks$1.push(callbackProvider);
61
61
  }
62
62
  });
63
63
  env.registerInit({
@@ -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 callbackFactoryExtensionPoint,\n CallbackFactory,\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: CallbackFactory[] = [];\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(callbackFactoryExtensionPoint, {\n register: callbackFactory => {\n callbacks.push(callbackFactory);\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","callbackFactoryExtensionPoint","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';\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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"}
@@ -3,23 +3,45 @@
3
3
  const createCallbackService = async ({
4
4
  callbacks
5
5
  }) => {
6
- const getAgentCallbackData = async (options) => {
7
- const metadata = {};
6
+ const getChainCallbacks = async (options) => {
8
7
  const callbackHandlers = [];
9
- for (const createCallback of callbacks) {
10
- const { metadata: cbMetadata, callback } = await createCallback(
11
- options
12
- );
13
- Object.assign(metadata, cbMetadata);
14
- callbackHandlers.push(callback);
8
+ for (const { chainCallback } of callbacks) {
9
+ if (!chainCallback) {
10
+ continue;
11
+ }
12
+ const callbackHandler = await chainCallback(options);
13
+ callbackHandlers.push(callbackHandler);
15
14
  }
16
15
  return {
17
- metadata,
18
16
  callbacks: callbackHandlers
19
17
  };
20
18
  };
19
+ const getChainMetadata = async (options) => {
20
+ const metadata = {};
21
+ for (const { chainMetadataCallback } of callbacks) {
22
+ if (!chainMetadataCallback) {
23
+ continue;
24
+ }
25
+ const callbackData = await chainMetadataCallback(options);
26
+ Object.assign(metadata, callbackData.metadata);
27
+ }
28
+ return { metadata };
29
+ };
30
+ const handleScoreCallbacks = async ({
31
+ name,
32
+ message
33
+ }) => {
34
+ callbacks.forEach(async ({ scoreCallback }) => {
35
+ if (!scoreCallback) {
36
+ return;
37
+ }
38
+ scoreCallback({ name, message });
39
+ });
40
+ };
21
41
  return {
22
- getAgentCallbackData
42
+ getChainCallbacks,
43
+ getChainMetadata,
44
+ handleScoreCallbacks
23
45
  };
24
46
  };
25
47
 
@@ -1 +1 @@
1
- {"version":3,"file":"callbacks.cjs.js","sources":["../../src/services/callbacks.ts"],"sourcesContent":["import {\n Callback,\n CallbackFactory,\n CallbackOptions,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\n\nexport type CallbackService = {\n getAgentCallbackData: (options: CallbackOptions) => Promise<{\n metadata: Callback['metadata'];\n callbacks: Callback['callback'][];\n }>;\n};\n\nexport type CreateCallbackServiceOptions = {\n callbacks: CallbackFactory[];\n};\n\nexport const createCallbackService = async ({\n callbacks,\n}: CreateCallbackServiceOptions): Promise<CallbackService> => {\n const getAgentCallbackData: CallbackService['getAgentCallbackData'] =\n async options => {\n const metadata = {};\n const callbackHandlers: Callback['callback'][] = [];\n\n for (const createCallback of callbacks) {\n const { metadata: cbMetadata, callback } = await createCallback(\n options,\n );\n Object.assign(metadata, cbMetadata);\n callbackHandlers.push(callback);\n }\n\n return {\n metadata,\n callbacks: callbackHandlers,\n };\n };\n\n return {\n getAgentCallbackData,\n };\n};\n"],"names":[],"mappings":";;AAiBO,MAAM,wBAAwB,OAAO;AAAA,EAC1C;AACF,CAAA,KAA8D;AAC5D,EAAA,MAAM,oBAAA,GACJ,OAAM,OAAA,KAAW;AACf,IAAA,MAAM,WAAW,EAAC;AAClB,IAAA,MAAM,mBAA2C,EAAC;AAElD,IAAA,KAAA,MAAW,kBAAkB,SAAA,EAAW;AACtC,MAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAY,QAAA,KAAa,MAAM,cAAA;AAAA,QAC/C;AAAA,OACF;AACA,MAAA,MAAA,CAAO,MAAA,CAAO,UAAU,UAAU,CAAA;AAClC,MAAA,gBAAA,CAAiB,KAAK,QAAQ,CAAA;AAAA,IAChC;AAEA,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACb;AAAA,EACF,CAAA;AAEF,EAAA,OAAO;AAAA,IACL;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"callbacks.cjs.js","sources":["../../src/services/callbacks.ts"],"sourcesContent":["import {\n CallbackProvider,\n ChainMetadata,\n ChainCallbackOptions,\n ChainCallback,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\n\nexport type CallbackService = {\n getChainCallbacks: (options: ChainCallbackOptions) => Promise<{\n callbacks: ReturnType<ChainCallback>[];\n }>;\n\n getChainMetadata: (\n options: ChainCallbackOptions,\n ) => Promise<{ metadata: ChainMetadata }>;\n\n handleScoreCallbacks: NonNullable<CallbackProvider['scoreCallback']>;\n};\n\nexport type CreateCallbackServiceOptions = {\n callbacks: CallbackProvider[];\n};\n\nexport const createCallbackService = async ({\n callbacks,\n}: CreateCallbackServiceOptions): Promise<CallbackService> => {\n const getChainCallbacks: CallbackService['getChainCallbacks'] =\n async options => {\n const callbackHandlers: ReturnType<ChainCallback>[] = [];\n\n for (const { chainCallback } of callbacks) {\n if (!chainCallback) {\n continue;\n }\n\n const callbackHandler = await chainCallback(options);\n\n callbackHandlers.push(callbackHandler);\n }\n\n return {\n callbacks: callbackHandlers,\n };\n };\n\n const getChainMetadata: CallbackService['getChainMetadata'] =\n async options => {\n const metadata: ChainMetadata = {};\n\n for (const { chainMetadataCallback } of callbacks) {\n if (!chainMetadataCallback) {\n continue;\n }\n\n const callbackData = await chainMetadataCallback(options);\n\n Object.assign(metadata, callbackData.metadata);\n }\n\n return { metadata };\n };\n\n const handleScoreCallbacks: CallbackService['handleScoreCallbacks'] = async ({\n name,\n message,\n }) => {\n callbacks.forEach(async ({ scoreCallback }) => {\n if (!scoreCallback) {\n return;\n }\n\n scoreCallback({ name, message });\n });\n };\n\n return {\n getChainCallbacks,\n getChainMetadata,\n handleScoreCallbacks,\n };\n};\n"],"names":[],"mappings":";;AAuBO,MAAM,wBAAwB,OAAO;AAAA,EAC1C;AACF,CAAA,KAA8D;AAC5D,EAAA,MAAM,iBAAA,GACJ,OAAM,OAAA,KAAW;AACf,IAAA,MAAM,mBAAgD,EAAC;AAEvD,IAAA,KAAA,MAAW,EAAE,aAAA,EAAc,IAAK,SAAA,EAAW;AACzC,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,eAAA,GAAkB,MAAM,aAAA,CAAc,OAAO,CAAA;AAEnD,MAAA,gBAAA,CAAiB,KAAK,eAAe,CAAA;AAAA,IACvC;AAEA,IAAA,OAAO;AAAA,MACL,SAAA,EAAW;AAAA,KACb;AAAA,EACF,CAAA;AAEF,EAAA,MAAM,gBAAA,GACJ,OAAM,OAAA,KAAW;AACf,IAAA,MAAM,WAA0B,EAAC;AAEjC,IAAA,KAAA,MAAW,EAAE,qBAAA,EAAsB,IAAK,SAAA,EAAW;AACjD,MAAA,IAAI,CAAC,qBAAA,EAAuB;AAC1B,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,YAAA,GAAe,MAAM,qBAAA,CAAsB,OAAO,CAAA;AAExD,MAAA,MAAA,CAAO,MAAA,CAAO,QAAA,EAAU,YAAA,CAAa,QAAQ,CAAA;AAAA,IAC/C;AAEA,IAAA,OAAO,EAAE,QAAA,EAAS;AAAA,EACpB,CAAA;AAEF,EAAA,MAAM,uBAAgE,OAAO;AAAA,IAC3E,IAAA;AAAA,IACA;AAAA,GACF,KAAM;AACJ,IAAA,SAAA,CAAU,OAAA,CAAQ,OAAO,EAAE,aAAA,EAAc,KAAM;AAC7C,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA;AAAA,MACF;AAEA,MAAA,aAAA,CAAc,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAAA,IACjC,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,iBAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
@@ -2,6 +2,7 @@
2
2
 
3
3
  var chatStore = require('../database/chat-store.cjs.js');
4
4
  var prompts = require('../constants/prompts.cjs.js');
5
+ var backstagePluginAiAssistantNode = require('@sweetoburrito/backstage-plugin-ai-assistant-node');
5
6
  var tools = require('@langchain/core/tools');
6
7
  var prebuilt = require('@langchain/langgraph/prebuilt');
7
8
  var prompts$1 = require('@langchain/core/prompts');
@@ -120,7 +121,7 @@ ${contentPrompt}`;
120
121
  ["tool"]
121
122
  );
122
123
  const credentials = await auth.getOwnServiceCredentials();
123
- const user = await getUser(cache, userEntityRef, credentials, catalog);
124
+ const user = await backstagePluginAiAssistantNode.getUser(cache, userEntityRef, credentials, catalog);
124
125
  const mcpTools = await mcp.getTools(userCredentials);
125
126
  const agentTools = tools$1.map((tool) => new tools.DynamicStructuredTool(tool)).concat(mcpTools.map((tool) => new tools.DynamicStructuredTool(tool)));
126
127
  addMessages(
@@ -141,11 +142,17 @@ ${contentPrompt}`;
141
142
  tools: agentTools,
142
143
  prompt: systemPrompt[0].text
143
144
  });
144
- const { metadata: promptMetadata, callbacks } = await callback.getAgentCallbackData({
145
+ const { callbacks } = await callback.getChainCallbacks({
145
146
  conversationId,
146
147
  userId: userEntityRef,
147
148
  modelId
148
149
  });
150
+ const { metadata: promptMetadata } = await callback.getChainMetadata({
151
+ conversationId,
152
+ userId: userEntityRef,
153
+ modelId
154
+ });
155
+ const traceId = uuid.v4();
149
156
  const promptStream = await agent.stream(
150
157
  {
151
158
  messages: [...recentConversationMessages, ...messages]
@@ -153,6 +160,7 @@ ${contentPrompt}`;
153
160
  {
154
161
  streamMode: ["values"],
155
162
  runName: "ai-assistant-chat",
163
+ runId: traceId,
156
164
  metadata: promptMetadata,
157
165
  callbacks
158
166
  }
@@ -160,13 +168,19 @@ ${contentPrompt}`;
160
168
  const responseMessages = [];
161
169
  for await (const [, chunk] of promptStream) {
162
170
  const { messages: promptMessages } = chunk;
163
- const newMessages = promptMessages.filter((m) => responseMessages.findIndex((rm) => rm.id === m.id) === -1).filter(
171
+ const newMessages = promptMessages.filter(
172
+ (m) => responseMessages.findIndex(
173
+ (rm) => m.id === rm.metadata.langGraphId
174
+ ) === -1
175
+ ).filter(
164
176
  (m) => recentConversationMessages.findIndex((rm) => rm.id === m.id) === -1
165
177
  ).filter((m) => m.getType() !== "human").map((m) => {
166
- const id = m.id ?? "";
178
+ const id = uuid.v4();
167
179
  const role = m.getType();
168
180
  const content = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
169
- const metadata = {};
181
+ const metadata = {
182
+ langGraphId: m.id ?? ""
183
+ };
170
184
  if (role === "ai") {
171
185
  const aiMessage = m;
172
186
  metadata.toolCalls = aiMessage.tool_calls || [];
@@ -183,7 +197,7 @@ ${contentPrompt}`;
183
197
  content,
184
198
  metadata,
185
199
  score: 0,
186
- traceId: void 0
200
+ traceId
187
201
  };
188
202
  });
189
203
  for await (const m of newMessages) {
@@ -207,12 +221,10 @@ ${contentPrompt}`;
207
221
  }
208
222
  responseMessages.push(...newMessages);
209
223
  }
210
- addMessages(
211
- responseMessages.map((m) => ({ ...m, id: uuid.v4() })),
212
- userEntityRef,
213
- conversationId,
214
- [...recentConversationMessages, ...messages]
215
- );
224
+ addMessages(responseMessages, userEntityRef, conversationId, [
225
+ ...recentConversationMessages,
226
+ ...messages
227
+ ]);
216
228
  return responseMessages;
217
229
  };
218
230
  const result = streamFn();
@@ -244,8 +256,11 @@ ${contentPrompt}`;
244
256
  ...message,
245
257
  score
246
258
  };
247
- await chatStore$1.updateMessage(updatedMessage);
248
- logger.info(`Message ${messageId} scored ${score}`);
259
+ chatStore$1.updateMessage(updatedMessage);
260
+ callback.handleScoreCallbacks({
261
+ name: "helpfulness",
262
+ message: updatedMessage
263
+ });
249
264
  };
250
265
  return {
251
266
  prompt,
@@ -256,17 +271,6 @@ ${contentPrompt}`;
256
271
  scoreMessage
257
272
  };
258
273
  };
259
- async function getUser(cache, userEntityRef, credentials, catalog) {
260
- const cached = await cache.get(userEntityRef);
261
- if (cached) {
262
- return JSON.parse(String(cached));
263
- }
264
- const user = await catalog.getEntityByRef(userEntityRef, {
265
- credentials
266
- });
267
- await cache.set(userEntityRef, JSON.stringify(user));
268
- return user;
269
- }
270
274
 
271
275
  exports.createChatService = createChatService;
272
276
  //# sourceMappingURL=chat.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat.cjs.js","sources":["../../src/services/chat.ts"],"sourcesContent":["import { Model } from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\nimport { UserEntity } from '@backstage/catalog-model';\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 { Tool } 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 { metadata: promptMetadata, callbacks } =\n await callback.getAgentCallbackData({\n conversationId,\n userId: userEntityRef,\n modelId,\n });\n\n const promptStream = await agent.stream(\n {\n messages: [...recentConversationMessages, ...messages],\n },\n {\n streamMode: ['values'],\n runName: 'ai-assistant-chat',\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(m => responseMessages.findIndex(rm => rm.id === m.id) === -1)\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 = m.id ?? '';\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\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: undefined,\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(\n responseMessages.map(m => ({ ...m, id: uuid() })),\n userEntityRef,\n conversationId,\n [...recentConversationMessages, ...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 await chatStore.updateMessage(updatedMessage);\n logger.info(`Message ${messageId} scored ${score}`);\n };\n\n return {\n prompt,\n getAvailableModels,\n getConversation,\n getConversations,\n addMessages,\n scoreMessage,\n };\n};\n\nasync function getUser(\n cache: CacheService,\n userEntityRef: string,\n credentials: BackstageCredentials,\n catalog: CatalogService,\n) {\n const cached = await cache.get(userEntityRef);\n\n if (cached) {\n return JSON.parse(String(cached));\n }\n\n const user = (await catalog.getEntityByRef(userEntityRef, {\n credentials,\n })) as UserEntity | undefined;\n await cache.set(userEntityRef, JSON.stringify(user));\n\n return user;\n}\n"],"names":["tools","DEFAULT_IDENTITY_PROMPT","DEFAULT_FORMATTING_PROMPT","DEFAULT_SYSTEM_PROMPT","DEFAULT_TOOL_GUIDELINE","chatStore","ChatStore","summarizer","createSummarizerService","SystemMessagePromptTemplate","conversation","DynamicStructuredTool","createReactAgent","uuid"],"mappings":"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"}
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":"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"}
@@ -38,7 +38,12 @@ const createSummarizerService = async ({
38
38
  summaryLength,
39
39
  conversation: conversationMessages.map((msg) => `${msg.role}: ${msg.content}`).join("\n")
40
40
  });
41
- const { callbacks, metadata } = await callback.getAgentCallbackData({
41
+ const { callbacks } = await callback.getChainCallbacks({
42
+ conversationId: "summarizer",
43
+ userId: "system",
44
+ modelId: summaryModelId
45
+ });
46
+ const { metadata } = await callback.getChainMetadata({
42
47
  conversationId: "summarizer",
43
48
  userId: "system",
44
49
  modelId: summaryModelId
@@ -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, metadata } = await callback.getAgentCallbackData({\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,EAAW,QAAA,EAAS,GAAI,MAAM,SAAS,oBAAA,CAAqB;AAAA,MAClE,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 { 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;;;;"}
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-20251113134620",
3
+ "version": "0.0.0-snapshot-20251114135736",
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-20251113134620",
47
- "@sweetoburrito/backstage-plugin-ai-assistant-node": "0.0.0-snapshot-20251113134620",
46
+ "@sweetoburrito/backstage-plugin-ai-assistant-common": "0.0.0-snapshot-20251114135736",
47
+ "@sweetoburrito/backstage-plugin-ai-assistant-node": "0.0.0-snapshot-20251114135736",
48
48
  "express": "^4.17.1",
49
49
  "express-promise-router": "^4.1.0",
50
50
  "knex": "^3.1.0",