You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
4.1 KiB
137 lines
4.1 KiB
"use client";
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { ModelInputDef, SelectedModel } from "@/types";
|
|
import { ModelParameter, ProviderModel } from "@/lib/providers/types";
|
|
import { useProviderApiKeys } from "@/store/workflowStore";
|
|
|
|
interface ModelSchemaResult {
|
|
parameters: ModelParameter[];
|
|
inputs: ModelInputDef[];
|
|
model?: ProviderModel;
|
|
}
|
|
|
|
interface UseSelectedModelSchemaOptions {
|
|
selectedModel?: SelectedModel;
|
|
enabled?: boolean;
|
|
refreshKey?: number;
|
|
onLoaded?: (schema: ModelSchemaResult) => void;
|
|
}
|
|
|
|
export function useSelectedModelSchema({
|
|
selectedModel,
|
|
enabled = true,
|
|
refreshKey,
|
|
onLoaded,
|
|
}: UseSelectedModelSchemaOptions) {
|
|
const [parameters, setParameters] = useState<ModelParameter[]>([]);
|
|
const [inputs, setInputs] = useState<ModelInputDef[]>([]);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const requestKeyRef = useRef<string | null>(null);
|
|
const abortRef = useRef<AbortController | null>(null);
|
|
const onLoadedRef = useRef(onLoaded);
|
|
const {
|
|
newApiWGBaseUrl,
|
|
geminiApiKey,
|
|
replicateApiKey,
|
|
falApiKey,
|
|
kieApiKey,
|
|
wavespeedApiKey,
|
|
} = useProviderApiKeys();
|
|
|
|
useEffect(() => {
|
|
onLoadedRef.current = onLoaded;
|
|
}, [onLoaded]);
|
|
|
|
useEffect(() => {
|
|
const provider = selectedModel?.provider;
|
|
const modelId = selectedModel?.modelId;
|
|
if (!enabled || !provider || !modelId) {
|
|
if (requestKeyRef.current) {
|
|
requestKeyRef.current = null;
|
|
abortRef.current?.abort();
|
|
setParameters([]);
|
|
setInputs([]);
|
|
setError(null);
|
|
setIsLoading(false);
|
|
onLoadedRef.current?.({ parameters: [], inputs: [] });
|
|
}
|
|
return;
|
|
}
|
|
|
|
const requestKey = `${provider}:${modelId}:${refreshKey ?? 0}`;
|
|
if (requestKeyRef.current === requestKey) return;
|
|
requestKeyRef.current = requestKey;
|
|
abortRef.current?.abort();
|
|
|
|
const controller = new AbortController();
|
|
abortRef.current = controller;
|
|
setIsLoading(true);
|
|
setError(null);
|
|
|
|
const headers: HeadersInit = {};
|
|
if (newApiWGBaseUrl) headers["X-NewApiWG-Base-URL"] = newApiWGBaseUrl;
|
|
if (geminiApiKey) headers["X-Gemini-API-Key"] = geminiApiKey;
|
|
if (replicateApiKey) headers["X-Replicate-Key"] = replicateApiKey;
|
|
if (falApiKey) headers["X-Fal-Key"] = falApiKey;
|
|
if (kieApiKey) headers["X-Kie-Key"] = kieApiKey;
|
|
if (wavespeedApiKey) headers["X-WaveSpeed-Key"] = wavespeedApiKey;
|
|
|
|
fetch(`/api/models/${encodeURIComponent(modelId)}?provider=${provider}`, {
|
|
headers,
|
|
signal: controller.signal,
|
|
})
|
|
.then(async (response) => {
|
|
const data = await response.json().catch(() => ({}));
|
|
if (!response.ok) {
|
|
throw new Error(data.error || `Failed to fetch schema: ${response.status}`);
|
|
}
|
|
if (controller.signal.aborted || requestKeyRef.current !== requestKey) {
|
|
return;
|
|
}
|
|
const nextSchema = {
|
|
parameters: data.parameters || [],
|
|
inputs: data.inputs || [],
|
|
model: data.model,
|
|
};
|
|
setParameters(nextSchema.parameters);
|
|
setInputs(nextSchema.inputs);
|
|
onLoadedRef.current?.(nextSchema);
|
|
})
|
|
.catch((err) => {
|
|
if (controller.signal.aborted || requestKeyRef.current !== requestKey) return;
|
|
setParameters([]);
|
|
setInputs([]);
|
|
setError(err instanceof Error ? err.message : "Failed to fetch schema");
|
|
})
|
|
.finally(() => {
|
|
if (!controller.signal.aborted && requestKeyRef.current === requestKey) {
|
|
setIsLoading(false);
|
|
}
|
|
});
|
|
|
|
return () => {
|
|
if (abortRef.current === controller) {
|
|
controller.abort();
|
|
abortRef.current = null;
|
|
requestKeyRef.current = null;
|
|
} else {
|
|
controller.abort();
|
|
}
|
|
};
|
|
}, [
|
|
enabled,
|
|
selectedModel?.provider,
|
|
selectedModel?.modelId,
|
|
refreshKey,
|
|
newApiWGBaseUrl,
|
|
geminiApiKey,
|
|
replicateApiKey,
|
|
falApiKey,
|
|
kieApiKey,
|
|
wavespeedApiKey,
|
|
]);
|
|
|
|
return { parameters, inputs, isLoading, error };
|
|
}
|
|
|