You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
4.4 KiB

11 months ago
  1. process.env.NODE_ENV === "development"
  2. ? require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` })
  3. : require("dotenv").config();
  4. require("./utils/logger")();
  5. const express = require("express");
  6. const bodyParser = require("body-parser");
  7. const cors = require("cors");
  8. const path = require("path");
  9. const { reqBody } = require("./utils/http");
  10. const { systemEndpoints } = require("./endpoints/system");
  11. const { workspaceEndpoints } = require("./endpoints/workspaces");
  12. const { chatEndpoints } = require("./endpoints/chat");
  13. const { embeddedEndpoints } = require("./endpoints/embed");
  14. const { embedManagementEndpoints } = require("./endpoints/embedManagement");
  15. const { getVectorDbClass } = require("./utils/helpers");
  16. const { adminEndpoints } = require("./endpoints/admin");
  17. const { inviteEndpoints } = require("./endpoints/invite");
  18. const { utilEndpoints } = require("./endpoints/utils");
  19. const { developerEndpoints } = require("./endpoints/api");
  20. const { extensionEndpoints } = require("./endpoints/extensions");
  21. const { bootHTTP, bootSSL } = require("./utils/boot");
  22. const { workspaceThreadEndpoints } = require("./endpoints/workspaceThreads");
  23. const { documentEndpoints } = require("./endpoints/document");
  24. const { agentWebsocket } = require("./endpoints/agentWebsocket");
  25. const { experimentalEndpoints } = require("./endpoints/experimental");
  26. const { browserExtensionEndpoints } = require("./endpoints/browserExtension");
  27. const { communityHubEndpoints } = require("./endpoints/communityHub");
  28. const { agentFlowEndpoints } = require("./endpoints/agentFlows");
  29. const app = express();
  30. const apiRouter = express.Router();
  31. const FILE_LIMIT = "3GB";
  32. app.use(cors({ origin: true }));
  33. app.use(bodyParser.text({ limit: FILE_LIMIT }));
  34. app.use(bodyParser.json({ limit: FILE_LIMIT }));
  35. app.use(
  36. bodyParser.urlencoded({
  37. limit: FILE_LIMIT,
  38. extended: true,
  39. })
  40. );
  41. if (!!process.env.ENABLE_HTTPS) {
  42. bootSSL(app, process.env.SERVER_PORT || 3001);
  43. } else {
  44. require("@mintplex-labs/express-ws").default(app); // load WebSockets in non-SSL mode.
  45. }
  46. app.use("/api", apiRouter);
  47. systemEndpoints(apiRouter);
  48. extensionEndpoints(apiRouter);
  49. workspaceEndpoints(apiRouter);
  50. workspaceThreadEndpoints(apiRouter);
  51. chatEndpoints(apiRouter);
  52. adminEndpoints(apiRouter);
  53. inviteEndpoints(apiRouter);
  54. embedManagementEndpoints(apiRouter);
  55. utilEndpoints(apiRouter);
  56. documentEndpoints(apiRouter);
  57. agentWebsocket(apiRouter);
  58. experimentalEndpoints(apiRouter);
  59. developerEndpoints(app, apiRouter);
  60. communityHubEndpoints(apiRouter);
  61. agentFlowEndpoints(apiRouter);
  62. // Externally facing embedder endpoints
  63. embeddedEndpoints(apiRouter);
  64. // Externally facing browser extension endpoints
  65. browserExtensionEndpoints(apiRouter);
  66. if (process.env.NODE_ENV !== "development") {
  67. const { MetaGenerator } = require("./utils/boot/MetaGenerator");
  68. const IndexPage = new MetaGenerator();
  69. app.use(
  70. express.static(path.resolve(__dirname, "public"), {
  71. extensions: ["js"],
  72. setHeaders: (res) => {
  73. // Disable I-framing of entire site UI
  74. res.removeHeader("X-Powered-By");
  75. res.setHeader("X-Frame-Options", "DENY");
  76. },
  77. })
  78. );
  79. app.use("/", function (_, response) {
  80. IndexPage.generate(response);
  81. return;
  82. });
  83. app.get("/robots.txt", function (_, response) {
  84. response.type("text/plain");
  85. response.send("User-agent: *\nDisallow: /").end();
  86. });
  87. } else {
  88. // Debug route for development connections to vectorDBs
  89. apiRouter.post("/v/:command", async (request, response) => {
  90. try {
  91. const VectorDb = getVectorDbClass();
  92. const { command } = request.params;
  93. if (!Object.getOwnPropertyNames(VectorDb).includes(command)) {
  94. response.status(500).json({
  95. message: "invalid interface command",
  96. commands: Object.getOwnPropertyNames(VectorDb),
  97. });
  98. return;
  99. }
  100. try {
  101. const body = reqBody(request);
  102. const resBody = await VectorDb[command](body);
  103. response.status(200).json({ ...resBody });
  104. } catch (e) {
  105. // console.error(e)
  106. console.error(JSON.stringify(e));
  107. response.status(500).json({ error: e.message });
  108. }
  109. return;
  110. } catch (e) {
  111. console.error(e.message, e);
  112. response.sendStatus(500).end();
  113. }
  114. });
  115. }
  116. app.all("*", function (_, response) {
  117. response.sendStatus(404);
  118. });
  119. // In non-https mode we need to boot at the end since the server has not yet
  120. // started and is `.listen`ing.
  121. if (!process.env.ENABLE_HTTPS) bootHTTP(app, process.env.SERVER_PORT || 3001);