@red-hat-developer-hub/backstage-plugin-intelligent-assistant-backend 3.0.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.
- package/CHANGELOG.md +607 -0
- package/README.md +400 -0
- package/app-config.yaml +25 -0
- package/config.d.ts +142 -0
- package/dist/database/migration.cjs.js +19 -0
- package/dist/database/migration.cjs.js.map +1 -0
- package/dist/index.cjs.js +12 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/plugin.cjs.js +95 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/service/constant.cjs.js +107 -0
- package/dist/service/constant.cjs.js.map +1 -0
- package/dist/service/mcp-server-store.cjs.js +107 -0
- package/dist/service/mcp-server-store.cjs.js.map +1 -0
- package/dist/service/mcp-server-validator.cjs.js +215 -0
- package/dist/service/mcp-server-validator.cjs.js.map +1 -0
- package/dist/service/middleware/createPermissionMiddleware.cjs.js +24 -0
- package/dist/service/middleware/createPermissionMiddleware.cjs.js.map +1 -0
- package/dist/service/middleware/createRateLimitMiddleware.cjs.js +52 -0
- package/dist/service/middleware/createRateLimitMiddleware.cjs.js.map +1 -0
- package/dist/service/middleware/getIdentity.cjs.js +39 -0
- package/dist/service/middleware/getIdentity.cjs.js.map +1 -0
- package/dist/service/notebooks/VectorStoresOperator.cjs.js +347 -0
- package/dist/service/notebooks/VectorStoresOperator.cjs.js.map +1 -0
- package/dist/service/notebooks/documents/documentHelpers.cjs.js +36 -0
- package/dist/service/notebooks/documents/documentHelpers.cjs.js.map +1 -0
- package/dist/service/notebooks/documents/documentService.cjs.js +189 -0
- package/dist/service/notebooks/documents/documentService.cjs.js.map +1 -0
- package/dist/service/notebooks/documents/fileParser.cjs.js +139 -0
- package/dist/service/notebooks/documents/fileParser.cjs.js.map +1 -0
- package/dist/service/notebooks/notebooksRouters.cjs.js +477 -0
- package/dist/service/notebooks/notebooksRouters.cjs.js.map +1 -0
- package/dist/service/notebooks/sessions/sessionService.cjs.js +226 -0
- package/dist/service/notebooks/sessions/sessionService.cjs.js.map +1 -0
- package/dist/service/notebooks/types/notebooksTypes.cjs.js +40 -0
- package/dist/service/notebooks/types/notebooksTypes.cjs.js.map +1 -0
- package/dist/service/notebooks/utils.cjs.js +70 -0
- package/dist/service/notebooks/utils.cjs.js.map +1 -0
- package/dist/service/permission.cjs.js +26 -0
- package/dist/service/permission.cjs.js.map +1 -0
- package/dist/service/router.cjs.js +638 -0
- package/dist/service/router.cjs.js.map +1 -0
- package/dist/service/token-encryption.cjs.js +101 -0
- package/dist/service/token-encryption.cjs.js.map +1 -0
- package/dist/service/utils.cjs.js +40 -0
- package/dist/service/utils.cjs.js.map +1 -0
- package/dist/service/validation.cjs.js +45 -0
- package/dist/service/validation.cjs.js.map +1 -0
- package/migrations/20260302120000_add_mcp_servers.js +41 -0
- package/package.json +109 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
var utils = require('../utils.cjs.js');
|
|
5
|
+
|
|
6
|
+
class SessionService {
|
|
7
|
+
logger;
|
|
8
|
+
client;
|
|
9
|
+
providerId;
|
|
10
|
+
constructor(client, logger) {
|
|
11
|
+
this.client = client;
|
|
12
|
+
this.logger = logger;
|
|
13
|
+
this.providerId = "notebooks";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a new notebook session
|
|
17
|
+
* @param userId - User ID creating the session
|
|
18
|
+
* @param name - Session name
|
|
19
|
+
* @param description - Optional session description
|
|
20
|
+
* @param metadata - Optional session metadata
|
|
21
|
+
* @returns Created notebook session
|
|
22
|
+
*/
|
|
23
|
+
async createSession(userId, name, description, metadata) {
|
|
24
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
25
|
+
this.logger.info(`Creating session for user ${userId}`);
|
|
26
|
+
const tempSession = {
|
|
27
|
+
session_id: "temp",
|
|
28
|
+
// Placeholder - will be replaced with vector store ID
|
|
29
|
+
user_id: userId,
|
|
30
|
+
name,
|
|
31
|
+
description: description || "",
|
|
32
|
+
created_at: now,
|
|
33
|
+
updated_at: now,
|
|
34
|
+
metadata: {
|
|
35
|
+
...metadata,
|
|
36
|
+
conversation_id: null,
|
|
37
|
+
provider_id: this.providerId
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const vectorStore = await this.client.vectorStores.create({
|
|
41
|
+
name: name || `Session for ${userId}`,
|
|
42
|
+
provider_id: this.providerId,
|
|
43
|
+
metadata: utils.buildVectorStoreMetadata(tempSession)
|
|
44
|
+
});
|
|
45
|
+
const sessionId = vectorStore.id;
|
|
46
|
+
const session = {
|
|
47
|
+
...tempSession,
|
|
48
|
+
session_id: sessionId,
|
|
49
|
+
document_count: 0
|
|
50
|
+
};
|
|
51
|
+
this.logger.info(`Created session ${sessionId} for user ${userId}`);
|
|
52
|
+
return session;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Retrieve a session and verify ownership
|
|
56
|
+
* @param sessionId - Session ID to retrieve
|
|
57
|
+
* @param userId - User ID requesting access
|
|
58
|
+
* @returns Notebook session
|
|
59
|
+
* @throws NotFoundError if session not found or has no metadata
|
|
60
|
+
* @throws NotAllowedError if user does not own the session
|
|
61
|
+
*/
|
|
62
|
+
async readSession(sessionId, userId) {
|
|
63
|
+
const vectorStore = await this.client.vectorStores.retrieve(sessionId);
|
|
64
|
+
if (!vectorStore.metadata) {
|
|
65
|
+
throw new errors.NotFoundError(`Session ${sessionId} has no metadata`);
|
|
66
|
+
}
|
|
67
|
+
const session = utils.extractSessionFromMetadata(
|
|
68
|
+
sessionId,
|
|
69
|
+
vectorStore.metadata
|
|
70
|
+
);
|
|
71
|
+
if (session.user_id !== userId) {
|
|
72
|
+
throw new errors.NotAllowedError(
|
|
73
|
+
`User ${userId} does not have access to session ${sessionId}`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const filesResponse = await this.client.vectorStores.files.list(sessionId);
|
|
78
|
+
session.document_count = filesResponse.data?.length || 0;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
this.logger.warn(
|
|
81
|
+
`Failed to fetch document count for session ${sessionId}: ${error}`
|
|
82
|
+
);
|
|
83
|
+
session.document_count = 0;
|
|
84
|
+
}
|
|
85
|
+
return session;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Update session details
|
|
89
|
+
* @param sessionId - Session ID to update
|
|
90
|
+
* @param userId - User ID performing the update
|
|
91
|
+
* @param name - New session name (optional)
|
|
92
|
+
* @param description - New session description (optional)
|
|
93
|
+
* @param metadata - New session metadata (optional)
|
|
94
|
+
* @returns Updated notebook session
|
|
95
|
+
* @throws NotAllowedError if user does not own the session
|
|
96
|
+
*/
|
|
97
|
+
async updateSession(sessionId, userId, name, description, metadata) {
|
|
98
|
+
const existing = await this.readSession(sessionId, userId);
|
|
99
|
+
const updated = {
|
|
100
|
+
...existing,
|
|
101
|
+
name: name !== void 0 ? name : existing.name,
|
|
102
|
+
description: description !== void 0 ? description : existing.description,
|
|
103
|
+
metadata: metadata !== void 0 ? metadata : existing.metadata,
|
|
104
|
+
updated_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
105
|
+
};
|
|
106
|
+
const vectorStore = await this.client.vectorStores.retrieve(sessionId);
|
|
107
|
+
await this.client.vectorStores.update(sessionId, {
|
|
108
|
+
embedding_model: vectorStore.embedding_model,
|
|
109
|
+
embedding_dimension: vectorStore.embedding_dimension,
|
|
110
|
+
metadata: utils.buildVectorStoreMetadata(updated)
|
|
111
|
+
});
|
|
112
|
+
return updated;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Delete a session and all associated files
|
|
116
|
+
* @param sessionId - Session ID to delete
|
|
117
|
+
* @param userId - User ID performing the deletion
|
|
118
|
+
* @throws NotAllowedError if user does not own the session
|
|
119
|
+
*/
|
|
120
|
+
async deleteSession(sessionId, userId) {
|
|
121
|
+
const session = await this.readSession(sessionId, userId);
|
|
122
|
+
const conversationId = session.metadata?.conversation_id;
|
|
123
|
+
if (conversationId) {
|
|
124
|
+
try {
|
|
125
|
+
const baseURL = this.client.baseURL;
|
|
126
|
+
const response = await fetch(
|
|
127
|
+
`${baseURL}/v2/conversations/${encodeURIComponent(conversationId)}?user_id=${encodeURIComponent(userId)}`,
|
|
128
|
+
{
|
|
129
|
+
method: "DELETE",
|
|
130
|
+
headers: {
|
|
131
|
+
"Content-Type": "application/json"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
if (!response.ok) {
|
|
136
|
+
this.logger.warn(
|
|
137
|
+
`Failed to delete conversation ${conversationId}: HTTP ${response.status}`
|
|
138
|
+
);
|
|
139
|
+
} else {
|
|
140
|
+
this.logger.info(
|
|
141
|
+
`Deleted conversation ${conversationId} for session ${sessionId}`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
} catch (error) {
|
|
145
|
+
this.logger.warn(
|
|
146
|
+
`Failed to delete conversation ${conversationId}: ${error}`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const filesResponse = await this.client.vectorStores.files.list(sessionId);
|
|
152
|
+
const files = filesResponse.data || [];
|
|
153
|
+
await Promise.all(
|
|
154
|
+
files.map(async (file) => {
|
|
155
|
+
try {
|
|
156
|
+
await this.client.vectorStores.files.delete(sessionId, file.id);
|
|
157
|
+
this.logger.info(
|
|
158
|
+
`Deleted vector store file ${file.id} (${file.attributes?.title || "untitled"})`
|
|
159
|
+
);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
this.logger.warn(
|
|
162
|
+
`Failed to delete vector store file ${file.id}: ${error}`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
);
|
|
167
|
+
} catch (error) {
|
|
168
|
+
this.logger.warn(
|
|
169
|
+
`Failed to clean up files for session ${sessionId}: ${error}`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
await this.client.vectorStores.delete(sessionId);
|
|
173
|
+
this.logger.info(`Session ${sessionId} deleted`);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* List all sessions for a user
|
|
177
|
+
* @param userId - User ID to filter sessions
|
|
178
|
+
* @returns Array of notebook sessions sorted by creation date (newest first)
|
|
179
|
+
*/
|
|
180
|
+
async listSessions(userId) {
|
|
181
|
+
const vectorStoresPage = await this.client.vectorStores.list();
|
|
182
|
+
const vectorStores = vectorStoresPage.data;
|
|
183
|
+
const sessions = [];
|
|
184
|
+
for (const store of vectorStores) {
|
|
185
|
+
const session_user_id = store.metadata?.user_id || "";
|
|
186
|
+
if (session_user_id === userId && store.metadata) {
|
|
187
|
+
try {
|
|
188
|
+
const session = utils.extractSessionFromMetadata(
|
|
189
|
+
store.id,
|
|
190
|
+
store.metadata
|
|
191
|
+
);
|
|
192
|
+
sessions.push(session);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
this.logger.warn(
|
|
195
|
+
`Failed to extract session from vector store ${store.id}: ${error}`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
await Promise.all(
|
|
201
|
+
sessions.map(async (session) => {
|
|
202
|
+
try {
|
|
203
|
+
const filesResponse = await this.client.vectorStores.files.list(
|
|
204
|
+
session.session_id
|
|
205
|
+
);
|
|
206
|
+
session.document_count = filesResponse.data?.length || 0;
|
|
207
|
+
} catch (error) {
|
|
208
|
+
this.logger.warn(
|
|
209
|
+
`Failed to fetch document count for session ${session.session_id}: ${error}`
|
|
210
|
+
);
|
|
211
|
+
session.document_count = 0;
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
);
|
|
215
|
+
return sessions.sort((a, b) => {
|
|
216
|
+
const byTime = new Date(b.created_at).getTime() - new Date(a.created_at).getTime();
|
|
217
|
+
if (byTime !== 0) {
|
|
218
|
+
return byTime;
|
|
219
|
+
}
|
|
220
|
+
return b.session_id.localeCompare(a.session_id);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
exports.SessionService = SessionService;
|
|
226
|
+
//# sourceMappingURL=sessionService.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionService.cjs.js","sources":["../../../../src/service/notebooks/sessions/sessionService.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport { NotAllowedError, NotFoundError } from '@backstage/errors';\n\nimport { NotebookSession, SessionMetadata } from '../types/notebooksTypes';\nimport { buildVectorStoreMetadata, extractSessionFromMetadata } from '../utils';\nimport { VectorStoresOperator } from '../VectorStoresOperator';\n\n/**\n * Service for managing notebook sessions with dedicated vector stores\n * - Session ID is the vector store ID\n * - Session metadata stored in VectorStore metadata field\n * - Uses VectorStoresOperator to proxy through lightspeed-core\n */\nexport class SessionService {\n private logger: LoggerService;\n private client: VectorStoresOperator;\n private providerId: string;\n\n constructor(client: VectorStoresOperator, logger: LoggerService) {\n this.client = client;\n this.logger = logger;\n this.providerId = 'notebooks';\n }\n\n /**\n * Create a new notebook session\n * @param userId - User ID creating the session\n * @param name - Session name\n * @param description - Optional session description\n * @param metadata - Optional session metadata\n * @returns Created notebook session\n */\n async createSession(\n userId: string,\n name: string,\n description?: string,\n metadata?: SessionMetadata,\n ): Promise<NotebookSession> {\n const now = new Date().toISOString();\n\n this.logger.info(`Creating session for user ${userId}`);\n\n // Build temporary session object to generate metadata\n const tempSession: NotebookSession = {\n session_id: 'temp', // Placeholder - will be replaced with vector store ID\n user_id: userId,\n name,\n description: description || '',\n created_at: now,\n updated_at: now,\n metadata: {\n ...metadata,\n conversation_id: null,\n provider_id: this.providerId,\n },\n };\n\n const vectorStore = await this.client.vectorStores.create({\n name: name || `Session for ${userId}`,\n provider_id: this.providerId,\n metadata: buildVectorStoreMetadata(tempSession),\n });\n\n const sessionId = vectorStore.id;\n\n // Build final session object with actual ID\n const session: NotebookSession = {\n ...tempSession,\n session_id: sessionId,\n document_count: 0,\n };\n\n this.logger.info(`Created session ${sessionId} for user ${userId}`);\n return session;\n }\n\n /**\n * Retrieve a session and verify ownership\n * @param sessionId - Session ID to retrieve\n * @param userId - User ID requesting access\n * @returns Notebook session\n * @throws NotFoundError if session not found or has no metadata\n * @throws NotAllowedError if user does not own the session\n */\n async readSession(\n sessionId: string,\n userId: string,\n ): Promise<NotebookSession> {\n // Retrieve vector store to get metadata\n const vectorStore = await this.client.vectorStores.retrieve(sessionId);\n\n if (!vectorStore.metadata) {\n throw new NotFoundError(`Session ${sessionId} has no metadata`);\n }\n\n const session = extractSessionFromMetadata(\n sessionId,\n vectorStore.metadata as Record<string, any>,\n );\n\n // Verify ownership\n if (session.user_id !== userId) {\n throw new NotAllowedError(\n `User ${userId} does not have access to session ${sessionId}`,\n );\n }\n\n // Fetch document count\n try {\n const filesResponse =\n await this.client.vectorStores.files.list(sessionId);\n session.document_count = filesResponse.data?.length || 0;\n } catch (error) {\n this.logger.warn(\n `Failed to fetch document count for session ${sessionId}: ${error}`,\n );\n session.document_count = 0;\n }\n\n return session;\n }\n\n /**\n * Update session details\n * @param sessionId - Session ID to update\n * @param userId - User ID performing the update\n * @param name - New session name (optional)\n * @param description - New session description (optional)\n * @param metadata - New session metadata (optional)\n * @returns Updated notebook session\n * @throws NotAllowedError if user does not own the session\n */\n async updateSession(\n sessionId: string,\n userId: string,\n name?: string,\n description?: string,\n metadata?: SessionMetadata,\n ): Promise<NotebookSession> {\n const existing = await this.readSession(sessionId, userId);\n\n const updated: NotebookSession = {\n ...existing,\n name: name !== undefined ? name : existing.name,\n description:\n description !== undefined ? description : existing.description,\n metadata: metadata !== undefined ? metadata : existing.metadata,\n updated_at: new Date().toISOString(),\n };\n\n // Retrieve vector store to preserve embedding configuration\n const vectorStore = await this.client.vectorStores.retrieve(sessionId);\n\n // Update vector store metadata while preserving embedding fields\n await this.client.vectorStores.update(sessionId, {\n embedding_model: vectorStore.embedding_model,\n embedding_dimension: vectorStore.embedding_dimension,\n metadata: buildVectorStoreMetadata(updated),\n });\n\n return updated;\n }\n\n /**\n * Delete a session and all associated files\n * @param sessionId - Session ID to delete\n * @param userId - User ID performing the deletion\n * @throws NotAllowedError if user does not own the session\n */\n async deleteSession(sessionId: string, userId: string): Promise<void> {\n // Verify ownership before deletion and get session details\n const session = await this.readSession(sessionId, userId);\n const conversationId = session.metadata?.conversation_id;\n\n // Delete associated conversation if it exists\n if (conversationId) {\n try {\n // Access the baseURL from the VectorStoresOperator client\n const baseURL = (this.client as any).baseURL;\n const response = await fetch(\n `${baseURL}/v2/conversations/${encodeURIComponent(conversationId)}?user_id=${encodeURIComponent(userId)}`,\n {\n method: 'DELETE',\n headers: {\n 'Content-Type': 'application/json',\n },\n },\n );\n\n if (!response.ok) {\n this.logger.warn(\n `Failed to delete conversation ${conversationId}: HTTP ${response.status}`,\n );\n } else {\n this.logger.info(\n `Deleted conversation ${conversationId} for session ${sessionId}`,\n );\n }\n } catch (error) {\n this.logger.warn(\n `Failed to delete conversation ${conversationId}: ${error}`,\n );\n }\n }\n\n // Delete all vector store files\n try {\n const filesResponse =\n await this.client.vectorStores.files.list(sessionId);\n const files = filesResponse.data || [];\n\n await Promise.all(\n files.map(async (file: any) => {\n try {\n await this.client.vectorStores.files.delete(sessionId, file.id);\n this.logger.info(\n `Deleted vector store file ${file.id} (${file.attributes?.title || 'untitled'})`,\n );\n } catch (error) {\n this.logger.warn(\n `Failed to delete vector store file ${file.id}: ${error}`,\n );\n }\n }),\n );\n } catch (error) {\n this.logger.warn(\n `Failed to clean up files for session ${sessionId}: ${error}`,\n );\n }\n\n // Delete the vector store\n await this.client.vectorStores.delete(sessionId);\n this.logger.info(`Session ${sessionId} deleted`);\n }\n\n /**\n * List all sessions for a user\n * @param userId - User ID to filter sessions\n * @returns Array of notebook sessions sorted by creation date (newest first)\n */\n async listSessions(userId: string): Promise<NotebookSession[]> {\n const vectorStoresPage = await this.client.vectorStores.list();\n const vectorStores = vectorStoresPage.data;\n const sessions: NotebookSession[] = [];\n\n // Extract sessions first\n for (const store of vectorStores) {\n const session_user_id = (store.metadata?.user_id as string) || '';\n if (session_user_id === userId && store.metadata) {\n try {\n const session = extractSessionFromMetadata(\n store.id,\n store.metadata as Record<string, any>,\n );\n sessions.push(session);\n } catch (error) {\n this.logger.warn(\n `Failed to extract session from vector store ${store.id}: ${error}`,\n );\n }\n }\n }\n\n // Fetch document counts in parallel\n await Promise.all(\n sessions.map(async session => {\n try {\n const filesResponse = await this.client.vectorStores.files.list(\n session.session_id,\n );\n session.document_count = filesResponse.data?.length || 0;\n } catch (error) {\n this.logger.warn(\n `Failed to fetch document count for session ${session.session_id}: ${error}`,\n );\n session.document_count = 0;\n }\n }),\n );\n\n // Sort by created_at descending (newest first), then session_id for stable ties\n return sessions.sort((a, b) => {\n const byTime =\n new Date(b.created_at).getTime() - new Date(a.created_at).getTime();\n if (byTime !== 0) {\n return byTime;\n }\n return b.session_id.localeCompare(a.session_id);\n });\n }\n}\n"],"names":["buildVectorStoreMetadata","NotFoundError","extractSessionFromMetadata","NotAllowedError"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const createSessionResponse = (session, message) => {
|
|
4
|
+
return {
|
|
5
|
+
status: "success",
|
|
6
|
+
session,
|
|
7
|
+
message
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
const createSessionListResponse = (sessions) => {
|
|
11
|
+
return {
|
|
12
|
+
status: "success",
|
|
13
|
+
sessions,
|
|
14
|
+
count: sessions.length
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
const createDocumentResponse = (document_id, session_id, message, options) => {
|
|
18
|
+
return {
|
|
19
|
+
status: "success",
|
|
20
|
+
document_id,
|
|
21
|
+
title: options?.title,
|
|
22
|
+
session_id,
|
|
23
|
+
replaced: options?.replaced,
|
|
24
|
+
message
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
const createDocumentListResponse = (session_id, documents) => {
|
|
28
|
+
return {
|
|
29
|
+
status: "success",
|
|
30
|
+
session_id,
|
|
31
|
+
documents,
|
|
32
|
+
count: documents.length
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
exports.createDocumentListResponse = createDocumentListResponse;
|
|
37
|
+
exports.createDocumentResponse = createDocumentResponse;
|
|
38
|
+
exports.createSessionListResponse = createSessionListResponse;
|
|
39
|
+
exports.createSessionResponse = createSessionResponse;
|
|
40
|
+
//# sourceMappingURL=notebooksTypes.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notebooksTypes.cjs.js","sources":["../../../../src/service/notebooks/types/notebooksTypes.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Session metadata for organization\n */\nexport interface SessionMetadata {\n conversation_id?: string | null; // Active conversation ID for RAG queries\n embedding_model?: string; // Embedding model used\n embedding_dimension?: number; // Embedding vector dimension\n provider_id?: string; // AI provider identifier\n [key: string]: any; // Allow custom metadata fields\n}\n\n/**\n * Notebook session with vector database\n * session_id is the Llama Stack vector store ID\n */\nexport interface NotebookSession {\n session_id: string;\n user_id: string;\n name: string;\n description: string;\n created_at: string;\n updated_at: string;\n metadata?: SessionMetadata;\n document_count?: number;\n}\n\n/**\n * Document within a session\n */\nexport interface SessionDocument {\n document_id: string;\n source_type: 'text' | 'pdf' | 'md' | 'json' | 'yaml' | 'log';\n created_at: string;\n updated_at: string;\n}\n\n/**\n * API Response types\n */\nexport interface SessionResponse {\n status: 'success' | 'error';\n session?: NotebookSession;\n message?: string;\n error?: string;\n}\n\nexport interface SessionListResponse {\n status: 'success' | 'error';\n sessions?: NotebookSession[];\n count?: number;\n error?: string;\n}\n\nexport interface DocumentResponse {\n status: 'success' | 'error';\n document_id?: string;\n title?: string;\n session_id?: string;\n replaced?: boolean;\n message?: string;\n error?: string;\n}\n\nexport interface DocumentListResponse {\n status: 'success' | 'error';\n session_id?: string;\n documents?: SessionDocument[];\n count?: number;\n error?: string;\n}\n\nexport interface QueryResponse {\n status: 'success' | 'error';\n chunks?: any[];\n error?: string;\n}\n\nexport interface UpsertResult {\n document_id: string;\n file_id: string;\n replaced: boolean;\n status: 'completed' | 'in_progress' | 'failed' | 'cancelled';\n}\n\n/**\n * Response factory functions\n */\n\n/**\n * Create a successful session response\n * @param session - Notebook session object\n * @param message - Success message\n * @returns Session response object\n */\nexport const createSessionResponse = (\n session: NotebookSession,\n message: string,\n): SessionResponse => {\n return {\n status: 'success',\n session,\n message,\n };\n};\n\n/**\n * Create a successful session list response\n * @param sessions - Array of notebook sessions\n * @returns Session list response object\n */\nexport const createSessionListResponse = (\n sessions: NotebookSession[],\n): SessionListResponse => {\n return {\n status: 'success',\n sessions,\n count: sessions.length,\n };\n};\n\n/**\n * Create a successful document response\n * @param document_id - Document identifier\n * @param session_id - Session identifier\n * @param message - Success message\n * @param options - Optional fields (title, replaced)\n * @returns Document response object\n */\nexport const createDocumentResponse = (\n document_id: string,\n session_id: string,\n message: string,\n options?: {\n title?: string;\n replaced?: boolean;\n },\n): DocumentResponse => {\n return {\n status: 'success',\n document_id,\n title: options?.title,\n session_id,\n replaced: options?.replaced,\n message,\n };\n};\n\n/**\n * Create a successful document list response\n * @param session_id - Session identifier\n * @param documents - Array of session documents\n * @returns Document list response object\n */\nexport const createDocumentListResponse = (\n session_id: string,\n documents: SessionDocument[],\n): DocumentListResponse => {\n return {\n status: 'success',\n session_id,\n documents,\n count: documents.length,\n };\n};\n"],"names":[],"mappings":";;AA8GO,MAAM,qBAAA,GAAwB,CACnC,OAAA,EACA,OAAA,KACoB;AACpB,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,SAAA;AAAA,IACR,OAAA;AAAA,IACA;AAAA,GACF;AACF;AAOO,MAAM,yBAAA,GAA4B,CACvC,QAAA,KACwB;AACxB,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,SAAA;AAAA,IACR,QAAA;AAAA,IACA,OAAO,QAAA,CAAS;AAAA,GAClB;AACF;AAUO,MAAM,sBAAA,GAAyB,CACpC,WAAA,EACA,UAAA,EACA,SACA,OAAA,KAIqB;AACrB,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,SAAA;AAAA,IACR,WAAA;AAAA,IACA,OAAO,OAAA,EAAS,KAAA;AAAA,IAChB,UAAA;AAAA,IACA,UAAU,OAAA,EAAS,QAAA;AAAA,IACnB;AAAA,GACF;AACF;AAQO,MAAM,0BAAA,GAA6B,CACxC,UAAA,EACA,SAAA,KACyB;AACzB,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,SAAA;AAAA,IACR,UAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAO,SAAA,CAAU;AAAA,GACnB;AACF;;;;;;;"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
|
|
5
|
+
const handleError = (logger, res, error, message) => {
|
|
6
|
+
if (typeof error === "string") {
|
|
7
|
+
logger.error(`Validation error: ${error}`);
|
|
8
|
+
res.status(400).json({ status: "error", error });
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
12
|
+
const errormsg = message ? `${message}: ${errorMessage}` : errorMessage;
|
|
13
|
+
logger.error(errormsg, error);
|
|
14
|
+
if (error instanceof errors.NotAllowedError) {
|
|
15
|
+
res.status(403).json({ status: "error", error: error.message });
|
|
16
|
+
} else if (error instanceof errors.NotFoundError) {
|
|
17
|
+
res.status(404).json({ status: "error", error: error.message });
|
|
18
|
+
} else if (error instanceof errors.InputError) {
|
|
19
|
+
res.status(400).json({ status: "error", error: error.message });
|
|
20
|
+
} else if (error instanceof errors.ConflictError) {
|
|
21
|
+
res.status(409).json({ status: "error", error: error.message });
|
|
22
|
+
} else if (error instanceof Error) {
|
|
23
|
+
res.status(500).json({ status: "error", error: error.message });
|
|
24
|
+
} else {
|
|
25
|
+
res.status(500).json({ status: "error", error: errorMessage });
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
const buildVectorStoreMetadata = (session) => {
|
|
29
|
+
return {
|
|
30
|
+
user_id: session.user_id,
|
|
31
|
+
name: session.name,
|
|
32
|
+
description: session.description,
|
|
33
|
+
created_at: session.created_at,
|
|
34
|
+
updated_at: session.updated_at,
|
|
35
|
+
...session.metadata || {}
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const extractSessionFromMetadata = (sessionId, metadata) => {
|
|
39
|
+
const {
|
|
40
|
+
user_id,
|
|
41
|
+
name,
|
|
42
|
+
description,
|
|
43
|
+
created_at,
|
|
44
|
+
updated_at,
|
|
45
|
+
provider_id,
|
|
46
|
+
conversation_id,
|
|
47
|
+
embedding_dimension,
|
|
48
|
+
...customMetadata
|
|
49
|
+
} = metadata;
|
|
50
|
+
delete customMetadata.provider_vector_store_id;
|
|
51
|
+
return {
|
|
52
|
+
session_id: sessionId,
|
|
53
|
+
user_id,
|
|
54
|
+
name,
|
|
55
|
+
description,
|
|
56
|
+
created_at,
|
|
57
|
+
updated_at,
|
|
58
|
+
metadata: {
|
|
59
|
+
...customMetadata,
|
|
60
|
+
provider_id,
|
|
61
|
+
conversation_id,
|
|
62
|
+
embedding_dimension
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
exports.buildVectorStoreMetadata = buildVectorStoreMetadata;
|
|
68
|
+
exports.extractSessionFromMetadata = extractSessionFromMetadata;
|
|
69
|
+
exports.handleError = handleError;
|
|
70
|
+
//# sourceMappingURL=utils.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.cjs.js","sources":["../../../src/service/notebooks/utils.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { LoggerService } from '@backstage/backend-plugin-api';\nimport {\n ConflictError,\n InputError,\n NotAllowedError,\n NotFoundError,\n} from '@backstage/errors';\n\nimport { Response } from 'express';\n\nimport { NotebookSession } from './types/notebooksTypes';\n\n/**\n * Handle error and return appropriate HTTP status code and error message\n * Supports both Error objects and plain strings (treated as validation errors)\n * @param logger - Logger service\n * @param res - Response object\n * @param error - Error object or validation error string\n * @param message - Optional context message (not used for string errors)\n * @returns Response object\n */\nexport const handleError = (\n logger: LoggerService,\n res: Response,\n error: unknown,\n message?: string,\n) => {\n if (typeof error === 'string') {\n logger.error(`Validation error: ${error}`);\n res.status(400).json({ status: 'error', error });\n return;\n }\n\n // Properly stringify error for logging\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errormsg = message ? `${message}: ${errorMessage}` : errorMessage;\n logger.error(errormsg, error as Error);\n\n // Handle specific error types with appropriate HTTP status codes\n if (error instanceof NotAllowedError) {\n // 403 Forbidden - User lacks permission\n res.status(403).json({ status: 'error', error: error.message });\n } else if (error instanceof NotFoundError) {\n // 404 Not Found - Resource doesn't exist\n res.status(404).json({ status: 'error', error: error.message });\n } else if (error instanceof InputError) {\n // 400 Bad Request - Invalid input/validation error\n res.status(400).json({ status: 'error', error: error.message });\n } else if (error instanceof ConflictError) {\n // 409 Conflict - Resource conflict (e.g., duplicate)\n res.status(409).json({ status: 'error', error: error.message });\n } else if (error instanceof Error) {\n // 500 Internal Server Error - Generic error\n res.status(500).json({ status: 'error', error: error.message });\n } else {\n // 500 Internal Server Error - Unknown error type\n res.status(500).json({ status: 'error', error: errorMessage });\n }\n};\n\n/**\n * Build VectorStore metadata object from session data\n * @param session - Notebook session\n * @returns Metadata object for vector store\n */\nexport const buildVectorStoreMetadata = (\n session: NotebookSession,\n): Record<string, any> => {\n return {\n user_id: session.user_id,\n name: session.name,\n description: session.description,\n created_at: session.created_at,\n updated_at: session.updated_at,\n ...(session.metadata || {}),\n };\n};\n\n/**\n * Extract session data from VectorStore metadata\n * @param sessionId - Session ID\n * @param metadata - Vector store metadata\n * @returns Notebook session object\n */\nexport const extractSessionFromMetadata = (\n sessionId: string,\n metadata: Record<string, any>,\n): NotebookSession => {\n // Extract session-level fields\n const {\n user_id,\n name,\n description,\n created_at,\n updated_at,\n provider_id,\n conversation_id,\n embedding_dimension,\n ...customMetadata\n } = metadata;\n delete customMetadata.provider_vector_store_id;\n\n return {\n session_id: sessionId,\n user_id: user_id as string,\n name: name as string,\n description: description as string,\n created_at: created_at as string,\n updated_at: updated_at as string,\n metadata: {\n ...customMetadata,\n provider_id: provider_id as string,\n conversation_id: conversation_id as string | null,\n embedding_dimension: embedding_dimension as number,\n },\n };\n};\n"],"names":["NotAllowedError","NotFoundError","InputError","ConflictError"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@backstage/errors');
|
|
4
|
+
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
5
|
+
|
|
6
|
+
function userPermissionAuthorization(permissionsService) {
|
|
7
|
+
const permissions = permissionsService;
|
|
8
|
+
return {
|
|
9
|
+
async authorizeUser(permission, credentials) {
|
|
10
|
+
const decision = (await permissions.authorize(
|
|
11
|
+
[
|
|
12
|
+
{
|
|
13
|
+
permission
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
{ credentials }
|
|
17
|
+
))[0];
|
|
18
|
+
if (decision.result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
19
|
+
throw new errors.NotAllowedError("Unauthorized");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
exports.userPermissionAuthorization = userPermissionAuthorization;
|
|
26
|
+
//# sourceMappingURL=permission.cjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission.cjs.js","sources":["../../src/service/permission.ts"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n BackstageCredentials,\n PermissionsService,\n} from '@backstage/backend-plugin-api';\nimport { NotAllowedError } from '@backstage/errors';\nimport {\n AuthorizeResult,\n BasicPermission,\n} from '@backstage/plugin-permission-common';\n\nexport function userPermissionAuthorization(\n permissionsService: PermissionsService,\n) {\n const permissions = permissionsService;\n\n return {\n async authorizeUser(\n permission: BasicPermission,\n credentials: BackstageCredentials,\n ): Promise<void> {\n const decision = (\n await permissions.authorize(\n [\n {\n permission,\n },\n ],\n { credentials },\n )\n )[0];\n\n if (decision.result !== AuthorizeResult.ALLOW) {\n throw new NotAllowedError('Unauthorized');\n }\n },\n };\n}\n"],"names":["AuthorizeResult","NotAllowedError"],"mappings":";;;;;AA0BO,SAAS,4BACd,kBAAA,EACA;AACA,EAAA,MAAM,WAAA,GAAc,kBAAA;AAEpB,EAAA,OAAO;AAAA,IACL,MAAM,aAAA,CACJ,UAAA,EACA,WAAA,EACe;AACf,MAAA,MAAM,QAAA,GAAA,CACJ,MAAM,WAAA,CAAY,SAAA;AAAA,QAChB;AAAA,UACE;AAAA,YACE;AAAA;AACF,SACF;AAAA,QACA,EAAE,WAAA;AAAY,SAEhB,CAAC,CAAA;AAEH,MAAA,IAAI,QAAA,CAAS,MAAA,KAAWA,sCAAA,CAAgB,KAAA,EAAO;AAC7C,QAAA,MAAM,IAAIC,uBAAgB,cAAc,CAAA;AAAA,MAC1C;AAAA,IACF;AAAA,GACF;AACF;;;;"}
|