Skip to content

Add OpenRouter Embeddings Support#852

Merged
sean-esk merged 8 commits intomainfrom
feature/openrouter-embeddings-support
Nov 29, 2025
Merged

Add OpenRouter Embeddings Support#852
sean-esk merged 8 commits intomainfrom
feature/openrouter-embeddings-support

Conversation

@leex279
Copy link
Copy Markdown
Collaborator

@leex279 leex279 commented Nov 8, 2025

Summary

Closes #851

This PR adds OpenRouter as a first-class embedding provider, enabling users to access multiple embedding models (OpenAI, Google Gemini, Qwen3, Mistral) through a single unified API.

Backend Changes

  • ✅ Added validate_openrouter_api_key() to config.py (validates sk-or-v1- format)
  • ✅ Added OpenRouterErrorAdapter for API key sanitization in error messages
  • ✅ Registered openrouter as valid provider in llm_provider_service.py
  • ✅ Created openrouter_discovery_service.py with hardcoded model metadata
  • ✅ Created /api/openrouter/models endpoint for model discovery
  • ✅ Updated .env.example with OPENROUTER_API_KEY documentation

Frontend Changes

  • ✅ Created openrouterService.ts with session storage caching (5-minute TTL)
  • ✅ Added OpenRouter to EMBEDDING_CAPABLE_PROVIDERS in RAGSettings
  • ✅ Fixed embedding model default to include provider prefix (openai/text-embedding-3-small)

Testing

  • ✅ Added comprehensive unit tests for model discovery (11 tests, all passing)
  • ✅ Tests validate provider prefixes, dimensions, pricing, and model metadata

Benefits

  • 🎯 Cost Optimization: Qwen3 models at $0.01/1M tokens (87% cheaper than OpenAI)
  • 📏 Extended Context: Gemini (20K) and Qwen3 (32K) vs OpenAI (8K)
  • 🔑 Unified API: Single API key for multiple embedding providers
  • 🚀 Provider Diversity: Reduces single-provider dependency

Implementation Details

  • Model names MUST include provider prefix (e.g., openai/text-embedding-3-large)
  • Uses OpenAI-compatible API adapter (no custom adapter needed)
  • Comprehensive error sanitization removes sk-or-v1-* patterns from logs

Test Plan

  • Backend linting passes (ruff, mypy on new files)
  • Unit tests pass (11/11 OpenRouter discovery tests)
  • Manual testing: Select OpenRouter provider in Settings UI
  • Manual testing: Configure OpenRouter API key
  • Manual testing: Discover and select embedding models
  • Manual testing: Generate embeddings with OpenRouter

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • OpenRouter added as a supported embedding provider
    • Users can discover and select OpenRouter embedding models from the UI
  • Documentation

    • Environment config template updated with OpenRouter API key guidance
  • Improvements

    • Provider selection layout updated for better clarity
    • Error messages for OpenRouter interactions are improved and sanitized for clarity

leex279 and others added 2 commits November 8, 2025 23:06
Implements OpenRouter as an embedding provider option, enabling access to multiple
embedding models (OpenAI, Google Gemini, Qwen3, Mistral) through a single API key.

Backend changes:
- Add validate_openrouter_api_key() for API key validation (sk-or-v1- format)
- Add OpenRouterErrorAdapter for error sanitization
- Add openrouter to valid providers in llm_provider_service
- Create openrouter_discovery_service with hardcoded model list
- Create /api/openrouter/models endpoint for model discovery
- Register OpenRouter router in FastAPI main app

Frontend changes:
- Create openrouterService.ts for model discovery API client
- Add OpenRouter to RAGSettings.tsx provider options
- Configure default models with provider prefix (openai/text-embedding-3-small)
- Add OpenRouter to embedding-capable providers list

Documentation:
- Update .env.example with OPENROUTER_API_KEY documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Tests cover:
- Model list validation (non-empty, valid types)
- Provider prefix validation (all models have provider/)
- Data validation (positive dimensions, non-negative pricing)
- Provider validation (valid provider names)
- Specific provider models (OpenAI, Qwen)
- Model ID validation (requires prefix)

All 11 tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 8, 2025

Warning

Rate limit exceeded

@leex279 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 22 minutes and 38 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 7f10527 and b4b534b.

📒 Files selected for processing (1)
  • archon-ui-main/src/services/openrouterService.ts (1 hunks)

Walkthrough

Adds OpenRouter embedding support: frontend UI and service, backend discovery service and API route, API key validation, provider error adapter, credential/provider wire-ups, and unit tests for discovery and model validation.

Changes

Cohort / File(s) Summary
Environment & Configuration
\.env.example, python/src/server/config/config.py
Added commented OPENROUTER_API_KEY doc line; added validate_openrouter_api_key(api_key: str) -> bool enforcing sk-or-v1- prefix and non-empty key.
Frontend RAG Settings
archon-ui-main/src/components/settings/RAGSettings.tsx
Added "openrouter" to EMBEDDING_CAPABLE_PROVIDERS; default OpenRouter embedding model changed to 'openai/text-embedding-3-small'; grid layout adjusts to 4 columns when chat inactive.
Frontend OpenRouter Service
archon-ui-main/src/services/openrouterService.ts
New OpenRouter client with OpenRouterEmbeddingModel / OpenRouterModelListResponse types, discoverModels() calling /api/openrouter/models, sessionStorage caching (5 min TTL), error handling, and exported singleton.
Backend API Routes
python/src/server/api_routes/openrouter_api.py, python/src/server/main.py
New /api/openrouter router with GET /models endpoint; router registered in FastAPI app.
Backend Model Discovery
python/src/server/services/openrouter_discovery_service.py
New Pydantic models OpenRouterEmbeddingModel, OpenRouterModelListResponse; OpenRouterDiscoveryService with discover_embedding_models() returning a hardcoded list of provider-prefixed embedding models; exported singleton.
Backend Provider Services
python/src/server/services/llm_provider_service.py, python/src/server/services/credential_service.py
OpenRouter embedding model selection now uses provider-prefixed model ID (openai/...); added "openrouter" to embedding_capable_providers. Minor type-syntax updates.
Error Handling
python/src/server/services/embeddings/provider_error_adapters.py
Added OpenRouterErrorAdapter, registered "openrouter" in adapters, added get_adapter() and sanitize_provider_error() helpers, and detection logic updated to recognize OpenRouter errors.
Tests
python/tests/test_openrouter_discovery.py
New pytest/async tests validating discovery output, provider-prefixed IDs, metadata fields, pricing/context constraints, and model ID validation behavior.

Sequence Diagram(s)

sequenceDiagram
    participant UI as Frontend UI
    participant FrontendSvc as openrouterService
    participant BackendAPI as /api/openrouter/models
    participant DiscoverySvc as OpenRouterDiscoveryService

    UI->>FrontendSvc: discoverModels()
    activate FrontendSvc
    FrontendSvc->>FrontendSvc: check sessionStorage cache (5m TTL)
    alt cache hit
        FrontendSvc-->>UI: return cached models
    else cache miss
        FrontendSvc->>BackendAPI: GET /api/openrouter/models
        activate BackendAPI
        BackendAPI->>DiscoverySvc: discover_embedding_models()
        activate DiscoverySvc
        DiscoverySvc-->>BackendAPI: return hardcoded model list
        deactivate DiscoverySvc
        BackendAPI-->>FrontendSvc: OpenRouterModelListResponse (with total_count)
        deactivate BackendAPI
        FrontendSvc->>FrontendSvc: cache response in sessionStorage (5m TTL)
        FrontendSvc-->>UI: return models
    end
    deactivate FrontendSvc
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus review on:
    • openrouter_discovery_service.py — verify correctness of hardcoded metadata and Pydantic validations.
    • openrouterService.ts — caching TTL logic, sessionStorage keying, and API error handling.
    • provider_error_adapters.py — ensure OpenRouter patterns don't mask unrelated data and ordering of detection is correct.
    • validate_openrouter_api_key() — confirm prefix rule matches OpenRouter documentation.
    • Tests — ensure assertions cover error/edge cases and that async handling is correct.

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • coleam00
  • Wirasm
  • sean-eskerium

Poem

🐰 I hopped in code where routers meet,
Models gathered, embeddings sweet,
Five-minute caches, prefixes neat,
Discovery sings in responses fleet,
A tiny rabbit cheers this feat! 🎉

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding OpenRouter as an embeddings support feature, which matches the primary objective of the PR.
Description check ✅ Passed The description covers Summary, Changes Made (with checkmarks), Type of Change, Affected Services, Testing, and test plan; however, checklist items under 'Checklist' and 'Breaking Changes' sections are not completed, and some manual testing items remain pending.
Linked Issues check ✅ Passed All coding requirements from issue #851 are met: OpenRouter integrated as embedding provider, OpenAI-compatible API leveraged, OPENROUTER_API_KEY configuration added, model discovery implemented with /api/openrouter/models endpoint, error handling and sanitization provided, and unified interface established.
Out of Scope Changes check ✅ Passed All changes align with PR objectives: backend OpenRouter integration, frontend UI updates for provider selection, model metadata caching, and unit tests for discovery service. Minor formatting changes (whitespace, type syntax updates) in existing files are non-functional and supportive.
Docstring Coverage ✅ Passed Docstring coverage is 82.76% which is sufficient. The required threshold is 80.00%.

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.

Changed grid-cols-3 to grid-cols-4 for embedding provider selection
so all 4 embedding-capable providers (OpenAI, Google, OpenRouter, Ollama)
fit on one line, matching the chat provider layout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@leex279
Copy link
Copy Markdown
Collaborator Author

leex279 commented Nov 8, 2025

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Nov 8, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a 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

🧹 Nitpick comments (2)
archon-ui-main/src/services/openrouterService.ts (2)

26-26: Consider lazy initialization of baseUrl.

The baseUrl is initialized once at class instantiation. If the API URL can change at runtime (e.g., via environment variable changes or configuration updates), this could cause stale URL issues.

Consider fetching the URL per-request:

-	private baseUrl = getApiUrl();
+	private getBaseUrl = () => getApiUrl();

And update the fetch call on line 104:

-			const response = await fetch(`${this.baseUrl}/api/openrouter/models`, {
+			const response = await fetch(`${this.getBaseUrl()}/api/openrouter/models`, {

96-125: LGTM with minor suggestion: Consider validating response structure.

The API call correctly implements cache-first pattern and error handling. However, response.json() on line 116 doesn't validate the returned structure matches OpenRouterModelListResponse.

Consider adding runtime validation:

 			const data = await response.json();
+			
+			// Validate response structure
+			if (!data.embedding_models || !Array.isArray(data.embedding_models)) {
+				throw new Error("Invalid response structure from OpenRouter API");
+			}

 			// Cache the successful response
 			this.cacheModels(data);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4ebdeda and f32f0c3.

📒 Files selected for processing (11)
  • .env.example (1 hunks)
  • PRPs/openrouter-embeddings-support.md (1 hunks)
  • archon-ui-main/src/components/settings/RAGSettings.tsx (3 hunks)
  • archon-ui-main/src/services/openrouterService.ts (1 hunks)
  • python/src/server/api_routes/openrouter_api.py (1 hunks)
  • python/src/server/config/config.py (1 hunks)
  • python/src/server/main.py (2 hunks)
  • python/src/server/services/embeddings/provider_error_adapters.py (5 hunks)
  • python/src/server/services/llm_provider_service.py (5 hunks)
  • python/src/server/services/openrouter_discovery_service.py (1 hunks)
  • python/tests/test_openrouter_discovery.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
python/src/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

python/src/**/*.py: On service startup, missing configuration, DB connection failures, auth/authorization failures, critical dependency outages, or invalid/corrupting data: fail fast and bubble errors
For batch processing, background tasks, WebSocket events, optional features, and external API calls: continue processing but log errors (with retries/backoff for APIs)
Never accept or persist corrupted data; skip failed items entirely (e.g., zero embeddings, null FKs, malformed JSON)
Error messages must include operation context, IDs/URLs, use specific exception types, preserve full stack traces (logging with exc_info=True), and avoid returning None/null—raise exceptions instead; for batches report success counts and detailed failures
Backend code targets Python 3.12 and adheres to a 120 character line length
Use Ruff for linting (errors, warnings, unused imports) in backend code
Use Mypy for static type checking in backend code

Files:

  • python/src/server/services/openrouter_discovery_service.py
  • python/src/server/services/embeddings/provider_error_adapters.py
  • python/src/server/config/config.py
  • python/src/server/main.py
  • python/src/server/api_routes/openrouter_api.py
  • python/src/server/services/llm_provider_service.py
archon-ui-main/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

archon-ui-main/src/**/*.{ts,tsx}: Frontend TypeScript must use strict mode with no implicit any
Use TanStack Query for all data fetching; avoid prop drilling
Use database values directly in the frontend; avoid mapping layers between BE and FE types

Files:

  • archon-ui-main/src/services/openrouterService.ts
  • archon-ui-main/src/components/settings/RAGSettings.tsx
🧠 Learnings (3)
📓 Common learnings
Learnt from: Chillbruhhh
Repo: coleam00/Archon PR: 736
File: archon-ui-main/src/components/settings/RAGSettings.tsx:17-19
Timestamp: 2025-09-25T16:36:48.527Z
Learning: OpenRouter does not provide embedding models - it only acts as a proxy/router for various LLM providers for chat completions, not embeddings. The EMBEDDING_CAPABLE_PROVIDERS array in RAGSettings.tsx correctly excludes 'openrouter'.
📚 Learning: 2025-09-25T16:36:48.527Z
Learnt from: Chillbruhhh
Repo: coleam00/Archon PR: 736
File: archon-ui-main/src/components/settings/RAGSettings.tsx:17-19
Timestamp: 2025-09-25T16:36:48.527Z
Learning: OpenRouter does not provide embedding models - it only acts as a proxy/router for various LLM providers for chat completions, not embeddings. The EMBEDDING_CAPABLE_PROVIDERS array in RAGSettings.tsx correctly excludes 'openrouter'.

Applied to files:

  • python/src/server/services/openrouter_discovery_service.py
  • python/src/server/services/embeddings/provider_error_adapters.py
  • archon-ui-main/src/services/openrouterService.ts
  • archon-ui-main/src/components/settings/RAGSettings.tsx
  • PRPs/openrouter-embeddings-support.md
📚 Learning: 2025-09-19T10:32:55.580Z
Learnt from: CR
Repo: coleam00/Archon PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-09-19T10:32:55.580Z
Learning: Applies to .env : Require SUPABASE_URL and SUPABASE_SERVICE_KEY in .env

Applied to files:

  • .env.example
🔇 Additional comments (19)
.env.example (1)

128-129: LGTM! Clear documentation for OpenRouter API key.

The documentation format is consistent with other API key entries and provides helpful information about the key format and where to obtain it.

python/src/server/config/config.py (1)

69-79: LGTM! Validation follows established patterns.

The validate_openrouter_api_key function correctly validates the OpenRouter API key format and provides clear error messages that include the URL for obtaining keys.

archon-ui-main/src/components/settings/RAGSettings.tsx (2)

45-45: Provider-prefixed model ID is consistent with backend validation.

Assuming OpenRouter embedding support is confirmed, the provider-prefixed model ID format (openai/text-embedding-3-small) correctly aligns with the backend's OpenRouterEmbeddingModel validation that requires provider prefixes.


18-18: The review comment is incorrect and should be disregarded.

OpenRouter supports embeddings with a /v1/embeddings endpoint, contradicting the stored learning from September 2025. The stored learning's claim that "OpenRouter does not provide embedding models" is outdated. Embedding models are available, making the addition of 'openrouter' to EMBEDDING_CAPABLE_PROVIDERS correct and appropriate.

Likely an incorrect or invalid review comment.

python/src/server/main.py (1)

29-29: LGTM! Standard router registration pattern.

The OpenRouter router import and registration follow the established pattern used for other API routers in the application.

Also applies to: 191-191

python/src/server/services/llm_provider_service.py (1)

658-659: LGTM! Provider prefix aligns with backend validation.

The change to include the provider prefix (openai/text-embedding-3-small) for OpenRouter is consistent with the OpenRouterEmbeddingModel validation that requires model IDs to contain provider prefixes. The comment clearly documents this requirement.

python/src/server/api_routes/openrouter_api.py (1)

14-27: LGTM! Clean API endpoint implementation.

The endpoint implementation is straightforward, properly typed with Pydantic response models, and follows FastAPI conventions. The async implementation is appropriate for the discovery service call.

python/tests/test_openrouter_discovery.py (1)

1-158: LGTM! Comprehensive test coverage for OpenRouter discovery.

The test suite thoroughly validates:

  • Model list structure and content
  • Provider prefix requirements (critical for OpenRouter)
  • Data type and range constraints (dimensions, pricing, context_length)
  • Presence of expected models (OpenAI, Qwen)
  • Model ID validation logic

The tests are well-documented and provide excellent coverage for the discovery service.

python/src/server/services/openrouter_discovery_service.py (1)

1-137: The stored learning is outdated; OpenRouter now supports embeddings. No issues found.

OpenRouter exposes an embeddings API (POST /api/v1/embeddings), and model IDs use a provider-prefix format such as "openai/text-embedding-3-small"—which the implementation correctly follows. All providers and models listed in the code (OpenAI, Google, Qwen, Mistral) are supported through OpenRouter's embeddings endpoint.

The code's hardcoded approach is already flagged in its own docstring as a temporary solution pending an OpenRouter models endpoint. The service is not currently integrated into the codebase.

archon-ui-main/src/services/openrouterService.ts (3)

10-18: LGTM: Type definitions match backend models.

The OpenRouterEmbeddingModel interface correctly mirrors the Python backend model with all required fields properly typed.


30-54: LGTM: Comprehensive error handling with good categorization.

The error handling properly differentiates network errors, timeouts, and generic errors with user-friendly messages.


59-91: LGTM: Robust caching implementation with appropriate error handling.

The caching logic correctly implements TTL checking and cleanup. Silent error handling for cache operations (lines 73-75, 88-90) is appropriate since cache failures shouldn't break functionality.

python/src/server/services/embeddings/provider_error_adapters.py (3)

114-139: LGTM: OpenRouterErrorAdapter follows established patterns.

The adapter correctly implements sanitization for OpenRouter-specific patterns including sk-or-v1- API keys, OpenRouter URLs, and Bearer tokens. The structure is consistent with existing adapters.


145-150: LGTM: OpenRouter adapter correctly registered in factory.

The adapter is properly added to the _adapters dictionary following the existing pattern.


170-172: LGTM: Provider detection correctly prioritizes OpenRouter.

The detection logic appropriately checks OpenRouter first to avoid false positives when model names contain "openai". The comment on line 170 clearly explains the reasoning.

PRPs/openrouter-embeddings-support.md (4)

1-75: LGTM: Comprehensive documentation with clear goals and success criteria.

The PRP provides excellent context for the feature implementation with quantified benefits and clear success criteria.


253-557: LGTM: Detailed implementation blueprint with valuable gotchas.

The implementation patterns and gotchas (especially around model name prefixes and base URLs) provide excellent guidance. The Pydantic validation ensuring provider prefixes (lines 274-280) is a critical safeguard.


599-794: LGTM: Thorough validation strategy with practical anti-patterns.

The multi-level validation approach and anti-patterns section (lines 782-793) provide excellent guidance for avoiding common mistakes. The manual testing checklist aligns well with the PR's test plan.


90-94: Verify OpenRouter embeddings API exists.

The documentation references OpenRouter's embeddings API documentation, but per learnings from September 2025, OpenRouter was documented as NOT supporting embeddings—only chat completions.

This inconsistency was flagged at the start of the review. Please confirm that OpenRouter has added embeddings support since September 2025 before proceeding with this PR.

leex279 and others added 2 commits November 8, 2025 23:36
Added 'openrouter' to embedding_capable_providers set in credential_service.py
to prevent it from being rejected and falling back to OpenAI.

Fixes: 'Invalid embedding provider openrouter doesn't support embeddings' error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
1. Lazy initialization of baseUrl via getBaseUrl() method
   - Allows API URL to be updated at runtime without stale URL issues

2. Runtime validation of API response structure
   - Validates embedding_models array exists before caching
   - Prevents invalid responses from being cached

Addresses CodeRabbit nitpick comments on PR #852

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@leex279 leex279 marked this pull request as ready for review November 8, 2025 22:56
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a 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 (1)
archon-ui-main/src/services/openrouterService.ts (1)

118-121: Consider more comprehensive response validation.

The current validation only checks that embedding_models exists and is an array. Consider validating:

  • Individual model structure (required fields like id, provider, dimensions, etc.)
  • The total_count field matches embedding_models.length
  • Basic sanity checks (e.g., positive dimensions, valid provider names)

This would catch malformed responses early and provide better error messages.

Example validation:

// Validate response structure
if (!data.embedding_models || !Array.isArray(data.embedding_models)) {
	throw new Error("Invalid response structure from OpenRouter API");
}

if (typeof data.total_count !== "number" || data.total_count < 0) {
	throw new Error("Invalid total_count in response");
}

// Validate at least one model has required fields
if (data.embedding_models.length > 0) {
	const model = data.embedding_models[0];
	if (!model.id || !model.provider || typeof model.dimensions !== "number") {
		throw new Error("Invalid model structure in response");
	}
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f32f0c3 and 038b00d.

📒 Files selected for processing (2)
  • archon-ui-main/src/services/openrouterService.ts (1 hunks)
  • python/src/server/services/credential_service.py (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
archon-ui-main/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

archon-ui-main/src/**/*.{ts,tsx}: Frontend TypeScript must use strict mode with no implicit any
Use TanStack Query for all data fetching; avoid prop drilling
Use database values directly in the frontend; avoid mapping layers between BE and FE types

Files:

  • archon-ui-main/src/services/openrouterService.ts
python/src/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

python/src/**/*.py: On service startup, missing configuration, DB connection failures, auth/authorization failures, critical dependency outages, or invalid/corrupting data: fail fast and bubble errors
For batch processing, background tasks, WebSocket events, optional features, and external API calls: continue processing but log errors (with retries/backoff for APIs)
Never accept or persist corrupted data; skip failed items entirely (e.g., zero embeddings, null FKs, malformed JSON)
Error messages must include operation context, IDs/URLs, use specific exception types, preserve full stack traces (logging with exc_info=True), and avoid returning None/null—raise exceptions instead; for batches report success counts and detailed failures
Backend code targets Python 3.12 and adheres to a 120 character line length
Use Ruff for linting (errors, warnings, unused imports) in backend code
Use Mypy for static type checking in backend code

Files:

  • python/src/server/services/credential_service.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: Chillbruhhh
Repo: coleam00/Archon PR: 736
File: archon-ui-main/src/components/settings/RAGSettings.tsx:17-19
Timestamp: 2025-09-25T16:36:48.527Z
Learning: OpenRouter does not provide embedding models - it only acts as a proxy/router for various LLM providers for chat completions, not embeddings. The EMBEDDING_CAPABLE_PROVIDERS array in RAGSettings.tsx correctly excludes 'openrouter'.
📚 Learning: 2025-09-25T16:36:48.527Z
Learnt from: Chillbruhhh
Repo: coleam00/Archon PR: 736
File: archon-ui-main/src/components/settings/RAGSettings.tsx:17-19
Timestamp: 2025-09-25T16:36:48.527Z
Learning: OpenRouter does not provide embedding models - it only acts as a proxy/router for various LLM providers for chat completions, not embeddings. The EMBEDDING_CAPABLE_PROVIDERS array in RAGSettings.tsx correctly excludes 'openrouter'.

Applied to files:

  • archon-ui-main/src/services/openrouterService.ts
  • python/src/server/services/credential_service.py
🧬 Code graph analysis (1)
archon-ui-main/src/services/openrouterService.ts (2)
python/src/server/services/openrouter_discovery_service.py (2)
  • OpenRouterEmbeddingModel (10-27)
  • OpenRouterModelListResponse (30-34)
archon-ui-main/src/config/api.ts (1)
  • getApiUrl (9-19)
⏰ 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: Backend Tests (Python + pytest)
🔇 Additional comments (5)
archon-ui-main/src/services/openrouterService.ts (4)

10-23: LGTM!

The type definitions correctly match the Python backend models from openrouter_discovery_service.py. The interface structure ensures type safety for the API responses.


30-54: LGTM!

The error handling provides good categorization of network, timeout, and general errors with contextual messages. The type-safe handling of unknown error types is appropriate.


81-91: LGTM!

The cache storage implementation is clean and appropriately fails silently on errors, which is correct behavior for a non-critical caching layer.


135-145: LGTM!

The cache clearing method and singleton export follow standard patterns. Silent error handling in cache operations is appropriate for non-critical functionality.

python/src/server/services/credential_service.py (1)

446-446: OpenRouter embeddings support confirmed — no issues found.

OpenRouter added embeddings endpoints with a POST /api/v1/embeddings endpoint and TypeScript SDK support for embeddings.generate (docs updated Nov 2025). The September 2025 learning is now outdated. Adding "openrouter" to the embedding-capable providers set is correct and valid.

Comment thread archon-ui-main/src/services/openrouterService.ts
leex279 and others added 2 commits November 9, 2025 00:03
Implemented comprehensive validation to prevent crashes from corrupted cache:
- Created isCacheEntry() type guard to validate cache structure
- Parse JSON into unknown type (TypeScript strict mode compliant)
- Validate timestamp is number and data has OpenRouterModelListResponse shape
- Validate each model has all required fields with correct types
- Remove corrupted cache entries to avoid repeated failures
- No 'any' types used, full strict mode compliance

Prevents crashes from malformed cache data while maintaining type safety.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Enhanced validation to catch malformed responses early:
- Validate total_count is non-negative number
- Verify total_count matches embedding_models.length
- Validate first model has required fields (id, provider, dimensions)
- Check dimensions are positive numbers
- Validate provider names are from expected set
- Provide specific error messages for each validation failure

Prevents caching invalid data and provides better debugging information.

Addresses CodeRabbit nitpick comment on PR #852

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@spencerthayer
Copy link
Copy Markdown

When will this get merged into the main branch? @coleam00?

@leex279
Copy link
Copy Markdown
Collaborator Author

leex279 commented Nov 26, 2025

@spencerthayer thanks for reminding. I asked in the team if someone has time to review it soon, so we can merge.

If you tested test PR yourself, would be great to get your feedback here.

@sean-esk sean-esk merged commit ecaece4 into main Nov 29, 2025
8 checks passed
@Wirasm Wirasm deleted the feature/openrouter-embeddings-support branch April 6, 2026 07:38
coleam00 pushed a commit that referenced this pull request Apr 7, 2026
Add per-project environment variable management as a first-class config
primitive. Env vars defined in .archon/config.yaml or stored in DB via
Web UI are merged into Options.env on Claude SDK calls.

Three env var sources merge in priority order (later wins):
1. process.env — global, from ~/.archon/.env via dotenv
2. .archon/config.yaml env: section — file-based per-project
3. DB remote_agent_codebase_env_vars table — Web UI per-project

Changes:
- Add remote_agent_codebase_env_vars table (PG migration + SQLite schema)
- Add DB CRUD module (packages/core/src/db/env-vars.ts)
- Extend IWorkflowStore with getCodebaseEnvVars method
- Add env field to RepoConfig, MergedConfig, WorkflowConfig, WorkflowAssistantOptions, AssistantRequestOptions
- Merge DB env vars in executor after config load
- Inject env vars into Claude subprocess via Options.env
- Add 3 API routes (GET/PUT/DELETE /api/codebases/:id/env)
- Add EnvVarsPanel to Settings page with masked value display

Fixes #852
Tyone88 pushed a commit to Tyone88/Archon that referenced this pull request Apr 16, 2026
)

Add per-project environment variable management as a first-class config
primitive. Env vars defined in .archon/config.yaml or stored in DB via
Web UI are merged into Options.env on Claude SDK calls.

Three env var sources merge in priority order (later wins):
1. process.env — global, from ~/.archon/.env via dotenv
2. .archon/config.yaml env: section — file-based per-project
3. DB remote_agent_codebase_env_vars table — Web UI per-project

Changes:
- Add remote_agent_codebase_env_vars table (PG migration + SQLite schema)
- Add DB CRUD module (packages/core/src/db/env-vars.ts)
- Extend IWorkflowStore with getCodebaseEnvVars method
- Add env field to RepoConfig, MergedConfig, WorkflowConfig, WorkflowAssistantOptions, AssistantRequestOptions
- Merge DB env vars in executor after config load
- Inject env vars into Claude subprocess via Options.env
- Add 3 API routes (GET/PUT/DELETE /api/codebases/:id/env)
- Add EnvVarsPanel to Settings page with masked value display

Fixes coleam00#852
POWERFULMOVES added a commit to POWERFULMOVES/PMOVES-Archon that referenced this pull request Apr 19, 2026
…gration (#12)

* Remove Docusaurus documentation system

Remove the standalone Docusaurus documentation website to simplify the project structure and reduce maintenance overhead.

Changes:
- Delete /docs directory (480MB freed) containing all Docusaurus files
- Remove docker-compose.docs.yml (optional docs service)
- Remove ARCHON_DOCS_PORT from .env.example
- Update .github/workflows/release-notes.yml (remove docs section)
- Update .github/test-release-notes.sh (remove docs section)

Preserved:
- Project documents feature (archon-ui-main/src/features/projects/documents/)
- Backend document service (python/src/server/services/projects/document_service.py)
- Project documents API endpoints (/api/projects/{id}/docs)

Benefits:
- Eliminates redundancy (content duplicated in /PRPs/ai_docs/)
- Reduces complexity (removes 480MB dependencies and configuration)
- Simplifies deployment (eliminates optional Docker service on port 3838)
- Lowers maintenance burden (single documentation source)

All validation tests passed:
✓ File system validation
✓ Backend imports verification
✓ Docker Compose integration testing
✓ CI/CD workflow validation
✓ Project documents API still functional

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add OpenRouter embeddings support

Implements OpenRouter as an embedding provider option, enabling access to multiple
embedding models (OpenAI, Google Gemini, Qwen3, Mistral) through a single API key.

Backend changes:
- Add validate_openrouter_api_key() for API key validation (sk-or-v1- format)
- Add OpenRouterErrorAdapter for error sanitization
- Add openrouter to valid providers in llm_provider_service
- Create openrouter_discovery_service with hardcoded model list
- Create /api/openrouter/models endpoint for model discovery
- Register OpenRouter router in FastAPI main app

Frontend changes:
- Create openrouterService.ts for model discovery API client
- Add OpenRouter to RAGSettings.tsx provider options
- Configure default models with provider prefix (openai/text-embedding-3-small)
- Add OpenRouter to embedding-capable providers list

Documentation:
- Update .env.example with OPENROUTER_API_KEY documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add unit tests for OpenRouter model discovery

Tests cover:
- Model list validation (non-empty, valid types)
- Provider prefix validation (all models have provider/)
- Data validation (positive dimensions, non-negative pricing)
- Provider validation (valid provider names)
- Specific provider models (OpenAI, Qwen)
- Model ID validation (requires prefix)

All 11 tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix embedding provider grid to fit all providers in one line

Changed grid-cols-3 to grid-cols-4 for embedding provider selection
so all 4 embedding-capable providers (OpenAI, Google, OpenRouter, Ollama)
fit on one line, matching the chat provider layout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix credential_service to recognize OpenRouter as embedding provider

Added 'openrouter' to embedding_capable_providers set in credential_service.py
to prevent it from being rejected and falling back to OpenAI.

Fixes: 'Invalid embedding provider openrouter doesn't support embeddings' error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address CodeRabbit review: Improve openrouterService robustness

1. Lazy initialization of baseUrl via getBaseUrl() method
   - Allows API URL to be updated at runtime without stale URL issues

2. Runtime validation of API response structure
   - Validates embedding_models array exists before caching
   - Prevents invalid responses from being cached

Addresses CodeRabbit nitpick comments on PR coleam00#852

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Delete PRPs/openrouter-embeddings-support.md

* Add robust cache validation with type guards in openrouterService

Implemented comprehensive validation to prevent crashes from corrupted cache:
- Created isCacheEntry() type guard to validate cache structure
- Parse JSON into unknown type (TypeScript strict mode compliant)
- Validate timestamp is number and data has OpenRouterModelListResponse shape
- Validate each model has all required fields with correct types
- Remove corrupted cache entries to avoid repeated failures
- No 'any' types used, full strict mode compliance

Prevents crashes from malformed cache data while maintaining type safety.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add comprehensive API response validation in discoverModels

Enhanced validation to catch malformed responses early:
- Validate total_count is non-negative number
- Verify total_count matches embedding_models.length
- Validate first model has required fields (id, provider, dimensions)
- Check dimensions are positive numbers
- Validate provider names are from expected set
- Provide specific error messages for each validation failure

Prevents caching invalid data and provides better debugging information.

Addresses CodeRabbit nitpick comment on PR coleam00#852

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Update README for Supabase service role key instructions (coleam00#836)

* chore(security): add CODEOWNERS and Dependabot configuration

Adds repository security files:
- CODEOWNERS for PR review routing
- dependabot.yml for automated security updates

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(hardened): Add nested submodule integrations for standalone operation

- Add .gitmodules with 7 nested integrations:
  - PMOVES-Agent-Zero (agent orchestration)
  - PMOVES-BoTZ (MCP tools)
  - PMOVES-HiRAG (knowledge retrieval)
  - PMOVES-Deep-Serch (deep research)
  - docling (document processing)
  - PMOVES-BotZ-gateway (MCP gateway)
  - PMOVES-tensorzero (TensorZero client)

- Fix PydanticAI Agent initialization (remove invalid result_type parameter)

Enables Archon to run standalone with PMOVES.AI service connections.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(pmoves): add Claude Code MCP adapter for PMOVES.AI integration

New module: python/pmoves_mcp/
- claude_code_adapter.py: Async MCP adapter for Claude Code CLI
- __init__.py: Module exports

Features:
- Execute TAC slash commands via Agent Zero's MCP interface
- ClaudeCodeMCPAdapter with async httpx client
- CommandResult dataclass for structured responses
- ARCHON_MCP_TOOLS registration for Archon integration

Available commands through adapter:
- /search:hirag, /search:supaserch, /search:deepresearch
- /health:check-all, /health:metrics
- /agents:status, /agents:mcp-query
- /deploy:smoke-test, /deploy:services, /deploy:up
- /botz:init, /botz:profile, /botz:mcp, /botz:secrets

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: Restore fail-fast behavior for API key validation in upload

- Remove HTTPException catch that was allowing uploads to proceed with invalid credentials
- Aligns with beta guidelines: authentication failures should halt execution
- Addresses code review feedback from PR #1

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* chore(deps): Update uv.lock with dependency revisions

- Bump revision from 1 to 3
- Add upload-time fields for PyPI packages
- Sync with latest uv dependency resolution

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(observability): add Prometheus metrics endpoint

Add /metrics endpoint for Prometheus scraping with:
- HTTP request counter (by method, endpoint, status)
- HTTP request duration histogram
- Knowledge operations counter
- MCP commands execution counter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(search): Add Hi-RAG v2 semantic expansion to keyword extraction

- Add optional Hi-RAG v2 integration for knowledge-aware keyword discovery
- Enable semantic keyword expansion via PMOVES knowledge graph
- Add hirag_url parameter to KeywordExtractor for knowledge graph queries
- Improves search relevance with ontology-driven term expansion

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(pmoves-ai): Add PMOVES.AI integration patterns (#3)

* feat(pmoves-ai): Add PMOVES.AI integration patterns

- Add CHIT secrets manifest (chit/secrets_manifest_v2.yaml)
- Add tier-based environment loading (env.shared, env.tier-agent.sh)
- Add health check module (pmoves_health/)
- Add NATS service announcer (pmoves_announcer/)
- Add service registry client (pmoves_registry/)
- Add Docker Compose YAML anchors (docker-compose.pmoves.yml)
- Add integration documentation (PMOVES.AI_INTEGRATION.md)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(integration): Apply Phase 1 critical bug fixes

- Fix deprecated datetime.utcnow() → datetime.now(timezone.utc)
- Fix YAML environment merge (list → map for proper merging)
- Fix health check decorator accumulation bug
- Fix health endpoint status codes (return 503 when unhealthy)
- Remove APP/UI tiers (stick to 6-tier architecture)
- Fix resource leaks in NATS connections (try/finally)

* fix(security): Remove hardcoded credential defaults

- Neo4j: Remove neo4j:neo4j default credentials
- MinIO: Remove minioadmin:minioadmin default credentials
- ClickHouse: Remove tensorzero:tensorzero default credentials
- Fix typo: export_CACHE_TTL → export CACHE_TTL

Empty defaults now require explicit configuration for production use.

* refactor(code-quality): Phase 3 & 4 improvements

Phase 3: Code Quality
- Add pmoves_common shared types module (ServiceTier, HealthStatus)
- Update ServiceTier imports with fallback to shared module
- Remove duplicate ServiceTier enum definitions

Phase 4: Documentation
- Add comprehensive module docstrings to all integration modules
- Create .coderabbit.yaml for automated PR reviews
- Enable reviews on feat/* and fix/* branches
- Set docstring coverage target to 80%

This reduces code duplication and improves type consistency across
the PMOVES.AI ecosystem.

---------

Co-authored-by: POWERFULMOVES <POWERFULMOVES@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* chore: Add GitHub Actions workflows and update submodule SHAs

- Add CI/CD workflows: ci.yml, claude-fix.yml, claude-review.yml, release-notes.yml
- Update submodule references to latest commits

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(pr): Address CodeRabbit review issues

- Fix dependabot.yml: Point pip to /python, npm to /archon-ui-main
- Add branch = main to docling submodule in .gitmodules
- Add prometheus-client>=0.20.0 to all dependency group

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat: Sync main to hardened - MCP adapter, CODEOWNERS, nested submodules, persona service

Syncs 4 commits from main to PMOVES.AI-Edition-Hardened:

- Claude Code MCP adapter for PMOVES.AI integration
- CODEOWNERS configuration (security)
- Nested submodule integrations for standalone operation
- Persona service and API routes for agent creation

Includes CodeRabbit review fixes:
- Fixed route ordering (/thread-types before /{persona_id})
- Added proper error handling and validation
- Removed Git conflict markers
- Fixed .coderabbit.yaml configuration

🤖 Generated with Claude Code

* docs: add PMOVES.AI skill hints context tags

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore(submodules): update nested PMOVES-HiRAG submodule pointer

* security: update PBKDF2 iterations to 600,000

* fix: correct indentation in state_reconciliation.py if-block

* fix(env): strip export syntax and add NATS auth to env.shared defaults

- Remove `export` prefix from all variables (incompatible with Docker env_file)
- Update NATS_URL default to include pmoves credentials
- Update usage comment to reflect Docker Compose env_file pattern

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(claude): add CHIT-aware integration context (#9)

Co-authored-by: Shaela Bello <slbello@uncg.edu>

* fix(auth): align NATS default URLs with credentialed runtime (#10)

Co-authored-by: Shaela Bello <slbello@uncg.edu>

* chore(submodules): sync HiRAG and BotZ gateway pointers (#11)

Co-authored-by: Shaela Bello <slbello@uncg.edu>

* fix(security): add USER directive to archon-ui Dockerfile

Run as non-root user (uid 65532) to satisfy BuildKit audit and
defense-in-depth container hardening requirements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(github): add GitHub App token minting and client

Implements GitHub App integration for agent work orders with:
- Token minting with JWT RS256 signing (10-min lifetime)
- Installation token exchange via GitHub API
- Token caching with 50-minute expiry window
- GitHubClient with App token + gh CLI fallback
- Full test coverage for token minting and PR operations

Environment variables required:
- GH_APP_ID: GitHub App numeric ID
- GH_APP_SEC: PEM private key (handles double-escaped env values)
- GH_APP_INSTALLATION_ID: Installation ID for org access

Key features:
- mint_installation_token(): Creates short-lived JWT + exchanges for token
- get_installation_token(): Cached token retrieval with force_refresh option
- clear_token_cache(): Manual cache invalidation
- GitHubClient.list_pull_requests(): API-first with CLI fallback
- Graceful degradation when credentials unavailable

Security considerations:
- PEM keys stored in env.tier-agent (plaintext - production hardening needed)
- No persistent token storage (in-memory cache only)
- Short-lived tokens (JWT <10min, installation tokens = 1 hour)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(submodules): promote nested submodule pointers (HiRAG, BotZ-gateway)

- external/PMOVES-HiRAG: 89d4abf→e904b12 (CHIT + geometry bus context, PR #4)
- pmoves_multi_agent_pro_pack/PMOVES-BotZ-gateway: 40e1e33→2565022 (log sanitizer, PR #4)

Both commits are merged on their respective origin/main branches.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore(submodules): recover nested wipes + promote BoTZ skill pointers

- Recovered 3 wiped nested subs: Deep-Serch (88 files), tensorzero
  (2906 files), docling (839 files) — same wipe pattern as Phase 5
- Recovered 6 wiped sub-sub-subs inside nested BoTZ copy
- Promoted 7 skill repo pointer advances in nested BoTZ copy

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: leex279 <thomas@thirty3.de>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: sean-eskerium <sean@eskerium.com>
Co-authored-by: Jason Pickens <jasonpickensnz@gmail.com>
Co-authored-by: POWERFULMOVES <POWERFULMOVES@users.noreply.github.com>
Co-authored-by: PMOVES.AI <claude@pmoves.ai>
Co-authored-by: Shaela Bello <slbello@uncg.edu>
joaobmonteiro pushed a commit to joaobmonteiro/Archon that referenced this pull request Apr 26, 2026
)

Add per-project environment variable management as a first-class config
primitive. Env vars defined in .archon/config.yaml or stored in DB via
Web UI are merged into Options.env on Claude SDK calls.

Three env var sources merge in priority order (later wins):
1. process.env — global, from ~/.archon/.env via dotenv
2. .archon/config.yaml env: section — file-based per-project
3. DB remote_agent_codebase_env_vars table — Web UI per-project

Changes:
- Add remote_agent_codebase_env_vars table (PG migration + SQLite schema)
- Add DB CRUD module (packages/core/src/db/env-vars.ts)
- Extend IWorkflowStore with getCodebaseEnvVars method
- Add env field to RepoConfig, MergedConfig, WorkflowConfig, WorkflowAssistantOptions, AssistantRequestOptions
- Merge DB env vars in executor after config load
- Inject env vars into Claude subprocess via Options.env
- Add 3 API routes (GET/PUT/DELETE /api/codebases/:id/env)
- Add EnvVarsPanel to Settings page with masked value display

Fixes coleam00#852
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Add OpenRouter embeddings support

3 participants