Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion archon-ui-main/src/components/layouts/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export const MainLayout: React.FC<MainLayoutProps> = ({
const timeoutId = setTimeout(() => controller.abort(), 5000);

// Check if backend is responding with a simple health check
const response = await fetch(`${credentialsService['baseUrl']}/api/health`, {
// Always use the proxy endpoint to ensure it works through Vite proxy
const response = await fetch('/api/health', {
method: 'GET',
signal: controller.signal
});
Expand Down
4 changes: 2 additions & 2 deletions archon-ui-main/src/components/settings/FeaturesSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const FeaturesSection = () => {
const [logfireResponse, projectsResponse, projectsHealthResponse, disconnectScreenRes] = await Promise.all([
credentialsService.getCredential('LOGFIRE_ENABLED').catch(() => ({ value: undefined })),
credentialsService.getCredential('PROJECTS_ENABLED').catch(() => ({ value: undefined })),
fetch(`${credentialsService['baseUrl']}/api/projects/health`).catch(() => null),
fetch('/api/projects/health').catch(() => null),
credentialsService.getCredential('DISCONNECT_SCREEN_ENABLED').catch(() => ({ value: 'true' }))
]);

Expand All @@ -58,7 +58,7 @@ export const FeaturesSection = () => {
response: projectsHealthResponse,
ok: projectsHealthResponse?.ok,
status: projectsHealthResponse?.status,
url: `${credentialsService['baseUrl']}/api/projects/health`
url: '/api/projects/health'
});

if (projectsHealthResponse && projectsHealthResponse.ok) {
Expand Down
14 changes: 3 additions & 11 deletions archon-ui-main/src/config/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,9 @@ export function getApiUrl(): string {
return import.meta.env.VITE_API_URL;
}

// For development, construct from window location
const protocol = window.location.protocol;
const host = window.location.hostname;
// Use configured port or default to 8181
const port = import.meta.env.VITE_ARCHON_SERVER_PORT || '8181';

if (!import.meta.env.VITE_ARCHON_SERVER_PORT) {
console.info('[Archon] Using default ARCHON_SERVER_PORT: 8181');
}

return `${protocol}//${host}:${port}`;
// In development mode, always use relative URLs to go through Vite proxy
// This ensures the proxy configuration in vite.config.ts is used
return '';
}

// Get the base path for API endpoints
Expand Down
2 changes: 1 addition & 1 deletion archon-ui-main/src/services/bugReportService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class BugReportService {
context: bugReport.context
};

const response = await fetch(`${getApiUrl()}/api/bug-report/github`, {
const response = await fetch('/api/bug-report/github', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Expand Down
15 changes: 8 additions & 7 deletions archon-ui-main/src/services/credentialsService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export interface CodeExtractionSettings {
import { getApiUrl } from "../config/api";

class CredentialsService {
private baseUrl = getApiUrl();
// Always use relative URLs to go through Vite proxy
private baseUrl = '';

private handleCredentialError(error: any, context: string): Error {
const errorMessage = error instanceof Error ? error.message : String(error);
Expand All @@ -78,7 +79,7 @@ class CredentialsService {
}

async getAllCredentials(): Promise<Credential[]> {
const response = await fetch(`${this.baseUrl}/api/credentials`);
const response = await fetch('/api/credentials');
if (!response.ok) {
throw new Error("Failed to fetch credentials");
}
Expand All @@ -87,7 +88,7 @@ class CredentialsService {

async getCredentialsByCategory(category: string): Promise<Credential[]> {
const response = await fetch(
`${this.baseUrl}/api/credentials/categories/${category}`,
`/api/credentials/categories/${category}`,
);
if (!response.ok) {
throw new Error(`Failed to fetch credentials for category: ${category}`);
Expand Down Expand Up @@ -128,7 +129,7 @@ class CredentialsService {
async getCredential(
key: string,
): Promise<{ key: string; value?: string; is_encrypted?: boolean }> {
const response = await fetch(`${this.baseUrl}/api/credentials/${key}`);
const response = await fetch(`/api/credentials/${key}`);
if (!response.ok) {
if (response.status === 404) {
// Return empty object if credential not found
Expand Down Expand Up @@ -222,7 +223,7 @@ class CredentialsService {
async updateCredential(credential: Credential): Promise<Credential> {
try {
const response = await fetch(
`${this.baseUrl}/api/credentials/${credential.key}`,
`/api/credentials/${credential.key}`,
{
method: "PUT",
headers: {
Expand All @@ -248,7 +249,7 @@ class CredentialsService {

async createCredential(credential: Credential): Promise<Credential> {
try {
const response = await fetch(`${this.baseUrl}/api/credentials`, {
const response = await fetch('/api/credentials', {
method: "POST",
headers: {
"Content-Type": "application/json",
Expand All @@ -272,7 +273,7 @@ class CredentialsService {

async deleteCredential(key: string): Promise<void> {
try {
const response = await fetch(`${this.baseUrl}/api/credentials/${key}`, {
const response = await fetch(`/api/credentials/${key}`, {
method: "DELETE",
});

Expand Down
29 changes: 15 additions & 14 deletions archon-ui-main/src/services/mcpClientService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ import { getApiUrl } from '../config/api';
* This service communicates with the standalone Python MCP client service
*/
class MCPClientService {
private baseUrl = getApiUrl();
// Always use relative URLs to go through Vite proxy
private baseUrl = '';

// ========================================
// CLIENT MANAGEMENT
Expand All @@ -106,7 +107,7 @@ class MCPClientService {
* Get all configured MCP clients
*/
async getClients(): Promise<MCPClient[]> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/`);
const response = await fetch('/api/mcp/clients/');

if (!response.ok) {
throw new Error('Failed to get MCP clients');
Expand All @@ -119,7 +120,7 @@ class MCPClientService {
* Create a new MCP client
*/
async createClient(config: MCPClientConfig): Promise<MCPClient> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/`, {
const response = await fetch('/api/mcp/clients/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config)
Expand All @@ -137,7 +138,7 @@ class MCPClientService {
* Get a specific MCP client
*/
async getClient(clientId: string): Promise<MCPClient> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/${clientId}`);
const response = await fetch(`/api/mcp/clients/${clientId}`);

if (!response.ok) {
const error = await response.json();
Expand All @@ -151,7 +152,7 @@ class MCPClientService {
* Update an MCP client
*/
async updateClient(clientId: string, updates: Partial<MCPClientConfig>): Promise<MCPClient> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/${clientId}`, {
const response = await fetch(`/api/mcp/clients/${clientId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates)
Expand All @@ -169,7 +170,7 @@ class MCPClientService {
* Delete an MCP client
*/
async deleteClient(clientId: string): Promise<{ success: boolean; message: string }> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/${clientId}`, {
const response = await fetch(`/api/mcp/clients/${clientId}`, {
method: 'DELETE'
});

Expand All @@ -189,7 +190,7 @@ class MCPClientService {
* Connect to an MCP client
*/
async connectClient(clientId: string): Promise<{ success: boolean; message: string }> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/${clientId}/connect`, {
const response = await fetch(`/api/mcp/clients/${clientId}/connect`, {
method: 'POST'
});

Expand All @@ -205,7 +206,7 @@ class MCPClientService {
* Disconnect from an MCP client
*/
async disconnectClient(clientId: string): Promise<{ success: boolean; message: string }> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/${clientId}/disconnect`, {
const response = await fetch(`/api/mcp/clients/${clientId}/disconnect`, {
method: 'POST'
});

Expand All @@ -221,7 +222,7 @@ class MCPClientService {
* Get client status and health
*/
async getClientStatus(clientId: string): Promise<ClientStatus> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/${clientId}/status`);
const response = await fetch(`/api/mcp/clients/${clientId}/status`);

if (!response.ok) {
const error = await response.json();
Expand All @@ -235,7 +236,7 @@ class MCPClientService {
* Test a client configuration before saving
*/
async testClientConfig(config: MCPClientConfig): Promise<{ success: boolean; message: string }> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/test-config`, {
const response = await fetch('/api/mcp/clients/test-config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(config)
Expand All @@ -257,7 +258,7 @@ class MCPClientService {
* Get tools from a specific client
*/
async getClientTools(clientId: string): Promise<ToolsResponse> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/${clientId}/tools`);
const response = await fetch(`/api/mcp/clients/${clientId}/tools`);

if (!response.ok) {
const error = await response.json();
Expand All @@ -271,7 +272,7 @@ class MCPClientService {
* Call a tool on a specific client
*/
async callClientTool(request: ToolCallRequest): Promise<any> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/tools/call`, {
const response = await fetch('/api/mcp/clients/tools/call', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request)
Expand All @@ -289,7 +290,7 @@ class MCPClientService {
* Get tools from all connected clients (including Archon via MCP client)
*/
async getAllAvailableTools(): Promise<AllToolsResponse> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/tools/all`);
const response = await fetch('/api/mcp/clients/tools/all');

if (!response.ok) {
const error = await response.json();
Expand All @@ -303,7 +304,7 @@ class MCPClientService {
* Discover tools from a specific client (force refresh)
*/
async discoverClientTools(clientId: string): Promise<ToolsResponse> {
const response = await fetch(`${this.baseUrl}/api/mcp/clients/${clientId}/tools/discover`, {
const response = await fetch(`/api/mcp/clients/${clientId}/tools/discover`, {
method: 'POST'
});

Expand Down
3 changes: 2 additions & 1 deletion archon-ui-main/src/services/testService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export interface TestStatus {
import { getApiUrl, getWebSocketUrl } from '../config/api';

// Use unified API configuration
const API_BASE_URL = getApiUrl();
// Always use relative URLs to go through Vite proxy
const API_BASE_URL = '';

// Error class for test service errors
export class TestServiceError extends Error {
Expand Down
3 changes: 3 additions & 0 deletions python/src/server/api_routes/knowledge_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,9 @@ async def knowledge_health():
"status": "healthy",
"service": "knowledge-api",
"timestamp": datetime.now().isoformat(),
"ready": True,
"credentials_loaded": True,
"schema_valid": True,
}
Comment on lines +886 to 889
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Derive readiness flags instead of hard-coding True.

Hard-coding ready/credentials/schema as True can mislead the UI and mask startup/config issues. Compute them from actual state and env so external clients don’t proceed prematurely.

Apply this diff within the response block:

-    "ready": True,
-    "credentials_loaded": True,
-    "schema_valid": True,
+    "ready": credentials_loaded and schema_status["valid"],
+    "credentials_loaded": credentials_loaded,
+    "schema_valid": True,

And add this snippet inside knowledge_health() before building result:

import os  # if not already imported at top
credentials_loaded = bool(
    os.getenv("SUPABASE_URL")
    and (os.getenv("SUPABASE_SERVICE_ROLE_KEY") or os.getenv("SUPABASE_ANON_KEY"))
)
# Optionally include LM provider keys if required for your ready gate:
# credentials_loaded = credentials_loaded and bool(os.getenv("OPENAI_API_KEY") or os.getenv("ANTHROPIC_API_KEY"))

Would you like me to wire a lightweight Supabase connectivity probe with a short timeout to further validate readiness?

🤖 Prompt for AI Agents
In python/src/server/api_routes/knowledge_api.py around lines 886 to 889, the
readiness fields are hard-coded to True which can mislead clients; compute
credentials_loaded and ready from environment/state instead: add an import for
os if missing and insert the provided credentials_loaded assignment before
building result, then replace "credentials_loaded": True and "ready": True with
"credentials_loaded": credentials_loaded and "ready": credentials_loaded (or a
combined boolean that also checks any LM provider keys you require); similarly
compute and set "schema_valid" based on your actual schema validation logic
instead of True; optionally consider wiring a short-timeout Supabase
connectivity probe to further validate readiness.


return result
Expand Down