|
@@ -53,7 +53,7 @@ class RequestThrottler {
|
|
|
const throttler = new RequestThrottler();
|
|
const throttler = new RequestThrottler();
|
|
|
|
|
|
|
|
// Debounce utility for frequent calls
|
|
// Debounce utility for frequent calls
|
|
|
-function debounce<T extends (...args: any[]) => any>(
|
|
|
|
|
|
|
+function _debounce<T extends (...args: unknown[]) => unknown>(
|
|
|
func: T,
|
|
func: T,
|
|
|
wait: number,
|
|
wait: number,
|
|
|
immediate?: boolean,
|
|
immediate?: boolean,
|
|
@@ -77,11 +77,11 @@ function debounce<T extends (...args: any[]) => any>(
|
|
|
|
|
|
|
|
// Cache for API responses to reduce redundant calls
|
|
// Cache for API responses to reduce redundant calls
|
|
|
class ApiCache {
|
|
class ApiCache {
|
|
|
- private cache: Map<string, { data: any; timestamp: number; ttl: number }> =
|
|
|
|
|
|
|
+ private cache: Map<string, { data: unknown; timestamp: number; ttl: number }> =
|
|
|
new Map();
|
|
new Map();
|
|
|
private defaultTtl: number = 5000; // 5 seconds default TTL
|
|
private defaultTtl: number = 5000; // 5 seconds default TTL
|
|
|
|
|
|
|
|
- set(key: string, data: any, ttl?: number): void {
|
|
|
|
|
|
|
+ set(key: string, data: unknown, ttl?: number): void {
|
|
|
this.cache.set(key, {
|
|
this.cache.set(key, {
|
|
|
data,
|
|
data,
|
|
|
timestamp: Date.now(),
|
|
timestamp: Date.now(),
|
|
@@ -89,7 +89,7 @@ class ApiCache {
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- get(key: string): any | null {
|
|
|
|
|
|
|
+ get(key: string): unknown | null {
|
|
|
const cached = this.cache.get(key);
|
|
const cached = this.cache.get(key);
|
|
|
if (!cached) return null;
|
|
if (!cached) return null;
|
|
|
|
|
|
|
@@ -220,7 +220,7 @@ export interface ModelInfo {
|
|
|
recommended_vae?: RecommendedModelInfo;
|
|
recommended_vae?: RecommendedModelInfo;
|
|
|
recommended_textual_inversions?: RecommendedModelInfo[];
|
|
recommended_textual_inversions?: RecommendedModelInfo[];
|
|
|
recommended_loras?: RecommendedModelInfo[];
|
|
recommended_loras?: RecommendedModelInfo[];
|
|
|
- metadata?: Record<string, any>;
|
|
|
|
|
|
|
+ metadata?: Record<string, unknown>;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
export interface RequiredModelInfo {
|
|
export interface RequiredModelInfo {
|
|
@@ -257,7 +257,7 @@ export interface EnhancedModelsResponse {
|
|
|
has_next: boolean;
|
|
has_next: boolean;
|
|
|
has_prev: boolean;
|
|
has_prev: boolean;
|
|
|
};
|
|
};
|
|
|
- statistics: any;
|
|
|
|
|
|
|
+ statistics: Record<string, unknown>;
|
|
|
auto_selection?: AutoSelectionState;
|
|
auto_selection?: AutoSelectionState;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -344,12 +344,12 @@ class ApiClient {
|
|
|
const headers: Record<string, string> = {
|
|
const headers: Record<string, string> = {
|
|
|
"Content-Type": "application/json",
|
|
"Content-Type": "application/json",
|
|
|
...(options.headers as Record<string, string>),
|
|
...(options.headers as Record<string, string>),
|
|
|
- };
|
|
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
- if (authMethod === "unix" && unixUser) {
|
|
|
|
|
- // For Unix auth, send the username in X-Unix-User header
|
|
|
|
|
- headers["X-Unix-User"] = unixUser;
|
|
|
|
|
- } else if (token) {
|
|
|
|
|
|
|
+ if (authMethod === "unix" && unixUser) {
|
|
|
|
|
+ // For Unix auth, send username in X-Unix-User header
|
|
|
|
|
+ headers["X-Unix-User"] = unixUser;
|
|
|
|
|
+ } else if (token) {
|
|
|
// For JWT auth, send the token in Authorization header
|
|
// For JWT auth, send the token in Authorization header
|
|
|
headers["Authorization"] = `Bearer ${token}`;
|
|
headers["Authorization"] = `Bearer ${token}`;
|
|
|
}
|
|
}
|
|
@@ -380,7 +380,7 @@ class ApiClient {
|
|
|
// Enhanced health check with caching and better error handling
|
|
// Enhanced health check with caching and better error handling
|
|
|
async checkHealth(): Promise<HealthStatus> {
|
|
async checkHealth(): Promise<HealthStatus> {
|
|
|
const cacheKey = "health_check";
|
|
const cacheKey = "health_check";
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as HealthStatus | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -443,7 +443,7 @@ class ApiClient {
|
|
|
cache.set(cacheKey, healthStatus, 10000); // Cache for 10 seconds
|
|
cache.set(cacheKey, healthStatus, 10000); // Cache for 10 seconds
|
|
|
return healthStatus;
|
|
return healthStatus;
|
|
|
}
|
|
}
|
|
|
- } catch (error) {
|
|
|
|
|
|
|
+ } catch (error) {
|
|
|
// Continue to next endpoint if this one fails
|
|
// Continue to next endpoint if this one fails
|
|
|
console.warn(`Health check failed for endpoint ${endpoint}:`, error);
|
|
console.warn(`Health check failed for endpoint ${endpoint}:`, error);
|
|
|
continue;
|
|
continue;
|
|
@@ -457,8 +457,8 @@ class ApiClient {
|
|
|
// Alternative simple connectivity check with caching
|
|
// Alternative simple connectivity check with caching
|
|
|
async checkConnectivity(): Promise<boolean> {
|
|
async checkConnectivity(): Promise<boolean> {
|
|
|
const cacheKey = "connectivity_check";
|
|
const cacheKey = "connectivity_check";
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
- if (cachedResult !== null) {
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as boolean | undefined;
|
|
|
|
|
+ if (cachedResult !== undefined) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -470,7 +470,7 @@ class ApiClient {
|
|
|
const result = response.ok || response.status < 500;
|
|
const result = response.ok || response.status < 500;
|
|
|
cache.set(cacheKey, result, 5000); // Cache for 5 seconds
|
|
cache.set(cacheKey, result, 5000); // Cache for 5 seconds
|
|
|
return result;
|
|
return result;
|
|
|
- } catch (error) {
|
|
|
|
|
|
|
+ } catch {
|
|
|
cache.set(cacheKey, false, 5000); // Cache failure for 5 seconds
|
|
cache.set(cacheKey, false, 5000); // Cache failure for 5 seconds
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
@@ -518,7 +518,7 @@ class ApiClient {
|
|
|
// Job management with caching for status checks
|
|
// Job management with caching for status checks
|
|
|
async getJobStatus(jobId: string): Promise<JobDetailsResponse> {
|
|
async getJobStatus(jobId: string): Promise<JobDetailsResponse> {
|
|
|
const cacheKey = `job_status_${jobId}`;
|
|
const cacheKey = `job_status_${jobId}`;
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as JobDetailsResponse | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -647,7 +647,7 @@ class ApiClient {
|
|
|
// Get queue status with caching and throttling
|
|
// Get queue status with caching and throttling
|
|
|
async getQueueStatus(): Promise<QueueStatus> {
|
|
async getQueueStatus(): Promise<QueueStatus> {
|
|
|
const cacheKey = "queue_status";
|
|
const cacheKey = "queue_status";
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as QueueStatus | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -686,7 +686,7 @@ class ApiClient {
|
|
|
search?: string,
|
|
search?: string,
|
|
|
): Promise<EnhancedModelsResponse> {
|
|
): Promise<EnhancedModelsResponse> {
|
|
|
const cacheKey = `models_${type || "all"}_${loaded ? "loaded" : "all"}_${page}_${limit}_${search || "all"}`;
|
|
const cacheKey = `models_${type || "all"}_${loaded ? "loaded" : "all"}_${page}_${limit}_${search || "all"}`;
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as EnhancedModelsResponse | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -737,7 +737,7 @@ class ApiClient {
|
|
|
checkpointModel?: string,
|
|
checkpointModel?: string,
|
|
|
): Promise<EnhancedModelsResponse> {
|
|
): Promise<EnhancedModelsResponse> {
|
|
|
const cacheKey = `models_auto_selection_${checkpointModel || "none"}`;
|
|
const cacheKey = `models_auto_selection_${checkpointModel || "none"}`;
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as EnhancedModelsResponse | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -814,7 +814,7 @@ class ApiClient {
|
|
|
|
|
|
|
|
async getModelInfo(modelId: string): Promise<ModelInfo> {
|
|
async getModelInfo(modelId: string): Promise<ModelInfo> {
|
|
|
const cacheKey = `model_info_${modelId}`;
|
|
const cacheKey = `model_info_${modelId}`;
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as ModelInfo | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -862,7 +862,14 @@ class ApiClient {
|
|
|
}>
|
|
}>
|
|
|
> {
|
|
> {
|
|
|
const cacheKey = "model_types";
|
|
const cacheKey = "model_types";
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as Array<{
|
|
|
|
|
+ type: string;
|
|
|
|
|
+ description: string;
|
|
|
|
|
+ extensions: string[];
|
|
|
|
|
+ capabilities: string[];
|
|
|
|
|
+ requires?: string[];
|
|
|
|
|
+ recommended_for: string;
|
|
|
|
|
+ }> | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -904,12 +911,12 @@ class ApiClient {
|
|
|
return this.request<{ status: string }>("/health");
|
|
return this.request<{ status: string }>("/health");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- async getStatus(): Promise<any> {
|
|
|
|
|
- return this.request<any>("/status");
|
|
|
|
|
|
|
+ async getStatus(): Promise<Record<string, unknown>> {
|
|
|
|
|
+ return this.request<Record<string, unknown>>("/status");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- async getSystemInfo(): Promise<any> {
|
|
|
|
|
- return this.request<any>("/system");
|
|
|
|
|
|
|
+ async getSystemInfo(): Promise<Record<string, unknown>> {
|
|
|
|
|
+ return this.request<Record<string, unknown>>("/system");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async restartServer(): Promise<{ message: string }> {
|
|
async restartServer(): Promise<{ message: string }> {
|
|
@@ -959,7 +966,7 @@ class ApiClient {
|
|
|
Array<{ name: string; description: string; recommended_steps: number }>
|
|
Array<{ name: string; description: string; recommended_steps: number }>
|
|
|
> {
|
|
> {
|
|
|
const cacheKey = "samplers";
|
|
const cacheKey = "samplers";
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as Array<{ name: string; description: string; recommended_steps: number }> | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -977,7 +984,7 @@ class ApiClient {
|
|
|
|
|
|
|
|
async getSchedulers(): Promise<Array<{ name: string; description: string }>> {
|
|
async getSchedulers(): Promise<Array<{ name: string; description: string }>> {
|
|
|
const cacheKey = "schedulers";
|
|
const cacheKey = "schedulers";
|
|
|
- const cachedResult = cache.get(cacheKey);
|
|
|
|
|
|
|
+ const cachedResult = cache.get(cacheKey) as Array<{ name: string; description: string }> | null;
|
|
|
if (cachedResult) {
|
|
if (cachedResult) {
|
|
|
return cachedResult;
|
|
return cachedResult;
|
|
|
}
|
|
}
|
|
@@ -996,7 +1003,11 @@ class ApiClient {
|
|
|
|
|
|
|
|
clearCacheByPrefix(prefix: string): void {
|
|
clearCacheByPrefix(prefix: string): void {
|
|
|
const keysToDelete: string[] = [];
|
|
const keysToDelete: string[] = [];
|
|
|
- (cache as any).cache.forEach((_: any, key: string) => {
|
|
|
|
|
|
|
+ // Access the private cache property through type assertion for cleanup
|
|
|
|
|
+ const cacheInstance = cache as unknown as {
|
|
|
|
|
+ cache: Map<string, { data: unknown; timestamp: number; ttl: number }>
|
|
|
|
|
+ };
|
|
|
|
|
+ cacheInstance.cache.forEach((_: unknown, key: string) => {
|
|
|
if (key.startsWith(prefix)) {
|
|
if (key.startsWith(prefix)) {
|
|
|
keysToDelete.push(key);
|
|
keysToDelete.push(key);
|
|
|
}
|
|
}
|
|
@@ -1013,6 +1024,9 @@ export async function apiRequest(
|
|
|
const { apiUrl, apiBase } = getApiConfig();
|
|
const { apiUrl, apiBase } = getApiConfig();
|
|
|
const url = `${apiUrl}${apiBase}${endpoint}`;
|
|
const url = `${apiUrl}${apiBase}${endpoint}`;
|
|
|
|
|
|
|
|
|
|
+ // For both Unix and JWT auth, send username and password
|
|
|
|
|
+ // The server will handle whether password is required based on PAM availability
|
|
|
|
|
+
|
|
|
// Get authentication method from server config
|
|
// Get authentication method from server config
|
|
|
const authMethod =
|
|
const authMethod =
|
|
|
typeof window !== "undefined" && window.__SERVER_CONFIG__
|
|
typeof window !== "undefined" && window.__SERVER_CONFIG__
|