2023-07-25 19:37:04 +02:00
|
|
|
const { reqBody, multiUserMode, userFromSession } = require("../utils/http");
|
2023-06-08 06:31:35 +02:00
|
|
|
const { Workspace } = require("../models/workspace");
|
|
|
|
const { Document } = require("../models/documents");
|
|
|
|
const { DocumentVectors } = require("../models/vectors");
|
|
|
|
const { WorkspaceChats } = require("../models/workspaceChats");
|
|
|
|
const { convertToChatHistory } = require("../utils/chats");
|
|
|
|
const { getVectorDbClass } = require("../utils/helpers");
|
2023-06-17 01:01:27 +02:00
|
|
|
const { setupMulter } = require("../utils/files/multer");
|
|
|
|
const {
|
2023-12-15 00:14:56 +01:00
|
|
|
checkProcessorAlive,
|
2023-06-17 01:01:27 +02:00
|
|
|
processDocument,
|
2023-11-17 02:15:01 +01:00
|
|
|
processLink,
|
2023-06-17 01:01:27 +02:00
|
|
|
} = require("../utils/files/documentProcessor");
|
2023-07-25 19:37:04 +02:00
|
|
|
const { validatedRequest } = require("../utils/middleware/validatedRequest");
|
2023-08-15 02:42:17 +02:00
|
|
|
const { Telemetry } = require("../models/telemetry");
|
2023-11-13 23:51:16 +01:00
|
|
|
const { flexUserRoleValid } = require("../utils/middleware/multiUserProtected");
|
2023-06-17 01:01:27 +02:00
|
|
|
const { handleUploads } = setupMulter();
|
2023-06-04 04:28:07 +02:00
|
|
|
|
|
|
|
function workspaceEndpoints(app) {
|
|
|
|
if (!app) return;
|
|
|
|
|
2023-11-13 23:51:16 +01:00
|
|
|
app.post(
|
|
|
|
"/workspace/new",
|
|
|
|
[validatedRequest, flexUserRoleValid],
|
|
|
|
async (request, response) => {
|
|
|
|
try {
|
|
|
|
const user = await userFromSession(request, response);
|
|
|
|
const { name = null, onboardingComplete = false } = reqBody(request);
|
|
|
|
const { workspace, message } = await Workspace.new(name, user?.id);
|
|
|
|
await Telemetry.sendTelemetry(
|
|
|
|
"workspace_created",
|
|
|
|
{
|
|
|
|
multiUserMode: multiUserMode(response),
|
|
|
|
LLMSelection: process.env.LLM_PROVIDER || "openai",
|
2023-12-07 17:53:37 +01:00
|
|
|
Embedder: process.env.EMBEDDING_ENGINE || "inherit",
|
2023-11-13 23:51:16 +01:00
|
|
|
VectorDbSelection: process.env.VECTOR_DB || "pinecone",
|
|
|
|
},
|
|
|
|
user?.id
|
|
|
|
);
|
|
|
|
if (onboardingComplete === true)
|
|
|
|
await Telemetry.sendTelemetry("onboarding_complete");
|
2023-10-26 22:49:01 +02:00
|
|
|
|
2023-11-13 23:51:16 +01:00
|
|
|
response.status(200).json({ workspace, message });
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e.message, e);
|
|
|
|
response.sendStatus(500).end();
|
|
|
|
}
|
2023-06-08 22:13:48 +02:00
|
|
|
}
|
2023-11-13 23:51:16 +01:00
|
|
|
);
|
2023-06-04 04:28:07 +02:00
|
|
|
|
2023-07-25 19:37:04 +02:00
|
|
|
app.post(
|
|
|
|
"/workspace/:slug/update",
|
|
|
|
[validatedRequest],
|
|
|
|
async (request, response) => {
|
|
|
|
try {
|
|
|
|
const user = await userFromSession(request, response);
|
|
|
|
const { slug = null } = request.params;
|
|
|
|
const data = reqBody(request);
|
|
|
|
const currWorkspace = multiUserMode(response)
|
2023-09-28 23:00:03 +02:00
|
|
|
? await Workspace.getWithUser(user, { slug })
|
|
|
|
: await Workspace.get({ slug });
|
2023-07-25 19:37:04 +02:00
|
|
|
|
|
|
|
if (!currWorkspace) {
|
|
|
|
response.sendStatus(400).end();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const { workspace, message } = await Workspace.update(
|
|
|
|
currWorkspace.id,
|
|
|
|
data
|
|
|
|
);
|
|
|
|
response.status(200).json({ workspace, message });
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e.message, e);
|
|
|
|
response.sendStatus(500).end();
|
2023-06-15 08:12:59 +02:00
|
|
|
}
|
|
|
|
}
|
2023-07-25 19:37:04 +02:00
|
|
|
);
|
2023-06-15 08:12:59 +02:00
|
|
|
|
2023-06-17 01:01:27 +02:00
|
|
|
app.post(
|
|
|
|
"/workspace/:slug/upload",
|
|
|
|
handleUploads.single("file"),
|
2023-08-23 04:18:47 +02:00
|
|
|
async function (request, response) {
|
2023-06-17 01:01:27 +02:00
|
|
|
const { originalname } = request.file;
|
2023-12-15 00:14:56 +01:00
|
|
|
const processingOnline = await checkProcessorAlive();
|
2023-06-17 01:01:27 +02:00
|
|
|
|
|
|
|
if (!processingOnline) {
|
2023-08-23 04:18:47 +02:00
|
|
|
response
|
|
|
|
.status(500)
|
|
|
|
.json({
|
|
|
|
success: false,
|
2023-12-15 00:14:56 +01:00
|
|
|
error: `Document processing API is not online. Document ${originalname} will not be processed automatically.`,
|
2023-08-23 04:18:47 +02:00
|
|
|
})
|
|
|
|
.end();
|
2023-08-25 02:57:35 +02:00
|
|
|
return;
|
2023-06-17 01:01:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const { success, reason } = await processDocument(originalname);
|
|
|
|
if (!success) {
|
2023-08-23 04:18:47 +02:00
|
|
|
response.status(500).json({ success: false, error: reason }).end();
|
2023-08-25 02:57:35 +02:00
|
|
|
return;
|
2023-06-17 01:01:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
console.log(
|
|
|
|
`Document ${originalname} uploaded processed and successfully. It is now available in documents.`
|
|
|
|
);
|
2023-08-15 02:42:17 +02:00
|
|
|
await Telemetry.sendTelemetry("document_uploaded");
|
2023-08-23 04:18:47 +02:00
|
|
|
response.status(200).json({ success: true, error: null });
|
2023-11-17 02:15:01 +01:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
app.post(
|
|
|
|
"/workspace/:slug/upload-link",
|
|
|
|
[validatedRequest],
|
|
|
|
async (request, response) => {
|
|
|
|
const { link = "" } = reqBody(request);
|
2023-12-15 00:14:56 +01:00
|
|
|
const processingOnline = await checkProcessorAlive();
|
2023-11-17 02:15:01 +01:00
|
|
|
|
|
|
|
if (!processingOnline) {
|
|
|
|
response
|
|
|
|
.status(500)
|
|
|
|
.json({
|
|
|
|
success: false,
|
2023-12-15 00:14:56 +01:00
|
|
|
error: `Document processing API is not online. Link ${link} will not be processed automatically.`,
|
2023-11-17 02:15:01 +01:00
|
|
|
})
|
|
|
|
.end();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const { success, reason } = await processLink(link);
|
|
|
|
if (!success) {
|
|
|
|
response.status(500).json({ success: false, error: reason }).end();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log(
|
|
|
|
`Link ${link} uploaded processed and successfully. It is now available in documents.`
|
|
|
|
);
|
|
|
|
await Telemetry.sendTelemetry("link_uploaded");
|
|
|
|
response.status(200).json({ success: true, error: null });
|
2023-06-17 01:01:27 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
2023-07-25 19:37:04 +02:00
|
|
|
app.post(
|
|
|
|
"/workspace/:slug/update-embeddings",
|
|
|
|
[validatedRequest],
|
|
|
|
async (request, response) => {
|
|
|
|
try {
|
|
|
|
const user = await userFromSession(request, response);
|
|
|
|
const { slug = null } = request.params;
|
|
|
|
const { adds = [], deletes = [] } = reqBody(request);
|
|
|
|
const currWorkspace = multiUserMode(response)
|
2023-09-28 23:00:03 +02:00
|
|
|
? await Workspace.getWithUser(user, { slug })
|
|
|
|
: await Workspace.get({ slug });
|
2023-07-25 19:37:04 +02:00
|
|
|
|
|
|
|
if (!currWorkspace) {
|
|
|
|
response.sendStatus(400).end();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
await Document.removeDocuments(currWorkspace, deletes);
|
2023-10-26 19:57:37 +02:00
|
|
|
const { failed = [] } = await Document.addDocuments(
|
|
|
|
currWorkspace,
|
|
|
|
adds
|
|
|
|
);
|
2023-09-28 23:00:03 +02:00
|
|
|
const updatedWorkspace = await Workspace.get({ id: currWorkspace.id });
|
2023-10-26 19:57:37 +02:00
|
|
|
response.status(200).json({
|
|
|
|
workspace: updatedWorkspace,
|
|
|
|
message:
|
|
|
|
failed.length > 0
|
|
|
|
? `${failed.length} documents could not be embedded.`
|
|
|
|
: null,
|
|
|
|
});
|
2023-07-25 19:37:04 +02:00
|
|
|
} catch (e) {
|
|
|
|
console.log(e.message, e);
|
|
|
|
response.sendStatus(500).end();
|
2023-06-08 22:13:48 +02:00
|
|
|
}
|
|
|
|
}
|
2023-07-25 19:37:04 +02:00
|
|
|
);
|
2023-06-04 04:28:07 +02:00
|
|
|
|
2023-07-25 19:37:04 +02:00
|
|
|
app.delete(
|
|
|
|
"/workspace/:slug",
|
2023-11-13 23:51:16 +01:00
|
|
|
[validatedRequest, flexUserRoleValid],
|
2023-07-25 19:37:04 +02:00
|
|
|
async (request, response) => {
|
2023-06-08 22:13:48 +02:00
|
|
|
try {
|
2023-07-25 19:37:04 +02:00
|
|
|
const { slug = "" } = request.params;
|
|
|
|
const user = await userFromSession(request, response);
|
|
|
|
const VectorDb = getVectorDbClass();
|
|
|
|
const workspace = multiUserMode(response)
|
2023-09-28 23:00:03 +02:00
|
|
|
? await Workspace.getWithUser(user, { slug })
|
|
|
|
: await Workspace.get({ slug });
|
2023-07-25 19:37:04 +02:00
|
|
|
|
|
|
|
if (!workspace) {
|
|
|
|
response.sendStatus(400).end();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-09-28 23:00:03 +02:00
|
|
|
await WorkspaceChats.delete({ workspaceId: Number(workspace.id) });
|
2023-07-25 19:37:04 +02:00
|
|
|
await DocumentVectors.deleteForWorkspace(workspace.id);
|
2023-09-28 23:00:03 +02:00
|
|
|
await Document.delete({ workspaceId: Number(workspace.id) });
|
|
|
|
await Workspace.delete({ id: Number(workspace.id) });
|
|
|
|
|
2023-07-25 19:37:04 +02:00
|
|
|
try {
|
|
|
|
await VectorDb["delete-namespace"]({ namespace: slug });
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e.message);
|
|
|
|
}
|
|
|
|
response.sendStatus(200).end();
|
2023-06-08 22:13:48 +02:00
|
|
|
} catch (e) {
|
2023-07-25 19:37:04 +02:00
|
|
|
console.log(e.message, e);
|
|
|
|
response.sendStatus(500).end();
|
2023-06-08 22:13:48 +02:00
|
|
|
}
|
2023-06-08 06:31:35 +02:00
|
|
|
}
|
2023-07-25 19:37:04 +02:00
|
|
|
);
|
2023-06-04 04:28:07 +02:00
|
|
|
|
2023-07-25 19:37:04 +02:00
|
|
|
app.get("/workspaces", [validatedRequest], async (request, response) => {
|
2023-06-08 22:13:48 +02:00
|
|
|
try {
|
2023-07-25 19:37:04 +02:00
|
|
|
const user = await userFromSession(request, response);
|
|
|
|
const workspaces = multiUserMode(response)
|
|
|
|
? await Workspace.whereWithUser(user)
|
|
|
|
: await Workspace.where();
|
|
|
|
|
2023-06-08 22:13:48 +02:00
|
|
|
response.status(200).json({ workspaces });
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e.message, e);
|
|
|
|
response.sendStatus(500).end();
|
|
|
|
}
|
2023-06-08 06:31:35 +02:00
|
|
|
});
|
2023-06-04 04:28:07 +02:00
|
|
|
|
2023-07-25 19:37:04 +02:00
|
|
|
app.get("/workspace/:slug", [validatedRequest], async (request, response) => {
|
2023-06-08 22:13:48 +02:00
|
|
|
try {
|
|
|
|
const { slug } = request.params;
|
2023-07-25 19:37:04 +02:00
|
|
|
const user = await userFromSession(request, response);
|
|
|
|
const workspace = multiUserMode(response)
|
2023-09-28 23:00:03 +02:00
|
|
|
? await Workspace.getWithUser(user, { slug })
|
|
|
|
: await Workspace.get({ slug });
|
2023-07-25 19:37:04 +02:00
|
|
|
|
2023-06-08 22:13:48 +02:00
|
|
|
response.status(200).json({ workspace });
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e.message, e);
|
|
|
|
response.sendStatus(500).end();
|
|
|
|
}
|
2023-06-08 06:31:35 +02:00
|
|
|
});
|
2023-06-04 04:28:07 +02:00
|
|
|
|
2023-07-25 19:37:04 +02:00
|
|
|
app.get(
|
|
|
|
"/workspace/:slug/chats",
|
|
|
|
[validatedRequest],
|
|
|
|
async (request, response) => {
|
|
|
|
try {
|
|
|
|
const { slug } = request.params;
|
|
|
|
const user = await userFromSession(request, response);
|
|
|
|
const workspace = multiUserMode(response)
|
2023-09-28 23:00:03 +02:00
|
|
|
? await Workspace.getWithUser(user, { slug })
|
|
|
|
: await Workspace.get({ slug });
|
2023-07-25 19:37:04 +02:00
|
|
|
|
|
|
|
if (!workspace) {
|
|
|
|
response.sendStatus(400).end();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const history = multiUserMode(response)
|
|
|
|
? await WorkspaceChats.forWorkspaceByUser(workspace.id, user.id)
|
|
|
|
: await WorkspaceChats.forWorkspace(workspace.id);
|
|
|
|
|
|
|
|
response.status(200).json({ history: convertToChatHistory(history) });
|
|
|
|
} catch (e) {
|
|
|
|
console.log(e.message, e);
|
|
|
|
response.sendStatus(500).end();
|
2023-06-08 22:13:48 +02:00
|
|
|
}
|
|
|
|
}
|
2023-07-25 19:37:04 +02:00
|
|
|
);
|
2023-06-04 04:28:07 +02:00
|
|
|
}
|
|
|
|
|
2023-06-08 06:31:35 +02:00
|
|
|
module.exports = { workspaceEndpoints };
|