feat: add API settings page for managing providers, endpoints, cache, model pools, and CLI settings

feat: implement semantic install dialog for CodexLens with GPU mode selection
feat: add radio group component for GPU mode selection
feat: update navigation and localization for API settings and semantic install
This commit is contained in:
catlog22
2026-02-02 11:16:19 +08:00
parent e4b627bc76
commit a54246a46f
10 changed files with 2648 additions and 14 deletions

View File

@@ -16,6 +16,9 @@ export const flowKeys = {
list: (filters?: Record<string, unknown>) => [...flowKeys.lists(), filters] as const,
details: () => [...flowKeys.all, 'detail'] as const,
detail: (id: string) => [...flowKeys.details(), id] as const,
executions: () => [...flowKeys.all, 'execution'] as const,
executionState: (execId: string) => [...flowKeys.executions(), 'state', execId] as const,
executionLogs: (execId: string, options?: Record<string, unknown>) => [...flowKeys.executions(), 'logs', execId, options] as const,
};
// API response types
@@ -293,3 +296,72 @@ export function useStopExecution() {
mutationFn: stopExecution,
});
}
// ========== Execution Monitoring Fetch Functions ==========
async function fetchExecutionStateById(execId: string): Promise<{ success: boolean; data: { execId: string; flowId: string; status: string; currentNodeId?: string; startedAt: string; completedAt?: string; elapsedMs: number } }> {
const response = await fetch(`${API_BASE}/executions/${execId}`);
if (!response.ok) {
throw new Error(`Failed to fetch execution state: ${response.statusText}`);
}
return response.json();
}
async function fetchExecutionLogsById(
execId: string,
options?: {
limit?: number;
offset?: number;
level?: string;
nodeId?: string;
}
): Promise<{ success: boolean; data: { execId: string; logs: unknown[]; total: number; limit: number; offset: number; hasMore: boolean } }> {
const params = new URLSearchParams();
if (options?.limit) params.append('limit', String(options.limit));
if (options?.offset) params.append('offset', String(options.offset));
if (options?.level) params.append('level', options.level);
if (options?.nodeId) params.append('nodeId', options.nodeId);
const queryString = params.toString();
const response = await fetch(`${API_BASE}/executions/${execId}/logs${queryString ? `?${queryString}` : ''}`);
if (!response.ok) {
throw new Error(`Failed to fetch execution logs: ${response.statusText}`);
}
return response.json();
}
// ========== Execution Monitoring Query Hooks ==========
/**
* Fetch execution state
* Uses useQuery to get execution state, enabled when execId exists
*/
export function useExecutionState(execId: string | null) {
return useQuery({
queryKey: flowKeys.executionState(execId ?? ''),
queryFn: () => fetchExecutionStateById(execId!),
enabled: !!execId,
staleTime: 5000, // 5 seconds - needs more frequent updates for monitoring
});
}
/**
* Fetch execution logs with pagination
* Uses useQuery to get execution logs with pagination support
*/
export function useExecutionLogs(
execId: string | null,
options?: {
limit?: number;
offset?: number;
level?: string;
nodeId?: string;
}
) {
return useQuery({
queryKey: flowKeys.executionLogs(execId ?? '', options),
queryFn: () => fetchExecutionLogsById(execId!, options),
enabled: !!execId,
staleTime: 10000, // 10 seconds
});
}

View File

@@ -3822,3 +3822,72 @@ export async function toggleCliSettingsEnabled(endpointId: string, enabled: bool
export async function getCliSettingsPath(endpointId: string): Promise<{ endpointId: string; filePath: string; enabled: boolean }> {
return fetchApi(`/api/cli/settings/${encodeURIComponent(endpointId)}/path`);
}
// ========== Orchestrator Execution Monitoring API ==========
/**
* Execution state response from orchestrator
*/
export interface ExecutionStateResponse {
execId: string;
flowId: string;
status: 'pending' | 'running' | 'paused' | 'completed' | 'failed';
currentNodeId?: string;
startedAt: string;
completedAt?: string;
elapsedMs: number;
}
/**
* Execution log entry
*/
export interface ExecutionLogEntry {
timestamp: string;
level: 'info' | 'warn' | 'error' | 'debug';
nodeId?: string;
message: string;
}
/**
* Execution logs response
*/
export interface ExecutionLogsResponse {
execId: string;
logs: ExecutionLogEntry[];
total: number;
limit: number;
offset: number;
hasMore: boolean;
}
/**
* Fetch execution state by execId
* @param execId - Execution ID
*/
export async function fetchExecutionState(execId: string): Promise<{ success: boolean; data: ExecutionStateResponse }> {
return fetchApi(`/api/orchestrator/executions/${encodeURIComponent(execId)}`);
}
/**
* Fetch execution logs with pagination and filtering
* @param execId - Execution ID
* @param options - Query options
*/
export async function fetchExecutionLogs(
execId: string,
options?: {
limit?: number;
offset?: number;
level?: 'info' | 'warn' | 'error' | 'debug';
nodeId?: string;
}
): Promise<{ success: boolean; data: ExecutionLogsResponse }> {
const params = new URLSearchParams();
if (options?.limit) params.append('limit', String(options.limit));
if (options?.offset) params.append('offset', String(options.offset));
if (options?.level) params.append('level', options.level);
if (options?.nodeId) params.append('nodeId', options.nodeId);
const queryString = params.toString();
return fetchApi(`/api/orchestrator/executions/${encodeURIComponent(execId)}/logs${queryString ? `?${queryString}` : ''}`);
}