@lenne.tech/nest-server 11.25.6 → 11.26.1

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 (340) 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/better-auth/core-better-auth.controller.d.ts +2 -1
  222. package/dist/core/modules/better-auth/core-better-auth.controller.js +12 -1
  223. package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
  224. package/dist/core/modules/error-code/error-codes.d.ts +81 -0
  225. package/dist/core/modules/error-code/error-codes.js +72 -0
  226. package/dist/core/modules/error-code/error-codes.js.map +1 -1
  227. package/dist/core.module.js +8 -0
  228. package/dist/core.module.js.map +1 -1
  229. package/dist/index.d.ts +1 -0
  230. package/dist/index.js +1 -0
  231. package/dist/index.js.map +1 -1
  232. package/dist/server/modules/ai/ai-tools.module.d.ts +5 -0
  233. package/dist/server/modules/ai/ai-tools.module.js +36 -0
  234. package/dist/server/modules/ai/ai-tools.module.js.map +1 -0
  235. package/dist/server/modules/ai/tools/delete-user.tool.d.ts +30 -0
  236. package/dist/server/modules/ai/tools/delete-user.tool.js +49 -0
  237. package/dist/server/modules/ai/tools/delete-user.tool.js.map +1 -0
  238. package/dist/server/modules/ai/tools/find-users.tool.d.ts +30 -0
  239. package/dist/server/modules/ai/tools/find-users.tool.js +52 -0
  240. package/dist/server/modules/ai/tools/find-users.tool.js.map +1 -0
  241. package/dist/server/modules/ai/tools/get-user.tool.d.ts +26 -0
  242. package/dist/server/modules/ai/tools/get-user.tool.js +48 -0
  243. package/dist/server/modules/ai/tools/get-user.tool.js.map +1 -0
  244. package/dist/server/modules/ai/tools/update-user-job-title.tool.d.ts +32 -0
  245. package/dist/server/modules/ai/tools/update-user-job-title.tool.js +54 -0
  246. package/dist/server/modules/ai/tools/update-user-job-title.tool.js.map +1 -0
  247. package/dist/server/modules/error-code/error-codes.d.ts +9 -0
  248. package/dist/server/server.module.js +2 -0
  249. package/dist/server/server.module.js.map +1 -1
  250. package/dist/tsconfig.build.tsbuildinfo +1 -1
  251. package/docs/REQUEST-LIFECYCLE.md +10 -0
  252. package/migration-guides/11.25.x-to-11.26.0.md +278 -0
  253. package/migration-guides/11.26.0-to-11.26.1.md +193 -0
  254. package/package.json +2 -1
  255. package/src/config.env.ts +48 -1
  256. package/src/core/common/helpers/config.helper.ts +5 -2
  257. package/src/core/common/interceptors/check-security.interceptor.ts +13 -3
  258. package/src/core/common/interfaces/server-options.interface.ts +312 -0
  259. package/src/core/modules/ai/INTEGRATION-CHECKLIST.md +220 -0
  260. package/src/core/modules/ai/README.md +526 -0
  261. package/src/core/modules/ai/core-ai-mcp.controller.ts +223 -0
  262. package/src/core/modules/ai/core-ai.controller.ts +547 -0
  263. package/src/core/modules/ai/core-ai.module.ts +269 -0
  264. package/src/core/modules/ai/core-ai.resolver.ts +526 -0
  265. package/src/core/modules/ai/helpers/ai-mcp-oauth.helper.ts +35 -0
  266. package/src/core/modules/ai/hooks/ai-hook.base.ts +23 -0
  267. package/src/core/modules/ai/hooks/ai-hook.registry.ts +119 -0
  268. package/src/core/modules/ai/index.ts +70 -0
  269. package/src/core/modules/ai/inputs/core-ai-budget-limit-create.input.ts +27 -0
  270. package/src/core/modules/ai/inputs/core-ai-budget-limit.input.ts +52 -0
  271. package/src/core/modules/ai/inputs/core-ai-connection-create.input.ts +32 -0
  272. package/src/core/modules/ai/inputs/core-ai-connection-preference.input.ts +42 -0
  273. package/src/core/modules/ai/inputs/core-ai-connection.input.ts +235 -0
  274. package/src/core/modules/ai/inputs/core-ai-conversation-create.input.ts +13 -0
  275. package/src/core/modules/ai/inputs/core-ai-conversation.input.ts +33 -0
  276. package/src/core/modules/ai/inputs/core-ai-prompt-create.input.ts +50 -0
  277. package/src/core/modules/ai/inputs/core-ai-prompt-hint-create.input.ts +26 -0
  278. package/src/core/modules/ai/inputs/core-ai-prompt-hint.input.ts +43 -0
  279. package/src/core/modules/ai/inputs/core-ai-prompt-update.input.ts +42 -0
  280. package/src/core/modules/ai/inputs/core-ai-prompt.input.ts +144 -0
  281. package/src/core/modules/ai/inputs/core-ai-slot-create.input.ts +26 -0
  282. package/src/core/modules/ai/inputs/core-ai-slot-update.input.ts +65 -0
  283. package/src/core/modules/ai/interfaces/ai-hook.interface.ts +74 -0
  284. package/src/core/modules/ai/interfaces/ai-placeholder.interface.ts +49 -0
  285. package/src/core/modules/ai/interfaces/ai-tool.interface.ts +112 -0
  286. package/src/core/modules/ai/interfaces/llm-provider.interface.ts +187 -0
  287. package/src/core/modules/ai/interfaces/resolved-ai-connection.interface.ts +55 -0
  288. package/src/core/modules/ai/models/core-ai-action.model.ts +37 -0
  289. package/src/core/modules/ai/models/core-ai-available-connection.model.ts +42 -0
  290. package/src/core/modules/ai/models/core-ai-budget-limit.model.ts +82 -0
  291. package/src/core/modules/ai/models/core-ai-connection-preference.model.ts +72 -0
  292. package/src/core/modules/ai/models/core-ai-connection.model.ts +330 -0
  293. package/src/core/modules/ai/models/core-ai-conversation.model.ts +87 -0
  294. package/src/core/modules/ai/models/core-ai-interaction.model.ts +145 -0
  295. package/src/core/modules/ai/models/core-ai-message.model.ts +29 -0
  296. package/src/core/modules/ai/models/core-ai-mode.model.ts +93 -0
  297. package/src/core/modules/ai/models/core-ai-prompt-hint.model.ts +98 -0
  298. package/src/core/modules/ai/models/core-ai-prompt.model.ts +120 -0
  299. package/src/core/modules/ai/models/core-ai-response.model.ts +119 -0
  300. package/src/core/modules/ai/models/core-ai-slot.model.ts +146 -0
  301. package/src/core/modules/ai/models/core-ai-tool-grant.model.ts +87 -0
  302. package/src/core/modules/ai/models/core-ai-tool-policy.model.ts +115 -0
  303. package/src/core/modules/ai/models/core-ai-usage-info.model.ts +107 -0
  304. package/src/core/modules/ai/models/core-ai-usage.model.ts +29 -0
  305. package/src/core/modules/ai/providers/claude-cli.provider.ts +240 -0
  306. package/src/core/modules/ai/providers/llm-provider.factory.ts +63 -0
  307. package/src/core/modules/ai/providers/openai-compatible.provider.ts +329 -0
  308. package/src/core/modules/ai/services/ai-crypto.service.ts +120 -0
  309. package/src/core/modules/ai/services/core-ai-budget.service.ts +297 -0
  310. package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +74 -0
  311. package/src/core/modules/ai/services/core-ai-connection-resolver.service.ts +308 -0
  312. package/src/core/modules/ai/services/core-ai-connection.service.ts +387 -0
  313. package/src/core/modules/ai/services/core-ai-conversation.service.ts +105 -0
  314. package/src/core/modules/ai/services/core-ai-interaction.service.ts +56 -0
  315. package/src/core/modules/ai/services/core-ai-mcp-client.service.ts +169 -0
  316. package/src/core/modules/ai/services/core-ai-mcp-oauth.service.ts +445 -0
  317. package/src/core/modules/ai/services/core-ai-mcp.service.ts +94 -0
  318. package/src/core/modules/ai/services/core-ai-mode.service.ts +43 -0
  319. package/src/core/modules/ai/services/core-ai-placeholder.registry.ts +123 -0
  320. package/src/core/modules/ai/services/core-ai-prompt-builder.service.ts +228 -0
  321. package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +133 -0
  322. package/src/core/modules/ai/services/core-ai-prompt.service.ts +164 -0
  323. package/src/core/modules/ai/services/core-ai-slot.service.ts +526 -0
  324. package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +107 -0
  325. package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +124 -0
  326. package/src/core/modules/ai/services/core-ai.service.ts +1396 -0
  327. package/src/core/modules/ai/tools/ai-tool.base.ts +46 -0
  328. package/src/core/modules/ai/tools/ai-tool.registry.ts +124 -0
  329. package/src/core/modules/ai/tools/ask-user-question.tool.ts +76 -0
  330. package/src/core/modules/ai/tools/search-tools.tool.ts +70 -0
  331. package/src/core/modules/better-auth/core-better-auth.controller.ts +20 -3
  332. package/src/core/modules/error-code/error-codes.ts +86 -0
  333. package/src/core.module.ts +12 -0
  334. package/src/index.ts +6 -0
  335. package/src/server/modules/ai/ai-tools.module.ts +33 -0
  336. package/src/server/modules/ai/tools/delete-user.tool.ts +44 -0
  337. package/src/server/modules/ai/tools/find-users.tool.ts +49 -0
  338. package/src/server/modules/ai/tools/get-user.tool.ts +43 -0
  339. package/src/server/modules/ai/tools/update-user-job-title.tool.ts +62 -0
  340. package/src/server/server.module.ts +5 -0
@@ -1045,10 +1045,267 @@ export interface ICorsConfig {
1045
1045
  enabled?: boolean;
1046
1046
  }
1047
1047
 
1048
+ /**
1049
+ * Bootstrap configuration for a default AI connection.
1050
+ *
1051
+ * When set and no connection exists yet, the AI module seeds this as the default
1052
+ * connection on first start. The database remains the source of truth afterwards;
1053
+ * connections are managed at runtime (admin CRUD / frontend settings). Prefer
1054
+ * `apiKeyEnv` over an inline `apiKey` so no secret is committed to config.
1055
+ */
1056
+ export interface IAiDefaultConnection {
1057
+ /** Inline plaintext API key (encrypted on seed). Prefer `apiKeyEnv` instead. */
1058
+ apiKey?: string;
1059
+
1060
+ /** Name of an environment variable holding the API key (e.g. 'AI_API_KEY'). */
1061
+ apiKeyEnv?: string;
1062
+
1063
+ /** Base URL of the OpenAI-compatible endpoint. */
1064
+ baseUrl: string;
1065
+
1066
+ /** Capability tags (free-form, e.g. 'analysis', 'vision'). */
1067
+ capabilities?: string[];
1068
+
1069
+ /** Default maximum number of tokens for completions. */
1070
+ defaultMaxTokens?: number;
1071
+
1072
+ /** Default sampling temperature. */
1073
+ defaultTemperature?: number;
1074
+
1075
+ /** Human-readable description. */
1076
+ description?: string;
1077
+
1078
+ /** Model id sent to the backend (e.g. 'gpt-oss-120b'). */
1079
+ model: string;
1080
+
1081
+ /** Human-readable connection name. */
1082
+ name: string;
1083
+
1084
+ /** Provider type (default 'openai-compatible'). */
1085
+ providerType?: string;
1086
+
1087
+ /**
1088
+ * Native JSON / structured-output support. Omit to auto-detect by probing the
1089
+ * endpoint (explicit `true`/`false` is authoritative and never probed).
1090
+ */
1091
+ supportsJsonResponse?: boolean;
1092
+
1093
+ /**
1094
+ * Native function/tool-calling support. Omit to auto-detect by probing the
1095
+ * endpoint (explicit `true`/`false` is authoritative and never probed).
1096
+ */
1097
+ supportsNativeTools?: boolean;
1098
+
1099
+ /** Whether the model supports image input. */
1100
+ supportsVision?: boolean;
1101
+ }
1102
+
1103
+ /**
1104
+ * Rate-limit configuration for AI prompts (presence implies enabled).
1105
+ */
1106
+ export interface IAiRateLimit {
1107
+ /** Explicitly disable while keeping the config (default: enabled when present). */
1108
+ enabled?: boolean;
1109
+
1110
+ /** Maximum number of prompts per window per user. @default 20 */
1111
+ max?: number;
1112
+
1113
+ /** Window length in seconds. @default 60 */
1114
+ windowSeconds?: number;
1115
+ }
1116
+
1117
+ /**
1118
+ * Configuration for the AI assistant module (presence implies enabled).
1119
+ *
1120
+ * The AI module adds a prompt orchestrator with emulated/native tool calling and
1121
+ * database-backed LLM connections (managed at runtime by admins). Omit the block
1122
+ * to disable the module entirely; set `enabled: false` to keep config but disable.
1123
+ *
1124
+ * @example
1125
+ * ```typescript
1126
+ * ai: {
1127
+ * maxIterations: 5,
1128
+ * rateLimit: { max: 20, windowSeconds: 60 },
1129
+ * defaultConnection: {
1130
+ * name: 'Default LLM',
1131
+ * baseUrl: 'https://llm.example.com/v1',
1132
+ * model: 'gpt-oss-120b',
1133
+ * apiKeyEnv: 'AI_API_KEY',
1134
+ * },
1135
+ * }
1136
+ * ```
1137
+ */
1138
+ export interface IAi {
1139
+ /**
1140
+ * Optional SSRF allowlist for connection base URLs. When set (non-empty), the
1141
+ * provider only sends requests to these hosts (matched by `host` incl. port, or
1142
+ * bare `hostname`); unset → permissive (so local providers like Ollama on localhost
1143
+ * work out of the box). `baseUrl` is admin-only, so this guards a compromised or
1144
+ * misconfigured admin, not end-user input.
1145
+ * @example ['llm.example.com', 'localhost:11434']
1146
+ */
1147
+ allowedBaseUrlHosts?: string[];
1148
+
1149
+ /**
1150
+ * Persist an audit record (`aiInteractions`) for every prompt run (admin-readable).
1151
+ * @default false
1152
+ */
1153
+ audit?: boolean;
1154
+
1155
+ /**
1156
+ * Token/prompt budgets for AI prompts, enforced before a run (HTTP 429 + translated
1157
+ * message). Requires `audit` (usage is read from `aiInteractions`). All limits are
1158
+ * optional — a missing or `0` limit means unlimited (only the LLM's own limit then
1159
+ * applies). These are the DEFAULTS; admins can override per user/tenant at runtime
1160
+ * (`aiBudgetLimits`, `CoreAiBudgetService`).
1161
+ */
1162
+ budget?: {
1163
+ /** Reset window. @default 'day' */
1164
+ period?: 'day' | 'month' | 'none';
1165
+ /** Default limit applied to a whole tenant (sum of all its users). */
1166
+ tenant?: { maxPrompts?: number; maxTokens?: number };
1167
+ /** Default limit applied per user. */
1168
+ user?: { maxPrompts?: number; maxTokens?: number };
1169
+ };
1170
+
1171
+ /**
1172
+ * Confirmation policy for mutating tool actions (create/update/delete).
1173
+ * `destructive` tools always require confirmation regardless of this policy.
1174
+ */
1175
+ confirmation?: {
1176
+ mutating?: {
1177
+ /** Admin default: require confirmation for mutating actions. @default false */
1178
+ default?: boolean;
1179
+ /** When true, the client cannot override the default (always require). @default false */
1180
+ enforced?: boolean;
1181
+ };
1182
+ };
1183
+
1184
+ /**
1185
+ * System documentation injected into the system prompt to inform the LLM
1186
+ * (official docs, domain rules, API description). For dynamic/RAG docs, override
1187
+ * `CoreAiPromptBuilderService.getDocumentation()` instead.
1188
+ */
1189
+ documentation?: string;
1190
+
1191
+ /** Optional one-time seed for a default connection (see {@link IAiDefaultConnection}). */
1192
+ defaultConnection?: IAiDefaultConnection;
1193
+
1194
+ /**
1195
+ * Default execution mode when the client does not specify one.
1196
+ * `auto` (reactive loop) or `plan` (validate all permissions, then execute atomically).
1197
+ * @default 'auto'
1198
+ */
1199
+ defaultMode?: 'auto' | 'plan';
1200
+
1201
+ /** Explicitly disable while keeping the config (default: enabled when present). */
1202
+ enabled?: boolean;
1203
+
1204
+ /**
1205
+ * Pass-phrase used to derive the AES-256-GCM key for encrypting connection API
1206
+ * keys. Falls back to `NSC__AI__ENCRYPTION_SECRET` / `SECRETS_ENCRYPTION_KEY`.
1207
+ * MUST be set to a random 32+ char value in production.
1208
+ */
1209
+ encryptionSecret?: string;
1210
+
1211
+ /**
1212
+ * Fallback total context window (input + output tokens) used to budget the
1213
+ * assembled session messages when a connection has no `contextWindow` set. When the
1214
+ * conversation (per user/session) would overflow, the oldest history turns are
1215
+ * dropped and oversized payloads truncated before the LLM call.
1216
+ * @default 8192
1217
+ */
1218
+ contextWindow?: number;
1219
+
1220
+ /**
1221
+ * Optional config for the `ClaudeCliProvider` (LLM backend that invokes a local
1222
+ * `claude` CLI binary). Only consumed when a connection's `providerType` is
1223
+ * `claude-cli` or the provider is registered explicitly.
1224
+ */
1225
+ claudeCli?: {
1226
+ /** Path/name of the Claude CLI binary. @default 'claude' */
1227
+ bin?: string;
1228
+ /** Extra CLI flags appended verbatim to every invocation (admin-only). */
1229
+ extraArgs?: string[];
1230
+ /** Optional `--budget` cap (USD) appended to every invocation. */
1231
+ maxBudgetUsd?: number;
1232
+ };
1233
+
1234
+ /**
1235
+ * LLM-driven context compaction: when a session would overflow the connection's
1236
+ * context window, the oldest non-system/non-last turns are summarized by a single
1237
+ * LLM call (via the same connection's provider) and REPLACED by a one-paragraph
1238
+ * summary system message — instead of being dropped. Falls back to the hard trim
1239
+ * path on any error. Disable with `false`.
1240
+ * @default true
1241
+ */
1242
+ compaction?: boolean;
1243
+
1244
+ /**
1245
+ * Defer the parameter schemas of tools out of the system prompt. With many tools
1246
+ * the JSON-Schema catalog dominates the prompt; with `deferToolSchemas: true`
1247
+ * the system prompt only lists tool names + short descriptions and the built-in
1248
+ * `search_tools` meta-tool lets the model fetch a single tool's schema on demand.
1249
+ * @default false
1250
+ */
1251
+ deferToolSchemas?: boolean;
1252
+
1253
+ /** Maximum number of agent-loop iterations (tool round-trips). @default 5 */
1254
+ maxIterations?: number;
1255
+
1256
+ /** Maximum characters of a tool-results payload fed back to the model. @default 12000 */
1257
+ maxToolResultChars?: number;
1258
+
1259
+ /**
1260
+ * Governed self-improvement loop for the system prompt. The orchestrator records
1261
+ * failure signals (tool errors, not-permitted calls); recurring patterns become
1262
+ * learned hints. By default hints are `suggested` and only affect the prompt once an
1263
+ * admin approves them; `autoApply` auto-approves them. Learning never relaxes
1264
+ * permissions — hints only add textual guidance.
1265
+ */
1266
+ promptLearning?: {
1267
+ /** Auto-approve learned hints instead of requiring admin approval. @default false */
1268
+ autoApply?: boolean;
1269
+ /** Enable the learning loop. @default true (when an `ai` block is present) */
1270
+ enabled?: boolean;
1271
+ /** Occurrences before a suggested hint is auto-approved (with `autoApply`). @default 1 */
1272
+ minOccurrences?: number;
1273
+ };
1274
+
1275
+ /**
1276
+ * Expose the tool registry as an MCP server at `/ai/mcp` (Streamable HTTP) for
1277
+ * external MCP clients. Requires `@modelcontextprotocol/sdk`. Boolean shorthand.
1278
+ *
1279
+ * `oauth: true` additionally enables the OAuth 2.1 layer (dynamic client
1280
+ * registration + PKCE) so generic MCP clients can authenticate; mount the OAuth
1281
+ * router in `main.ts` via `mountAiMcpOAuth(app)` (see INTEGRATION-CHECKLIST).
1282
+ * Without it, MCP authenticates via the existing Bearer/session token.
1283
+ * @default false
1284
+ */
1285
+ mcp?: boolean | { enabled?: boolean; oauth?: boolean; oauthSecret?: string };
1286
+
1287
+ /** Rate limiting for prompts. */
1288
+ rateLimit?: IAiRateLimit;
1289
+
1290
+ /** Base system prompt prepended to every conversation. */
1291
+ systemPrompt?: string;
1292
+ }
1293
+
1048
1294
  /**
1049
1295
  * Options for the server
1050
1296
  */
1051
1297
  export interface IServerOptions {
1298
+ /**
1299
+ * Configuration for the AI assistant module.
1300
+ *
1301
+ * Presence implies enabled (omit to disable, `{ enabled: false }` to keep config
1302
+ * but disable). Adds the prompt orchestrator, the tool registry and admin-managed
1303
+ * database-backed LLM connections.
1304
+ *
1305
+ * @see IAi
1306
+ */
1307
+ ai?: boolean | IAi;
1308
+
1052
1309
  /**
1053
1310
  * Base URL of the frontend/app application.
1054
1311
  *
@@ -2866,6 +3123,61 @@ interface IBetterAuthWithPasskey extends IBetterAuthBase {
2866
3123
  * @since 11.22.0
2867
3124
  */
2868
3125
  export interface ICoreModuleOverrides {
3126
+ /**
3127
+ * Override AI module collaborators with project-specific subclasses.
3128
+ *
3129
+ * - `budgetService` must extend `CoreAiBudgetService`
3130
+ * - `connectionResolver` must extend `CoreAiConnectionResolverService`
3131
+ * - `connectionService` must extend `CoreAiConnectionService`
3132
+ * - `controller` must extend `CoreAiController`
3133
+ * - `conversationService` must extend `CoreAiConversationService`
3134
+ * - `interactionService` must extend `CoreAiInteractionService`
3135
+ * - `mcpClientService` must extend `CoreAiMcpClientService`
3136
+ * - `modeService` must extend `CoreAiModeService`
3137
+ * - `placeholderRegistry` must extend `CoreAiPlaceholderRegistry`
3138
+ * - `preferenceService` must extend `CoreAiConnectionPreferenceService`
3139
+ * - `promptBuilder` must extend `CoreAiPromptBuilderService`
3140
+ * - `promptHintService` must extend `CoreAiPromptHintService`
3141
+ * - `promptService` must extend `CoreAiPromptService`
3142
+ * - `resolver` must extend `CoreAiResolver` (re-declare GraphQL decorators)
3143
+ * - `service` must extend `CoreAiService`
3144
+ * - `slotService` must extend `CoreAiSlotService`
3145
+ * - `toolGrantService` must extend `CoreAiToolGrantService`
3146
+ * - `toolPolicyService` must extend `CoreAiToolPolicyService`
3147
+ *
3148
+ * @example
3149
+ * ```typescript
3150
+ * {
3151
+ * ai: {
3152
+ * service: MyAiService,
3153
+ * resolver: MyAiResolver,
3154
+ * connectionResolver: MyConnectionResolver,
3155
+ * slotService: MySlotService,
3156
+ * },
3157
+ * }
3158
+ * ```
3159
+ */
3160
+ ai?: {
3161
+ budgetService?: Type<any>;
3162
+ connectionResolver?: Type<any>;
3163
+ connectionService?: Type<any>;
3164
+ controller?: Type<any>;
3165
+ conversationService?: Type<any>;
3166
+ interactionService?: Type<any>;
3167
+ mcpClientService?: Type<any>;
3168
+ modeService?: Type<any>;
3169
+ placeholderRegistry?: Type<any>;
3170
+ preferenceService?: Type<any>;
3171
+ promptBuilder?: Type<any>;
3172
+ promptHintService?: Type<any>;
3173
+ promptService?: Type<any>;
3174
+ resolver?: Type<any>;
3175
+ service?: Type<any>;
3176
+ slotService?: Type<any>;
3177
+ toolGrantService?: Type<any>;
3178
+ toolPolicyService?: Type<any>;
3179
+ };
3180
+
2869
3181
  /**
2870
3182
  * Override BetterAuth controller and/or resolver.
2871
3183
  *
@@ -0,0 +1,220 @@
1
+ # AI Module Integration Checklist
2
+
3
+ ## Reference Implementation
4
+
5
+ - Local (npm): `node_modules/@lenne.tech/nest-server/src/server/modules/ai/`
6
+ - Local (vendor): `src/server/modules/ai/` in this repo
7
+ - GitHub: https://github.com/lenneTech/nest-server/tree/develop/src/server/modules/ai
8
+
9
+ ## Overview
10
+
11
+ The AI module is **auto-registered by `CoreModule.forRoot()`** when an `ai` config
12
+ block is present (presence implies enabled). You only need to:
13
+
14
+ 1. add the `ai` config block,
15
+ 2. set an encryption secret,
16
+ 3. create one or more AI tools (project-specific capabilities),
17
+ 4. register your tools in a module.
18
+
19
+ No manual `CoreAiModule` import is required for the default setup.
20
+
21
+ ## Required Steps
22
+
23
+ ### 1. Configure the module (`config.env.ts`)
24
+
25
+ Add an `ai` block to each relevant environment:
26
+
27
+ ```typescript
28
+ ai: {
29
+ encryptionSecret: process.env.NSC__AI__ENCRYPTION_SECRET, // REQUIRED in prod (32+ chars)
30
+ maxIterations: 5,
31
+ rateLimit: { max: 20, windowSeconds: 60 },
32
+ defaultConnection: { // optional one-time seed
33
+ name: 'Default LLM',
34
+ baseUrl: process.env.AI_BASE_URL, // any OpenAI-compatible endpoint
35
+ model: process.env.AI_MODEL,
36
+ apiKeyEnv: 'AI_API_KEY', // prefer env over inline apiKey
37
+ supportsNativeTools: false, // set per the backend's actual support
38
+ },
39
+ }
40
+ ```
41
+
42
+ **WHY the encryption secret:** connection API keys are AES-256-GCM encrypted at
43
+ rest. Without `ai.encryptionSecret` / `NSC__AI__ENCRYPTION_SECRET` /
44
+ `SECRETS_ENCRYPTION_KEY`, an insecure development default is used (logged as a
45
+ warning) in non-production environments. In **production/staging the app refuses to
46
+ boot** when AI is enabled but no secret is set (mirrors the email/cookie production
47
+ guards) — so a missing secret can never silently ship. The same applies to the MCP
48
+ OAuth signing secret when `ai.mcp.oauth` is enabled.
49
+
50
+ ### 2. Set the LLM API key (environment)
51
+
52
+ ```bash
53
+ # .env
54
+ AI_API_KEY=...
55
+ AI_BASE_URL=https://your-openai-compatible-endpoint/v1
56
+ NSC__AI__ENCRYPTION_SECRET=<random 32+ char string>
57
+ ```
58
+
59
+ Admins can also store/rotate keys at runtime via the connection CRUD endpoints
60
+ (stored encrypted; env is only the fallback).
61
+
62
+ ### 3. Create AI tools — REQUIRED for the assistant to do anything domain-specific
63
+
64
+ > **AI agents / new integrators read this first:** the AI module has **no automatic
65
+ > access to your domain models**. Without explicitly registered tools, every domain
66
+ > question (e.g. "show me the latest orders", "find user X") gets the answer
67
+ > _"I don't have a tool to do that"_ — that's the LLM correctly reporting its
68
+ > capabilities, NOT a bug. **You must write a tool for every domain operation that
69
+ > should be reachable from chat.**
70
+
71
+ **Create:** `src/server/modules/ai/tools/<your>.tool.ts`
72
+ **Copy from:** the reference tools shipped at
73
+ `node_modules/@lenne.tech/nest-server/src/server/modules/ai/tools/` (`find-users.tool.ts`,
74
+ `get-user.tool.ts`, `delete-user.tool.ts`, `update-user-job-title.tool.ts`) — those
75
+ demonstrate read / restricted-read / destructive-write / mutating-write patterns.
76
+
77
+ When copying:
78
+
79
+ - Replace relative framework imports `'../../../../core/...'` with the npm specifier
80
+ `'@lenne.tech/nest-server'`.
81
+ - Adjust the relative path to your own services (e.g. `'../../user/user.service'`
82
+ becomes `'../user/user.service'` if you copy `tools/` one level shallower; the
83
+ reference structure assumes `tools/` is a sub-folder of `ai/`).
84
+ - For each tool: declare `name` / `description` / `parameters` (JSON-Schema) /
85
+ `roles`; flag mutating ones with `mutating: true` and irreversible ones with
86
+ `destructive: true`.
87
+ - Implement `execute(args, context)` by **always** routing through a `CrudService`
88
+ with `context.serviceOptions` — NOT directly through `Model.find()` etc.
89
+ CrudService preserves the caller's `@Restricted` / `@Roles` / `securityCheck()`
90
+ guarantees. Direct Model access bypasses the permission layer and IS a security
91
+ bug.
92
+
93
+ ### 4. Register your tools in a module — REQUIRED
94
+
95
+ **Create:** `src/server/modules/ai/ai-tools.module.ts` (copy from the framework
96
+ reference at `node_modules/@lenne.tech/nest-server/src/server/modules/ai/ai-tools.module.ts`)
97
+ and import it in `server.module.ts`:
98
+
99
+ ```typescript
100
+ // server.module.ts → imports: [ … , AiToolsModule ]
101
+ ```
102
+
103
+ Each tool subclass listed in the module's `providers: []` self-registers in the
104
+ global `AiToolRegistry` via the `AiTool` base class. The registry is provided
105
+ globally by the auto-registered `CoreAiModule`, so your module only needs to
106
+ import whatever services your tools depend on (e.g. `UserModule`).
107
+
108
+ A consumer project without `AiToolsModule` (or with an empty `providers: []`)
109
+ will boot fine — the AI just won't have any domain tools to call.
110
+
111
+ ### 5. (Optional) Override collaborators
112
+
113
+ For custom behaviour, pass subclasses via `CoreModule.forRoot()`:
114
+
115
+ ```typescript
116
+ CoreModule.forRoot(envConfig, {
117
+ ai: { service: MyAiService, resolver: MyAiResolver, promptBuilder: MyPromptBuilder },
118
+ });
119
+ ```
120
+
121
+ When overriding the resolver, **re-declare all GraphQL decorators**
122
+ (`@Mutation`/`@Query`/`@Roles`) — the schema is built from decorators at compile
123
+ time.
124
+
125
+ ## Advanced configuration (optional)
126
+
127
+ ```typescript
128
+ ai: {
129
+ defaultMode: 'auto', // or 'plan' (validate all permissions, then execute atomically)
130
+ documentation: '…', // system docs injected into the prompt (or override getDocumentation())
131
+ confirmation: { mutating: { default: false, enforced: false } }, // require confirmation for create/update/delete
132
+ audit: true, // persist runs to aiInteractions (required for budget)
133
+ budget: { // per-user/tenant token limits (defaults; admins override per user/tenant)
134
+ period: 'day', // 'day' | 'month' | 'none'
135
+ user: { maxTokens: 50000 }, // 0/undefined = unlimited
136
+ tenant: { maxTokens: 2000000 },
137
+ },
138
+ contextWindow: 8192, // fallback when a connection has no auto-detected window
139
+ maxToolResultChars: 12000, // cap tool-results fed back to the model
140
+ promptLearning: { autoApply: false },// governed self-improvement (admins approve learned hints)
141
+ mcp: { oauth: true, oauthSecret: process.env.NSC__AI__ENCRYPTION_SECRET },
142
+ }
143
+ ```
144
+
145
+ - **Plan mode / pre-flight permissions:** give data-mutating tools an `authorize()` that
146
+ checks permission WITHOUT mutating (e.g. load the record + verify ownership). Plan mode
147
+ runs it for every step before executing anything.
148
+ - **Confirmation:** mark create/update/delete tools `mutating: true` and irreversible ones
149
+ `destructive: true`.
150
+ - **Self-optimizing prompts:** the system prompt is built from editable, keyed slots —
151
+ admins customize any slot via `aiSlots` (`/ai/slots`, tenant-scoped) and review the
152
+ learned hints the system records on tool failures via `aiPromptHints` (`/ai/prompt-hints`).
153
+ Both are `@Roles(ADMIN)`; build an admin UI with the `useLtAiAdmin` composable
154
+ (`listEffectiveSlots` returns framework defaults + tenant overrides + custom slots with
155
+ `isSystem`/`isOverride` flags; `resetSlot` undoes an override). Hints never relax
156
+ permissions.
157
+ - **User prompts ("Vorlagen"):** users author re-usable short prompts for themselves
158
+ (private) or their tenant (public) via `aiPrompts` (`/ai/prompts`, `useLtAiPrompts`).
159
+ Inserted into the chat input by a picker.
160
+ - **Placeholders:** `{{placeholder}}` tokens in both system slots AND user prompts are
161
+ resolved at run time by `CoreAiPlaceholderRegistry`. The current list is served via
162
+ `GET /ai/placeholders` (`useLtAiPlaceholders`) — your slot/prompt editors should render
163
+ it dynamically so project-added placeholders show up without a frontend change. Register
164
+ project-specific placeholders via `placeholderRegistry.register({ name, description, resolve })`.
165
+ - **Context window:** detected automatically per connection and persisted; no setup needed.
166
+ Override per connection (`contextWindow`) or globally (`ai.contextWindow`) if a backend
167
+ isn't recognized.
168
+
169
+ ### MCP server (only when `ai.mcp.enabled` or `ai.mcp` is truthy)
170
+
171
+ **Install the MCP SDK** in your project:
172
+
173
+ ```bash
174
+ pnpm add @modelcontextprotocol/sdk
175
+ # or: npm install @modelcontextprotocol/sdk
176
+ ```
177
+
178
+ The SDK is a peer-style optional dependency — it is `import()`-ed lazily by
179
+ `CoreAiMcpController` only when an MCP request actually arrives, so projects
180
+ that don't enable MCP pay no install cost. When `ai.mcp` is set but the SDK
181
+ is not installed, `/ai/mcp` returns **503 Service Unavailable** with an
182
+ install-hint message instead of a 500 trace.
183
+
184
+ ### MCP OAuth 2.1 (only when `ai.mcp.oauth` is enabled)
185
+
186
+ **Edit `main.ts`** (after `app.init()`):
187
+
188
+ ```typescript
189
+ import { mountAiMcpOAuth } from '@lenne.tech/nest-server';
190
+ await mountAiMcpOAuth(app, { baseUrl: process.env.BASE_URL });
191
+ ```
192
+
193
+ Override `CoreAiMcpOAuthService.authorizeConsent()` with your login/consent UI (the only
194
+ browser-interactive step). All other OAuth pieces (tokens, PKCE, stores) are built in.
195
+
196
+ ## Verification Checklist
197
+
198
+ - [ ] Build succeeds (`pnpm run build`)
199
+ - [ ] Tests pass (`pnpm test`)
200
+ - [ ] `findAiConnections` / `getAiConnection` etc. are admin-only and never return `apiKeyEncrypted`
201
+ - [ ] A created connection's `hasApiKey` is `true`, the key is stored encrypted
202
+ - [ ] `aiPrompt` works for an authenticated user
203
+ - [ ] With multiple connections, resolution honors the chain (default → tenant → user → client → enforced)
204
+ - [ ] `aiAvailableConnections` returns a non-sensitive list (no `apiKey`/`baseUrl`) flagging `selected`/`locked`
205
+ - [ ] `aiSetUserConnection` rejects a connection not available to the caller's tenant
206
+ - [ ] With zero connections, `aiPrompt` returns a denied "unavailable" response (no crash)
207
+ - [ ] Your tools appear in `AiToolRegistry.all()` and are role-filtered correctly
208
+ - [ ] Tools route through `CrudService` (no raw `.lean()`/aggregate results sent to the LLM)
209
+
210
+ ## Common Mistakes
211
+
212
+ | Mistake | Symptom | Fix |
213
+ | --------------------------------------------- | ------------------------------------------------------------- | --------------------------------------------------------- |
214
+ | No `ai` config block | Module not loaded, `aiPrompt` missing from schema | Add an `ai` block (presence implies enabled) |
215
+ | No encryption secret in prod | **App refuses to boot** (throws); dev/local only warns | Set `NSC__AI__ENCRYPTION_SECRET` (32+ chars) |
216
+ | Encryption secret changed after keys stored | Boot logs "key(s) could not be decrypted"; those prompts fail | Re-enter the API key for the listed connections |
217
+ | Tool returns `.lean()`/aggregate data | `@Restricted` fields leak into the LLM context | Route through `CrudService` with `context.serviceOptions` |
218
+ | Tool not registered | Tool never offered to the LLM | Declare it as a provider in a module (extends `AiTool`) |
219
+ | Overridden resolver method missing decorators | Method absent from GraphQL schema | Re-declare `@Mutation`/`@Query`/`@Roles` in the override |
220
+ | Storing a real API key in `config.env.ts` | Secret committed to the repo | Use `apiKeyEnv` or the runtime connection CRUD |