@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,107 @@
1
+ import { Field, Int, ObjectType } from '@nestjs/graphql';
2
+
3
+ import { Restricted } from '../../../common/decorators/restricted.decorator';
4
+ import { RoleEnum } from '../../../common/enums/role.enum';
5
+
6
+ /**
7
+ * Compact token-budget summary attached to every prompt response.
8
+ *
9
+ * Kept small on purpose: this prompt's token cost plus the remaining/used totals
10
+ * and the reset time for the binding (user) scope. The full breakdown (user +
11
+ * tenant scopes, prompts + tokens) is available via the `aiUsage` query / `GET /ai/usage`.
12
+ */
13
+ @ObjectType({ description: 'Compact token-budget summary for a prompt response' })
14
+ @Restricted(RoleEnum.S_EVERYONE)
15
+ export class CoreAiBudgetSummary {
16
+ /**
17
+ * Effective token limit for the binding scope (resolution: user → tenant → LLM
18
+ * context window → null = no limit). Frontends use this to drive a usage progress
19
+ * bar; null/undefined = no limit → hide the bar.
20
+ */
21
+ @Field(() => Int, { description: 'Effective token limit (null = no limit)', nullable: true })
22
+ maxTokens?: number;
23
+
24
+ /** Tokens this prompt consumed. */
25
+ @Field(() => Int, { description: 'Tokens consumed by this prompt', nullable: true })
26
+ promptTokens?: number;
27
+
28
+ /** Remaining tokens in the current period (null = unlimited). */
29
+ @Field(() => Int, { description: 'Remaining tokens in the current period (null = unlimited)', nullable: true })
30
+ remainingTokens?: number;
31
+
32
+ /** When the current period resets (null = never). */
33
+ @Field(() => Date, { description: 'When the current budget period resets (null = never)', nullable: true })
34
+ resetAt?: Date;
35
+
36
+ /**
37
+ * Which scope yielded {@link maxTokens} ('user', 'tenant' or 'llm').
38
+ */
39
+ @Field(() => String, { description: "Which scope yielded the limit ('user', 'tenant' or 'llm')", nullable: true })
40
+ scope?: string;
41
+
42
+ /** Tokens used so far in the current period (user scope). */
43
+ @Field(() => Int, { description: 'Tokens used so far in the current period', nullable: true })
44
+ usedTokens?: number;
45
+ }
46
+
47
+ /**
48
+ * Token/prompt usage for a single scope (user or tenant).
49
+ */
50
+ @ObjectType({ description: 'AI usage for a single scope (user or tenant)' })
51
+ @Restricted(RoleEnum.S_EVERYONE)
52
+ export class CoreAiUsageScope {
53
+ /** Maximum prompts per period (null = unlimited). */
54
+ @Field(() => Int, { description: 'Maximum prompts per period (null = unlimited)', nullable: true })
55
+ maxPrompts?: number;
56
+
57
+ /** Maximum tokens per period (null = unlimited). */
58
+ @Field(() => Int, { description: 'Maximum tokens per period (null = unlimited)', nullable: true })
59
+ maxTokens?: number;
60
+
61
+ /** Reset period ('day', 'month' or 'none'). */
62
+ @Field(() => String, { description: "Reset period ('day', 'month', 'none')" })
63
+ period: string;
64
+
65
+ /** Remaining prompts (null = unlimited). */
66
+ @Field(() => Int, { description: 'Remaining prompts (null = unlimited)', nullable: true })
67
+ remainingPrompts?: number;
68
+
69
+ /** Remaining tokens (null = unlimited). */
70
+ @Field(() => Int, { description: 'Remaining tokens (null = unlimited)', nullable: true })
71
+ remainingTokens?: number;
72
+
73
+ /** When the period resets (null = never). */
74
+ @Field(() => Date, { description: 'When the period resets (null = never)', nullable: true })
75
+ resetAt?: Date;
76
+
77
+ /** Scope id (user id or tenant id). */
78
+ @Field(() => String, { description: 'Scope reference id', nullable: true })
79
+ refId?: string;
80
+
81
+ /** Scope name ('user' or 'tenant'). */
82
+ @Field(() => String, { description: "Scope: 'user' or 'tenant'" })
83
+ scope: string;
84
+
85
+ /** Prompts used in the current period. */
86
+ @Field(() => Int, { description: 'Prompts used in the current period' })
87
+ usedPrompts: number;
88
+
89
+ /** Tokens used in the current period. */
90
+ @Field(() => Int, { description: 'Tokens used in the current period' })
91
+ usedTokens: number;
92
+ }
93
+
94
+ /**
95
+ * Full AI usage info: user scope plus the tenant scope when a tenant context exists.
96
+ */
97
+ @ObjectType({ description: 'Full AI token usage for the current user (and tenant)' })
98
+ @Restricted(RoleEnum.S_EVERYONE)
99
+ export class CoreAiUsageInfo {
100
+ /** Tenant-scope usage (present when a tenant context exists). */
101
+ @Field(() => CoreAiUsageScope, { description: 'Tenant-scope usage', nullable: true })
102
+ tenant?: CoreAiUsageScope;
103
+
104
+ /** User-scope usage. */
105
+ @Field(() => CoreAiUsageScope, { description: 'User-scope usage', nullable: true })
106
+ user?: CoreAiUsageScope;
107
+ }
@@ -0,0 +1,29 @@
1
+ import { Field, Int, ObjectType } from '@nestjs/graphql';
2
+
3
+ import { Restricted } from '../../../common/decorators/restricted.decorator';
4
+ import { RoleEnum } from '../../../common/enums/role.enum';
5
+
6
+ /**
7
+ * Token usage of an AI prompt (best effort, summed across agent-loop iterations).
8
+ */
9
+ @ObjectType({ description: 'Token usage of an AI prompt' })
10
+ @Restricted(RoleEnum.S_EVERYONE)
11
+ export class CoreAiUsage {
12
+ /**
13
+ * Number of completion (output) tokens.
14
+ */
15
+ @Field(() => Int, { description: 'Number of completion tokens', nullable: true })
16
+ completionTokens?: number;
17
+
18
+ /**
19
+ * Number of prompt (input) tokens.
20
+ */
21
+ @Field(() => Int, { description: 'Number of prompt tokens', nullable: true })
22
+ promptTokens?: number;
23
+
24
+ /**
25
+ * Total number of tokens.
26
+ */
27
+ @Field(() => Int, { description: 'Total number of tokens', nullable: true })
28
+ totalTokens?: number;
29
+ }
@@ -0,0 +1,240 @@
1
+ import { BadGatewayException, Logger, ServiceUnavailableException } from '@nestjs/common';
2
+ import { spawn } from 'node:child_process';
3
+ import { tmpdir } from 'node:os';
4
+
5
+ import { ConfigService } from '../../../common/services/config.service';
6
+ import { ErrorCode } from '../../error-code';
7
+ import {
8
+ ILlmProvider,
9
+ LlmCapabilities,
10
+ LlmCompletionOptions,
11
+ LlmMessage,
12
+ LlmResponse,
13
+ LlmToolSchema,
14
+ } from '../interfaces/llm-provider.interface';
15
+ import { ResolvedAiConnection } from '../interfaces/resolved-ai-connection.interface';
16
+
17
+ /**
18
+ * Provider that drives the local Claude Code CLI (`claude`) as an LLM backend.
19
+ *
20
+ * Claude Code is an agentic CLI, not an HTTP completion endpoint, so this provider
21
+ * shells out to it in non-interactive print mode and parses the single JSON result.
22
+ * It is **opt-in**: register it on the {@link LlmProviderFactory} from a consumer
23
+ * module, then create a connection with `providerType: 'claude-cli'`.
24
+ *
25
+ * ```typescript
26
+ * factory.registerBuilder('claude-cli', (conn) => new ClaudeCliProvider(conn));
27
+ * ```
28
+ *
29
+ * ## Security model
30
+ *
31
+ * The CLI is invoked with **all of its own tools disabled** (`--tools ""`), so
32
+ * Claude Code cannot read files, run shell commands, or reach the network on its
33
+ * own. Tool calling for the orchestrator is therefore **emulated** (capabilities
34
+ * `nativeTools: false`) — exactly like any other emulated backend, the orchestrator
35
+ * injects the tool catalog into the system prompt and executes tools itself through
36
+ * `CrudService` with the caller's permissions. Additional hardening:
37
+ *
38
+ * - `spawn` is called with an **argument array (never a shell string)**, so prompt
39
+ * content can never be interpreted as a shell command (no command injection).
40
+ * - The conversation is written to **stdin**, not passed as an argv element.
41
+ * - The child runs in a neutral working directory ({@link tmpdir}) so no project
42
+ * `CLAUDE.md`/settings are auto-discovered into the context.
43
+ * - `--system-prompt` **replaces** Claude Code's default agent prompt with the
44
+ * orchestrator's prompt, and `--no-session-persistence` avoids writing session files.
45
+ * - The call is bounded by a timeout; the child is killed if it overruns.
46
+ *
47
+ * The connection's `model` is passed to `--model` (e.g. `opus`, `sonnet`, `haiku`,
48
+ * or a full model id). `baseUrl` is unused (auth is the CLI's own login / API key);
49
+ * if `apiKey` is set it is forwarded to the child as `ANTHROPIC_API_KEY`.
50
+ *
51
+ * Optional config (`ai.claudeCli`): `{ bin?: string; extraArgs?: string[]; maxBudgetUsd?: number }`.
52
+ */
53
+ export class ClaudeCliProvider implements ILlmProvider {
54
+ readonly capabilities: LlmCapabilities = { jsonResponse: false, nativeTools: false, systemPrompt: true };
55
+ readonly name = 'claude-cli';
56
+
57
+ protected readonly defaultTimeoutMs: number;
58
+ private readonly logger = new Logger(ClaudeCliProvider.name);
59
+
60
+ constructor(protected readonly connection: ResolvedAiConnection) {
61
+ this.defaultTimeoutMs = connection.timeoutMs ?? 120_000;
62
+ }
63
+
64
+ /**
65
+ * Run a completion via `claude -p --output-format json`. `tools` is intentionally
66
+ * ignored — the CLI runs tool-free and the orchestrator emulates tool calling via
67
+ * the (replaced) system prompt. Maps spawn/exit/parse failures to a gateway error.
68
+ */
69
+ async chat(messages: LlmMessage[], _tools: LlmToolSchema[], options?: LlmCompletionOptions): Promise<LlmResponse> {
70
+ const system = messages
71
+ .filter((m) => m.role === 'system')
72
+ .map((m) => m.content)
73
+ .join('\n\n');
74
+ // Flatten the remaining turns into a single labelled transcript for stdin. The
75
+ // emulated 'tool' role is rendered as tool results the model can read.
76
+ const transcript = messages
77
+ .filter((m) => m.role !== 'system')
78
+ .map((m) => `${this.labelFor(m.role)}:\n${m.content}`)
79
+ .join('\n\n');
80
+
81
+ const args = this.buildArgs(system, options);
82
+ const timeoutMs = options?.timeoutMs ?? this.defaultTimeoutMs;
83
+
84
+ let stdout: string;
85
+ try {
86
+ stdout = await this.run(args, transcript, timeoutMs);
87
+ } catch (err) {
88
+ this.logger.warn(`Claude CLI invocation for "${this.connection.name}" failed: ${(err as Error).message}`);
89
+ throw new ServiceUnavailableException(ErrorCode.AI_PROVIDER_ERROR);
90
+ }
91
+
92
+ let parsed: {
93
+ is_error?: boolean;
94
+ result?: string;
95
+ subtype?: string;
96
+ usage?: { input_tokens?: number; output_tokens?: number };
97
+ };
98
+ try {
99
+ parsed = JSON.parse(stdout);
100
+ } catch {
101
+ this.logger.warn(`Claude CLI returned non-JSON output for "${this.connection.name}": ${stdout.slice(0, 300)}`);
102
+ throw new BadGatewayException(ErrorCode.AI_PROVIDER_ERROR);
103
+ }
104
+
105
+ if (parsed.is_error || parsed.subtype !== 'success' || typeof parsed.result !== 'string') {
106
+ this.logger.warn(`Claude CLI reported an error for "${this.connection.name}": ${stdout.slice(0, 300)}`);
107
+ throw new BadGatewayException(ErrorCode.AI_PROVIDER_ERROR);
108
+ }
109
+
110
+ const promptTokens = parsed.usage?.input_tokens;
111
+ const completionTokens = parsed.usage?.output_tokens;
112
+ return {
113
+ raw: parsed,
114
+ text: parsed.result,
115
+ usage: {
116
+ completionTokens,
117
+ promptTokens,
118
+ totalTokens:
119
+ promptTokens !== undefined || completionTokens !== undefined
120
+ ? (promptTokens ?? 0) + (completionTokens ?? 0)
121
+ : undefined,
122
+ },
123
+ };
124
+ }
125
+
126
+ /**
127
+ * Claude models all expose a large context window. Return the model-appropriate
128
+ * size automatically (default 200k; 1M for the Opus 4.x 1m-context variants).
129
+ */
130
+ async detectContextWindow(): Promise<number | undefined> {
131
+ const model = (this.connection.model || '').toLowerCase();
132
+ return model.includes('[1m]') || model.includes('-1m') ? 1_000_000 : 200_000;
133
+ }
134
+
135
+ /**
136
+ * Build the argv for the CLI. Override to customize flags. Tools are always
137
+ * disabled (`--tools ""`) — do not re-enable them unless you fully trust the model
138
+ * with local file/shell access.
139
+ */
140
+ protected buildArgs(system: string, options?: LlmCompletionOptions): string[] {
141
+ const args = [
142
+ '-p',
143
+ '--output-format',
144
+ 'json',
145
+ // Disable ALL of Claude Code's own tools — it must be a pure text generator.
146
+ '--tools',
147
+ '',
148
+ '--no-session-persistence',
149
+ '--model',
150
+ options?.model ?? this.connection.model,
151
+ ];
152
+ if (system) {
153
+ // Replace (not append) Claude Code's default agent prompt with ours.
154
+ args.push('--system-prompt', system);
155
+ }
156
+ const maxBudgetUsd = ConfigService.get<number>('ai.claudeCli.maxBudgetUsd');
157
+ if (typeof maxBudgetUsd === 'number' && maxBudgetUsd > 0) {
158
+ args.push('--max-budget-usd', String(maxBudgetUsd));
159
+ }
160
+ const extraArgs = ConfigService.get<string[]>('ai.claudeCli.extraArgs');
161
+ if (Array.isArray(extraArgs)) {
162
+ args.push(...extraArgs);
163
+ }
164
+ return args;
165
+ }
166
+
167
+ /** Resolve the CLI binary (override or `ai.claudeCli.bin`, default `claude`). */
168
+ protected getBinary(): string {
169
+ return ConfigService.get<string>('ai.claudeCli.bin') || 'claude';
170
+ }
171
+
172
+ /** Render a transcript label for a non-system message role. */
173
+ protected labelFor(role: LlmMessage['role']): string {
174
+ if (role === 'assistant') {
175
+ return 'Assistant';
176
+ }
177
+ if (role === 'tool') {
178
+ return 'Tool results';
179
+ }
180
+ return 'User';
181
+ }
182
+
183
+ /**
184
+ * Spawn the CLI with an argument array (never a shell), feed the transcript via
185
+ * stdin, and resolve with stdout. Rejects on non-zero exit, spawn error, or timeout
186
+ * (the child is killed). Runs in {@link tmpdir} so no project files are discovered.
187
+ */
188
+ protected run(args: string[], input: string, timeoutMs: number): Promise<string> {
189
+ return new Promise<string>((resolve, reject) => {
190
+ const env = { ...process.env };
191
+ if (this.connection.apiKey) {
192
+ env.ANTHROPIC_API_KEY = this.connection.apiKey;
193
+ }
194
+
195
+ const child = spawn(this.getBinary(), args, { cwd: tmpdir(), env, shell: false });
196
+
197
+ let stdout = '';
198
+ let stderr = '';
199
+ let settled = false;
200
+
201
+ const timer = setTimeout(() => {
202
+ if (!settled) {
203
+ settled = true;
204
+ child.kill('SIGKILL');
205
+ reject(new Error(`Claude CLI timed out after ${timeoutMs}ms`));
206
+ }
207
+ }, timeoutMs);
208
+
209
+ child.stdout.on('data', (chunk) => (stdout += chunk.toString()));
210
+ child.stderr.on('data', (chunk) => (stderr += chunk.toString()));
211
+
212
+ child.on('error', (err) => {
213
+ if (!settled) {
214
+ settled = true;
215
+ clearTimeout(timer);
216
+ reject(err);
217
+ }
218
+ });
219
+
220
+ child.on('close', (code) => {
221
+ if (settled) {
222
+ return;
223
+ }
224
+ settled = true;
225
+ clearTimeout(timer);
226
+ if (code === 0) {
227
+ resolve(stdout);
228
+ } else {
229
+ reject(new Error(`Claude CLI exited with code ${code}: ${stderr.slice(0, 300)}`));
230
+ }
231
+ });
232
+
233
+ child.stdin.on('error', () => {
234
+ // Ignore EPIPE if the child closed stdin early; close handler reports the failure.
235
+ });
236
+ child.stdin.write(input);
237
+ child.stdin.end();
238
+ });
239
+ }
240
+ }
@@ -0,0 +1,63 @@
1
+ import { Injectable, Logger } from '@nestjs/common';
2
+
3
+ import { ILlmProvider } from '../interfaces/llm-provider.interface';
4
+ import { ResolvedAiConnection } from '../interfaces/resolved-ai-connection.interface';
5
+ import { OpenAiCompatibleProvider } from './openai-compatible.provider';
6
+
7
+ /**
8
+ * Builds an {@link ILlmProvider} from a resolved connection.
9
+ *
10
+ * Builders are keyed by `providerType`. The factory ships with a builder for the
11
+ * `openai-compatible` chat API shape (a de-facto standard spoken by many local and
12
+ * hosted backends — not a specific vendor). Projects add builders for other
13
+ * backends/protocols by calling {@link registerBuilder} — typically from a
14
+ * module's `onModuleInit` — without subclassing the factory.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * factory.registerBuilder('my-provider', (conn) => new MyProvider(conn));
19
+ * ```
20
+ */
21
+ @Injectable()
22
+ export class LlmProviderFactory {
23
+ private readonly logger = new Logger(LlmProviderFactory.name);
24
+ private readonly builders = new Map<string, (connection: ResolvedAiConnection) => ILlmProvider>();
25
+
26
+ constructor() {
27
+ // Default builder for the OpenAI-compatible API shape (protocol, not a vendor).
28
+ const openAiCompatibleBuilder = (connection: ResolvedAiConnection) => new OpenAiCompatibleProvider(connection);
29
+ this.registerBuilder('openai-compatible', openAiCompatibleBuilder);
30
+ // Convenience alias for connections that store the shorter protocol key.
31
+ this.registerBuilder('openai', openAiCompatibleBuilder);
32
+ }
33
+
34
+ /**
35
+ * Register (or override) a provider builder for a `providerType`.
36
+ */
37
+ registerBuilder(providerType: string, builder: (connection: ResolvedAiConnection) => ILlmProvider): void {
38
+ this.builders.set(providerType, builder);
39
+ this.logger.debug(`Registered LLM provider builder: ${providerType}`);
40
+ }
41
+
42
+ /**
43
+ * Create a provider for a resolved connection.
44
+ * @throws Error if no builder is registered for the connection's providerType.
45
+ */
46
+ create(connection: ResolvedAiConnection): ILlmProvider {
47
+ const builder = this.builders.get(connection.providerType);
48
+ if (!builder) {
49
+ throw new Error(
50
+ `No LLM provider builder registered for providerType "${connection.providerType}". ` +
51
+ `Register one via LlmProviderFactory.registerBuilder().`,
52
+ );
53
+ }
54
+ return builder(connection);
55
+ }
56
+
57
+ /**
58
+ * Whether a builder exists for the given provider type.
59
+ */
60
+ supports(providerType: string): boolean {
61
+ return this.builders.has(providerType);
62
+ }
63
+ }