@sweetoburrito/backstage-plugin-ai-assistant-backend 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@ class ChatStore {
17
17
  return this.client(TABLE_NAME);
18
18
  }
19
19
  async getChatMessages(conversationId, userRef, limit) {
20
- let query = this.table().where({ conversation_id: conversationId, userRef }).select("*");
20
+ let query = this.table().where({ conversation_id: conversationId, userRef }).select("*").orderBy("created_at", "asc");
21
21
  if (typeof limit === "number") {
22
22
  query = query.limit(limit).orderBy("created_at", "desc");
23
23
  }
@@ -40,6 +40,12 @@ class ChatStore {
40
40
  }));
41
41
  await this.table().insert(rows);
42
42
  }
43
+ async updateMessage(message) {
44
+ await this.table().where({ id: message.id }).update({
45
+ role: message.role,
46
+ content: message.content
47
+ });
48
+ }
43
49
  }
44
50
 
45
51
  exports.ChatStore = ChatStore;
@@ -1 +1 @@
1
- {"version":3,"file":"chat-store.cjs.js","sources":["../../src/database/chat-store.ts"],"sourcesContent":["import { DatabaseService } from '@backstage/backend-plugin-api';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-node';\n\nimport { Knex } from 'knex';\n\nconst TABLE_NAME = 'conversation';\n\nexport type ChatStoreOptions = {\n database: DatabaseService;\n};\n\nexport class ChatStore {\n /**\n * Creates an instance of ChatStore.\n * @param client - The Knex client to interact with the PostgreSQL database.\n */\n constructor(private readonly client: Knex) {}\n\n static async fromConfig({ database }: ChatStoreOptions) {\n const client = await database.getClient();\n return new ChatStore(client);\n }\n\n table() {\n return this.client(TABLE_NAME);\n }\n\n async getChatMessages(\n conversationId: string,\n userRef: string,\n limit?: number,\n ): Promise<Required<Message>[]> {\n let query = this.table()\n .where({ conversation_id: conversationId, userRef })\n .select('*');\n\n if (typeof limit === 'number') {\n query = query.limit(limit).orderBy('created_at', 'desc');\n }\n\n const rows = await query;\n\n const chatMessages: Required<Message>[] = rows.map(row => ({\n role: row.role,\n content: row.content,\n id: row.id,\n }));\n\n return chatMessages;\n }\n\n async addChatMessage(\n messages: Message[],\n userRef: string,\n conversationId: string,\n ): Promise<void> {\n const rows = messages.map(msg => ({\n id: msg.id,\n conversation_id: conversationId,\n role: msg.role,\n content: msg.content,\n userRef,\n created_at: this.client.fn.now(),\n }));\n\n await this.table().insert(rows);\n }\n}\n"],"names":[],"mappings":";;AAKA,MAAM,UAAA,GAAa,cAAA;AAMZ,MAAM,SAAA,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrB,YAA6B,MAAA,EAAc;AAAd,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAe;AAAA,EAE5C,aAAa,UAAA,CAAW,EAAE,QAAA,EAAS,EAAqB;AACtD,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,SAAA,EAAU;AACxC,IAAA,OAAO,IAAI,UAAU,MAAM,CAAA;AAAA,EAC7B;AAAA,EAEA,KAAA,GAAQ;AACN,IAAA,OAAO,IAAA,CAAK,OAAO,UAAU,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,eAAA,CACJ,cAAA,EACA,OAAA,EACA,KAAA,EAC8B;AAC9B,IAAA,IAAI,KAAA,GAAQ,IAAA,CAAK,KAAA,EAAM,CACpB,KAAA,CAAM,EAAE,eAAA,EAAiB,cAAA,EAAgB,OAAA,EAAS,CAAA,CAClD,MAAA,CAAO,GAAG,CAAA;AAEb,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,KAAA,GAAQ,MAAM,KAAA,CAAM,KAAK,CAAA,CAAE,OAAA,CAAQ,cAAc,MAAM,CAAA;AAAA,IACzD;AAEA,IAAA,MAAM,OAAO,MAAM,KAAA;AAEnB,IAAA,MAAM,YAAA,GAAoC,IAAA,CAAK,GAAA,CAAI,CAAA,GAAA,MAAQ;AAAA,MACzD,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,IAAI,GAAA,CAAI;AAAA,KACV,CAAE,CAAA;AAEF,IAAA,OAAO,YAAA;AAAA,EACT;AAAA,EAEA,MAAM,cAAA,CACJ,QAAA,EACA,OAAA,EACA,cAAA,EACe;AACf,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,CAAA,GAAA,MAAQ;AAAA,MAChC,IAAI,GAAA,CAAI,EAAA;AAAA,MACR,eAAA,EAAiB,cAAA;AAAA,MACjB,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,OAAA;AAAA,MACA,UAAA,EAAY,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,GAAA;AAAI,KACjC,CAAE,CAAA;AAEF,IAAA,MAAM,IAAA,CAAK,KAAA,EAAM,CAAE,MAAA,CAAO,IAAI,CAAA;AAAA,EAChC;AACF;;;;"}
1
+ {"version":3,"file":"chat-store.cjs.js","sources":["../../src/database/chat-store.ts"],"sourcesContent":["import { DatabaseService } from '@backstage/backend-plugin-api';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\nimport { Knex } from 'knex';\n\nconst TABLE_NAME = 'conversation';\n\nexport type ChatStoreOptions = {\n database: DatabaseService;\n};\n\nexport class ChatStore {\n /**\n * Creates an instance of ChatStore.\n * @param client - The Knex client to interact with the PostgreSQL database.\n */\n constructor(private readonly client: Knex) {}\n\n static async fromConfig({ database }: ChatStoreOptions) {\n const client = await database.getClient();\n return new ChatStore(client);\n }\n\n table() {\n return this.client(TABLE_NAME);\n }\n\n async getChatMessages(\n conversationId: string,\n userRef: string,\n limit?: number,\n ): Promise<Required<Message>[]> {\n let query = this.table()\n .where({ conversation_id: conversationId, userRef })\n .select('*')\n .orderBy('created_at', 'asc');\n\n if (typeof limit === 'number') {\n query = query.limit(limit).orderBy('created_at', 'desc');\n }\n\n const rows = await query;\n\n const chatMessages: Required<Message>[] = rows.map(row => ({\n role: row.role,\n content: row.content,\n id: row.id,\n }));\n\n return chatMessages;\n }\n\n async addChatMessage(\n messages: Message[],\n userRef: string,\n conversationId: string,\n ): Promise<void> {\n const rows = messages.map(msg => ({\n id: msg.id,\n conversation_id: conversationId,\n role: msg.role,\n content: msg.content,\n userRef,\n created_at: this.client.fn.now(),\n }));\n\n await this.table().insert(rows);\n }\n\n async updateMessage(message: Required<Message>) {\n await this.table().where({ id: message.id }).update({\n role: message.role,\n content: message.content,\n });\n }\n}\n"],"names":[],"mappings":";;AAKA,MAAM,UAAA,GAAa,cAAA;AAMZ,MAAM,SAAA,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrB,YAA6B,MAAA,EAAc;AAAd,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAe;AAAA,EAE5C,aAAa,UAAA,CAAW,EAAE,QAAA,EAAS,EAAqB;AACtD,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,SAAA,EAAU;AACxC,IAAA,OAAO,IAAI,UAAU,MAAM,CAAA;AAAA,EAC7B;AAAA,EAEA,KAAA,GAAQ;AACN,IAAA,OAAO,IAAA,CAAK,OAAO,UAAU,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,eAAA,CACJ,cAAA,EACA,OAAA,EACA,KAAA,EAC8B;AAC9B,IAAA,IAAI,QAAQ,IAAA,CAAK,KAAA,EAAM,CACpB,KAAA,CAAM,EAAE,eAAA,EAAiB,cAAA,EAAgB,OAAA,EAAS,EAClD,MAAA,CAAO,GAAG,CAAA,CACV,OAAA,CAAQ,cAAc,KAAK,CAAA;AAE9B,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,KAAA,GAAQ,MAAM,KAAA,CAAM,KAAK,CAAA,CAAE,OAAA,CAAQ,cAAc,MAAM,CAAA;AAAA,IACzD;AAEA,IAAA,MAAM,OAAO,MAAM,KAAA;AAEnB,IAAA,MAAM,YAAA,GAAoC,IAAA,CAAK,GAAA,CAAI,CAAA,GAAA,MAAQ;AAAA,MACzD,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,IAAI,GAAA,CAAI;AAAA,KACV,CAAE,CAAA;AAEF,IAAA,OAAO,YAAA;AAAA,EACT;AAAA,EAEA,MAAM,cAAA,CACJ,QAAA,EACA,OAAA,EACA,cAAA,EACe;AACf,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,CAAA,GAAA,MAAQ;AAAA,MAChC,IAAI,GAAA,CAAI,EAAA;AAAA,MACR,eAAA,EAAiB,cAAA;AAAA,MACjB,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,SAAS,GAAA,CAAI,OAAA;AAAA,MACb,OAAA;AAAA,MACA,UAAA,EAAY,IAAA,CAAK,MAAA,CAAO,EAAA,CAAG,GAAA;AAAI,KACjC,CAAE,CAAA;AAEF,IAAA,MAAM,IAAA,CAAK,KAAA,EAAM,CAAE,MAAA,CAAO,IAAI,CAAA;AAAA,EAChC;AAAA,EAEA,MAAM,cAAc,OAAA,EAA4B;AAC9C,IAAA,MAAM,IAAA,CAAK,KAAA,EAAM,CAAE,KAAA,CAAM,EAAE,IAAI,OAAA,CAAQ,EAAA,EAAI,CAAA,CAAE,MAAA,CAAO;AAAA,MAClD,MAAM,OAAA,CAAQ,IAAA;AAAA,MACd,SAAS,OAAA,CAAQ;AAAA,KAClB,CAAA;AAAA,EACH;AACF;;;;"}
@@ -8,6 +8,7 @@ var chat = require('./services/chat.cjs.js');
8
8
  var prompt = require('./services/prompt.cjs.js');
9
9
  var migrations = require('./database/migrations.cjs.js');
10
10
  var pgVectorStore = require('./database/pg-vector-store.cjs.js');
11
+ var pluginSignalsNode = require('@backstage/plugin-signals-node');
11
12
 
12
13
  const aiAssistantPlugin = backendPluginApi.createBackendPlugin({
13
14
  pluginId: "ai-assistant",
@@ -48,7 +49,8 @@ const aiAssistantPlugin = backendPluginApi.createBackendPlugin({
48
49
  config: backendPluginApi.coreServices.rootConfig,
49
50
  scheduler: backendPluginApi.coreServices.scheduler,
50
51
  httpAuth: backendPluginApi.coreServices.httpAuth,
51
- userInfo: backendPluginApi.coreServices.userInfo
52
+ userInfo: backendPluginApi.coreServices.userInfo,
53
+ signals: pluginSignalsNode.signalsServiceRef
52
54
  },
53
55
  async init(options) {
54
56
  const { httpRouter, database } = options;
@@ -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} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { createDataIngestionPipeline } from './services/ingestor';\nimport { createChatService } from './services/chat';\nimport { createPromptBuilder } from './services/prompt';\nimport { applyDatabaseMigrations } from './database/migrations';\nimport { PgVectorStore } from './database';\n\n/**\n * aiAssistantPlugin backend plugin\n *\n * @public\n */\nexport const aiAssistantPlugin = createBackendPlugin({\n pluginId: 'ai-assistant',\n register(env) {\n const ingestors: Ingestor[] = [];\n const models: Model[] = [];\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.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 },\n\n async init(options) {\n const { httpRouter, database } = options;\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 promptBuilder = createPromptBuilder(options);\n\n const chat = await createChatService({\n ...options,\n models,\n vectorStore,\n promptBuilder,\n });\n\n httpRouter.use(await createRouter({ ...options, chat }));\n dataIngestionPipeline.start();\n },\n });\n },\n});\n"],"names":["createBackendPlugin","dataIngestorExtensionPoint","embeddingsProviderExtensionPoint","modelProviderExtensionPoint","coreServices","applyDatabaseMigrations","PgVectorStore","createDataIngestionPipeline","createPromptBuilder","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} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport { createDataIngestionPipeline } from './services/ingestor';\nimport { createChatService } from './services/chat';\nimport { createPromptBuilder } from './services/prompt';\nimport { applyDatabaseMigrations } from './database/migrations';\nimport { PgVectorStore } from './database';\nimport { signalsServiceRef } from '@backstage/plugin-signals-node';\n\n/**\n * aiAssistantPlugin backend plugin\n *\n * @public\n */\nexport const aiAssistantPlugin = createBackendPlugin({\n pluginId: 'ai-assistant',\n register(env) {\n const ingestors: Ingestor[] = [];\n const models: Model[] = [];\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.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 },\n\n async init(options) {\n const { httpRouter, database } = options;\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 promptBuilder = createPromptBuilder(options);\n\n const chat = await createChatService({\n ...options,\n models,\n vectorStore,\n promptBuilder,\n });\n\n httpRouter.use(await createRouter({ ...options, chat }));\n dataIngestionPipeline.start();\n },\n });\n },\n});\n"],"names":["createBackendPlugin","dataIngestorExtensionPoint","embeddingsProviderExtensionPoint","modelProviderExtensionPoint","coreServices","signalsServiceRef","applyDatabaseMigrations","PgVectorStore","createDataIngestionPipeline","createPromptBuilder","chat","createChatService","createRouter"],"mappings":"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"}
@@ -8,18 +8,48 @@ const createChatService = async ({
8
8
  logger,
9
9
  vectorStore,
10
10
  promptBuilder,
11
- database
11
+ database,
12
+ signals
12
13
  }) => {
13
14
  logger.info(`Available models: ${models.map((m) => m.id).join(", ")}`);
14
15
  const chatStore$1 = await chatStore.ChatStore.fromConfig({ database });
15
16
  const getChatModelById = (id) => {
16
17
  return models.find((model) => model.id === id)?.chatModel;
17
18
  };
19
+ const streamMessage = async ({
20
+ modelId,
21
+ messages,
22
+ messageId,
23
+ userEntityRef
24
+ }) => {
25
+ const model = getChatModelById(modelId);
26
+ if (!model) {
27
+ throw new Error(`Model with id ${modelId} not found`);
28
+ }
29
+ const promptStream = await model.stream(messages);
30
+ const aiMessage = {
31
+ id: messageId,
32
+ role: "assistant",
33
+ content: ""
34
+ };
35
+ for await (const chunk of promptStream) {
36
+ aiMessage.content += chunk.content ?? "";
37
+ chatStore$1.updateMessage(aiMessage);
38
+ signals.publish({
39
+ channel: `ai-assistant.chat.message-stream:${messageId}`,
40
+ message: aiMessage,
41
+ recipients: {
42
+ type: "user",
43
+ entityRef: userEntityRef
44
+ }
45
+ });
46
+ }
47
+ };
18
48
  const prompt = async ({
19
49
  conversationId,
20
50
  messages,
21
51
  modelId,
22
- stream,
52
+ stream = true,
23
53
  userEntityRef
24
54
  }) => {
25
55
  const model = getChatModelById(modelId);
@@ -39,20 +69,26 @@ const createChatService = async ({
39
69
  [...recentConversationMessages, ...messages],
40
70
  context
41
71
  );
42
- const responseId = uuid.v4();
72
+ const messageId = uuid.v4();
73
+ const aiMessage = {
74
+ id: messageId,
75
+ role: "assistant",
76
+ content: ""
77
+ };
78
+ await chatStore$1.addChatMessage([aiMessage], userEntityRef, conversationId);
43
79
  if (stream) {
44
- throw new Error("Not Implemented");
80
+ streamMessage({
81
+ modelId,
82
+ messages: promptMessages,
83
+ messageId,
84
+ userEntityRef
85
+ });
86
+ return [aiMessage];
45
87
  }
46
- const response = await model.invoke(promptMessages);
47
- const aiMessages = [
48
- {
49
- id: responseId,
50
- role: "assistant",
51
- content: response.text
52
- }
53
- ];
54
- chatStore$1.addChatMessage(aiMessages, userEntityRef, conversationId);
55
- return aiMessages;
88
+ const { text } = await model.invoke(promptMessages);
89
+ aiMessage.content = text;
90
+ await chatStore$1.updateMessage(aiMessage);
91
+ return [aiMessage];
56
92
  };
57
93
  const getAvailableModels = async () => {
58
94
  return models.map((x) => x.id);
@@ -1 +1 @@
1
- {"version":3,"file":"chat.cjs.js","sources":["../../src/services/chat.ts"],"sourcesContent":["import {\n Message,\n Model,\n VectorStore,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport {\n LoggerService,\n RootConfigService,\n DatabaseService,\n} from '@backstage/backend-plugin-api';\nimport { PromptBuilder } from './prompt';\nimport { v4 as uuid } from 'uuid';\nimport { ChatStore } from '../database/chat-store';\n\nexport type ChatServiceOptions = {\n models: Model[];\n logger: LoggerService;\n vectorStore: VectorStore;\n config: RootConfigService;\n promptBuilder: PromptBuilder;\n database: DatabaseService;\n};\n\ntype PromptOptions = {\n modelId: string;\n messages: Message[];\n conversationId: string;\n stream: boolean;\n userEntityRef: string;\n};\n\ntype GetConversationOptions = {\n conversationId: string;\n userEntityRef: string;\n};\n\nexport type ChatService = {\n prompt: (options: PromptOptions) => Promise<Required<Message>[]>;\n getAvailableModels: () => Promise<string[]>;\n getConversation: (\n options: GetConversationOptions,\n ) => Promise<Required<Message>[]>;\n};\n\nexport const createChatService = async ({\n models,\n logger,\n vectorStore,\n promptBuilder,\n database,\n}: ChatServiceOptions): Promise<ChatService> => {\n logger.info(`Available models: ${models.map(m => m.id).join(', ')}`);\n\n const chatStore = await ChatStore.fromConfig({ database });\n\n const getChatModelById = (id: string) => {\n return models.find(model => model.id === id)?.chatModel;\n };\n\n const prompt: ChatService['prompt'] = async ({\n conversationId,\n messages,\n modelId,\n stream,\n userEntityRef,\n }: PromptOptions) => {\n const model = getChatModelById(modelId);\n\n if (!model) {\n throw new Error(`Model with id ${modelId} not found`);\n }\n\n chatStore.addChatMessage(messages, userEntityRef, conversationId);\n\n const context = await vectorStore.similaritySearch(\n messages\n .filter(m => m.role === 'user')\n .map(m => m.content)\n .join('\\n'),\n );\n\n const recentConversationMessages = await chatStore.getChatMessages(\n conversationId,\n userEntityRef,\n 10,\n );\n\n const promptMessages = promptBuilder.buildPrompt(\n [...recentConversationMessages, ...messages],\n context,\n );\n\n const responseId: string = uuid();\n\n if (stream) {\n // Handle streaming response\n throw new Error('Not Implemented');\n }\n\n const response = await model.invoke(promptMessages);\n\n const aiMessages: Required<Message>[] = [\n {\n id: responseId,\n role: 'assistant',\n content: response.text,\n },\n ];\n\n chatStore.addChatMessage(aiMessages, userEntityRef, conversationId);\n\n return aiMessages;\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 return {\n prompt,\n getAvailableModels,\n getConversation,\n };\n};\n"],"names":["chatStore","ChatStore","uuid"],"mappings":";;;;;AA4CO,MAAM,oBAAoB,OAAO;AAAA,EACtC,MAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;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;AAEnE,EAAA,MAAMA,cAAY,MAAMC,mBAAA,CAAU,UAAA,CAAW,EAAE,UAAU,CAAA;AAEzD,EAAA,MAAM,gBAAA,GAAmB,CAAC,EAAA,KAAe;AACvC,IAAA,OAAO,OAAO,IAAA,CAAK,CAAA,KAAA,KAAS,KAAA,CAAM,EAAA,KAAO,EAAE,CAAA,EAAG,SAAA;AAAA,EAChD,CAAA;AAEA,EAAA,MAAM,SAAgC,OAAO;AAAA,IAC3C,cAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF,KAAqB;AACnB,IAAA,MAAM,KAAA,GAAQ,iBAAiB,OAAO,CAAA;AAEtC,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,OAAO,CAAA,UAAA,CAAY,CAAA;AAAA,IACtD;AAEA,IAAAD,WAAA,CAAU,cAAA,CAAe,QAAA,EAAU,aAAA,EAAe,cAAc,CAAA;AAEhE,IAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,gBAAA;AAAA,MAChC,QAAA,CACG,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,IAAA,KAAS,MAAM,CAAA,CAC7B,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,CAAA,CAClB,KAAK,IAAI;AAAA,KACd;AAEA,IAAA,MAAM,0BAAA,GAA6B,MAAMA,WAAA,CAAU,eAAA;AAAA,MACjD,cAAA;AAAA,MACA,aAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,iBAAiB,aAAA,CAAc,WAAA;AAAA,MACnC,CAAC,GAAG,0BAAA,EAA4B,GAAG,QAAQ,CAAA;AAAA,MAC3C;AAAA,KACF;AAEA,IAAA,MAAM,aAAqBE,OAAA,EAAK;AAEhC,IAAA,IAAI,MAAA,EAAQ;AAEV,MAAA,MAAM,IAAI,MAAM,iBAAiB,CAAA;AAAA,IACnC;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,MAAA,CAAO,cAAc,CAAA;AAElD,IAAA,MAAM,UAAA,GAAkC;AAAA,MACtC;AAAA,QACE,EAAA,EAAI,UAAA;AAAA,QACJ,IAAA,EAAM,WAAA;AAAA,QACN,SAAS,QAAA,CAAS;AAAA;AACpB,KACF;AAEA,IAAAF,WAAA,CAAU,cAAA,CAAe,UAAA,EAAY,aAAA,EAAe,cAAc,CAAA;AAElE,IAAA,OAAO,UAAA;AAAA,EACT,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,MAAMA,WAAA,CAAU,eAAA;AAAA,MACnC,cAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO,YAAA;AAAA,EACT,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"chat.cjs.js","sources":["../../src/services/chat.ts"],"sourcesContent":["import {\n Model,\n VectorStore,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\nimport {\n LoggerService,\n RootConfigService,\n DatabaseService,\n} from '@backstage/backend-plugin-api';\nimport { PromptBuilder } from './prompt';\nimport { v4 as uuid } from 'uuid';\nimport { ChatStore } from '../database/chat-store';\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\nimport { SignalsService } from '@backstage/plugin-signals-node';\n\nexport type ChatServiceOptions = {\n models: Model[];\n logger: LoggerService;\n vectorStore: VectorStore;\n config: RootConfigService;\n promptBuilder: PromptBuilder;\n database: DatabaseService;\n signals: SignalsService;\n};\n\ntype StreamOptions = {\n modelId: string;\n messages: Message[];\n messageId: string;\n userEntityRef: string;\n};\n\ntype PromptOptions = {\n modelId: string;\n messages: Message[];\n conversationId: string;\n stream?: boolean;\n userEntityRef: string;\n};\n\ntype GetConversationOptions = {\n conversationId: string;\n userEntityRef: string;\n};\n\nexport type ChatService = {\n prompt: (options: PromptOptions) => Promise<Required<Message>[]>;\n getAvailableModels: () => Promise<string[]>;\n getConversation: (\n options: GetConversationOptions,\n ) => Promise<Required<Message>[]>;\n};\n\nexport const createChatService = async ({\n models,\n logger,\n vectorStore,\n promptBuilder,\n database,\n signals,\n}: ChatServiceOptions): Promise<ChatService> => {\n logger.info(`Available models: ${models.map(m => m.id).join(', ')}`);\n\n const chatStore = await ChatStore.fromConfig({ database });\n\n const getChatModelById = (id: string) => {\n return models.find(model => model.id === id)?.chatModel;\n };\n\n const streamMessage = async ({\n modelId,\n messages,\n messageId,\n userEntityRef,\n }: StreamOptions) => {\n const model = getChatModelById(modelId);\n\n if (!model) {\n throw new Error(`Model with id ${modelId} not found`);\n }\n\n const promptStream = await model.stream(messages);\n\n const aiMessage: Required<Message> = {\n id: messageId,\n role: 'assistant',\n content: '',\n };\n\n for await (const chunk of promptStream) {\n aiMessage.content += chunk.content ?? '';\n\n chatStore.updateMessage(aiMessage);\n\n signals.publish({\n channel: `ai-assistant.chat.message-stream:${messageId}`,\n message: aiMessage,\n recipients: {\n type: 'user',\n entityRef: userEntityRef,\n },\n });\n }\n };\n\n const prompt: ChatService['prompt'] = async ({\n conversationId,\n messages,\n modelId,\n stream = true,\n userEntityRef,\n }: PromptOptions) => {\n const model = getChatModelById(modelId);\n\n if (!model) {\n throw new Error(`Model with id ${modelId} not found`);\n }\n\n chatStore.addChatMessage(messages, userEntityRef, conversationId);\n\n const context = await vectorStore.similaritySearch(\n messages\n .filter(m => m.role === 'user')\n .map(m => m.content)\n .join('\\n'),\n );\n\n const recentConversationMessages = await chatStore.getChatMessages(\n conversationId,\n userEntityRef,\n 10,\n );\n\n const promptMessages = promptBuilder.buildPrompt(\n [...recentConversationMessages, ...messages],\n context,\n );\n\n const messageId: string = uuid();\n\n const aiMessage: Required<Message> = {\n id: messageId,\n role: 'assistant',\n content: '',\n };\n\n await chatStore.addChatMessage([aiMessage], userEntityRef, conversationId);\n\n if (stream) {\n streamMessage({\n modelId,\n messages: promptMessages,\n messageId,\n userEntityRef,\n });\n\n return [aiMessage];\n }\n const { text } = await model.invoke(promptMessages);\n\n aiMessage.content = text;\n\n await chatStore.updateMessage(aiMessage);\n\n return [aiMessage];\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 return {\n prompt,\n getAvailableModels,\n getConversation,\n };\n};\n"],"names":["chatStore","ChatStore","uuid"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.cjs.js","sources":["../../src/services/prompt.ts"],"sourcesContent":["import { RootConfigService } from '@backstage/backend-plugin-api';\nimport {\n Message,\n EmbeddingDocument,\n} from '@sweetoburrito/backstage-plugin-ai-assistant-node';\n\ntype PromptBuilderOptions = {\n config: RootConfigService;\n};\n\nexport type PromptBuilder = {\n buildPrompt: (\n chatHistory: Message[],\n promptContext: EmbeddingDocument[],\n ) => Message[];\n};\n\nconst DEFAULT_SYSTEM_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\nRules:\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. Format answers clearly and concisely. Use bullet points for lists when appropriate.\n4. Maintain a professional, friendly, and helpful tone.\n5. Return only the relevant information without any filler or unnecessary details.\n6. If you don't know the answer, admit it and suggest ways to find the information.\n7. Always return a well-structured response using markdown.\n`;\n\nexport const createPromptBuilder = ({\n config,\n}: PromptBuilderOptions): PromptBuilder => {\n const system = config.getOptionalString('system') || DEFAULT_SYSTEM_PROMPT;\n\n const getContext = (context: EmbeddingDocument[]) => {\n return `\n Context:\n ${context.map(doc => JSON.stringify(doc)).join('\\n')}\n `;\n };\n\n const buildPrompt: PromptBuilder['buildPrompt'] = (\n chatHistory,\n promptContext,\n ) => {\n const context = getContext(promptContext);\n\n return [\n {\n role: 'system',\n content: system.concat(context),\n },\n ...chatHistory,\n ];\n };\n\n return {\n buildPrompt,\n };\n};\n"],"names":[],"mappings":";;AAiBA,MAAM,qBAAA,GAAwB;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAavB,MAAM,sBAAsB,CAAC;AAAA,EAClC;AACF,CAAA,KAA2C;AACzC,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,iBAAA,CAAkB,QAAQ,CAAA,IAAK,qBAAA;AAErD,EAAA,MAAM,UAAA,GAAa,CAAC,OAAA,KAAiC;AACnD,IAAA,OAAO;AAAA;AAAA,IAAA,EAEL,OAAA,CAAQ,GAAA,CAAI,CAAA,GAAA,KAAO,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC;AAAA,IAAA,CAAA;AAAA,EAEtD,CAAA;AAEA,EAAA,MAAM,WAAA,GAA4C,CAChD,WAAA,EACA,aAAA,KACG;AACH,IAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AAExC,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,OAAO;AAAA,OAChC;AAAA,MACA,GAAG;AAAA,KACL;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"prompt.cjs.js","sources":["../../src/services/prompt.ts"],"sourcesContent":["import { RootConfigService } from '@backstage/backend-plugin-api';\nimport { EmbeddingDocument } from '@sweetoburrito/backstage-plugin-ai-assistant-node';\n\nimport { Message } from '@sweetoburrito/backstage-plugin-ai-assistant-common';\n\ntype PromptBuilderOptions = {\n config: RootConfigService;\n};\n\nexport type PromptBuilder = {\n buildPrompt: (\n chatHistory: Message[],\n promptContext: EmbeddingDocument[],\n ) => Message[];\n};\n\nconst DEFAULT_SYSTEM_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\nRules:\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. Format answers clearly and concisely. Use bullet points for lists when appropriate.\n4. Maintain a professional, friendly, and helpful tone.\n5. Return only the relevant information without any filler or unnecessary details.\n6. If you don't know the answer, admit it and suggest ways to find the information.\n7. Always return a well-structured response using markdown.\n`;\n\nexport const createPromptBuilder = ({\n config,\n}: PromptBuilderOptions): PromptBuilder => {\n const system = config.getOptionalString('system') || DEFAULT_SYSTEM_PROMPT;\n\n const getContext = (context: EmbeddingDocument[]) => {\n return `\n Context:\n ${context.map(doc => JSON.stringify(doc)).join('\\n')}\n `;\n };\n\n const buildPrompt: PromptBuilder['buildPrompt'] = (\n chatHistory,\n promptContext,\n ) => {\n const context = getContext(promptContext);\n\n return [\n {\n role: 'system',\n content: system.concat(context),\n },\n ...chatHistory,\n ];\n };\n\n return {\n buildPrompt,\n };\n};\n"],"names":[],"mappings":";;AAgBA,MAAM,qBAAA,GAAwB;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAavB,MAAM,sBAAsB,CAAC;AAAA,EAClC;AACF,CAAA,KAA2C;AACzC,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,iBAAA,CAAkB,QAAQ,CAAA,IAAK,qBAAA;AAErD,EAAA,MAAM,UAAA,GAAa,CAAC,OAAA,KAAiC;AACnD,IAAA,OAAO;AAAA;AAAA,IAAA,EAEL,OAAA,CAAQ,GAAA,CAAI,CAAA,GAAA,KAAO,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC;AAAA,IAAA,CAAA;AAAA,EAEtD,CAAA;AAEA,EAAA,MAAM,WAAA,GAA4C,CAChD,WAAA,EACA,aAAA,KACG;AACH,IAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AAExC,IAAA,OAAO;AAAA,MACL;AAAA,QACE,IAAA,EAAM,QAAA;AAAA,QACN,OAAA,EAAS,MAAA,CAAO,MAAA,CAAO,OAAO;AAAA,OAChC;AAAA,MACA,GAAG;AAAA,KACL;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL;AAAA,GACF;AACF;;;;"}
@@ -1,6 +1,5 @@
1
1
  'use strict';
2
2
 
3
- var express = require('express');
4
3
  var Router = require('express-promise-router');
5
4
  var z = require('zod');
6
5
  var validation = require('./middleware/validation.cjs.js');
@@ -8,14 +7,12 @@ var uuid = require('uuid');
8
7
 
9
8
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
10
9
 
11
- var express__default = /*#__PURE__*/_interopDefaultCompat(express);
12
10
  var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
13
11
  var z__default = /*#__PURE__*/_interopDefaultCompat(z);
14
12
 
15
13
  async function createChatRouter(options) {
16
14
  const { chat, httpAuth, userInfo } = options;
17
15
  const router = Router__default.default();
18
- router.use(express__default.default.json());
19
16
  const messageSchema = z__default.default.object({
20
17
  messages: z__default.default.array(
21
18
  z__default.default.object({
@@ -26,7 +23,7 @@ async function createChatRouter(options) {
26
23
  ),
27
24
  modelId: z__default.default.string(),
28
25
  conversationId: z__default.default.string().uuid().optional().default(uuid.v4),
29
- stream: z__default.default.boolean().optional().default(false)
26
+ stream: z__default.default.boolean().optional()
30
27
  });
31
28
  router.post(
32
29
  "/message",
@@ -51,8 +48,8 @@ async function createChatRouter(options) {
51
48
  const chatSchema = z__default.default.object({
52
49
  id: z__default.default.string().uuid()
53
50
  });
54
- router.get("/", validation.validation(chatSchema, "body"), async (req, res) => {
55
- const { id } = req.body;
51
+ router.get("/:id", validation.validation(chatSchema, "params"), async (req, res) => {
52
+ const { id } = req.params;
56
53
  const credentials = await httpAuth.credentials(req);
57
54
  const { userEntityRef } = await userInfo.getUserInfo(credentials);
58
55
  const conversation = await chat.getConversation({
@@ -1 +1 @@
1
- {"version":3,"file":"chat.cjs.js","sources":["../../../src/services/router/chat.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { ChatService } from '../chat';\nimport z from 'zod';\nimport { validation } from './middleware/validation';\nimport { v4 as uuid } from 'uuid';\nimport {\n DatabaseService,\n HttpAuthService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\n\nexport type ChatRouterOptions = {\n chat: ChatService;\n database: DatabaseService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n};\n\nexport async function createChatRouter(\n options: ChatRouterOptions,\n): Promise<express.Router> {\n const { chat, httpAuth, userInfo } = options;\n\n const router = Router();\n router.use(express.json());\n\n const messageSchema = z.object({\n messages: z.array(\n z.object({\n id: z.string().uuid().optional().default(uuid),\n role: z.string(),\n content: z.string(),\n }),\n ),\n modelId: z.string(),\n conversationId: z.string().uuid().optional().default(uuid),\n stream: z.boolean().optional().default(false),\n });\n\n router.post(\n '/message',\n validation(messageSchema, 'body'),\n async (req, res) => {\n const { messages, conversationId, modelId, stream } = req.body;\n\n const credentials = await httpAuth.credentials(req);\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n\n const responseMessages = await chat.prompt({\n modelId,\n messages,\n conversationId,\n stream,\n userEntityRef,\n });\n\n res.json({\n messages: responseMessages,\n conversationId,\n });\n },\n );\n\n const chatSchema = z.object({\n id: z.string().uuid(),\n });\n\n router.get('/', validation(chatSchema, 'body'), async (req, res) => {\n const { id } = req.body;\n\n const credentials = await httpAuth.credentials(req);\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n\n const conversation = await chat.getConversation({\n conversationId: id,\n userEntityRef,\n });\n res.json({ conversation });\n });\n\n return router;\n}\n"],"names":["Router","express","z","uuid","validation"],"mappings":";;;;;;;;;;;;;;AAmBA,eAAsB,iBACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAS,GAAI,OAAA;AAErC,EAAA,MAAM,SAASA,uBAAA,EAAO;AACtB,EAAA,MAAA,CAAO,GAAA,CAAIC,wBAAA,CAAQ,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAM,aAAA,GAAgBC,mBAAE,MAAA,CAAO;AAAA,IAC7B,UAAUA,kBAAA,CAAE,KAAA;AAAA,MACVA,mBAAE,MAAA,CAAO;AAAA,QACP,EAAA,EAAIA,mBAAE,MAAA,EAAO,CAAE,MAAK,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQC,OAAI,CAAA;AAAA,QAC7C,IAAA,EAAMD,mBAAE,MAAA,EAAO;AAAA,QACf,OAAA,EAASA,mBAAE,MAAA;AAAO,OACnB;AAAA,KACH;AAAA,IACA,OAAA,EAASA,mBAAE,MAAA,EAAO;AAAA,IAClB,cAAA,EAAgBA,mBAAE,MAAA,EAAO,CAAE,MAAK,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQC,OAAI,CAAA;AAAA,IACzD,QAAQD,kBAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAAE,QAAQ,KAAK;AAAA,GAC7C,CAAA;AAED,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,UAAA;AAAA,IACAE,qBAAA,CAAW,eAAe,MAAM,CAAA;AAAA,IAChC,OAAO,KAAK,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,QAAA,EAAU,cAAA,EAAgB,OAAA,EAAS,MAAA,KAAW,GAAA,CAAI,IAAA;AAE1D,MAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA;AAClD,MAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAEhE,MAAA,MAAM,gBAAA,GAAmB,MAAM,IAAA,CAAK,MAAA,CAAO;AAAA,QACzC,OAAA;AAAA,QACA,QAAA;AAAA,QACA,cAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,GAAA,CAAI,IAAA,CAAK;AAAA,QACP,QAAA,EAAU,gBAAA;AAAA,QACV;AAAA,OACD,CAAA;AAAA,IACH;AAAA,GACF;AAEA,EAAA,MAAM,UAAA,GAAaF,mBAAE,MAAA,CAAO;AAAA,IAC1B,EAAA,EAAIA,kBAAA,CAAE,MAAA,EAAO,CAAE,IAAA;AAAK,GACrB,CAAA;AAED,EAAA,MAAA,CAAO,GAAA,CAAI,KAAKE,qBAAA,CAAW,UAAA,EAAY,MAAM,CAAA,EAAG,OAAO,KAAK,GAAA,KAAQ;AAClE,IAAA,MAAM,EAAE,EAAA,EAAG,GAAI,GAAA,CAAI,IAAA;AAEnB,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA;AAClD,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAEhE,IAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,eAAA,CAAgB;AAAA,MAC9C,cAAA,EAAgB,EAAA;AAAA,MAChB;AAAA,KACD,CAAA;AACD,IAAA,GAAA,CAAI,IAAA,CAAK,EAAE,YAAA,EAAc,CAAA;AAAA,EAC3B,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;"}
1
+ {"version":3,"file":"chat.cjs.js","sources":["../../../src/services/router/chat.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { ChatService } from '../chat';\nimport z from 'zod';\nimport { validation } from './middleware/validation';\nimport { v4 as uuid } from 'uuid';\nimport {\n DatabaseService,\n HttpAuthService,\n UserInfoService,\n} from '@backstage/backend-plugin-api';\n\nexport type ChatRouterOptions = {\n chat: ChatService;\n database: DatabaseService;\n httpAuth: HttpAuthService;\n userInfo: UserInfoService;\n};\n\nexport async function createChatRouter(\n options: ChatRouterOptions,\n): Promise<express.Router> {\n const { chat, httpAuth, userInfo } = options;\n\n const router = Router();\n\n const messageSchema = z.object({\n messages: z.array(\n z.object({\n id: z.string().uuid().optional().default(uuid),\n role: z.string(),\n content: z.string(),\n }),\n ),\n modelId: z.string(),\n conversationId: z.string().uuid().optional().default(uuid),\n stream: z.boolean().optional(),\n });\n\n router.post(\n '/message',\n validation(messageSchema, 'body'),\n async (req, res) => {\n const { messages, conversationId, modelId, stream } = req.body;\n\n const credentials = await httpAuth.credentials(req);\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n\n const responseMessages = await chat.prompt({\n modelId,\n messages,\n conversationId,\n stream,\n userEntityRef,\n });\n\n res.json({\n messages: responseMessages,\n conversationId,\n });\n },\n );\n\n const chatSchema = z.object({\n id: z.string().uuid(),\n });\n\n router.get('/:id', validation(chatSchema, 'params'), async (req, res) => {\n const { id } = req.params;\n\n const credentials = await httpAuth.credentials(req);\n const { userEntityRef } = await userInfo.getUserInfo(credentials);\n\n const conversation = await chat.getConversation({\n conversationId: id,\n userEntityRef,\n });\n\n res.json({ conversation });\n });\n\n return router;\n}\n"],"names":["Router","z","uuid","validation"],"mappings":";;;;;;;;;;;;AAmBA,eAAsB,iBACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAS,GAAI,OAAA;AAErC,EAAA,MAAM,SAASA,uBAAA,EAAO;AAEtB,EAAA,MAAM,aAAA,GAAgBC,mBAAE,MAAA,CAAO;AAAA,IAC7B,UAAUA,kBAAA,CAAE,KAAA;AAAA,MACVA,mBAAE,MAAA,CAAO;AAAA,QACP,EAAA,EAAIA,mBAAE,MAAA,EAAO,CAAE,MAAK,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQC,OAAI,CAAA;AAAA,QAC7C,IAAA,EAAMD,mBAAE,MAAA,EAAO;AAAA,QACf,OAAA,EAASA,mBAAE,MAAA;AAAO,OACnB;AAAA,KACH;AAAA,IACA,OAAA,EAASA,mBAAE,MAAA,EAAO;AAAA,IAClB,cAAA,EAAgBA,mBAAE,MAAA,EAAO,CAAE,MAAK,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQC,OAAI,CAAA;AAAA,IACzD,MAAA,EAAQD,kBAAA,CAAE,OAAA,EAAQ,CAAE,QAAA;AAAS,GAC9B,CAAA;AAED,EAAA,MAAA,CAAO,IAAA;AAAA,IACL,UAAA;AAAA,IACAE,qBAAA,CAAW,eAAe,MAAM,CAAA;AAAA,IAChC,OAAO,KAAK,GAAA,KAAQ;AAClB,MAAA,MAAM,EAAE,QAAA,EAAU,cAAA,EAAgB,OAAA,EAAS,MAAA,KAAW,GAAA,CAAI,IAAA;AAE1D,MAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA;AAClD,MAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAEhE,MAAA,MAAM,gBAAA,GAAmB,MAAM,IAAA,CAAK,MAAA,CAAO;AAAA,QACzC,OAAA;AAAA,QACA,QAAA;AAAA,QACA,cAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,GAAA,CAAI,IAAA,CAAK;AAAA,QACP,QAAA,EAAU,gBAAA;AAAA,QACV;AAAA,OACD,CAAA;AAAA,IACH;AAAA,GACF;AAEA,EAAA,MAAM,UAAA,GAAaF,mBAAE,MAAA,CAAO;AAAA,IAC1B,EAAA,EAAIA,kBAAA,CAAE,MAAA,EAAO,CAAE,IAAA;AAAK,GACrB,CAAA;AAED,EAAA,MAAA,CAAO,GAAA,CAAI,QAAQE,qBAAA,CAAW,UAAA,EAAY,QAAQ,CAAA,EAAG,OAAO,KAAK,GAAA,KAAQ;AACvE,IAAA,MAAM,EAAE,EAAA,EAAG,GAAI,GAAA,CAAI,MAAA;AAEnB,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA;AAClD,IAAA,MAAM,EAAE,aAAA,EAAc,GAAI,MAAM,QAAA,CAAS,YAAY,WAAW,CAAA;AAEhE,IAAA,MAAM,YAAA,GAAe,MAAM,IAAA,CAAK,eAAA,CAAgB;AAAA,MAC9C,cAAA,EAAgB,EAAA;AAAA,MAChB;AAAA,KACD,CAAA;AAED,IAAA,GAAA,CAAI,IAAA,CAAK,EAAE,YAAA,EAAc,CAAA;AAAA,EAC3B,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;"}
@@ -1,17 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var express = require('express');
4
3
  var Router = require('express-promise-router');
5
4
 
6
5
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
7
6
 
8
- var express__default = /*#__PURE__*/_interopDefaultCompat(express);
9
7
  var Router__default = /*#__PURE__*/_interopDefaultCompat(Router);
10
8
 
11
9
  async function createModelRouter(options) {
12
10
  const { chat } = options;
13
11
  const router = Router__default.default();
14
- router.use(express__default.default.json());
15
12
  router.get("/", async (_req, res) => {
16
13
  const models = await chat.getAvailableModels();
17
14
  res.json({ models });
@@ -1 +1 @@
1
- {"version":3,"file":"models.cjs.js","sources":["../../../src/services/router/models.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { ChatService } from '../chat';\n\nexport type ModelRouterOptions = {\n chat: ChatService;\n};\n\nexport async function createModelRouter(\n options: ModelRouterOptions,\n): Promise<express.Router> {\n const { chat } = options;\n const router = Router();\n router.use(express.json());\n\n router.get('/', async (_req, res) => {\n const models = await chat.getAvailableModels();\n res.json({ models });\n });\n\n return router;\n}\n"],"names":["Router","express"],"mappings":";;;;;;;;;;AAQA,eAAsB,kBACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,MAAK,GAAI,OAAA;AACjB,EAAA,MAAM,SAASA,uBAAA,EAAO;AACtB,EAAA,MAAA,CAAO,GAAA,CAAIC,wBAAA,CAAQ,IAAA,EAAM,CAAA;AAEzB,EAAA,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,OAAO,IAAA,EAAM,GAAA,KAAQ;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,kBAAA,EAAmB;AAC7C,IAAA,GAAA,CAAI,IAAA,CAAK,EAAE,MAAA,EAAQ,CAAA;AAAA,EACrB,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;"}
1
+ {"version":3,"file":"models.cjs.js","sources":["../../../src/services/router/models.ts"],"sourcesContent":["import express from 'express';\nimport Router from 'express-promise-router';\nimport { ChatService } from '../chat';\n\nexport type ModelRouterOptions = {\n chat: ChatService;\n};\n\nexport async function createModelRouter(\n options: ModelRouterOptions,\n): Promise<express.Router> {\n const { chat } = options;\n const router = Router();\n\n router.get('/', async (_req, res) => {\n const models = await chat.getAvailableModels();\n res.json({ models });\n });\n\n return router;\n}\n"],"names":["Router"],"mappings":";;;;;;;;AAQA,eAAsB,kBACpB,OAAA,EACyB;AACzB,EAAA,MAAM,EAAE,MAAK,GAAI,OAAA;AACjB,EAAA,MAAM,SAASA,uBAAA,EAAO;AAEtB,EAAA,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,OAAO,IAAA,EAAM,GAAA,KAAQ;AACnC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,kBAAA,EAAmB;AAC7C,IAAA,GAAA,CAAI,IAAA,CAAK,EAAE,MAAA,EAAQ,CAAA;AAAA,EACrB,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sweetoburrito/backstage-plugin-ai-assistant-backend",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "dist/index.cjs.js",
6
6
  "types": "dist/index.d.ts",
@@ -13,7 +13,9 @@
13
13
  "role": "backend-plugin",
14
14
  "pluginId": "ai-assistant",
15
15
  "pluginPackages": [
16
+ "@sweetoburrito/backstage-plugin-ai-assistant",
16
17
  "@sweetoburrito/backstage-plugin-ai-assistant-backend",
18
+ "@sweetoburrito/backstage-plugin-ai-assistant-common",
17
19
  "@sweetoburrito/backstage-plugin-ai-assistant-node"
18
20
  ],
19
21
  "features": {
@@ -34,8 +36,10 @@
34
36
  "@backstage/backend-plugin-api": "backstage:^",
35
37
  "@backstage/catalog-client": "backstage:^",
36
38
  "@backstage/errors": "backstage:^",
39
+ "@backstage/plugin-signals-node": "backstage:^",
37
40
  "@langchain/core": "^0.3.72",
38
41
  "@langchain/textsplitters": "^0.1.0",
42
+ "@sweetoburrito/backstage-plugin-ai-assistant-common": "workspace:^",
39
43
  "@sweetoburrito/backstage-plugin-ai-assistant-node": "workspace:^",
40
44
  "express": "^4.17.1",
41
45
  "express-promise-router": "^4.1.0",
@@ -46,7 +50,15 @@
46
50
  "devDependencies": {
47
51
  "@backstage/backend-test-utils": "backstage:^",
48
52
  "@backstage/cli": "backstage:^",
53
+ "@backstage/plugin-auth-backend": "backstage:^",
54
+ "@backstage/plugin-auth-backend-module-guest-provider": "backstage:^",
55
+ "@backstage/plugin-catalog-backend": "backstage:^",
56
+ "@backstage/plugin-signals-backend": "backstage:^",
49
57
  "@backstage/types": "backstage:^",
58
+ "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-embeddings-provider-ollama": "workspace:^",
59
+ "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-ingestor-catalog": "workspace:^",
60
+ "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-azure-ai": "workspace:^",
61
+ "@sweetoburrito/backstage-plugin-ai-assistant-backend-module-model-provider-ollama": "workspace:^",
50
62
  "@types/express": "^4.0.0",
51
63
  "@types/supertest": "^2.0.12",
52
64
  "supertest": "^6.2.4"