-
Notifications
You must be signed in to change notification settings - Fork 548
[REF-920] feat: Implement rule-based auto model routing #1911
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds Prisma models for auto-model routing and a new AutoModelRoutingService with rule-based routing, caching, multi-tier fallback selection, async routing-result persistence, integrations into ProviderModule and SkillService, and supporting ID/scene utilities. Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant SkillService
participant AutoModelRoutingService
participant RuleCache
participant RuleRouter
participant PrismaService
participant ProviderRegistry
Client->>SkillService: invoke skill (mode, user, actionResult)
SkillService->>AutoModelRoutingService: route(originalProviderItem, RoutingContext)
AutoModelRoutingService->>RuleCache: getRules(scene)
alt cache hit
RuleCache-->>AutoModelRoutingService: rules
else cache miss / stale
RuleCache->>PrismaService: query AutoModelRoutingRule
PrismaService-->>RuleCache: rules
RuleCache-->>AutoModelRoutingService: rules
end
alt rule matches
AutoModelRoutingService->>RuleRouter: evaluate(rules, context)
RuleRouter-->>AutoModelRoutingService: matchedTarget
AutoModelRoutingService->>ProviderRegistry: selectProviderItem(matchedTarget)
ProviderRegistry-->>AutoModelRoutingService: providerItem
AutoModelRoutingService->>PrismaService: saveRoutingResultAsync(...)
else no match -> fallbacks
AutoModelRoutingService->>ProviderRegistry: select via tool/random/priority/first
ProviderRegistry-->>AutoModelRoutingService: providerItem
AutoModelRoutingService->>PrismaService: saveRoutingResultAsync(...)
end
AutoModelRoutingService-->>SkillService: routed providerItem (with routedData)
SkillService-->>Client: proceed with routed model
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (7)
🚧 Files skipped from review as they are similar to previous changes (2)
🧰 Additional context used📓 Path-based instructions (15)**/*.{js,ts,jsx,tsx}📄 CodeRabbit inference engine (.cursorrules)
Files:
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Files:
**/*.{js,ts,tsx,jsx}📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Files:
**/*.{js,jsx,ts,tsx}📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
Files:
**/*.{ts,tsx}📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
Files:
**/*.{js,ts,jsx,tsx,css,json}📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Files:
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Files:
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Files:
**/*.{css,scss,sass,less,js,jsx,ts,tsx}📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
Files:
**/*.{tsx,ts}📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Files:
**/*.{tsx,ts,json}📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Files:
**/*.{tsx,ts,jsx,js,vue,css,scss,less}📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
Files:
**/*.{tsx,ts,jsx,js,vue}📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
Files:
**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
Files:
apps/api/src/**/*.{controller,service}.ts📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Files:
🧠 Learnings (4)📓 Common learnings📚 Learning: 2025-12-22T09:48:22.120ZApplied to files:
📚 Learning: 2025-11-25T03:04:12.836ZApplied to files:
📚 Learning: 2025-11-25T03:04:12.836ZApplied to files:
🧬 Code graph analysis (2)packages/utils/src/models.ts (1)
apps/api/src/modules/skill/skill.service.ts (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (14)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/api/src/modules/provider/auto-model-router.service.ts (2)
405-421: Potential fragility in scene derivation logic.The
deriveSceneFromModemethod usesstring.includes()which could be fragile if future modes contain multiple keywords. For example, a hypothetical mode like'copilot_agent_hybrid'would match'copilot'first (which is correct due to the order), but this behavior relies on the order of checks.Consider using exact string matching or a lookup map for more robust mode-to-scene mapping, especially since
getModelSceneFromModeinpackages/utils/src/models.tsuses exact equality checks.🔎 Alternative: Use the centralized helper
- private deriveSceneFromMode(mode?: string): string { - if (!mode) { - return 'chat'; - } - - // Map mode to scene - if (mode.includes('copilot')) { - return 'copilot'; - } - - if (mode.includes('agent')) { - return 'agent'; - } - - // Default fallback - return 'chat'; - } + private deriveSceneFromMode(mode?: string): string { + // Use the centralized helper from utils + return getModelSceneFromMode(mode); + }This ensures consistency with the mode-to-scene mapping used throughout the codebase.
437-470: Improve documentation and add logging for scene mismatch during routing.The conditional persistence at lines 448-449 is documented in the JSDoc (
@param externalScene), but the logic needs better inline explanation and observability:
- Add an inline comment explaining the business reason for conditional persistence (why scenes should match)
- Add debug logging when scenes don't match to aid troubleshooting and routing analysis
- Verify this conditional persistence pattern is applied consistently across all routing strategies (confirmed: it is applied to rule-based, tool-based, and fallback paths)
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/api/prisma/schema.prismaapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.tsapps/api/src/modules/skill/skill.service.tspackages/skill-template/src/skills/agent.tspackages/utils/src/id.tspackages/utils/src/models.ts
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,jsx,tsx}: Always use optional chaining (?.) when accessing object properties
Always use nullish coalescing (??) or default values for potentially undefined values
Always check array existence before using array methods
Always validate object properties before destructuring
Always use single quotes for string literals in JavaScript/TypeScript code
**/*.{js,ts,jsx,tsx}: Use semicolons at the end of statements
Include spaces around operators (e.g.,a + binstead ofa+b)
Always use curly braces for control statements
Place opening braces on the same line as their statement
**/*.{js,ts,jsx,tsx}: Group import statements in order: React/framework libraries, third-party libraries, internal modules, relative path imports, type imports, style imports
Sort imports alphabetically within each import group
Leave a blank line between import groups
Extract complex logic into custom hooks
Use functional updates for state (e.g.,setCount(prev => prev + 1))
Split complex state into multiple state variables rather than single large objects
Use useReducer for complex state logic instead of multiple useState calls
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}: All code comments MUST be written in English
All variable names, function names, class names, and other identifiers MUST use English words
Comments should be concise and explain 'why' rather than 'what'
Use proper grammar and punctuation in comments
Keep comments up-to-date when code changes
Document complex logic, edge cases, and important implementation details
Use clear, descriptive names that indicate purpose
Avoid abbreviations unless they are universally understood
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Use JSDoc style comments for functions and classes in JavaScript/TypeScript
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{js,jsx,ts,tsx}: Use single quotes for string literals in TypeScript/JavaScript
Always use optional chaining (?.) when accessing object properties in TypeScript/JavaScript
Always use nullish coalescing (??) or default values for potentially undefined values in TypeScript/JavaScript
Always check array existence before using array methods in TypeScript/JavaScript
Validate object properties before destructuring in TypeScript/JavaScript
Use ES6+ features like arrow functions, destructuring, and spread operators in TypeScript/JavaScript
Avoid magic numbers and strings - use named constants in TypeScript/JavaScript
Use async/await instead of raw promises for asynchronous code in TypeScript/JavaScript
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
**/*.{ts,tsx}: Avoid usinganytype whenever possible - useunknowntype instead with proper type guards
Always define explicit return types for functions, especially for public APIs
Prefer extending existing types over creating entirely new types
Use TypeScript utility types (Partial<T>,Pick<T, K>,Omit<T, K>,Readonly<T>,Record<K, T>) to derive new types
Use union types and intersection types to combine existing types
Always import types explicitly using theimport typesyntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,jsx,tsx,css,json}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Maximum line length of 100 characters
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Use 2 spaces for indentation, no tabs
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
No trailing whitespace at the end of lines
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{css,scss,sass,less,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
**/*.{css,scss,sass,less,js,jsx,ts,tsx}: Primary color (#155EEF) should be used for main brand color in buttons, links, and accents
Error color (#F04438) should be used for error states and destructive actions
Success color (#12B76A) should be used for success states and confirmations
Warning color (#F79009) should be used for warnings and important notifications
Info color (#0BA5EC) should be used for informational elements
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
**/*.{tsx,ts}: Use the translation wrapper component and useTranslation hook in components
Ensure all user-facing text is translatable
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{tsx,ts,json}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Support dynamic content with placeholders in translations
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{tsx,ts,jsx,js,vue,css,scss,less}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue,css,scss,less}: Use the primary blue (#155EEF) for main UI elements, CTAs, and active states
Use red (#F04438) only for errors, warnings, and destructive actions
Use green (#12B76A) for success states and confirmations
Use orange (#F79009) for warning states and important notifications
Use blue (#0BA5EC) for informational elements
Primary buttons should be solid with the primary color
Secondary buttons should have a border with transparent or light background
Danger buttons should use the error color
Use consistent padding, border radius, and hover states for all buttons
Follow fixed button sizes based on their importance and context
Use consistent border radius (rounded-lg) for all cards
Apply light shadows (shadow-sm) for card elevation
Maintain consistent padding inside cards (p-4orp-6)
Use subtle borders for card separation
Ensure proper spacing between card elements
Apply consistent styling to all form inputs
Use clear visual indicators for focus, hover, and error states in form elements
Apply proper spacing between elements using 8px, 16px, 24px increments
Ensure proper alignment of elements (left, center, or right)
Use responsive layouts that work across different device sizes
Maintain a minimum contrast ratio of 4.5:1 for text
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{tsx,ts,jsx,js,vue}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue}: Include appropriate loading states for async actions in buttons
Group related form elements with appropriate spacing
Provide clear validation feedback for forms
Ensure proper labeling and accessibility for form elements
Ensure all interactive elements are keyboard accessible
Include appropriate ARIA attributes for complex components
Provide alternative text for images and icons
Support screen readers with semantic HTML elements
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
**/*.{ts,tsx,js,jsx}: Follow the TypeScript/JavaScript style guidelines
Ensure code is well-tested and documented
Files:
packages/skill-template/src/skills/agent.tsapps/api/src/modules/provider/provider.module.tspackages/utils/src/id.tsapps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/models.tsapps/api/src/modules/skill/skill.service.ts
apps/api/src/**/*.{controller,service}.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Implement proper error handling in API modules
Files:
apps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/skill/skill.service.ts
🧠 Learnings (2)
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/{auth,user,project,canvas,rag,knowledge,search,skill,share,code-artifact}/**/*.{controller,service}.ts : Use dependency injection for module dependencies in NestJS
Applied to files:
apps/api/src/modules/provider/provider.module.tsapps/api/src/modules/skill/skill.service.ts
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/{auth,user,project,canvas,rag,knowledge,search,skill,share,code-artifact}/**/*.{ts,tsx} : Follow NestJS module structure with controllers, services, and DTOs in dedicated module directories
Applied to files:
apps/api/src/modules/provider/provider.module.ts
🧬 Code graph analysis (3)
packages/skill-template/src/skills/agent.ts (4)
packages/utils/src/models.ts (1)
getModelSceneFromMode(10-14)packages/openapi-schema/src/types.gen.ts (1)
mode(34-34)packages/request/src/requests/types.gen.ts (1)
mode(34-34)packages/ai-workspace-common/src/requests/types.gen.ts (1)
mode(34-34)
apps/api/src/modules/provider/auto-model-router.service.ts (5)
packages/openapi-schema/src/types.gen.ts (2)
mode(34-34)LLMModelConfig(5937-5966)apps/api/src/modules/tool/utils/token.ts (1)
safeParseJSON(371-377)apps/api/src/modules/tool/sandbox/scalebox.dto.ts (1)
error(218-224)packages/utils/src/auto-model.ts (3)
isAutoModel(92-112)selectAutoModel(41-48)AUTO_MODEL_ROUTING_PRIORITY(14-20)packages/utils/src/id.ts (1)
genRoutingResultID(329-331)
apps/api/src/modules/skill/skill.service.ts (2)
apps/api/src/modules/provider/auto-model-router.service.ts (1)
RoutingContext(59-96)packages/utils/src/models.ts (1)
getModelSceneFromMode(10-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build / Build
🔇 Additional comments (16)
packages/utils/src/models.ts (1)
5-14: LGTM!The
getModelSceneFromModefunction provides clear, centralized mode-to-scene mapping logic. The implementation correctly handles the three mode cases with appropriate fallback to 'chat'.packages/skill-template/src/skills/agent.ts (3)
20-20: LGTM!Good refactoring to use the centralized
getModelSceneFromModehelper, which improves maintainability and consistency across the codebase.
109-110: LGTM!The replacement of inline conditional logic with
getModelSceneFromMode(mode)correctly implements the centralized mapping, and the updated comment accurately reflects the new node_agent → agent scene mapping.
137-138: LGTM!Consistent usage of
getModelSceneFromMode(mode)ensures uniform scene resolution across both the preprocessing and initialization phases.apps/api/prisma/schema.prisma (2)
2186-2222: LGTM!The
AutoModelRoutingRulemodel is well-designed with appropriate fields, indexes, and constraints:
- Unique constraint on
[scene, ruleName]prevents duplicate rules per scene- Composite index on
[scene, enabled, priority(sort: Desc), ruleId]efficiently supports the priority-based rule lookup pattern used in the service- JSON storage for
conditionandtargetprovides necessary flexibility for rule matching
2224-2264: LGTM!The
AutoModelRoutingResultmodel appropriately tracks routing decisions:
- Unique constraint on
[actionResultId, actionResultVersion]ensures one routing result per action execution- Index on
[userId, createdAt(sort: Desc)]supports efficient user-scoped queries- Optional
actionResultIdandactionResultVersioncorrectly handle cases where routing occurs before action creation- Denormalized
matchedRuleNamefield improves query performance for viewing routing decisionspackages/utils/src/id.ts (2)
54-55: LGTM!The new ID prefixes follow the established naming convention and provide clear identifiers for routing-related entities.
329-335: LGTM!The ID generator functions are consistent with existing patterns in the file and correctly use the new prefixes.
apps/api/src/modules/provider/provider.module.ts (1)
4-11: LGTM!The module correctly registers and exports
AutoModelRoutingService, following NestJS best practices for dependency injection and module organization.Based on learnings, this follows the established pattern for module structure in the API.
apps/api/src/modules/skill/skill.service.ts (4)
510-524: LGTM!The routing implementation correctly targets only the primary scene while preserving auxiliary scenes (titleGeneration, queryAnalysis, image, video, audio). This design prevents unintended routing side effects on non-primary models.
833-836: LGTM!The refactoring to use
getModelSceneFromModeformodelNamederivation ensures consistency with the routing logic and correctly uses the routedmodelConfigMap.
529-557: Clarify surface model tracking vs. execution/billing model separation.The distinction between tracked model (
param.modelItemId- for UI/audit) and execution model (providerItem- for actual execution and billing) requires clarification:
- Line 532-534:
param.modelItemIdis set to original itemId to track the user's selected model for UI and audit purposes, not billing.- Line 536-539:
providerItem(resolved via routed itemId) is used for execution, and itscreditBilling(line 570) determines the actual cost charged to users.- Line 546-557:
routedDatainjection correctly preserves original model IDs for audit tracking when auto-routing occurs.The current design charges users for the model they actually receive (routed), while preserving the original selection in metadata. Verify this billing approach aligns with intended business logic—users should understand they pay for executed models, not selected models.
Likely an incorrect or invalid review comment.
487-502: inputPrompt field is not currently used in routing logic.The routing service does not consume
inputPromptdespite its JSDoc indicating it's "for regex matching." TheRoutingContext.inputPromptfield is passed but never referenced inRuleRouteror any routing decision logic. TheRuleConditioninterface only evaluatestoolsetInventoryKeys. Either remove the unused field or implement the regex matching logic if planned for future use.The
actionResultVersionversioning logic is correct and consistent with the Prisma schema (version Int @default(0)) and action result creation logic elsewhere in the file.apps/api/src/modules/provider/auto-model-router.service.ts (3)
203-376: LGTM!The
RuleCacheimplementation demonstrates solid design:
- 3-minute TTL with periodic refresh provides a good balance between freshness and performance
unref()on the timer (line 340) correctly prevents blocking process exit- Deep comparison in
hasRulesChangedensures accurate change detection- Fallback to cached rules on fetch failure (lines 272-276) provides resilience
658-706: LGTM!The non-blocking
saveRoutingResultpattern (lines 667-676) correctly prevents routing persistence failures from affecting the main request flow. The async save operation includes proper error handling with logging.
162-178: The nested optional chaining patterntoolset.toolset?.keyis intentional and consistent across the codebase. This structure is confirmed in the external@refly/openapi-schemapackage'sGenericToolsettype, which contains a nestedtoolsetproperty. The same pattern appears in 8+ other files (tool.service.ts, composio.service.ts, pilot-engine.ts, workflow-app.service.ts, intent-analysis.service.ts, etc.), confirming this is the established design. The optional chaining is properly applied per coding guidelines, and the truthiness check on line 172 (if (inventoryKey && keysSet.has(inventoryKey))) safely handles the potential undefined value. No changes are needed.
8b18d05 to
c4279d0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
apps/api/src/modules/provider/auto-model-router.service.ts (1)
545-559: Reasoning model exclusion is intentional.Lines 551-552 explicitly exclude models with
capabilities.reasoning === truefrom auto-routing. This exclusion is documented in comments and appears intentional, likely to ensure reasoning models are only used when explicitly selected.However, this design choice lacks configuration flexibility. If there are scenarios where reasoning models should be available for auto-routing, consider making this behavior configurable.
This concern was already raised in past review comments on this file.
🧹 Nitpick comments (3)
apps/api/src/modules/skill/skill.service.ts (1)
510-539: Consider null safety for routedProviderItem.At line 518-520,
await this.autoModelRoutingService.route()returns aProviderItemModel, but there's a possibility thatmodelProviderMap[primaryScene]could be undefined if routing fails for some reason. Consider adding explicit null checks or using optional chaining when accessingroutedProviderItemat line 530.🔎 Suggested defensive coding
- const originalProviderItem = originalModelProviderMap[primaryScene]; - const routedProviderItem = modelProviderMap[primaryScene]; + const originalProviderItem = originalModelProviderMap[primaryScene]; + const routedProviderItem = modelProviderMap[primaryScene]; + + if (!originalProviderItem) { + throw new ProviderItemNotFoundError(`No provider item found for scene ${primaryScene}`); + }apps/api/prisma/schema.prisma (1)
2187-2214: LGTM! Well-designed schema for routing rules.The AutoModelRoutingRule model has:
- Proper indexing for efficient query by scene, enabled status, and priority
- UUID-based ruleId for distributed systems
- Consistent field naming and type choices
Consider implementing application-level validation for the JSON fields (
conditionandtarget) to ensure data integrity beyond schema constraints.apps/api/src/modules/provider/auto-model-router.service.ts (1)
203-376: LGTM! Robust cache implementation with lifecycle management.The
RuleCacheclass demonstrates several best practices:
- Proper lifecycle cleanup via
OnModuleDestroy(line 373)- Non-blocking timer with
unref()at line 340- Fallback to expired cache on database errors (lines 274-276)
- Deep comparison for change detection
The 3-minute TTL with periodic refresh balances freshness with database load.
Consider adding a maximum cache size limit to prevent unbounded growth if many scenes are used over time.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/api/prisma/schema.prismaapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.tsapps/api/src/modules/skill/skill.service.tspackages/skill-template/src/skills/agent.tspackages/utils/src/id.tspackages/utils/src/models.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/utils/src/id.ts
- packages/utils/src/models.ts
- packages/skill-template/src/skills/agent.ts
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,jsx,tsx}: Always use optional chaining (?.) when accessing object properties
Always use nullish coalescing (??) or default values for potentially undefined values
Always check array existence before using array methods
Always validate object properties before destructuring
Always use single quotes for string literals in JavaScript/TypeScript code
**/*.{js,ts,jsx,tsx}: Use semicolons at the end of statements
Include spaces around operators (e.g.,a + binstead ofa+b)
Always use curly braces for control statements
Place opening braces on the same line as their statement
**/*.{js,ts,jsx,tsx}: Group import statements in order: React/framework libraries, third-party libraries, internal modules, relative path imports, type imports, style imports
Sort imports alphabetically within each import group
Leave a blank line between import groups
Extract complex logic into custom hooks
Use functional updates for state (e.g.,setCount(prev => prev + 1))
Split complex state into multiple state variables rather than single large objects
Use useReducer for complex state logic instead of multiple useState calls
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}: All code comments MUST be written in English
All variable names, function names, class names, and other identifiers MUST use English words
Comments should be concise and explain 'why' rather than 'what'
Use proper grammar and punctuation in comments
Keep comments up-to-date when code changes
Document complex logic, edge cases, and important implementation details
Use clear, descriptive names that indicate purpose
Avoid abbreviations unless they are universally understood
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Use JSDoc style comments for functions and classes in JavaScript/TypeScript
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{js,jsx,ts,tsx}: Use single quotes for string literals in TypeScript/JavaScript
Always use optional chaining (?.) when accessing object properties in TypeScript/JavaScript
Always use nullish coalescing (??) or default values for potentially undefined values in TypeScript/JavaScript
Always check array existence before using array methods in TypeScript/JavaScript
Validate object properties before destructuring in TypeScript/JavaScript
Use ES6+ features like arrow functions, destructuring, and spread operators in TypeScript/JavaScript
Avoid magic numbers and strings - use named constants in TypeScript/JavaScript
Use async/await instead of raw promises for asynchronous code in TypeScript/JavaScript
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
**/*.{ts,tsx}: Avoid usinganytype whenever possible - useunknowntype instead with proper type guards
Always define explicit return types for functions, especially for public APIs
Prefer extending existing types over creating entirely new types
Use TypeScript utility types (Partial<T>,Pick<T, K>,Omit<T, K>,Readonly<T>,Record<K, T>) to derive new types
Use union types and intersection types to combine existing types
Always import types explicitly using theimport typesyntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,jsx,tsx,css,json}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Maximum line length of 100 characters
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Use 2 spaces for indentation, no tabs
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
No trailing whitespace at the end of lines
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
apps/api/src/**/*.{controller,service}.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Implement proper error handling in API modules
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.ts
**/*.{css,scss,sass,less,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
**/*.{css,scss,sass,less,js,jsx,ts,tsx}: Primary color (#155EEF) should be used for main brand color in buttons, links, and accents
Error color (#F04438) should be used for error states and destructive actions
Success color (#12B76A) should be used for success states and confirmations
Warning color (#F79009) should be used for warnings and important notifications
Info color (#0BA5EC) should be used for informational elements
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
**/*.{tsx,ts}: Use the translation wrapper component and useTranslation hook in components
Ensure all user-facing text is translatable
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{tsx,ts,json}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Support dynamic content with placeholders in translations
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{tsx,ts,jsx,js,vue,css,scss,less}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue,css,scss,less}: Use the primary blue (#155EEF) for main UI elements, CTAs, and active states
Use red (#F04438) only for errors, warnings, and destructive actions
Use green (#12B76A) for success states and confirmations
Use orange (#F79009) for warning states and important notifications
Use blue (#0BA5EC) for informational elements
Primary buttons should be solid with the primary color
Secondary buttons should have a border with transparent or light background
Danger buttons should use the error color
Use consistent padding, border radius, and hover states for all buttons
Follow fixed button sizes based on their importance and context
Use consistent border radius (rounded-lg) for all cards
Apply light shadows (shadow-sm) for card elevation
Maintain consistent padding inside cards (p-4orp-6)
Use subtle borders for card separation
Ensure proper spacing between card elements
Apply consistent styling to all form inputs
Use clear visual indicators for focus, hover, and error states in form elements
Apply proper spacing between elements using 8px, 16px, 24px increments
Ensure proper alignment of elements (left, center, or right)
Use responsive layouts that work across different device sizes
Maintain a minimum contrast ratio of 4.5:1 for text
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{tsx,ts,jsx,js,vue}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue}: Include appropriate loading states for async actions in buttons
Group related form elements with appropriate spacing
Provide clear validation feedback for forms
Ensure proper labeling and accessibility for form elements
Ensure all interactive elements are keyboard accessible
Include appropriate ARIA attributes for complex components
Provide alternative text for images and icons
Support screen readers with semantic HTML elements
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
**/*.{ts,tsx,js,jsx}: Follow the TypeScript/JavaScript style guidelines
Ensure code is well-tested and documented
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
🧠 Learnings (2)
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/{auth,user,project,canvas,rag,knowledge,search,skill,share,code-artifact}/**/*.{controller,service}.ts : Use dependency injection for module dependencies in NestJS
Applied to files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/provider.module.ts
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/{auth,user,project,canvas,rag,knowledge,search,skill,share,code-artifact}/**/*.{ts,tsx} : Follow NestJS module structure with controllers, services, and DTOs in dedicated module directories
Applied to files:
apps/api/src/modules/provider/provider.module.ts
🧬 Code graph analysis (1)
apps/api/src/modules/skill/skill.service.ts (2)
apps/api/src/modules/provider/auto-model-router.service.ts (1)
RoutingContext(59-96)packages/utils/src/models.ts (1)
getModelSceneFromMode(10-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build / Build
🔇 Additional comments (10)
apps/api/src/modules/provider/provider.module.ts (1)
4-4: LGTM! Proper NestJS module integration.The AutoModelRoutingService is correctly registered as a provider and exported for dependency injection, following NestJS best practices.
Based on learnings, this aligns with the requirement to use dependency injection for module dependencies in NestJS.
Also applies to: 10-11
apps/api/src/modules/skill/skill.service.ts (3)
47-47: LGTM! Clean integration of routing dependencies.The imports and constructor injection properly integrate the AutoModelRoutingService and supporting utilities. The dependency injection follows NestJS best practices.
Also applies to: 69-69, 109-109
833-836: LGTM! Cleaner model name resolution.The refactored
getModelNameForModefunction usinggetModelSceneFromModeprovides consistent scene mapping and is more maintainable than the previous mode-based conditionals.
487-502: No privacy concern - inputPrompt is correctly excluded from routing result persistence.The
inputPromptfield is passed to the routing context but is not persisted to the database, not logged, and not used in any routing logic. ThesaveRoutingResultAsyncmethod saves only the routing decision metadata (strategy, matched rule, selected model), explicitly excluding user input. The existing code already implements the privacy protection stated in the comment.Likely an incorrect or invalid review comment.
apps/api/src/modules/provider/auto-model-router.service.ts (5)
18-96: LGTM! Well-structured type definitions.The interfaces and enums provide clear contracts for the routing system:
RuleConditionsupports extensible matching logicRoutingStrategyenum covers all fallback tiersRoutingContextincludes comprehensive context for routing decisionsThe JSDoc comments are helpful and follow the coding guidelines for explaining 'why' rather than 'what'.
102-189: LGTM! Clean rule matching implementation.The
RuleRouterclass provides well-encapsulated rule matching logic:
- Stateless design with context injection
- Efficient Set-based toolset matching at lines 168-176
- Proper null handling for invalid rules
- Clear separation of concerns
The implementation follows SOLID principles effectively.
437-539: LGTM! Well-structured multi-tier routing strategy.The
route()method implements a clear priority cascade:
- Rule-based routing
- Tool-based routing
- Random selection
- Built-in priority list
- First available fallback
The scene validation at lines 448-449 ensures routing results are only saved when they match the expected context, preventing data inconsistencies.
584-621: LGTM! Clear tool-based routing logic.The
routeByToolsmethod has explicit guards:
- Only applies to
node_agentmode withagentscene (lines 590-596)- Checks environment configuration before proceeding
- Handles missing models gracefully
This temporary strategy is well-isolated and can be easily removed or modified later.
658-714: LGTM! Non-blocking result persistence with proper error handling.The routing result persistence is designed correctly:
- Async operation that doesn't block routing decisions (line 667)
- Errors are logged but don't fail the request (line 675)
- Comprehensive metadata captured for observability
This fire-and-forget approach is appropriate for non-critical tracking data.
apps/api/prisma/schema.prisma (1)
2217-2248: Verify nullable fields in the unique constraint on lines 2224–2225 and 2245.Both
actionResultIdandactionResultVersionare nullable but included in the composite unique constraint@@unique([actionResultId, actionResultVersion]). Prisma requires all fields that make up a unique constraint to be mandatory fields. Either make these fields required (non-nullable) if all routing results must have an associated action, or remove them from the unique constraint and use a different approach to prevent duplicates.
c4279d0 to
b499efb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/api/prisma/schema.prisma (1)
2190-2190: Consider using consistent ID generation pattern.The
ruleIdfield uses@default(uuid())which generates PostgreSQL UUIDs, while other entities in the schema use CUID2-based IDs (e.g.,genSkillID(),genActionResultID()). The codebase includesgenRoutingRuleID()in the utilities package, but it's not referenced in the Prisma schema default.This inconsistency could lead to:
- Mixed ID formats across the database
- Difficulty in identifying entity types from ID prefixes
- Inconsistent ID generation patterns
Consider aligning with the existing ID generation pattern
If CUID2-based IDs are preferred (as suggested by the presence of
genRoutingRuleID()), consider either:
- Removing the
@default(uuid())and generating IDs in application code usinggenRoutingRuleID(), or- If PostgreSQL UUIDs are intentionally chosen for this model, document the rationale
apps/api/src/modules/provider/auto-model-router.service.ts (1)
105-130: Consider logging when rule target model is not found.When a rule matches but the target model is not in the
modelMap(line 116-126), the router silently continues to the next rule. This could mask configuration errors where rules reference models that don't exist or aren't available to the user.Suggested logging enhancement
Add logging when a matched rule's target model is unavailable:
const selectedModel = this.selectModelFromTarget(target, modelMap); if (selectedModel) { return { providerItem: selectedModel, matchedRule: { ruleId: rule.ruleId, ruleName: rule.ruleName, }, }; +} else { + // Log when rule matches but target model is not available + this.logger?.debug( + `Rule '${rule.ruleName}' (${rule.ruleId}) matched but target model '${target.model}' not found` + ); }Note: Would need to inject logger into RuleRouter or pass it in constructor.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/api/prisma/schema.prismaapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.tsapps/api/src/modules/skill/skill.service.tspackages/skill-template/src/skills/agent.tspackages/utils/src/id.tspackages/utils/src/models.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/skill-template/src/skills/agent.ts
- packages/utils/src/models.ts
- packages/utils/src/id.ts
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,jsx,tsx}: Always use optional chaining (?.) when accessing object properties
Always use nullish coalescing (??) or default values for potentially undefined values
Always check array existence before using array methods
Always validate object properties before destructuring
Always use single quotes for string literals in JavaScript/TypeScript code
**/*.{js,ts,jsx,tsx}: Use semicolons at the end of statements
Include spaces around operators (e.g.,a + binstead ofa+b)
Always use curly braces for control statements
Place opening braces on the same line as their statement
**/*.{js,ts,jsx,tsx}: Group import statements in order: React/framework libraries, third-party libraries, internal modules, relative path imports, type imports, style imports
Sort imports alphabetically within each import group
Leave a blank line between import groups
Extract complex logic into custom hooks
Use functional updates for state (e.g.,setCount(prev => prev + 1))
Split complex state into multiple state variables rather than single large objects
Use useReducer for complex state logic instead of multiple useState calls
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}: All code comments MUST be written in English
All variable names, function names, class names, and other identifiers MUST use English words
Comments should be concise and explain 'why' rather than 'what'
Use proper grammar and punctuation in comments
Keep comments up-to-date when code changes
Document complex logic, edge cases, and important implementation details
Use clear, descriptive names that indicate purpose
Avoid abbreviations unless they are universally understood
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Use JSDoc style comments for functions and classes in JavaScript/TypeScript
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{js,jsx,ts,tsx}: Use single quotes for string literals in TypeScript/JavaScript
Always use optional chaining (?.) when accessing object properties in TypeScript/JavaScript
Always use nullish coalescing (??) or default values for potentially undefined values in TypeScript/JavaScript
Always check array existence before using array methods in TypeScript/JavaScript
Validate object properties before destructuring in TypeScript/JavaScript
Use ES6+ features like arrow functions, destructuring, and spread operators in TypeScript/JavaScript
Avoid magic numbers and strings - use named constants in TypeScript/JavaScript
Use async/await instead of raw promises for asynchronous code in TypeScript/JavaScript
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
**/*.{ts,tsx}: Avoid usinganytype whenever possible - useunknowntype instead with proper type guards
Always define explicit return types for functions, especially for public APIs
Prefer extending existing types over creating entirely new types
Use TypeScript utility types (Partial<T>,Pick<T, K>,Omit<T, K>,Readonly<T>,Record<K, T>) to derive new types
Use union types and intersection types to combine existing types
Always import types explicitly using theimport typesyntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,jsx,tsx,css,json}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Maximum line length of 100 characters
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Use 2 spaces for indentation, no tabs
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
No trailing whitespace at the end of lines
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
apps/api/src/**/*.{controller,service}.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Implement proper error handling in API modules
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.ts
**/*.{css,scss,sass,less,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
**/*.{css,scss,sass,less,js,jsx,ts,tsx}: Primary color (#155EEF) should be used for main brand color in buttons, links, and accents
Error color (#F04438) should be used for error states and destructive actions
Success color (#12B76A) should be used for success states and confirmations
Warning color (#F79009) should be used for warnings and important notifications
Info color (#0BA5EC) should be used for informational elements
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
**/*.{tsx,ts}: Use the translation wrapper component and useTranslation hook in components
Ensure all user-facing text is translatable
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{tsx,ts,json}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Support dynamic content with placeholders in translations
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{tsx,ts,jsx,js,vue,css,scss,less}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue,css,scss,less}: Use the primary blue (#155EEF) for main UI elements, CTAs, and active states
Use red (#F04438) only for errors, warnings, and destructive actions
Use green (#12B76A) for success states and confirmations
Use orange (#F79009) for warning states and important notifications
Use blue (#0BA5EC) for informational elements
Primary buttons should be solid with the primary color
Secondary buttons should have a border with transparent or light background
Danger buttons should use the error color
Use consistent padding, border radius, and hover states for all buttons
Follow fixed button sizes based on their importance and context
Use consistent border radius (rounded-lg) for all cards
Apply light shadows (shadow-sm) for card elevation
Maintain consistent padding inside cards (p-4orp-6)
Use subtle borders for card separation
Ensure proper spacing between card elements
Apply consistent styling to all form inputs
Use clear visual indicators for focus, hover, and error states in form elements
Apply proper spacing between elements using 8px, 16px, 24px increments
Ensure proper alignment of elements (left, center, or right)
Use responsive layouts that work across different device sizes
Maintain a minimum contrast ratio of 4.5:1 for text
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{tsx,ts,jsx,js,vue}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue}: Include appropriate loading states for async actions in buttons
Group related form elements with appropriate spacing
Provide clear validation feedback for forms
Ensure proper labeling and accessibility for form elements
Ensure all interactive elements are keyboard accessible
Include appropriate ARIA attributes for complex components
Provide alternative text for images and icons
Support screen readers with semantic HTML elements
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
**/*.{ts,tsx,js,jsx}: Follow the TypeScript/JavaScript style guidelines
Ensure code is well-tested and documented
Files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.ts
🧠 Learnings (2)
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/{auth,user,project,canvas,rag,knowledge,search,skill,share,code-artifact}/**/*.{controller,service}.ts : Use dependency injection for module dependencies in NestJS
Applied to files:
apps/api/src/modules/skill/skill.service.tsapps/api/src/modules/provider/provider.module.ts
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/{auth,user,project,canvas,rag,knowledge,search,skill,share,code-artifact}/**/*.{ts,tsx} : Follow NestJS module structure with controllers, services, and DTOs in dedicated module directories
Applied to files:
apps/api/src/modules/provider/provider.module.ts
🧬 Code graph analysis (1)
apps/api/src/modules/skill/skill.service.ts (2)
apps/api/src/modules/provider/auto-model-router.service.ts (1)
RoutingContext(59-96)packages/utils/src/models.ts (1)
getModelSceneFromMode(10-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build / Build
🔇 Additional comments (11)
apps/api/src/modules/provider/provider.module.ts (1)
4-11: LGTM!The dependency injection wiring correctly registers and exports
AutoModelRoutingService, following NestJS patterns and aligning with the module structure guidelines.apps/api/src/modules/provider/auto-model-router.service.ts (4)
18-96: LGTM! Well-designed routing interfaces.The interface definitions are clean and well-documented:
RuleConditionprovides extensible AND-logic matchingRoutingContextcaptures comprehensive context for routing decisionsRoutingStrategyenum clearly defines the fallback hierarchy- Good JSDoc comments explaining the purpose of each field
203-376: LGTM! Robust cache implementation.The
RuleCacheclass is well-designed with:
- Proper lifecycle management via
OnModuleDestroy- Reasonable TTL (3 minutes) with periodic background refresh
- Resilient error handling (falls back to cached rules on fetch failure)
- Deep rule comparison to detect changes
- Proper timer cleanup with
unref()to avoid blocking process exitThe intentional exclusion of timestamps from
isRuleEqual()makes sense since metadata updates shouldn't trigger change notifications.
545-559: Reasoning model exclusion is documented.The explicit exclusion of reasoning models from auto-routing (line 552) aligns with past review feedback. While this limitation was previously flagged, the design choice appears intentional for the current implementation.
As noted in the past review, consider making this behavior configurable in future iterations if reasoning models should be available for auto-routing in specific scenarios.
Based on learnings, the reasoning model exclusion has been previously discussed and is intentional in the current design.
565-715: LGTM! Clean routing implementation.The routing methods are well-structured:
- Clear separation of concerns across routing strategies
- Proper error handling with non-blocking persistence
- Defensive null checking in helper methods
- Good logging for monitoring routing decisions
apps/api/src/modules/skill/skill.service.ts (5)
47-47: LGTM! Proper dependency injection.The imports and constructor injection correctly introduce
AutoModelRoutingServiceandRoutingContext, following NestJS patterns and the coding guidelines for dependency injection.As per coding guidelines, dependency injection is properly used for module dependencies in NestJS.
Also applies to: 69-69, 109-109
487-502: LGTM! Well-constructed routing context.The
RoutingContextis properly constructed with:
- Correct
actionResultVersioncalculation (incrementing from existing result or starting at 0)- Comprehensive context information for rule-based routing
- Privacy-conscious handling of
inputPrompt(noted as not stored)- All necessary fields for matching routing rules
526-557: LGTM! Proper surface vs. actual provider item handling.The code correctly:
- Distinguishes between surface model (
param.modelItemId) for billing/UI and routed model (providerItem) for execution- Injects
routedDatametadata to track routing decisions- Preserves original identifiers for audit trails
- Handles the isAutoModelRouted flag for downstream processing
833-836: LGTM! Cleaner model name resolution.The refactored
getModelNameForMode()method is much cleaner and more maintainable:
- Uses
getModelSceneFromMode()for consistent scene derivation- Replaces mode-specific branching with scene-based lookup
- Aligns with the overall routing approach
510-524: The code already includes explicit validation with the conditionif (originalModelProviderMap[primaryScene])on line 518, which prevents routing when the primary scene is missing. No changes needed.Likely an incorrect or invalid review comment.
apps/api/prisma/schema.prisma (1)
2224-2245: Schema allows nullable field in unique constraint, but code always assigns numeric values.While
actionResultVersionis marked as optional (Int?) in the Prisma schema, the routing service always assigns it a numeric value (0 or higher) and never sets it to NULL. The unique constraint@@unique([actionResultId, actionResultVersion])therefore works as intended without the multiple-NULL issue initially flagged. No changes needed.Likely an incorrect or invalid review comment.
b499efb to
39dc7d9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
apps/api/src/modules/provider/auto-model-router.service.ts (3)
106-131: Consider logging failed rule parsing for observability.When
safeParseJSON(rule.target)returnsnull(line 112), the code silently continues to the next rule. This could make debugging difficult if a rule is misconfigured.Optional improvement
route( rules: AutoModelRoutingRuleModel[], modelMap: Map<string, ProviderItemModel>, ): RuleRouteResult | null { for (const rule of rules) { if (this.matchRule(rule)) { const target = safeParseJSON(rule.target) as RoutingTarget; if (!target) { + this.logger.warn(`Failed to parse target for rule ${rule.ruleId}: ${rule.target}`); continue; } const selectedModel = this.selectModelFromTarget(target, modelMap); if (selectedModel) { return { providerItem: selectedModel, matchedRule: { ruleId: rule.ruleId, ruleName: rule.ruleName, }, }; } } } return null; }Note: You'll need to pass a logger instance to the RuleRouter constructor.
285-300: Array comparison assumes consistent ordering.The
hasRulesChanged()method compares rules by index position (line 293-296), assuming the database returns rules in the same order. Since the query orders by[{ priority: 'desc' }, { ruleId: 'asc' }](line 256), this should be stable, but the comparison is fragile to any changes in the ordering logic.More robust comparison approach
Consider using a Set-based comparison or comparing rules by
ruleIdinstead of array position to make the logic more resilient:private hasRulesChanged( oldRules: AutoModelRoutingRuleModel[], newRules: AutoModelRoutingRuleModel[], ): boolean { if (oldRules.length !== newRules.length) { return true; } + // Create a map of ruleId -> rule for efficient lookup + const oldRulesMap = new Map(oldRules.map(r => [r.ruleId, r])); + + for (const newRule of newRules) { + const oldRule = oldRulesMap.get(newRule.ruleId); + if (!oldRule || !this.isRuleEqual(oldRule, newRule)) { + return true; + } + } - for (let i = 0; i < oldRules.length; i++) { - if (!this.isRuleEqual(oldRules[i], newRules[i])) { - return true; - } - } return false; }However, the current implementation is acceptable if rule ordering is guaranteed to be stable.
619-637: Non-blocking persistence could silently lose routing metadata.Line 636 catches and logs errors from
saveRoutingResultAsync()but doesn't propagate them. While this prevents routing failures from blocking execution, it means routing metadata might be lost without the caller knowing.Consider one of these approaches:
- Add metrics/monitoring for failed routing result saves
- Use a dead-letter queue for failed saves
- At minimum, increment an error counter that can be monitored
private saveRoutingResult(...args) { this.saveRoutingResultAsync(...args) .catch((err) => { this.logger.warn('Failed to save routing result', err); // Add metric or monitoring here // this.metrics.incrementRoutingResultSaveFailures(); }); }
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
apps/api/prisma/schema.prismaapps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/provider/provider.module.tsapps/api/src/modules/skill/skill.service.tspackages/skill-template/src/skills/agent.tspackages/utils/src/id.tspackages/utils/src/models.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- apps/api/src/modules/provider/provider.module.ts
- packages/skill-template/src/skills/agent.ts
- packages/utils/src/models.ts
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,ts,jsx,tsx}: Always use optional chaining (?.) when accessing object properties
Always use nullish coalescing (??) or default values for potentially undefined values
Always check array existence before using array methods
Always validate object properties before destructuring
Always use single quotes for string literals in JavaScript/TypeScript code
**/*.{js,ts,jsx,tsx}: Use semicolons at the end of statements
Include spaces around operators (e.g.,a + binstead ofa+b)
Always use curly braces for control statements
Place opening braces on the same line as their statement
**/*.{js,ts,jsx,tsx}: Group import statements in order: React/framework libraries, third-party libraries, internal modules, relative path imports, type imports, style imports
Sort imports alphabetically within each import group
Leave a blank line between import groups
Extract complex logic into custom hooks
Use functional updates for state (e.g.,setCount(prev => prev + 1))
Split complex state into multiple state variables rather than single large objects
Use useReducer for complex state logic instead of multiple useState calls
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
**/*.{js,ts,tsx,jsx,py,java,cpp,c,cs,rb,go,rs,php,swift,kt,scala,r,m,mm,sql}: All code comments MUST be written in English
All variable names, function names, class names, and other identifiers MUST use English words
Comments should be concise and explain 'why' rather than 'what'
Use proper grammar and punctuation in comments
Keep comments up-to-date when code changes
Document complex logic, edge cases, and important implementation details
Use clear, descriptive names that indicate purpose
Avoid abbreviations unless they are universally understood
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/00-language-priority.mdc)
Use JSDoc style comments for functions and classes in JavaScript/TypeScript
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/01-code-style.mdc)
**/*.{js,jsx,ts,tsx}: Use single quotes for string literals in TypeScript/JavaScript
Always use optional chaining (?.) when accessing object properties in TypeScript/JavaScript
Always use nullish coalescing (??) or default values for potentially undefined values in TypeScript/JavaScript
Always check array existence before using array methods in TypeScript/JavaScript
Validate object properties before destructuring in TypeScript/JavaScript
Use ES6+ features like arrow functions, destructuring, and spread operators in TypeScript/JavaScript
Avoid magic numbers and strings - use named constants in TypeScript/JavaScript
Use async/await instead of raw promises for asynchronous code in TypeScript/JavaScript
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/03-typescript-guidelines.mdc)
**/*.{ts,tsx}: Avoid usinganytype whenever possible - useunknowntype instead with proper type guards
Always define explicit return types for functions, especially for public APIs
Prefer extending existing types over creating entirely new types
Use TypeScript utility types (Partial<T>,Pick<T, K>,Omit<T, K>,Readonly<T>,Record<K, T>) to derive new types
Use union types and intersection types to combine existing types
Always import types explicitly using theimport typesyntax
Group type imports separately from value imports
Minimize creating local type aliases for imported types
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,jsx,tsx,css,json}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Maximum line length of 100 characters
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
Use 2 spaces for indentation, no tabs
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{js,ts,jsx,tsx,css,json,yml,yaml,md}
📄 CodeRabbit inference engine (.cursor/rules/04-code-formatting.mdc)
No trailing whitespace at the end of lines
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
apps/api/src/**/*.{controller,service}.ts
📄 CodeRabbit inference engine (.cursor/rules/06-api-structure.mdc)
Implement proper error handling in API modules
Files:
apps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/skill/skill.service.ts
**/*.{css,scss,sass,less,js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/09-design-system.mdc)
**/*.{css,scss,sass,less,js,jsx,ts,tsx}: Primary color (#155EEF) should be used for main brand color in buttons, links, and accents
Error color (#F04438) should be used for error states and destructive actions
Success color (#12B76A) should be used for success states and confirmations
Warning color (#F79009) should be used for warnings and important notifications
Info color (#0BA5EC) should be used for informational elements
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{tsx,ts}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
**/*.{tsx,ts}: Use the translation wrapper component and useTranslation hook in components
Ensure all user-facing text is translatable
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{tsx,ts,json}
📄 CodeRabbit inference engine (.cursor/rules/09-i18n-guidelines.mdc)
Support dynamic content with placeholders in translations
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{tsx,ts,jsx,js,vue,css,scss,less}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue,css,scss,less}: Use the primary blue (#155EEF) for main UI elements, CTAs, and active states
Use red (#F04438) only for errors, warnings, and destructive actions
Use green (#12B76A) for success states and confirmations
Use orange (#F79009) for warning states and important notifications
Use blue (#0BA5EC) for informational elements
Primary buttons should be solid with the primary color
Secondary buttons should have a border with transparent or light background
Danger buttons should use the error color
Use consistent padding, border radius, and hover states for all buttons
Follow fixed button sizes based on their importance and context
Use consistent border radius (rounded-lg) for all cards
Apply light shadows (shadow-sm) for card elevation
Maintain consistent padding inside cards (p-4orp-6)
Use subtle borders for card separation
Ensure proper spacing between card elements
Apply consistent styling to all form inputs
Use clear visual indicators for focus, hover, and error states in form elements
Apply proper spacing between elements using 8px, 16px, 24px increments
Ensure proper alignment of elements (left, center, or right)
Use responsive layouts that work across different device sizes
Maintain a minimum contrast ratio of 4.5:1 for text
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{tsx,ts,jsx,js,vue}
📄 CodeRabbit inference engine (.cursor/rules/11-ui-design-patterns.mdc)
**/*.{tsx,ts,jsx,js,vue}: Include appropriate loading states for async actions in buttons
Group related form elements with appropriate spacing
Provide clear validation feedback for forms
Ensure proper labeling and accessibility for form elements
Ensure all interactive elements are keyboard accessible
Include appropriate ARIA attributes for complex components
Provide alternative text for images and icons
Support screen readers with semantic HTML elements
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursor/rules/08-contributing-guidelines.mdc)
**/*.{ts,tsx,js,jsx}: Follow the TypeScript/JavaScript style guidelines
Ensure code is well-tested and documented
Files:
apps/api/src/modules/provider/auto-model-router.service.tspackages/utils/src/id.tsapps/api/src/modules/skill/skill.service.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: nettee
Repo: refly-ai/refly PR: 1911
File: apps/api/src/modules/provider/auto-model-router.service.ts:545-559
Timestamp: 2025-12-22T09:48:22.120Z
Learning: In apps/api/src/modules/provider/auto-model-router.service.ts, reasoning models (where config.capabilities.reasoning === true) are intentionally excluded from auto-routing in the buildModelMap method. This is a deliberate design decision.
📚 Learning: 2025-12-22T09:48:22.120Z
Learnt from: nettee
Repo: refly-ai/refly PR: 1911
File: apps/api/src/modules/provider/auto-model-router.service.ts:545-559
Timestamp: 2025-12-22T09:48:22.120Z
Learning: In apps/api/src/modules/provider/auto-model-router.service.ts, reasoning models (where config.capabilities.reasoning === true) are intentionally excluded from auto-routing in the buildModelMap method. This is a deliberate design decision.
Applied to files:
apps/api/src/modules/provider/auto-model-router.service.tsapps/api/src/modules/skill/skill.service.tsapps/api/prisma/schema.prisma
📚 Learning: 2025-11-25T03:04:12.836Z
Learnt from: CR
Repo: refly-ai/refly PR: 0
File: .cursor/rules/06-api-structure.mdc:0-0
Timestamp: 2025-11-25T03:04:12.836Z
Learning: Applies to apps/api/src/{auth,user,project,canvas,rag,knowledge,search,skill,share,code-artifact}/**/*.{controller,service}.ts : Use dependency injection for module dependencies in NestJS
Applied to files:
apps/api/src/modules/skill/skill.service.ts
🧬 Code graph analysis (2)
apps/api/src/modules/provider/auto-model-router.service.ts (4)
apps/api/src/modules/tool/utils/token.ts (1)
safeParseJSON(371-377)packages/utils/src/auto-model.ts (3)
isAutoModel(92-112)selectAutoModel(41-48)AUTO_MODEL_ROUTING_PRIORITY(14-20)packages/utils/src/id.ts (1)
genRoutingResultID(329-331)packages/utils/src/models.ts (1)
getModelSceneFromMode(10-14)
apps/api/src/modules/skill/skill.service.ts (2)
apps/api/src/modules/provider/auto-model-router.service.ts (1)
RoutingContext(60-97)packages/utils/src/models.ts (1)
getModelSceneFromMode(10-14)
🔇 Additional comments (10)
packages/utils/src/id.ts (1)
54-55: LGTM! ID generators follow established patterns.The new routing-related ID prefixes and generator functions are consistent with existing conventions in the file and align with the routing system requirements.
Also applies to: 329-335
apps/api/src/modules/provider/auto-model-router.service.ts (3)
1-97: Well-structured type definitions with clear separation of concerns.The interface definitions are comprehensive and well-documented. Good attention to privacy in the
inputPromptfield documentation noting it's not stored.
412-500: Multi-tier routing strategy is well-structured and resilient.The 5-tier fallback approach (rule-based → tool-based → random → priority → first available) provides excellent resilience. Each tier persists its routing decision for observability, which is valuable for debugging and analytics.
545-582: Tool-based routing scope is clearly defined.The explicit checks for
mode === 'node_agent'andscene === 'agent'clearly define when tool-based routing applies. The early returns make the logic easy to follow.apps/api/prisma/schema.prisma (2)
2186-2214: Well-designed routing rule schema with optimal indexes.The
AutoModelRoutingRulemodel has:
- Proper field types for JSON storage (condition, target)
- Sensible defaults (priority = 0, enabled = true)
- Optimal index for query pattern:
[scene, enabled, priority(sort: Desc), ruleId]matches the query in RuleCache.fetchAndCache()
2216-2248: Comprehensive routing result tracking with proper constraints.The
AutoModelRoutingResultmodel captures all necessary routing metadata:
- Links to action results via
[actionResultId, actionResultVersion]unique constraint- Stores matched rule info for observability
- Records both original and selected model IDs for analytics
- Efficient query support with
[userId, createdAt(sort: Desc)]indexapps/api/src/modules/skill/skill.service.ts (4)
47-47: Clean integration of routing service via dependency injection.The new dependencies (
getModelSceneFromMode,AutoModelRoutingService,RoutingContext) are properly imported and injected following NestJS patterns.Based on learnings: Uses dependency injection for module dependencies in NestJS.
Also applies to: 69-69, 109-109
487-502: RoutingContext now includes comprehensive metadata for rule-based routing.The context now captures:
actionResultIdandactionResultVersionfor associating routing decisions with executionsmodefor scene derivationinputPromptfor potential regex matching (noted as not stored for privacy)toolsetsfor tool-based routingThis rich context enables sophisticated routing rules while respecting privacy constraints.
560-572: Routing metadata injection enables tracking without schema changes.Injecting
routedDatainto the config when routing occurs (line 561-571) is a clean way to track routing decisions without modifying the database schema. This metadata can be used for billing, analytics, and debugging.
848-851: Scene derivation is now consistent across routing and execution.Using
getModelSceneFromMode()from the utility module ensures consistent scene mapping throughout the routing and execution flow. This replaces any local derivation logic and reduces the risk of inconsistencies.
- Introduce AutoModelRoutingRule and AutoModelRoutingResult database models - Refactor AutoModelRouter into AutoModelRoutingService with NestJS integration - Implement rule-based routing with in-memory caching and periodic refresh - Support multi-tier routing strategy (Rule-based, Tool-based, legacy strategies) - Add asynchronous tracking for routing decisions and matched rules - Integrate the new routing service into SkillService
39dc7d9 to
eefb838
Compare
Summary
This PR implements a rule-based auto-model routing system. It allows the system to dynamically select the best LLM model based on rules stored in the database, while keeping the existing environment-based fallbacks.
Changes
AutoModelRoutingRuleandAutoModelRoutingResulttables to PrismaAutoModelRoutingServicewith a 3-minute in-memory cache for routing rulesgetModelSceneFromMode()helper to consistently map agent modes to scenesSkillServiceto pass more context (toolsets, input prompt) for smarter routingagentscene fornode_agentmodeSummary by CodeRabbit
New Features
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.