Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9b2a17f
Add Anthropic and Grok provider support
Sep 18, 2025
791ecd1
feat: Add crucial GPT-5 and reasoning model support for OpenRouter
Sep 19, 2025
9a7a34d
fully working model providers, addressing securtiy and code related c…
Sep 19, 2025
e9a78e8
added multiprovider support, embeddings model support, cleaned the pr…
Sep 20, 2025
4dc3e97
fixed contextual embeddings issue
Sep 20, 2025
b7b1167
- Added inspect-aware shutdown handling so get_llm_client always clos…
Sep 20, 2025
7cc29ac
- Restructured get_llm_client so client creation and usage live in …
Sep 20, 2025
6fdce7b
added provider connection support
Sep 20, 2025
3ed0281
added provider api key not being configured warning
Sep 20, 2025
c5d5342
Updated get_llm_client so missing OpenAI keys automatically fall bac…
Sep 20, 2025
2314be7
Resolved a few needed code rabbit suggestion - Updated the knowledg…
Sep 20, 2025
2878f5d
updated via code rabbit PR review, code rabbit in my IDE found no iss…
Sep 21, 2025
6f15225
test fix
Sep 21, 2025
dca839d
enhanced Openrouters parsing logic to automatically detect reasoning …
Sep 21, 2025
ba387a6
bringing to current branch
Sep 24, 2025
d15cc31
updated ui llm interface, added seprate embeddings provider, made the…
Sep 25, 2025
94e3230
added warning labels and updated ollama health checks
Sep 25, 2025
810c80f
ready for review, fixed som error warnings and consildated ollama sta…
Sep 25, 2025
11388d6
fixed FAILED test_async_embedding_service.py
Sep 25, 2025
aa354ca
code rabbit fixes
Sep 25, 2025
64835ec
Separated the code-summary LLM provider from the embedding provider, …
Sep 25, 2025
fedf595
- Swapped API credential storage to booleans so decrypted keys never…
Sep 25, 2025
ec4ceee
Update RAGSettings.tsx - header for 'LLM Settings' is now 'LLM Provid…
Chillbruhhh Sep 25, 2025
7b8c834
(RAG Settings)
Sep 25, 2025
dde9051
Merge branch 'feature/LLM-Providers-Ui-Polished' of https://github.co…
Sep 25, 2025
21cf54c
- migration/complete_setup.sql:101 seeds Google/OpenRouter/Anthropic…
Sep 25, 2025
b690695
- archon-ui-main/src/components/settings/RAGSettings.tsx:90 adds a …
Sep 25, 2025
c07beeb
Update credentialsService.ts default model
Chillbruhhh Sep 26, 2025
e438b71
updated the google embedding adapter for multi dimensional rag querying
Sep 28, 2025
4c00e79
Merge branch 'feature/LLM-Providers-Ui-Polished' of https://github.co…
Sep 28, 2025
b5930ba
thought this micro fix in the google embedding pushed with the embedd…
Sep 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,381 changes: 737 additions & 644 deletions archon-ui-main/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions archon-ui-main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.3.1",
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^6.26.2",
"tailwind-merge": "latest",
Expand Down
1,508 changes: 979 additions & 529 deletions archon-ui-main/src/components/settings/RAGSettings.tsx

Large diffs are not rendered by default.

41 changes: 30 additions & 11 deletions archon-ui-main/src/services/credentialsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface RagSettings {
OLLAMA_EMBEDDING_URL?: string;
OLLAMA_EMBEDDING_INSTANCE_NAME?: string;
EMBEDDING_MODEL?: string;
EMBEDDING_PROVIDER?: string;
// Crawling Performance Settings
CRAWL_BATCH_SIZE?: number;
CRAWL_MAX_CONCURRENT?: number;
Expand Down Expand Up @@ -75,6 +76,16 @@ import { getApiUrl } from "../config/api";
class CredentialsService {
private baseUrl = getApiUrl();

private notifyCredentialUpdate(keys: string[]): void {
if (typeof window === "undefined") {
return;
}

window.dispatchEvent(
new CustomEvent("archon:credentials-updated", { detail: { keys } })
);
}

private handleCredentialError(error: any, context: string): Error {
const errorMessage = error instanceof Error ? error.message : String(error);

Expand Down Expand Up @@ -182,15 +193,16 @@ class CredentialsService {
USE_CONTEXTUAL_EMBEDDINGS: false,
CONTEXTUAL_EMBEDDINGS_MAX_WORKERS: 3,
USE_HYBRID_SEARCH: true,
USE_AGENTIC_RAG: true,
USE_RERANKING: true,
MODEL_CHOICE: "gpt-4.1-nano",
LLM_PROVIDER: "openai",
LLM_BASE_URL: "",
LLM_INSTANCE_NAME: "",
OLLAMA_EMBEDDING_URL: "",
OLLAMA_EMBEDDING_INSTANCE_NAME: "",
EMBEDDING_MODEL: "",
USE_AGENTIC_RAG: true,
USE_RERANKING: true,
MODEL_CHOICE: "gpt-4.1-nano",
LLM_PROVIDER: "openai",
LLM_BASE_URL: "",
LLM_INSTANCE_NAME: "",
OLLAMA_EMBEDDING_URL: "",
OLLAMA_EMBEDDING_INSTANCE_NAME: "",
EMBEDDING_PROVIDER: "openai",
EMBEDDING_MODEL: "",
// Crawling Performance Settings defaults
Comment thread
coderabbitai[bot] marked this conversation as resolved.
CRAWL_BATCH_SIZE: 50,
CRAWL_MAX_CONCURRENT: 10,
Expand Down Expand Up @@ -221,6 +233,7 @@ class CredentialsService {
"LLM_INSTANCE_NAME",
"OLLAMA_EMBEDDING_URL",
"OLLAMA_EMBEDDING_INSTANCE_NAME",
"EMBEDDING_PROVIDER",
"EMBEDDING_MODEL",
"CRAWL_WAIT_STRATEGY",
].includes(cred.key)
Expand Down Expand Up @@ -278,7 +291,9 @@ class CredentialsService {
throw new Error(`HTTP ${response.status}: ${errorText}`);
}

return response.json();
const updated = await response.json();
this.notifyCredentialUpdate([credential.key]);
return updated;
} catch (error) {
throw this.handleCredentialError(
error,
Expand All @@ -302,7 +317,9 @@ class CredentialsService {
throw new Error(`HTTP ${response.status}: ${errorText}`);
}

return response.json();
const created = await response.json();
this.notifyCredentialUpdate([credential.key]);
return created;
} catch (error) {
throw this.handleCredentialError(
error,
Expand All @@ -321,6 +338,8 @@ class CredentialsService {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}

this.notifyCredentialUpdate([key]);
} catch (error) {
throw this.handleCredentialError(error, `Deleting credential '${key}'`);
}
Expand Down
18 changes: 18 additions & 0 deletions migration/0.1.0/009_add_provider_placeholders.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- Migration: 009_add_provider_placeholders.sql
-- Description: Add placeholder API key rows for OpenRouter, Anthropic, and Grok
-- Version: 0.1.0
-- Author: Archon Team
-- Date: 2025

-- Insert provider API key placeholders (idempotent)
INSERT INTO archon_settings (key, encrypted_value, is_encrypted, category, description)
VALUES
('OPENROUTER_API_KEY', NULL, true, 'api_keys', 'OpenRouter API key for hosted community models. Get from: https://openrouter.ai/keys'),
('ANTHROPIC_API_KEY', NULL, true, 'api_keys', 'Anthropic API key for Claude models. Get from: https://console.anthropic.com/account/keys'),
('GROK_API_KEY', NULL, true, 'api_keys', 'Grok API key for xAI models. Get from: https://console.x.ai/')
ON CONFLICT (key) DO NOTHING;

-- Record migration application for tracking
INSERT INTO archon_migrations (version, migration_name)
VALUES ('0.1.0', '009_add_provider_placeholders')
ON CONFLICT (version, migration_name) DO NOTHING;
5 changes: 4 additions & 1 deletion migration/complete_setup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ ON CONFLICT (key) DO NOTHING;

-- Add provider API key placeholders
INSERT INTO archon_settings (key, encrypted_value, is_encrypted, category, description) VALUES
('GOOGLE_API_KEY', NULL, true, 'api_keys', 'Google API Key for Gemini models. Get from: https://aistudio.google.com/apikey')
('GOOGLE_API_KEY', NULL, true, 'api_keys', 'Google API key for Gemini models. Get from: https://aistudio.google.com/apikey'),
('OPENROUTER_API_KEY', NULL, true, 'api_keys', 'OpenRouter API key for hosted community models. Get from: https://openrouter.ai/keys'),
('ANTHROPIC_API_KEY', NULL, true, 'api_keys', 'Anthropic API key for Claude models. Get from: https://console.anthropic.com/account/keys'),
('GROK_API_KEY', NULL, true, 'api_keys', 'Grok API key for xAI models. Get from: https://console.x.ai/')
ON CONFLICT (key) DO NOTHING;

-- Code Extraction Settings Migration
Expand Down
4 changes: 2 additions & 2 deletions python/src/server/api_routes/knowledge_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1288,7 +1288,7 @@ async def stop_crawl_task(progress_id: str):

found = False
# Step 1: Cancel the orchestration service
orchestration = get_active_orchestration(progress_id)
orchestration = await get_active_orchestration(progress_id)
if orchestration:
orchestration.cancel()
found = True
Expand All @@ -1306,7 +1306,7 @@ async def stop_crawl_task(progress_id: str):
found = True

# Step 3: Remove from active orchestrations registry
unregister_orchestration(progress_id)
await unregister_orchestration(progress_id)

# Step 4: Update progress tracker to reflect cancellation (only if we found and cancelled something)
if found:
Expand Down
68 changes: 58 additions & 10 deletions python/src/server/services/crawling/code_extraction_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ async def extract_and_store_code_examples(
progress_callback: Callable | None = None,
cancellation_check: Callable[[], None] | None = None,
provider: str | None = None,
embedding_provider: str | None = None,
) -> int:
"""
Extract code examples from crawled documents and store them.
Expand All @@ -150,6 +151,8 @@ async def extract_and_store_code_examples(
source_id: The unique source_id for all documents
progress_callback: Optional async callback for progress updates
cancellation_check: Optional function to check for cancellation
provider: Optional LLM provider identifier for summary generation
embedding_provider: Optional embedding provider override for vector creation

Returns:
Number of code examples stored
Expand All @@ -158,9 +161,16 @@ async def extract_and_store_code_examples(
extraction_callback = None
if progress_callback:
async def extraction_progress(data: dict):
# Scale progress to 0-20% range
raw_progress = data.get("progress", 0)
scaled_progress = int(raw_progress * 0.2) # 0-20%
# Scale progress to 0-20% range with normalization similar to later phases
raw = data.get("progress", data.get("percentage", 0))
try:
raw_num = float(raw)
except (TypeError, ValueError):
raw_num = 0.0
if 0.0 <= raw_num <= 1.0:
raw_num *= 100.0
# 0-20% with clamping
scaled_progress = min(20, max(0, int(raw_num * 0.2)))
data["progress"] = scaled_progress
await progress_callback(data)
extraction_callback = extraction_progress
Expand Down Expand Up @@ -197,8 +207,15 @@ async def extraction_progress(data: dict):
if progress_callback:
async def summary_progress(data: dict):
# Scale progress to 20-90% range
raw_progress = data.get("progress", 0)
scaled_progress = 20 + int(raw_progress * 0.7) # 20-90%
raw = data.get("progress", data.get("percentage", 0))
try:
raw_num = float(raw)
except (TypeError, ValueError):
raw_num = 0.0
if 0.0 <= raw_num <= 1.0:
raw_num *= 100.0
# 20-90% with clamping
scaled_progress = min(90, max(20, 20 + int(raw_num * 0.7)))
data["progress"] = scaled_progress
await progress_callback(data)
summary_callback = summary_progress
Expand All @@ -216,15 +233,26 @@ async def summary_progress(data: dict):
if progress_callback:
async def storage_progress(data: dict):
# Scale progress to 90-100% range
raw_progress = data.get("progress", 0)
scaled_progress = 90 + int(raw_progress * 0.1) # 90-100%
raw = data.get("progress", data.get("percentage", 0))
try:
raw_num = float(raw)
except (TypeError, ValueError):
raw_num = 0.0
if 0.0 <= raw_num <= 1.0:
raw_num *= 100.0
# 90-100% with clamping
scaled_progress = min(100, max(90, 90 + int(raw_num * 0.1)))
data["progress"] = scaled_progress
await progress_callback(data)
storage_callback = storage_progress

# Store code examples in database
return await self._store_code_examples(
storage_data, url_to_full_document, storage_callback, provider
storage_data,
url_to_full_document,
storage_callback,
provider,
embedding_provider,
)

async def _extract_code_blocks_from_documents(
Expand Down Expand Up @@ -880,9 +908,20 @@ async def _extract_text_file_code_blocks(
current_indent = indent
block_start_idx = i
current_block.append(line)
elif current_block and len("\n".join(current_block)) >= min_length:
elif current_block:
block_text = "\n".join(current_block)
threshold = (
min_length
if min_length is not None
else await self._get_min_code_length()
)
if len(block_text) < threshold:
current_block = []
current_indent = None
continue

# End of indented block, check if it's code
code_content = "\n".join(current_block)
code_content = block_text

# Try to detect language from content
language = self._detect_language_from_content(code_content)
Expand Down Expand Up @@ -1670,12 +1709,20 @@ async def _store_code_examples(
url_to_full_document: dict[str, str],
progress_callback: Callable | None = None,
provider: str | None = None,
embedding_provider: str | None = None,
) -> int:
"""
Store code examples in the database.

Returns:
Number of code examples stored

Args:
storage_data: Prepared code example payloads
url_to_full_document: Mapping of URLs to their full document content
progress_callback: Optional callback for progress updates
provider: Optional LLM provider identifier for summaries
embedding_provider: Optional embedding provider override for vector storage
"""
# Create progress callback for storage phase
storage_progress_callback = None
Expand Down Expand Up @@ -1713,6 +1760,7 @@ async def storage_callback(data: dict):
url_to_full_document=url_to_full_document,
progress_callback=storage_progress_callback,
provider=provider,
embedding_provider=embedding_provider,
)

# Report completion of code extraction/storage phase
Expand Down
Loading