Skip to content

feat: add model alias resolution and HTTP API (Part 2/2) - #111

Merged
yacosta738 merged 1 commit into
feat/model-aliasing-foundationfrom
feat/model-aliasing-integration
Jun 5, 2026
Merged

feat: add model alias resolution and HTTP API (Part 2/2)#111
yacosta738 merged 1 commit into
feat/model-aliasing-foundationfrom
feat/model-aliasing-integration

Conversation

@yacosta738

Copy link
Copy Markdown
Contributor

Summary

Part 2 of 2 for Model Aliasing & Normalization (#47). This PR integrates alias resolution into the routing flow, adds HTTP API for alias management, and completes the feature with comprehensive testing.

Depends on: #109 (PR #1: Foundation)

Changes

Phase 3: Resolution Logic

  • Add [model_aliases] config section with enabled and auto_seed flags (both default to true)
  • Wire SqliteModelAliasRepository into DI container with startup seeding (26 built-in aliases)
  • Implement alias resolution in RouteRequest::execute_with_format() before restrictions check
  • Fail-open error handling: if resolution fails, pass through original model ID
  • Debug-level logging for resolution events

Phase 4: HTTP API

  • GET /api/models/aliases — List all aliases (built-in + custom)
  • POST /api/models/aliases — Create custom alias with validation (cycle prevention, non-empty fields)
  • DELETE /api/models/aliases/:alias — Delete alias (404 if not found)

Phase 5: Final Verification

  • 7 E2E tests for alias resolution flow (resolution, seeding, provider-scoped, concurrent access)
  • 10 HTTP API integration tests (CRUD operations, validation, error cases)
  • 5 config tests (defaults, enabled/disabled, auto_seed)

Test Results

Total: 548 tests passing
- 11 repository unit tests (from PR #1)
- 7 E2E tests (resolution flow)
- 10 HTTP API tests
- 5 config tests
- 515 existing tests (all passing)

✅ cargo test --all
✅ cargo clippy (no warnings)
✅ cargo fmt --check

Usage Example

Config (rook.toml)

[model_aliases]
enabled = true      # Enable alias resolution (default: true)
auto_seed = true    # Seed built-in aliases at startup (default: true)

Built-in Aliases (26 total, seeded automatically)

  • OpenAI: gpt-4o-latest → gpt-4o-2024-05-13, gpt-4-turbo → gpt-4-turbo-2024-04-09, etc.
  • Anthropic: claude-opus → claude-3-opus-20240229, claude-sonnet → claude-3-5-sonnet-20241022, etc.
  • Google: gemini-pro → gemini-1.5-pro-latest, gemini-flash → gemini-1.5-flash-latest, etc.
  • Mistral: mistral-large, mistral-small, ministral-8b
  • Groq: groq-llama-3.1-70b, groq-llama-3.1-8b, groq-llama-3.3-70b

HTTP API Examples

# List all aliases
GET /api/models/aliases

# Create custom alias
POST /api/models/aliases
Body: {"alias": "my-gpt4", "canonical": "gpt-4o-2024-05-13", "providerId": null}

# Delete alias
DELETE /api/models/aliases/my-gpt4

Request Flow

  1. Client sends request with model: "gpt-4o-latest"
  2. Alias resolution resolves to gpt-4o-2024-05-13
  3. Restrictions check sees canonical model
  4. Router selects provider using canonical model
  5. Audit log records canonical model

Related

- Add [model_aliases] config section with enabled and auto_seed flags
- Wire SqliteModelAliasRepository into DI container with startup seeding
- Implement alias resolution in RouteRequest before restrictions check
- Add GET/POST/DELETE endpoints for alias management at /api/models/aliases
- Add cycle prevention validation in create endpoint
- Add 7 E2E tests for alias resolution and seeding
- Add 10 HTTP API integration tests
- Add 5 config tests for model aliases section

Part of #47
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@yacosta738, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 5 minutes and 23 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4c058cc1-e914-464b-966f-03f0f8542f86

📥 Commits

Reviewing files that changed from the base of the PR and between 91f140a and f6863c2.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (23)
  • Cargo.toml
  • apps/rook/Cargo.toml
  • apps/rook/src/config.rs
  • apps/rook/src/di.rs
  • apps/rook/tests/alias_routing_e2e.rs
  • apps/rook/tests/config_tests.rs
  • crates/application/rook-usecases/src/route_request.rs
  • crates/application/rook-usecases/tests/route_request_restrictions.rs
  • crates/domain/rook-core/src/model.rs
  • crates/domain/rook-core/src/ports.rs
  • crates/infrastructure/alias-sqlite/Cargo.toml
  • crates/infrastructure/alias-sqlite/src/builtin.rs
  • crates/infrastructure/alias-sqlite/src/lib.rs
  • crates/infrastructure/alias-sqlite/src/repository.rs
  • crates/infrastructure/db-migration/src/migrations/V5__model_aliases.sql
  • crates/infrastructure/transport-axum/src/alias_routes.rs
  • crates/infrastructure/transport-axum/src/bootstrap_helpers.rs
  • crates/infrastructure/transport-axum/src/handlers/aliases.rs
  • crates/infrastructure/transport-axum/src/handlers/mod.rs
  • crates/infrastructure/transport-axum/src/lib.rs
  • crates/infrastructure/transport-axum/src/routes.rs
  • crates/infrastructure/transport-axum/tests/alias_api.rs
  • crates/infrastructure/transport-axum/tests/format_translation_integration.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/model-aliasing-integration

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added area/ci CI, tooling, and automation area/testing Tests and testing infrastructure labels Jun 5, 2026
@yacosta738
yacosta738 changed the base branch from main to feat/model-aliasing-foundation June 5, 2026 07:39
@yacosta738
yacosta738 merged commit 7a397b2 into feat/model-aliasing-foundation Jun 5, 2026
12 checks passed
@yacosta738
yacosta738 deleted the feat/model-aliasing-integration branch June 5, 2026 07:39
yacosta738 added a commit that referenced this pull request Jun 5, 2026
- Add [model_aliases] config section with enabled and auto_seed flags
- Wire SqliteModelAliasRepository into DI container with startup seeding
- Implement alias resolution in RouteRequest before restrictions check
- Add GET/POST/DELETE endpoints for alias management at /api/models/aliases
- Add cycle prevention validation in create endpoint
- Add 7 E2E tests for alias resolution and seeding
- Add 10 HTTP API integration tests
- Add 5 config tests for model aliases section

Part of #47
yacosta738 added a commit that referenced this pull request Jun 5, 2026
…109)

* feat: add model alias domain model and SQLite repository

- Add ModelAlias struct and ModelAliasRepositoryPort trait
- Create alias-sqlite crate with SqliteModelAliasRepository
- Add V5 migration for model_aliases table
- Include 26 built-in aliases (OpenAI, Anthropic, Google, Mistral, Groq)
- Add 11 unit tests for repository operations
- Implement cycle prevention and idempotent seeding

Part of #47

* feat: add model alias resolution and HTTP API (#111)

- Add [model_aliases] config section with enabled and auto_seed flags
- Wire SqliteModelAliasRepository into DI container with startup seeding
- Implement alias resolution in RouteRequest before restrictions check
- Add GET/POST/DELETE endpoints for alias management at /api/models/aliases
- Add cycle prevention validation in create endpoint
- Add 7 E2E tests for alias resolution and seeding
- Add 10 HTTP API integration tests
- Add 5 config tests for model aliases section

Part of #47

* feat(cache): HTTP management API, config validation, and observability (2/2) (#110)

* feat(cache): content-based cache keys with SHA-256 signatures

Implement content-based caching for issue #50:
- Add signature field to CacheKey (SHA-256 hex string)
- Update CompletionRequest.cache_key() to hash (model + messages + params)
- Add CacheStats struct with hit_rate() and utilization() methods
- Add LRU eviction to InMemoryCache with max_entries support
- Add AtomicU64 counters (hits, misses, evictions)
- Implement stats() method in InMemoryCache
- Add comprehensive unit tests for hashing, LRU, and stats

Breaking change: CacheKey now requires signature field (documented in proposal)

* fix(cache): address code review findings

- Add documentation for approximate LRU under concurrency
- Fix evict_if_needed to only trigger on new keys (not overwrites)
- Add test for no-eviction-on-overwrite behavior
- Clarify spec: None=unlimited, Some(0)=rejected (usize cannot be negative)
- Update tasks to specify max_entries validation rules

* feat(cache): HTTP management API, config validation, and observability (2/2)

Completes issue #50 implementation:

**Phase 3: Ports**
- Add stats() method to CachePort trait
- Add delete_by_signature() for HTTP endpoint support
- Implement both methods in InMemoryCache

**Phase 4: Configuration**
- Add max_entries field to CacheConfig
- Implement validate() rejecting ttl > 24h and max_entries = Some(0)
- Wire validation at config load (fail-fast)
- Pass max_entries to cache constructor in DI

**Phase 5: Application**
- Add cache() accessor to RouteRequest (already tracking stats)

**Phase 6: Transport**
- Create cache.rs handler module
- Implement GET /api/cache/stats (200 with CacheStats JSON)
- Implement DELETE /api/cache (204 clear all)
- Implement DELETE /api/cache/:signature (204/404)
- Wire cache routes (management API, requires auth)
- Extend /health with cache_entries, cache_hit_rate, cache_utilization

**Phase 7: Observability**
- Add rook_cache_evictions counter description
- Wire eviction metric in InMemoryCache

**Tests**
- 5 config validation tests
- 6 cache HTTP endpoint integration tests
- All 450+ tests passing

* fix: apply remaining code review findings from PR #110

- cache-memory: only increment deleted/evictions when store.remove returns Some
- routes.rs: use Axum 0.8 path syntax {signature}
- cache_routes.rs: add test_cache_routes_require_management_auth
- config_tests.rs: fix assertion message to match actual validation error
- tasks.md: fix dependencies (9.* → 9.1-9.4), update delete behavior description

* feat: add model alias domain model and SQLite repository

- Add ModelAlias struct and ModelAliasRepositoryPort trait
- Create alias-sqlite crate with SqliteModelAliasRepository
- Add V5 migration for model_aliases table
- Include 26 built-in aliases (OpenAI, Anthropic, Google, Mistral, Groq)
- Add 11 unit tests for repository operations
- Implement cycle prevention and idempotent seeding

Part of #47

* feat: add model alias resolution and HTTP API (#111)

- Add [model_aliases] config section with enabled and auto_seed flags
- Wire SqliteModelAliasRepository into DI container with startup seeding
- Implement alias resolution in RouteRequest before restrictions check
- Add GET/POST/DELETE endpoints for alias management at /api/models/aliases
- Add cycle prevention validation in create endpoint
- Add 7 E2E tests for alias resolution and seeding
- Add 10 HTTP API integration tests
- Add 5 config tests for model aliases section

Part of #47

* fix: address code review findings for model aliasing

- Add alias resolution to execute_stream_with_format for streaming requests
- Change ModelAlias.created_at from String to DateTime<Utc> for consistency
- Generate unique timestamps per alias in builtin_aliases()
- Update builtin.rs comment to reflect provider-scoped aliases
- Clarify cycle detection as depth-1 only in repository
- Replace string matching with enum matching for AlreadyExists error
- Make cycle check provider-scoped in handler and repository query
- Add db_migration import to fix test initialization

All changes verified with full CI passing.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci CI, tooling, and automation area/testing Tests and testing infrastructure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Model Aliasing & Normalization

1 participant