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