Migrate local inference model management to ACP (#10124)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,99 @@
|
||||
import type {
|
||||
LocalInferenceDownloadProgressDto,
|
||||
LocalInferenceHfModelInfoDto,
|
||||
LocalInferenceHfModelVariantDto,
|
||||
LocalInferenceModelDownloadRequest_unstable,
|
||||
LocalInferenceModelDto,
|
||||
LocalInferenceModelSettingsDto,
|
||||
} from '@aaif/goose-sdk';
|
||||
import { getAcpClient } from './acpConnection';
|
||||
|
||||
export type LocalModelResponse = LocalInferenceModelDto;
|
||||
export type DownloadProgress = LocalInferenceDownloadProgressDto;
|
||||
export type DownloadModelRequest = LocalInferenceModelDownloadRequest_unstable;
|
||||
export type HfModelInfo = LocalInferenceHfModelInfoDto;
|
||||
export type HfModelVariant = LocalInferenceHfModelVariantDto;
|
||||
export type ModelSettings = LocalInferenceModelSettingsDto;
|
||||
export type SamplingConfig = NonNullable<LocalInferenceModelSettingsDto['sampling']>;
|
||||
export type ToolCallingMode = NonNullable<LocalInferenceModelSettingsDto['toolCalling']>;
|
||||
export type ChatTemplate = NonNullable<LocalInferenceModelSettingsDto['chatTemplate']>;
|
||||
|
||||
export type RepoVariantsResponse = {
|
||||
variants: HfModelVariant[];
|
||||
recommendedIndex: number | null;
|
||||
availableMemoryBytes: number;
|
||||
downloadedQuants: string[];
|
||||
downloadedVariants: string[];
|
||||
};
|
||||
|
||||
export async function listLocalModels(): Promise<LocalModelResponse[]> {
|
||||
const client = await getAcpClient();
|
||||
const response = await client.goose.localInferenceModelsList_unstable({});
|
||||
return response.models;
|
||||
}
|
||||
|
||||
export async function downloadHfModel(request: DownloadModelRequest): Promise<string> {
|
||||
const client = await getAcpClient();
|
||||
const response = await client.goose.localInferenceModelsDownload_unstable(request);
|
||||
return response.modelId;
|
||||
}
|
||||
|
||||
export async function getLocalModelDownloadProgress(
|
||||
modelId: string
|
||||
): Promise<DownloadProgress | null> {
|
||||
const client = await getAcpClient();
|
||||
const response = await client.goose.localInferenceModelsDownloadProgress_unstable({ modelId });
|
||||
return response.progress ?? null;
|
||||
}
|
||||
|
||||
export async function cancelLocalModelDownload(modelId: string): Promise<void> {
|
||||
const client = await getAcpClient();
|
||||
await client.goose.localInferenceModelsDownloadCancel_unstable({ modelId });
|
||||
}
|
||||
|
||||
export async function deleteLocalModel(modelId: string): Promise<void> {
|
||||
const client = await getAcpClient();
|
||||
await client.goose.localInferenceModelsDelete_unstable({ modelId });
|
||||
}
|
||||
|
||||
export async function getModelSettings(modelId: string): Promise<ModelSettings> {
|
||||
const client = await getAcpClient();
|
||||
const response = await client.goose.localInferenceModelsSettingsRead_unstable({ modelId });
|
||||
return response.settings;
|
||||
}
|
||||
|
||||
export async function updateModelSettings(
|
||||
modelId: string,
|
||||
settings: ModelSettings
|
||||
): Promise<ModelSettings> {
|
||||
const client = await getAcpClient();
|
||||
const response = await client.goose.localInferenceModelsSettingsUpdate_unstable({
|
||||
modelId,
|
||||
settings,
|
||||
});
|
||||
return response.settings;
|
||||
}
|
||||
|
||||
export async function searchHfModels(query: string, limit?: number): Promise<HfModelInfo[]> {
|
||||
const client = await getAcpClient();
|
||||
const response = await client.goose.localInferenceHuggingfaceSearch_unstable({ query, limit });
|
||||
return response.models;
|
||||
}
|
||||
|
||||
export async function getRepoFiles(repoId: string): Promise<RepoVariantsResponse> {
|
||||
const client = await getAcpClient();
|
||||
const response = await client.goose.localInferenceHuggingfaceRepoVariants_unstable({ repoId });
|
||||
return {
|
||||
variants: response.variants,
|
||||
recommendedIndex: response.recommendedIndex ?? null,
|
||||
availableMemoryBytes: response.availableMemoryBytes,
|
||||
downloadedQuants: response.downloadedQuants,
|
||||
downloadedVariants: response.downloadedVariants,
|
||||
};
|
||||
}
|
||||
|
||||
export async function listBuiltinChatTemplates(): Promise<string[]> {
|
||||
const client = await getAcpClient();
|
||||
const response = await client.goose.localInferenceChatTemplatesBuiltinList_unstable({});
|
||||
return response.templates;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -59,16 +59,6 @@ export type ChatRequest = {
|
||||
user_message: Message;
|
||||
};
|
||||
|
||||
export type ChatTemplate = {
|
||||
type: 'embedded';
|
||||
} | {
|
||||
name: string;
|
||||
type: 'builtin';
|
||||
} | {
|
||||
template: string;
|
||||
type: 'custom_inline';
|
||||
};
|
||||
|
||||
export type CheckProviderRequest = {
|
||||
provider: string;
|
||||
};
|
||||
@@ -316,21 +306,6 @@ export type DictationProviderStatus = {
|
||||
uses_provider_config: boolean;
|
||||
};
|
||||
|
||||
export type DownloadModelRequest = {
|
||||
/**
|
||||
* Optional backend id for callers selecting a concrete variant row.
|
||||
*/
|
||||
backend_id?: string | null;
|
||||
/**
|
||||
* Model spec/download id like "bartowski/Llama-3.2-3B-Instruct-GGUF:Q4_K_M" or "google/gemma-4-31B-it"
|
||||
*/
|
||||
spec: string;
|
||||
/**
|
||||
* Optional backend-specific variant id, such as a GGUF quantization or MLX dtype.
|
||||
*/
|
||||
variant_id?: string | null;
|
||||
};
|
||||
|
||||
export type DownloadProgress = {
|
||||
/**
|
||||
* Bytes downloaded so far
|
||||
@@ -568,55 +543,6 @@ export type GooseApp = McpAppResource & (WindowProps | null) & {
|
||||
|
||||
export type GooseMode = 'auto' | 'approve' | 'smart_approve' | 'chat';
|
||||
|
||||
/**
|
||||
* A single downloadable GGUF file (used internally and for downloads).
|
||||
*/
|
||||
export type HfGgufFile = {
|
||||
download_url: string;
|
||||
filename: string;
|
||||
quantization: string;
|
||||
size_bytes: number;
|
||||
};
|
||||
|
||||
export type HfModelInfo = {
|
||||
author: string;
|
||||
downloads: number;
|
||||
gguf_files: Array<HfGgufFile>;
|
||||
model_name: string;
|
||||
repo_id: string;
|
||||
variants?: Array<HfModelVariant>;
|
||||
};
|
||||
|
||||
export type HfModelVariant = {
|
||||
backend_id: string;
|
||||
description: string;
|
||||
download_id: string;
|
||||
download_url?: string | null;
|
||||
filename?: string | null;
|
||||
format: string;
|
||||
label: string;
|
||||
model_id: string;
|
||||
quality_rank: number;
|
||||
sharded?: boolean;
|
||||
size_bytes: number;
|
||||
supported?: boolean;
|
||||
unsupported_reason?: string | null;
|
||||
variant_id: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* A quantization variant — groups sharded files into one logical entry.
|
||||
*/
|
||||
export type HfQuantVariant = {
|
||||
description: string;
|
||||
download_url: string;
|
||||
filename: string;
|
||||
quality_rank: number;
|
||||
quantization: string;
|
||||
sharded?: boolean;
|
||||
size_bytes: number;
|
||||
};
|
||||
|
||||
export type Icon = {
|
||||
mimeType?: string;
|
||||
sizes?: Array<string>;
|
||||
@@ -672,19 +598,6 @@ export type LoadedProvider = {
|
||||
is_editable: boolean;
|
||||
};
|
||||
|
||||
export type LocalModelResponse = {
|
||||
filename: string;
|
||||
id: string;
|
||||
mmproj_status?: ModelDownloadStatus | null;
|
||||
quantization: string;
|
||||
recommended: boolean;
|
||||
repo_id: string;
|
||||
settings: ModelSettings;
|
||||
size_bytes: number;
|
||||
status: ModelDownloadStatus;
|
||||
vision_capable: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* MCP App Resource
|
||||
* Represents a UI resource that can be rendered in an MCP App
|
||||
@@ -824,18 +737,6 @@ export type ModelConfig = {
|
||||
toolshim_model?: string | null;
|
||||
};
|
||||
|
||||
export type ModelDownloadStatus = {
|
||||
state: 'NotDownloaded';
|
||||
} | {
|
||||
bytes_downloaded: number;
|
||||
progress_percent: number;
|
||||
speed_bps?: number | null;
|
||||
state: 'Downloading';
|
||||
total_bytes: number;
|
||||
} | {
|
||||
state: 'Downloaded';
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about a model's capabilities
|
||||
*/
|
||||
@@ -897,43 +798,6 @@ export type ModelInfoResponse = {
|
||||
source: string;
|
||||
};
|
||||
|
||||
export type ModelSettings = {
|
||||
/**
|
||||
* Backend implementation to use for this model. Defaults to llama.cpp.
|
||||
*/
|
||||
backend_id?: string | null;
|
||||
chat_template?: ChatTemplate;
|
||||
context_size?: number | null;
|
||||
draft_model?: string | null;
|
||||
enable_thinking?: boolean;
|
||||
flash_attention?: boolean | null;
|
||||
frequency_penalty?: number;
|
||||
/**
|
||||
* Estimated tokens per image for budget planning before mtmd tokenization.
|
||||
* The actual count is determined after tokenization via `chunks.total_tokens()`.
|
||||
*/
|
||||
image_token_estimate?: number;
|
||||
max_output_tokens?: number | null;
|
||||
/**
|
||||
* Size of the mmproj file in bytes, used for memory accounting.
|
||||
*/
|
||||
mmproj_size_bytes?: number;
|
||||
n_batch?: number | null;
|
||||
n_gpu_layers?: number | null;
|
||||
n_threads?: number | null;
|
||||
presence_penalty?: number;
|
||||
repeat_last_n?: number;
|
||||
repeat_penalty?: number;
|
||||
sampling?: SamplingConfig;
|
||||
tool_calling?: ToolCallingMode;
|
||||
use_mlock?: boolean;
|
||||
/**
|
||||
* Whether this model architecture supports vision input.
|
||||
* Derived from associated mmproj metadata, not user-configurable.
|
||||
*/
|
||||
vision_capable?: boolean;
|
||||
};
|
||||
|
||||
export type ModelTemplate = {
|
||||
capabilities: ModelCapabilities;
|
||||
context_limit: number;
|
||||
@@ -1200,14 +1064,6 @@ export type RemoveExtensionRequest = {
|
||||
session_id: string;
|
||||
};
|
||||
|
||||
export type RepoVariantsResponse = {
|
||||
available_memory_bytes: number;
|
||||
downloaded_quants: Array<string>;
|
||||
downloaded_variants: Array<string>;
|
||||
recommended_index?: number | null;
|
||||
variants: Array<HfModelVariant>;
|
||||
};
|
||||
|
||||
export type ResourceContents = {
|
||||
_meta?: {
|
||||
[key: string]: unknown;
|
||||
@@ -1285,22 +1141,6 @@ export type RunNowResponse = {
|
||||
session_id: string;
|
||||
};
|
||||
|
||||
export type SamplingConfig = {
|
||||
type: 'Greedy';
|
||||
} | {
|
||||
min_p: number;
|
||||
seed?: number | null;
|
||||
temperature: number;
|
||||
top_k: number;
|
||||
top_p: number;
|
||||
type: 'Temperature';
|
||||
} | {
|
||||
eta: number;
|
||||
seed?: number | null;
|
||||
tau: number;
|
||||
type: 'MirostatV2';
|
||||
};
|
||||
|
||||
export type SavePromptRequest = {
|
||||
content: string;
|
||||
};
|
||||
@@ -1572,8 +1412,6 @@ export type ToolAnnotations = {
|
||||
title?: string;
|
||||
};
|
||||
|
||||
export type ToolCallingMode = 'auto' | 'force_native' | 'force_emulated';
|
||||
|
||||
export type ToolConfirmationRequest = {
|
||||
arguments: JsonObject;
|
||||
id: string;
|
||||
@@ -3054,251 +2892,6 @@ export type TranscribeDictationResponses = {
|
||||
|
||||
export type TranscribeDictationResponse = TranscribeDictationResponses[keyof TranscribeDictationResponses];
|
||||
|
||||
export type ListBuiltinChatTemplatesData = {
|
||||
body?: never;
|
||||
path?: never;
|
||||
query?: never;
|
||||
url: '/local-inference/chat-templates/builtin';
|
||||
};
|
||||
|
||||
export type ListBuiltinChatTemplatesResponses = {
|
||||
/**
|
||||
* llama.cpp built-in chat template names
|
||||
*/
|
||||
200: Array<string>;
|
||||
};
|
||||
|
||||
export type ListBuiltinChatTemplatesResponse = ListBuiltinChatTemplatesResponses[keyof ListBuiltinChatTemplatesResponses];
|
||||
|
||||
export type DownloadHfModelData = {
|
||||
body: DownloadModelRequest;
|
||||
path?: never;
|
||||
query?: never;
|
||||
url: '/local-inference/download';
|
||||
};
|
||||
|
||||
export type DownloadHfModelErrors = {
|
||||
/**
|
||||
* Invalid request
|
||||
*/
|
||||
400: unknown;
|
||||
};
|
||||
|
||||
export type DownloadHfModelResponses = {
|
||||
/**
|
||||
* Download started
|
||||
*/
|
||||
202: string;
|
||||
};
|
||||
|
||||
export type DownloadHfModelResponse = DownloadHfModelResponses[keyof DownloadHfModelResponses];
|
||||
|
||||
export type ListLocalModelsData = {
|
||||
body?: never;
|
||||
path?: never;
|
||||
query?: never;
|
||||
url: '/local-inference/models';
|
||||
};
|
||||
|
||||
export type ListLocalModelsResponses = {
|
||||
/**
|
||||
* List of available local LLM models
|
||||
*/
|
||||
200: Array<LocalModelResponse>;
|
||||
};
|
||||
|
||||
export type ListLocalModelsResponse = ListLocalModelsResponses[keyof ListLocalModelsResponses];
|
||||
|
||||
export type DeleteLocalModelData = {
|
||||
body?: never;
|
||||
path: {
|
||||
model_id: string;
|
||||
};
|
||||
query?: never;
|
||||
url: '/local-inference/models/{model_id}';
|
||||
};
|
||||
|
||||
export type DeleteLocalModelErrors = {
|
||||
/**
|
||||
* Model not found
|
||||
*/
|
||||
404: unknown;
|
||||
};
|
||||
|
||||
export type DeleteLocalModelResponses = {
|
||||
/**
|
||||
* Model deleted
|
||||
*/
|
||||
200: unknown;
|
||||
};
|
||||
|
||||
export type CancelLocalModelDownloadData = {
|
||||
body?: never;
|
||||
path: {
|
||||
model_id: string;
|
||||
};
|
||||
query?: never;
|
||||
url: '/local-inference/models/{model_id}/download';
|
||||
};
|
||||
|
||||
export type CancelLocalModelDownloadErrors = {
|
||||
/**
|
||||
* No active download
|
||||
*/
|
||||
404: unknown;
|
||||
};
|
||||
|
||||
export type CancelLocalModelDownloadResponses = {
|
||||
/**
|
||||
* Download cancelled
|
||||
*/
|
||||
200: unknown;
|
||||
};
|
||||
|
||||
export type GetLocalModelDownloadProgressData = {
|
||||
body?: never;
|
||||
path: {
|
||||
model_id: string;
|
||||
};
|
||||
query?: never;
|
||||
url: '/local-inference/models/{model_id}/download';
|
||||
};
|
||||
|
||||
export type GetLocalModelDownloadProgressErrors = {
|
||||
/**
|
||||
* No active download
|
||||
*/
|
||||
404: unknown;
|
||||
};
|
||||
|
||||
export type GetLocalModelDownloadProgressResponses = {
|
||||
/**
|
||||
* Download progress
|
||||
*/
|
||||
200: DownloadProgress;
|
||||
};
|
||||
|
||||
export type GetLocalModelDownloadProgressResponse = GetLocalModelDownloadProgressResponses[keyof GetLocalModelDownloadProgressResponses];
|
||||
|
||||
export type GetModelSettingsData = {
|
||||
body?: never;
|
||||
path: {
|
||||
model_id: string;
|
||||
};
|
||||
query?: never;
|
||||
url: '/local-inference/models/{model_id}/settings';
|
||||
};
|
||||
|
||||
export type GetModelSettingsErrors = {
|
||||
/**
|
||||
* Model not found
|
||||
*/
|
||||
404: unknown;
|
||||
};
|
||||
|
||||
export type GetModelSettingsResponses = {
|
||||
/**
|
||||
* Model settings
|
||||
*/
|
||||
200: ModelSettings;
|
||||
};
|
||||
|
||||
export type GetModelSettingsResponse = GetModelSettingsResponses[keyof GetModelSettingsResponses];
|
||||
|
||||
export type UpdateModelSettingsData = {
|
||||
body: ModelSettings;
|
||||
path: {
|
||||
model_id: string;
|
||||
};
|
||||
query?: never;
|
||||
url: '/local-inference/models/{model_id}/settings';
|
||||
};
|
||||
|
||||
export type UpdateModelSettingsErrors = {
|
||||
/**
|
||||
* Model not found
|
||||
*/
|
||||
404: unknown;
|
||||
/**
|
||||
* Failed to save settings
|
||||
*/
|
||||
500: unknown;
|
||||
};
|
||||
|
||||
export type UpdateModelSettingsResponses = {
|
||||
/**
|
||||
* Settings updated
|
||||
*/
|
||||
200: ModelSettings;
|
||||
};
|
||||
|
||||
export type UpdateModelSettingsResponse = UpdateModelSettingsResponses[keyof UpdateModelSettingsResponses];
|
||||
|
||||
export type GetRepoFilesData = {
|
||||
body?: never;
|
||||
path: {
|
||||
author: string;
|
||||
repo: string;
|
||||
};
|
||||
query?: never;
|
||||
url: '/local-inference/repo/{author}/{repo}/files';
|
||||
};
|
||||
|
||||
export type GetRepoFilesResponses = {
|
||||
/**
|
||||
* GGUF files in the repo
|
||||
*/
|
||||
200: RepoVariantsResponse;
|
||||
};
|
||||
|
||||
export type GetRepoFilesResponse = GetRepoFilesResponses[keyof GetRepoFilesResponses];
|
||||
|
||||
export type SearchHfModelsData = {
|
||||
body?: never;
|
||||
path?: never;
|
||||
query: {
|
||||
/**
|
||||
* Search query
|
||||
*/
|
||||
q: string;
|
||||
/**
|
||||
* Max results
|
||||
*/
|
||||
limit?: number | null;
|
||||
};
|
||||
url: '/local-inference/search';
|
||||
};
|
||||
|
||||
export type SearchHfModelsErrors = {
|
||||
/**
|
||||
* Search failed
|
||||
*/
|
||||
500: unknown;
|
||||
};
|
||||
|
||||
export type SearchHfModelsResponses = {
|
||||
/**
|
||||
* Search results
|
||||
*/
|
||||
200: Array<HfModelInfo>;
|
||||
};
|
||||
|
||||
export type SearchHfModelsResponse = SearchHfModelsResponses[keyof SearchHfModelsResponses];
|
||||
|
||||
export type SyncFeaturedModelsData = {
|
||||
body?: never;
|
||||
path?: never;
|
||||
query?: never;
|
||||
url: '/local-inference/sync-featured';
|
||||
};
|
||||
|
||||
export type SyncFeaturedModelsResponses = {
|
||||
/**
|
||||
* Featured models synced to registry
|
||||
*/
|
||||
200: unknown;
|
||||
};
|
||||
|
||||
export type DecodeRecipeData = {
|
||||
body: DecodeRecipeRequest;
|
||||
path?: never;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import {
|
||||
listLocalModels,
|
||||
syncFeaturedModels,
|
||||
downloadHfModel,
|
||||
getLocalModelDownloadProgress,
|
||||
cancelLocalModelDownload,
|
||||
type DownloadProgress,
|
||||
type LocalModelResponse,
|
||||
} from '../../api';
|
||||
} from '../../acp/local-inference';
|
||||
import { trackOnboardingSetupFailed } from '../../utils/analytics';
|
||||
import { defineMessages, useIntl } from '../../i18n';
|
||||
|
||||
@@ -124,16 +123,15 @@ export default function LocalModelPicker({ onConfigured }: LocalModelPickerProps
|
||||
useEffect(() => {
|
||||
const load = async () => {
|
||||
try {
|
||||
await syncFeaturedModels();
|
||||
const response = await listLocalModels({ throwOnError: true });
|
||||
if (response.data) {
|
||||
setModels(response.data);
|
||||
const models = await listLocalModels();
|
||||
if (models) {
|
||||
setModels(models);
|
||||
|
||||
const alreadyDownloaded = response.data.find((m) => m.status.state === 'Downloaded');
|
||||
const alreadyDownloaded = models.find((m) => m.status.state === 'Downloaded');
|
||||
if (alreadyDownloaded) {
|
||||
setSelectedModelId(alreadyDownloaded.id);
|
||||
} else {
|
||||
const recommended = response.data.find((m: LocalModelResponse) => m.recommended);
|
||||
const recommended = models.find((m: LocalModelResponse) => m.recommended);
|
||||
if (recommended) setSelectedModelId(recommended.id);
|
||||
}
|
||||
}
|
||||
@@ -165,7 +163,7 @@ export default function LocalModelPicker({ onConfigured }: LocalModelPickerProps
|
||||
}
|
||||
|
||||
try {
|
||||
await downloadHfModel({ body: { spec: model.id }, throwOnError: true });
|
||||
await downloadHfModel({ spec: model.id });
|
||||
} catch (error) {
|
||||
console.error('Failed to start download:', error);
|
||||
setErrorMessage(intl.formatMessage(i18n.failedToStartDownload));
|
||||
@@ -176,24 +174,27 @@ export default function LocalModelPicker({ onConfigured }: LocalModelPickerProps
|
||||
|
||||
pollRef.current = setInterval(async () => {
|
||||
try {
|
||||
const response = await getLocalModelDownloadProgress({
|
||||
path: { model_id: modelId },
|
||||
throwOnError: true,
|
||||
});
|
||||
if (response.data) {
|
||||
setDownloadProgress(response.data);
|
||||
if (response.data.status === 'completed') {
|
||||
cleanup();
|
||||
finishSetup(modelId);
|
||||
} else if (response.data.status === 'failed') {
|
||||
cleanup();
|
||||
setErrorMessage(response.data.error || 'Download failed.');
|
||||
trackOnboardingSetupFailed(LOCAL_PROVIDER, response.data.error || 'download_failed');
|
||||
setPhase('error');
|
||||
} else if (response.data.status === 'cancelled') {
|
||||
cleanup();
|
||||
setPhase('select');
|
||||
}
|
||||
const progress = await getLocalModelDownloadProgress(modelId);
|
||||
if (!progress) {
|
||||
cleanup();
|
||||
setErrorMessage(intl.formatMessage(i18n.lostConnection));
|
||||
trackOnboardingSetupFailed(LOCAL_PROVIDER, 'progress_missing');
|
||||
setPhase('error');
|
||||
return;
|
||||
}
|
||||
|
||||
setDownloadProgress(progress);
|
||||
if (progress.status === 'completed') {
|
||||
cleanup();
|
||||
finishSetup(modelId);
|
||||
} else if (progress.status === 'failed') {
|
||||
cleanup();
|
||||
setErrorMessage(progress.error || 'Download failed.');
|
||||
trackOnboardingSetupFailed(LOCAL_PROVIDER, progress.error || 'download_failed');
|
||||
setPhase('error');
|
||||
} else if (progress.status === 'cancelled') {
|
||||
cleanup();
|
||||
setPhase('select');
|
||||
}
|
||||
} catch {
|
||||
cleanup();
|
||||
@@ -208,7 +209,7 @@ export default function LocalModelPicker({ onConfigured }: LocalModelPickerProps
|
||||
if (phase === 'downloading' && selectedModelId) {
|
||||
cleanup();
|
||||
try {
|
||||
await cancelLocalModelDownload({ path: { model_id: selectedModelId } });
|
||||
await cancelLocalModelDownload(selectedModelId);
|
||||
} catch {
|
||||
// best-effort
|
||||
}
|
||||
@@ -296,7 +297,7 @@ export default function LocalModelPicker({ onConfigured }: LocalModelPickerProps
|
||||
)}
|
||||
</div>
|
||||
<p className="text-text-muted text-xs mt-1">
|
||||
{formatSize(recommended.size_bytes)}
|
||||
{formatSize(recommended.sizeBytes)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -350,7 +351,7 @@ export default function LocalModelPicker({ onConfigured }: LocalModelPickerProps
|
||||
{model.id}
|
||||
</span>
|
||||
<span className="text-xs text-text-muted">
|
||||
{formatSize(model.size_bytes)}
|
||||
{formatSize(model.sizeBytes)}
|
||||
</span>
|
||||
{model.status.state === 'Downloaded' && (
|
||||
<span className="text-xs bg-green-600 text-white px-2 py-0.5 rounded-full">
|
||||
@@ -375,7 +376,7 @@ export default function LocalModelPicker({ onConfigured }: LocalModelPickerProps
|
||||
{selectedModel?.status.state === 'Downloaded'
|
||||
? intl.formatMessage(i18n.useModel, { modelId: selectedModel.id })
|
||||
: selectedModel
|
||||
? intl.formatMessage(i18n.downloadModel, { modelId: selectedModel.id, size: formatSize(selectedModel.size_bytes) })
|
||||
? intl.formatMessage(i18n.downloadModel, { modelId: selectedModel.id, size: formatSize(selectedModel.sizeBytes) })
|
||||
: intl.formatMessage(i18n.selectModel)}
|
||||
</button>
|
||||
|
||||
@@ -394,30 +395,30 @@ export default function LocalModelPicker({ onConfigured }: LocalModelPickerProps
|
||||
<div className="w-full bg-background-subtle rounded-full h-2 overflow-hidden">
|
||||
<div
|
||||
className="bg-blue-500 h-2 rounded-full transition-all duration-500 ease-out"
|
||||
style={{ width: `${downloadProgress.progress_percent}%` }}
|
||||
style={{ width: `${downloadProgress.progressPercent}%` }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between text-xs text-text-muted">
|
||||
<span>
|
||||
{formatBytes(downloadProgress.bytes_downloaded)} of{' '}
|
||||
{formatBytes(downloadProgress.total_bytes)}
|
||||
{formatBytes(downloadProgress.bytesDownloaded)} of{' '}
|
||||
{formatBytes(downloadProgress.totalBytes)}
|
||||
</span>
|
||||
<span>{downloadProgress.progress_percent.toFixed(0)}%</span>
|
||||
<span>{downloadProgress.progressPercent.toFixed(0)}%</span>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between text-xs text-text-muted">
|
||||
{downloadProgress.speed_bps ? (
|
||||
<span>{formatBytes(downloadProgress.speed_bps)}/s</span>
|
||||
{downloadProgress.speedBps ? (
|
||||
<span>{formatBytes(downloadProgress.speedBps)}/s</span>
|
||||
) : (
|
||||
<span />
|
||||
)}
|
||||
{downloadProgress.eta_seconds != null && downloadProgress.eta_seconds > 0 && (
|
||||
{downloadProgress.etaSeconds != null && downloadProgress.etaSeconds > 0 && (
|
||||
<span>
|
||||
~
|
||||
{downloadProgress.eta_seconds < 60
|
||||
? `${Math.round(downloadProgress.eta_seconds)}s`
|
||||
: `${Math.round(downloadProgress.eta_seconds / 60)}m`}{' '}
|
||||
{downloadProgress.etaSeconds < 60
|
||||
? `${Math.round(downloadProgress.etaSeconds)}s`
|
||||
: `${Math.round(downloadProgress.etaSeconds / 60)}m`}{' '}
|
||||
remaining
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -17,7 +17,8 @@ import {
|
||||
type DownloadModelRequest,
|
||||
type HfModelInfo,
|
||||
type HfModelVariant,
|
||||
} from '../../../api';
|
||||
type RepoVariantsResponse,
|
||||
} from '../../../acp/local-inference';
|
||||
import { defineMessages, useIntl } from '../../../i18n';
|
||||
|
||||
const i18n = defineMessages({
|
||||
@@ -127,61 +128,43 @@ export const HuggingFaceModelSearch = ({
|
||||
setSearching(true);
|
||||
setError(null);
|
||||
try {
|
||||
const response = await searchHfModels({
|
||||
query: { q, limit: 20 },
|
||||
});
|
||||
if (response.data) {
|
||||
// Pre-fetch variants for all results and filter out repos with no compatible local variants
|
||||
const modelsWithVariants = await Promise.all(
|
||||
response.data.map(async (model) => {
|
||||
try {
|
||||
const [author, repo] = model.repo_id.split('/');
|
||||
const filesResponse = await getRepoFiles({ path: { author, repo } });
|
||||
if (filesResponse.data && filesResponse.data.variants.length > 0) {
|
||||
return { model, data: filesResponse.data };
|
||||
}
|
||||
} catch {
|
||||
// Skip repos we can't fetch
|
||||
const models = await searchHfModels(q, 20);
|
||||
const modelsWithVariants = await Promise.all(
|
||||
models.map(async (model) => {
|
||||
try {
|
||||
const repoData = await getRepoFiles(model.repoId);
|
||||
if (repoData.variants.length > 0) {
|
||||
return { model, data: repoData };
|
||||
}
|
||||
return null;
|
||||
})
|
||||
);
|
||||
|
||||
const validResults = modelsWithVariants.filter(Boolean) as {
|
||||
model: HfModelInfo;
|
||||
data: {
|
||||
variants: HfModelVariant[];
|
||||
recommended_index?: number | null;
|
||||
available_memory_bytes: number;
|
||||
downloaded_quants: string[];
|
||||
downloaded_variants: string[];
|
||||
};
|
||||
}[];
|
||||
|
||||
setResults(validResults.map((r) => r.model));
|
||||
setRepoData((prev) => {
|
||||
const next = { ...prev };
|
||||
for (const r of validResults) {
|
||||
next[r.model.repo_id] = {
|
||||
variants: r.data.variants,
|
||||
recommendedIndex: r.data.recommended_index ?? null,
|
||||
availableMemoryBytes: r.data.available_memory_bytes,
|
||||
downloadedQuants: new Set(r.data.downloaded_quants),
|
||||
downloadedVariants: new Set(r.data.downloaded_variants),
|
||||
};
|
||||
} catch {
|
||||
// Skip repos we can't fetch
|
||||
}
|
||||
return next;
|
||||
});
|
||||
return null;
|
||||
})
|
||||
);
|
||||
|
||||
if (validResults.length === 0) {
|
||||
setError(intl.formatMessage(i18n.noGgufModels));
|
||||
const validResults = modelsWithVariants.filter(Boolean) as {
|
||||
model: HfModelInfo;
|
||||
data: RepoVariantsResponse;
|
||||
}[];
|
||||
|
||||
setResults(validResults.map((r) => r.model));
|
||||
setRepoData((prev) => {
|
||||
const next = { ...prev };
|
||||
for (const r of validResults) {
|
||||
next[r.model.repoId] = {
|
||||
variants: r.data.variants,
|
||||
recommendedIndex: r.data.recommendedIndex ?? null,
|
||||
availableMemoryBytes: r.data.availableMemoryBytes,
|
||||
downloadedQuants: new Set(r.data.downloadedQuants),
|
||||
downloadedVariants: new Set(r.data.downloadedVariants),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
console.error('Search response:', response);
|
||||
const errMsg = response.error
|
||||
? intl.formatMessage(i18n.searchError, { details: JSON.stringify(response.error) })
|
||||
: intl.formatMessage(i18n.searchNoData);
|
||||
setError(errMsg);
|
||||
return next;
|
||||
});
|
||||
|
||||
if (validResults.length === 0) {
|
||||
setError(intl.formatMessage(i18n.noGgufModels));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Search failed:', e);
|
||||
@@ -209,22 +192,17 @@ export const HuggingFaceModelSearch = ({
|
||||
if (!repoData[repoId]?.variants.length) {
|
||||
setLoadingFiles((prev) => new Set(prev).add(repoId));
|
||||
try {
|
||||
const [author, repo] = repoId.split('/');
|
||||
const response = await getRepoFiles({
|
||||
path: { author, repo },
|
||||
});
|
||||
if (response.data) {
|
||||
setRepoData((prev) => ({
|
||||
...prev,
|
||||
[repoId]: {
|
||||
variants: response.data!.variants,
|
||||
recommendedIndex: response.data!.recommended_index ?? null,
|
||||
availableMemoryBytes: response.data!.available_memory_bytes,
|
||||
downloadedQuants: new Set(response.data!.downloaded_quants),
|
||||
downloadedVariants: new Set(response.data!.downloaded_variants),
|
||||
},
|
||||
}));
|
||||
}
|
||||
const response = await getRepoFiles(repoId);
|
||||
setRepoData((prev) => ({
|
||||
...prev,
|
||||
[repoId]: {
|
||||
variants: response.variants,
|
||||
recommendedIndex: response.recommendedIndex ?? null,
|
||||
availableMemoryBytes: response.availableMemoryBytes,
|
||||
downloadedQuants: new Set(response.downloadedQuants),
|
||||
downloadedVariants: new Set(response.downloadedVariants),
|
||||
},
|
||||
}));
|
||||
} catch (e) {
|
||||
console.error('Failed to fetch repo files:', e);
|
||||
} finally {
|
||||
@@ -238,20 +216,16 @@ export const HuggingFaceModelSearch = ({
|
||||
};
|
||||
|
||||
const startDownload = async (repoId: string, variant: HfModelVariant) => {
|
||||
const downloadKey = variant.download_id;
|
||||
const downloadKey = variant.downloadId;
|
||||
const request: DownloadModelRequest = {
|
||||
spec: repoId,
|
||||
backend_id: variant.backend_id,
|
||||
variant_id: variant.variant_id,
|
||||
backendId: variant.backendId,
|
||||
variantId: variant.variantId,
|
||||
};
|
||||
setDownloading((prev) => new Set(prev).add(downloadKey));
|
||||
try {
|
||||
const response = await downloadHfModel({
|
||||
body: request,
|
||||
});
|
||||
if (response.data) {
|
||||
onDownloadStarted(response.data, request);
|
||||
}
|
||||
const modelId = await downloadHfModel(request);
|
||||
onDownloadStarted(modelId, request);
|
||||
} catch (e) {
|
||||
console.error('Download failed:', e);
|
||||
} finally {
|
||||
@@ -289,8 +263,8 @@ export const HuggingFaceModelSearch = ({
|
||||
{results.length > 0 && (
|
||||
<div className="space-y-1">
|
||||
{results.map((model) => {
|
||||
const isExpanded = expandedRepo === model.repo_id;
|
||||
const data = repoData[model.repo_id];
|
||||
const isExpanded = expandedRepo === model.repoId;
|
||||
const data = repoData[model.repoId];
|
||||
const variants = data?.variants || [];
|
||||
const recommendedIndex = data?.recommendedIndex ?? null;
|
||||
const availableMemory = data?.availableMemoryBytes ?? 0;
|
||||
@@ -298,15 +272,15 @@ export const HuggingFaceModelSearch = ({
|
||||
const downloadedVariants = data?.downloadedVariants ?? new Set<string>();
|
||||
|
||||
return (
|
||||
<div key={model.repo_id} className="border border-border-subtle rounded-lg">
|
||||
<div key={model.repoId} className="border border-border-subtle rounded-lg">
|
||||
<button
|
||||
onClick={() => toggleRepo(model.repo_id)}
|
||||
onClick={() => toggleRepo(model.repoId)}
|
||||
className="w-full flex items-center justify-between p-3 text-left hover:bg-background-subtle rounded-lg"
|
||||
>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium text-text-default truncate">
|
||||
{model.repo_id}
|
||||
{model.repoId}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-3 mt-0.5">
|
||||
@@ -324,28 +298,28 @@ export const HuggingFaceModelSearch = ({
|
||||
|
||||
{isExpanded && (
|
||||
<div className="border-t border-border-subtle px-3 pb-3 space-y-1">
|
||||
{loadingFiles.has(model.repo_id) && (
|
||||
{loadingFiles.has(model.repoId) && (
|
||||
<div className="flex items-center gap-2 py-2 text-xs text-text-muted">
|
||||
<Loader2 className="w-3 h-3 animate-spin" />
|
||||
{intl.formatMessage(i18n.loadingVariants)}
|
||||
</div>
|
||||
)}
|
||||
{variants.map((variant, idx) => {
|
||||
const isStarting = downloading.has(variant.download_id);
|
||||
const isStarting = downloading.has(variant.downloadId);
|
||||
const isRecommended = idx === recommendedIndex;
|
||||
const modelId = variant.model_id;
|
||||
const modelId = variant.modelId;
|
||||
const isActiveDownload = activeDownloadIds?.has(modelId) ?? false;
|
||||
const isDownloaded = downloadedModelIds
|
||||
? downloadedModelIds.has(modelId)
|
||||
: downloadedVariants.has(modelId) ||
|
||||
downloadedQuants.has(variant.variant_id);
|
||||
downloadedQuants.has(variant.variantId);
|
||||
const tooLarge =
|
||||
availableMemory > 0 && variant.size_bytes > availableMemory * 0.85;
|
||||
availableMemory > 0 && variant.sizeBytes > availableMemory * 0.85;
|
||||
const isSupported = variant.supported ?? true;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={variant.download_id}
|
||||
key={variant.downloadId}
|
||||
className={`flex items-center justify-between py-2 px-2 rounded ${
|
||||
isDownloaded
|
||||
? 'bg-green-500/5 border border-green-500/20'
|
||||
@@ -363,7 +337,7 @@ export const HuggingFaceModelSearch = ({
|
||||
{variant.label}
|
||||
</span>
|
||||
<span className="text-xs text-text-muted">
|
||||
{formatBytes(variant.size_bytes)}
|
||||
{formatBytes(variant.sizeBytes)}
|
||||
</span>
|
||||
{isRecommended && !isDownloaded && (
|
||||
<span className="inline-flex items-center gap-1 text-xs bg-blue-500 text-white px-1.5 py-0.5 rounded">
|
||||
@@ -375,17 +349,17 @@ export const HuggingFaceModelSearch = ({
|
||||
{variant.description && (
|
||||
<span className="text-xs text-text-muted">{variant.description}</span>
|
||||
)}
|
||||
{!isSupported && variant.unsupported_reason && (
|
||||
{!isSupported && variant.unsupportedReason && (
|
||||
<span className="inline-flex items-center gap-1 text-xs text-amber-500">
|
||||
<AlertTriangle className="w-3 h-3" />
|
||||
{variant.unsupported_reason}
|
||||
{variant.unsupportedReason}
|
||||
</span>
|
||||
)}
|
||||
{tooLarge && !isDownloaded && (
|
||||
<span className="inline-flex items-center gap-1 text-xs text-amber-500">
|
||||
<AlertTriangle className="w-3 h-3" />
|
||||
{intl.formatMessage(i18n.tooLarge, {
|
||||
size: formatBytes(variant.size_bytes),
|
||||
size: formatBytes(variant.sizeBytes),
|
||||
available: formatBytes(availableMemory),
|
||||
})}
|
||||
</span>
|
||||
@@ -406,7 +380,7 @@ export const HuggingFaceModelSearch = ({
|
||||
variant="outline"
|
||||
size="sm"
|
||||
disabled={isStarting || !isSupported}
|
||||
onClick={() => startDownload(model.repo_id, variant)}
|
||||
onClick={() => startDownload(model.repoId, variant)}
|
||||
>
|
||||
{isStarting ? (
|
||||
<Loader2 className="w-3 h-3 animate-spin" />
|
||||
|
||||
@@ -14,7 +14,6 @@ import { useModelAndProvider } from '../../ModelAndProviderContext';
|
||||
import { defineMessages, useIntl } from '../../../i18n';
|
||||
import {
|
||||
listLocalModels,
|
||||
syncFeaturedModels,
|
||||
downloadHfModel,
|
||||
getLocalModelDownloadProgress,
|
||||
cancelLocalModelDownload,
|
||||
@@ -22,7 +21,7 @@ import {
|
||||
type DownloadProgress,
|
||||
type DownloadModelRequest,
|
||||
type LocalModelResponse,
|
||||
} from '../../../api';
|
||||
} from '../../../acp/local-inference';
|
||||
import { HuggingFaceModelSearch } from './HuggingFaceModelSearch';
|
||||
import { ModelSettingsPanel } from './ModelSettingsPanel';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/dialog';
|
||||
@@ -133,9 +132,9 @@ const VisionBadge = ({
|
||||
model: LocalModelResponse;
|
||||
intl: ReturnType<typeof useIntl>;
|
||||
}) => {
|
||||
if (!model.vision_capable) return null;
|
||||
if (!model.visionCapable) return null;
|
||||
|
||||
const mmproj = model.mmproj_status;
|
||||
const mmproj = model.mmprojStatus;
|
||||
const isDownloaded = mmproj?.state === 'Downloaded';
|
||||
const isDownloading = mmproj?.state === 'Downloading';
|
||||
|
||||
@@ -150,7 +149,7 @@ const VisionBadge = ({
|
||||
|
||||
if (isDownloading) {
|
||||
const percent =
|
||||
mmproj && 'progress_percent' in mmproj ? Math.round(mmproj.progress_percent) : null;
|
||||
mmproj && mmproj.progressPercent != null ? Math.round(mmproj.progressPercent) : null;
|
||||
return (
|
||||
<span className="inline-flex items-center gap-1 text-xs text-yellow-400 bg-yellow-500/10 px-2 py-0.5 rounded">
|
||||
<Eye className="w-3 h-3" />
|
||||
@@ -191,12 +190,11 @@ export const LocalInferenceSettings = () => {
|
||||
|
||||
const loadModels = useCallback(async (): Promise<LocalModelResponse[] | undefined> => {
|
||||
try {
|
||||
await syncFeaturedModels();
|
||||
const response = await listLocalModels();
|
||||
if (response.data) {
|
||||
setModels(response.data);
|
||||
const models = await listLocalModels();
|
||||
if (models) {
|
||||
setModels(models);
|
||||
const downloadedIds = new Set(
|
||||
response.data
|
||||
models
|
||||
.filter((model) => model.status.state === 'Downloaded')
|
||||
.map((model) => model.id)
|
||||
);
|
||||
@@ -212,13 +210,13 @@ export const LocalInferenceSettings = () => {
|
||||
return next;
|
||||
});
|
||||
}
|
||||
response.data.forEach((model) => {
|
||||
models.forEach((model) => {
|
||||
if (model.status.state === 'Downloading') {
|
||||
pollDownloadProgress(model.id);
|
||||
}
|
||||
});
|
||||
|
||||
return response.data;
|
||||
return models;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load models:', error);
|
||||
@@ -235,7 +233,7 @@ export const LocalInferenceSettings = () => {
|
||||
// Poll model list while any vision encoder is downloading
|
||||
useEffect(() => {
|
||||
const hasDownloadingMmproj = models.some(
|
||||
(m) => m.vision_capable && m.mmproj_status?.state === 'Downloading'
|
||||
(m) => m.visionCapable && m.mmprojStatus?.state === 'Downloading'
|
||||
);
|
||||
if (!hasDownloadingMmproj) return;
|
||||
|
||||
@@ -259,7 +257,7 @@ export const LocalInferenceSettings = () => {
|
||||
if (!model) return;
|
||||
const request = { spec: model.id };
|
||||
try {
|
||||
await downloadHfModel({ body: request });
|
||||
await downloadHfModel(request);
|
||||
setDownloadRequests((prev) => new Map(prev).set(modelId, request));
|
||||
pollDownloadProgress(modelId);
|
||||
scrollToDownloads();
|
||||
@@ -285,9 +283,8 @@ export const LocalInferenceSettings = () => {
|
||||
|
||||
const interval = setInterval(async () => {
|
||||
try {
|
||||
const response = await getLocalModelDownloadProgress({ path: { model_id: modelId } });
|
||||
if (response.data) {
|
||||
const progress = response.data;
|
||||
const progress = await getLocalModelDownloadProgress(modelId);
|
||||
if (progress) {
|
||||
setDownloads((prev) => new Map(prev).set(modelId, progress));
|
||||
|
||||
if (progress.status === 'completed') {
|
||||
@@ -314,7 +311,7 @@ export const LocalInferenceSettings = () => {
|
||||
|
||||
const cancelDownload = async (modelId: string) => {
|
||||
try {
|
||||
await cancelLocalModelDownload({ path: { model_id: modelId } });
|
||||
await cancelLocalModelDownload(modelId);
|
||||
setDownloads((prev) => {
|
||||
const next = new Map(prev);
|
||||
const progress = next.get(modelId);
|
||||
@@ -346,8 +343,7 @@ export const LocalInferenceSettings = () => {
|
||||
const request = downloadRequests.get(modelId) ?? { spec: modelId };
|
||||
dismissDownload(modelId);
|
||||
try {
|
||||
const response = await downloadHfModel({ body: request });
|
||||
const nextModelId = response.data ?? modelId;
|
||||
const nextModelId = await downloadHfModel(request);
|
||||
setDownloadRequests((prev) => new Map(prev).set(nextModelId, request));
|
||||
pollDownloadProgress(nextModelId);
|
||||
scrollToDownloads();
|
||||
@@ -359,7 +355,7 @@ export const LocalInferenceSettings = () => {
|
||||
const handleDeleteModel = async (modelId: string) => {
|
||||
if (!window.confirm(intl.formatMessage(i18n.deleteConfirm))) return;
|
||||
try {
|
||||
await deleteLocalModel({ path: { model_id: modelId } });
|
||||
await deleteLocalModel(modelId);
|
||||
const updatedModels = await loadModels();
|
||||
|
||||
if (selectedModelId === modelId && updatedModels) {
|
||||
@@ -442,30 +438,30 @@ export const LocalInferenceSettings = () => {
|
||||
<div className="w-full bg-gray-700 rounded-full h-2">
|
||||
<div
|
||||
className="bg-blue-500 h-2 rounded-full transition-all duration-300"
|
||||
style={{ width: `${progress.progress_percent}%` }}
|
||||
style={{ width: `${progress.progressPercent}%` }}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex justify-between text-xs text-text-muted">
|
||||
<span>
|
||||
{intl.formatMessage(i18n.downloadProgress, {
|
||||
downloaded: formatBytes(progress.bytes_downloaded),
|
||||
total: formatBytes(progress.total_bytes),
|
||||
percent: progress.progress_percent.toFixed(0),
|
||||
downloaded: formatBytes(progress.bytesDownloaded),
|
||||
total: formatBytes(progress.totalBytes),
|
||||
percent: progress.progressPercent.toFixed(0),
|
||||
})}
|
||||
</span>
|
||||
<span className="flex gap-2">
|
||||
{progress.eta_seconds != null && progress.eta_seconds > 0 && (
|
||||
{progress.etaSeconds != null && progress.etaSeconds > 0 && (
|
||||
<span>
|
||||
{intl.formatMessage(i18n.remaining, {
|
||||
time:
|
||||
progress.eta_seconds < 60
|
||||
? `${Math.round(progress.eta_seconds)}s`
|
||||
: `${Math.round(progress.eta_seconds / 60)}m`,
|
||||
progress.etaSeconds < 60
|
||||
? `${Math.round(progress.etaSeconds)}s`
|
||||
: `${Math.round(progress.etaSeconds / 60)}m`,
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
{progress.speed_bps != null && progress.speed_bps > 0 && (
|
||||
<span>{formatBytes(progress.speed_bps)}/s</span>
|
||||
{progress.speedBps != null && progress.speedBps > 0 && (
|
||||
<span>{formatBytes(progress.speedBps)}/s</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -540,7 +536,7 @@ export const LocalInferenceSettings = () => {
|
||||
/>
|
||||
<span className="text-sm font-medium text-text-default">{model.id}</span>
|
||||
<span className="text-xs text-text-muted">
|
||||
{formatBytes(model.size_bytes)}
|
||||
{formatBytes(model.sizeBytes)}
|
||||
</span>
|
||||
{model.recommended && (
|
||||
<span className="text-xs bg-blue-500 text-white px-2 py-0.5 rounded">
|
||||
@@ -592,7 +588,7 @@ export const LocalInferenceSettings = () => {
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<h4 className="text-sm font-medium text-text-default">{model.id}</h4>
|
||||
<span className="text-xs text-text-muted">
|
||||
{formatBytes(model.size_bytes)}
|
||||
{formatBytes(model.sizeBytes)}
|
||||
</span>
|
||||
{model.recommended && (
|
||||
<span className="text-xs bg-blue-500 text-white px-2 py-0.5 rounded">
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
type ModelSettings,
|
||||
type SamplingConfig,
|
||||
type ToolCallingMode,
|
||||
} from '../../../api';
|
||||
} from '../../../acp/local-inference';
|
||||
import { defineMessages, useIntl } from '../../../i18n';
|
||||
|
||||
const i18n = defineMessages({
|
||||
@@ -221,27 +221,33 @@ const i18n = defineMessages({
|
||||
});
|
||||
|
||||
const DEFAULT_SETTINGS: ModelSettings = {
|
||||
context_size: null,
|
||||
max_output_tokens: null,
|
||||
backendId: null,
|
||||
contextSize: null,
|
||||
maxOutputTokens: null,
|
||||
draftModel: null,
|
||||
sampling: {
|
||||
type: 'Temperature',
|
||||
temperature: 0.8,
|
||||
top_k: 40,
|
||||
top_p: 0.95,
|
||||
min_p: 0.05,
|
||||
topK: 40,
|
||||
topP: 0.95,
|
||||
minP: 0.05,
|
||||
seed: null,
|
||||
},
|
||||
repeat_penalty: 1.0,
|
||||
repeat_last_n: 64,
|
||||
frequency_penalty: 0.0,
|
||||
presence_penalty: 0.0,
|
||||
n_batch: null,
|
||||
n_gpu_layers: null,
|
||||
use_mlock: false,
|
||||
flash_attention: null,
|
||||
n_threads: null,
|
||||
tool_calling: 'auto',
|
||||
chat_template: { type: 'embedded' },
|
||||
repeatPenalty: 1.0,
|
||||
repeatLastN: 64,
|
||||
frequencyPenalty: 0.0,
|
||||
presencePenalty: 0.0,
|
||||
nBatch: null,
|
||||
nGpuLayers: null,
|
||||
useMlock: false,
|
||||
flashAttention: null,
|
||||
nThreads: null,
|
||||
toolCalling: 'auto',
|
||||
chatTemplate: { type: 'embedded' },
|
||||
enableThinking: true,
|
||||
visionCapable: false,
|
||||
imageTokenEstimate: 256,
|
||||
mmprojSizeBytes: 0,
|
||||
};
|
||||
|
||||
type SamplingType = SamplingConfig['type'];
|
||||
@@ -390,17 +396,17 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
const load = useCallback(async () => {
|
||||
try {
|
||||
const [settingsResult, builtinsResult] = await Promise.allSettled([
|
||||
getModelSettings({ path: { model_id: modelId } }),
|
||||
getModelSettings(modelId),
|
||||
listBuiltinChatTemplates(),
|
||||
]);
|
||||
if (builtinsResult.status === 'fulfilled' && builtinsResult.value.data?.length) {
|
||||
setBuiltinTemplateOptions(builtinsResult.value.data);
|
||||
if (builtinsResult.status === 'fulfilled' && builtinsResult.value.length) {
|
||||
setBuiltinTemplateOptions(builtinsResult.value);
|
||||
}
|
||||
if (settingsResult.status === 'fulfilled' && settingsResult.value.data) {
|
||||
if (settingsResult.status === 'fulfilled') {
|
||||
setSettings({
|
||||
...settingsResult.value.data,
|
||||
tool_calling: settingsResult.value.data.tool_calling ?? 'auto',
|
||||
chat_template: settingsResult.value.data.chat_template ?? { type: 'embedded' },
|
||||
...settingsResult.value,
|
||||
toolCalling: settingsResult.value.toolCalling ?? 'auto',
|
||||
chatTemplate: settingsResult.value.chatTemplate ?? { type: 'embedded' },
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
@@ -415,7 +421,7 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
}, [load]);
|
||||
|
||||
useEffect(() => {
|
||||
const chatTemplate = settings.chat_template;
|
||||
const chatTemplate = settings.chatTemplate;
|
||||
if (chatTemplate?.type === 'custom_inline') {
|
||||
setChatTemplateDraft(chatTemplate.template ?? '');
|
||||
} else {
|
||||
@@ -424,13 +430,13 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
if (chatTemplate?.type === 'builtin') {
|
||||
setBuiltinTemplateDraft(chatTemplate.name ?? 'chatml');
|
||||
}
|
||||
}, [settings.chat_template]);
|
||||
}, [settings.chatTemplate]);
|
||||
|
||||
const save = async (updated: ModelSettings) => {
|
||||
setSettings(updated);
|
||||
setSaving(true);
|
||||
try {
|
||||
await updateModelSettings({ path: { model_id: modelId }, body: updated });
|
||||
await updateModelSettings(modelId, updated);
|
||||
} catch (e) {
|
||||
console.error('Failed to save settings:', e);
|
||||
} finally {
|
||||
@@ -445,7 +451,7 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
};
|
||||
|
||||
const samplingType: SamplingType = settings.sampling?.type ?? 'Temperature';
|
||||
const chatTemplate = settings.chat_template ?? { type: 'embedded' };
|
||||
const chatTemplate = settings.chatTemplate ?? { type: 'embedded' };
|
||||
const chatTemplateMode: ChatTemplateMode =
|
||||
chatTemplate.type === 'custom_inline'
|
||||
? 'custom_inline'
|
||||
@@ -458,23 +464,26 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
if (mode === 'custom_inline') {
|
||||
next = { type: 'custom_inline', template: chatTemplateDraft };
|
||||
} else if (mode === 'builtin') {
|
||||
next = { type: 'builtin', name: builtinTemplateDraft.trim() || builtinTemplateOptions[0] || 'chatml' };
|
||||
next = {
|
||||
type: 'builtin',
|
||||
name: builtinTemplateDraft.trim() || builtinTemplateOptions[0] || 'chatml',
|
||||
};
|
||||
} else {
|
||||
next = { type: 'embedded' };
|
||||
}
|
||||
updateField('chat_template', next);
|
||||
updateField('chatTemplate', next);
|
||||
};
|
||||
|
||||
const setBuiltinTemplateName = (name: string) => {
|
||||
setBuiltinTemplateDraft(name);
|
||||
if (chatTemplateMode === 'builtin') {
|
||||
updateField('chat_template', { type: 'builtin', name });
|
||||
updateField('chatTemplate', { type: 'builtin', name });
|
||||
}
|
||||
};
|
||||
|
||||
const saveChatTemplateDraft = () => {
|
||||
if (chatTemplateMode === 'custom_inline') {
|
||||
updateField('chat_template', { type: 'custom_inline', template: chatTemplateDraft });
|
||||
updateField('chatTemplate', { type: 'custom_inline', template: chatTemplateDraft });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -488,9 +497,9 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
sampling = {
|
||||
type: 'Temperature',
|
||||
temperature: 0.8,
|
||||
top_k: 40,
|
||||
top_p: 0.95,
|
||||
min_p: 0.05,
|
||||
topK: 40,
|
||||
topP: 0.95,
|
||||
minP: 0.05,
|
||||
seed: null,
|
||||
};
|
||||
}
|
||||
@@ -526,8 +535,8 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.contextSize)}
|
||||
description={intl.formatMessage(i18n.contextSizeDescription)}
|
||||
value={settings.context_size}
|
||||
onChange={(v) => updateField('context_size', v)}
|
||||
value={settings.contextSize}
|
||||
onChange={(v) => updateField('contextSize', v)}
|
||||
placeholder="Auto"
|
||||
min={0}
|
||||
allowNull
|
||||
@@ -535,8 +544,8 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.maxOutputTokens)}
|
||||
description={intl.formatMessage(i18n.maxOutputTokensDescription)}
|
||||
value={settings.max_output_tokens}
|
||||
onChange={(v) => updateField('max_output_tokens', v)}
|
||||
value={settings.maxOutputTokens}
|
||||
onChange={(v) => updateField('maxOutputTokens', v)}
|
||||
placeholder="No limit"
|
||||
min={1}
|
||||
allowNull
|
||||
@@ -569,22 +578,22 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
/>
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.topK)}
|
||||
value={settings.sampling.top_k}
|
||||
onChange={(v) => updateSampling({ top_k: v ?? 40 })}
|
||||
value={settings.sampling.topK}
|
||||
onChange={(v) => updateSampling({ topK: v ?? 40 })}
|
||||
min={0}
|
||||
/>
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.topP)}
|
||||
value={settings.sampling.top_p}
|
||||
onChange={(v) => updateSampling({ top_p: v ?? 0.95 })}
|
||||
value={settings.sampling.topP}
|
||||
onChange={(v) => updateSampling({ topP: v ?? 0.95 })}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
/>
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.minP)}
|
||||
value={settings.sampling.min_p}
|
||||
onChange={(v) => updateSampling({ min_p: v ?? 0.05 })}
|
||||
value={settings.sampling.minP}
|
||||
onChange={(v) => updateSampling({ minP: v ?? 0.05 })}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
@@ -636,23 +645,23 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.repeatPenalty)}
|
||||
description={intl.formatMessage(i18n.repeatPenaltyDescription)}
|
||||
value={settings.repeat_penalty}
|
||||
onChange={(v) => updateField('repeat_penalty', v ?? 1.0)}
|
||||
value={settings.repeatPenalty}
|
||||
onChange={(v) => updateField('repeatPenalty', v ?? 1.0)}
|
||||
min={0}
|
||||
step={0.05}
|
||||
/>
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.repeatWindow)}
|
||||
description={intl.formatMessage(i18n.repeatWindowDescription)}
|
||||
value={settings.repeat_last_n}
|
||||
onChange={(v) => updateField('repeat_last_n', v ?? 64)}
|
||||
value={settings.repeatLastN}
|
||||
onChange={(v) => updateField('repeatLastN', v ?? 64)}
|
||||
min={0}
|
||||
/>
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.frequencyPenalty)}
|
||||
description={intl.formatMessage(i18n.frequencyPenaltyDescription)}
|
||||
value={settings.frequency_penalty}
|
||||
onChange={(v) => updateField('frequency_penalty', v ?? 0.0)}
|
||||
value={settings.frequencyPenalty}
|
||||
onChange={(v) => updateField('frequencyPenalty', v ?? 0.0)}
|
||||
min={0}
|
||||
max={2}
|
||||
step={0.05}
|
||||
@@ -660,8 +669,8 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.presencePenalty)}
|
||||
description={intl.formatMessage(i18n.presencePenaltyDescription)}
|
||||
value={settings.presence_penalty}
|
||||
onChange={(v) => updateField('presence_penalty', v ?? 0.0)}
|
||||
value={settings.presencePenalty}
|
||||
onChange={(v) => updateField('presencePenalty', v ?? 0.0)}
|
||||
min={0}
|
||||
max={2}
|
||||
step={0.05}
|
||||
@@ -676,8 +685,8 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.batchSize)}
|
||||
description={intl.formatMessage(i18n.batchSizeDescription)}
|
||||
value={settings.n_batch}
|
||||
onChange={(v) => updateField('n_batch', v)}
|
||||
value={settings.nBatch}
|
||||
onChange={(v) => updateField('nBatch', v)}
|
||||
placeholder="Auto"
|
||||
min={1}
|
||||
allowNull
|
||||
@@ -685,8 +694,8 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.gpuLayers)}
|
||||
description={intl.formatMessage(i18n.gpuLayersDescription)}
|
||||
value={settings.n_gpu_layers}
|
||||
onChange={(v) => updateField('n_gpu_layers', v)}
|
||||
value={settings.nGpuLayers}
|
||||
onChange={(v) => updateField('nGpuLayers', v)}
|
||||
placeholder="All"
|
||||
min={0}
|
||||
allowNull
|
||||
@@ -694,8 +703,8 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
<NumberField
|
||||
label={intl.formatMessage(i18n.threads)}
|
||||
description={intl.formatMessage(i18n.threadsDescription)}
|
||||
value={settings.n_threads}
|
||||
onChange={(v) => updateField('n_threads', v)}
|
||||
value={settings.nThreads}
|
||||
onChange={(v) => updateField('nThreads', v)}
|
||||
placeholder="Auto"
|
||||
min={1}
|
||||
allowNull
|
||||
@@ -704,16 +713,16 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
<ToggleField
|
||||
label={intl.formatMessage(i18n.lockModelInRam)}
|
||||
description={intl.formatMessage(i18n.lockModelInRamDescription)}
|
||||
value={settings.use_mlock ?? false}
|
||||
onChange={(v) => updateField('use_mlock', v)}
|
||||
value={settings.useMlock ?? false}
|
||||
onChange={(v) => updateField('useMlock', v)}
|
||||
/>
|
||||
<SelectField
|
||||
label={intl.formatMessage(i18n.flashAttention)}
|
||||
description={intl.formatMessage(i18n.flashAttentionDescription)}
|
||||
value={
|
||||
settings.flash_attention === null || settings.flash_attention === undefined
|
||||
settings.flashAttention === null || settings.flashAttention === undefined
|
||||
? 'auto'
|
||||
: settings.flash_attention
|
||||
: settings.flashAttention
|
||||
? 'on'
|
||||
: 'off'
|
||||
}
|
||||
@@ -722,18 +731,18 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => {
|
||||
{ value: 'on', label: 'On' },
|
||||
{ value: 'off', label: 'Off' },
|
||||
]}
|
||||
onChange={(v) => updateField('flash_attention', v === 'auto' ? null : v === 'on')}
|
||||
onChange={(v) => updateField('flashAttention', v === 'auto' ? null : v === 'on')}
|
||||
/>
|
||||
<SelectField<ToolCallingMode>
|
||||
label={intl.formatMessage(i18n.toolCalling)}
|
||||
description={intl.formatMessage(i18n.toolCallingDescription)}
|
||||
value={settings.tool_calling ?? 'auto'}
|
||||
value={settings.toolCalling ?? 'auto'}
|
||||
options={[
|
||||
{ value: 'auto', label: intl.formatMessage(i18n.toolCallingAuto) },
|
||||
{ value: 'force_native', label: intl.formatMessage(i18n.toolCallingForceNative) },
|
||||
{ value: 'force_emulated', label: intl.formatMessage(i18n.toolCallingForceEmulated) },
|
||||
]}
|
||||
onChange={(v) => updateField('tool_calling', v)}
|
||||
onChange={(v) => updateField('toolCalling', v)}
|
||||
/>
|
||||
<SelectField<ChatTemplateMode>
|
||||
label={intl.formatMessage(i18n.chatTemplate)}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ProviderDetails, ThinkingEffort, listLocalModels } from '../../../api';
|
||||
import { ProviderDetails, ThinkingEffort } from '../../../api';
|
||||
import { listLocalModels } from '../../../acp/local-inference';
|
||||
import { acpListProviderDetails, acpListProviderModels } from '../../../acp/providers';
|
||||
import { errorMessage as getErrorMessage } from '../../../utils/conversionUtils';
|
||||
|
||||
@@ -56,8 +57,7 @@ export async function fetchModelsForProviders(
|
||||
try {
|
||||
// For local provider, use listLocalModels and filter to only downloaded models
|
||||
if (p.name === 'local') {
|
||||
const response = await listLocalModels();
|
||||
const allModels = response.data || [];
|
||||
const allModels = await listLocalModels();
|
||||
const downloadedModels = allModels
|
||||
.filter((m) => m.status.state === 'Downloaded')
|
||||
.map((m) => ({ name: m.id, provider: p.name }) as Model);
|
||||
|
||||
@@ -109,6 +109,24 @@ import type {
|
||||
ListSlashCommandsResponse_unstable,
|
||||
ListSourcesRequest_unstable,
|
||||
ListSourcesResponse_unstable,
|
||||
LocalInferenceBuiltinChatTemplatesListRequest_unstable,
|
||||
LocalInferenceBuiltinChatTemplatesListResponse_unstable,
|
||||
LocalInferenceHuggingFaceRepoVariantsRequest_unstable,
|
||||
LocalInferenceHuggingFaceRepoVariantsResponse_unstable,
|
||||
LocalInferenceHuggingFaceSearchRequest_unstable,
|
||||
LocalInferenceHuggingFaceSearchResponse_unstable,
|
||||
LocalInferenceModelDeleteRequest_unstable,
|
||||
LocalInferenceModelDownloadCancelRequest_unstable,
|
||||
LocalInferenceModelDownloadProgressRequest_unstable,
|
||||
LocalInferenceModelDownloadProgressResponse_unstable,
|
||||
LocalInferenceModelDownloadRequest_unstable,
|
||||
LocalInferenceModelDownloadResponse_unstable,
|
||||
LocalInferenceModelSettingsReadRequest_unstable,
|
||||
LocalInferenceModelSettingsReadResponse_unstable,
|
||||
LocalInferenceModelSettingsUpdateRequest_unstable,
|
||||
LocalInferenceModelSettingsUpdateResponse_unstable,
|
||||
LocalInferenceModelsListRequest_unstable,
|
||||
LocalInferenceModelsListResponse_unstable,
|
||||
OnboardingImportApplyRequest_unstable,
|
||||
OnboardingImportApplyResponse_unstable,
|
||||
OnboardingImportScanRequest_unstable,
|
||||
@@ -222,6 +240,14 @@ import {
|
||||
zListSchedulesResponse_unstable,
|
||||
zListSlashCommandsResponse_unstable,
|
||||
zListSourcesResponse_unstable,
|
||||
zLocalInferenceBuiltinChatTemplatesListResponse_unstable,
|
||||
zLocalInferenceHuggingFaceRepoVariantsResponse_unstable,
|
||||
zLocalInferenceHuggingFaceSearchResponse_unstable,
|
||||
zLocalInferenceModelDownloadProgressResponse_unstable,
|
||||
zLocalInferenceModelDownloadResponse_unstable,
|
||||
zLocalInferenceModelSettingsReadResponse_unstable,
|
||||
zLocalInferenceModelSettingsUpdateResponse_unstable,
|
||||
zLocalInferenceModelsListResponse_unstable,
|
||||
zOnboardingImportApplyResponse_unstable,
|
||||
zOnboardingImportScanResponse_unstable,
|
||||
zParseRecipeResponse_unstable,
|
||||
@@ -1296,6 +1322,120 @@ export class GooseExtClient {
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
async localInferenceModelsList_unstable(
|
||||
params: LocalInferenceModelsListRequest_unstable,
|
||||
): Promise<LocalInferenceModelsListResponse_unstable> {
|
||||
const raw = await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/models/list",
|
||||
params,
|
||||
);
|
||||
return zLocalInferenceModelsListResponse_unstable.parse(
|
||||
raw,
|
||||
) as LocalInferenceModelsListResponse_unstable;
|
||||
}
|
||||
|
||||
async localInferenceModelsDownload_unstable(
|
||||
params: LocalInferenceModelDownloadRequest_unstable,
|
||||
): Promise<LocalInferenceModelDownloadResponse_unstable> {
|
||||
const raw = await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/models/download",
|
||||
params,
|
||||
);
|
||||
return zLocalInferenceModelDownloadResponse_unstable.parse(
|
||||
raw,
|
||||
) as LocalInferenceModelDownloadResponse_unstable;
|
||||
}
|
||||
|
||||
async localInferenceModelsDownloadProgress_unstable(
|
||||
params: LocalInferenceModelDownloadProgressRequest_unstable,
|
||||
): Promise<LocalInferenceModelDownloadProgressResponse_unstable> {
|
||||
const raw = await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/models/download/progress",
|
||||
params,
|
||||
);
|
||||
return zLocalInferenceModelDownloadProgressResponse_unstable.parse(
|
||||
raw,
|
||||
) as LocalInferenceModelDownloadProgressResponse_unstable;
|
||||
}
|
||||
|
||||
async localInferenceModelsDownloadCancel_unstable(
|
||||
params: LocalInferenceModelDownloadCancelRequest_unstable,
|
||||
): Promise<void> {
|
||||
await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/models/download/cancel",
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
async localInferenceModelsDelete_unstable(
|
||||
params: LocalInferenceModelDeleteRequest_unstable,
|
||||
): Promise<void> {
|
||||
await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/models/delete",
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
async localInferenceModelsSettingsRead_unstable(
|
||||
params: LocalInferenceModelSettingsReadRequest_unstable,
|
||||
): Promise<LocalInferenceModelSettingsReadResponse_unstable> {
|
||||
const raw = await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/models/settings/read",
|
||||
params,
|
||||
);
|
||||
return zLocalInferenceModelSettingsReadResponse_unstable.parse(
|
||||
raw,
|
||||
) as LocalInferenceModelSettingsReadResponse_unstable;
|
||||
}
|
||||
|
||||
async localInferenceModelsSettingsUpdate_unstable(
|
||||
params: LocalInferenceModelSettingsUpdateRequest_unstable,
|
||||
): Promise<LocalInferenceModelSettingsUpdateResponse_unstable> {
|
||||
const raw = await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/models/settings/update",
|
||||
params,
|
||||
);
|
||||
return zLocalInferenceModelSettingsUpdateResponse_unstable.parse(
|
||||
raw,
|
||||
) as LocalInferenceModelSettingsUpdateResponse_unstable;
|
||||
}
|
||||
|
||||
async localInferenceHuggingfaceSearch_unstable(
|
||||
params: LocalInferenceHuggingFaceSearchRequest_unstable,
|
||||
): Promise<LocalInferenceHuggingFaceSearchResponse_unstable> {
|
||||
const raw = await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/huggingface/search",
|
||||
params,
|
||||
);
|
||||
return zLocalInferenceHuggingFaceSearchResponse_unstable.parse(
|
||||
raw,
|
||||
) as LocalInferenceHuggingFaceSearchResponse_unstable;
|
||||
}
|
||||
|
||||
async localInferenceHuggingfaceRepoVariants_unstable(
|
||||
params: LocalInferenceHuggingFaceRepoVariantsRequest_unstable,
|
||||
): Promise<LocalInferenceHuggingFaceRepoVariantsResponse_unstable> {
|
||||
const raw = await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/huggingface/repo/variants",
|
||||
params,
|
||||
);
|
||||
return zLocalInferenceHuggingFaceRepoVariantsResponse_unstable.parse(
|
||||
raw,
|
||||
) as LocalInferenceHuggingFaceRepoVariantsResponse_unstable;
|
||||
}
|
||||
|
||||
async localInferenceChatTemplatesBuiltinList_unstable(
|
||||
params: LocalInferenceBuiltinChatTemplatesListRequest_unstable,
|
||||
): Promise<LocalInferenceBuiltinChatTemplatesListResponse_unstable> {
|
||||
const raw = await this.conn.extMethod(
|
||||
"_goose/unstable/local-inference/chat-templates/builtin/list",
|
||||
params,
|
||||
);
|
||||
return zLocalInferenceBuiltinChatTemplatesListResponse_unstable.parse(
|
||||
raw,
|
||||
) as LocalInferenceBuiltinChatTemplatesListResponse_unstable;
|
||||
}
|
||||
}
|
||||
|
||||
export interface GooseExtNotifications {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2312,6 +2312,205 @@ export type DictationModelSelectRequest_unstable = {
|
||||
modelId: string;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelsListRequest_unstable = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelsListResponse_unstable = {
|
||||
models: Array<LocalInferenceModelDto>;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelDto = {
|
||||
id: string;
|
||||
repoId: string;
|
||||
filename: string;
|
||||
quantization: string;
|
||||
sizeBytes: number;
|
||||
status: LocalInferenceModelDownloadStatusDto;
|
||||
recommended: boolean;
|
||||
settings: LocalInferenceModelSettingsDto;
|
||||
visionCapable: boolean;
|
||||
mmprojStatus?: LocalInferenceModelDownloadStatusDto | null;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelDownloadStatusDto = {
|
||||
state: LocalInferenceDownloadState;
|
||||
progressPercent?: number | null;
|
||||
bytesDownloaded?: number | null;
|
||||
totalBytes?: number | null;
|
||||
speedBps?: number | null;
|
||||
};
|
||||
|
||||
export type LocalInferenceDownloadState = 'NotDownloaded' | 'Downloading' | 'Downloaded';
|
||||
|
||||
export type LocalInferenceModelSettingsDto = {
|
||||
backendId?: string | null;
|
||||
contextSize?: number | null;
|
||||
maxOutputTokens?: number | null;
|
||||
draftModel?: string | null;
|
||||
sampling?: LocalInferenceSamplingConfig;
|
||||
repeatPenalty: number;
|
||||
repeatLastN: number;
|
||||
frequencyPenalty: number;
|
||||
presencePenalty: number;
|
||||
nBatch?: number | null;
|
||||
nGpuLayers?: number | null;
|
||||
useMlock: boolean;
|
||||
flashAttention?: boolean | null;
|
||||
nThreads?: number | null;
|
||||
toolCalling?: LocalInferenceToolCallingMode;
|
||||
chatTemplate?: LocalInferenceChatTemplate;
|
||||
enableThinking: boolean;
|
||||
visionCapable: boolean;
|
||||
imageTokenEstimate: number;
|
||||
mmprojSizeBytes: number;
|
||||
};
|
||||
|
||||
export type LocalInferenceSamplingConfig = {
|
||||
type: 'Greedy';
|
||||
} | {
|
||||
temperature: number;
|
||||
topK: number;
|
||||
topP: number;
|
||||
minP: number;
|
||||
seed?: number | null;
|
||||
type: 'Temperature';
|
||||
} | {
|
||||
tau: number;
|
||||
eta: number;
|
||||
seed?: number | null;
|
||||
type: 'MirostatV2';
|
||||
};
|
||||
|
||||
export type LocalInferenceToolCallingMode = 'auto' | 'force_native' | 'force_emulated';
|
||||
|
||||
export type LocalInferenceChatTemplate = {
|
||||
type: 'embedded';
|
||||
} | {
|
||||
name: string;
|
||||
type: 'builtin';
|
||||
} | {
|
||||
template: string;
|
||||
type: 'custom_inline';
|
||||
};
|
||||
|
||||
export type LocalInferenceModelDownloadRequest_unstable = {
|
||||
spec: string;
|
||||
backendId?: string | null;
|
||||
variantId?: string | null;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelDownloadResponse_unstable = {
|
||||
modelId: string;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelDownloadProgressRequest_unstable = {
|
||||
modelId: string;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelDownloadProgressResponse_unstable = {
|
||||
progress?: LocalInferenceDownloadProgressDto | null;
|
||||
};
|
||||
|
||||
export type LocalInferenceDownloadProgressDto = {
|
||||
modelId: string;
|
||||
status: string;
|
||||
bytesDownloaded: number;
|
||||
totalBytes: number;
|
||||
progressPercent: number;
|
||||
speedBps?: number | null;
|
||||
etaSeconds?: number | null;
|
||||
error?: string | null;
|
||||
taskExited: boolean;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelDownloadCancelRequest_unstable = {
|
||||
modelId: string;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelDeleteRequest_unstable = {
|
||||
modelId: string;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelSettingsReadRequest_unstable = {
|
||||
modelId: string;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelSettingsReadResponse_unstable = {
|
||||
settings: LocalInferenceModelSettingsDto;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelSettingsUpdateRequest_unstable = {
|
||||
modelId: string;
|
||||
settings: LocalInferenceModelSettingsDto;
|
||||
};
|
||||
|
||||
export type LocalInferenceModelSettingsUpdateResponse_unstable = {
|
||||
settings: LocalInferenceModelSettingsDto;
|
||||
};
|
||||
|
||||
export type LocalInferenceHuggingFaceSearchRequest_unstable = {
|
||||
query: string;
|
||||
limit?: number | null;
|
||||
};
|
||||
|
||||
export type LocalInferenceHuggingFaceSearchResponse_unstable = {
|
||||
models: Array<LocalInferenceHfModelInfoDto>;
|
||||
};
|
||||
|
||||
export type LocalInferenceHfModelInfoDto = {
|
||||
repoId: string;
|
||||
author: string;
|
||||
modelName: string;
|
||||
downloads: number;
|
||||
ggufFiles?: Array<LocalInferenceHfGgufFileDto>;
|
||||
variants?: Array<LocalInferenceHfModelVariantDto>;
|
||||
};
|
||||
|
||||
export type LocalInferenceHfGgufFileDto = {
|
||||
filename: string;
|
||||
sizeBytes: number;
|
||||
quantization: string;
|
||||
downloadUrl: string;
|
||||
};
|
||||
|
||||
export type LocalInferenceHfModelVariantDto = {
|
||||
variantId: string;
|
||||
label: string;
|
||||
backendId: string;
|
||||
format: string;
|
||||
modelId: string;
|
||||
downloadId: string;
|
||||
sizeBytes: number;
|
||||
filename?: string | null;
|
||||
downloadUrl?: string | null;
|
||||
description: string;
|
||||
qualityRank: number;
|
||||
sharded: boolean;
|
||||
supported: boolean;
|
||||
unsupportedReason?: string | null;
|
||||
};
|
||||
|
||||
export type LocalInferenceHuggingFaceRepoVariantsRequest_unstable = {
|
||||
repoId: string;
|
||||
};
|
||||
|
||||
export type LocalInferenceHuggingFaceRepoVariantsResponse_unstable = {
|
||||
variants: Array<LocalInferenceHfModelVariantDto>;
|
||||
recommendedIndex?: number | null;
|
||||
availableMemoryBytes: number;
|
||||
downloadedQuants: Array<string>;
|
||||
downloadedVariants: Array<string>;
|
||||
};
|
||||
|
||||
export type LocalInferenceBuiltinChatTemplatesListRequest_unstable = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
export type LocalInferenceBuiltinChatTemplatesListResponse_unstable = {
|
||||
templates: Array<string>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Goose-custom session update notification — a parallel to ACP's
|
||||
* `session/update` carrying goose-specific update variants.
|
||||
@@ -2379,14 +2578,14 @@ export type RecipeParamsAction = 'submit' | 'cancel';
|
||||
export type ExtRequest = {
|
||||
id: string;
|
||||
method: string;
|
||||
params?: AddSessionExtensionRequest_unstable | RemoveSessionExtensionRequest_unstable | GetToolsRequest_unstable | SetToolPermissionsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | AppsListRequest_unstable | AppsExportRequest_unstable | AppsImportRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | SteerSessionRequest_unstable | DiagnosticsGetRequest_unstable | ListPromptsRequest_unstable | GetPromptRequest_unstable | SavePromptRequest_unstable | ResetPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | ProviderSecretsListRequest_unstable | ProviderSecretDeleteRequest_unstable | CanonicalModelInfoRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | ConfigReadRequest_unstable | ConfigUpsertRequest_unstable | ConfigRemoveRequest_unstable | ConfigReadAllRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | DefaultsClearRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | ShareSessionNostrRequest_unstable | EncodeRecipeRequest_unstable | DecodeRecipeRequest_unstable | ScanRecipeRequest_unstable | ListRecipesRequest_unstable | DeleteRecipeRequest_unstable | ScheduleRecipeRequest_unstable | SetRecipeSlashCommandRequest_unstable | SaveRecipeRequest_unstable | ParseRecipeRequest_unstable | RecipeToYamlRequest_unstable | ListSchedulesRequest_unstable | ListScheduleSessionsRequest_unstable | CreateScheduleRequest_unstable | DeleteScheduleRequest_unstable | PauseScheduleRequest_unstable | UnpauseScheduleRequest_unstable | UpdateScheduleRequest_unstable | RunScheduleNowRequest_unstable | KillRunningJobRequest_unstable | InspectRunningJobRequest_unstable | GetSessionInfoRequest_unstable | TruncateSessionConversationRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | ListAgentMentionsRequest_unstable | ListSlashCommandsRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | {
|
||||
params?: AddSessionExtensionRequest_unstable | RemoveSessionExtensionRequest_unstable | GetToolsRequest_unstable | SetToolPermissionsRequest_unstable | GooseToolCallRequest_unstable | ReadResourceRequest_unstable | AppsListRequest_unstable | AppsExportRequest_unstable | AppsImportRequest_unstable | UpdateWorkingDirRequest_unstable | SetSessionSystemPromptRequest_unstable | SteerSessionRequest_unstable | DiagnosticsGetRequest_unstable | ListPromptsRequest_unstable | GetPromptRequest_unstable | SavePromptRequest_unstable | ResetPromptRequest_unstable | DeleteSessionRequest | GetConfigExtensionsRequest_unstable | GetAvailableExtensionsRequest_unstable | AddConfigExtensionRequest_unstable | RemoveConfigExtensionRequest_unstable | SetConfigExtensionEnabledRequest_unstable | GetSessionExtensionsRequest_unstable | ListProvidersRequest_unstable | ProviderSupportedModelsListRequest_unstable | ProviderCatalogListRequest_unstable | ProviderSetupCatalogListRequest_unstable | ProviderCatalogTemplateRequest_unstable | CustomProviderCreateRequest_unstable | CustomProviderReadRequest_unstable | CustomProviderUpdateRequest_unstable | CustomProviderDeleteRequest_unstable | RefreshProviderInventoryRequest_unstable | ProviderConfigReadRequest_unstable | ProviderConfigStatusRequest_unstable | ProviderConfigSaveRequest_unstable | ProviderConfigDeleteRequest_unstable | ProviderConfigAuthenticateRequest_unstable | ProviderSecretsListRequest_unstable | ProviderSecretDeleteRequest_unstable | CanonicalModelInfoRequest_unstable | PreferencesReadRequest_unstable | PreferencesSaveRequest_unstable | PreferencesRemoveRequest_unstable | ConfigReadRequest_unstable | ConfigUpsertRequest_unstable | ConfigRemoveRequest_unstable | ConfigReadAllRequest_unstable | DefaultsReadRequest_unstable | DefaultsSaveRequest_unstable | DefaultsClearRequest_unstable | OnboardingImportScanRequest_unstable | OnboardingImportApplyRequest_unstable | ExportSessionRequest_unstable | ImportSessionRequest_unstable | ShareSessionNostrRequest_unstable | EncodeRecipeRequest_unstable | DecodeRecipeRequest_unstable | ScanRecipeRequest_unstable | ListRecipesRequest_unstable | DeleteRecipeRequest_unstable | ScheduleRecipeRequest_unstable | SetRecipeSlashCommandRequest_unstable | SaveRecipeRequest_unstable | ParseRecipeRequest_unstable | RecipeToYamlRequest_unstable | ListSchedulesRequest_unstable | ListScheduleSessionsRequest_unstable | CreateScheduleRequest_unstable | DeleteScheduleRequest_unstable | PauseScheduleRequest_unstable | UnpauseScheduleRequest_unstable | UpdateScheduleRequest_unstable | RunScheduleNowRequest_unstable | KillRunningJobRequest_unstable | InspectRunningJobRequest_unstable | GetSessionInfoRequest_unstable | TruncateSessionConversationRequest_unstable | UpdateSessionProjectRequest_unstable | RenameSessionRequest_unstable | ArchiveSessionRequest_unstable | UnarchiveSessionRequest_unstable | CreateSourceRequest_unstable | ListSourcesRequest_unstable | ListAgentMentionsRequest_unstable | ListSlashCommandsRequest_unstable | UpdateSourceRequest_unstable | DeleteSourceRequest_unstable | ExportSourceRequest_unstable | ImportSourcesRequest_unstable | DictationTranscribeRequest_unstable | DictationConfigRequest_unstable | DictationSecretSaveRequest_unstable | DictationSecretDeleteRequest_unstable | DictationModelsListRequest_unstable | DictationModelDownloadRequest_unstable | DictationModelDownloadProgressRequest_unstable | DictationModelCancelRequest_unstable | DictationModelDeleteRequest_unstable | DictationModelSelectRequest_unstable | LocalInferenceModelsListRequest_unstable | LocalInferenceModelDownloadRequest_unstable | LocalInferenceModelDownloadProgressRequest_unstable | LocalInferenceModelDownloadCancelRequest_unstable | LocalInferenceModelDeleteRequest_unstable | LocalInferenceModelSettingsReadRequest_unstable | LocalInferenceModelSettingsUpdateRequest_unstable | LocalInferenceHuggingFaceSearchRequest_unstable | LocalInferenceHuggingFaceRepoVariantsRequest_unstable | LocalInferenceBuiltinChatTemplatesListRequest_unstable | {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export type ExtResponse = {
|
||||
id: string;
|
||||
result?: EmptyResponse | GetToolsResponse_unstable | SetToolPermissionsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | AppsListResponse_unstable | AppsExportResponse_unstable | AppsImportResponse_unstable | SteerSessionResponse_unstable | DiagnosticsGetResponse_unstable | ListPromptsResponse_unstable | GetPromptResponse_unstable | PromptOperationResponse_unstable | GetConfigExtensionsResponse_unstable | GetAvailableExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | ProviderSecretsListResponse_unstable | CanonicalModelInfoResponse_unstable | PreferencesReadResponse_unstable | ConfigReadResponse_unstable | ConfigReadAllResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | ShareSessionNostrResponse_unstable | EncodeRecipeResponse_unstable | DecodeRecipeResponse_unstable | ScanRecipeResponse_unstable | ListRecipesResponse_unstable | SaveRecipeResponse_unstable | ParseRecipeResponse_unstable | RecipeToYamlResponse_unstable | ListSchedulesResponse_unstable | ListScheduleSessionsResponse_unstable | CreateScheduleResponse_unstable | UpdateScheduleResponse_unstable | RunScheduleNowResponse_unstable | KillRunningJobResponse_unstable | InspectRunningJobResponse_unstable | GetSessionInfoResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | ListAgentMentionsResponse_unstable | ListSlashCommandsResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | unknown;
|
||||
result?: EmptyResponse | GetToolsResponse_unstable | SetToolPermissionsResponse_unstable | GooseToolCallResponse_unstable | ReadResourceResponse_unstable | AppsListResponse_unstable | AppsExportResponse_unstable | AppsImportResponse_unstable | SteerSessionResponse_unstable | DiagnosticsGetResponse_unstable | ListPromptsResponse_unstable | GetPromptResponse_unstable | PromptOperationResponse_unstable | GetConfigExtensionsResponse_unstable | GetAvailableExtensionsResponse_unstable | GetSessionExtensionsResponse_unstable | ListProvidersResponse_unstable | ProviderSupportedModelsListResponse_unstable | ProviderCatalogListResponse_unstable | ProviderSetupCatalogListResponse_unstable | ProviderCatalogTemplateResponse_unstable | CustomProviderCreateResponse_unstable | CustomProviderReadResponse_unstable | CustomProviderUpdateResponse_unstable | CustomProviderDeleteResponse_unstable | RefreshProviderInventoryResponse_unstable | ProviderConfigReadResponse_unstable | ProviderConfigStatusResponse_unstable | ProviderConfigChangeResponse_unstable | ProviderSecretsListResponse_unstable | CanonicalModelInfoResponse_unstable | PreferencesReadResponse_unstable | ConfigReadResponse_unstable | ConfigReadAllResponse_unstable | DefaultsReadResponse_unstable | OnboardingImportScanResponse_unstable | OnboardingImportApplyResponse_unstable | ExportSessionResponse_unstable | ImportSessionResponse_unstable | ShareSessionNostrResponse_unstable | EncodeRecipeResponse_unstable | DecodeRecipeResponse_unstable | ScanRecipeResponse_unstable | ListRecipesResponse_unstable | SaveRecipeResponse_unstable | ParseRecipeResponse_unstable | RecipeToYamlResponse_unstable | ListSchedulesResponse_unstable | ListScheduleSessionsResponse_unstable | CreateScheduleResponse_unstable | UpdateScheduleResponse_unstable | RunScheduleNowResponse_unstable | KillRunningJobResponse_unstable | InspectRunningJobResponse_unstable | GetSessionInfoResponse_unstable | CreateSourceResponse_unstable | ListSourcesResponse_unstable | ListAgentMentionsResponse_unstable | ListSlashCommandsResponse_unstable | UpdateSourceResponse_unstable | ExportSourceResponse_unstable | ImportSourcesResponse_unstable | DictationTranscribeResponse_unstable | DictationConfigResponse_unstable | DictationModelsListResponse_unstable | DictationModelDownloadProgressResponse_unstable | LocalInferenceModelsListResponse_unstable | LocalInferenceModelDownloadResponse_unstable | LocalInferenceModelDownloadProgressResponse_unstable | LocalInferenceModelSettingsReadResponse_unstable | LocalInferenceModelSettingsUpdateResponse_unstable | LocalInferenceHuggingFaceSearchResponse_unstable | LocalInferenceHuggingFaceRepoVariantsResponse_unstable | LocalInferenceBuiltinChatTemplatesListResponse_unstable | unknown;
|
||||
} | {
|
||||
error: {
|
||||
code: number;
|
||||
|
||||
@@ -2369,6 +2369,301 @@ export const zDictationModelSelectRequest_unstable = z.object({
|
||||
modelId: z.string()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelsListRequest_unstable = z.record(z.unknown());
|
||||
|
||||
export const zLocalInferenceDownloadState = z.enum([
|
||||
'NotDownloaded',
|
||||
'Downloading',
|
||||
'Downloaded'
|
||||
]);
|
||||
|
||||
export const zLocalInferenceModelDownloadStatusDto = z.object({
|
||||
state: zLocalInferenceDownloadState,
|
||||
progressPercent: z.union([
|
||||
z.number(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
bytesDownloaded: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
totalBytes: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
speedBps: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional()
|
||||
});
|
||||
|
||||
export const zLocalInferenceSamplingConfig = z.union([
|
||||
z.object({
|
||||
type: z.literal('Greedy')
|
||||
}),
|
||||
z.object({
|
||||
temperature: z.number(),
|
||||
topK: z.number().int(),
|
||||
topP: z.number(),
|
||||
minP: z.number(),
|
||||
seed: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
type: z.literal('Temperature')
|
||||
}),
|
||||
z.object({
|
||||
tau: z.number(),
|
||||
eta: z.number(),
|
||||
seed: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
type: z.literal('MirostatV2')
|
||||
})
|
||||
]);
|
||||
|
||||
export const zLocalInferenceToolCallingMode = z.enum([
|
||||
'auto',
|
||||
'force_native',
|
||||
'force_emulated'
|
||||
]);
|
||||
|
||||
export const zLocalInferenceChatTemplate = z.union([
|
||||
z.object({
|
||||
type: z.literal('embedded')
|
||||
}),
|
||||
z.object({
|
||||
name: z.string(),
|
||||
type: z.literal('builtin')
|
||||
}),
|
||||
z.object({
|
||||
template: z.string(),
|
||||
type: z.literal('custom_inline')
|
||||
})
|
||||
]);
|
||||
|
||||
export const zLocalInferenceModelSettingsDto = z.object({
|
||||
backendId: z.union([
|
||||
z.string(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
contextSize: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
maxOutputTokens: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
draftModel: z.union([
|
||||
z.string(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
sampling: zLocalInferenceSamplingConfig.optional().default({
|
||||
type: 'Temperature',
|
||||
temperature: 0.800000011920929,
|
||||
topK: 40,
|
||||
topP: 0.949999988079071,
|
||||
minP: 0.05000000074505806
|
||||
}),
|
||||
repeatPenalty: z.number(),
|
||||
repeatLastN: z.number().int(),
|
||||
frequencyPenalty: z.number(),
|
||||
presencePenalty: z.number(),
|
||||
nBatch: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
nGpuLayers: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
useMlock: z.boolean(),
|
||||
flashAttention: z.union([
|
||||
z.boolean(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
nThreads: z.union([
|
||||
z.number().int(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
toolCalling: zLocalInferenceToolCallingMode.optional().default('auto'),
|
||||
chatTemplate: zLocalInferenceChatTemplate.optional().default({ type: 'embedded' }),
|
||||
enableThinking: z.boolean(),
|
||||
visionCapable: z.boolean(),
|
||||
imageTokenEstimate: z.number().int().gte(0),
|
||||
mmprojSizeBytes: z.number().int().gte(0)
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelDto = z.object({
|
||||
id: z.string(),
|
||||
repoId: z.string(),
|
||||
filename: z.string(),
|
||||
quantization: z.string(),
|
||||
sizeBytes: z.number().int().gte(0),
|
||||
status: zLocalInferenceModelDownloadStatusDto,
|
||||
recommended: z.boolean(),
|
||||
settings: zLocalInferenceModelSettingsDto,
|
||||
visionCapable: z.boolean(),
|
||||
mmprojStatus: z.union([
|
||||
zLocalInferenceModelDownloadStatusDto,
|
||||
z.null()
|
||||
]).optional()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelsListResponse_unstable = z.object({
|
||||
models: z.array(zLocalInferenceModelDto)
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelDownloadRequest_unstable = z.object({
|
||||
spec: z.string(),
|
||||
backendId: z.union([
|
||||
z.string(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
variantId: z.union([
|
||||
z.string(),
|
||||
z.null()
|
||||
]).optional()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelDownloadResponse_unstable = z.object({
|
||||
modelId: z.string()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelDownloadProgressRequest_unstable = z.object({
|
||||
modelId: z.string()
|
||||
});
|
||||
|
||||
export const zLocalInferenceDownloadProgressDto = z.object({
|
||||
modelId: z.string(),
|
||||
status: z.string(),
|
||||
bytesDownloaded: z.number().int().gte(0),
|
||||
totalBytes: z.number().int().gte(0),
|
||||
progressPercent: z.number(),
|
||||
speedBps: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
etaSeconds: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
error: z.union([
|
||||
z.string(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
taskExited: z.boolean()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelDownloadProgressResponse_unstable = z.object({
|
||||
progress: z.union([
|
||||
zLocalInferenceDownloadProgressDto,
|
||||
z.null()
|
||||
]).optional()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelDownloadCancelRequest_unstable = z.object({
|
||||
modelId: z.string()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelDeleteRequest_unstable = z.object({
|
||||
modelId: z.string()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelSettingsReadRequest_unstable = z.object({
|
||||
modelId: z.string()
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelSettingsReadResponse_unstable = z.object({
|
||||
settings: zLocalInferenceModelSettingsDto
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelSettingsUpdateRequest_unstable = z.object({
|
||||
modelId: z.string(),
|
||||
settings: zLocalInferenceModelSettingsDto
|
||||
});
|
||||
|
||||
export const zLocalInferenceModelSettingsUpdateResponse_unstable = z.object({
|
||||
settings: zLocalInferenceModelSettingsDto
|
||||
});
|
||||
|
||||
export const zLocalInferenceHuggingFaceSearchRequest_unstable = z.object({
|
||||
query: z.string(),
|
||||
limit: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional()
|
||||
});
|
||||
|
||||
export const zLocalInferenceHfGgufFileDto = z.object({
|
||||
filename: z.string(),
|
||||
sizeBytes: z.number().int().gte(0),
|
||||
quantization: z.string(),
|
||||
downloadUrl: z.string()
|
||||
});
|
||||
|
||||
export const zLocalInferenceHfModelVariantDto = z.object({
|
||||
variantId: z.string(),
|
||||
label: z.string(),
|
||||
backendId: z.string(),
|
||||
format: z.string(),
|
||||
modelId: z.string(),
|
||||
downloadId: z.string(),
|
||||
sizeBytes: z.number().int().gte(0),
|
||||
filename: z.union([
|
||||
z.string(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
downloadUrl: z.union([
|
||||
z.string(),
|
||||
z.null()
|
||||
]).optional(),
|
||||
description: z.string(),
|
||||
qualityRank: z.number().int().gte(0).lte(255),
|
||||
sharded: z.boolean(),
|
||||
supported: z.boolean(),
|
||||
unsupportedReason: z.union([
|
||||
z.string(),
|
||||
z.null()
|
||||
]).optional()
|
||||
});
|
||||
|
||||
export const zLocalInferenceHfModelInfoDto = z.object({
|
||||
repoId: z.string(),
|
||||
author: z.string(),
|
||||
modelName: z.string(),
|
||||
downloads: z.number().int().gte(0),
|
||||
ggufFiles: z.array(zLocalInferenceHfGgufFileDto).optional().default([]),
|
||||
variants: z.array(zLocalInferenceHfModelVariantDto).optional().default([])
|
||||
});
|
||||
|
||||
export const zLocalInferenceHuggingFaceSearchResponse_unstable = z.object({
|
||||
models: z.array(zLocalInferenceHfModelInfoDto)
|
||||
});
|
||||
|
||||
export const zLocalInferenceHuggingFaceRepoVariantsRequest_unstable = z.object({
|
||||
repoId: z.string()
|
||||
});
|
||||
|
||||
export const zLocalInferenceHuggingFaceRepoVariantsResponse_unstable = z.object({
|
||||
variants: z.array(zLocalInferenceHfModelVariantDto),
|
||||
recommendedIndex: z.union([
|
||||
z.number().int().gte(0),
|
||||
z.null()
|
||||
]).optional(),
|
||||
availableMemoryBytes: z.number().int().gte(0),
|
||||
downloadedQuants: z.array(z.string()),
|
||||
downloadedVariants: z.array(z.string())
|
||||
});
|
||||
|
||||
export const zLocalInferenceBuiltinChatTemplatesListRequest_unstable = z.record(z.unknown());
|
||||
|
||||
export const zLocalInferenceBuiltinChatTemplatesListResponse_unstable = z.object({
|
||||
templates: z.array(z.string())
|
||||
});
|
||||
|
||||
/**
|
||||
* Streaming context-window usage update for a session.
|
||||
*/
|
||||
@@ -2545,7 +2840,17 @@ export const zExtRequest = z.object({
|
||||
zDictationModelDownloadProgressRequest_unstable,
|
||||
zDictationModelCancelRequest_unstable,
|
||||
zDictationModelDeleteRequest_unstable,
|
||||
zDictationModelSelectRequest_unstable
|
||||
zDictationModelSelectRequest_unstable,
|
||||
zLocalInferenceModelsListRequest_unstable,
|
||||
zLocalInferenceModelDownloadRequest_unstable,
|
||||
zLocalInferenceModelDownloadProgressRequest_unstable,
|
||||
zLocalInferenceModelDownloadCancelRequest_unstable,
|
||||
zLocalInferenceModelDeleteRequest_unstable,
|
||||
zLocalInferenceModelSettingsReadRequest_unstable,
|
||||
zLocalInferenceModelSettingsUpdateRequest_unstable,
|
||||
zLocalInferenceHuggingFaceSearchRequest_unstable,
|
||||
zLocalInferenceHuggingFaceRepoVariantsRequest_unstable,
|
||||
zLocalInferenceBuiltinChatTemplatesListRequest_unstable
|
||||
]),
|
||||
z.union([
|
||||
z.record(z.unknown()),
|
||||
@@ -2624,7 +2929,15 @@ export const zExtResponse = z.union([
|
||||
zDictationTranscribeResponse_unstable,
|
||||
zDictationConfigResponse_unstable,
|
||||
zDictationModelsListResponse_unstable,
|
||||
zDictationModelDownloadProgressResponse_unstable
|
||||
zDictationModelDownloadProgressResponse_unstable,
|
||||
zLocalInferenceModelsListResponse_unstable,
|
||||
zLocalInferenceModelDownloadResponse_unstable,
|
||||
zLocalInferenceModelDownloadProgressResponse_unstable,
|
||||
zLocalInferenceModelSettingsReadResponse_unstable,
|
||||
zLocalInferenceModelSettingsUpdateResponse_unstable,
|
||||
zLocalInferenceHuggingFaceSearchResponse_unstable,
|
||||
zLocalInferenceHuggingFaceRepoVariantsResponse_unstable,
|
||||
zLocalInferenceBuiltinChatTemplatesListResponse_unstable
|
||||
]),
|
||||
z.unknown()
|
||||
]).optional()
|
||||
|
||||
Reference in New Issue
Block a user