add Letsur AI Gateway config for development#37
Conversation
…ack-letsur-dev # Conflicts: # src/chat/services/chat-orchestration.service.ts
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 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 |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds message-level feedback (GOOD/BAD) for assistant answers, enables one-time regeneration for BAD feedback without consuming the session question limit, and surfaces a “resolution rate” metric in widget key usage stats.
Changes:
- Introduced
message_feedbackstable + enum, DTOs, and API endpoints to upsert feedback and initiate regeneration streaming. - Updated chat history responses to include feedback state and added orchestration options to skip persisting the regenerated “user message”.
- Added resolution rate calculation to usage stats based on BAD feedback ratio.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/jest-e2e.json | Adds Jest config for e2e tests. |
| test/chat-feedback.e2e-spec.ts | End-to-end coverage for feedback + regeneration endpoints. |
| src/usage/usage.service.ts | Computes per-key resolution rate from answers + BAD feedback counts. |
| src/usage/usage.service.spec.ts | Unit tests for calculateResolutionRate. |
| src/db/schema.ts | Adds feedback enum/table + relations; tightens metadata typing. |
| src/db/message-feedback.schema.spec.ts | Verifies migration SQL includes enum/table/unique constraint. |
| src/config/env.validation.ts | Renames required API key env var for the gateway. |
| src/common/dto/widget-key-usage.dto.ts | Exposes resolutionRate in returned widget key stats. |
| src/common/dto/message-feedback.dto.ts | Adds feedback DTOs + FeedbackRating enum. |
| src/common/dto/chat-message.dto.ts | Adds feedback field to message DTO. |
| src/chat/services/open-router.service.ts | Switches config keys from OpenRouter to Letsur AI Gateway names. |
| src/chat/services/chat.service.ts | Implements feedback upsert, feedback-aware history, and regeneration target lookup/locking. |
| src/chat/services/chat.service.spec.ts | Unit tests for feedback and regeneration flows in ChatService. |
| src/chat/services/chat-orchestration.service.ts | Adds streaming options (persistUserMessage/historyBefore/assistantMetadata). |
| src/chat/chat.controller.ts | Adds PUT feedback + POST regenerate endpoints. |
| eslint.config.mjs | Adjusts TS ESLint project service config to include test files. |
| drizzle/meta/_journal.json | Adds migration journal entry for new schema version. |
| drizzle/meta/0007_snapshot.json | Snapshot updated to include feedback enum/table. |
| drizzle/0007_past_silk_fever.sql | Migration creating feedback enum/table and indexes. |
| docker-compose.yml | Renames gateway env variables used by the app container. |
| .env.example | Documents Letsur AI Gateway env vars and keeps legacy OpenRouter vars. |
Comments suppressed due to low confidence (1)
src/common/dto/chat-message.dto.ts:1
- The PR tightens DB metadata typing to
Record<string, unknown>(and service mapping usesRecord<string, unknown>), but the public DTO still exposesRecord<string, any>. Updating this DTO toRecord<string, unknown>would preventanyfrom leaking into the API layer and keep types consistent across schema/service/DTO.
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Open Router Configuration | ||
| @IsString() | ||
| @IsNotEmpty() | ||
| OPEN_ROUTER_API_KEY: string; | ||
| LETSUR_AI_GATEWAY_API_KEY: string; |
| Authorization: `Bearer ${this.apiKey}`, | ||
| 'Content-Type': 'application/json', | ||
| 'HTTP-Referer': this.configService.get<string>('DOMAIN_NAME'), | ||
| 'X-Title': this.configService.get<string>('OPEN_ROUTER_TITLE'), | ||
| 'X-Title': this.configService.get<string>('LETSUR_AI_GATEWAY_TITLE'), |
| export function calculateResolutionRate( | ||
| totalAnswers: number, | ||
| badAnswers: number, | ||
| ): number { | ||
| if (totalAnswers <= 0) { | ||
| return 0; | ||
| } | ||
|
|
||
| const rate = (1 - badAnswers / totalAnswers) * 100; | ||
| return Math.round(rate * 100) / 100; | ||
| } |
| const normalizedSessionSource = sql<string>` | ||
| case | ||
| when btrim(${sessions.pageUrl}) = '' then 'unknown' | ||
| when btrim(${sessions.pageUrl}) like 'app:%' then coalesce(nullif(btrim(substring(btrim(${sessions.pageUrl}) from 5)), ''), 'unknown') | ||
| when btrim(${sessions.pageUrl}) ~* '^[a-z][a-z0-9+.-]*://' then coalesce(nullif(split_part(regexp_replace(btrim(${sessions.pageUrl}), '^[a-z][a-z0-9+.-]*://([^/\\?#]+).*$', '\\1', 'i'), ':', 1), ''), 'unknown') | ||
| else coalesce(nullif(regexp_replace(btrim(${sessions.pageUrl}), '^(?:https?://)?([^/\\?#]+).*$', '\\1', 'i'), ''), 'unknown') | ||
| end | ||
| `; |
Changes
Add Letsur AI Gateway environment variables
LETSUR_AI_GATEWAY_BASE_URLLETSUR_AI_GATEWAY_API_KEYLETSUR_AI_GATEWAY_MODEL_LIGHTLETSUR_AI_GATEWAY_MODEL_NORMALLETSUR_AI_GATEWAY_MODEL_HEAVYKeep existing OpenRouter environment variables for backward compatibility
Update
.env.exampleto reflect the new configuration formatMerge latest
developmentchanges into the feat: add assistant answer feedback #36-based branch and resolve conflictsNotes
developmentfor local integration/testing before the related changes are merged intomain.