totem-llm 0.1.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.
Files changed (800) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +81 -0
  3. package/bin/totem-llm.js +80 -0
  4. package/collector/.env +9 -0
  5. package/collector/.env.example +9 -0
  6. package/collector/.nvmrc +1 -0
  7. package/collector/extensions/index.js +239 -0
  8. package/collector/extensions/resync/index.js +197 -0
  9. package/collector/hotdir/__HOTDIR__.md +3 -0
  10. package/collector/index.js +202 -0
  11. package/collector/middleware/httpLogger.js +29 -0
  12. package/collector/middleware/setDataSigner.js +44 -0
  13. package/collector/middleware/verifyIntegrity.js +32 -0
  14. package/collector/package.json +67 -0
  15. package/collector/processLink/convert/generic.js +240 -0
  16. package/collector/processLink/helpers/index.js +190 -0
  17. package/collector/processLink/index.js +47 -0
  18. package/collector/processRawText/index.js +83 -0
  19. package/collector/processSingleFile/convert/asAudio.js +79 -0
  20. package/collector/processSingleFile/convert/asDocx.js +63 -0
  21. package/collector/processSingleFile/convert/asEPub.js +61 -0
  22. package/collector/processSingleFile/convert/asImage.js +56 -0
  23. package/collector/processSingleFile/convert/asMbox.js +83 -0
  24. package/collector/processSingleFile/convert/asOfficeMime.js +59 -0
  25. package/collector/processSingleFile/convert/asPDF/PDFLoader/index.js +97 -0
  26. package/collector/processSingleFile/convert/asPDF/index.js +86 -0
  27. package/collector/processSingleFile/convert/asTxt.js +59 -0
  28. package/collector/processSingleFile/convert/asXlsx.js +193 -0
  29. package/collector/processSingleFile/index.js +95 -0
  30. package/collector/utils/EncryptionWorker/index.js +77 -0
  31. package/collector/utils/OCRLoader/index.js +355 -0
  32. package/collector/utils/OCRLoader/validLangs.js +155 -0
  33. package/collector/utils/WhisperProviders/OpenAiWhisper.js +49 -0
  34. package/collector/utils/WhisperProviders/ffmpeg/index.js +114 -0
  35. package/collector/utils/WhisperProviders/localWhisper.js +197 -0
  36. package/collector/utils/comKey/index.js +54 -0
  37. package/collector/utils/constants.js +92 -0
  38. package/collector/utils/downloadURIToFile/index.js +90 -0
  39. package/collector/utils/extensions/Confluence/ConfluenceLoader/index.js +154 -0
  40. package/collector/utils/extensions/Confluence/index.js +292 -0
  41. package/collector/utils/extensions/DrupalWiki/DrupalWiki/index.js +338 -0
  42. package/collector/utils/extensions/DrupalWiki/index.js +102 -0
  43. package/collector/utils/extensions/ObsidianVault/index.js +95 -0
  44. package/collector/utils/extensions/PaperlessNgx/PaperlessNgxLoader/index.js +157 -0
  45. package/collector/utils/extensions/PaperlessNgx/index.js +128 -0
  46. package/collector/utils/extensions/RepoLoader/GithubRepo/RepoLoader/index.js +265 -0
  47. package/collector/utils/extensions/RepoLoader/GithubRepo/index.js +159 -0
  48. package/collector/utils/extensions/RepoLoader/GitlabRepo/RepoLoader/index.js +447 -0
  49. package/collector/utils/extensions/RepoLoader/GitlabRepo/index.js +261 -0
  50. package/collector/utils/extensions/RepoLoader/index.js +41 -0
  51. package/collector/utils/extensions/WebsiteDepth/index.js +211 -0
  52. package/collector/utils/extensions/YoutubeTranscript/YoutubeLoader/index.js +99 -0
  53. package/collector/utils/extensions/YoutubeTranscript/YoutubeLoader/youtube-transcript.js +246 -0
  54. package/collector/utils/extensions/YoutubeTranscript/index.js +219 -0
  55. package/collector/utils/files/index.js +240 -0
  56. package/collector/utils/files/mime.js +64 -0
  57. package/collector/utils/http/index.js +54 -0
  58. package/collector/utils/logger/index.js +68 -0
  59. package/collector/utils/runtimeSettings/index.js +97 -0
  60. package/collector/utils/shell.js +25 -0
  61. package/collector/utils/tokenizer/index.js +66 -0
  62. package/collector/utils/url/index.js +137 -0
  63. package/collector/yarn.lock +4413 -0
  64. package/lib/config.js +79 -0
  65. package/lib/launcher.js +116 -0
  66. package/lib/setup.js +143 -0
  67. package/package.json +64 -0
  68. package/scripts/postinstall.mjs +117 -0
  69. package/server/.env +489 -0
  70. package/server/.env.example +496 -0
  71. package/server/.flowconfig +30 -0
  72. package/server/.nvmrc +1 -0
  73. package/server/endpoints/admin.js +566 -0
  74. package/server/endpoints/agentFileServer.js +174 -0
  75. package/server/endpoints/agentFlows.js +192 -0
  76. package/server/endpoints/agentSkillWhitelist.js +82 -0
  77. package/server/endpoints/agentWebsocket.js +62 -0
  78. package/server/endpoints/api/admin/index.js +775 -0
  79. package/server/endpoints/api/auth/index.js +33 -0
  80. package/server/endpoints/api/document/index.js +1210 -0
  81. package/server/endpoints/api/embed/index.js +409 -0
  82. package/server/endpoints/api/index.js +29 -0
  83. package/server/endpoints/api/openai/compatibility-test-script.cjs +79 -0
  84. package/server/endpoints/api/openai/helpers.js +50 -0
  85. package/server/endpoints/api/openai/index.js +321 -0
  86. package/server/endpoints/api/system/index.js +275 -0
  87. package/server/endpoints/api/userManagement/index.js +124 -0
  88. package/server/endpoints/api/workspace/index.js +1008 -0
  89. package/server/endpoints/api/workspaceThread/index.js +627 -0
  90. package/server/endpoints/browserExtension.js +221 -0
  91. package/server/endpoints/chat.js +193 -0
  92. package/server/endpoints/communityHub.js +214 -0
  93. package/server/endpoints/document.js +111 -0
  94. package/server/endpoints/embed/index.js +103 -0
  95. package/server/endpoints/embedManagement.js +131 -0
  96. package/server/endpoints/experimental/imported-agent-plugins.js +65 -0
  97. package/server/endpoints/experimental/index.js +12 -0
  98. package/server/endpoints/experimental/liveSync.js +110 -0
  99. package/server/endpoints/extensions/index.js +175 -0
  100. package/server/endpoints/invite.js +81 -0
  101. package/server/endpoints/mcpServers.js +127 -0
  102. package/server/endpoints/memory.js +196 -0
  103. package/server/endpoints/mobile/index.js +160 -0
  104. package/server/endpoints/mobile/middleware/index.js +97 -0
  105. package/server/endpoints/mobile/utils/index.js +195 -0
  106. package/server/endpoints/modelRouter.js +205 -0
  107. package/server/endpoints/scheduledJobs.js +374 -0
  108. package/server/endpoints/system.js +1490 -0
  109. package/server/endpoints/telegram.js +333 -0
  110. package/server/endpoints/utils/dockerModelRunnerUtils.js +94 -0
  111. package/server/endpoints/utils/googleAgentSkillEndpoints.js +70 -0
  112. package/server/endpoints/utils/lemonadeUtilsEndpoints.js +170 -0
  113. package/server/endpoints/utils/outlookAgentUtils.js +190 -0
  114. package/server/endpoints/utils.js +220 -0
  115. package/server/endpoints/webPush.js +27 -0
  116. package/server/endpoints/workspaceThreads.js +245 -0
  117. package/server/endpoints/workspaces.js +1159 -0
  118. package/server/endpoints/workspacesParsedFiles.js +208 -0
  119. package/server/index.js +178 -0
  120. package/server/jobs/cleanup-generated-files.js +160 -0
  121. package/server/jobs/cleanup-orphan-documents.js +79 -0
  122. package/server/jobs/embedding-worker.js +197 -0
  123. package/server/jobs/extract-memories.js +192 -0
  124. package/server/jobs/handle-telegram-chat.js +67 -0
  125. package/server/jobs/helpers/index.js +54 -0
  126. package/server/jobs/helpers/memory-extraction-utils.js +366 -0
  127. package/server/jobs/helpers/scheduled-job-helper.js +111 -0
  128. package/server/jobs/run-scheduled-job.js +157 -0
  129. package/server/jobs/sync-watched-documents.js +209 -0
  130. package/server/jsconfig.json +14 -0
  131. package/server/middleware/httpLogger.js +23 -0
  132. package/server/models/agentSkillWhitelist.js +100 -0
  133. package/server/models/apiKeys.js +99 -0
  134. package/server/models/browserExtensionApiKey.js +190 -0
  135. package/server/models/cacheData.js +69 -0
  136. package/server/models/communityHub.js +213 -0
  137. package/server/models/documentSyncQueue.js +252 -0
  138. package/server/models/documentSyncRun.js +88 -0
  139. package/server/models/documents.js +356 -0
  140. package/server/models/embedChats.js +199 -0
  141. package/server/models/embedConfig.js +251 -0
  142. package/server/models/eventLogs.js +129 -0
  143. package/server/models/externalCommunicationConnector.js +110 -0
  144. package/server/models/invite.js +144 -0
  145. package/server/models/memory.js +451 -0
  146. package/server/models/mobileDevice.js +251 -0
  147. package/server/models/modelRouter.js +259 -0
  148. package/server/models/modelRouterRule.js +336 -0
  149. package/server/models/passwordRecovery.js +115 -0
  150. package/server/models/promptHistory.js +107 -0
  151. package/server/models/scheduledJob.js +499 -0
  152. package/server/models/scheduledJobRun.js +362 -0
  153. package/server/models/slashCommandsPresets.js +143 -0
  154. package/server/models/systemPromptVariables.js +361 -0
  155. package/server/models/systemSettings.js +1183 -0
  156. package/server/models/temporaryAuthToken.js +104 -0
  157. package/server/models/user.js +381 -0
  158. package/server/models/vectors.js +79 -0
  159. package/server/models/workspace.js +720 -0
  160. package/server/models/workspaceAgentInvocation.js +97 -0
  161. package/server/models/workspaceChats.js +386 -0
  162. package/server/models/workspaceParsedFiles.js +246 -0
  163. package/server/models/workspaceThread.js +151 -0
  164. package/server/models/workspaceUsers.js +103 -0
  165. package/server/models/workspacesSuggestedMessages.js +83 -0
  166. package/server/package.json +130 -0
  167. package/server/prisma/migrations/20230921191814_init/migration.sql +125 -0
  168. package/server/prisma/migrations/20231101001441_init/migration.sql +2 -0
  169. package/server/prisma/migrations/20231101195421_init/migration.sql +11 -0
  170. package/server/prisma/migrations/20231129012019_add/migration.sql +2 -0
  171. package/server/prisma/migrations/20240113013409_init/migration.sql +2 -0
  172. package/server/prisma/migrations/20240118201333_init/migration.sql +2 -0
  173. package/server/prisma/migrations/20240202002020_init/migration.sql +37 -0
  174. package/server/prisma/migrations/20240206181106_init/migration.sql +13 -0
  175. package/server/prisma/migrations/20240206211916_init/migration.sql +11 -0
  176. package/server/prisma/migrations/20240208224848_init/migration.sql +24 -0
  177. package/server/prisma/migrations/20240210004405_init/migration.sql +2 -0
  178. package/server/prisma/migrations/20240216214639_init/migration.sql +2 -0
  179. package/server/prisma/migrations/20240219211018_init/migration.sql +2 -0
  180. package/server/prisma/migrations/20240301002308_init/migration.sql +2 -0
  181. package/server/prisma/migrations/20240326231053_init/migration.sql +2 -0
  182. package/server/prisma/migrations/20240405015034_init/migration.sql +2 -0
  183. package/server/prisma/migrations/20240412183346_init/migration.sql +24 -0
  184. package/server/prisma/migrations/20240425004220_init/migration.sql +30 -0
  185. package/server/prisma/migrations/20240430230707_init/migration.sql +2 -0
  186. package/server/prisma/migrations/20240510032311_init/migration.sql +15 -0
  187. package/server/prisma/migrations/20240618224346_init/migration.sql +26 -0
  188. package/server/prisma/migrations/20240821215625_init/migration.sql +2 -0
  189. package/server/prisma/migrations/20240824005054_init/migration.sql +15 -0
  190. package/server/prisma/migrations/20241003192954_init/migration.sql +2 -0
  191. package/server/prisma/migrations/20241029203722_init/migration.sql +12 -0
  192. package/server/prisma/migrations/20241029233509_init/migration.sql +5 -0
  193. package/server/prisma/migrations/20250102204948_init/migration.sql +2 -0
  194. package/server/prisma/migrations/20250226005538_init/migration.sql +2 -0
  195. package/server/prisma/migrations/20250318154720_init/migration.sql +18 -0
  196. package/server/prisma/migrations/20250506214129_init/migration.sql +13 -0
  197. package/server/prisma/migrations/20250709230835_init/migration.sql +2 -0
  198. package/server/prisma/migrations/20250725194841_init/migration.sql +17 -0
  199. package/server/prisma/migrations/20250808171557_init/migration.sql +23 -0
  200. package/server/prisma/migrations/20260130040204_init/migration.sql +2 -0
  201. package/server/prisma/migrations/20260313192859_init/migration.sql +10 -0
  202. package/server/prisma/migrations/20260319202916_init/migration.sql +12 -0
  203. package/server/prisma/migrations/20260406120000_init/migration.sql +2 -0
  204. package/server/prisma/migrations/20260423191158_init/migration.sql +29 -0
  205. package/server/prisma/migrations/20260424013043_init/migration.sql +22 -0
  206. package/server/prisma/migrations/20260520160208_init/migration.sql +46 -0
  207. package/server/prisma/migrations/migration_lock.toml +3 -0
  208. package/server/prisma/schema.prisma +484 -0
  209. package/server/prisma/seed.js +31 -0
  210. package/server/public/KaTeX_AMS-Regular.eot +0 -0
  211. package/server/public/KaTeX_AMS-Regular.ttf +0 -0
  212. package/server/public/KaTeX_AMS-Regular.woff +0 -0
  213. package/server/public/KaTeX_AMS-Regular.woff2 +0 -0
  214. package/server/public/KaTeX_Caligraphic-Bold.eot +0 -0
  215. package/server/public/KaTeX_Caligraphic-Bold.ttf +0 -0
  216. package/server/public/KaTeX_Caligraphic-Bold.woff +0 -0
  217. package/server/public/KaTeX_Caligraphic-Bold.woff2 +0 -0
  218. package/server/public/KaTeX_Caligraphic-Regular.eot +0 -0
  219. package/server/public/KaTeX_Caligraphic-Regular.ttf +0 -0
  220. package/server/public/KaTeX_Caligraphic-Regular.woff +0 -0
  221. package/server/public/KaTeX_Caligraphic-Regular.woff2 +0 -0
  222. package/server/public/KaTeX_Fraktur-Bold.eot +0 -0
  223. package/server/public/KaTeX_Fraktur-Bold.ttf +0 -0
  224. package/server/public/KaTeX_Fraktur-Bold.woff +0 -0
  225. package/server/public/KaTeX_Fraktur-Bold.woff2 +0 -0
  226. package/server/public/KaTeX_Fraktur-Regular.eot +0 -0
  227. package/server/public/KaTeX_Fraktur-Regular.ttf +0 -0
  228. package/server/public/KaTeX_Fraktur-Regular.woff +0 -0
  229. package/server/public/KaTeX_Fraktur-Regular.woff2 +0 -0
  230. package/server/public/KaTeX_Main-Bold.eot +0 -0
  231. package/server/public/KaTeX_Main-Bold.ttf +0 -0
  232. package/server/public/KaTeX_Main-Bold.woff +0 -0
  233. package/server/public/KaTeX_Main-Bold.woff2 +0 -0
  234. package/server/public/KaTeX_Main-Italic.eot +0 -0
  235. package/server/public/KaTeX_Main-Italic.ttf +0 -0
  236. package/server/public/KaTeX_Main-Italic.woff +0 -0
  237. package/server/public/KaTeX_Main-Italic.woff2 +0 -0
  238. package/server/public/KaTeX_Main-Regular.eot +0 -0
  239. package/server/public/KaTeX_Main-Regular.ttf +0 -0
  240. package/server/public/KaTeX_Main-Regular.woff +0 -0
  241. package/server/public/KaTeX_Main-Regular.woff2 +0 -0
  242. package/server/public/KaTeX_Math-Italic.eot +0 -0
  243. package/server/public/KaTeX_Math-Italic.ttf +0 -0
  244. package/server/public/KaTeX_Math-Italic.woff +0 -0
  245. package/server/public/KaTeX_Math-Italic.woff2 +0 -0
  246. package/server/public/KaTeX_SansSerif-Regular.eot +0 -0
  247. package/server/public/KaTeX_SansSerif-Regular.ttf +0 -0
  248. package/server/public/KaTeX_SansSerif-Regular.woff +0 -0
  249. package/server/public/KaTeX_SansSerif-Regular.woff2 +0 -0
  250. package/server/public/KaTeX_Script-Regular.eot +0 -0
  251. package/server/public/KaTeX_Script-Regular.ttf +0 -0
  252. package/server/public/KaTeX_Script-Regular.woff +0 -0
  253. package/server/public/KaTeX_Script-Regular.woff2 +0 -0
  254. package/server/public/KaTeX_Size1-Regular.eot +0 -0
  255. package/server/public/KaTeX_Size1-Regular.ttf +0 -0
  256. package/server/public/KaTeX_Size1-Regular.woff +0 -0
  257. package/server/public/KaTeX_Size1-Regular.woff2 +0 -0
  258. package/server/public/KaTeX_Size2-Regular.eot +0 -0
  259. package/server/public/KaTeX_Size2-Regular.ttf +0 -0
  260. package/server/public/KaTeX_Size2-Regular.woff +0 -0
  261. package/server/public/KaTeX_Size2-Regular.woff2 +0 -0
  262. package/server/public/KaTeX_Size3-Regular.eot +0 -0
  263. package/server/public/KaTeX_Size3-Regular.ttf +0 -0
  264. package/server/public/KaTeX_Size3-Regular.woff +0 -0
  265. package/server/public/KaTeX_Size4-Regular.eot +0 -0
  266. package/server/public/KaTeX_Size4-Regular.ttf +0 -0
  267. package/server/public/KaTeX_Size4-Regular.woff +0 -0
  268. package/server/public/KaTeX_Size4-Regular.woff2 +0 -0
  269. package/server/public/KaTeX_Typewriter-Regular.eot +0 -0
  270. package/server/public/KaTeX_Typewriter-Regular.ttf +0 -0
  271. package/server/public/KaTeX_Typewriter-Regular.woff +0 -0
  272. package/server/public/KaTeX_Typewriter-Regular.woff2 +0 -0
  273. package/server/public/PlusJakartaSans.ttf +0 -0
  274. package/server/public/_index.html +45 -0
  275. package/server/public/agent-animation.webm +0 -0
  276. package/server/public/agent-static.png +0 -0
  277. package/server/public/anthropic.png +0 -0
  278. package/server/public/anything-llm-dark.png +0 -0
  279. package/server/public/anything-llm-light.png +0 -0
  280. package/server/public/anything-llm.png +0 -0
  281. package/server/public/apipie.png +0 -0
  282. package/server/public/assets/404-aca8e9d6.js +1 -0
  283. package/server/public/assets/Brain-24e386d5.js +1 -0
  284. package/server/public/assets/Browser-1820fad0.js +1 -0
  285. package/server/public/assets/ChatText-35275002.js +1 -0
  286. package/server/public/assets/Check-7e83fb0d.js +1 -0
  287. package/server/public/assets/Copy-d323e545.js +1 -0
  288. package/server/public/assets/Database-f1a76329.js +1 -0
  289. package/server/public/assets/Eye-9f033dc0.js +1 -0
  290. package/server/public/assets/File-b92df2f3.js +1 -0
  291. package/server/public/assets/Gauge-e6762f4d.js +1 -0
  292. package/server/public/assets/Hammer-05b5ccc7.js +1 -0
  293. package/server/public/assets/Plug-7d951c7d.js +1 -0
  294. package/server/public/assets/PlusCircle-31c6a8d8.js +1 -0
  295. package/server/public/assets/RunDetailPage-edfdbd4d.js +1 -0
  296. package/server/public/assets/RunHistoryPage-732dae26.js +1 -0
  297. package/server/public/assets/Stop-4b47ae05.js +1 -0
  298. package/server/public/assets/Trans-36b04c7b.js +1 -0
  299. package/server/public/assets/WarningCircle-27467274.js +1 -0
  300. package/server/public/assets/XCircle-edfe554c.js +1 -0
  301. package/server/public/assets/admin-04b020fe.js +1 -0
  302. package/server/public/assets/agentFlows-e4124dd3.js +1 -0
  303. package/server/public/assets/anything-llm-infinity-0d7244a1.js +1 -0
  304. package/server/public/assets/communityHub-aba61686.js +1 -0
  305. package/server/public/assets/cron-2ad9194f.js +1 -0
  306. package/server/public/assets/files-493643b0.js +23 -0
  307. package/server/public/assets/github-dark-57c241de.js +1 -0
  308. package/server/public/assets/index-08cd0bc2.js +9 -0
  309. package/server/public/assets/index-0bf8ea25.js +1 -0
  310. package/server/public/assets/index-25b2660c.js +1 -0
  311. package/server/public/assets/index-2a7c0b04.js +1 -0
  312. package/server/public/assets/index-3643e990.js +1 -0
  313. package/server/public/assets/index-3761d55d.js +1 -0
  314. package/server/public/assets/index-4b5e1c76.js +5 -0
  315. package/server/public/assets/index-4fb4d421.js +2 -0
  316. package/server/public/assets/index-56bb11a0.js +1 -0
  317. package/server/public/assets/index-5c320a5d.js +1 -0
  318. package/server/public/assets/index-62160652.js +3 -0
  319. package/server/public/assets/index-62fee0f9.js +4 -0
  320. package/server/public/assets/index-65801ac6.js +1 -0
  321. package/server/public/assets/index-71027183.js +1 -0
  322. package/server/public/assets/index-72832304.js +18 -0
  323. package/server/public/assets/index-7b0ea06b.js +14 -0
  324. package/server/public/assets/index-8132c765.js +1 -0
  325. package/server/public/assets/index-837868b3.js +1 -0
  326. package/server/public/assets/index-86e8a6b4.js +1 -0
  327. package/server/public/assets/index-8ba96f42.js +1 -0
  328. package/server/public/assets/index-8e43159f.js +1 -0
  329. package/server/public/assets/index-92574f3a.js +1 -0
  330. package/server/public/assets/index-925792fe.js +2 -0
  331. package/server/public/assets/index-92d3b7bc.js +1 -0
  332. package/server/public/assets/index-994c849a.js +1 -0
  333. package/server/public/assets/index-9f71774b.js +1 -0
  334. package/server/public/assets/index-9f7dabd6.js +1 -0
  335. package/server/public/assets/index-a0e2be61.js +1 -0
  336. package/server/public/assets/index-a6ac5511.js +1 -0
  337. package/server/public/assets/index-a6c0d98a.js +1 -0
  338. package/server/public/assets/index-aa687cfe.js +3 -0
  339. package/server/public/assets/index-ab35fb74.js +1 -0
  340. package/server/public/assets/index-ab72b353.js +4 -0
  341. package/server/public/assets/index-ad8e77d2.js +5 -0
  342. package/server/public/assets/index-c07cc087.js +110 -0
  343. package/server/public/assets/index-c22f7da1.js +1 -0
  344. package/server/public/assets/index-c9b59c35.js +1 -0
  345. package/server/public/assets/index-d59c6d7f.js +1 -0
  346. package/server/public/assets/index-d69f2e09.js +1 -0
  347. package/server/public/assets/index-e5b911ea.js +1 -0
  348. package/server/public/assets/index-e6c540e1.js +1 -0
  349. package/server/public/assets/index-f86e167c.js +4 -0
  350. package/server/public/assets/index-f984ef26.js +1 -0
  351. package/server/public/assets/index-fb26b60a.js +1 -0
  352. package/server/public/assets/index-fd922432.js +1 -0
  353. package/server/public/assets/main-8ad4162f.js +1 -0
  354. package/server/public/assets/mcpServers-957b1f1c.js +1 -0
  355. package/server/public/assets/moment-3ad2e1a6.js +10 -0
  356. package/server/public/assets/ort.min-faca3c2b.js +1827 -0
  357. package/server/public/assets/piper-o91UDS6e-0c78e94e.js +4 -0
  358. package/server/public/assets/purify-6b86d6dc.js +26 -0
  359. package/server/public/assets/react-beautiful-dnd.esm-86e87aba.js +68 -0
  360. package/server/public/assets/truncate-352eb33b.js +1 -0
  361. package/server/public/assets/types-e90e1137.js +1 -0
  362. package/server/public/assets/usePolling-417bb099.js +1 -0
  363. package/server/public/assets/voices_static-D_OtJDHM-5cdb0950.js +1 -0
  364. package/server/public/assets/worker-8f433525.js +1 -0
  365. package/server/public/azure.png +0 -0
  366. package/server/public/baidu.png +0 -0
  367. package/server/public/bedrock.png +0 -0
  368. package/server/public/bg.png +0 -0
  369. package/server/public/bing.png +0 -0
  370. package/server/public/cerebras.png +0 -0
  371. package/server/public/cohere.png +0 -0
  372. package/server/public/cometapi.png +0 -0
  373. package/server/public/community-hub.png +0 -0
  374. package/server/public/confluence.jpeg +0 -0
  375. package/server/public/deepseek.png +0 -0
  376. package/server/public/docker-model-runner.png +0 -0
  377. package/server/public/dpais.png +0 -0
  378. package/server/public/drupalwiki.jpg +0 -0
  379. package/server/public/duckduckgo.png +0 -0
  380. package/server/public/elevenlabs.png +0 -0
  381. package/server/public/embed/anythingllm-chat-widget.min.css +1 -0
  382. package/server/public/embed/anythingllm-chat-widget.min.js +37 -0
  383. package/server/public/exa.png +0 -0
  384. package/server/public/favicon.ico +0 -0
  385. package/server/public/favicon.png +0 -0
  386. package/server/public/file-system.png +0 -0
  387. package/server/public/files.css +1 -0
  388. package/server/public/fonts/PlusJakartaSans.ttf +0 -0
  389. package/server/public/foundry-local.png +0 -0
  390. package/server/public/gemini.png +0 -0
  391. package/server/public/generate-charts.png +0 -0
  392. package/server/public/generate-save-files.png +0 -0
  393. package/server/public/generic-openai.png +0 -0
  394. package/server/public/giteeai.png +0 -0
  395. package/server/public/github-dark.css +10 -0
  396. package/server/public/github.css +19 -0
  397. package/server/public/github.svg +4 -0
  398. package/server/public/gitlab.svg +7 -0
  399. package/server/public/gmail.png +0 -0
  400. package/server/public/google-calendar.png +0 -0
  401. package/server/public/gplay-badge.svg +55 -0
  402. package/server/public/huggingface.png +0 -0
  403. package/server/public/index.css +1 -0
  404. package/server/public/index.js +1739 -0
  405. package/server/public/koboldcpp.png +0 -0
  406. package/server/public/lancedb.png +0 -0
  407. package/server/public/lemonade.png +0 -0
  408. package/server/public/link.svg +1 -0
  409. package/server/public/litellm.png +0 -0
  410. package/server/public/lmstudio.png +0 -0
  411. package/server/public/localai.png +0 -0
  412. package/server/public/login-logo-light.svg +45 -0
  413. package/server/public/login-logo.svg +45 -0
  414. package/server/public/manifest.json +13 -0
  415. package/server/public/mcp-logo.svg +1 -0
  416. package/server/public/milvus.png +0 -0
  417. package/server/public/minimax.png +0 -0
  418. package/server/public/mistral.jpeg +0 -0
  419. package/server/public/moonshotai.png +0 -0
  420. package/server/public/mssql.png +0 -0
  421. package/server/public/mysql.png +0 -0
  422. package/server/public/nvidia-nim.png +0 -0
  423. package/server/public/obsidian.png +0 -0
  424. package/server/public/ollama.png +0 -0
  425. package/server/public/openai.png +0 -0
  426. package/server/public/openrouter.jpeg +0 -0
  427. package/server/public/outlook.png +0 -0
  428. package/server/public/paperless-ngx.jpeg +0 -0
  429. package/server/public/perplexity.png +0 -0
  430. package/server/public/pgvector.png +0 -0
  431. package/server/public/piper.png +0 -0
  432. package/server/public/privatemode.png +0 -0
  433. package/server/public/qdrant.png +0 -0
  434. package/server/public/rag-memory.png +0 -0
  435. package/server/public/robots.txt +2 -0
  436. package/server/public/router-animation.webm +0 -0
  437. package/server/public/sambanova.png +0 -0
  438. package/server/public/scrape-websites.png +0 -0
  439. package/server/public/searchapi.png +0 -0
  440. package/server/public/searxng.png +0 -0
  441. package/server/public/serpapi.png +0 -0
  442. package/server/public/serper.png +0 -0
  443. package/server/public/serply.png +0 -0
  444. package/server/public/service-workers/push-notifications.js +26 -0
  445. package/server/public/sql-agent.png +0 -0
  446. package/server/public/tavily.svg +1 -0
  447. package/server/public/text-generation-webui.png +0 -0
  448. package/server/public/thinking-animation.webm +0 -0
  449. package/server/public/thinking-static.png +0 -0
  450. package/server/public/togetherai.png +0 -0
  451. package/server/public/view-summarize.png +0 -0
  452. package/server/public/voyageai.png +0 -0
  453. package/server/public/weaviate.png +0 -0
  454. package/server/public/xai.png +0 -0
  455. package/server/public/youtube.svg +10 -0
  456. package/server/public/zai.png +0 -0
  457. package/server/public/zilliz.png +0 -0
  458. package/server/utils/AiProviders/anthropic/index.js +372 -0
  459. package/server/utils/AiProviders/apipie/index.js +386 -0
  460. package/server/utils/AiProviders/azureOpenAi/index.js +232 -0
  461. package/server/utils/AiProviders/bedrock/index.js +787 -0
  462. package/server/utils/AiProviders/bedrock/utils.js +166 -0
  463. package/server/utils/AiProviders/cerebras/index.js +314 -0
  464. package/server/utils/AiProviders/cohere/index.js +251 -0
  465. package/server/utils/AiProviders/cometapi/constants.js +39 -0
  466. package/server/utils/AiProviders/cometapi/index.js +445 -0
  467. package/server/utils/AiProviders/deepseek/index.js +180 -0
  468. package/server/utils/AiProviders/dellProAiStudio/index.js +217 -0
  469. package/server/utils/AiProviders/dockerModelRunner/index.js +520 -0
  470. package/server/utils/AiProviders/fireworksAi/index.js +273 -0
  471. package/server/utils/AiProviders/foundry/index.js +475 -0
  472. package/server/utils/AiProviders/gemini/defaultModels.js +74 -0
  473. package/server/utils/AiProviders/gemini/index.js +457 -0
  474. package/server/utils/AiProviders/gemini/syncStaticLists.mjs +48 -0
  475. package/server/utils/AiProviders/genericOpenAi/index.js +485 -0
  476. package/server/utils/AiProviders/giteeai/index.js +245 -0
  477. package/server/utils/AiProviders/groq/index.js +257 -0
  478. package/server/utils/AiProviders/huggingface/index.js +165 -0
  479. package/server/utils/AiProviders/koboldCPP/index.js +264 -0
  480. package/server/utils/AiProviders/lemonade/index.js +463 -0
  481. package/server/utils/AiProviders/liteLLM/index.js +201 -0
  482. package/server/utils/AiProviders/lmStudio/index.js +383 -0
  483. package/server/utils/AiProviders/localAi/index.js +198 -0
  484. package/server/utils/AiProviders/minimax/index.js +165 -0
  485. package/server/utils/AiProviders/mistral/index.js +191 -0
  486. package/server/utils/AiProviders/modelMap/index.js +212 -0
  487. package/server/utils/AiProviders/modelMap/legacy.js +162 -0
  488. package/server/utils/AiProviders/modelRouter/index.js +170 -0
  489. package/server/utils/AiProviders/moonshotAi/index.js +176 -0
  490. package/server/utils/AiProviders/novita/index.js +460 -0
  491. package/server/utils/AiProviders/nvidiaNim/index.js +253 -0
  492. package/server/utils/AiProviders/ollama/index.js +516 -0
  493. package/server/utils/AiProviders/openAi/index.js +301 -0
  494. package/server/utils/AiProviders/openRouter/index.js +567 -0
  495. package/server/utils/AiProviders/perplexity/index.js +304 -0
  496. package/server/utils/AiProviders/perplexity/models.js +24 -0
  497. package/server/utils/AiProviders/perplexity/scripts/chat_models.txt +6 -0
  498. package/server/utils/AiProviders/perplexity/scripts/parse.mjs +49 -0
  499. package/server/utils/AiProviders/ppio/index.js +274 -0
  500. package/server/utils/AiProviders/privatemode/index.js +220 -0
  501. package/server/utils/AiProviders/sambanova/index.js +273 -0
  502. package/server/utils/AiProviders/textGenWebUI/index.js +197 -0
  503. package/server/utils/AiProviders/togetherAi/index.js +263 -0
  504. package/server/utils/AiProviders/xai/index.js +200 -0
  505. package/server/utils/AiProviders/zai/index.js +184 -0
  506. package/server/utils/BackgroundWorkers/index.js +432 -0
  507. package/server/utils/DocumentManager/index.js +72 -0
  508. package/server/utils/EmbeddingEngines/azureOpenAi/index.js +115 -0
  509. package/server/utils/EmbeddingEngines/cohere/index.js +91 -0
  510. package/server/utils/EmbeddingEngines/gemini/index.js +136 -0
  511. package/server/utils/EmbeddingEngines/genericOpenAi/index.js +128 -0
  512. package/server/utils/EmbeddingEngines/lemonade/index.js +99 -0
  513. package/server/utils/EmbeddingEngines/liteLLM/index.js +102 -0
  514. package/server/utils/EmbeddingEngines/lmstudio/index.js +122 -0
  515. package/server/utils/EmbeddingEngines/localAi/index.js +122 -0
  516. package/server/utils/EmbeddingEngines/mistral/index.js +40 -0
  517. package/server/utils/EmbeddingEngines/native/constants.js +63 -0
  518. package/server/utils/EmbeddingEngines/native/index.js +290 -0
  519. package/server/utils/EmbeddingEngines/ollama/index.js +136 -0
  520. package/server/utils/EmbeddingEngines/openAi/index.js +102 -0
  521. package/server/utils/EmbeddingEngines/openRouter/index.js +131 -0
  522. package/server/utils/EmbeddingEngines/voyageAi/index.js +71 -0
  523. package/server/utils/EmbeddingRerankers/native/index.js +257 -0
  524. package/server/utils/EmbeddingWorkerManager.js +202 -0
  525. package/server/utils/EncryptionManager/index.js +85 -0
  526. package/server/utils/MCP/hypervisor/index.js +554 -0
  527. package/server/utils/MCP/index.js +269 -0
  528. package/server/utils/PasswordRecovery/index.js +103 -0
  529. package/server/utils/PushNotifications/index.js +228 -0
  530. package/server/utils/TextSplitter/index.js +206 -0
  531. package/server/utils/TextToSpeech/elevenLabs/index.js +54 -0
  532. package/server/utils/TextToSpeech/index.js +18 -0
  533. package/server/utils/TextToSpeech/openAi/index.js +29 -0
  534. package/server/utils/TextToSpeech/openAiGeneric/index.js +58 -0
  535. package/server/utils/agentFlows/executor.js +233 -0
  536. package/server/utils/agentFlows/executors/api-call.js +60 -0
  537. package/server/utils/agentFlows/executors/llm-instruction.js +47 -0
  538. package/server/utils/agentFlows/executors/web-scraping.js +110 -0
  539. package/server/utils/agentFlows/flowTypes.js +85 -0
  540. package/server/utils/agentFlows/index.js +288 -0
  541. package/server/utils/agents/aibitat/error.js +18 -0
  542. package/server/utils/agents/aibitat/example/beginner-chat.js +56 -0
  543. package/server/utils/agents/aibitat/example/blog-post-coding.js +55 -0
  544. package/server/utils/agents/aibitat/example/websocket/index.html +67 -0
  545. package/server/utils/agents/aibitat/example/websocket/websock-branding-collab.js +100 -0
  546. package/server/utils/agents/aibitat/example/websocket/websock-multi-turn-chat.js +91 -0
  547. package/server/utils/agents/aibitat/index.js +1437 -0
  548. package/server/utils/agents/aibitat/plugins/chat-history.js +210 -0
  549. package/server/utils/agents/aibitat/plugins/cli.js +134 -0
  550. package/server/utils/agents/aibitat/plugins/create-files/assets/anything-llm-invert.png +0 -0
  551. package/server/utils/agents/aibitat/plugins/create-files/assets/anything-llm.png +0 -0
  552. package/server/utils/agents/aibitat/plugins/create-files/docx/create-docx-file.js +301 -0
  553. package/server/utils/agents/aibitat/plugins/create-files/docx/test-themes.js +298 -0
  554. package/server/utils/agents/aibitat/plugins/create-files/docx/utils.js +1095 -0
  555. package/server/utils/agents/aibitat/plugins/create-files/index.js +23 -0
  556. package/server/utils/agents/aibitat/plugins/create-files/lib.js +300 -0
  557. package/server/utils/agents/aibitat/plugins/create-files/pdf/create-pdf-file.js +138 -0
  558. package/server/utils/agents/aibitat/plugins/create-files/pdf/utils.js +70 -0
  559. package/server/utils/agents/aibitat/plugins/create-files/pptx/create-presentation.js +342 -0
  560. package/server/utils/agents/aibitat/plugins/create-files/pptx/section-agent.js +257 -0
  561. package/server/utils/agents/aibitat/plugins/create-files/pptx/test-themes.js +143 -0
  562. package/server/utils/agents/aibitat/plugins/create-files/pptx/themes.js +181 -0
  563. package/server/utils/agents/aibitat/plugins/create-files/pptx/utils.js +378 -0
  564. package/server/utils/agents/aibitat/plugins/create-files/text/create-text-file.js +158 -0
  565. package/server/utils/agents/aibitat/plugins/create-files/xlsx/create-excel-file.js +362 -0
  566. package/server/utils/agents/aibitat/plugins/create-files/xlsx/utils.js +333 -0
  567. package/server/utils/agents/aibitat/plugins/file-history.js +37 -0
  568. package/server/utils/agents/aibitat/plugins/filesystem/copy-file.js +127 -0
  569. package/server/utils/agents/aibitat/plugins/filesystem/create-directory.js +84 -0
  570. package/server/utils/agents/aibitat/plugins/filesystem/edit-file.js +133 -0
  571. package/server/utils/agents/aibitat/plugins/filesystem/get-file-info.js +75 -0
  572. package/server/utils/agents/aibitat/plugins/filesystem/index.js +33 -0
  573. package/server/utils/agents/aibitat/plugins/filesystem/lib.js +787 -0
  574. package/server/utils/agents/aibitat/plugins/filesystem/list-directory.js +175 -0
  575. package/server/utils/agents/aibitat/plugins/filesystem/move-file.js +95 -0
  576. package/server/utils/agents/aibitat/plugins/filesystem/read-multiple-files.js +157 -0
  577. package/server/utils/agents/aibitat/plugins/filesystem/read-text-file.js +142 -0
  578. package/server/utils/agents/aibitat/plugins/filesystem/search-files.js +469 -0
  579. package/server/utils/agents/aibitat/plugins/filesystem/write-text-file.js +90 -0
  580. package/server/utils/agents/aibitat/plugins/gmail/account/gmail-get-mailbox-stats.js +75 -0
  581. package/server/utils/agents/aibitat/plugins/gmail/drafts/gmail-create-draft-reply.js +220 -0
  582. package/server/utils/agents/aibitat/plugins/gmail/drafts/gmail-create-draft.js +217 -0
  583. package/server/utils/agents/aibitat/plugins/gmail/drafts/gmail-delete-draft.js +87 -0
  584. package/server/utils/agents/aibitat/plugins/gmail/drafts/gmail-get-draft.js +84 -0
  585. package/server/utils/agents/aibitat/plugins/gmail/drafts/gmail-list-drafts.js +96 -0
  586. package/server/utils/agents/aibitat/plugins/gmail/drafts/gmail-send-draft.js +94 -0
  587. package/server/utils/agents/aibitat/plugins/gmail/drafts/gmail-update-draft.js +217 -0
  588. package/server/utils/agents/aibitat/plugins/gmail/index.js +73 -0
  589. package/server/utils/agents/aibitat/plugins/gmail/lib.js +573 -0
  590. package/server/utils/agents/aibitat/plugins/gmail/search/gmail-get-inbox.js +104 -0
  591. package/server/utils/agents/aibitat/plugins/gmail/search/gmail-read-thread.js +122 -0
  592. package/server/utils/agents/aibitat/plugins/gmail/search/gmail-search.js +121 -0
  593. package/server/utils/agents/aibitat/plugins/gmail/send/gmail-reply-to-thread.js +238 -0
  594. package/server/utils/agents/aibitat/plugins/gmail/send/gmail-send-email.js +242 -0
  595. package/server/utils/agents/aibitat/plugins/gmail/threads/gmail-mark-read.js +87 -0
  596. package/server/utils/agents/aibitat/plugins/gmail/threads/gmail-mark-unread.js +87 -0
  597. package/server/utils/agents/aibitat/plugins/gmail/threads/gmail-move-to-archive.js +89 -0
  598. package/server/utils/agents/aibitat/plugins/gmail/threads/gmail-move-to-inbox.js +89 -0
  599. package/server/utils/agents/aibitat/plugins/gmail/threads/gmail-move-to-trash.js +89 -0
  600. package/server/utils/agents/aibitat/plugins/google-calendar/calendars/gcal-get-calendar.js +79 -0
  601. package/server/utils/agents/aibitat/plugins/google-calendar/calendars/gcal-list-calendars.js +82 -0
  602. package/server/utils/agents/aibitat/plugins/google-calendar/events/gcal-create-event.js +233 -0
  603. package/server/utils/agents/aibitat/plugins/google-calendar/events/gcal-get-event.js +116 -0
  604. package/server/utils/agents/aibitat/plugins/google-calendar/events/gcal-get-events-for-day.js +117 -0
  605. package/server/utils/agents/aibitat/plugins/google-calendar/events/gcal-get-events.js +159 -0
  606. package/server/utils/agents/aibitat/plugins/google-calendar/events/gcal-get-upcoming-events.js +249 -0
  607. package/server/utils/agents/aibitat/plugins/google-calendar/events/gcal-quick-add.js +114 -0
  608. package/server/utils/agents/aibitat/plugins/google-calendar/events/gcal-set-my-status.js +125 -0
  609. package/server/utils/agents/aibitat/plugins/google-calendar/events/gcal-update-event.js +173 -0
  610. package/server/utils/agents/aibitat/plugins/google-calendar/index.js +40 -0
  611. package/server/utils/agents/aibitat/plugins/google-calendar/lib.js +288 -0
  612. package/server/utils/agents/aibitat/plugins/http-socket.js +249 -0
  613. package/server/utils/agents/aibitat/plugins/index.js +47 -0
  614. package/server/utils/agents/aibitat/plugins/memory.js +167 -0
  615. package/server/utils/agents/aibitat/plugins/outlook/account/outlook-get-mailbox-stats.js +78 -0
  616. package/server/utils/agents/aibitat/plugins/outlook/drafts/outlook-create-draft.js +232 -0
  617. package/server/utils/agents/aibitat/plugins/outlook/drafts/outlook-delete-draft.js +86 -0
  618. package/server/utils/agents/aibitat/plugins/outlook/drafts/outlook-list-drafts.js +80 -0
  619. package/server/utils/agents/aibitat/plugins/outlook/drafts/outlook-send-draft.js +82 -0
  620. package/server/utils/agents/aibitat/plugins/outlook/drafts/outlook-update-draft.js +132 -0
  621. package/server/utils/agents/aibitat/plugins/outlook/index.js +45 -0
  622. package/server/utils/agents/aibitat/plugins/outlook/lib.js +1413 -0
  623. package/server/utils/agents/aibitat/plugins/outlook/search/outlook-get-inbox.js +75 -0
  624. package/server/utils/agents/aibitat/plugins/outlook/search/outlook-read-thread.js +131 -0
  625. package/server/utils/agents/aibitat/plugins/outlook/search/outlook-search.js +101 -0
  626. package/server/utils/agents/aibitat/plugins/outlook/send/outlook-send-email.js +222 -0
  627. package/server/utils/agents/aibitat/plugins/rechart.js +114 -0
  628. package/server/utils/agents/aibitat/plugins/request-user-input.js +265 -0
  629. package/server/utils/agents/aibitat/plugins/router-classifier.js +122 -0
  630. package/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/MSSQL.js +114 -0
  631. package/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/MySQL.js +83 -0
  632. package/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/Postgresql.js +75 -0
  633. package/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/index.js +80 -0
  634. package/server/utils/agents/aibitat/plugins/sql-agent/SQLConnectors/utils.js +182 -0
  635. package/server/utils/agents/aibitat/plugins/sql-agent/get-table-schema.js +115 -0
  636. package/server/utils/agents/aibitat/plugins/sql-agent/index.js +21 -0
  637. package/server/utils/agents/aibitat/plugins/sql-agent/list-database.js +49 -0
  638. package/server/utils/agents/aibitat/plugins/sql-agent/list-table.js +105 -0
  639. package/server/utils/agents/aibitat/plugins/sql-agent/query.js +101 -0
  640. package/server/utils/agents/aibitat/plugins/summarize.js +189 -0
  641. package/server/utils/agents/aibitat/plugins/web-browsing.js +1182 -0
  642. package/server/utils/agents/aibitat/plugins/web-scraping.js +158 -0
  643. package/server/utils/agents/aibitat/plugins/websocket.js +361 -0
  644. package/server/utils/agents/aibitat/providers/ai-provider.js +706 -0
  645. package/server/utils/agents/aibitat/providers/anthropic.js +490 -0
  646. package/server/utils/agents/aibitat/providers/apipie.js +99 -0
  647. package/server/utils/agents/aibitat/providers/azure.js +122 -0
  648. package/server/utils/agents/aibitat/providers/bedrock.js +456 -0
  649. package/server/utils/agents/aibitat/providers/cerebras.js +208 -0
  650. package/server/utils/agents/aibitat/providers/cohere.js +269 -0
  651. package/server/utils/agents/aibitat/providers/cometapi.js +104 -0
  652. package/server/utils/agents/aibitat/providers/deepseek.js +223 -0
  653. package/server/utils/agents/aibitat/providers/dellProAiStudio.js +106 -0
  654. package/server/utils/agents/aibitat/providers/dockerModelRunner.js +189 -0
  655. package/server/utils/agents/aibitat/providers/fireworksai.js +101 -0
  656. package/server/utils/agents/aibitat/providers/foundry.js +112 -0
  657. package/server/utils/agents/aibitat/providers/gemini.js +450 -0
  658. package/server/utils/agents/aibitat/providers/genericOpenAi.js +206 -0
  659. package/server/utils/agents/aibitat/providers/giteeai.js +94 -0
  660. package/server/utils/agents/aibitat/providers/groq.js +184 -0
  661. package/server/utils/agents/aibitat/providers/helpers/classes.js +16 -0
  662. package/server/utils/agents/aibitat/providers/helpers/tooled.js +384 -0
  663. package/server/utils/agents/aibitat/providers/helpers/untooled.js +437 -0
  664. package/server/utils/agents/aibitat/providers/index.js +77 -0
  665. package/server/utils/agents/aibitat/providers/koboldcpp.js +103 -0
  666. package/server/utils/agents/aibitat/providers/lemonade.js +213 -0
  667. package/server/utils/agents/aibitat/providers/litellm.js +186 -0
  668. package/server/utils/agents/aibitat/providers/lmstudio.js +195 -0
  669. package/server/utils/agents/aibitat/providers/localai.js +190 -0
  670. package/server/utils/agents/aibitat/providers/minimax.js +194 -0
  671. package/server/utils/agents/aibitat/providers/mistral.js +103 -0
  672. package/server/utils/agents/aibitat/providers/moonshotAi.js +97 -0
  673. package/server/utils/agents/aibitat/providers/novita.js +188 -0
  674. package/server/utils/agents/aibitat/providers/nvidiaNim.js +101 -0
  675. package/server/utils/agents/aibitat/providers/ollama.js +606 -0
  676. package/server/utils/agents/aibitat/providers/openai.js +345 -0
  677. package/server/utils/agents/aibitat/providers/openrouter.js +195 -0
  678. package/server/utils/agents/aibitat/providers/perplexity.js +99 -0
  679. package/server/utils/agents/aibitat/providers/ppio.js +104 -0
  680. package/server/utils/agents/aibitat/providers/privatemode.js +107 -0
  681. package/server/utils/agents/aibitat/providers/sambanova.js +94 -0
  682. package/server/utils/agents/aibitat/providers/textgenwebui.js +99 -0
  683. package/server/utils/agents/aibitat/providers/togetherai.js +100 -0
  684. package/server/utils/agents/aibitat/providers/xai.js +99 -0
  685. package/server/utils/agents/aibitat/providers/zai.js +97 -0
  686. package/server/utils/agents/aibitat/utils/dedupe.js +152 -0
  687. package/server/utils/agents/aibitat/utils/summarize.js +63 -0
  688. package/server/utils/agents/aibitat/utils/toolReranker.js +225 -0
  689. package/server/utils/agents/defaults.js +196 -0
  690. package/server/utils/agents/ephemeral.js +790 -0
  691. package/server/utils/agents/imported-manifest.schema.json +158 -0
  692. package/server/utils/agents/imported.js +317 -0
  693. package/server/utils/agents/index.js +883 -0
  694. package/server/utils/boot/MetaGenerator.js +376 -0
  695. package/server/utils/boot/eagerLoadContextWindows.js +40 -0
  696. package/server/utils/boot/index.js +90 -0
  697. package/server/utils/boot/markOnboarded.js +52 -0
  698. package/server/utils/chats/agents.js +111 -0
  699. package/server/utils/chats/apiChatHandler.js +864 -0
  700. package/server/utils/chats/commands/reset.js +37 -0
  701. package/server/utils/chats/embed.js +301 -0
  702. package/server/utils/chats/index.js +128 -0
  703. package/server/utils/chats/openaiCompatible.js +537 -0
  704. package/server/utils/chats/stream.js +376 -0
  705. package/server/utils/collectorApi/index.js +319 -0
  706. package/server/utils/comKey/index.js +86 -0
  707. package/server/utils/database/index.js +83 -0
  708. package/server/utils/files/index.js +519 -0
  709. package/server/utils/files/logo.js +117 -0
  710. package/server/utils/files/multer.js +178 -0
  711. package/server/utils/files/pfp.js +63 -0
  712. package/server/utils/files/purgeDocument.js +91 -0
  713. package/server/utils/helpers/admin/index.js +56 -0
  714. package/server/utils/helpers/agents.js +35 -0
  715. package/server/utils/helpers/camelcase.js +143 -0
  716. package/server/utils/helpers/chat/LLMPerformanceMonitor.js +113 -0
  717. package/server/utils/helpers/chat/convertTo.js +256 -0
  718. package/server/utils/helpers/chat/index.js +448 -0
  719. package/server/utils/helpers/chat/responses.js +383 -0
  720. package/server/utils/helpers/customModels.js +1142 -0
  721. package/server/utils/helpers/index.js +716 -0
  722. package/server/utils/helpers/portAvailabilityChecker.js +46 -0
  723. package/server/utils/helpers/search.js +94 -0
  724. package/server/utils/helpers/shell.js +25 -0
  725. package/server/utils/helpers/tiktoken.js +107 -0
  726. package/server/utils/helpers/updateENV.js +1399 -0
  727. package/server/utils/http/index.js +141 -0
  728. package/server/utils/logger/index.js +66 -0
  729. package/server/utils/memories/index.js +139 -0
  730. package/server/utils/middleware/chatHistoryViewable.js +18 -0
  731. package/server/utils/middleware/communityHubDownloadsEnabled.js +77 -0
  732. package/server/utils/middleware/embedMiddleware.js +178 -0
  733. package/server/utils/middleware/featureFlagEnabled.js +24 -0
  734. package/server/utils/middleware/isSupportedRepoProviders.js +12 -0
  735. package/server/utils/middleware/multiUserProtected.js +107 -0
  736. package/server/utils/middleware/requireFeature.js +46 -0
  737. package/server/utils/middleware/simpleSSOEnabled.js +84 -0
  738. package/server/utils/middleware/validApiKey.js +29 -0
  739. package/server/utils/middleware/validBrowserExtensionApiKey.js +51 -0
  740. package/server/utils/middleware/validWorkspace.js +52 -0
  741. package/server/utils/middleware/validatedRequest.js +111 -0
  742. package/server/utils/middleware/workspaceDeletionProtection.js +18 -0
  743. package/server/utils/prisma/PRISMA.md +47 -0
  744. package/server/utils/prisma/index.js +13 -0
  745. package/server/utils/router/index.js +653 -0
  746. package/server/utils/telegramBot/chat/agent.js +425 -0
  747. package/server/utils/telegramBot/chat/stream.js +471 -0
  748. package/server/utils/telegramBot/constants.js +23 -0
  749. package/server/utils/telegramBot/index.js +844 -0
  750. package/server/utils/telegramBot/utils/commands/handlers/handleAbort.js +15 -0
  751. package/server/utils/telegramBot/utils/commands/handlers/handleHelp.js +15 -0
  752. package/server/utils/telegramBot/utils/commands/handlers/handleHistory.js +80 -0
  753. package/server/utils/telegramBot/utils/commands/handlers/handleNewThread.js +35 -0
  754. package/server/utils/telegramBot/utils/commands/handlers/handleProof.js +202 -0
  755. package/server/utils/telegramBot/utils/commands/handlers/handleReset.js +32 -0
  756. package/server/utils/telegramBot/utils/commands/handlers/handleStart.js +19 -0
  757. package/server/utils/telegramBot/utils/commands/handlers/handleStatus.js +80 -0
  758. package/server/utils/telegramBot/utils/commands/handlers/showModelMenu.js +98 -0
  759. package/server/utils/telegramBot/utils/commands/handlers/showThreadMenu.js +120 -0
  760. package/server/utils/telegramBot/utils/commands/handlers/showWorkspaceMenu.js +84 -0
  761. package/server/utils/telegramBot/utils/commands/index.js +125 -0
  762. package/server/utils/telegramBot/utils/format.js +225 -0
  763. package/server/utils/telegramBot/utils/index.js +203 -0
  764. package/server/utils/telegramBot/utils/media.js +163 -0
  765. package/server/utils/telegramBot/utils/messageQueue.js +53 -0
  766. package/server/utils/telegramBot/utils/navigation/callbacks/handleBackSources.js +16 -0
  767. package/server/utils/telegramBot/utils/navigation/callbacks/handleBackWorkspaces.js +18 -0
  768. package/server/utils/telegramBot/utils/navigation/callbacks/handleModelCancel.js +14 -0
  769. package/server/utils/telegramBot/utils/navigation/callbacks/handleModelPagination.js +24 -0
  770. package/server/utils/telegramBot/utils/navigation/callbacks/handleModelSelect.js +52 -0
  771. package/server/utils/telegramBot/utils/navigation/callbacks/handleSourcePagination.js +24 -0
  772. package/server/utils/telegramBot/utils/navigation/callbacks/handleSourceSelect.js +106 -0
  773. package/server/utils/telegramBot/utils/navigation/callbacks/handleThreadPagination.js +26 -0
  774. package/server/utils/telegramBot/utils/navigation/callbacks/handleThreadSelect.js +43 -0
  775. package/server/utils/telegramBot/utils/navigation/callbacks/handleToolApproval.js +104 -0
  776. package/server/utils/telegramBot/utils/navigation/callbacks/handleWorkspaceCreate.js +33 -0
  777. package/server/utils/telegramBot/utils/navigation/callbacks/handleWorkspacePagination.js +26 -0
  778. package/server/utils/telegramBot/utils/navigation/callbacks/handleWorkspaceSelect.js +24 -0
  779. package/server/utils/telegramBot/utils/navigation/callbacks/index.js +59 -0
  780. package/server/utils/telegramBot/utils/navigation/index.js +36 -0
  781. package/server/utils/telegramBot/utils/verification.js +171 -0
  782. package/server/utils/vectorDbProviders/astra/ASTRA_SETUP.md +22 -0
  783. package/server/utils/vectorDbProviders/astra/index.js +474 -0
  784. package/server/utils/vectorDbProviders/base.js +202 -0
  785. package/server/utils/vectorDbProviders/chroma/index.js +484 -0
  786. package/server/utils/vectorDbProviders/chromacloud/index.js +158 -0
  787. package/server/utils/vectorDbProviders/lance/index.js +506 -0
  788. package/server/utils/vectorDbProviders/milvus/MILVUS_SETUP.md +40 -0
  789. package/server/utils/vectorDbProviders/milvus/index.js +434 -0
  790. package/server/utils/vectorDbProviders/pgvector/SETUP.md +125 -0
  791. package/server/utils/vectorDbProviders/pgvector/index.js +850 -0
  792. package/server/utils/vectorDbProviders/pinecone/PINECONE_SETUP.md +24 -0
  793. package/server/utils/vectorDbProviders/pinecone/index.js +317 -0
  794. package/server/utils/vectorDbProviders/qdrant/QDRANT_SETUP.md +17 -0
  795. package/server/utils/vectorDbProviders/qdrant/index.js +442 -0
  796. package/server/utils/vectorDbProviders/weaviate/WEAVIATE_SETUP.md +17 -0
  797. package/server/utils/vectorDbProviders/weaviate/index.js +510 -0
  798. package/server/utils/vectorDbProviders/zilliz/index.js +36 -0
  799. package/server/utils/vectorStore/resetAllVectorStores.js +59 -0
  800. package/server/yarn.lock +10702 -0
@@ -0,0 +1,1413 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const os = require("os");
4
+ const mime = require("mime");
5
+ const { SystemSettings } = require("../../../../../models/systemSettings");
6
+ const { CollectorApi } = require("../../../../collectorApi");
7
+ const { humanFileSize } = require("../../../../helpers");
8
+ const { safeJsonParse } = require("../../../../http");
9
+
10
+ const MAX_TOTAL_ATTACHMENT_SIZE = 25 * 1024 * 1024; // 25MB limit for Outlook
11
+
12
+ /**
13
+ * Parses a comma-separated email string into Graph API recipient format.
14
+ * @param {string} emailString - Comma-separated email addresses
15
+ * @returns {Array<{emailAddress: {address: string}}>}
16
+ */
17
+ function parseEmailRecipients(emailString) {
18
+ if (!emailString) return [];
19
+ return emailString.split(",").map((email) => ({
20
+ emailAddress: { address: email.trim() },
21
+ }));
22
+ }
23
+
24
+ /**
25
+ * Validates organization auth type configuration.
26
+ * @param {Object} config - The Outlook configuration object
27
+ * @returns {{valid: boolean, error?: string}}
28
+ */
29
+ function validateOrganizationAuth(config) {
30
+ const authType = config.authType || AUTH_TYPES.common;
31
+ if (authType === AUTH_TYPES.organization && !config.tenantId) {
32
+ return {
33
+ valid: false,
34
+ error: "Tenant ID is required for organization-only authentication.",
35
+ };
36
+ }
37
+ return { valid: true };
38
+ }
39
+
40
+ /**
41
+ * Maps a Microsoft Graph message object to a simplified format.
42
+ * @param {Object} msg - The Graph API message object
43
+ * @param {Object} options - Mapping options
44
+ * @param {boolean} options.includeBody - Include full body content
45
+ * @param {boolean} options.includeAttachments - Include attachment details
46
+ * @returns {Object} Simplified message object
47
+ */
48
+ function mapGraphMessage(msg, options = {}) {
49
+ const base = {
50
+ id: msg.id,
51
+ conversationId: msg.conversationId,
52
+ subject: msg.subject,
53
+ from: msg.from?.emailAddress?.address || "Unknown",
54
+ fromName: msg.from?.emailAddress?.name || "",
55
+ to: msg.toRecipients?.map((r) => r.emailAddress?.address).join(", ") || "",
56
+ cc: msg.ccRecipients?.map((r) => r.emailAddress?.address).join(", ") || "",
57
+ isRead: msg.isRead,
58
+ hasAttachments: msg.hasAttachments,
59
+ };
60
+
61
+ if (msg.receivedDateTime) {
62
+ base.receivedDateTime = msg.receivedDateTime;
63
+ }
64
+ if (msg.bodyPreview !== undefined) {
65
+ base.preview = msg.bodyPreview;
66
+ }
67
+
68
+ if (options.includeBody && msg.body) {
69
+ base.date = msg.receivedDateTime;
70
+ base.body = msg.body?.content || "";
71
+ base.bodyType = msg.body?.contentType || "text";
72
+ }
73
+
74
+ if (options.includeAttachments && msg.attachments) {
75
+ base.attachments = (msg.attachments || []).map((att) => ({
76
+ id: att.id,
77
+ name: att.name,
78
+ contentType: att.contentType,
79
+ size: att.size,
80
+ contentBytes: att.contentBytes,
81
+ }));
82
+ }
83
+
84
+ return base;
85
+ }
86
+
87
+ /**
88
+ * Formats an array of messages into a human-readable summary string.
89
+ * @param {Array} messages - Array of simplified message objects
90
+ * @returns {string} Formatted summary
91
+ */
92
+ function formatMessageSummary(messages) {
93
+ return messages
94
+ .map(
95
+ (m, i) =>
96
+ `${i + 1}. [${m.isRead ? "READ" : "UNREAD"}] "${m.subject}" from ${m.fromName || m.from} (${new Date(m.receivedDateTime).toLocaleString()})${m.hasAttachments ? " 📎" : ""}\n ID: ${m.id}\n Conversation ID: ${m.conversationId}`
97
+ )
98
+ .join("\n\n");
99
+ }
100
+
101
+ /**
102
+ * Handles errors in Outlook skill handlers with consistent logging and messaging.
103
+ * @param {Object} context - The handler context (this) from the aibitat function
104
+ * @param {string} skillName - The name of the skill (e.g., "outlook-get-inbox")
105
+ * @param {Error} error - The error object
106
+ * @returns {string} User-friendly error message
107
+ */
108
+ function handleSkillError(context, skillName, error) {
109
+ context.super.handlerProps.log(`${skillName} error: ${error.message}`);
110
+ context.super.introspect(`Error: ${error.message}`);
111
+ return `Error in ${skillName}: ${error.message}`;
112
+ }
113
+
114
+ /**
115
+ * Normalizes a token expiry value to a number.
116
+ * @param {number|string|null|undefined} expiry - The token expiry value
117
+ * @returns {number|null} The normalized expiry as a number, or null if invalid
118
+ */
119
+ function normalizeTokenExpiry(expiry) {
120
+ if (expiry === null || expiry === undefined) return null;
121
+ return typeof expiry === "number" ? expiry : parseInt(expiry, 10);
122
+ }
123
+
124
+ /**
125
+ * Prepares and validates attachments for email sending/drafting.
126
+ * @param {Object} context - The handler context with introspect and caller
127
+ * @param {Array<string>} attachmentPaths - Array of absolute file paths
128
+ * @param {Object} options - Options for attachment handling
129
+ * @param {boolean} options.requireApprovalPerFile - Request approval for each file
130
+ * @param {string} options.recipientInfo - Recipient info for approval message
131
+ * @returns {Promise<{success: boolean, attachments?: Array, summaries?: Array, totalSize?: number, error?: string}>}
132
+ */
133
+ async function prepareAttachmentsWithValidation(
134
+ context,
135
+ attachmentPaths,
136
+ options = {}
137
+ ) {
138
+ if (!Array.isArray(attachmentPaths) || attachmentPaths.length === 0) {
139
+ return { success: true, attachments: [], summaries: [], totalSize: 0 };
140
+ }
141
+
142
+ const preparedAttachments = [];
143
+ const attachmentSummaries = [];
144
+ let totalAttachmentSize = 0;
145
+
146
+ context.super.introspect(
147
+ `${context.caller}: Validating ${attachmentPaths.length} attachment(s)...`
148
+ );
149
+
150
+ for (const filePath of attachmentPaths) {
151
+ const result = prepareAttachment(filePath);
152
+ if (!result.success) {
153
+ context.super.introspect(
154
+ `${context.caller}: Attachment validation failed - ${result.error}`
155
+ );
156
+ return { success: false, error: result.error };
157
+ }
158
+
159
+ totalAttachmentSize += result.fileInfo.size;
160
+ if (totalAttachmentSize > MAX_TOTAL_ATTACHMENT_SIZE) {
161
+ const totalFormatted = humanFileSize(totalAttachmentSize, true);
162
+ context.super.introspect(
163
+ `${context.caller}: Total attachment size (${totalFormatted}) exceeds 25MB limit`
164
+ );
165
+ return {
166
+ success: false,
167
+ error: `Total attachment size (${totalFormatted}) exceeds the 25MB limit.`,
168
+ };
169
+ }
170
+
171
+ if (options.requireApprovalPerFile && context.super.requestToolApproval) {
172
+ const approval = await context.super.requestToolApproval({
173
+ skillName: context.name,
174
+ payload: {
175
+ fileName: result.fileInfo.name,
176
+ fileSize: result.fileInfo.sizeFormatted,
177
+ filePath: result.fileInfo.path,
178
+ },
179
+ description:
180
+ `Attach file "${result.fileInfo.name}" (${result.fileInfo.sizeFormatted}) to email? ` +
181
+ `This file will be sent to ${options.recipientInfo || "recipients"}.`,
182
+ });
183
+
184
+ if (!approval.approved) {
185
+ context.super.introspect(
186
+ `${context.caller}: User rejected attaching "${result.fileInfo.name}"`
187
+ );
188
+ return {
189
+ success: false,
190
+ error: `Attachment rejected by user: ${result.fileInfo.name}. ${approval.message || ""}`,
191
+ };
192
+ }
193
+ }
194
+
195
+ preparedAttachments.push(result.attachment);
196
+ attachmentSummaries.push(
197
+ `${result.fileInfo.name} (${result.fileInfo.sizeFormatted})`
198
+ );
199
+ context.super.introspect(
200
+ `${context.caller}: Prepared attachment "${result.fileInfo.name}"`
201
+ );
202
+ }
203
+
204
+ return {
205
+ success: true,
206
+ attachments: preparedAttachments,
207
+ summaries: attachmentSummaries,
208
+ totalSize: totalAttachmentSize,
209
+ };
210
+ }
211
+
212
+ // ============================================================================
213
+ // Attachment Functions
214
+ // ============================================================================
215
+
216
+ /**
217
+ * Validates and prepares a file attachment for email.
218
+ * @param {string} filePath - Absolute path to the file
219
+ * @returns {{success: boolean, attachment?: object, error?: string, fileInfo?: object}}
220
+ */
221
+ function prepareAttachment(filePath) {
222
+ if (process.env.ANYTHING_LLM_RUNTIME === "docker") {
223
+ return {
224
+ success: false,
225
+ error: "File attachments are not supported in Docker environments.",
226
+ };
227
+ }
228
+
229
+ if (!path.isAbsolute(filePath)) {
230
+ return { success: false, error: `Path must be absolute: ${filePath}` };
231
+ }
232
+
233
+ if (!fs.existsSync(filePath)) {
234
+ return { success: false, error: `File does not exist: ${filePath}` };
235
+ }
236
+
237
+ const stats = fs.statSync(filePath);
238
+ if (!stats.isFile()) {
239
+ return { success: false, error: `Path is not a file: ${filePath}` };
240
+ }
241
+
242
+ if (stats.size === 0) {
243
+ return { success: false, error: `File is empty: ${filePath}` };
244
+ }
245
+
246
+ try {
247
+ const fileBuffer = fs.readFileSync(filePath);
248
+ const base64Data = fileBuffer.toString("base64");
249
+ const fileName = path.basename(filePath);
250
+ const contentType = mime.getType(filePath) || "application/octet-stream";
251
+
252
+ return {
253
+ success: true,
254
+ attachment: {
255
+ "@odata.type": "#microsoft.graph.fileAttachment",
256
+ name: fileName,
257
+ contentType,
258
+ contentBytes: base64Data,
259
+ },
260
+ fileInfo: {
261
+ path: filePath,
262
+ name: fileName,
263
+ size: stats.size,
264
+ sizeFormatted: humanFileSize(stats.size, true),
265
+ contentType,
266
+ },
267
+ };
268
+ } catch (e) {
269
+ return { success: false, error: `Failed to read file: ${e.message}` };
270
+ }
271
+ }
272
+
273
+ /**
274
+ * Parse an attachment using the CollectorApi for secure content extraction.
275
+ * @param {Object} attachment - The attachment object with name, contentType, size, contentBytes (base64)
276
+ * @returns {Promise<{success: boolean, content: string|null, error: string|null}>}
277
+ */
278
+ async function parseAttachment(attachment) {
279
+ const tempDir = os.tmpdir();
280
+ const safeFilename = attachment.name.replace(/[^a-zA-Z0-9._-]/g, "_");
281
+ const tempFilePath = path.join(
282
+ tempDir,
283
+ `outlook-attachment-${Date.now()}-${safeFilename}`
284
+ );
285
+
286
+ try {
287
+ const buffer = Buffer.from(attachment.contentBytes, "base64");
288
+ fs.writeFileSync(tempFilePath, buffer);
289
+
290
+ const collector = new CollectorApi();
291
+ const result = await collector.parseDocument(safeFilename, {
292
+ absolutePath: tempFilePath,
293
+ });
294
+
295
+ if (fs.existsSync(tempFilePath)) {
296
+ fs.unlinkSync(tempFilePath);
297
+ }
298
+
299
+ if (!result.success) {
300
+ return {
301
+ success: false,
302
+ content: null,
303
+ error: result.reason || "Failed to parse attachment",
304
+ };
305
+ }
306
+
307
+ const textContent = result.documents
308
+ ?.map((doc) => doc.pageContent || doc.content || "")
309
+ .filter(Boolean)
310
+ .join("\n\n");
311
+
312
+ return {
313
+ success: true,
314
+ content: textContent || "(No text content extracted)",
315
+ error: null,
316
+ };
317
+ } catch (e) {
318
+ if (fs.existsSync(tempFilePath)) {
319
+ try {
320
+ fs.unlinkSync(tempFilePath);
321
+ } catch {}
322
+ }
323
+ return { success: false, content: null, error: e.message };
324
+ }
325
+ }
326
+
327
+ /**
328
+ * MIME types that can be parsed by the collector to extract text content.
329
+ * These are a subset of ACCEPTED_MIMES from collector/utils/constants.js
330
+ * that are suitable for attachment parsing (excludes audio/video and images).
331
+ * Images are excluded because they're typically signature images in emails.
332
+ */
333
+ const PARSEABLE_ATTACHMENT_MIMES = [
334
+ "text/plain",
335
+ "text/html",
336
+ "text/csv",
337
+ "application/json",
338
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document", // .docx
339
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation", // .pptx
340
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // .xlsx
341
+ "application/vnd.oasis.opendocument.text", // .odt
342
+ "application/vnd.oasis.opendocument.presentation", // .odp
343
+ "application/pdf",
344
+ "application/epub+zip",
345
+ ];
346
+
347
+ /**
348
+ * Checks if an attachment's MIME type can be parsed for text extraction.
349
+ * @param {string} contentType - The MIME type of the attachment
350
+ * @returns {boolean}
351
+ */
352
+ function isParseableMimeType(contentType) {
353
+ if (!contentType) return false;
354
+ const baseMime = contentType.split(";")[0].trim().toLowerCase();
355
+ return PARSEABLE_ATTACHMENT_MIMES.includes(baseMime);
356
+ }
357
+
358
+ /**
359
+ * Collect attachments from messages and optionally parse them with user approval.
360
+ * Only attachments with parseable MIME types will be offered for parsing.
361
+ * If two attachments have the same name, only the first one will be kept (handling fwd emails)
362
+ * @param {Object} context - The handler context (this) from the aibitat function
363
+ * @param {Array} messages - Array of message objects
364
+ * @returns {Promise<{allAttachments: Array, parsedContent: string}>}
365
+ */
366
+ async function handleAttachments(context, messages) {
367
+ const allAttachments = [];
368
+ const uniqueAttachments = new Set();
369
+ messages.forEach((msg, msgIndex) => {
370
+ if (msg.attachments?.length > 0) {
371
+ msg.attachments.forEach((att) => {
372
+ if (uniqueAttachments.has(att.name)) return;
373
+ uniqueAttachments.add(att.name);
374
+ allAttachments.push({
375
+ ...att,
376
+ messageIndex: msgIndex + 1,
377
+ messageId: msg.id,
378
+ });
379
+ });
380
+ }
381
+ });
382
+
383
+ const parseableAttachments = allAttachments.filter((att) =>
384
+ isParseableMimeType(att.contentType)
385
+ );
386
+
387
+ let parsedContent = "";
388
+ const citations = [];
389
+ if (parseableAttachments.length > 0 && context.super.requestToolApproval) {
390
+ const attachmentNames = parseableAttachments
391
+ .map((a) => `${a.name} (${a.contentType})`)
392
+ .join(", ");
393
+
394
+ const approval = await context.super.requestToolApproval({
395
+ skillName: context.name,
396
+ payload: { attachments: attachmentNames },
397
+ description: `Download and parse ${parseableAttachments.length} attachment(s) to extract text content? (${attachmentNames})`,
398
+ });
399
+
400
+ if (approval.approved) {
401
+ context.super.introspect(
402
+ `${context.caller}: Downloading and parsing ${parseableAttachments.length} attachment(s)...`
403
+ );
404
+
405
+ const parsedResults = [];
406
+ for (const attachment of parseableAttachments) {
407
+ if (!attachment.contentBytes) {
408
+ context.super.introspect(
409
+ `${context.caller}: Skipping "${attachment.name}" - no content available`
410
+ );
411
+ continue;
412
+ }
413
+ context.super.introspect(
414
+ `${context.caller}: Parsing "${attachment.name}"...`
415
+ );
416
+ const parseResult = await parseAttachment(attachment);
417
+ if (!parseResult.success) {
418
+ context.super.introspect(
419
+ `${context.caller}: Failed to parse "${attachment.name}": ${parseResult.error}`
420
+ );
421
+ continue;
422
+ }
423
+
424
+ citations.push({
425
+ id: `outlook-attachment-${attachment.messageId}-${attachment.name}`,
426
+ title: attachment.name,
427
+ text: parseResult.content,
428
+ chunkSource: "outlook-attachment://" + attachment.name,
429
+ score: null,
430
+ });
431
+ parsedResults.push({
432
+ name: attachment.name,
433
+ messageIndex: attachment.messageIndex,
434
+ ...parseResult,
435
+ });
436
+ }
437
+
438
+ if (parsedResults.length > 0) {
439
+ parsedContent =
440
+ "\n\n--- Parsed Attachment Content ---\n" +
441
+ parsedResults
442
+ .map(
443
+ (r) => `\n[Message ${r.messageIndex}: ${r.name}]\n${r.content}`
444
+ )
445
+ .join("\n");
446
+ }
447
+
448
+ context.super.introspect(
449
+ `${context.caller}: Finished parsing attachments (${parsedResults.length}/${parseableAttachments.length} successful)`
450
+ );
451
+ } else {
452
+ context.super.introspect(
453
+ `${context.caller}: User declined to parse attachments`
454
+ );
455
+ }
456
+ }
457
+
458
+ citations.forEach((c) => context.super.addCitation?.(c));
459
+ return { allAttachments, parsedContent };
460
+ }
461
+
462
+ /**
463
+ * Microsoft Graph API OAuth2 Configuration
464
+ * Uses Authorization Code Flow with PKCE
465
+ */
466
+ const MICROSOFT_AUTH_URL = "https://login.microsoftonline.com";
467
+ const GRAPH_API_URL = "https://graph.microsoft.com/v1.0";
468
+ const SCOPES = [
469
+ "offline_access",
470
+ "Mail.Read",
471
+ "Mail.ReadWrite",
472
+ "Mail.Send",
473
+ "User.Read",
474
+ ].join(" ");
475
+
476
+ /**
477
+ * Authentication types for Microsoft OAuth2.
478
+ * - "organization": Use tenant ID endpoint (work/school accounts from a specific tenant only)
479
+ * - "common": Use /common endpoint (both personal and work/school accounts)
480
+ * - "consumers": Use /consumers endpoint (personal Microsoft accounts only)
481
+ */
482
+ const AUTH_TYPES = {
483
+ organization: "organization",
484
+ common: "common",
485
+ consumers: "consumers",
486
+ };
487
+
488
+ /**
489
+ * Gets the appropriate OAuth2 authority endpoint based on auth type.
490
+ * @param {string} authType - The authentication type
491
+ * @param {string} tenantId - The tenant ID (used only for "organization" type)
492
+ * @returns {string} The authority path segment
493
+ */
494
+ function getAuthority(authType, tenantId) {
495
+ switch (authType) {
496
+ case AUTH_TYPES.consumers:
497
+ return "consumers";
498
+ case AUTH_TYPES.organization:
499
+ return tenantId || "common";
500
+ case AUTH_TYPES.common:
501
+ default:
502
+ return "common";
503
+ }
504
+ }
505
+
506
+ /**
507
+ * Outlook Bridge Library
508
+ * Handles OAuth2 authentication and Microsoft Graph API communication for Outlook mail.
509
+ */
510
+ class OutlookBridge {
511
+ #accessToken = null;
512
+ #isInitialized = false;
513
+
514
+ #log(text, ...args) {
515
+ console.log(`\x1b[35m[OutlookBridge]\x1b[0m ${text}`, ...args);
516
+ }
517
+
518
+ /**
519
+ * Decodes a JWT token and logs relevant info.
520
+ * @param {string} token - The JWT token to decode
521
+ * @param {string} context - Context label for logging (e.g., "NEW token", "Token")
522
+ * @returns {Object|null} The decoded payload or null if decoding fails
523
+ */
524
+ #decodeAndLogToken(token, context = "Token") {
525
+ try {
526
+ const parts = token.split(".");
527
+ if (parts.length !== 3) return null;
528
+ const payload = JSON.parse(Buffer.from(parts[1], "base64").toString());
529
+ this.#log(
530
+ `${context} for: ${payload.upn || payload.email || payload.unique_name || "unknown"}`
531
+ );
532
+ return payload;
533
+ } catch {
534
+ this.#log(`Could not decode ${context.toLowerCase()}`);
535
+ return null;
536
+ }
537
+ }
538
+
539
+ /**
540
+ * Resets the bridge state, forcing re-initialization on next use.
541
+ */
542
+ reset() {
543
+ this.#accessToken = null;
544
+ this.#isInitialized = false;
545
+ }
546
+
547
+ /**
548
+ * Gets the current Outlook agent configuration from system settings.
549
+ * @returns {Promise<{clientId?: string, tenantId?: string, clientSecret?: string, authType?: string, accessToken?: string, refreshToken?: string, tokenExpiry?: number}>}
550
+ */
551
+ static async getConfig() {
552
+ const configJson = await SystemSettings.getValueOrFallback(
553
+ { label: "outlook_agent_config" },
554
+ "{}"
555
+ );
556
+ return safeJsonParse(configJson, {});
557
+ }
558
+
559
+ /**
560
+ * Updates the Outlook agent configuration in system settings.
561
+ * @param {Object} updates - Fields to update
562
+ * @returns {Promise<{success: boolean, error?: string}>}
563
+ */
564
+ static async updateConfig(updates) {
565
+ try {
566
+ await SystemSettings.updateSettings({
567
+ outlook_agent_config: JSON.stringify(updates),
568
+ });
569
+ return { success: true };
570
+ } catch (error) {
571
+ return { success: false, error: error.message };
572
+ }
573
+ }
574
+
575
+ /**
576
+ * Generates the OAuth2 authorization URL for the user to authenticate.
577
+ * @param {string} redirectUri - The callback URL for OAuth
578
+ * @returns {Promise<{success: boolean, url?: string, error?: string}>}
579
+ */
580
+ async getAuthUrl(redirectUri) {
581
+ const config = await OutlookBridge.getConfig();
582
+
583
+ if (!config.clientId) {
584
+ return {
585
+ success: false,
586
+ error: "Outlook configuration incomplete. Please set Client ID.",
587
+ };
588
+ }
589
+
590
+ const orgAuth = validateOrganizationAuth(config);
591
+ if (!orgAuth.valid) {
592
+ return { success: false, error: orgAuth.error };
593
+ }
594
+
595
+ const authType = config.authType || AUTH_TYPES.common;
596
+ const authority = getAuthority(authType, config.tenantId);
597
+ const params = new URLSearchParams({
598
+ client_id: config.clientId,
599
+ response_type: "code",
600
+ redirect_uri: redirectUri,
601
+ response_mode: "query",
602
+ scope: SCOPES,
603
+ prompt: "consent",
604
+ });
605
+
606
+ const url = `${MICROSOFT_AUTH_URL}/${authority}/oauth2/v2.0/authorize?${params.toString()}`;
607
+ this.#log(`Auth URL using authType: ${authType}, authority: ${authority}`);
608
+ return { success: true, url };
609
+ }
610
+
611
+ /**
612
+ * Exchanges the authorization code for access and refresh tokens.
613
+ * @param {string} code - The authorization code from OAuth callback
614
+ * @param {string} redirectUri - The callback URL used in the initial auth request
615
+ * @returns {Promise<{success: boolean, error?: string}>}
616
+ */
617
+ async exchangeCodeForToken(code, redirectUri) {
618
+ const config = await OutlookBridge.getConfig();
619
+
620
+ if (!config.clientId || !config.clientSecret) {
621
+ return {
622
+ success: false,
623
+ error: "Outlook configuration incomplete.",
624
+ };
625
+ }
626
+
627
+ const orgAuth = validateOrganizationAuth(config);
628
+ if (!orgAuth.valid) {
629
+ return { success: false, error: orgAuth.error };
630
+ }
631
+
632
+ try {
633
+ const authType = config.authType || AUTH_TYPES.common;
634
+ const authority = getAuthority(authType, config.tenantId);
635
+ const tokenUrl = `${MICROSOFT_AUTH_URL}/${authority}/oauth2/v2.0/token`;
636
+ this.#log(
637
+ `Token exchange using authType: ${authType}, authority: ${authority}`
638
+ );
639
+
640
+ const params = new URLSearchParams({
641
+ client_id: config.clientId,
642
+ client_secret: config.clientSecret,
643
+ code,
644
+ redirect_uri: redirectUri,
645
+ grant_type: "authorization_code",
646
+ scope: SCOPES,
647
+ });
648
+
649
+ const response = await fetch(tokenUrl, {
650
+ method: "POST",
651
+ headers: {
652
+ "Content-Type": "application/x-www-form-urlencoded",
653
+ },
654
+ body: params.toString(),
655
+ });
656
+
657
+ const data = await response.json();
658
+
659
+ if (!response.ok) {
660
+ this.#log("Token exchange failed:", data);
661
+ return {
662
+ success: false,
663
+ error:
664
+ data.error_description || data.error || "Token exchange failed",
665
+ };
666
+ }
667
+
668
+ const expiresAt = Date.now() + (data.expires_in - 60) * 1000;
669
+ this.#decodeAndLogToken(data.access_token, "NEW token received");
670
+ await OutlookBridge.updateConfig({
671
+ ...config,
672
+ accessToken: data.access_token,
673
+ refreshToken: data.refresh_token,
674
+ tokenExpiry: expiresAt,
675
+ });
676
+
677
+ this.#accessToken = data.access_token;
678
+ this.#isInitialized = false; // Force re-initialization
679
+
680
+ this.#log("Successfully obtained tokens");
681
+ return { success: true };
682
+ } catch (error) {
683
+ this.#log("Token exchange error:", error.message);
684
+ return { success: false, error: error.message };
685
+ }
686
+ }
687
+
688
+ /**
689
+ * Refreshes the access token using the refresh token.
690
+ * @returns {Promise<{success: boolean, error?: string}>}
691
+ */
692
+ async #refreshAccessToken() {
693
+ const config = await OutlookBridge.getConfig();
694
+
695
+ if (!config.clientId || !config.clientSecret || !config.refreshToken) {
696
+ return {
697
+ success: false,
698
+ error: "Cannot refresh token. Missing configuration or refresh token.",
699
+ };
700
+ }
701
+
702
+ const orgAuth = validateOrganizationAuth(config);
703
+ if (!orgAuth.valid) {
704
+ return { success: false, error: orgAuth.error };
705
+ }
706
+
707
+ try {
708
+ const authType = config.authType || AUTH_TYPES.common;
709
+ const authority = getAuthority(authType, config.tenantId);
710
+ const tokenUrl = `${MICROSOFT_AUTH_URL}/${authority}/oauth2/v2.0/token`;
711
+ this.#log(
712
+ `Token refresh using authType: ${authType}, authority: ${authority}`
713
+ );
714
+
715
+ const params = new URLSearchParams({
716
+ client_id: config.clientId,
717
+ client_secret: config.clientSecret,
718
+ refresh_token: config.refreshToken,
719
+ grant_type: "refresh_token",
720
+ scope: SCOPES,
721
+ });
722
+
723
+ const response = await fetch(tokenUrl, {
724
+ method: "POST",
725
+ headers: {
726
+ "Content-Type": "application/x-www-form-urlencoded",
727
+ },
728
+ body: params.toString(),
729
+ });
730
+
731
+ const data = await response.json();
732
+
733
+ if (!response.ok) {
734
+ this.#log("Token refresh failed:", data);
735
+ return {
736
+ success: false,
737
+ error: data.error_description || data.error || "Token refresh failed",
738
+ };
739
+ }
740
+
741
+ const expiresAt = Date.now() + (data.expires_in - 60) * 1000;
742
+
743
+ await OutlookBridge.updateConfig({
744
+ ...config,
745
+ accessToken: data.access_token,
746
+ refreshToken: data.refresh_token || config.refreshToken,
747
+ tokenExpiry: expiresAt,
748
+ });
749
+
750
+ this.#accessToken = data.access_token;
751
+
752
+ this.#log("Successfully refreshed access token");
753
+ return { success: true };
754
+ } catch (error) {
755
+ this.#log("Token refresh error:", error.message);
756
+ return { success: false, error: error.message };
757
+ }
758
+ }
759
+
760
+ /**
761
+ * Ensures we have a valid access token, refreshing if necessary.
762
+ * @returns {Promise<{success: boolean, error?: string}>}
763
+ */
764
+ async #ensureValidToken() {
765
+ const config = await OutlookBridge.getConfig();
766
+
767
+ if (!config.accessToken || !config.tokenExpiry) {
768
+ this.#log("No access token or expiry found in config");
769
+ return {
770
+ success: false,
771
+ error: "Outlook is not authenticated. Please complete the OAuth flow.",
772
+ };
773
+ }
774
+
775
+ const expiryTime = normalizeTokenExpiry(config.tokenExpiry);
776
+
777
+ const now = Date.now();
778
+ const timeUntilExpiry = expiryTime - now;
779
+ this.#log(
780
+ `Token check: expires in ${Math.round(timeUntilExpiry / 1000)}s (at ${new Date(expiryTime).toISOString()})`
781
+ );
782
+
783
+ const payload = this.#decodeAndLogToken(config.accessToken, "Token check");
784
+ if (payload) {
785
+ this.#log(`Token aud: ${payload.aud}`);
786
+ this.#log(`Token scp: ${payload.scp}`);
787
+ }
788
+
789
+ if (now >= expiryTime) {
790
+ this.#log("Access token expired, refreshing...");
791
+ return this.#refreshAccessToken();
792
+ }
793
+
794
+ this.#accessToken = config.accessToken;
795
+ return { success: true };
796
+ }
797
+
798
+ /**
799
+ * Initializes the Outlook bridge by fetching configuration from system settings.
800
+ * @returns {Promise<{success: boolean, error?: string}>}
801
+ */
802
+ async initialize() {
803
+ if (this.#isInitialized) return { success: true };
804
+
805
+ try {
806
+ const isMultiUser = await SystemSettings.isMultiUserMode();
807
+ if (isMultiUser) {
808
+ return {
809
+ success: false,
810
+ error:
811
+ "Outlook integration is not available in multi-user mode for security reasons.",
812
+ };
813
+ }
814
+
815
+ const config = await OutlookBridge.getConfig();
816
+
817
+ if (!config.clientId || !config.clientSecret) {
818
+ return {
819
+ success: false,
820
+ error:
821
+ "Outlook integration is not configured. Please set Client ID and Client Secret in the agent settings.",
822
+ };
823
+ }
824
+
825
+ const orgAuth = validateOrganizationAuth(config);
826
+ if (!orgAuth.valid) {
827
+ return { success: false, error: orgAuth.error };
828
+ }
829
+
830
+ this.#log(
831
+ `Initializing with authType: ${config.authType || AUTH_TYPES.common}`
832
+ );
833
+
834
+ if (!config.accessToken) {
835
+ return {
836
+ success: false,
837
+ error:
838
+ "Outlook is not authenticated. Please complete the OAuth authorization flow.",
839
+ };
840
+ }
841
+
842
+ const tokenResult = await this.#ensureValidToken();
843
+ if (!tokenResult.success) {
844
+ return tokenResult;
845
+ }
846
+
847
+ this.#isInitialized = true;
848
+ return { success: true };
849
+ } catch (error) {
850
+ return { success: false, error: error.message };
851
+ }
852
+ }
853
+
854
+ /**
855
+ * Checks if the Outlook bridge is properly configured and available.
856
+ * @returns {Promise<boolean>}
857
+ */
858
+ async isAvailable() {
859
+ const result = await this.initialize();
860
+ return result.success;
861
+ }
862
+
863
+ /**
864
+ * Checks if Outlook tools are available (not in multi-user mode and has configuration).
865
+ * @returns {Promise<boolean>}
866
+ */
867
+ static async isToolAvailable() {
868
+ const isMultiUser = await SystemSettings.isMultiUserMode();
869
+ if (isMultiUser) return false;
870
+
871
+ const config = await OutlookBridge.getConfig();
872
+
873
+ if (!config.clientId || !config.clientSecret || !config.accessToken) {
874
+ return false;
875
+ }
876
+
877
+ const orgAuth = validateOrganizationAuth(config);
878
+ return orgAuth.valid;
879
+ }
880
+
881
+ /**
882
+ * Makes a request to the Microsoft Graph API.
883
+ * @param {string} endpoint - The API endpoint (relative to /v1.0)
884
+ * @param {object} options - Fetch options
885
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
886
+ */
887
+ async request(endpoint, options = {}) {
888
+ const initResult = await this.initialize();
889
+ if (!initResult.success) {
890
+ this.#log(`Initialize failed: ${initResult.error}`);
891
+ return { success: false, error: initResult.error };
892
+ }
893
+
894
+ const tokenResult = await this.#ensureValidToken();
895
+ if (!tokenResult.success) {
896
+ this.#log(`Token validation failed: ${tokenResult.error}`);
897
+ return { success: false, error: tokenResult.error };
898
+ }
899
+
900
+ try {
901
+ const url = endpoint.startsWith("http")
902
+ ? endpoint
903
+ : `${GRAPH_API_URL}${endpoint}`;
904
+
905
+ this.#log(`Making request to: ${url}`);
906
+
907
+ const response = await fetch(url, {
908
+ ...options,
909
+ headers: {
910
+ Authorization: `Bearer ${this.#accessToken}`,
911
+ "Content-Type": "application/json",
912
+ ...options.headers,
913
+ },
914
+ });
915
+
916
+ if (!response.ok) {
917
+ const errorText = await response.text();
918
+ let errorData = {};
919
+ try {
920
+ errorData = JSON.parse(errorText);
921
+ } catch {
922
+ errorData = { raw: errorText };
923
+ }
924
+ this.#log(
925
+ `API request failed: ${response.status} ${response.statusText}`,
926
+ `\n Endpoint: ${endpoint}`,
927
+ `\n Headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`,
928
+ `\n Error: ${JSON.stringify(errorData, null, 2)}`
929
+ );
930
+ return {
931
+ success: false,
932
+ error:
933
+ errorData.error?.message ||
934
+ `Request failed with status ${response.status}`,
935
+ };
936
+ }
937
+
938
+ // Handle responses with no content (204 No Content, 202 Accepted with empty body, etc.)
939
+ if (response.status === 204 || response.status === 202) {
940
+ return { success: true, data: {} };
941
+ }
942
+
943
+ const text = await response.text();
944
+ if (!text || text.trim() === "") {
945
+ return { success: true, data: {} };
946
+ }
947
+
948
+ const data = JSON.parse(text);
949
+ return { success: true, data };
950
+ } catch (error) {
951
+ return {
952
+ success: false,
953
+ error: `Outlook API request failed: ${error.message}`,
954
+ };
955
+ }
956
+ }
957
+
958
+ /**
959
+ * Search emails using OData filter syntax.
960
+ * Note: Microsoft Graph API does not support $skip with $search, so pagination
961
+ * is only available when no query is provided.
962
+ * @param {string} query - Search query (uses Microsoft Search syntax)
963
+ * @param {number} limit - Maximum results to return
964
+ * @param {number} skip - Number of results to skip for pagination (ignored when query is provided)
965
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
966
+ */
967
+ async search(query = "", limit = 10, skip = 0) {
968
+ let endpoint;
969
+
970
+ if (query) {
971
+ // $skip is not supported with $search in Microsoft Graph API
972
+ // $orderby is also not supported with $search - results are ordered by relevance
973
+ endpoint = `/me/messages?$top=${limit}&$select=id,subject,from,toRecipients,ccRecipients,receivedDateTime,isRead,hasAttachments,bodyPreview,conversationId&$search="${encodeURIComponent(query)}"`;
974
+ } else {
975
+ endpoint = `/me/messages?$top=${limit}&$skip=${skip}&$orderby=receivedDateTime desc&$select=id,subject,from,toRecipients,ccRecipients,receivedDateTime,isRead,hasAttachments,bodyPreview,conversationId`;
976
+ }
977
+
978
+ const result = await this.request(endpoint);
979
+ if (!result.success) return result;
980
+
981
+ const messages = result.data.value || [];
982
+ return {
983
+ success: true,
984
+ data: {
985
+ messages: messages.map((msg) => mapGraphMessage(msg)),
986
+ resultCount: messages.length,
987
+ hasMore: !!result.data["@odata.nextLink"],
988
+ },
989
+ };
990
+ }
991
+
992
+ /**
993
+ * Get inbox messages (only from the Inbox folder, not archived/other folders).
994
+ * @param {number} limit - Maximum results to return
995
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
996
+ */
997
+ async getInbox(limit = 25) {
998
+ const endpoint = `/me/mailFolders/inbox/messages?$top=${limit}&$orderby=receivedDateTime desc&$select=id,subject,from,toRecipients,ccRecipients,receivedDateTime,isRead,hasAttachments,bodyPreview,conversationId`;
999
+
1000
+ const result = await this.request(endpoint);
1001
+ if (!result.success) return result;
1002
+
1003
+ const messages = result.data.value || [];
1004
+ return {
1005
+ success: true,
1006
+ data: {
1007
+ messages: messages.map((msg) => mapGraphMessage(msg)),
1008
+ resultCount: messages.length,
1009
+ hasMore: !!result.data["@odata.nextLink"],
1010
+ },
1011
+ };
1012
+ }
1013
+
1014
+ /**
1015
+ * Read a full conversation thread by conversation ID.
1016
+ * Note: We avoid combining $filter with $orderby due to Microsoft Graph API
1017
+ * "InefficientFilter" errors. Instead, we fetch without orderby and sort client-side.
1018
+ * @param {string} conversationId - The conversation ID
1019
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
1020
+ */
1021
+ async readThread(conversationId) {
1022
+ const endpoint = `/me/messages?$filter=conversationId eq '${conversationId}'&$select=id,subject,from,toRecipients,ccRecipients,receivedDateTime,isRead,hasAttachments,body,attachments&$expand=attachments`;
1023
+
1024
+ const result = await this.request(endpoint);
1025
+ if (!result.success) return result;
1026
+
1027
+ let messages = result.data.value || [];
1028
+ if (messages.length === 0) {
1029
+ return {
1030
+ success: false,
1031
+ error: "No messages found in this conversation.",
1032
+ };
1033
+ }
1034
+
1035
+ // Sort by receivedDateTime ascending (oldest first) client-side
1036
+ messages.sort(
1037
+ (a, b) => new Date(a.receivedDateTime) - new Date(b.receivedDateTime)
1038
+ );
1039
+
1040
+ return {
1041
+ success: true,
1042
+ data: {
1043
+ conversationId,
1044
+ subject: messages[0]?.subject || "No Subject",
1045
+ messageCount: messages.length,
1046
+ messages: messages.map((msg) =>
1047
+ mapGraphMessage(msg, { includeBody: true, includeAttachments: true })
1048
+ ),
1049
+ },
1050
+ };
1051
+ }
1052
+
1053
+ /**
1054
+ * Read a single message by ID.
1055
+ * @param {string} messageId - The message ID
1056
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
1057
+ */
1058
+ async readMessage(messageId) {
1059
+ const endpoint = `/me/messages/${messageId}?$select=id,subject,from,toRecipients,ccRecipients,receivedDateTime,isRead,hasAttachments,body,conversationId&$expand=attachments`;
1060
+
1061
+ const result = await this.request(endpoint);
1062
+ if (!result.success) return result;
1063
+
1064
+ return {
1065
+ success: true,
1066
+ data: mapGraphMessage(result.data, {
1067
+ includeBody: true,
1068
+ includeAttachments: true,
1069
+ }),
1070
+ };
1071
+ }
1072
+
1073
+ /**
1074
+ * Create a new draft email.
1075
+ * @param {string} to - Recipient email
1076
+ * @param {string} subject - Email subject
1077
+ * @param {string} body - Email body
1078
+ * @param {object} options - Additional options (cc, bcc, isHtml, attachments)
1079
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
1080
+ */
1081
+ async createDraft(to, subject, body, options = {}) {
1082
+ const message = {
1083
+ subject,
1084
+ body: {
1085
+ contentType: options.isHtml ? "HTML" : "Text",
1086
+ content: body,
1087
+ },
1088
+ toRecipients: parseEmailRecipients(to),
1089
+ };
1090
+
1091
+ if (options.cc) {
1092
+ message.ccRecipients = parseEmailRecipients(options.cc);
1093
+ }
1094
+
1095
+ if (options.bcc) {
1096
+ message.bccRecipients = parseEmailRecipients(options.bcc);
1097
+ }
1098
+
1099
+ const result = await this.request("/me/messages", {
1100
+ method: "POST",
1101
+ body: JSON.stringify(message),
1102
+ });
1103
+
1104
+ if (!result.success) return result;
1105
+
1106
+ const draftId = result.data.id;
1107
+
1108
+ if (options.attachments && options.attachments.length > 0) {
1109
+ for (const attachment of options.attachments) {
1110
+ const attachResult = await this.request(
1111
+ `/me/messages/${draftId}/attachments`,
1112
+ {
1113
+ method: "POST",
1114
+ body: JSON.stringify(attachment),
1115
+ }
1116
+ );
1117
+ if (!attachResult.success) {
1118
+ this.#log(`Failed to add attachment: ${attachResult.error}`);
1119
+ }
1120
+ }
1121
+ }
1122
+
1123
+ return {
1124
+ success: true,
1125
+ data: {
1126
+ draftId: result.data.id,
1127
+ subject: result.data.subject,
1128
+ to,
1129
+ webLink: result.data.webLink,
1130
+ },
1131
+ };
1132
+ }
1133
+
1134
+ /**
1135
+ * Create a draft reply to an existing message.
1136
+ * @param {string} messageId - The message ID to reply to
1137
+ * @param {string} body - Reply body
1138
+ * @param {boolean} replyAll - Whether to reply all
1139
+ * @param {object} options - Additional options
1140
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
1141
+ */
1142
+ async createDraftReply(messageId, body, replyAll = false, _options = {}) {
1143
+ const endpoint = replyAll
1144
+ ? `/me/messages/${messageId}/createReplyAll`
1145
+ : `/me/messages/${messageId}/createReply`;
1146
+
1147
+ const result = await this.request(endpoint, {
1148
+ method: "POST",
1149
+ body: JSON.stringify({
1150
+ comment: body,
1151
+ }),
1152
+ });
1153
+
1154
+ if (!result.success) return result;
1155
+
1156
+ return {
1157
+ success: true,
1158
+ data: {
1159
+ draftId: result.data.id,
1160
+ subject: result.data.subject,
1161
+ webLink: result.data.webLink,
1162
+ },
1163
+ };
1164
+ }
1165
+
1166
+ /**
1167
+ * Get a specific draft by ID.
1168
+ * @param {string} draftId - The draft ID
1169
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
1170
+ */
1171
+ async getDraft(draftId) {
1172
+ return this.readMessage(draftId);
1173
+ }
1174
+
1175
+ /**
1176
+ * List all drafts.
1177
+ * @param {number} limit - Maximum drafts to return
1178
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
1179
+ */
1180
+ async listDrafts(limit = 25) {
1181
+ const endpoint = `/me/mailFolders/drafts/messages?$top=${limit}&$orderby=lastModifiedDateTime desc&$select=id,subject,toRecipients,lastModifiedDateTime,bodyPreview`;
1182
+
1183
+ const result = await this.request(endpoint);
1184
+ if (!result.success) return result;
1185
+
1186
+ const drafts = result.data.value || [];
1187
+ return {
1188
+ success: true,
1189
+ data: {
1190
+ drafts: drafts.map((draft) => ({
1191
+ id: draft.id,
1192
+ subject: draft.subject,
1193
+ to:
1194
+ draft.toRecipients
1195
+ ?.map((r) => r.emailAddress?.address)
1196
+ .join(", ") || "",
1197
+ lastModified: draft.lastModifiedDateTime,
1198
+ preview: draft.bodyPreview,
1199
+ })),
1200
+ count: drafts.length,
1201
+ },
1202
+ };
1203
+ }
1204
+
1205
+ /**
1206
+ * Update an existing draft.
1207
+ * @param {string} draftId - The draft ID
1208
+ * @param {object} updates - Fields to update
1209
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
1210
+ */
1211
+ async updateDraft(draftId, updates) {
1212
+ const message = {};
1213
+
1214
+ if (updates.subject) message.subject = updates.subject;
1215
+ if (updates.body) {
1216
+ message.body = {
1217
+ contentType: updates.isHtml ? "HTML" : "Text",
1218
+ content: updates.body,
1219
+ };
1220
+ }
1221
+ if (updates.to) {
1222
+ message.toRecipients = parseEmailRecipients(updates.to);
1223
+ }
1224
+ if (updates.cc) {
1225
+ message.ccRecipients = parseEmailRecipients(updates.cc);
1226
+ }
1227
+
1228
+ const result = await this.request(`/me/messages/${draftId}`, {
1229
+ method: "PATCH",
1230
+ body: JSON.stringify(message),
1231
+ });
1232
+
1233
+ if (!result.success) return result;
1234
+
1235
+ return {
1236
+ success: true,
1237
+ data: {
1238
+ draftId: result.data.id,
1239
+ subject: result.data.subject,
1240
+ },
1241
+ };
1242
+ }
1243
+
1244
+ /**
1245
+ * Delete a draft.
1246
+ * @param {string} draftId - The draft ID
1247
+ * @returns {Promise<{success: boolean, error?: string}>}
1248
+ */
1249
+ async deleteDraft(draftId) {
1250
+ return this.request(`/me/messages/${draftId}`, {
1251
+ method: "DELETE",
1252
+ });
1253
+ }
1254
+
1255
+ /**
1256
+ * Send an existing draft.
1257
+ * @param {string} draftId - The draft ID
1258
+ * @returns {Promise<{success: boolean, error?: string}>}
1259
+ */
1260
+ async sendDraft(draftId) {
1261
+ return this.request(`/me/messages/${draftId}/send`, {
1262
+ method: "POST",
1263
+ });
1264
+ }
1265
+
1266
+ /**
1267
+ * Send an email immediately.
1268
+ * @param {string} to - Recipient email
1269
+ * @param {string} subject - Email subject
1270
+ * @param {string} body - Email body
1271
+ * @param {object} options - Additional options
1272
+ * @returns {Promise<{success: boolean, error?: string}>}
1273
+ */
1274
+ async sendEmail(to, subject, body, options = {}) {
1275
+ const message = {
1276
+ subject,
1277
+ body: {
1278
+ contentType: options.isHtml ? "HTML" : "Text",
1279
+ content: body,
1280
+ },
1281
+ toRecipients: parseEmailRecipients(to),
1282
+ };
1283
+
1284
+ if (options.cc) {
1285
+ message.ccRecipients = parseEmailRecipients(options.cc);
1286
+ }
1287
+
1288
+ if (options.bcc) {
1289
+ message.bccRecipients = parseEmailRecipients(options.bcc);
1290
+ }
1291
+
1292
+ if (options.attachments && options.attachments.length > 0) {
1293
+ message.attachments = options.attachments;
1294
+ }
1295
+
1296
+ return this.request("/me/sendMail", {
1297
+ method: "POST",
1298
+ body: JSON.stringify({
1299
+ message,
1300
+ saveToSentItems: true,
1301
+ }),
1302
+ });
1303
+ }
1304
+
1305
+ /**
1306
+ * Reply to a message immediately.
1307
+ * @param {string} messageId - The message ID to reply to
1308
+ * @param {string} body - Reply body
1309
+ * @param {boolean} replyAll - Whether to reply all
1310
+ * @returns {Promise<{success: boolean, error?: string}>}
1311
+ */
1312
+ async replyToMessage(messageId, body, replyAll = false) {
1313
+ const endpoint = replyAll
1314
+ ? `/me/messages/${messageId}/replyAll`
1315
+ : `/me/messages/${messageId}/reply`;
1316
+
1317
+ return this.request(endpoint, {
1318
+ method: "POST",
1319
+ body: JSON.stringify({
1320
+ comment: body,
1321
+ }),
1322
+ });
1323
+ }
1324
+
1325
+ /**
1326
+ * Mark a message as read.
1327
+ * @param {string} messageId - The message ID
1328
+ * @returns {Promise<{success: boolean, error?: string}>}
1329
+ */
1330
+ async markRead(messageId) {
1331
+ return this.request(`/me/messages/${messageId}`, {
1332
+ method: "PATCH",
1333
+ body: JSON.stringify({ isRead: true }),
1334
+ });
1335
+ }
1336
+
1337
+ /**
1338
+ * Mark a message as unread.
1339
+ * @param {string} messageId - The message ID
1340
+ * @returns {Promise<{success: boolean, error?: string}>}
1341
+ */
1342
+ async markUnread(messageId) {
1343
+ return this.request(`/me/messages/${messageId}`, {
1344
+ method: "PATCH",
1345
+ body: JSON.stringify({ isRead: false }),
1346
+ });
1347
+ }
1348
+
1349
+ /**
1350
+ * Move a message to trash.
1351
+ * @param {string} messageId - The message ID
1352
+ * @returns {Promise<{success: boolean, error?: string}>}
1353
+ */
1354
+ async moveToTrash(messageId) {
1355
+ return this.request(`/me/messages/${messageId}/move`, {
1356
+ method: "POST",
1357
+ body: JSON.stringify({
1358
+ destinationId: "deleteditems",
1359
+ }),
1360
+ });
1361
+ }
1362
+
1363
+ /**
1364
+ * Get mailbox folder statistics.
1365
+ * @returns {Promise<{success: boolean, data?: object, error?: string}>}
1366
+ */
1367
+ async getMailboxStats() {
1368
+ const folders = ["inbox", "drafts", "sentitems", "deleteditems"];
1369
+ const stats = {};
1370
+
1371
+ for (const folder of folders) {
1372
+ const result = await this.request(
1373
+ `/me/mailFolders/${folder}?$select=displayName,totalItemCount,unreadItemCount`
1374
+ );
1375
+ if (result.success) {
1376
+ stats[folder] = {
1377
+ name: result.data.displayName,
1378
+ total: result.data.totalItemCount,
1379
+ unread: result.data.unreadItemCount,
1380
+ };
1381
+ }
1382
+ }
1383
+
1384
+ const profileResult = await this.request("/me?$select=displayName,mail");
1385
+
1386
+ return {
1387
+ success: true,
1388
+ data: {
1389
+ email: profileResult.data?.mail || "Unknown",
1390
+ displayName: profileResult.data?.displayName || "Unknown",
1391
+ folders: stats,
1392
+ },
1393
+ };
1394
+ }
1395
+ }
1396
+
1397
+ module.exports = new OutlookBridge();
1398
+ module.exports.OutlookBridge = OutlookBridge;
1399
+ module.exports.prepareAttachment = prepareAttachment;
1400
+ module.exports.parseAttachment = parseAttachment;
1401
+ module.exports.handleAttachments = handleAttachments;
1402
+ module.exports.isParseableMimeType = isParseableMimeType;
1403
+ module.exports.PARSEABLE_ATTACHMENT_MIMES = PARSEABLE_ATTACHMENT_MIMES;
1404
+ module.exports.MAX_TOTAL_ATTACHMENT_SIZE = MAX_TOTAL_ATTACHMENT_SIZE;
1405
+ module.exports.AUTH_TYPES = AUTH_TYPES;
1406
+ module.exports.formatMessageSummary = formatMessageSummary;
1407
+ module.exports.mapGraphMessage = mapGraphMessage;
1408
+ module.exports.parseEmailRecipients = parseEmailRecipients;
1409
+ module.exports.validateOrganizationAuth = validateOrganizationAuth;
1410
+ module.exports.prepareAttachmentsWithValidation =
1411
+ prepareAttachmentsWithValidation;
1412
+ module.exports.handleSkillError = handleSkillError;
1413
+ module.exports.normalizeTokenExpiry = normalizeTokenExpiry;