@lenne.tech/nest-server 11.25.6 → 11.26.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 (335) hide show
  1. package/.claude/rules/configurable-features.md +2 -0
  2. package/CLAUDE.md +18 -0
  3. package/FRAMEWORK-API.md +48 -1
  4. package/dist/config.env.js +35 -1
  5. package/dist/config.env.js.map +1 -1
  6. package/dist/core/common/helpers/config.helper.js +2 -2
  7. package/dist/core/common/helpers/config.helper.js.map +1 -1
  8. package/dist/core/common/interceptors/check-security.interceptor.js +9 -2
  9. package/dist/core/common/interceptors/check-security.interceptor.js.map +1 -1
  10. package/dist/core/common/interfaces/server-options.interface.d.ts +89 -0
  11. package/dist/core/modules/ai/core-ai-mcp.controller.d.ts +21 -0
  12. package/dist/core/modules/ai/core-ai-mcp.controller.js +191 -0
  13. package/dist/core/modules/ai/core-ai-mcp.controller.js.map +1 -0
  14. package/dist/core/modules/ai/core-ai.controller.d.ts +90 -0
  15. package/dist/core/modules/ai/core-ai.controller.js +576 -0
  16. package/dist/core/modules/ai/core-ai.controller.js.map +1 -0
  17. package/dist/core/modules/ai/core-ai.module.d.ts +43 -0
  18. package/dist/core/modules/ai/core-ai.module.js +164 -0
  19. package/dist/core/modules/ai/core-ai.module.js.map +1 -0
  20. package/dist/core/modules/ai/core-ai.resolver.d.ts +84 -0
  21. package/dist/core/modules/ai/core-ai.resolver.js +530 -0
  22. package/dist/core/modules/ai/core-ai.resolver.js.map +1 -0
  23. package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.d.ts +7 -0
  24. package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.js +16 -0
  25. package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.js.map +1 -0
  26. package/dist/core/modules/ai/hooks/ai-hook.base.d.ts +10 -0
  27. package/dist/core/modules/ai/hooks/ai-hook.base.js +30 -0
  28. package/dist/core/modules/ai/hooks/ai-hook.base.js.map +1 -0
  29. package/dist/core/modules/ai/hooks/ai-hook.registry.d.ts +22 -0
  30. package/dist/core/modules/ai/hooks/ai-hook.registry.js +98 -0
  31. package/dist/core/modules/ai/hooks/ai-hook.registry.js.map +1 -0
  32. package/dist/core/modules/ai/index.d.ts +69 -0
  33. package/dist/core/modules/ai/index.js +86 -0
  34. package/dist/core/modules/ai/index.js.map +1 -0
  35. package/dist/core/modules/ai/inputs/core-ai-budget-limit-create.input.d.ts +5 -0
  36. package/dist/core/modules/ai/inputs/core-ai-budget-limit-create.input.js +43 -0
  37. package/dist/core/modules/ai/inputs/core-ai-budget-limit-create.input.js.map +1 -0
  38. package/dist/core/modules/ai/inputs/core-ai-budget-limit.input.d.ts +7 -0
  39. package/dist/core/modules/ai/inputs/core-ai-budget-limit.input.js +74 -0
  40. package/dist/core/modules/ai/inputs/core-ai-budget-limit.input.js.map +1 -0
  41. package/dist/core/modules/ai/inputs/core-ai-connection-create.input.d.ts +6 -0
  42. package/dist/core/modules/ai/inputs/core-ai-connection-create.input.js +49 -0
  43. package/dist/core/modules/ai/inputs/core-ai-connection-create.input.js.map +1 -0
  44. package/dist/core/modules/ai/inputs/core-ai-connection-preference.input.d.ts +6 -0
  45. package/dist/core/modules/ai/inputs/core-ai-connection-preference.input.js +60 -0
  46. package/dist/core/modules/ai/inputs/core-ai-connection-preference.input.js.map +1 -0
  47. package/dist/core/modules/ai/inputs/core-ai-connection.input.d.ts +23 -0
  48. package/dist/core/modules/ai/inputs/core-ai-connection.input.js +229 -0
  49. package/dist/core/modules/ai/inputs/core-ai-connection.input.js.map +1 -0
  50. package/dist/core/modules/ai/inputs/core-ai-conversation-create.input.d.ts +3 -0
  51. package/dist/core/modules/ai/inputs/core-ai-conversation-create.input.js +21 -0
  52. package/dist/core/modules/ai/inputs/core-ai-conversation-create.input.js.map +1 -0
  53. package/dist/core/modules/ai/inputs/core-ai-conversation.input.d.ts +4 -0
  54. package/dist/core/modules/ai/inputs/core-ai-conversation.input.js +42 -0
  55. package/dist/core/modules/ai/inputs/core-ai-conversation.input.js.map +1 -0
  56. package/dist/core/modules/ai/inputs/core-ai-prompt-create.input.d.ts +10 -0
  57. package/dist/core/modules/ai/inputs/core-ai-prompt-create.input.js +74 -0
  58. package/dist/core/modules/ai/inputs/core-ai-prompt-create.input.js.map +1 -0
  59. package/dist/core/modules/ai/inputs/core-ai-prompt-hint-create.input.d.ts +5 -0
  60. package/dist/core/modules/ai/inputs/core-ai-prompt-hint-create.input.js +41 -0
  61. package/dist/core/modules/ai/inputs/core-ai-prompt-hint-create.input.js.map +1 -0
  62. package/dist/core/modules/ai/inputs/core-ai-prompt-hint.input.d.ts +6 -0
  63. package/dist/core/modules/ai/inputs/core-ai-prompt-hint.input.js +63 -0
  64. package/dist/core/modules/ai/inputs/core-ai-prompt-hint.input.js.map +1 -0
  65. package/dist/core/modules/ai/inputs/core-ai-prompt-update.input.d.ts +10 -0
  66. package/dist/core/modules/ai/inputs/core-ai-prompt-update.input.js +70 -0
  67. package/dist/core/modules/ai/inputs/core-ai-prompt-update.input.js.map +1 -0
  68. package/dist/core/modules/ai/inputs/core-ai-prompt.input.d.ts +18 -0
  69. package/dist/core/modules/ai/inputs/core-ai-prompt.input.js +131 -0
  70. package/dist/core/modules/ai/inputs/core-ai-prompt.input.js.map +1 -0
  71. package/dist/core/modules/ai/inputs/core-ai-slot-create.input.d.ts +5 -0
  72. package/dist/core/modules/ai/inputs/core-ai-slot-create.input.js +41 -0
  73. package/dist/core/modules/ai/inputs/core-ai-slot-create.input.js.map +1 -0
  74. package/dist/core/modules/ai/inputs/core-ai-slot-update.input.d.ts +9 -0
  75. package/dist/core/modules/ai/inputs/core-ai-slot-update.input.js +91 -0
  76. package/dist/core/modules/ai/inputs/core-ai-slot-update.input.js.map +1 -0
  77. package/dist/core/modules/ai/interfaces/ai-hook.interface.d.ts +28 -0
  78. package/dist/core/modules/ai/interfaces/ai-hook.interface.js +3 -0
  79. package/dist/core/modules/ai/interfaces/ai-hook.interface.js.map +1 -0
  80. package/dist/core/modules/ai/interfaces/ai-placeholder.interface.d.ts +21 -0
  81. package/dist/core/modules/ai/interfaces/ai-placeholder.interface.js +3 -0
  82. package/dist/core/modules/ai/interfaces/ai-placeholder.interface.js.map +1 -0
  83. package/dist/core/modules/ai/interfaces/ai-tool.interface.d.ts +30 -0
  84. package/dist/core/modules/ai/interfaces/ai-tool.interface.js +3 -0
  85. package/dist/core/modules/ai/interfaces/ai-tool.interface.js.map +1 -0
  86. package/dist/core/modules/ai/interfaces/llm-provider.interface.d.ts +55 -0
  87. package/dist/core/modules/ai/interfaces/llm-provider.interface.js +3 -0
  88. package/dist/core/modules/ai/interfaces/llm-provider.interface.js.map +1 -0
  89. package/dist/core/modules/ai/interfaces/resolved-ai-connection.interface.d.ts +16 -0
  90. package/dist/core/modules/ai/interfaces/resolved-ai-connection.interface.js +3 -0
  91. package/dist/core/modules/ai/interfaces/resolved-ai-connection.interface.js.map +1 -0
  92. package/dist/core/modules/ai/models/core-ai-action.model.d.ts +6 -0
  93. package/dist/core/modules/ai/models/core-ai-action.model.js +44 -0
  94. package/dist/core/modules/ai/models/core-ai-action.model.js.map +1 -0
  95. package/dist/core/modules/ai/models/core-ai-available-connection.model.d.ts +8 -0
  96. package/dist/core/modules/ai/models/core-ai-available-connection.model.js +53 -0
  97. package/dist/core/modules/ai/models/core-ai-available-connection.model.js.map +1 -0
  98. package/dist/core/modules/ai/models/core-ai-budget-limit.model.d.ts +97 -0
  99. package/dist/core/modules/ai/models/core-ai-budget-limit.model.js +79 -0
  100. package/dist/core/modules/ai/models/core-ai-budget-limit.model.js.map +1 -0
  101. package/dist/core/modules/ai/models/core-ai-connection-preference.model.d.ts +91 -0
  102. package/dist/core/modules/ai/models/core-ai-connection-preference.model.js +67 -0
  103. package/dist/core/modules/ai/models/core-ai-connection-preference.model.js.map +1 -0
  104. package/dist/core/modules/ai/models/core-ai-connection.model.d.ts +200 -0
  105. package/dist/core/modules/ai/models/core-ai-connection.model.js +263 -0
  106. package/dist/core/modules/ai/models/core-ai-connection.model.js.map +1 -0
  107. package/dist/core/modules/ai/models/core-ai-conversation.model.d.ts +93 -0
  108. package/dist/core/modules/ai/models/core-ai-conversation.model.js +82 -0
  109. package/dist/core/modules/ai/models/core-ai-conversation.model.js.map +1 -0
  110. package/dist/core/modules/ai/models/core-ai-interaction.model.d.ts +133 -0
  111. package/dist/core/modules/ai/models/core-ai-interaction.model.js +137 -0
  112. package/dist/core/modules/ai/models/core-ai-interaction.model.js.map +1 -0
  113. package/dist/core/modules/ai/models/core-ai-message.model.d.ts +5 -0
  114. package/dist/core/modules/ai/models/core-ai-message.model.js +38 -0
  115. package/dist/core/modules/ai/models/core-ai-message.model.js.map +1 -0
  116. package/dist/core/modules/ai/models/core-ai-mode.model.d.ts +109 -0
  117. package/dist/core/modules/ai/models/core-ai-mode.model.js +100 -0
  118. package/dist/core/modules/ai/models/core-ai-mode.model.js.map +1 -0
  119. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.d.ts +103 -0
  120. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js +89 -0
  121. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js.map +1 -0
  122. package/dist/core/modules/ai/models/core-ai-prompt.model.d.ts +122 -0
  123. package/dist/core/modules/ai/models/core-ai-prompt.model.js +117 -0
  124. package/dist/core/modules/ai/models/core-ai-prompt.model.js.map +1 -0
  125. package/dist/core/modules/ai/models/core-ai-response.model.d.ts +29 -0
  126. package/dist/core/modules/ai/models/core-ai-response.model.js +105 -0
  127. package/dist/core/modules/ai/models/core-ai-response.model.js.map +1 -0
  128. package/dist/core/modules/ai/models/core-ai-slot.model.d.ts +121 -0
  129. package/dist/core/modules/ai/models/core-ai-slot.model.js +119 -0
  130. package/dist/core/modules/ai/models/core-ai-slot.model.js.map +1 -0
  131. package/dist/core/modules/ai/models/core-ai-tool-grant.model.d.ts +103 -0
  132. package/dist/core/modules/ai/models/core-ai-tool-grant.model.js +88 -0
  133. package/dist/core/modules/ai/models/core-ai-tool-grant.model.js.map +1 -0
  134. package/dist/core/modules/ai/models/core-ai-tool-policy.model.d.ts +122 -0
  135. package/dist/core/modules/ai/models/core-ai-tool-policy.model.js +121 -0
  136. package/dist/core/modules/ai/models/core-ai-tool-policy.model.js.map +1 -0
  137. package/dist/core/modules/ai/models/core-ai-usage-info.model.d.ts +24 -0
  138. package/dist/core/modules/ai/models/core-ai-usage-info.model.js +127 -0
  139. package/dist/core/modules/ai/models/core-ai-usage-info.model.js.map +1 -0
  140. package/dist/core/modules/ai/models/core-ai-usage.model.d.ts +5 -0
  141. package/dist/core/modules/ai/models/core-ai-usage.model.js +38 -0
  142. package/dist/core/modules/ai/models/core-ai-usage.model.js.map +1 -0
  143. package/dist/core/modules/ai/providers/claude-cli.provider.d.ts +16 -0
  144. package/dist/core/modules/ai/providers/claude-cli.provider.js +151 -0
  145. package/dist/core/modules/ai/providers/claude-cli.provider.js.map +1 -0
  146. package/dist/core/modules/ai/providers/llm-provider.factory.d.ts +10 -0
  147. package/dist/core/modules/ai/providers/llm-provider.factory.js +45 -0
  148. package/dist/core/modules/ai/providers/llm-provider.factory.js.map +1 -0
  149. package/dist/core/modules/ai/providers/openai-compatible.provider.d.ts +32 -0
  150. package/dist/core/modules/ai/providers/openai-compatible.provider.js +236 -0
  151. package/dist/core/modules/ai/providers/openai-compatible.provider.js.map +1 -0
  152. package/dist/core/modules/ai/services/ai-crypto.service.d.ts +11 -0
  153. package/dist/core/modules/ai/services/ai-crypto.service.js +84 -0
  154. package/dist/core/modules/ai/services/ai-crypto.service.js.map +1 -0
  155. package/dist/core/modules/ai/services/core-ai-budget.service.d.ts +42 -0
  156. package/dist/core/modules/ai/services/core-ai-budget.service.js +211 -0
  157. package/dist/core/modules/ai/services/core-ai-budget.service.js.map +1 -0
  158. package/dist/core/modules/ai/services/core-ai-connection-preference.service.d.ts +18 -0
  159. package/dist/core/modules/ai/services/core-ai-connection-preference.service.js +53 -0
  160. package/dist/core/modules/ai/services/core-ai-connection-preference.service.js.map +1 -0
  161. package/dist/core/modules/ai/services/core-ai-connection-resolver.service.d.ts +55 -0
  162. package/dist/core/modules/ai/services/core-ai-connection-resolver.service.js +177 -0
  163. package/dist/core/modules/ai/services/core-ai-connection-resolver.service.js.map +1 -0
  164. package/dist/core/modules/ai/services/core-ai-connection.service.d.ts +43 -0
  165. package/dist/core/modules/ai/services/core-ai-connection.service.js +272 -0
  166. package/dist/core/modules/ai/services/core-ai-connection.service.js.map +1 -0
  167. package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +26 -0
  168. package/dist/core/modules/ai/services/core-ai-conversation.service.js +72 -0
  169. package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -0
  170. package/dist/core/modules/ai/services/core-ai-interaction.service.d.ts +13 -0
  171. package/dist/core/modules/ai/services/core-ai-interaction.service.js +52 -0
  172. package/dist/core/modules/ai/services/core-ai-interaction.service.js.map +1 -0
  173. package/dist/core/modules/ai/services/core-ai-mcp-client.service.d.ts +51 -0
  174. package/dist/core/modules/ai/services/core-ai-mcp-client.service.js +123 -0
  175. package/dist/core/modules/ai/services/core-ai-mcp-client.service.js.map +1 -0
  176. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.d.ts +68 -0
  177. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js +279 -0
  178. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js.map +1 -0
  179. package/dist/core/modules/ai/services/core-ai-mcp.service.d.ts +22 -0
  180. package/dist/core/modules/ai/services/core-ai-mcp.service.js +59 -0
  181. package/dist/core/modules/ai/services/core-ai-mcp.service.js.map +1 -0
  182. package/dist/core/modules/ai/services/core-ai-mode.service.d.ts +14 -0
  183. package/dist/core/modules/ai/services/core-ai-mode.service.js +56 -0
  184. package/dist/core/modules/ai/services/core-ai-mode.service.js.map +1 -0
  185. package/dist/core/modules/ai/services/core-ai-placeholder.registry.d.ts +15 -0
  186. package/dist/core/modules/ai/services/core-ai-placeholder.registry.js +102 -0
  187. package/dist/core/modules/ai/services/core-ai-placeholder.registry.js.map +1 -0
  188. package/dist/core/modules/ai/services/core-ai-prompt-builder.service.d.ts +42 -0
  189. package/dist/core/modules/ai/services/core-ai-prompt-builder.service.js +136 -0
  190. package/dist/core/modules/ai/services/core-ai-prompt-builder.service.js.map +1 -0
  191. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.d.ts +29 -0
  192. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js +98 -0
  193. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js.map +1 -0
  194. package/dist/core/modules/ai/services/core-ai-prompt.service.d.ts +21 -0
  195. package/dist/core/modules/ai/services/core-ai-prompt.service.js +143 -0
  196. package/dist/core/modules/ai/services/core-ai-prompt.service.js.map +1 -0
  197. package/dist/core/modules/ai/services/core-ai-slot.service.d.ts +51 -0
  198. package/dist/core/modules/ai/services/core-ai-slot.service.js +372 -0
  199. package/dist/core/modules/ai/services/core-ai-slot.service.js.map +1 -0
  200. package/dist/core/modules/ai/services/core-ai-tool-grant.service.d.ts +22 -0
  201. package/dist/core/modules/ai/services/core-ai-tool-grant.service.js +97 -0
  202. package/dist/core/modules/ai/services/core-ai-tool-grant.service.js.map +1 -0
  203. package/dist/core/modules/ai/services/core-ai-tool-policy.service.d.ts +23 -0
  204. package/dist/core/modules/ai/services/core-ai-tool-policy.service.js +102 -0
  205. package/dist/core/modules/ai/services/core-ai-tool-policy.service.js.map +1 -0
  206. package/dist/core/modules/ai/services/core-ai.service.d.ts +144 -0
  207. package/dist/core/modules/ai/services/core-ai.service.js +991 -0
  208. package/dist/core/modules/ai/services/core-ai.service.js.map +1 -0
  209. package/dist/core/modules/ai/tools/ai-tool.base.d.ts +15 -0
  210. package/dist/core/modules/ai/tools/ai-tool.base.js +30 -0
  211. package/dist/core/modules/ai/tools/ai-tool.base.js.map +1 -0
  212. package/dist/core/modules/ai/tools/ai-tool.registry.d.ts +19 -0
  213. package/dist/core/modules/ai/tools/ai-tool.registry.js +71 -0
  214. package/dist/core/modules/ai/tools/ai-tool.registry.js.map +1 -0
  215. package/dist/core/modules/ai/tools/ask-user-question.tool.d.ts +38 -0
  216. package/dist/core/modules/ai/tools/ask-user-question.tool.js +65 -0
  217. package/dist/core/modules/ai/tools/ask-user-question.tool.js.map +1 -0
  218. package/dist/core/modules/ai/tools/search-tools.tool.d.ts +24 -0
  219. package/dist/core/modules/ai/tools/search-tools.tool.js +68 -0
  220. package/dist/core/modules/ai/tools/search-tools.tool.js.map +1 -0
  221. package/dist/core/modules/error-code/error-codes.d.ts +81 -0
  222. package/dist/core/modules/error-code/error-codes.js +72 -0
  223. package/dist/core/modules/error-code/error-codes.js.map +1 -1
  224. package/dist/core.module.js +8 -0
  225. package/dist/core.module.js.map +1 -1
  226. package/dist/index.d.ts +1 -0
  227. package/dist/index.js +1 -0
  228. package/dist/index.js.map +1 -1
  229. package/dist/server/modules/ai/ai-tools.module.d.ts +5 -0
  230. package/dist/server/modules/ai/ai-tools.module.js +36 -0
  231. package/dist/server/modules/ai/ai-tools.module.js.map +1 -0
  232. package/dist/server/modules/ai/tools/delete-user.tool.d.ts +30 -0
  233. package/dist/server/modules/ai/tools/delete-user.tool.js +49 -0
  234. package/dist/server/modules/ai/tools/delete-user.tool.js.map +1 -0
  235. package/dist/server/modules/ai/tools/find-users.tool.d.ts +30 -0
  236. package/dist/server/modules/ai/tools/find-users.tool.js +52 -0
  237. package/dist/server/modules/ai/tools/find-users.tool.js.map +1 -0
  238. package/dist/server/modules/ai/tools/get-user.tool.d.ts +26 -0
  239. package/dist/server/modules/ai/tools/get-user.tool.js +48 -0
  240. package/dist/server/modules/ai/tools/get-user.tool.js.map +1 -0
  241. package/dist/server/modules/ai/tools/update-user-job-title.tool.d.ts +32 -0
  242. package/dist/server/modules/ai/tools/update-user-job-title.tool.js +54 -0
  243. package/dist/server/modules/ai/tools/update-user-job-title.tool.js.map +1 -0
  244. package/dist/server/modules/error-code/error-codes.d.ts +9 -0
  245. package/dist/server/server.module.js +2 -0
  246. package/dist/server/server.module.js.map +1 -1
  247. package/dist/tsconfig.build.tsbuildinfo +1 -1
  248. package/docs/REQUEST-LIFECYCLE.md +10 -0
  249. package/migration-guides/11.25.x-to-11.26.0.md +278 -0
  250. package/package.json +2 -1
  251. package/src/config.env.ts +48 -1
  252. package/src/core/common/helpers/config.helper.ts +5 -2
  253. package/src/core/common/interceptors/check-security.interceptor.ts +13 -3
  254. package/src/core/common/interfaces/server-options.interface.ts +312 -0
  255. package/src/core/modules/ai/INTEGRATION-CHECKLIST.md +220 -0
  256. package/src/core/modules/ai/README.md +526 -0
  257. package/src/core/modules/ai/core-ai-mcp.controller.ts +223 -0
  258. package/src/core/modules/ai/core-ai.controller.ts +547 -0
  259. package/src/core/modules/ai/core-ai.module.ts +269 -0
  260. package/src/core/modules/ai/core-ai.resolver.ts +526 -0
  261. package/src/core/modules/ai/helpers/ai-mcp-oauth.helper.ts +35 -0
  262. package/src/core/modules/ai/hooks/ai-hook.base.ts +23 -0
  263. package/src/core/modules/ai/hooks/ai-hook.registry.ts +119 -0
  264. package/src/core/modules/ai/index.ts +70 -0
  265. package/src/core/modules/ai/inputs/core-ai-budget-limit-create.input.ts +27 -0
  266. package/src/core/modules/ai/inputs/core-ai-budget-limit.input.ts +52 -0
  267. package/src/core/modules/ai/inputs/core-ai-connection-create.input.ts +32 -0
  268. package/src/core/modules/ai/inputs/core-ai-connection-preference.input.ts +42 -0
  269. package/src/core/modules/ai/inputs/core-ai-connection.input.ts +235 -0
  270. package/src/core/modules/ai/inputs/core-ai-conversation-create.input.ts +13 -0
  271. package/src/core/modules/ai/inputs/core-ai-conversation.input.ts +33 -0
  272. package/src/core/modules/ai/inputs/core-ai-prompt-create.input.ts +50 -0
  273. package/src/core/modules/ai/inputs/core-ai-prompt-hint-create.input.ts +26 -0
  274. package/src/core/modules/ai/inputs/core-ai-prompt-hint.input.ts +43 -0
  275. package/src/core/modules/ai/inputs/core-ai-prompt-update.input.ts +42 -0
  276. package/src/core/modules/ai/inputs/core-ai-prompt.input.ts +144 -0
  277. package/src/core/modules/ai/inputs/core-ai-slot-create.input.ts +26 -0
  278. package/src/core/modules/ai/inputs/core-ai-slot-update.input.ts +65 -0
  279. package/src/core/modules/ai/interfaces/ai-hook.interface.ts +74 -0
  280. package/src/core/modules/ai/interfaces/ai-placeholder.interface.ts +49 -0
  281. package/src/core/modules/ai/interfaces/ai-tool.interface.ts +112 -0
  282. package/src/core/modules/ai/interfaces/llm-provider.interface.ts +187 -0
  283. package/src/core/modules/ai/interfaces/resolved-ai-connection.interface.ts +55 -0
  284. package/src/core/modules/ai/models/core-ai-action.model.ts +37 -0
  285. package/src/core/modules/ai/models/core-ai-available-connection.model.ts +42 -0
  286. package/src/core/modules/ai/models/core-ai-budget-limit.model.ts +82 -0
  287. package/src/core/modules/ai/models/core-ai-connection-preference.model.ts +72 -0
  288. package/src/core/modules/ai/models/core-ai-connection.model.ts +330 -0
  289. package/src/core/modules/ai/models/core-ai-conversation.model.ts +87 -0
  290. package/src/core/modules/ai/models/core-ai-interaction.model.ts +145 -0
  291. package/src/core/modules/ai/models/core-ai-message.model.ts +29 -0
  292. package/src/core/modules/ai/models/core-ai-mode.model.ts +93 -0
  293. package/src/core/modules/ai/models/core-ai-prompt-hint.model.ts +98 -0
  294. package/src/core/modules/ai/models/core-ai-prompt.model.ts +120 -0
  295. package/src/core/modules/ai/models/core-ai-response.model.ts +119 -0
  296. package/src/core/modules/ai/models/core-ai-slot.model.ts +146 -0
  297. package/src/core/modules/ai/models/core-ai-tool-grant.model.ts +87 -0
  298. package/src/core/modules/ai/models/core-ai-tool-policy.model.ts +115 -0
  299. package/src/core/modules/ai/models/core-ai-usage-info.model.ts +107 -0
  300. package/src/core/modules/ai/models/core-ai-usage.model.ts +29 -0
  301. package/src/core/modules/ai/providers/claude-cli.provider.ts +240 -0
  302. package/src/core/modules/ai/providers/llm-provider.factory.ts +63 -0
  303. package/src/core/modules/ai/providers/openai-compatible.provider.ts +329 -0
  304. package/src/core/modules/ai/services/ai-crypto.service.ts +120 -0
  305. package/src/core/modules/ai/services/core-ai-budget.service.ts +297 -0
  306. package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +74 -0
  307. package/src/core/modules/ai/services/core-ai-connection-resolver.service.ts +308 -0
  308. package/src/core/modules/ai/services/core-ai-connection.service.ts +387 -0
  309. package/src/core/modules/ai/services/core-ai-conversation.service.ts +105 -0
  310. package/src/core/modules/ai/services/core-ai-interaction.service.ts +56 -0
  311. package/src/core/modules/ai/services/core-ai-mcp-client.service.ts +169 -0
  312. package/src/core/modules/ai/services/core-ai-mcp-oauth.service.ts +445 -0
  313. package/src/core/modules/ai/services/core-ai-mcp.service.ts +94 -0
  314. package/src/core/modules/ai/services/core-ai-mode.service.ts +43 -0
  315. package/src/core/modules/ai/services/core-ai-placeholder.registry.ts +123 -0
  316. package/src/core/modules/ai/services/core-ai-prompt-builder.service.ts +228 -0
  317. package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +133 -0
  318. package/src/core/modules/ai/services/core-ai-prompt.service.ts +164 -0
  319. package/src/core/modules/ai/services/core-ai-slot.service.ts +526 -0
  320. package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +107 -0
  321. package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +124 -0
  322. package/src/core/modules/ai/services/core-ai.service.ts +1396 -0
  323. package/src/core/modules/ai/tools/ai-tool.base.ts +46 -0
  324. package/src/core/modules/ai/tools/ai-tool.registry.ts +124 -0
  325. package/src/core/modules/ai/tools/ask-user-question.tool.ts +76 -0
  326. package/src/core/modules/ai/tools/search-tools.tool.ts +70 -0
  327. package/src/core/modules/error-code/error-codes.ts +86 -0
  328. package/src/core.module.ts +12 -0
  329. package/src/index.ts +6 -0
  330. package/src/server/modules/ai/ai-tools.module.ts +33 -0
  331. package/src/server/modules/ai/tools/delete-user.tool.ts +44 -0
  332. package/src/server/modules/ai/tools/find-users.tool.ts +49 -0
  333. package/src/server/modules/ai/tools/get-user.tool.ts +43 -0
  334. package/src/server/modules/ai/tools/update-user-job-title.tool.ts +62 -0
  335. package/src/server/server.module.ts +5 -0
@@ -0,0 +1,547 @@
1
+ import { Body, Controller, Delete, Get, Param, Post, Put, Res } from '@nestjs/common';
2
+ import { Response } from 'express';
3
+
4
+ import { RESTServiceOptions } from '../../common/decorators/rest-service-options.decorator';
5
+ import { Roles } from '../../common/decorators/roles.decorator';
6
+ import { RoleEnum } from '../../common/enums/role.enum';
7
+ import { ServiceOptions } from '../../common/interfaces/service-options.interface';
8
+ import { RequestContext } from '../../common/services/request-context.service';
9
+ import { CoreAiBudgetLimitCreateInput } from './inputs/core-ai-budget-limit-create.input';
10
+ import { CoreAiBudgetLimitInput } from './inputs/core-ai-budget-limit.input';
11
+ import { CoreAiConnectionCreateInput } from './inputs/core-ai-connection-create.input';
12
+ import { CoreAiConnectionPreferenceInput } from './inputs/core-ai-connection-preference.input';
13
+ import { CoreAiConnectionInput } from './inputs/core-ai-connection.input';
14
+ import { CoreAiConversationCreateInput } from './inputs/core-ai-conversation-create.input';
15
+ import { CoreAiPromptHintCreateInput } from './inputs/core-ai-prompt-hint-create.input';
16
+ import { CoreAiPromptHintInput } from './inputs/core-ai-prompt-hint.input';
17
+ import { CoreAiPromptCreateInput } from './inputs/core-ai-prompt-create.input';
18
+ import { CoreAiPromptUpdateInput } from './inputs/core-ai-prompt-update.input';
19
+ import { CoreAiSlotCreateInput } from './inputs/core-ai-slot-create.input';
20
+ import { CoreAiSlotUpdateInput } from './inputs/core-ai-slot-update.input';
21
+ import { CoreAiPromptInput } from './inputs/core-ai-prompt.input';
22
+ import { CoreAiAvailableConnection } from './models/core-ai-available-connection.model';
23
+ import { CoreAiBudgetLimit } from './models/core-ai-budget-limit.model';
24
+ import { CoreAiConnectionPreference } from './models/core-ai-connection-preference.model';
25
+ import { CoreAiConnection } from './models/core-ai-connection.model';
26
+ import { CoreAiConversation } from './models/core-ai-conversation.model';
27
+ import { CoreAiInteraction } from './models/core-ai-interaction.model';
28
+ import { CoreAiPromptHint } from './models/core-ai-prompt-hint.model';
29
+ import { CoreAiPrompt } from './models/core-ai-prompt.model';
30
+ import { CoreAiSlot } from './models/core-ai-slot.model';
31
+ import { CoreAiResponse } from './models/core-ai-response.model';
32
+ import { CoreAiUsageInfo } from './models/core-ai-usage-info.model';
33
+ import { CoreAiBudgetService } from './services/core-ai-budget.service';
34
+ import { CoreAiConnectionPreferenceService } from './services/core-ai-connection-preference.service';
35
+ import { CoreAiConnectionResolverService } from './services/core-ai-connection-resolver.service';
36
+ import { CoreAiConnectionService } from './services/core-ai-connection.service';
37
+ import { CoreAiConversationService } from './services/core-ai-conversation.service';
38
+ import { CoreAiInteractionService } from './services/core-ai-interaction.service';
39
+ import { CoreAiPlaceholderRegistry } from './services/core-ai-placeholder.registry';
40
+ import { CoreAiPromptHintService } from './services/core-ai-prompt-hint.service';
41
+ import { CoreAiPromptService } from './services/core-ai-prompt.service';
42
+ import { CoreAiSlotService } from './services/core-ai-slot.service';
43
+ import { CoreAiService } from './services/core-ai.service';
44
+
45
+ /**
46
+ * REST controller for AI prompts and connection management.
47
+ *
48
+ * - `POST /ai/prompt`: any authenticated user.
49
+ * - `/ai/connections*`: admin only.
50
+ *
51
+ * Extend this controller in a project and pass it via `CoreAiModule.forRoot({ controller })`.
52
+ */
53
+ @Controller('ai')
54
+ @Roles(RoleEnum.ADMIN)
55
+ export class CoreAiController {
56
+ constructor(
57
+ protected readonly aiService: CoreAiService,
58
+ protected readonly connectionService: CoreAiConnectionService,
59
+ protected readonly conversationService: CoreAiConversationService,
60
+ protected readonly interactionService: CoreAiInteractionService,
61
+ protected readonly budgetService: CoreAiBudgetService,
62
+ protected readonly connectionResolver: CoreAiConnectionResolverService,
63
+ protected readonly preferenceService: CoreAiConnectionPreferenceService,
64
+ protected readonly slotService: CoreAiSlotService,
65
+ protected readonly promptHintService: CoreAiPromptHintService,
66
+ protected readonly promptService: CoreAiPromptService,
67
+ protected readonly placeholderRegistry: CoreAiPlaceholderRegistry,
68
+ ) {}
69
+
70
+ /**
71
+ * Send a prompt to the AI assistant.
72
+ */
73
+ @Post('prompt')
74
+ @Roles(RoleEnum.S_USER)
75
+ async prompt(
76
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
77
+ @Body() input: CoreAiPromptInput,
78
+ ): Promise<CoreAiResponse> {
79
+ return this.aiService.prompt(input, serviceOptions);
80
+ }
81
+
82
+ /**
83
+ * Send a prompt and stream the answer via Server-Sent Events.
84
+ *
85
+ * Emits `action`, `token`, `final` and `error` events as `data:` lines.
86
+ * Uses the raw response (`@Res()`), so interceptors are bypassed — the events
87
+ * already carry permission-filtered data from the orchestrator.
88
+ */
89
+ @Post('stream')
90
+ @Roles(RoleEnum.S_USER)
91
+ async stream(
92
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
93
+ @Body() input: CoreAiPromptInput,
94
+ @Res() res: Response,
95
+ ): Promise<void> {
96
+ res.setHeader('Cache-Control', 'no-cache');
97
+ res.setHeader('Connection', 'keep-alive');
98
+ res.setHeader('Content-Type', 'text/event-stream');
99
+ res.flushHeaders?.();
100
+ try {
101
+ for await (const event of this.aiService.promptStream(input, serviceOptions)) {
102
+ res.write(`data: ${JSON.stringify(event)}\n\n`);
103
+ }
104
+ } catch (err) {
105
+ res.write(`data: ${JSON.stringify({ message: (err as Error).message, type: 'error' })}\n\n`);
106
+ } finally {
107
+ res.end();
108
+ }
109
+ }
110
+
111
+ // ===================================================================================================================
112
+ // Connection selection (user self-service + admin preferences)
113
+ //
114
+ // NOTE: literal subpaths (`connections/available`, `connections/preferences`) are
115
+ // declared BEFORE `connections/:id` so Express matches them before the id param.
116
+ // ===================================================================================================================
117
+
118
+ /**
119
+ * List the AI connections the current user/tenant may use (non-sensitive).
120
+ */
121
+ @Get('connections/available')
122
+ @Roles(RoleEnum.S_USER)
123
+ async availableConnections(
124
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
125
+ ): Promise<CoreAiAvailableConnection[]> {
126
+ return this.connectionResolver.listAvailable({
127
+ tenantId: RequestContext.getTenantId(),
128
+ userId: serviceOptions?.currentUser?.id,
129
+ });
130
+ }
131
+
132
+ /**
133
+ * Set the current user's own default AI connection (validated against availability).
134
+ */
135
+ @Post('connections/select')
136
+ @Roles(RoleEnum.S_USER)
137
+ async setUserConnection(
138
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
139
+ @Body('connectionId') connectionId: string,
140
+ ): Promise<CoreAiAvailableConnection[]> {
141
+ const tenantId = RequestContext.getTenantId();
142
+ const userId = serviceOptions?.currentUser?.id;
143
+ await this.connectionResolver.setUserConnection(userId, connectionId, tenantId);
144
+ return this.connectionResolver.listAvailable({ tenantId, userId });
145
+ }
146
+
147
+ /**
148
+ * Find AI connection preferences (admin).
149
+ */
150
+ @Get('connections/preferences')
151
+ @Roles(RoleEnum.ADMIN)
152
+ async findConnectionPreferences(
153
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
154
+ ): Promise<CoreAiConnectionPreference[]> {
155
+ return this.preferenceService.find({}, serviceOptions);
156
+ }
157
+
158
+ /**
159
+ * Upsert a tenant/user connection preference (admin).
160
+ */
161
+ @Post('connections/preferences')
162
+ @Roles(RoleEnum.ADMIN)
163
+ async setConnectionPreference(@Body() input: CoreAiConnectionPreferenceInput): Promise<CoreAiConnectionPreference> {
164
+ return this.connectionResolver.setPreference(
165
+ input.scope as 'tenant' | 'user',
166
+ input.refId,
167
+ input.connectionId,
168
+ input.enforced ?? false,
169
+ );
170
+ }
171
+
172
+ /**
173
+ * Delete an AI connection preference by id (admin).
174
+ */
175
+ @Delete('connections/preferences/:id')
176
+ @Roles(RoleEnum.ADMIN)
177
+ async deleteConnectionPreference(
178
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
179
+ @Param('id') id: string,
180
+ ): Promise<CoreAiConnectionPreference> {
181
+ return this.preferenceService.delete(id, serviceOptions);
182
+ }
183
+
184
+ /**
185
+ * Find all AI connections.
186
+ */
187
+ @Get('connections')
188
+ @Roles(RoleEnum.ADMIN)
189
+ async findConnections(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<CoreAiConnection[]> {
190
+ return this.connectionService.find({}, serviceOptions);
191
+ }
192
+
193
+ /**
194
+ * Get an AI connection by id.
195
+ */
196
+ @Get('connections/:id')
197
+ @Roles(RoleEnum.ADMIN)
198
+ async getConnection(
199
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
200
+ @Param('id') id: string,
201
+ ): Promise<CoreAiConnection> {
202
+ return this.connectionService.get(id, serviceOptions);
203
+ }
204
+
205
+ /**
206
+ * Create a new AI connection.
207
+ */
208
+ @Post('connections')
209
+ @Roles(RoleEnum.ADMIN)
210
+ async createConnection(
211
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
212
+ @Body() input: CoreAiConnectionCreateInput,
213
+ ): Promise<CoreAiConnection> {
214
+ return this.connectionService.create(input, { ...serviceOptions, inputType: CoreAiConnectionCreateInput });
215
+ }
216
+
217
+ /**
218
+ * Probe an AI connection's endpoint to auto-detect and persist its capabilities
219
+ * (JSON / native tools) for any flag left undefined.
220
+ */
221
+ @Post('connections/:id/detect-capabilities')
222
+ @Roles(RoleEnum.ADMIN)
223
+ async detectConnectionCapabilities(
224
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
225
+ @Param('id') id: string,
226
+ ): Promise<CoreAiConnection> {
227
+ await this.connectionService.detectAndPersistCapabilities(id);
228
+ return this.connectionService.get(id, serviceOptions);
229
+ }
230
+
231
+ /**
232
+ * Update an AI connection.
233
+ */
234
+ @Put('connections/:id')
235
+ @Roles(RoleEnum.ADMIN)
236
+ async updateConnection(
237
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
238
+ @Param('id') id: string,
239
+ @Body() input: CoreAiConnectionInput,
240
+ ): Promise<CoreAiConnection> {
241
+ return this.connectionService.update(id, input, { ...serviceOptions, inputType: CoreAiConnectionInput });
242
+ }
243
+
244
+ /**
245
+ * Delete an AI connection.
246
+ */
247
+ @Delete('connections/:id')
248
+ @Roles(RoleEnum.ADMIN)
249
+ async deleteConnection(
250
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
251
+ @Param('id') id: string,
252
+ ): Promise<CoreAiConnection> {
253
+ return this.connectionService.delete(id, serviceOptions);
254
+ }
255
+
256
+ /**
257
+ * Create a new AI conversation for the current user.
258
+ */
259
+ @Post('conversations')
260
+ @Roles(RoleEnum.S_USER)
261
+ async createConversation(
262
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
263
+ @Body() input: CoreAiConversationCreateInput,
264
+ ): Promise<CoreAiConversation> {
265
+ return this.conversationService.create(input, { ...serviceOptions, inputType: CoreAiConversationCreateInput });
266
+ }
267
+
268
+ /**
269
+ * Find the current user's AI conversations (admins see all).
270
+ *
271
+ * The `messages` subdocument array is excluded from the list result — clients
272
+ * fetching the conversation detail via `getConversation` get the full message
273
+ * history. List payloads stay small even for users with many long conversations.
274
+ */
275
+ @Get('conversations')
276
+ @Roles(RoleEnum.S_USER)
277
+ async findConversations(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<CoreAiConversation[]> {
278
+ const currentUser = serviceOptions?.currentUser;
279
+ const filterQuery = currentUser?.roles?.includes(RoleEnum.ADMIN) ? {} : { createdBy: currentUser?.id };
280
+ return this.conversationService.find(
281
+ { filterQuery },
282
+ { ...serviceOptions, roles: [RoleEnum.ADMIN, RoleEnum.S_CREATOR, RoleEnum.S_SELF], select: '-messages' },
283
+ );
284
+ }
285
+
286
+ /**
287
+ * Get an AI conversation by id (owner or admin).
288
+ */
289
+ @Get('conversations/:id')
290
+ @Roles(RoleEnum.S_USER)
291
+ async getConversation(
292
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
293
+ @Param('id') id: string,
294
+ ): Promise<CoreAiConversation> {
295
+ return this.conversationService.get(id, {
296
+ ...serviceOptions,
297
+ roles: [RoleEnum.ADMIN, RoleEnum.S_CREATOR, RoleEnum.S_SELF],
298
+ });
299
+ }
300
+
301
+ /**
302
+ * Delete an AI conversation (owner or admin).
303
+ */
304
+ @Delete('conversations/:id')
305
+ @Roles(RoleEnum.S_USER)
306
+ async deleteConversation(
307
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
308
+ @Param('id') id: string,
309
+ ): Promise<CoreAiConversation> {
310
+ return this.conversationService.delete(id, {
311
+ ...serviceOptions,
312
+ roles: [RoleEnum.ADMIN, RoleEnum.S_CREATOR, RoleEnum.S_SELF],
313
+ });
314
+ }
315
+
316
+ /**
317
+ * Find AI interaction audit records.
318
+ */
319
+ @Get('interactions')
320
+ @Roles(RoleEnum.ADMIN)
321
+ async findInteractions(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<CoreAiInteraction[]> {
322
+ return this.interactionService.find({}, serviceOptions);
323
+ }
324
+
325
+ /**
326
+ * Get an AI interaction audit record by id.
327
+ */
328
+ @Get('interactions/:id')
329
+ @Roles(RoleEnum.ADMIN)
330
+ async getInteraction(
331
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
332
+ @Param('id') id: string,
333
+ ): Promise<CoreAiInteraction> {
334
+ return this.interactionService.get(id, serviceOptions);
335
+ }
336
+
337
+ /**
338
+ * Token usage for the current user (and tenant) until the next reset.
339
+ */
340
+ @Get('usage')
341
+ @Roles(RoleEnum.S_USER)
342
+ async usage(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<CoreAiUsageInfo> {
343
+ return this.budgetService.getUsageInfo(serviceOptions?.currentUser?.id, RequestContext.getTenantId());
344
+ }
345
+
346
+ /**
347
+ * Find AI budget limits (admin).
348
+ */
349
+ @Get('budget-limits')
350
+ @Roles(RoleEnum.ADMIN)
351
+ async findBudgetLimits(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<CoreAiBudgetLimit[]> {
352
+ return this.budgetService.find({}, serviceOptions);
353
+ }
354
+
355
+ /**
356
+ * Create an AI budget limit (admin).
357
+ */
358
+ @Post('budget-limits')
359
+ @Roles(RoleEnum.ADMIN)
360
+ async createBudgetLimit(
361
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
362
+ @Body() input: CoreAiBudgetLimitCreateInput,
363
+ ): Promise<CoreAiBudgetLimit> {
364
+ return this.budgetService.create(input, { ...serviceOptions, inputType: CoreAiBudgetLimitCreateInput });
365
+ }
366
+
367
+ /**
368
+ * Update an AI budget limit (admin).
369
+ */
370
+ @Put('budget-limits/:id')
371
+ @Roles(RoleEnum.ADMIN)
372
+ async updateBudgetLimit(
373
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
374
+ @Param('id') id: string,
375
+ @Body() input: CoreAiBudgetLimitInput,
376
+ ): Promise<CoreAiBudgetLimit> {
377
+ return this.budgetService.update(id, input, { ...serviceOptions, inputType: CoreAiBudgetLimitInput });
378
+ }
379
+
380
+ /**
381
+ * Delete an AI budget limit (admin).
382
+ */
383
+ @Delete('budget-limits/:id')
384
+ @Roles(RoleEnum.ADMIN)
385
+ async deleteBudgetLimit(
386
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
387
+ @Param('id') id: string,
388
+ ): Promise<CoreAiBudgetLimit> {
389
+ return this.budgetService.delete(id, serviceOptions);
390
+ }
391
+
392
+ // ===================================================================================================================
393
+ // Placeholders — runtime registry, available to any signed-in user (for slot/prompt editors)
394
+ // ===================================================================================================================
395
+
396
+ /** List every registered placeholder with its name + description (for slot/prompt editors). */
397
+ @Get('placeholders')
398
+ @Roles(RoleEnum.S_USER)
399
+ async listPlaceholders(): Promise<unknown[]> {
400
+ return this.placeholderRegistry.list();
401
+ }
402
+
403
+ // ===================================================================================================================
404
+ // Slots — admin-editable system-prompt building blocks (tenant-scoped)
405
+ // ===================================================================================================================
406
+
407
+ /**
408
+ * Effective slots for the admin UI — framework defaults + tenant overrides + tenant customs.
409
+ * Each entry carries `isSystem` / `isOverride` flags so the UI can render the correct action.
410
+ * NOTE: this route comes BEFORE `:id` parameter routes so Express matches it literally.
411
+ */
412
+ @Get('slots/effective')
413
+ @Roles(RoleEnum.ADMIN)
414
+ async listEffectiveSlots(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<unknown[]> {
415
+ return this.slotService.listEffective(serviceOptions);
416
+ }
417
+
418
+ /**
419
+ * Reset a system-slot override (deletes the row → framework default applies
420
+ * again). Returns the now-effective system-default slot so the caller can
421
+ * refresh its UI without a follow-up `/ai/slots/effective` call.
422
+ */
423
+ @Post('slots/:id/reset')
424
+ @Roles(RoleEnum.ADMIN)
425
+ async resetSlot(@RESTServiceOptions() serviceOptions: ServiceOptions, @Param('id') id: string) {
426
+ return this.slotService.resetSystemSlot(id, serviceOptions);
427
+ }
428
+
429
+ /** Find slots stored for the current tenant (admin). Custom + override rows only — system defaults are virtual. */
430
+ @Get('slots')
431
+ @Roles(RoleEnum.ADMIN)
432
+ async findSlots(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<CoreAiSlot[]> {
433
+ return this.slotService.find({}, serviceOptions);
434
+ }
435
+
436
+ /** Create a tenant slot (admin). Use the system-default `key` to override a default. */
437
+ @Post('slots')
438
+ @Roles(RoleEnum.ADMIN)
439
+ async createSlot(
440
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
441
+ @Body() input: CoreAiSlotCreateInput,
442
+ ): Promise<CoreAiSlot> {
443
+ return this.slotService.create(input, { ...serviceOptions, inputType: CoreAiSlotCreateInput });
444
+ }
445
+
446
+ /** Update a tenant slot (admin). Slot must belong to the calling admin's tenant. */
447
+ @Put('slots/:id')
448
+ @Roles(RoleEnum.ADMIN)
449
+ async updateSlot(
450
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
451
+ @Param('id') id: string,
452
+ @Body() input: CoreAiSlotUpdateInput,
453
+ ): Promise<CoreAiSlot> {
454
+ return this.slotService.update(id, input, { ...serviceOptions, inputType: CoreAiSlotUpdateInput });
455
+ }
456
+
457
+ /** Delete a tenant slot (admin). Real delete; custom slots cannot be restored. */
458
+ @Delete('slots/:id')
459
+ @Roles(RoleEnum.ADMIN)
460
+ async deleteSlot(@RESTServiceOptions() serviceOptions: ServiceOptions, @Param('id') id: string): Promise<CoreAiSlot> {
461
+ return this.slotService.delete(id, serviceOptions);
462
+ }
463
+
464
+ // ===================================================================================================================
465
+ // Learned prompt hints (governed self-improvement loop)
466
+ // ===================================================================================================================
467
+
468
+ /** Find learned prompt hints (admin). */
469
+ @Get('prompt-hints')
470
+ @Roles(RoleEnum.ADMIN)
471
+ async findPromptHints(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<CoreAiPromptHint[]> {
472
+ return this.promptHintService.find({}, serviceOptions);
473
+ }
474
+
475
+ /** Create a learned prompt hint manually (admin). */
476
+ @Post('prompt-hints')
477
+ @Roles(RoleEnum.ADMIN)
478
+ async createPromptHint(
479
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
480
+ @Body() input: CoreAiPromptHintCreateInput,
481
+ ): Promise<CoreAiPromptHint> {
482
+ return this.promptHintService.create(input, { ...serviceOptions, inputType: CoreAiPromptHintCreateInput });
483
+ }
484
+
485
+ /** Update a learned prompt hint (admin) — typically approve/reject or edit. */
486
+ @Put('prompt-hints/:id')
487
+ @Roles(RoleEnum.ADMIN)
488
+ async updatePromptHint(
489
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
490
+ @Param('id') id: string,
491
+ @Body() input: CoreAiPromptHintInput,
492
+ ): Promise<CoreAiPromptHint> {
493
+ return this.promptHintService.update(id, input, { ...serviceOptions, inputType: CoreAiPromptHintInput });
494
+ }
495
+
496
+ /** Delete a learned prompt hint (admin). */
497
+ @Delete('prompt-hints/:id')
498
+ @Roles(RoleEnum.ADMIN)
499
+ async deletePromptHint(
500
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
501
+ @Param('id') id: string,
502
+ ): Promise<CoreAiPromptHint> {
503
+ return this.promptHintService.delete(id, serviceOptions);
504
+ }
505
+
506
+ // ===================================================================================================================
507
+ // User-facing user prompts ("Vorlagen") — own / tenant / global
508
+ // ===================================================================================================================
509
+
510
+ /** List user prompts visible to the current user (own + tenant + global). */
511
+ @Get('prompts')
512
+ @Roles(RoleEnum.S_USER)
513
+ async findPrompts(@RESTServiceOptions() serviceOptions: ServiceOptions): Promise<CoreAiPrompt[]> {
514
+ return this.promptService.listVisible(serviceOptions);
515
+ }
516
+
517
+ /** Create a user prompt for the current user / tenant (global requires admin). */
518
+ @Post('prompts')
519
+ @Roles(RoleEnum.S_USER)
520
+ async createPrompt(
521
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
522
+ @Body() input: CoreAiPromptCreateInput,
523
+ ): Promise<CoreAiPrompt> {
524
+ return this.promptService.create(input, { ...serviceOptions, inputType: CoreAiPromptCreateInput });
525
+ }
526
+
527
+ /** Update a user prompt (owner only; admins via standard admin pipeline). */
528
+ @Put('prompts/:id')
529
+ @Roles(RoleEnum.S_USER)
530
+ async updatePrompt(
531
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
532
+ @Param('id') id: string,
533
+ @Body() input: CoreAiPromptUpdateInput,
534
+ ): Promise<CoreAiPrompt> {
535
+ return this.promptService.update(id, input, { ...serviceOptions, inputType: CoreAiPromptUpdateInput });
536
+ }
537
+
538
+ /** Delete a user prompt (owner only; admins via standard admin pipeline). */
539
+ @Delete('prompts/:id')
540
+ @Roles(RoleEnum.S_USER)
541
+ async deletePrompt(
542
+ @RESTServiceOptions() serviceOptions: ServiceOptions,
543
+ @Param('id') id: string,
544
+ ): Promise<CoreAiPrompt> {
545
+ return this.promptService.delete(id, serviceOptions);
546
+ }
547
+ }