("");
+ useEffect(() => {
+ if (!usesLlm || provider !== "lm_studio") {
+ setLoadedModelHint("");
+ setModelLookupStatus("idle");
+ setModelLookupError("");
+ return;
+ }
+ let cancelled = false;
+ setModelLookupStatus("loading");
+ setModelLookupError("");
+ (async () => {
+ try {
+ const res = await crawlApi.listExtractorModels(provider, baseUrl);
+ if (cancelled) return;
+ if (!res.ok) {
+ setModelLookupStatus("error");
+ setModelLookupError(res.error || "모델 조회 실패");
+ return;
+ }
+ const first = res.models?.[0]?.id;
+ if (!first) {
+ setModelLookupStatus("error");
+ setModelLookupError("로드된 모델이 없습니다");
+ return;
+ }
+ setLoadedModelHint(first);
+ setValue("extractor_model", first, { shouldDirty: false });
+ setModelLookupStatus("ok");
+ } catch (e) {
+ if (cancelled) return;
+ setModelLookupStatus("error");
+ setModelLookupError((e as Error).message);
+ }
+ })();
+ return () => {
+ cancelled = true;
+ };
+ }, [provider, baseUrl, usesLlm, setValue]);
const selectedSource = sources.find((s) => s.name === sourceName);
const progress = job?.progress;
const visited = progress?.visited_count ?? 0;
@@ -385,9 +431,30 @@ export default function CrawlPage() {
+ {provider === "lm_studio" &&
+ modelLookupStatus === "loading" && (
+
+ LM Studio 로드 모델 확인 중...
+
+ )}
+ {provider === "lm_studio" &&
+ modelLookupStatus === "ok" &&
+ loadedModelHint && (
+
+ LM Studio 로드 모델: {loadedModelHint}
+
+ )}
+ {provider === "lm_studio" &&
+ modelLookupStatus === "error" && (
+
+ LM Studio 모델 조회 실패: {modelLookupError}
+
+ )}