@hed-hog/core 0.0.387 → 0.0.390

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 (535) hide show
  1. package/README.md +12 -11
  2. package/dist/access-log/access-log.interceptor.d.ts.map +1 -1
  3. package/dist/access-log/access-log.interceptor.js +4 -2
  4. package/dist/access-log/access-log.interceptor.js.map +1 -1
  5. package/dist/ai/ai-attachment.fragments.d.ts +23 -0
  6. package/dist/ai/ai-attachment.fragments.d.ts.map +1 -0
  7. package/dist/ai/ai-attachment.fragments.js +34 -0
  8. package/dist/ai/ai-attachment.fragments.js.map +1 -0
  9. package/dist/ai/ai.controller.d.ts +7 -16
  10. package/dist/ai/ai.controller.d.ts.map +1 -1
  11. package/dist/ai/ai.prompts.d.ts +16 -0
  12. package/dist/ai/ai.prompts.d.ts.map +1 -0
  13. package/dist/ai/ai.prompts.js +37 -0
  14. package/dist/ai/ai.prompts.js.map +1 -0
  15. package/dist/ai/ai.service.d.ts +63 -12
  16. package/dist/ai/ai.service.d.ts.map +1 -1
  17. package/dist/ai/ai.service.js +215 -88
  18. package/dist/ai/ai.service.js.map +1 -1
  19. package/dist/ai/dto/chat.dto.d.ts +4 -1
  20. package/dist/ai/dto/chat.dto.d.ts.map +1 -1
  21. package/dist/ai/dto/chat.dto.js +23 -1
  22. package/dist/ai/dto/chat.dto.js.map +1 -1
  23. package/dist/ai/dto/create-agent.dto.d.ts +1 -1
  24. package/dist/ai/dto/create-agent.dto.d.ts.map +1 -1
  25. package/dist/ai/dto/create-agent.dto.js +1 -1
  26. package/dist/ai/dto/create-agent.dto.js.map +1 -1
  27. package/dist/ai/dto/update-agent.dto.d.ts +1 -1
  28. package/dist/ai/dto/update-agent.dto.d.ts.map +1 -1
  29. package/dist/ai/dto/update-agent.dto.js +1 -1
  30. package/dist/ai/dto/update-agent.dto.js.map +1 -1
  31. package/dist/ai-instruction/ai-instruction.controller.d.ts +61 -7
  32. package/dist/ai-instruction/ai-instruction.controller.d.ts.map +1 -1
  33. package/dist/ai-instruction/ai-instruction.controller.js +63 -20
  34. package/dist/ai-instruction/ai-instruction.controller.js.map +1 -1
  35. package/dist/ai-instruction/ai-instruction.module.d.ts.map +1 -1
  36. package/dist/ai-instruction/ai-instruction.module.js +13 -2
  37. package/dist/ai-instruction/ai-instruction.module.js.map +1 -1
  38. package/dist/ai-instruction/ai-instruction.service.d.ts +131 -6
  39. package/dist/ai-instruction/ai-instruction.service.d.ts.map +1 -1
  40. package/dist/ai-instruction/ai-instruction.service.js +533 -60
  41. package/dist/ai-instruction/ai-instruction.service.js.map +1 -1
  42. package/dist/ai-instruction/ai-prompt-builder.service.d.ts +8 -0
  43. package/dist/ai-instruction/ai-prompt-builder.service.d.ts.map +1 -1
  44. package/dist/ai-instruction/ai-prompt-builder.service.js +10 -1
  45. package/dist/ai-instruction/ai-prompt-builder.service.js.map +1 -1
  46. package/dist/ai-instruction/ai-prompt-registry.d.ts +45 -0
  47. package/dist/ai-instruction/ai-prompt-registry.d.ts.map +1 -0
  48. package/dist/ai-instruction/ai-prompt-registry.js +49 -0
  49. package/dist/ai-instruction/ai-prompt-registry.js.map +1 -0
  50. package/dist/ai-instruction/ai-prompt-resolver.service.d.ts +89 -0
  51. package/dist/ai-instruction/ai-prompt-resolver.service.d.ts.map +1 -0
  52. package/dist/ai-instruction/ai-prompt-resolver.service.js +222 -0
  53. package/dist/ai-instruction/ai-prompt-resolver.service.js.map +1 -0
  54. package/dist/ai-instruction/ai-prompt-template.util.d.ts +70 -0
  55. package/dist/ai-instruction/ai-prompt-template.util.d.ts.map +1 -0
  56. package/dist/ai-instruction/ai-prompt-template.util.js +154 -0
  57. package/dist/ai-instruction/ai-prompt-template.util.js.map +1 -0
  58. package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts +5 -0
  59. package/dist/ai-instruction/dto/create-ai-instruction.dto.d.ts.map +1 -1
  60. package/dist/ai-instruction/dto/create-ai-instruction.dto.js +27 -1
  61. package/dist/ai-instruction/dto/create-ai-instruction.dto.js.map +1 -1
  62. package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts +14 -0
  63. package/dist/ai-instruction/dto/preview-ai-instruction.dto.d.ts.map +1 -0
  64. package/dist/ai-instruction/dto/preview-ai-instruction.dto.js +42 -0
  65. package/dist/ai-instruction/dto/preview-ai-instruction.dto.js.map +1 -0
  66. package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts +11 -0
  67. package/dist/ai-instruction/dto/update-ai-instruction.dto.d.ts.map +1 -1
  68. package/dist/ai-instruction/dto/update-ai-instruction.dto.js +34 -0
  69. package/dist/ai-instruction/dto/update-ai-instruction.dto.js.map +1 -1
  70. package/dist/ai-instruction/types/ai-instruction.types.d.ts +13 -1
  71. package/dist/ai-instruction/types/ai-instruction.types.d.ts.map +1 -1
  72. package/dist/ai-instruction/types/ai-instruction.types.js +10 -0
  73. package/dist/ai-instruction/types/ai-instruction.types.js.map +1 -1
  74. package/dist/auth/auth.controller.d.ts +24 -9
  75. package/dist/auth/auth.controller.d.ts.map +1 -1
  76. package/dist/auth/auth.controller.js +49 -21
  77. package/dist/auth/auth.controller.js.map +1 -1
  78. package/dist/auth/auth.service.d.ts +33 -8
  79. package/dist/auth/auth.service.d.ts.map +1 -1
  80. package/dist/auth/auth.service.js +78 -29
  81. package/dist/auth/auth.service.js.map +1 -1
  82. package/dist/captcha/captcha.module.d.ts +3 -0
  83. package/dist/captcha/captcha.module.d.ts.map +1 -0
  84. package/dist/captcha/captcha.module.js +23 -0
  85. package/dist/captcha/captcha.module.js.map +1 -0
  86. package/dist/captcha/captcha.service.d.ts +38 -0
  87. package/dist/captcha/captcha.service.d.ts.map +1 -0
  88. package/dist/captcha/captcha.service.js +144 -0
  89. package/dist/captcha/captcha.service.js.map +1 -0
  90. package/dist/challenge/challenge.service.d.ts +16 -7
  91. package/dist/challenge/challenge.service.d.ts.map +1 -1
  92. package/dist/challenge/challenge.service.js +64 -16
  93. package/dist/challenge/challenge.service.js.map +1 -1
  94. package/dist/core.module.d.ts +3 -1
  95. package/dist/core.module.d.ts.map +1 -1
  96. package/dist/core.module.js +29 -2
  97. package/dist/core.module.js.map +1 -1
  98. package/dist/dashboard/dashboard/dashboard.controller.d.ts +15 -15
  99. package/dist/dashboard/dashboard/dashboard.service.d.ts +15 -15
  100. package/dist/dashboard/dashboard-component/dashboard-component.controller.d.ts +6 -6
  101. package/dist/dashboard/dashboard-component/dashboard-component.service.d.ts +6 -6
  102. package/dist/dashboard/dashboard-component-role/dashboard-component-role.controller.d.ts +20 -20
  103. package/dist/dashboard/dashboard-component-role/dashboard-component-role.service.d.ts +20 -20
  104. package/dist/dashboard/dashboard-core/dashboard-core.controller.d.ts +1 -1
  105. package/dist/dashboard/dashboard-core/dashboard-core.service.d.ts +1 -1
  106. package/dist/dashboard/dashboard-role/dashboard-role.controller.d.ts +13 -13
  107. package/dist/dashboard/dashboard-role/dashboard-role.service.d.ts +13 -13
  108. package/dist/file/file.service.d.ts +6 -0
  109. package/dist/file/file.service.d.ts.map +1 -1
  110. package/dist/file/file.service.js +44 -4
  111. package/dist/file/file.service.js.map +1 -1
  112. package/dist/incident/incident-notifier.service.d.ts +36 -0
  113. package/dist/incident/incident-notifier.service.d.ts.map +1 -0
  114. package/dist/incident/incident-notifier.service.js +208 -0
  115. package/dist/incident/incident-notifier.service.js.map +1 -0
  116. package/dist/incident/incident.controller.d.ts +23 -0
  117. package/dist/incident/incident.controller.d.ts.map +1 -0
  118. package/dist/incident/incident.controller.js +75 -0
  119. package/dist/incident/incident.controller.js.map +1 -0
  120. package/dist/incident/incident.module.d.ts +7 -0
  121. package/dist/incident/incident.module.d.ts.map +1 -0
  122. package/dist/incident/incident.module.js +32 -0
  123. package/dist/incident/incident.module.js.map +1 -0
  124. package/dist/incident/incident.service.d.ts +72 -0
  125. package/dist/incident/incident.service.d.ts.map +1 -0
  126. package/dist/incident/incident.service.js +184 -0
  127. package/dist/incident/incident.service.js.map +1 -0
  128. package/dist/index.d.ts +26 -0
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +30 -0
  131. package/dist/index.js.map +1 -1
  132. package/dist/integration-profile/dto/test.dto.d.ts +13 -0
  133. package/dist/integration-profile/dto/test.dto.d.ts.map +1 -0
  134. package/dist/integration-profile/dto/test.dto.js +26 -0
  135. package/dist/integration-profile/dto/test.dto.js.map +1 -0
  136. package/dist/integration-profile/integration-profile.controller.d.ts +12 -1
  137. package/dist/integration-profile/integration-profile.controller.d.ts.map +1 -1
  138. package/dist/integration-profile/integration-profile.controller.js +9 -1
  139. package/dist/integration-profile/integration-profile.controller.js.map +1 -1
  140. package/dist/integration-profile/integration-profile.module.d.ts +6 -1
  141. package/dist/integration-profile/integration-profile.module.d.ts.map +1 -1
  142. package/dist/integration-profile/integration-profile.module.js +26 -3
  143. package/dist/integration-profile/integration-profile.module.js.map +1 -1
  144. package/dist/integration-profile/integration-profile.secrets.d.ts.map +1 -1
  145. package/dist/integration-profile/integration-profile.secrets.js +9 -1
  146. package/dist/integration-profile/integration-profile.secrets.js.map +1 -1
  147. package/dist/integration-profile/integration-profile.service.d.ts +26 -7
  148. package/dist/integration-profile/integration-profile.service.d.ts.map +1 -1
  149. package/dist/integration-profile/integration-profile.service.js +94 -91
  150. package/dist/integration-profile/integration-profile.service.js.map +1 -1
  151. package/dist/integration-profile/integration-profile.utils.d.ts +13 -1
  152. package/dist/integration-profile/integration-profile.utils.d.ts.map +1 -1
  153. package/dist/integration-profile/integration-profile.utils.js +20 -5
  154. package/dist/integration-profile/integration-profile.utils.js.map +1 -1
  155. package/dist/integration-profile/testers/ai.testers.d.ts +3 -0
  156. package/dist/integration-profile/testers/ai.testers.d.ts.map +1 -0
  157. package/dist/integration-profile/testers/ai.testers.js +125 -0
  158. package/dist/integration-profile/testers/ai.testers.js.map +1 -0
  159. package/dist/integration-profile/testers/captcha.testers.d.ts +3 -0
  160. package/dist/integration-profile/testers/captcha.testers.d.ts.map +1 -0
  161. package/dist/integration-profile/testers/captcha.testers.js +121 -0
  162. package/dist/integration-profile/testers/captcha.testers.js.map +1 -0
  163. package/dist/integration-profile/testers/email.testers.d.ts +3 -0
  164. package/dist/integration-profile/testers/email.testers.d.ts.map +1 -0
  165. package/dist/integration-profile/testers/email.testers.js +128 -0
  166. package/dist/integration-profile/testers/email.testers.js.map +1 -0
  167. package/dist/integration-profile/testers/http-probe.d.ts +57 -0
  168. package/dist/integration-profile/testers/http-probe.d.ts.map +1 -0
  169. package/dist/integration-profile/testers/http-probe.js +140 -0
  170. package/dist/integration-profile/testers/http-probe.js.map +1 -0
  171. package/dist/integration-profile/testers/index.d.ts +12 -0
  172. package/dist/integration-profile/testers/index.d.ts.map +1 -0
  173. package/dist/integration-profile/testers/index.js +45 -0
  174. package/dist/integration-profile/testers/index.js.map +1 -0
  175. package/dist/integration-profile/testers/infrastructure.testers.d.ts +3 -0
  176. package/dist/integration-profile/testers/infrastructure.testers.d.ts.map +1 -0
  177. package/dist/integration-profile/testers/infrastructure.testers.js +105 -0
  178. package/dist/integration-profile/testers/infrastructure.testers.js.map +1 -0
  179. package/dist/integration-profile/testers/integration-tester.registry.d.ts +17 -0
  180. package/dist/integration-profile/testers/integration-tester.registry.d.ts.map +1 -0
  181. package/dist/integration-profile/testers/integration-tester.registry.js +52 -0
  182. package/dist/integration-profile/testers/integration-tester.registry.js.map +1 -0
  183. package/dist/integration-profile/testers/integration-tester.types.d.ts +55 -0
  184. package/dist/integration-profile/testers/integration-tester.types.d.ts.map +1 -0
  185. package/dist/integration-profile/testers/integration-tester.types.js +16 -0
  186. package/dist/integration-profile/testers/integration-tester.types.js.map +1 -0
  187. package/dist/integration-profile/testers/messaging.testers.d.ts +3 -0
  188. package/dist/integration-profile/testers/messaging.testers.d.ts.map +1 -0
  189. package/dist/integration-profile/testers/messaging.testers.js +70 -0
  190. package/dist/integration-profile/testers/messaging.testers.js.map +1 -0
  191. package/dist/integration-profile/testers/oauth.testers.d.ts +3 -0
  192. package/dist/integration-profile/testers/oauth.testers.d.ts.map +1 -0
  193. package/dist/integration-profile/testers/oauth.testers.js +285 -0
  194. package/dist/integration-profile/testers/oauth.testers.js.map +1 -0
  195. package/dist/integration-profile/testers/payment.testers.d.ts +3 -0
  196. package/dist/integration-profile/testers/payment.testers.d.ts.map +1 -0
  197. package/dist/integration-profile/testers/payment.testers.js +169 -0
  198. package/dist/integration-profile/testers/payment.testers.js.map +1 -0
  199. package/dist/integration-profile/testers/storage.testers.d.ts +3 -0
  200. package/dist/integration-profile/testers/storage.testers.d.ts.map +1 -0
  201. package/dist/integration-profile/testers/storage.testers.js +208 -0
  202. package/dist/integration-profile/testers/storage.testers.js.map +1 -0
  203. package/dist/language/en.json +4 -2
  204. package/dist/language/pt.json +4 -2
  205. package/dist/leaked-password/leaked-password.controller.d.ts +24 -0
  206. package/dist/leaked-password/leaked-password.controller.d.ts.map +1 -0
  207. package/dist/leaked-password/leaked-password.controller.js +78 -0
  208. package/dist/leaked-password/leaked-password.controller.js.map +1 -0
  209. package/dist/leaked-password/leaked-password.module.d.ts +8 -0
  210. package/dist/leaked-password/leaked-password.module.d.ts.map +1 -0
  211. package/dist/leaked-password/leaked-password.module.js +31 -0
  212. package/dist/leaked-password/leaked-password.module.js.map +1 -0
  213. package/dist/leaked-password/leaked-password.service.d.ts +64 -0
  214. package/dist/leaked-password/leaked-password.service.d.ts.map +1 -0
  215. package/dist/leaked-password/leaked-password.service.js +218 -0
  216. package/dist/leaked-password/leaked-password.service.js.map +1 -0
  217. package/dist/locale/locale.controller.d.ts +1 -1
  218. package/dist/locale/locale.service.d.ts +1 -1
  219. package/dist/mail/dto/preview.dto.d.ts +18 -0
  220. package/dist/mail/dto/preview.dto.d.ts.map +1 -0
  221. package/dist/mail/dto/preview.dto.js +66 -0
  222. package/dist/mail/dto/preview.dto.js.map +1 -0
  223. package/dist/mail/dto/send.dto.d.ts +7 -0
  224. package/dist/mail/dto/send.dto.d.ts.map +1 -1
  225. package/dist/mail/dto/send.dto.js +10 -0
  226. package/dist/mail/dto/send.dto.js.map +1 -1
  227. package/dist/mail/mail.controller.d.ts +4 -0
  228. package/dist/mail/mail.controller.d.ts.map +1 -1
  229. package/dist/mail/mail.controller.js +16 -2
  230. package/dist/mail/mail.controller.js.map +1 -1
  231. package/dist/mail/mail.service.d.ts +23 -2
  232. package/dist/mail/mail.service.d.ts.map +1 -1
  233. package/dist/mail/mail.service.js +102 -13
  234. package/dist/mail/mail.service.js.map +1 -1
  235. package/dist/mail-layout/dto/update.dto.d.ts +17 -0
  236. package/dist/mail-layout/dto/update.dto.d.ts.map +1 -0
  237. package/dist/mail-layout/dto/update.dto.js +27 -0
  238. package/dist/mail-layout/dto/update.dto.js.map +1 -0
  239. package/dist/mail-layout/mail-layout.controller.d.ts +15 -0
  240. package/dist/mail-layout/mail-layout.controller.d.ts.map +1 -0
  241. package/dist/mail-layout/mail-layout.controller.js +71 -0
  242. package/dist/mail-layout/mail-layout.controller.js.map +1 -0
  243. package/dist/mail-layout/mail-layout.module.d.ts +3 -0
  244. package/dist/mail-layout/mail-layout.module.d.ts.map +1 -0
  245. package/dist/mail-layout/mail-layout.module.js +35 -0
  246. package/dist/mail-layout/mail-layout.module.js.map +1 -0
  247. package/dist/mail-layout/mail-layout.service.d.ts +27 -0
  248. package/dist/mail-layout/mail-layout.service.d.ts.map +1 -0
  249. package/dist/mail-layout/mail-layout.service.js +80 -0
  250. package/dist/mail-layout/mail-layout.service.js.map +1 -0
  251. package/dist/mcp-chat/mcp-chat.controller.d.ts +2 -2
  252. package/dist/mcp-chat/mcp-chat.service.d.ts +24 -2
  253. package/dist/mcp-chat/mcp-chat.service.d.ts.map +1 -1
  254. package/dist/mcp-chat/mcp-chat.service.js +80 -24
  255. package/dist/mcp-chat/mcp-chat.service.js.map +1 -1
  256. package/dist/menu/menu.controller.d.ts +3 -3
  257. package/dist/menu/menu.service.d.ts +3 -3
  258. package/dist/notification/notification.controller.d.ts +12 -12
  259. package/dist/notification/notification.service.d.ts +12 -12
  260. package/dist/oauth/oauth-token-broker.service.d.ts +72 -0
  261. package/dist/oauth/oauth-token-broker.service.d.ts.map +1 -0
  262. package/dist/oauth/oauth-token-broker.service.js +258 -0
  263. package/dist/oauth/oauth-token-broker.service.js.map +1 -0
  264. package/dist/oauth/oauth.module.d.ts.map +1 -1
  265. package/dist/oauth/oauth.module.js +3 -1
  266. package/dist/oauth/oauth.module.js.map +1 -1
  267. package/dist/oauth/oauth.service.d.ts +2 -0
  268. package/dist/oauth/oauth.service.d.ts.map +1 -1
  269. package/dist/oauth/oauth.service.js +6 -3
  270. package/dist/oauth/oauth.service.js.map +1 -1
  271. package/dist/pdf/pdf.service.d.ts +8 -0
  272. package/dist/pdf/pdf.service.d.ts.map +1 -1
  273. package/dist/pdf/pdf.service.js +52 -0
  274. package/dist/pdf/pdf.service.js.map +1 -1
  275. package/dist/presence/presence.controller.d.ts +16 -0
  276. package/dist/presence/presence.controller.d.ts.map +1 -0
  277. package/dist/presence/presence.controller.js +60 -0
  278. package/dist/presence/presence.controller.js.map +1 -0
  279. package/dist/presence/presence.listener.d.ts +29 -0
  280. package/dist/presence/presence.listener.d.ts.map +1 -0
  281. package/dist/presence/presence.listener.js +82 -0
  282. package/dist/presence/presence.listener.js.map +1 -0
  283. package/dist/presence/presence.module.d.ts +3 -0
  284. package/dist/presence/presence.module.d.ts.map +1 -0
  285. package/dist/presence/presence.module.js +32 -0
  286. package/dist/presence/presence.module.js.map +1 -0
  287. package/dist/presence/presence.service.d.ts +42 -0
  288. package/dist/presence/presence.service.d.ts.map +1 -0
  289. package/dist/presence/presence.service.js +147 -0
  290. package/dist/presence/presence.service.js.map +1 -0
  291. package/dist/profile/dto/delete-account.dto.d.ts +8 -0
  292. package/dist/profile/dto/delete-account.dto.d.ts.map +1 -0
  293. package/dist/profile/dto/delete-account.dto.js +22 -0
  294. package/dist/profile/dto/delete-account.dto.js.map +1 -0
  295. package/dist/profile/events/profile-account-deleted.event.d.ts +12 -0
  296. package/dist/profile/events/profile-account-deleted.event.d.ts.map +1 -0
  297. package/dist/profile/events/profile-account-deleted.event.js +17 -0
  298. package/dist/profile/events/profile-account-deleted.event.js.map +1 -0
  299. package/dist/profile/profile.controller.d.ts +21 -15
  300. package/dist/profile/profile.controller.d.ts.map +1 -1
  301. package/dist/profile/profile.controller.js +75 -46
  302. package/dist/profile/profile.controller.js.map +1 -1
  303. package/dist/profile/profile.service.d.ts +30 -18
  304. package/dist/profile/profile.service.d.ts.map +1 -1
  305. package/dist/profile/profile.service.js +113 -37
  306. package/dist/profile/profile.service.js.map +1 -1
  307. package/dist/realtime/realtime.gateway.d.ts +48 -0
  308. package/dist/realtime/realtime.gateway.d.ts.map +1 -0
  309. package/dist/realtime/realtime.gateway.js +156 -0
  310. package/dist/realtime/realtime.gateway.js.map +1 -0
  311. package/dist/realtime/realtime.module.d.ts +8 -0
  312. package/dist/realtime/realtime.module.d.ts.map +1 -0
  313. package/dist/realtime/realtime.module.js +29 -0
  314. package/dist/realtime/realtime.module.js.map +1 -0
  315. package/dist/realtime/realtime.service.d.ts +51 -0
  316. package/dist/realtime/realtime.service.d.ts.map +1 -0
  317. package/dist/realtime/realtime.service.js +177 -0
  318. package/dist/realtime/realtime.service.js.map +1 -0
  319. package/dist/redis/redis-pubsub.d.ts +27 -0
  320. package/dist/redis/redis-pubsub.d.ts.map +1 -0
  321. package/dist/redis/redis-pubsub.js +140 -0
  322. package/dist/redis/redis-pubsub.js.map +1 -0
  323. package/dist/role/role.controller.d.ts +3 -3
  324. package/dist/role/role.service.d.ts +3 -3
  325. package/dist/setting/dto/create.dto.d.ts.map +1 -1
  326. package/dist/setting/dto/create.dto.js +9 -2
  327. package/dist/setting/dto/create.dto.js.map +1 -1
  328. package/dist/setting/setting.controller.d.ts +5 -5
  329. package/dist/setting/setting.service.d.ts +8 -5
  330. package/dist/setting/setting.service.d.ts.map +1 -1
  331. package/dist/setting/setting.service.js +25 -1
  332. package/dist/setting/setting.service.js.map +1 -1
  333. package/dist/user/dto/create-with-email-and-password.dto.d.ts +2 -0
  334. package/dist/user/dto/create-with-email-and-password.dto.d.ts.map +1 -1
  335. package/dist/user/dto/create-with-email-and-password.dto.js +5 -0
  336. package/dist/user/dto/create-with-email-and-password.dto.js.map +1 -1
  337. package/dist/user/dto/query-user-mail-list.dto.d.ts +5 -0
  338. package/dist/user/dto/query-user-mail-list.dto.d.ts.map +1 -0
  339. package/dist/user/dto/query-user-mail-list.dto.js +25 -0
  340. package/dist/user/dto/query-user-mail-list.dto.js.map +1 -0
  341. package/dist/user/user-credential.util.d.ts +19 -0
  342. package/dist/user/user-credential.util.d.ts.map +1 -0
  343. package/dist/user/user-credential.util.js +32 -0
  344. package/dist/user/user-credential.util.js.map +1 -0
  345. package/dist/user/user.controller.d.ts +17 -5
  346. package/dist/user/user.controller.d.ts.map +1 -1
  347. package/dist/user/user.controller.js +18 -3
  348. package/dist/user/user.controller.js.map +1 -1
  349. package/dist/user/user.service.d.ts +28 -6
  350. package/dist/user/user.service.d.ts.map +1 -1
  351. package/dist/user/user.service.js +204 -13
  352. package/dist/user/user.service.js.map +1 -1
  353. package/dist/validators/is-strong-password-with-settings.validator.d.ts.map +1 -1
  354. package/dist/validators/is-strong-password-with-settings.validator.js +11 -0
  355. package/dist/validators/is-strong-password-with-settings.validator.js.map +1 -1
  356. package/dist/validators/service-locator.d.ts +9 -0
  357. package/dist/validators/service-locator.d.ts.map +1 -1
  358. package/dist/validators/service-locator.js +12 -0
  359. package/dist/validators/service-locator.js.map +1 -1
  360. package/dist/whatsapp-sender/whatsapp-sender.module.d.ts +3 -0
  361. package/dist/whatsapp-sender/whatsapp-sender.module.d.ts.map +1 -0
  362. package/dist/whatsapp-sender/whatsapp-sender.module.js +23 -0
  363. package/dist/whatsapp-sender/whatsapp-sender.module.js.map +1 -0
  364. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts +50 -0
  365. package/dist/whatsapp-sender/whatsapp-sender.service.d.ts.map +1 -0
  366. package/dist/whatsapp-sender/whatsapp-sender.service.js +224 -0
  367. package/dist/whatsapp-sender/whatsapp-sender.service.js.map +1 -0
  368. package/hedhog/data/integration_provider.yaml +16 -0
  369. package/hedhog/data/mail.yaml +88 -61
  370. package/hedhog/data/mail_layout.yaml +188 -0
  371. package/hedhog/data/menu.yaml +67 -3
  372. package/hedhog/data/route.yaml +135 -0
  373. package/hedhog/data/setting_group.yaml +139 -1
  374. package/hedhog/frontend/app/account/components/mfa-setup-dialog.tsx.ejs +36 -0
  375. package/hedhog/frontend/app/account/components/two-factor-auth.tsx.ejs +2 -0
  376. package/hedhog/frontend/app/account/hooks/use-mfa-setup.ts.ejs +10 -7
  377. package/hedhog/frontend/app/ai_agent/page.tsx.ejs +7 -4
  378. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-form.tsx.ejs +580 -0
  379. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-preview.tsx.ejs +150 -0
  380. package/hedhog/frontend/app/ai_instruction/_components/ai-instruction-versions.tsx.ejs +199 -0
  381. package/hedhog/frontend/app/ai_instruction/_components/prompt-diff.tsx.ejs +63 -0
  382. package/hedhog/frontend/app/ai_instruction/_lib/line-diff.spec.ts.ejs +59 -0
  383. package/hedhog/frontend/app/ai_instruction/_lib/line-diff.ts.ejs +72 -0
  384. package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.spec.ts.ejs +170 -0
  385. package/hedhog/frontend/app/ai_instruction/_lib/prompt-template.ts.ejs +167 -0
  386. package/hedhog/frontend/app/ai_instruction/_lib/types.ts.ejs +99 -0
  387. package/hedhog/frontend/app/ai_instruction/page.tsx.ejs +422 -0
  388. package/hedhog/frontend/app/configurations/[slug]/components/setting-field.tsx.ejs +51 -4
  389. package/hedhog/frontend/app/incidents/page.tsx.ejs +400 -0
  390. package/hedhog/frontend/app/integration/profiles/page.tsx.ejs +153 -84
  391. package/hedhog/frontend/app/mail/layout/page.tsx.ejs +344 -0
  392. package/hedhog/frontend/app/mail/template/page.tsx.ejs +155 -121
  393. package/hedhog/frontend/app/mcp_chat/page.tsx.ejs +129 -17
  394. package/hedhog/frontend/app/pages/_components/page-delete-dialog.tsx.ejs +343 -0
  395. package/hedhog/frontend/app/pages/_components/page-detail-sheet.tsx.ejs +438 -0
  396. package/hedhog/frontend/app/pages/_components/page-wizard-sheet.tsx.ejs +1009 -0
  397. package/hedhog/frontend/app/pages/_components/system-page-types.ts.ejs +56 -0
  398. package/hedhog/frontend/app/pages/_components/use-system-pages.ts.ejs +171 -0
  399. package/hedhog/frontend/app/pages/page.tsx.ejs +514 -0
  400. package/hedhog/frontend/app/users/page.tsx.ejs +119 -13
  401. package/hedhog/frontend/app/users/user-activity-timeline.tsx.ejs +231 -0
  402. package/hedhog/frontend/app/users/user-mails.tsx.ejs +399 -0
  403. package/hedhog/frontend/app/users/user-sheet.tsx.ejs +60 -75
  404. package/hedhog/frontend/messages/en.json +499 -3
  405. package/hedhog/frontend/messages/pt.json +499 -3
  406. package/hedhog/table/ai_agent.yaml +1 -0
  407. package/hedhog/table/ai_instruction.yaml +15 -0
  408. package/hedhog/table/leaked_password.yaml +18 -0
  409. package/hedhog/table/mail_layout.yaml +35 -0
  410. package/hedhog/table/mail_var.yaml +4 -0
  411. package/hedhog/table/setting.yaml +1 -0
  412. package/hedhog/table/system_incident.yaml +59 -0
  413. package/hedhog/table/user_presence.yaml +36 -0
  414. package/package.json +8 -4
  415. package/src/access-log/access-log.interceptor.ts +4 -2
  416. package/src/ai/ai-attachment.fragments.spec.ts +319 -0
  417. package/src/ai/ai-attachment.fragments.ts +35 -0
  418. package/src/ai/ai.prompts.ts +38 -0
  419. package/src/ai/ai.service.spec.ts +280 -0
  420. package/src/ai/ai.service.ts +338 -82
  421. package/src/ai/dto/chat.dto.ts +33 -3
  422. package/src/ai/dto/create-agent.dto.ts +2 -2
  423. package/src/ai/dto/update-agent.dto.ts +2 -2
  424. package/src/ai-instruction/ai-instruction.controller.ts +40 -9
  425. package/src/ai-instruction/ai-instruction.module.ts +13 -2
  426. package/src/ai-instruction/ai-instruction.service.spec.ts +658 -0
  427. package/src/ai-instruction/ai-instruction.service.ts +661 -62
  428. package/src/ai-instruction/ai-prompt-builder.service.ts +10 -1
  429. package/src/ai-instruction/ai-prompt-registry.ts +87 -0
  430. package/src/ai-instruction/ai-prompt-resolver.service.spec.ts +375 -0
  431. package/src/ai-instruction/ai-prompt-resolver.service.ts +295 -0
  432. package/src/ai-instruction/ai-prompt-template.util.spec.ts +162 -0
  433. package/src/ai-instruction/ai-prompt-template.util.ts +199 -0
  434. package/src/ai-instruction/dto/create-ai-instruction.dto.ts +39 -3
  435. package/src/ai-instruction/dto/preview-ai-instruction.dto.ts +26 -0
  436. package/src/ai-instruction/dto/update-ai-instruction.dto.ts +42 -1
  437. package/src/ai-instruction/types/ai-instruction.types.ts +24 -1
  438. package/src/auth/auth.controller.ts +31 -5
  439. package/src/auth/auth.service.spec.ts +3 -1
  440. package/src/auth/auth.service.ts +101 -36
  441. package/src/captcha/captcha.module.ts +10 -0
  442. package/src/captcha/captcha.service.spec.ts +210 -0
  443. package/src/captcha/captcha.service.ts +191 -0
  444. package/src/challenge/challenge.service.spec.ts +39 -4
  445. package/src/challenge/challenge.service.ts +72 -17
  446. package/src/core.module.ts +27 -1
  447. package/src/file/file.service.spec.ts +105 -0
  448. package/src/file/file.service.ts +60 -3
  449. package/src/incident/incident-notifier.service.spec.ts +205 -0
  450. package/src/incident/incident-notifier.service.ts +241 -0
  451. package/src/incident/incident.controller.ts +38 -0
  452. package/src/incident/incident.module.ts +19 -0
  453. package/src/incident/incident.service.spec.ts +150 -0
  454. package/src/incident/incident.service.ts +209 -0
  455. package/src/index.ts +37 -0
  456. package/src/integration-profile/dto/test.dto.ts +19 -0
  457. package/src/integration-profile/integration-profile.controller.ts +10 -1
  458. package/src/integration-profile/integration-profile.module.spec.ts +51 -0
  459. package/src/integration-profile/integration-profile.module.ts +23 -4
  460. package/src/integration-profile/integration-profile.secrets.ts +9 -1
  461. package/src/integration-profile/integration-profile.service.spec.ts +279 -0
  462. package/src/integration-profile/integration-profile.service.ts +120 -124
  463. package/src/integration-profile/integration-profile.utils.spec.ts +22 -0
  464. package/src/integration-profile/integration-profile.utils.ts +40 -3
  465. package/src/integration-profile/testers/ai.testers.ts +165 -0
  466. package/src/integration-profile/testers/captcha.testers.spec.ts +92 -0
  467. package/src/integration-profile/testers/captcha.testers.ts +139 -0
  468. package/src/integration-profile/testers/email.testers.ts +161 -0
  469. package/src/integration-profile/testers/http-probe.spec.ts +153 -0
  470. package/src/integration-profile/testers/http-probe.ts +171 -0
  471. package/src/integration-profile/testers/index.ts +30 -0
  472. package/src/integration-profile/testers/infrastructure.testers.ts +122 -0
  473. package/src/integration-profile/testers/integration-tester.registry.spec.ts +75 -0
  474. package/src/integration-profile/testers/integration-tester.registry.ts +43 -0
  475. package/src/integration-profile/testers/integration-tester.types.ts +61 -0
  476. package/src/integration-profile/testers/messaging.testers.ts +102 -0
  477. package/src/integration-profile/testers/oauth.testers.spec.ts +220 -0
  478. package/src/integration-profile/testers/oauth.testers.ts +305 -0
  479. package/src/integration-profile/testers/payment.testers.ts +185 -0
  480. package/src/integration-profile/testers/remaining.testers.spec.ts +401 -0
  481. package/src/integration-profile/testers/storage.testers.spec.ts +185 -0
  482. package/src/integration-profile/testers/storage.testers.ts +226 -0
  483. package/src/integration-profile/testers/tester-coverage.spec.ts +58 -0
  484. package/src/language/en.json +4 -2
  485. package/src/language/pt.json +4 -2
  486. package/src/leaked-password/README.md +83 -0
  487. package/src/leaked-password/leaked-password.controller.ts +52 -0
  488. package/src/leaked-password/leaked-password.module.ts +18 -0
  489. package/src/leaked-password/leaked-password.service.ts +242 -0
  490. package/src/leaked-password/seed/build-seed-sql.mjs +180 -0
  491. package/src/leaked-password/seed/common-passwords.txt +335 -0
  492. package/src/mail/dto/preview.dto.ts +50 -0
  493. package/src/mail/dto/send.dto.ts +14 -1
  494. package/src/mail/mail-template.spec.ts +197 -0
  495. package/src/mail/mail.controller.ts +9 -2
  496. package/src/mail/mail.service.spec.ts +116 -1
  497. package/src/mail/mail.service.ts +118 -12
  498. package/src/mail-layout/dto/update.dto.ts +19 -0
  499. package/src/mail-layout/mail-layout.controller.ts +47 -0
  500. package/src/mail-layout/mail-layout.module.ts +22 -0
  501. package/src/mail-layout/mail-layout.service.ts +94 -0
  502. package/src/mcp-chat/mcp-chat.service.spec.ts +236 -0
  503. package/src/mcp-chat/mcp-chat.service.ts +122 -26
  504. package/src/oauth/oauth-token-broker.service.spec.ts +172 -0
  505. package/src/oauth/oauth-token-broker.service.ts +363 -0
  506. package/src/oauth/oauth.module.ts +3 -1
  507. package/src/oauth/oauth.service.ts +8 -2
  508. package/src/pdf/pdf.service.ts +75 -0
  509. package/src/presence/presence.controller.ts +29 -0
  510. package/src/presence/presence.listener.ts +53 -0
  511. package/src/presence/presence.module.ts +19 -0
  512. package/src/presence/presence.service.spec.ts +97 -0
  513. package/src/presence/presence.service.ts +160 -0
  514. package/src/profile/dto/delete-account.dto.ts +11 -0
  515. package/src/profile/events/profile-account-deleted.event.ts +13 -0
  516. package/src/profile/profile.controller.ts +46 -34
  517. package/src/profile/profile.service.ts +138 -38
  518. package/src/realtime/realtime.gateway.ts +138 -0
  519. package/src/realtime/realtime.module.ts +16 -0
  520. package/src/realtime/realtime.service.spec.ts +50 -0
  521. package/src/realtime/realtime.service.ts +187 -0
  522. package/src/redis/redis-pubsub.ts +179 -0
  523. package/src/setting/dto/create.dto.ts +13 -2
  524. package/src/setting/setting.service.spec.ts +56 -0
  525. package/src/setting/setting.service.ts +29 -1
  526. package/src/user/dto/create-with-email-and-password.dto.ts +6 -1
  527. package/src/user/dto/query-user-mail-list.dto.ts +10 -0
  528. package/src/user/user-credential.util.ts +35 -0
  529. package/src/user/user.controller.ts +17 -2
  530. package/src/user/user.service.spec.ts +153 -0
  531. package/src/user/user.service.ts +255 -12
  532. package/src/validators/is-strong-password-with-settings.validator.ts +12 -0
  533. package/src/validators/service-locator.ts +15 -0
  534. package/src/whatsapp-sender/whatsapp-sender.module.ts +10 -0
  535. package/src/whatsapp-sender/whatsapp-sender.service.ts +313 -0
@@ -13,16 +13,57 @@ import axios from 'axios';
13
13
  import { createHash } from 'crypto';
14
14
  import pdfParse from 'pdf-parse';
15
15
  import { AiExecutionService } from '../ai-instruction/ai-execution.service';
16
+ import {
17
+ AiPromptResolverService,
18
+ applyGeminiModelParams,
19
+ applyOpenAiModelParams,
20
+ mergeModelParams,
21
+ type PromptSource,
22
+ } from '../ai-instruction/ai-prompt-resolver.service';
23
+ import type { TemplateVars } from '../ai-instruction/ai-prompt-template.util';
16
24
  import { DeleteDTO } from '../dto/delete.dto';
17
25
  import { FileService } from '../file/file.service';
18
- import { buildAiConfigFromIntegration } from '../integration-profile/integration-profile.utils';
26
+ import {
27
+ buildAiConfigFromIntegration,
28
+ DEEPSEEK_API_BASE_URL,
29
+ DEEPSEEK_DEFAULT_MODEL,
30
+ } from '../integration-profile/integration-profile.utils';
19
31
  import { SettingService } from '../setting/setting.service';
32
+ import {
33
+ attachedFileBlock,
34
+ binaryAttachmentMarker,
35
+ unreadablePdfMarker,
36
+ } from './ai-attachment.fragments';
37
+ import { CORE_AI_PROMPT_SLUGS } from './ai.prompts';
20
38
  import { ChatAgentDTO } from './dto/chat-agent.dto';
21
39
  import { ChatDTO } from './dto/chat.dto';
22
40
  import { CreateAgentDTO } from './dto/create-agent.dto';
23
41
  import { UpdateAgentDTO } from './dto/update-agent.dto';
24
42
 
25
- type AiProvider = 'openai' | 'gemini';
43
+ type AiProvider = 'openai' | 'gemini' | 'deepseek';
44
+
45
+ /** Fallback call timeout when the active AI integration profile doesn't set `timeout_ms`. */
46
+ const DEFAULT_AI_CALL_TIMEOUT_MS = 120_000;
47
+
48
+ /** Setting (Settings → AI) que guarda o perfil de integração de cada provider. */
49
+ const AI_PROFILE_SETTING: Record<AiProvider, string> = {
50
+ openai: 'ai-openai-profile-id',
51
+ gemini: 'ai-gemini-profile-id',
52
+ deepseek: 'ai-deepseek-profile-id',
53
+ };
54
+
55
+ /**
56
+ * Optional per-call model tuning.
57
+ *
58
+ * These are only sent to the provider when a value is present: the request
59
+ * bodies must stay byte-identical to what they were before this existed, since
60
+ * some newer models reject `temperature` / `max_tokens` outright.
61
+ */
62
+ export type AiChatModelParams = {
63
+ temperature?: number | null;
64
+ maxTokens?: number | null;
65
+ responseFormat?: 'text' | 'json_object';
66
+ };
26
67
 
27
68
  type AiAgentRecord = {
28
69
  id: number;
@@ -54,68 +95,141 @@ export class AiService implements OnModuleInit {
54
95
  private readonly fileService: FileService,
55
96
  @Inject(forwardRef(() => AiExecutionService))
56
97
  private readonly aiExecution: AiExecutionService,
98
+ @Inject(forwardRef(() => AiPromptResolverService))
99
+ private readonly promptResolver: AiPromptResolverService,
57
100
  ) {}
58
101
 
59
102
  async onModuleInit() {
60
103
  try {
61
- const s = await this.settingService.getSettingValues([
62
- 'ai-openai-profile-id',
63
- 'ai-gemini-profile-id',
64
- ]);
65
- if (
66
- !String(s['ai-openai-profile-id'] ?? '').trim() &&
67
- !String(s['ai-gemini-profile-id'] ?? '').trim()
68
- ) {
104
+ const slugs = Object.values(AI_PROFILE_SETTING);
105
+ const s = await this.settingService.getSettingValues(slugs);
106
+ if (slugs.every((slug) => !String(s[slug] ?? '').trim())) {
69
107
  this.logger.warn('No AI profiles configured. Set profiles in Settings → AI.');
70
108
  }
71
109
  } catch { /* settings not available yet */ }
72
110
  }
73
111
 
74
112
  async chat(data: ChatDTO, file?: MulterFile) {
75
- const provider = data.provider || 'openai';
113
+ const provider = data.provider || (await this.getDefaultProvider());
76
114
  const attachment = await this.resolveAttachment(file, data.file_id);
115
+ const aiProfile = await this.getAiProfile(provider);
116
+ const model = data.model || aiProfile.model || this.getDefaultModel(provider);
117
+ const timeoutMs = aiProfile.timeoutMs ?? DEFAULT_AI_CALL_TIMEOUT_MS;
118
+ const params: AiChatModelParams = {
119
+ temperature: data.temperature,
120
+ maxTokens: data.max_tokens,
121
+ responseFormat: data.response_format,
122
+ };
77
123
 
78
124
  const executionId = await this.aiExecution.start({ trigger: 'api', contextSlug: 'ai-chat' });
79
125
  const stepStart = Date.now();
80
126
 
81
127
  try {
82
- if (provider === 'openai') {
83
- const model = data.model || 'gpt-4o-mini';
84
- const { content, usage } = await this.chatWithOpenAi({
128
+ const { content, usage } = await this.withTimeout(
129
+ this.chatWithProvider(provider, {
85
130
  message: data.message,
86
131
  model,
87
132
  systemPrompt: data.systemPrompt,
88
133
  attachment,
89
- });
90
-
91
- await this.aiExecution.recordStep({
92
- executionId,
93
- stepOrder: 0,
94
- type: 'output',
95
- provider: 'openai',
96
- model,
97
- durationMs: Date.now() - stepStart,
98
- usage,
99
- outputSummary: content.slice(0, 200),
100
- });
101
- await this.aiExecution.finish(executionId, 'completed');
102
-
103
- return { provider, model, content };
104
- }
134
+ apiKey: aiProfile.apiKey,
135
+ baseUrl: aiProfile.baseUrl,
136
+ params,
137
+ }),
138
+ timeoutMs,
139
+ );
105
140
 
106
- const model = data.model || 'gemini-1.5-flash';
107
- const { content, usage } = await this.chatWithGemini({
108
- message: data.message,
141
+ await this.aiExecution.recordStep({
142
+ executionId,
143
+ stepOrder: 0,
144
+ type: 'output',
145
+ provider,
109
146
  model,
110
- systemPrompt: data.systemPrompt,
111
- attachment,
147
+ durationMs: Date.now() - stepStart,
148
+ usage,
149
+ outputSummary: content.slice(0, 200),
112
150
  });
151
+ await this.aiExecution.finish(executionId, 'completed');
152
+
153
+ return { provider, model, content };
154
+ } catch (err) {
155
+ await this.aiExecution.finish(executionId, 'failed', String(err));
156
+ throw err;
157
+ }
158
+ }
159
+
160
+ /**
161
+ * Chat driven by prompts stored in `ai_instruction`.
162
+ *
163
+ * Resolves the system and user prompts by slug in one query, applies whatever
164
+ * model params the records declare (falling back to `params` and then to the
165
+ * provider defaults), and reports back where each prompt came from so callers
166
+ * can log a fallback.
167
+ */
168
+ async chatWithPrompt(input: {
169
+ systemPromptSlug?: string;
170
+ userPromptSlug: string;
171
+ variables?: TemplateVars;
172
+ provider?: AiProvider;
173
+ params?: AiChatModelParams;
174
+ contextSlug?: string;
175
+ }): Promise<{
176
+ provider: AiProvider;
177
+ model: string;
178
+ content: string;
179
+ promptSources: Record<string, PromptSource>;
180
+ }> {
181
+ const slugs = input.systemPromptSlug
182
+ ? [input.systemPromptSlug, input.userPromptSlug]
183
+ : [input.userPromptSlug];
184
+
185
+ const resolved = await this.promptResolver.resolveMany(
186
+ slugs.map((slug) => ({ slug, variables: input.variables })),
187
+ );
188
+
189
+ const systemPrompt = input.systemPromptSlug
190
+ ? resolved[input.systemPromptSlug]
191
+ : undefined;
192
+ const userPrompt = resolved[input.userPromptSlug];
193
+
194
+ // The system prompt represents the call, so its params win over the user one.
195
+ const stored = mergeModelParams(systemPrompt, userPrompt);
196
+
197
+ const provider = input.provider || (await this.getDefaultProvider());
198
+ const aiProfile = await this.getAiProfile(provider);
199
+ const model =
200
+ stored.model || aiProfile.model || this.getDefaultModel(provider);
201
+ const timeoutMs = aiProfile.timeoutMs ?? DEFAULT_AI_CALL_TIMEOUT_MS;
202
+
203
+ const params: AiChatModelParams = {
204
+ temperature: stored.temperature ?? input.params?.temperature,
205
+ maxTokens: stored.maxTokens ?? input.params?.maxTokens,
206
+ responseFormat: input.params?.responseFormat,
207
+ };
208
+
209
+ const executionId = await this.aiExecution.start({
210
+ trigger: 'api',
211
+ contextSlug: input.contextSlug || input.userPromptSlug,
212
+ });
213
+ const stepStart = Date.now();
214
+
215
+ try {
216
+ const { content, usage } = await this.withTimeout(
217
+ this.chatWithProvider(provider, {
218
+ message: userPrompt.content,
219
+ model,
220
+ systemPrompt: systemPrompt?.content || undefined,
221
+ apiKey: aiProfile.apiKey,
222
+ baseUrl: aiProfile.baseUrl,
223
+ params,
224
+ }),
225
+ timeoutMs,
226
+ );
113
227
 
114
228
  await this.aiExecution.recordStep({
115
229
  executionId,
116
230
  stepOrder: 0,
117
231
  type: 'output',
118
- provider: 'gemini',
232
+ provider,
119
233
  model,
120
234
  durationMs: Date.now() - stepStart,
121
235
  usage,
@@ -123,7 +237,11 @@ export class AiService implements OnModuleInit {
123
237
  });
124
238
  await this.aiExecution.finish(executionId, 'completed');
125
239
 
126
- return { provider, model, content };
240
+ const promptSources = Object.fromEntries(
241
+ Object.entries(resolved).map(([slug, prompt]) => [slug, prompt.source]),
242
+ );
243
+
244
+ return { provider, model, content, promptSources };
127
245
  } catch (err) {
128
246
  await this.aiExecution.finish(executionId, 'failed', String(err));
129
247
  throw err;
@@ -155,7 +273,7 @@ export class AiService implements OnModuleInit {
155
273
  INSERT INTO ai_agent (slug, provider, model, instructions, external_agent_id)
156
274
  VALUES (
157
275
  ${slug},
158
- CAST(${provider} AS ai_agent_provider_enum),
276
+ CAST(${provider} AS ai_agent_provider_7cb93b1143_enum),
159
277
  ${model},
160
278
  ${instructions},
161
279
  ${externalAgentId}
@@ -165,6 +283,39 @@ export class AiService implements OnModuleInit {
165
283
  return this.findAgentBySlug(slug);
166
284
  }
167
285
 
286
+ /**
287
+ * Creates the agent, or updates it when its stored instructions/model drifted
288
+ * from what the caller now wants.
289
+ *
290
+ * `createAgent` returns the existing row untouched, so a caller that passes
291
+ * instructions on every request would keep whatever the very first call
292
+ * persisted. That silently defeats an editable prompt: the admin would save a
293
+ * change and the agent would go on using the original text.
294
+ */
295
+ async upsertAgent(data: CreateAgentDTO) {
296
+ const existing = await this.findAgentBySlug(data.slug.trim());
297
+
298
+ if (!existing) {
299
+ return this.createAgent(data);
300
+ }
301
+
302
+ const instructions = data.instructions?.trim() || null;
303
+ const model = data.model || existing.model;
304
+
305
+ const unchanged =
306
+ (instructions === null || instructions === existing.instructions) &&
307
+ model === existing.model;
308
+
309
+ if (unchanged) {
310
+ return existing;
311
+ }
312
+
313
+ return this.updateAgent(existing.id, {
314
+ instructions: instructions ?? undefined,
315
+ model: model ?? undefined,
316
+ });
317
+ }
318
+
168
319
  async listAgents(paginationParams: PaginationDTO) {
169
320
  const page = Math.max(Number(paginationParams?.page || 1), 1);
170
321
  const pageSize = Math.min(
@@ -248,7 +399,7 @@ export class AiService implements OnModuleInit {
248
399
  await this.prismaService.$executeRaw`
249
400
  UPDATE ai_agent
250
401
  SET slug = ${slug},
251
- provider = CAST(${provider} AS ai_agent_provider_enum),
402
+ provider = CAST(${provider} AS ai_agent_provider_7cb93b1143_enum),
252
403
  model = ${model},
253
404
  instructions = ${instructions},
254
405
  external_agent_id = ${externalAgentId},
@@ -292,27 +443,11 @@ export class AiService implements OnModuleInit {
292
443
  throw new NotFoundException(`AI agent with slug "${slug}" was not found.`);
293
444
  }
294
445
 
295
- if (agent.provider === 'openai') {
296
- if (agent.external_agent_id && !attachment) {
297
- const content = await this.chatWithOpenAiAssistant(
298
- agent.external_agent_id,
299
- data.message,
300
- );
301
-
302
- return {
303
- slug: agent.slug,
304
- provider: agent.provider,
305
- model: agent.model,
306
- content,
307
- };
308
- }
309
-
310
- const { content } = await this.chatWithOpenAi({
311
- message: data.message,
312
- model: agent.model || this.getDefaultModel('openai'),
313
- systemPrompt: agent.instructions || undefined,
314
- attachment,
315
- });
446
+ if (agent.provider === 'openai' && agent.external_agent_id && !attachment) {
447
+ const content = await this.chatWithOpenAiAssistant(
448
+ agent.external_agent_id,
449
+ data.message,
450
+ );
316
451
 
317
452
  return {
318
453
  slug: agent.slug,
@@ -322,11 +457,15 @@ export class AiService implements OnModuleInit {
322
457
  };
323
458
  }
324
459
 
325
- const { content } = await this.chatWithGemini({
460
+ const aiProfile = await this.getAiProfile(agent.provider);
461
+
462
+ const { content } = await this.chatWithProvider(agent.provider, {
326
463
  message: data.message,
327
- model: agent.model || this.getDefaultModel('gemini'),
464
+ model: agent.model || this.getDefaultModel(agent.provider),
328
465
  systemPrompt: agent.instructions || undefined,
329
466
  attachment,
467
+ apiKey: aiProfile.apiKey,
468
+ baseUrl: aiProfile.baseUrl,
330
469
  });
331
470
 
332
471
  return {
@@ -435,15 +574,74 @@ export class AiService implements OnModuleInit {
435
574
  }
436
575
 
437
576
  private getDefaultModel(provider: AiProvider): string {
438
- if (provider === 'openai') {
439
- return 'gpt-4o-mini';
577
+ if (provider === 'gemini') {
578
+ return 'gemini-1.5-flash';
579
+ }
580
+
581
+ if (provider === 'deepseek') {
582
+ return DEEPSEEK_DEFAULT_MODEL;
583
+ }
584
+
585
+ return 'gpt-4o-mini';
586
+ }
587
+
588
+ /** Default AI provider used when a caller doesn't specify one (Settings → AI). */
589
+ private async getDefaultProvider(): Promise<AiProvider> {
590
+ const settings = await this.settingService.getSettingValues(['ai-default-provider']);
591
+ const value = String(settings['ai-default-provider'] ?? '').trim();
592
+ return value in AI_PROFILE_SETTING ? (value as AiProvider) : 'openai';
593
+ }
594
+
595
+ /**
596
+ * Envia o chat ao provider certo.
597
+ *
598
+ * O DeepSeek expõe a mesma API de `/chat/completions` da OpenAI, então reusa o
599
+ * caminho da OpenAI trocando a base URL — só não aceita imagens, porque os
600
+ * modelos `deepseek-chat`/`deepseek-reasoner` não têm visão.
601
+ */
602
+ private chatWithProvider(
603
+ provider: AiProvider,
604
+ input: {
605
+ message: string;
606
+ model: string;
607
+ systemPrompt?: string;
608
+ attachment?: AiAttachment | null;
609
+ apiKey?: string;
610
+ baseUrl?: string;
611
+ params?: AiChatModelParams;
612
+ },
613
+ ) {
614
+ if (provider === 'gemini') {
615
+ return this.chatWithGemini(input);
440
616
  }
441
617
 
442
- return 'gemini-1.5-flash';
618
+ if (provider === 'deepseek') {
619
+ return this.chatWithOpenAi({
620
+ ...input,
621
+ provider,
622
+ baseUrl: input.baseUrl || DEEPSEEK_API_BASE_URL,
623
+ supportsImages: false,
624
+ });
625
+ }
626
+
627
+ return this.chatWithOpenAi(input);
443
628
  }
444
629
 
445
630
  private async getAiApiKey(provider: AiProvider): Promise<string> {
446
- const slug = provider === 'openai' ? 'ai-openai-profile-id' : 'ai-gemini-profile-id';
631
+ return (await this.getAiProfile(provider)).apiKey;
632
+ }
633
+
634
+ /** Resolves the active AI integration profile's credentials plus its optional model/timeout overrides. */
635
+ private async getAiProfile(
636
+ provider: AiProvider,
637
+ ): Promise<{
638
+ apiKey: string;
639
+ organization?: string;
640
+ model?: string;
641
+ timeoutMs?: number;
642
+ baseUrl?: string;
643
+ }> {
644
+ const slug = AI_PROFILE_SETTING[provider] ?? AI_PROFILE_SETTING.openai;
447
645
  const settings = await this.settingService.getSettingValues([slug]);
448
646
  const profileSlug = String(settings[slug] ?? '').trim();
449
647
 
@@ -462,16 +660,33 @@ export class AiService implements OnModuleInit {
462
660
  throw new BadRequestException(`AI profile "${profileSlug}" not found.`);
463
661
  }
464
662
 
465
- const { apiKey } = buildAiConfigFromIntegration(
663
+ const aiConfig = buildAiConfigFromIntegration(
466
664
  profile.integration_provider.slug,
467
665
  profile.config,
468
666
  );
469
667
 
470
- if (!apiKey) {
668
+ if (!aiConfig.apiKey) {
471
669
  throw new BadRequestException(`AI profile "${profileSlug}" has no API key configured.`);
472
670
  }
473
671
 
474
- return apiKey;
672
+ return aiConfig;
673
+ }
674
+
675
+ /** Rejects with a timeout error if `promise` doesn't settle within `ms`. */
676
+ private withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
677
+ return new Promise<T>((resolve, reject) => {
678
+ const timer = setTimeout(() => reject(new Error(`AI call timed out after ${ms}ms`)), ms);
679
+ promise.then(
680
+ (value) => {
681
+ clearTimeout(timer);
682
+ resolve(value);
683
+ },
684
+ (error) => {
685
+ clearTimeout(timer);
686
+ reject(error);
687
+ },
688
+ );
689
+ });
475
690
  }
476
691
 
477
692
  private async chatWithOpenAi({
@@ -479,13 +694,24 @@ export class AiService implements OnModuleInit {
479
694
  model,
480
695
  systemPrompt,
481
696
  attachment,
697
+ apiKey,
698
+ params,
699
+ provider = 'openai',
700
+ baseUrl = 'https://api.openai.com/v1',
701
+ supportsImages = true,
482
702
  }: {
483
703
  message: string;
484
704
  model: string;
485
705
  systemPrompt?: string;
486
706
  attachment?: AiAttachment | null;
707
+ apiKey?: string;
708
+ params?: AiChatModelParams;
709
+ /** Provider dono da chave — o DeepSeek usa este mesmo formato de requisição. */
710
+ provider?: AiProvider;
711
+ baseUrl?: string;
712
+ supportsImages?: boolean;
487
713
  }): Promise<{ content: string; usage?: { input: number; output: number; total: number } }> {
488
- const openai = await this.getAiApiKey('openai');
714
+ const openai = apiKey ?? (await this.getAiApiKey(provider));
489
715
 
490
716
  const messages: Array<any> = [];
491
717
 
@@ -493,12 +719,22 @@ export class AiService implements OnModuleInit {
493
719
  messages.push({ role: 'system', content: systemPrompt });
494
720
  }
495
721
 
496
- const userContent = await this.buildOpenAiUserContent(message, attachment);
722
+ const userContent = await this.buildOpenAiUserContent(
723
+ message,
724
+ attachment,
725
+ supportsImages,
726
+ );
497
727
  messages.push({ role: 'user', content: userContent });
498
728
 
729
+ const body = applyOpenAiModelParams(
730
+ { messages },
731
+ { model: null, temperature: params?.temperature ?? null, maxTokens: params?.maxTokens ?? null },
732
+ { model, jsonObject: params?.responseFormat === 'json_object' },
733
+ );
734
+
499
735
  const response = await axios.post(
500
- 'https://api.openai.com/v1/chat/completions',
501
- { model, messages },
736
+ `${baseUrl.replace(/\/+$/, '')}/chat/completions`,
737
+ body,
502
738
  {
503
739
  headers: {
504
740
  Authorization: `Bearer ${openai}`,
@@ -525,12 +761,17 @@ export class AiService implements OnModuleInit {
525
761
  }): Promise<string> {
526
762
  const openai = await this.getAiApiKey('openai');
527
763
 
764
+ const defaultInstructions = await this.promptResolver.resolve({
765
+ slug: CORE_AI_PROMPT_SLUGS.agentDefaultInstructions,
766
+ variables: { slug },
767
+ });
768
+
528
769
  const response = await axios.post(
529
770
  'https://api.openai.com/v1/assistants',
530
771
  {
531
772
  name: slug,
532
773
  model,
533
- instructions: instructions || `You are the assistant identified by slug ${slug}.`,
774
+ instructions: instructions || defaultInstructions.content,
534
775
  },
535
776
  {
536
777
  headers: {
@@ -646,13 +887,17 @@ export class AiService implements OnModuleInit {
646
887
  model,
647
888
  systemPrompt,
648
889
  attachment,
890
+ apiKey,
891
+ params,
649
892
  }: {
650
893
  message: string;
651
894
  model: string;
652
895
  systemPrompt?: string;
653
896
  attachment?: AiAttachment | null;
897
+ apiKey?: string;
898
+ params?: AiChatModelParams;
654
899
  }): Promise<{ content: string; usage?: { input: number; output: number; total: number } }> {
655
- const gemini = await this.getAiApiKey('gemini');
900
+ const gemini = apiKey ?? (await this.getAiApiKey('gemini'));
656
901
 
657
902
  const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${gemini}`;
658
903
 
@@ -661,13 +906,13 @@ export class AiService implements OnModuleInit {
661
906
  if (attachment) {
662
907
  if (this.isTextMime(attachment.mimeType)) {
663
908
  userParts.push({
664
- text: `\n\n[Attached file: ${attachment.filename}]\n${this.toUtf8Text(attachment.buffer)}`,
909
+ text: attachedFileBlock(attachment.filename, this.toUtf8Text(attachment.buffer)),
665
910
  });
666
911
  } else if (this.isPdfMime(attachment.mimeType)) {
667
912
  const pdfText = await this.extractPdfText(attachment.buffer);
668
913
  if (pdfText) {
669
914
  userParts.push({
670
- text: `\n\n[Attached file: ${attachment.filename}]\n${pdfText}`,
915
+ text: attachedFileBlock(attachment.filename, pdfText),
671
916
  });
672
917
  } else {
673
918
  userParts.push({
@@ -687,7 +932,7 @@ export class AiService implements OnModuleInit {
687
932
  }
688
933
  }
689
934
 
690
- const payload: any = {
935
+ let payload: any = {
691
936
  contents: [{ parts: userParts }],
692
937
  };
693
938
 
@@ -697,6 +942,12 @@ export class AiService implements OnModuleInit {
697
942
  };
698
943
  }
699
944
 
945
+ payload = applyGeminiModelParams(
946
+ payload,
947
+ { model: null, temperature: params?.temperature ?? null, maxTokens: params?.maxTokens ?? null },
948
+ { jsonObject: params?.responseFormat === 'json_object' },
949
+ );
950
+
700
951
  const response = await axios.post(url, payload, {
701
952
  headers: {
702
953
  'Content-Type': 'application/json',
@@ -751,12 +1002,13 @@ export class AiService implements OnModuleInit {
751
1002
  private async buildOpenAiUserContent(
752
1003
  message: string,
753
1004
  attachment?: AiAttachment | null,
1005
+ supportsImages = true,
754
1006
  ) {
755
1007
  if (!attachment) {
756
1008
  return message;
757
1009
  }
758
1010
 
759
- if (this.isImageMime(attachment.mimeType)) {
1011
+ if (supportsImages && this.isImageMime(attachment.mimeType)) {
760
1012
  const dataUri = `data:${attachment.mimeType};base64,${attachment.buffer.toString('base64')}`;
761
1013
  return [
762
1014
  { type: 'text', text: message },
@@ -771,12 +1023,16 @@ export class AiService implements OnModuleInit {
771
1023
  } else if (this.isPdfMime(attachment.mimeType)) {
772
1024
  text =
773
1025
  (await this.extractPdfText(attachment.buffer)) ||
774
- `[PDF attachment with unreadable text: ${attachment.filename}]`;
1026
+ unreadablePdfMarker(attachment.filename);
775
1027
  } else {
776
- text = `[Binary attachment: ${attachment.filename} | ${attachment.mimeType} | ${attachment.buffer.length} bytes]`;
1028
+ text = binaryAttachmentMarker(
1029
+ attachment.filename,
1030
+ attachment.mimeType,
1031
+ attachment.buffer.length,
1032
+ );
777
1033
  }
778
1034
 
779
- return `${message}\n\n[Attached file: ${attachment.filename}]\n${text}`;
1035
+ return `${message}${attachedFileBlock(attachment.filename, text)}`;
780
1036
  }
781
1037
 
782
1038
  private isImageMime(mimeType: string) {
@@ -1,5 +1,14 @@
1
1
  import { Type } from 'class-transformer';
2
- import { IsIn, IsInt, IsNotEmpty, IsOptional, IsString } from 'class-validator';
2
+ import {
3
+ IsIn,
4
+ IsInt,
5
+ IsNotEmpty,
6
+ IsNumber,
7
+ IsOptional,
8
+ IsString,
9
+ Max,
10
+ Min,
11
+ } from 'class-validator';
3
12
 
4
13
  export class ChatDTO {
5
14
  @IsString()
@@ -8,8 +17,8 @@ export class ChatDTO {
8
17
 
9
18
  @IsOptional()
10
19
  @IsString()
11
- @IsIn(['openai', 'gemini'])
12
- provider?: 'openai' | 'gemini';
20
+ @IsIn(['openai', 'gemini', 'deepseek'])
21
+ provider?: 'openai' | 'gemini' | 'deepseek';
13
22
 
14
23
  @IsOptional()
15
24
  @IsString()
@@ -23,4 +32,25 @@ export class ChatDTO {
23
32
  @Type(() => Number)
24
33
  @IsInt()
25
34
  file_id?: number;
35
+
36
+ // Omitted parameters are not sent to the provider at all — some newer models
37
+ // reject temperature/max_tokens.
38
+ @IsOptional()
39
+ @Type(() => Number)
40
+ @IsNumber()
41
+ @Min(0)
42
+ @Max(2)
43
+ temperature?: number;
44
+
45
+ @IsOptional()
46
+ @Type(() => Number)
47
+ @IsInt()
48
+ @Min(1)
49
+ @Max(200000)
50
+ max_tokens?: number;
51
+
52
+ @IsOptional()
53
+ @IsString()
54
+ @IsIn(['text', 'json_object'])
55
+ response_format?: 'text' | 'json_object';
26
56
  }
@@ -7,8 +7,8 @@ export class CreateAgentDTO {
7
7
 
8
8
  @IsOptional()
9
9
  @IsString()
10
- @IsIn(['openai', 'gemini'])
11
- provider?: 'openai' | 'gemini';
10
+ @IsIn(['openai', 'gemini', 'deepseek'])
11
+ provider?: 'openai' | 'gemini' | 'deepseek';
12
12
 
13
13
  @IsOptional()
14
14
  @IsString()