@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.
- package/.claude/rules/configurable-features.md +2 -0
- package/CLAUDE.md +18 -0
- package/FRAMEWORK-API.md +48 -1
- package/dist/config.env.js +35 -1
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/config.helper.js +2 -2
- package/dist/core/common/helpers/config.helper.js.map +1 -1
- package/dist/core/common/interceptors/check-security.interceptor.js +9 -2
- package/dist/core/common/interceptors/check-security.interceptor.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +89 -0
- package/dist/core/modules/ai/core-ai-mcp.controller.d.ts +21 -0
- package/dist/core/modules/ai/core-ai-mcp.controller.js +191 -0
- package/dist/core/modules/ai/core-ai-mcp.controller.js.map +1 -0
- package/dist/core/modules/ai/core-ai.controller.d.ts +90 -0
- package/dist/core/modules/ai/core-ai.controller.js +576 -0
- package/dist/core/modules/ai/core-ai.controller.js.map +1 -0
- package/dist/core/modules/ai/core-ai.module.d.ts +43 -0
- package/dist/core/modules/ai/core-ai.module.js +164 -0
- package/dist/core/modules/ai/core-ai.module.js.map +1 -0
- package/dist/core/modules/ai/core-ai.resolver.d.ts +84 -0
- package/dist/core/modules/ai/core-ai.resolver.js +530 -0
- package/dist/core/modules/ai/core-ai.resolver.js.map +1 -0
- package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.d.ts +7 -0
- package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.js +16 -0
- package/dist/core/modules/ai/helpers/ai-mcp-oauth.helper.js.map +1 -0
- package/dist/core/modules/ai/hooks/ai-hook.base.d.ts +10 -0
- package/dist/core/modules/ai/hooks/ai-hook.base.js +30 -0
- package/dist/core/modules/ai/hooks/ai-hook.base.js.map +1 -0
- package/dist/core/modules/ai/hooks/ai-hook.registry.d.ts +22 -0
- package/dist/core/modules/ai/hooks/ai-hook.registry.js +98 -0
- package/dist/core/modules/ai/hooks/ai-hook.registry.js.map +1 -0
- package/dist/core/modules/ai/index.d.ts +69 -0
- package/dist/core/modules/ai/index.js +86 -0
- package/dist/core/modules/ai/index.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-budget-limit-create.input.d.ts +5 -0
- package/dist/core/modules/ai/inputs/core-ai-budget-limit-create.input.js +43 -0
- package/dist/core/modules/ai/inputs/core-ai-budget-limit-create.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-budget-limit.input.d.ts +7 -0
- package/dist/core/modules/ai/inputs/core-ai-budget-limit.input.js +74 -0
- package/dist/core/modules/ai/inputs/core-ai-budget-limit.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-connection-create.input.d.ts +6 -0
- package/dist/core/modules/ai/inputs/core-ai-connection-create.input.js +49 -0
- package/dist/core/modules/ai/inputs/core-ai-connection-create.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-connection-preference.input.d.ts +6 -0
- package/dist/core/modules/ai/inputs/core-ai-connection-preference.input.js +60 -0
- package/dist/core/modules/ai/inputs/core-ai-connection-preference.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-connection.input.d.ts +23 -0
- package/dist/core/modules/ai/inputs/core-ai-connection.input.js +229 -0
- package/dist/core/modules/ai/inputs/core-ai-connection.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-conversation-create.input.d.ts +3 -0
- package/dist/core/modules/ai/inputs/core-ai-conversation-create.input.js +21 -0
- package/dist/core/modules/ai/inputs/core-ai-conversation-create.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-conversation.input.d.ts +4 -0
- package/dist/core/modules/ai/inputs/core-ai-conversation.input.js +42 -0
- package/dist/core/modules/ai/inputs/core-ai-conversation.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-create.input.d.ts +10 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-create.input.js +74 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-create.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-hint-create.input.d.ts +5 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-hint-create.input.js +41 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-hint-create.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-hint.input.d.ts +6 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-hint.input.js +63 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-hint.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-update.input.d.ts +10 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-update.input.js +70 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt-update.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt.input.d.ts +18 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt.input.js +131 -0
- package/dist/core/modules/ai/inputs/core-ai-prompt.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-slot-create.input.d.ts +5 -0
- package/dist/core/modules/ai/inputs/core-ai-slot-create.input.js +41 -0
- package/dist/core/modules/ai/inputs/core-ai-slot-create.input.js.map +1 -0
- package/dist/core/modules/ai/inputs/core-ai-slot-update.input.d.ts +9 -0
- package/dist/core/modules/ai/inputs/core-ai-slot-update.input.js +91 -0
- package/dist/core/modules/ai/inputs/core-ai-slot-update.input.js.map +1 -0
- package/dist/core/modules/ai/interfaces/ai-hook.interface.d.ts +28 -0
- package/dist/core/modules/ai/interfaces/ai-hook.interface.js +3 -0
- package/dist/core/modules/ai/interfaces/ai-hook.interface.js.map +1 -0
- package/dist/core/modules/ai/interfaces/ai-placeholder.interface.d.ts +21 -0
- package/dist/core/modules/ai/interfaces/ai-placeholder.interface.js +3 -0
- package/dist/core/modules/ai/interfaces/ai-placeholder.interface.js.map +1 -0
- package/dist/core/modules/ai/interfaces/ai-tool.interface.d.ts +30 -0
- package/dist/core/modules/ai/interfaces/ai-tool.interface.js +3 -0
- package/dist/core/modules/ai/interfaces/ai-tool.interface.js.map +1 -0
- package/dist/core/modules/ai/interfaces/llm-provider.interface.d.ts +55 -0
- package/dist/core/modules/ai/interfaces/llm-provider.interface.js +3 -0
- package/dist/core/modules/ai/interfaces/llm-provider.interface.js.map +1 -0
- package/dist/core/modules/ai/interfaces/resolved-ai-connection.interface.d.ts +16 -0
- package/dist/core/modules/ai/interfaces/resolved-ai-connection.interface.js +3 -0
- package/dist/core/modules/ai/interfaces/resolved-ai-connection.interface.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-action.model.d.ts +6 -0
- package/dist/core/modules/ai/models/core-ai-action.model.js +44 -0
- package/dist/core/modules/ai/models/core-ai-action.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-available-connection.model.d.ts +8 -0
- package/dist/core/modules/ai/models/core-ai-available-connection.model.js +53 -0
- package/dist/core/modules/ai/models/core-ai-available-connection.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-budget-limit.model.d.ts +97 -0
- package/dist/core/modules/ai/models/core-ai-budget-limit.model.js +79 -0
- package/dist/core/modules/ai/models/core-ai-budget-limit.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-connection-preference.model.d.ts +91 -0
- package/dist/core/modules/ai/models/core-ai-connection-preference.model.js +67 -0
- package/dist/core/modules/ai/models/core-ai-connection-preference.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-connection.model.d.ts +200 -0
- package/dist/core/modules/ai/models/core-ai-connection.model.js +263 -0
- package/dist/core/modules/ai/models/core-ai-connection.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-conversation.model.d.ts +93 -0
- package/dist/core/modules/ai/models/core-ai-conversation.model.js +82 -0
- package/dist/core/modules/ai/models/core-ai-conversation.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-interaction.model.d.ts +133 -0
- package/dist/core/modules/ai/models/core-ai-interaction.model.js +137 -0
- package/dist/core/modules/ai/models/core-ai-interaction.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-message.model.d.ts +5 -0
- package/dist/core/modules/ai/models/core-ai-message.model.js +38 -0
- package/dist/core/modules/ai/models/core-ai-message.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-mode.model.d.ts +109 -0
- package/dist/core/modules/ai/models/core-ai-mode.model.js +100 -0
- package/dist/core/modules/ai/models/core-ai-mode.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-prompt-hint.model.d.ts +103 -0
- package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js +89 -0
- package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-prompt.model.d.ts +122 -0
- package/dist/core/modules/ai/models/core-ai-prompt.model.js +117 -0
- package/dist/core/modules/ai/models/core-ai-prompt.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-response.model.d.ts +29 -0
- package/dist/core/modules/ai/models/core-ai-response.model.js +105 -0
- package/dist/core/modules/ai/models/core-ai-response.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-slot.model.d.ts +121 -0
- package/dist/core/modules/ai/models/core-ai-slot.model.js +119 -0
- package/dist/core/modules/ai/models/core-ai-slot.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-tool-grant.model.d.ts +103 -0
- package/dist/core/modules/ai/models/core-ai-tool-grant.model.js +88 -0
- package/dist/core/modules/ai/models/core-ai-tool-grant.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-tool-policy.model.d.ts +122 -0
- package/dist/core/modules/ai/models/core-ai-tool-policy.model.js +121 -0
- package/dist/core/modules/ai/models/core-ai-tool-policy.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-usage-info.model.d.ts +24 -0
- package/dist/core/modules/ai/models/core-ai-usage-info.model.js +127 -0
- package/dist/core/modules/ai/models/core-ai-usage-info.model.js.map +1 -0
- package/dist/core/modules/ai/models/core-ai-usage.model.d.ts +5 -0
- package/dist/core/modules/ai/models/core-ai-usage.model.js +38 -0
- package/dist/core/modules/ai/models/core-ai-usage.model.js.map +1 -0
- package/dist/core/modules/ai/providers/claude-cli.provider.d.ts +16 -0
- package/dist/core/modules/ai/providers/claude-cli.provider.js +151 -0
- package/dist/core/modules/ai/providers/claude-cli.provider.js.map +1 -0
- package/dist/core/modules/ai/providers/llm-provider.factory.d.ts +10 -0
- package/dist/core/modules/ai/providers/llm-provider.factory.js +45 -0
- package/dist/core/modules/ai/providers/llm-provider.factory.js.map +1 -0
- package/dist/core/modules/ai/providers/openai-compatible.provider.d.ts +32 -0
- package/dist/core/modules/ai/providers/openai-compatible.provider.js +236 -0
- package/dist/core/modules/ai/providers/openai-compatible.provider.js.map +1 -0
- package/dist/core/modules/ai/services/ai-crypto.service.d.ts +11 -0
- package/dist/core/modules/ai/services/ai-crypto.service.js +84 -0
- package/dist/core/modules/ai/services/ai-crypto.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-budget.service.d.ts +42 -0
- package/dist/core/modules/ai/services/core-ai-budget.service.js +211 -0
- package/dist/core/modules/ai/services/core-ai-budget.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.d.ts +18 -0
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.js +53 -0
- package/dist/core/modules/ai/services/core-ai-connection-preference.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-connection-resolver.service.d.ts +55 -0
- package/dist/core/modules/ai/services/core-ai-connection-resolver.service.js +177 -0
- package/dist/core/modules/ai/services/core-ai-connection-resolver.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-connection.service.d.ts +43 -0
- package/dist/core/modules/ai/services/core-ai-connection.service.js +272 -0
- package/dist/core/modules/ai/services/core-ai-connection.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +26 -0
- package/dist/core/modules/ai/services/core-ai-conversation.service.js +72 -0
- package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-interaction.service.d.ts +13 -0
- package/dist/core/modules/ai/services/core-ai-interaction.service.js +52 -0
- package/dist/core/modules/ai/services/core-ai-interaction.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-mcp-client.service.d.ts +51 -0
- package/dist/core/modules/ai/services/core-ai-mcp-client.service.js +123 -0
- package/dist/core/modules/ai/services/core-ai-mcp-client.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.d.ts +68 -0
- package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js +279 -0
- package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-mcp.service.d.ts +22 -0
- package/dist/core/modules/ai/services/core-ai-mcp.service.js +59 -0
- package/dist/core/modules/ai/services/core-ai-mcp.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-mode.service.d.ts +14 -0
- package/dist/core/modules/ai/services/core-ai-mode.service.js +56 -0
- package/dist/core/modules/ai/services/core-ai-mode.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-placeholder.registry.d.ts +15 -0
- package/dist/core/modules/ai/services/core-ai-placeholder.registry.js +102 -0
- package/dist/core/modules/ai/services/core-ai-placeholder.registry.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-prompt-builder.service.d.ts +42 -0
- package/dist/core/modules/ai/services/core-ai-prompt-builder.service.js +136 -0
- package/dist/core/modules/ai/services/core-ai-prompt-builder.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.d.ts +29 -0
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js +98 -0
- package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-prompt.service.d.ts +21 -0
- package/dist/core/modules/ai/services/core-ai-prompt.service.js +143 -0
- package/dist/core/modules/ai/services/core-ai-prompt.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-slot.service.d.ts +51 -0
- package/dist/core/modules/ai/services/core-ai-slot.service.js +372 -0
- package/dist/core/modules/ai/services/core-ai-slot.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.d.ts +22 -0
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.js +97 -0
- package/dist/core/modules/ai/services/core-ai-tool-grant.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.d.ts +23 -0
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.js +102 -0
- package/dist/core/modules/ai/services/core-ai-tool-policy.service.js.map +1 -0
- package/dist/core/modules/ai/services/core-ai.service.d.ts +144 -0
- package/dist/core/modules/ai/services/core-ai.service.js +991 -0
- package/dist/core/modules/ai/services/core-ai.service.js.map +1 -0
- package/dist/core/modules/ai/tools/ai-tool.base.d.ts +15 -0
- package/dist/core/modules/ai/tools/ai-tool.base.js +30 -0
- package/dist/core/modules/ai/tools/ai-tool.base.js.map +1 -0
- package/dist/core/modules/ai/tools/ai-tool.registry.d.ts +19 -0
- package/dist/core/modules/ai/tools/ai-tool.registry.js +71 -0
- package/dist/core/modules/ai/tools/ai-tool.registry.js.map +1 -0
- package/dist/core/modules/ai/tools/ask-user-question.tool.d.ts +38 -0
- package/dist/core/modules/ai/tools/ask-user-question.tool.js +65 -0
- package/dist/core/modules/ai/tools/ask-user-question.tool.js.map +1 -0
- package/dist/core/modules/ai/tools/search-tools.tool.d.ts +24 -0
- package/dist/core/modules/ai/tools/search-tools.tool.js +68 -0
- package/dist/core/modules/ai/tools/search-tools.tool.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +2 -1
- package/dist/core/modules/better-auth/core-better-auth.controller.js +12 -1
- package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -1
- package/dist/core/modules/error-code/error-codes.d.ts +81 -0
- package/dist/core/modules/error-code/error-codes.js +72 -0
- package/dist/core/modules/error-code/error-codes.js.map +1 -1
- package/dist/core.module.js +8 -0
- package/dist/core.module.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/server/modules/ai/ai-tools.module.d.ts +5 -0
- package/dist/server/modules/ai/ai-tools.module.js +36 -0
- package/dist/server/modules/ai/ai-tools.module.js.map +1 -0
- package/dist/server/modules/ai/tools/delete-user.tool.d.ts +30 -0
- package/dist/server/modules/ai/tools/delete-user.tool.js +49 -0
- package/dist/server/modules/ai/tools/delete-user.tool.js.map +1 -0
- package/dist/server/modules/ai/tools/find-users.tool.d.ts +30 -0
- package/dist/server/modules/ai/tools/find-users.tool.js +52 -0
- package/dist/server/modules/ai/tools/find-users.tool.js.map +1 -0
- package/dist/server/modules/ai/tools/get-user.tool.d.ts +26 -0
- package/dist/server/modules/ai/tools/get-user.tool.js +48 -0
- package/dist/server/modules/ai/tools/get-user.tool.js.map +1 -0
- package/dist/server/modules/ai/tools/update-user-job-title.tool.d.ts +32 -0
- package/dist/server/modules/ai/tools/update-user-job-title.tool.js +54 -0
- package/dist/server/modules/ai/tools/update-user-job-title.tool.js.map +1 -0
- package/dist/server/modules/error-code/error-codes.d.ts +9 -0
- package/dist/server/server.module.js +2 -0
- package/dist/server/server.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +10 -0
- package/migration-guides/11.25.x-to-11.26.0.md +278 -0
- package/migration-guides/11.26.0-to-11.26.1.md +193 -0
- package/package.json +2 -1
- package/src/config.env.ts +48 -1
- package/src/core/common/helpers/config.helper.ts +5 -2
- package/src/core/common/interceptors/check-security.interceptor.ts +13 -3
- package/src/core/common/interfaces/server-options.interface.ts +312 -0
- package/src/core/modules/ai/INTEGRATION-CHECKLIST.md +220 -0
- package/src/core/modules/ai/README.md +526 -0
- package/src/core/modules/ai/core-ai-mcp.controller.ts +223 -0
- package/src/core/modules/ai/core-ai.controller.ts +547 -0
- package/src/core/modules/ai/core-ai.module.ts +269 -0
- package/src/core/modules/ai/core-ai.resolver.ts +526 -0
- package/src/core/modules/ai/helpers/ai-mcp-oauth.helper.ts +35 -0
- package/src/core/modules/ai/hooks/ai-hook.base.ts +23 -0
- package/src/core/modules/ai/hooks/ai-hook.registry.ts +119 -0
- package/src/core/modules/ai/index.ts +70 -0
- package/src/core/modules/ai/inputs/core-ai-budget-limit-create.input.ts +27 -0
- package/src/core/modules/ai/inputs/core-ai-budget-limit.input.ts +52 -0
- package/src/core/modules/ai/inputs/core-ai-connection-create.input.ts +32 -0
- package/src/core/modules/ai/inputs/core-ai-connection-preference.input.ts +42 -0
- package/src/core/modules/ai/inputs/core-ai-connection.input.ts +235 -0
- package/src/core/modules/ai/inputs/core-ai-conversation-create.input.ts +13 -0
- package/src/core/modules/ai/inputs/core-ai-conversation.input.ts +33 -0
- package/src/core/modules/ai/inputs/core-ai-prompt-create.input.ts +50 -0
- package/src/core/modules/ai/inputs/core-ai-prompt-hint-create.input.ts +26 -0
- package/src/core/modules/ai/inputs/core-ai-prompt-hint.input.ts +43 -0
- package/src/core/modules/ai/inputs/core-ai-prompt-update.input.ts +42 -0
- package/src/core/modules/ai/inputs/core-ai-prompt.input.ts +144 -0
- package/src/core/modules/ai/inputs/core-ai-slot-create.input.ts +26 -0
- package/src/core/modules/ai/inputs/core-ai-slot-update.input.ts +65 -0
- package/src/core/modules/ai/interfaces/ai-hook.interface.ts +74 -0
- package/src/core/modules/ai/interfaces/ai-placeholder.interface.ts +49 -0
- package/src/core/modules/ai/interfaces/ai-tool.interface.ts +112 -0
- package/src/core/modules/ai/interfaces/llm-provider.interface.ts +187 -0
- package/src/core/modules/ai/interfaces/resolved-ai-connection.interface.ts +55 -0
- package/src/core/modules/ai/models/core-ai-action.model.ts +37 -0
- package/src/core/modules/ai/models/core-ai-available-connection.model.ts +42 -0
- package/src/core/modules/ai/models/core-ai-budget-limit.model.ts +82 -0
- package/src/core/modules/ai/models/core-ai-connection-preference.model.ts +72 -0
- package/src/core/modules/ai/models/core-ai-connection.model.ts +330 -0
- package/src/core/modules/ai/models/core-ai-conversation.model.ts +87 -0
- package/src/core/modules/ai/models/core-ai-interaction.model.ts +145 -0
- package/src/core/modules/ai/models/core-ai-message.model.ts +29 -0
- package/src/core/modules/ai/models/core-ai-mode.model.ts +93 -0
- package/src/core/modules/ai/models/core-ai-prompt-hint.model.ts +98 -0
- package/src/core/modules/ai/models/core-ai-prompt.model.ts +120 -0
- package/src/core/modules/ai/models/core-ai-response.model.ts +119 -0
- package/src/core/modules/ai/models/core-ai-slot.model.ts +146 -0
- package/src/core/modules/ai/models/core-ai-tool-grant.model.ts +87 -0
- package/src/core/modules/ai/models/core-ai-tool-policy.model.ts +115 -0
- package/src/core/modules/ai/models/core-ai-usage-info.model.ts +107 -0
- package/src/core/modules/ai/models/core-ai-usage.model.ts +29 -0
- package/src/core/modules/ai/providers/claude-cli.provider.ts +240 -0
- package/src/core/modules/ai/providers/llm-provider.factory.ts +63 -0
- package/src/core/modules/ai/providers/openai-compatible.provider.ts +329 -0
- package/src/core/modules/ai/services/ai-crypto.service.ts +120 -0
- package/src/core/modules/ai/services/core-ai-budget.service.ts +297 -0
- package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +74 -0
- package/src/core/modules/ai/services/core-ai-connection-resolver.service.ts +308 -0
- package/src/core/modules/ai/services/core-ai-connection.service.ts +387 -0
- package/src/core/modules/ai/services/core-ai-conversation.service.ts +105 -0
- package/src/core/modules/ai/services/core-ai-interaction.service.ts +56 -0
- package/src/core/modules/ai/services/core-ai-mcp-client.service.ts +169 -0
- package/src/core/modules/ai/services/core-ai-mcp-oauth.service.ts +445 -0
- package/src/core/modules/ai/services/core-ai-mcp.service.ts +94 -0
- package/src/core/modules/ai/services/core-ai-mode.service.ts +43 -0
- package/src/core/modules/ai/services/core-ai-placeholder.registry.ts +123 -0
- package/src/core/modules/ai/services/core-ai-prompt-builder.service.ts +228 -0
- package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +133 -0
- package/src/core/modules/ai/services/core-ai-prompt.service.ts +164 -0
- package/src/core/modules/ai/services/core-ai-slot.service.ts +526 -0
- package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +107 -0
- package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +124 -0
- package/src/core/modules/ai/services/core-ai.service.ts +1396 -0
- package/src/core/modules/ai/tools/ai-tool.base.ts +46 -0
- package/src/core/modules/ai/tools/ai-tool.registry.ts +124 -0
- package/src/core/modules/ai/tools/ask-user-question.tool.ts +76 -0
- package/src/core/modules/ai/tools/search-tools.tool.ts +70 -0
- package/src/core/modules/better-auth/core-better-auth.controller.ts +20 -3
- package/src/core/modules/error-code/error-codes.ts +86 -0
- package/src/core.module.ts +12 -0
- package/src/index.ts +6 -0
- package/src/server/modules/ai/ai-tools.module.ts +33 -0
- package/src/server/modules/ai/tools/delete-user.tool.ts +44 -0
- package/src/server/modules/ai/tools/find-users.tool.ts +49 -0
- package/src/server/modules/ai/tools/get-user.tool.ts +43 -0
- package/src/server/modules/ai/tools/update-user-job-title.tool.ts +62 -0
- 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 |
|