feat: add any-model fallback search for civitai, civarchive, and lora_manager_archive

When a model search returns no results for a specific base_model, retry the
same query with base_model_context=None so the provider can match any model.
Fallback matches are marked with any_model_match and base_model_fallback on
the result payload. The UI reports 'Found (Any Model)' when a result came
from this fallback path, and the cancel/progress button styling is tightened
to 16x16px with border-radius.
This commit is contained in:
Dariusz L
2026-06-20 00:53:51 +02:00
parent e66c660dd3
commit 1a4156f00d
4 changed files with 111 additions and 1 deletions
+90
View File
@@ -1337,6 +1337,21 @@ class ModelResolverExtension:
)
return payload
def mark_any_model_fallback(result):
if isinstance(result, list):
return [
mark_any_model_fallback(item)
for item in result
]
if not isinstance(result, dict):
return result
marked = dict(result)
marked["any_model_match"] = True
marked["base_model_fallback"] = True
marked["requested_base_model"] = base_model_context
return marked
def search_local_sources():
source_results = {"popular": None, "model_list": None}
source_found = False
@@ -1521,6 +1536,32 @@ class ModelResolverExtension:
use_html_fallback=civitai_use_html_fallback,
)
log_search_result("civitai", civitai_result)
if not civitai_result and base_model_context:
log_info(
"Search [civitai] retry any model "
+ format_log_fields(
file=filename,
cat=category,
base=base_model_context,
)
)
civitai_result = search_civitai_for_file(
filename,
model_type=category,
base_model_context=None,
session_token=civitai_session_token or None,
candidate_limit=civitai_candidate_limit,
use_trpc_search=civitai_use_trpc_search,
use_html_fallback=civitai_use_html_fallback,
)
log_search_result(
"civitai/any_model",
civitai_result,
)
if civitai_result:
civitai_result = mark_any_model_fallback(
civitai_result
)
if civitai_result:
source_results["civitai"] = civitai_result
source_found = True
@@ -1577,6 +1618,29 @@ class ModelResolverExtension:
limit=civarchive_candidate_limit,
)
log_search_result("civarchive", civarchive_result)
if not civarchive_result and base_model_context:
log_info(
"Search [civarchive] retry any model "
+ format_log_fields(
file=filename,
cat=category,
base=base_model_context,
)
)
civarchive_result = search_civarchive_for_file(
filename,
model_type=category,
base_model_context=None,
limit=civarchive_candidate_limit,
)
log_search_result(
"civarchive/any_model",
civarchive_result,
)
if civarchive_result:
civarchive_result = mark_any_model_fallback(
civarchive_result
)
if civarchive_result:
source_results["civarchive"] = civarchive_result
source_found = True
@@ -1605,6 +1669,32 @@ class ModelResolverExtension:
"lora_manager_archive",
lora_manager_archive_result,
)
if not lora_manager_archive_result and base_model_context:
log_info(
"Search [lora_manager_archive] retry any model "
+ format_log_fields(
file=filename,
cat=category,
base=base_model_context,
)
)
lora_manager_archive_result = (
search_lora_manager_archive_for_file(
filename,
model_type=category,
base_model_context=None,
)
)
log_search_result(
"lora_manager_archive/any_model",
lora_manager_archive_result,
)
if lora_manager_archive_result:
lora_manager_archive_result = (
mark_any_model_fallback(
lora_manager_archive_result
)
)
return (
{
"lora_manager_archive": lora_manager_archive_result
+11
View File
@@ -2237,6 +2237,14 @@
}
#model-resolver-modal .mr-search-result-action-btn.mr-search-progress-cancel,
#model-resolver-modal .mr-missing-detail-pane .mr-search-result-action-btn.mr-search-progress-cancel {
width: 16px;
height: 16px;
min-width: 16px;
min-height: 16px;
max-width: 16px;
max-height: 16px;
flex: 0 0 16px;
border-radius: 5px;
border-color: rgba(255, 120, 112, 0.28);
background: rgba(255, 120, 112, 0.055);
color: #ff8a80;
@@ -2249,6 +2257,9 @@
}
#model-resolver-modal .mr-search-result-action-btn.mr-search-progress-cancel svg,
#model-resolver-modal .mr-missing-detail-pane .mr-search-result-action-btn.mr-search-progress-cancel svg {
width: 9px;
height: 9px;
flex: 0 0 9px;
color: currentColor;
stroke: currentColor;
}
@@ -1623,6 +1623,8 @@ export const resolveDownloadMethods = {
|| null;
const found = this.hasSearchResults(data);
const foundViaAnyModel = this.isAnyModelSearchResult?.(data[source]);
const foundMessage = foundViaAnyModel ? 'Found (Any Model)' : 'Found';
anyFound = anyFound || found;
hadError = hadError || Boolean(sourceError);
state.results = this.mergeSearchResults(state.results, data, {
@@ -1635,7 +1637,7 @@ export const resolveDownloadMethods = {
this.setSourceProgress(state, source, {
status: sourceError ? 'error' : (found ? 'found' : 'none'),
percent: 100,
message: sourceError ? 'Error' : (found ? 'Found' : 'No match'),
message: sourceError ? 'Error' : (found ? foundMessage : 'No match'),
error: sourceError || null
}, missing, { workflowKey });
+7
View File
@@ -556,6 +556,13 @@ export const searchPanelMethods = {
return !!(data.popular || data.model_list || data.huggingface || data.civitai || data.civarchive || data.lora_manager_archive);
},
isAnyModelSearchResult(result) {
if (Array.isArray(result)) {
return result.some(item => this.isAnyModelSearchResult(item));
}
return Boolean(result && typeof result === 'object' && (result.any_model_match || result.base_model_fallback));
},
hasSearchResultsForMissing(missing = {}) {
if (missing?.download_source?.url) return true;
const state = this.searchResultCache?.get(this.getMissingSearchKey(missing));