Conversation
|
Thanks for opening this, but we'd appreciate a little more information. Could you update it with more details? |
|
Important Review skippedToo many files! This PR contains 167 files, which is 17 over the limit of 150. To get a review, narrow the scope: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (10)
📒 Files selected for processing (167)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| [HttpPost("Webhook")] | ||
| [Consumes("application/json")] | ||
| [ProducesResponseType(StatusCodes.Status200OK)] | ||
| public async Task<IActionResult> Webhook() |
| /// </summary> | ||
| [HttpPost("GenerateLinkingCode")] | ||
| [ProducesResponseType(StatusCodes.Status200OK)] | ||
| public async Task<IActionResult> GenerateLinkingCode() |
| /// </summary> | ||
| [HttpPost("UnlinkAccount")] | ||
| [ProducesResponseType(StatusCodes.Status200OK)] | ||
| public async Task<IActionResult> UnlinkAccount([FromBody] UnlinkRequest request) |
| /// </summary> | ||
| [HttpPost("OAuthComplete")] | ||
| [ProducesResponseType(StatusCodes.Status200OK)] | ||
| public async Task<IActionResult> OAuthComplete([FromBody] OAuthCompleteRequest request) |
| { | ||
| try | ||
| { | ||
| if (request == null) |
| [HttpPost("SetRollout")] | ||
| [ProducesResponseType(StatusCodes.Status200OK)] | ||
| [Authorize(Policy = ResgridResources.SystemAdmin)] | ||
| public async Task<ActionResult<FeatureFlagResult>> SetRollout([FromBody] SetRolloutInput input) |
| [HttpPost("SaveTargetingRule")] | ||
| [ProducesResponseType(StatusCodes.Status200OK)] | ||
| [Authorize(Policy = ResgridResources.SystemAdmin)] | ||
| public async Task<ActionResult<FeatureFlagTargetingRulesResult>> SaveTargetingRule([FromBody] SaveTargetingRuleInput input) |
| [HttpPost("AddPrerequisite")] | ||
| [ProducesResponseType(StatusCodes.Status200OK)] | ||
| [Authorize(Policy = ResgridResources.SystemAdmin)] | ||
| public async Task<ActionResult<FeatureFlagPrerequisitesResult>> AddPrerequisite([FromBody] AddPrerequisiteInput input) |
| [HttpPost("SetOverride")] | ||
| [ProducesResponseType(StatusCodes.Status200OK)] | ||
| [Authorize] | ||
| public async Task<ActionResult<FeatureFlagOverrideResult>> SetOverride([FromBody] SetFeatureFlagOverrideInput input) |
| [Authorize] | ||
| public async Task<ActionResult<FeatureFlagOverrideResult>> SetOverride([FromBody] SetFeatureFlagOverrideInput input) | ||
| { | ||
| if (input == null || string.IsNullOrWhiteSpace(input.Key)) |
There was a problem hiding this comment.
Pull request overview
This PR introduces a sizable new chatbot subsystem and a built-in feature-toggle subsystem into the Resgrid codebase, alongside a number of supporting changes. The chatbot work adds platform adapters (SMS, Discord, Slack, Telegram, WhatsApp, WebChat), per-department configuration with optional encrypted LLM provider override, identity/linking persistence, an outbound chat channel wired into CommunicationService, localization, rate limiting, and a new "Chatbot Settings" admin UI. The feature-toggle work introduces flag/override/targeting/prerequisite/usage entities, repositories, an IFeatureToggleService interface, a usage-flush worker, and a new FeatureFlagsConfig. Several pieces are also wired into existing DI modules and project files.
Changes:
- New
Resgrid.Chatbot/Resgrid.Chatbot.NLU/Resgrid.Providers.Chatbotprojects with adapters, handlers, services, models, and DI modules, plus a per-department config UI, migrations (M0069/M0070), andIChatbotOutboundServiceintegration intoCommunicationService. - New feature-toggle model/repository/service surface with global config (
FeatureFlagsConfig), DI registrations inDataModule/ServicesModule, aFeatureToggleUsageProcessorworker, and a newICacheProvider.IncrementAsyncfor atomic counters. - Supporting infrastructure: SQL/Postgres migrations for chatbot/linking-code tables and LLM override columns, English/Spanish localization additions, audit-log enum entries, and updated test mocks for the new
IChatbotOutboundService/IChatbotIngressServiceconstructor parameters.
Reviewed changes
Copilot reviewed 174 out of 177 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Workers/Resgrid.Workers.Framework/Logic/FeatureToggleUsageProcessor.cs | New worker that flushes feature-flag evaluation counters. |
| Web/Resgrid.Web/Startup.cs | Registers ChatbotDepartmentConfigService in the web container. |
| Web/Resgrid.Web/Resgrid.Web.csproj | Adds Resgrid.Chatbot project reference. |
| Web/Resgrid.Web/Areas/User/Views/Department/Settings.cshtml | Adds Chatbot Settings nav link. |
| Web/Resgrid.Web/Areas/User/Models/ChatbotSettingsModel.cs | View model for chatbot settings page. |
| Web/Resgrid.Web/Areas/User/Controllers/ChatbotSettingsController.cs | New controller for per-department chatbot config. |
| Web/Resgrid.Web/Areas/User/Apps/package-lock.json | Adjusts peer flags on transitive dev deps. |
| Web/Resgrid.Web.Services/Startup.cs | Registers ChatbotModule, NLUModule, and chatbot provider module. |
| Web/Resgrid.Web.Services/Resgrid.Web.Services.csproj | Adds chatbot/NLU project references. |
| Web/Resgrid.Web.Services/Models/v4/FeatureToggles/FeatureToggleInputs.cs | DTOs for feature-toggle API endpoints. |
| Tests/Resgrid.Tests/Web/Services/TwilioControllerVoiceVerificationTests.cs | Adds chatbot ingress mock to controller construction. |
| Tests/Resgrid.Tests/Services/CommunicationServiceTests.cs | Adds chatbot outbound mock to CommunicationService ctor. |
| Tests/Resgrid.Tests/Chatbot/WebChatAdapterTests.cs | New tests for WebChatAdapter. |
| Tests/Resgrid.Tests/Chatbot/ChatbotLocalizationTests.cs | New tests for chatbot localization and handler culture flow. |
| Repositories/Resgrid.Repositories.DataRepository/Modules/DataModule.cs | Registers new feature-flag and chatbot repositories. |
| Repositories/Resgrid.Repositories.DataRepository/FeatureFlag*Repository.cs (5 files) | Dapper repos for FeatureFlag/Override/TargetingRule/Prerequisite/Usage. |
| Repositories/Resgrid.Repositories.DataRepository/ChatbotLinkingCodeRepository.cs | Lookup by code (returns newest unused, falls back to newest). |
| Repositories/Resgrid.Repositories.DataRepository/ChatbotIdentityRepository.cs | Lookup of chat identities by platform/platform-user-id. |
| Repositories/Resgrid.Repositories.DataRepository/ChatbotDepartmentConfigRepository.cs | Lookup of per-dept chatbot config. |
| Providers/Resgrid.Providers.MigrationsPg/Migrations/M0069/M0070*.cs | Postgres migrations for chatbot linking codes & config columns. |
| Providers/Resgrid.Providers.Migrations/Migrations/M0069/M0070*.cs | SQL Server migrations for the same tables/columns. |
| Providers/Resgrid.Providers.Chatbot/* | New chatbot provider project: adapters, outbound service, registry, DI module. |
| Providers/Resgrid.Providers.Cache/AzureRedisCacheProvider.cs | Adds IncrementAsync for atomic counter w/ TTL on first set. |
| Core/Resgrid.Services/ServicesModule.cs | Registers NullChatbotOutboundService default and FeatureToggleService. |
| Core/Resgrid.Services/NullChatbotOutboundService.cs | No-op fallback for hosts without chatbot module. |
| Core/Resgrid.Services/CommunicationService.cs | Adds chatbot outbound delivery to message/call paths. |
| Core/Resgrid.Model/Services/IFeatureToggleService.cs | New feature-toggle service interface. |
| Core/Resgrid.Model/Services/IChatbotOutboundService.cs | Interface for outbound chat delivery. |
| Core/Resgrid.Model/Repositories/IFeatureFlag*Repository.cs (5) | Repository interfaces for feature toggle entities. |
| Core/Resgrid.Model/Repositories/IChatbot*Repository.cs (3) | Repository interfaces for chatbot entities. |
| Core/Resgrid.Model/Providers/ICacheProvider.cs | Adds IncrementAsync to cache abstraction. |
| Core/Resgrid.Model/FeatureToggles/*.cs (8 files) | New entity/enum/eval-result classes. |
| Core/Resgrid.Model/Chatbot*.cs (3 files) | Persistence entities + outbound message types. |
| Core/Resgrid.Model/AuditLogTypes.cs | Adds feature-flag audit log enum values. |
| Core/Resgrid.Localization/Areas/User/Department/Department.{en,es}.resx | Adds chatbot settings UI strings. |
| Core/Resgrid.Config/FeatureFlagsConfig.cs | Global config for feature-toggle subsystem. |
| Core/Resgrid.Chatbot/* | New core chatbot project: models, interfaces, handlers, session/rate-limit/config services, localization. |
| Core/Resgrid.Chatbot.NLU/* | NLU project: keyword/ML.NET/cloud providers, entity extractor, Autofac module. |
| CONTEXT.md | New repo-level context notes for the chatbot work. |
| .gitignore | Cleans up duplicate entries; adds .dual-graph-pro/. |
| .claude/settings.local.json | Local Claude settings/hooks updates. |
Files not reviewed (1)
- Web/Resgrid.Web/Areas/User/Apps/package-lock.json: Language not supported
| // A blank key means "keep the existing one"; a value is encrypted and stored by the service. | ||
| var newPlaintextKey = string.IsNullOrWhiteSpace(model.LlmApiKey) ? null : model.LlmApiKey; | ||
| await _chatbotConfigService.SaveConfigAsync(config, newPlaintextKey); |
| // Prefer the newest unused code if duplicates ever exist for the same value. | ||
| return results | ||
| .OrderByDescending(r => r.CreatedAt) | ||
| .FirstOrDefault(r => !r.IsUsed) ?? results.OrderByDescending(r => r.CreatedAt).FirstOrDefault(); |
| public async Task<bool> TryAcquireAsync(string userId, int departmentId, int perUserPerMinute, int perDepartmentPerMinute) | ||
| { | ||
| if (UseRedis()) | ||
| { | ||
| // Check the user limit first; only consume the department slot if the user is allowed. | ||
| if (!await CheckAndConsumeRedisAsync($"u:{departmentId}:{userId}", perUserPerMinute)) | ||
| return false; | ||
|
|
||
| if (!await CheckAndConsumeRedisAsync($"d:{departmentId}", perDepartmentPerMinute)) | ||
| return false; | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| if (!CheckAndConsumeMemory($"u:{departmentId}:{userId}", perUserPerMinute)) | ||
| return false; | ||
|
|
||
| if (!CheckAndConsumeMemory($"d:{departmentId}", perDepartmentPerMinute)) | ||
| return false; | ||
|
|
||
| return true; |
No description provided.