aboutsummaryrefslogtreecommitdiff
path: root/llama.cpp/tools/server/webui/src/lib/services/models.ts
blob: eecb7fa26287be378a78b78cbc2b10977b0355ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { base } from '$app/paths';
import { ServerModelStatus } from '$lib/enums';
import { getJsonHeaders } from '$lib/utils';

/**
 * ModelsService - Stateless service for model management API communication
 *
 * This service handles communication with model-related endpoints:
 * - `/v1/models` - OpenAI-compatible model list (MODEL + ROUTER mode)
 * - `/models/load`, `/models/unload` - Router-specific model management (ROUTER mode only)
 *
 * **Responsibilities:**
 * - List available models
 * - Load/unload models (ROUTER mode)
 * - Check model status (ROUTER mode)
 *
 * **Used by:**
 * - modelsStore: Primary consumer for model state management
 */
export class ModelsService {
	// ─────────────────────────────────────────────────────────────────────────────
	// Listing
	// ─────────────────────────────────────────────────────────────────────────────

	/**
	 * Fetch list of models from OpenAI-compatible endpoint
	 * Works in both MODEL and ROUTER modes
	 */
	static async list(): Promise<ApiModelListResponse> {
		const response = await fetch(`${base}/v1/models`, {
			headers: getJsonHeaders()
		});

		if (!response.ok) {
			throw new Error(`Failed to fetch model list (status ${response.status})`);
		}

		return response.json() as Promise<ApiModelListResponse>;
	}

	/**
	 * Fetch list of all models with detailed metadata (ROUTER mode)
	 * Returns models with load status, paths, and other metadata
	 */
	static async listRouter(): Promise<ApiRouterModelsListResponse> {
		const response = await fetch(`${base}/v1/models`, {
			headers: getJsonHeaders()
		});

		if (!response.ok) {
			throw new Error(`Failed to fetch router models list (status ${response.status})`);
		}

		return response.json() as Promise<ApiRouterModelsListResponse>;
	}

	// ─────────────────────────────────────────────────────────────────────────────
	// Load/Unload
	// ─────────────────────────────────────────────────────────────────────────────

	/**
	 * Load a model (ROUTER mode)
	 * POST /models/load
	 * @param modelId - Model identifier to load
	 * @param extraArgs - Optional additional arguments to pass to the model instance
	 */
	static async load(modelId: string, extraArgs?: string[]): Promise<ApiRouterModelsLoadResponse> {
		const payload: { model: string; extra_args?: string[] } = { model: modelId };
		if (extraArgs && extraArgs.length > 0) {
			payload.extra_args = extraArgs;
		}

		const response = await fetch(`${base}/models/load`, {
			method: 'POST',
			headers: getJsonHeaders(),
			body: JSON.stringify(payload)
		});

		if (!response.ok) {
			const errorData = await response.json().catch(() => ({}));
			throw new Error(errorData.error || `Failed to load model (status ${response.status})`);
		}

		return response.json() as Promise<ApiRouterModelsLoadResponse>;
	}

	/**
	 * Unload a model (ROUTER mode)
	 * POST /models/unload
	 * @param modelId - Model identifier to unload
	 */
	static async unload(modelId: string): Promise<ApiRouterModelsUnloadResponse> {
		const response = await fetch(`${base}/models/unload`, {
			method: 'POST',
			headers: getJsonHeaders(),
			body: JSON.stringify({ model: modelId })
		});

		if (!response.ok) {
			const errorData = await response.json().catch(() => ({}));
			throw new Error(errorData.error || `Failed to unload model (status ${response.status})`);
		}

		return response.json() as Promise<ApiRouterModelsUnloadResponse>;
	}

	// ─────────────────────────────────────────────────────────────────────────────
	// Status
	// ─────────────────────────────────────────────────────────────────────────────

	/**
	 * Check if a model is loaded based on its metadata
	 */
	static isModelLoaded(model: ApiModelDataEntry): boolean {
		return model.status.value === ServerModelStatus.LOADED;
	}

	/**
	 * Check if a model is currently loading
	 */
	static isModelLoading(model: ApiModelDataEntry): boolean {
		return model.status.value === ServerModelStatus.LOADING;
	}
}