mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-07-03 07:51:16 -03:00
feat(agent): add LLM-powered metadata enrichment system with AgentCLI and PostProcessor
Introduce an agent skill framework for LLM-driven metadata enrichment: - AgentCLI (py/agent_cli/): in-process wrappers around internal services using standard relative imports, eliminating the need for sys.path hacks - LLMService: centralized BYOK (bring-your-own-key) LLM client supporting OpenAI, Ollama, and custom OpenAI-compatible endpoints - PostProcessor: deterministic engine that applies LLM output via AgentCLI (replaces old handler.py + _BASE_MODEL_ALIASES approach) - SkillRegistry: filesystem-based skill discovery (skill.yaml + prompt.md) - AgentService: orchestrates skill execution with WebSocket progress - Frontend AgentManager: WebSocket listeners, skill execution, config UI - Context menu entries (single + bulk) for "Enrich Metadata (Agent)" - Settings UI for AI Provider configuration (BYOK) - Full i18n support across 9 locales Bug fixes found during review: - aiohttp.web.json_response: status_code= -> status= - settings_modal cancelEditApiKey: wrong argument position - AgentManager.isLlmConfigured: allow Ollama without API key - PostProcessor._merge_tags: lowercase all tags to match TagUpdateService
This commit is contained in:
91
tests/services/test_skill_registry.py
Normal file
91
tests/services/test_skill_registry.py
Normal file
@@ -0,0 +1,91 @@
|
||||
"""Tests for the SkillRegistry."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from py.services.agent.skill_registry import SkillRegistry
|
||||
from py.services.agent.skill_definition import SkillDefinition, SkillPermissions
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def registry():
|
||||
"""Create a SkillRegistry with the real skills directory."""
|
||||
SkillRegistry.reset_instance()
|
||||
reg = SkillRegistry()
|
||||
reg._discover()
|
||||
return reg
|
||||
|
||||
|
||||
class TestSkillRegistryDiscovery:
|
||||
def test_discovers_enrich_hf_metadata_skill(self, registry):
|
||||
skills = registry.list_skills()
|
||||
assert len(skills) >= 1
|
||||
skill = registry.get_skill("enrich_hf_metadata")
|
||||
assert skill is not None
|
||||
assert skill.name == "enrich_hf_metadata"
|
||||
assert skill.llm_required is True
|
||||
|
||||
def test_skill_has_correct_model_type_filter(self, registry):
|
||||
skill = registry.get_skill("enrich_hf_metadata")
|
||||
assert skill.model_type_filter == ["lora", "checkpoint", "embedding"]
|
||||
|
||||
def test_skill_has_permissions(self, registry):
|
||||
skill = registry.get_skill("enrich_hf_metadata")
|
||||
assert skill.permissions.write_metadata is True
|
||||
assert skill.permissions.write_previews is True
|
||||
assert "huggingface.co" in skill.permissions.network_domains
|
||||
|
||||
def test_get_skill_returns_none_for_unknown(self, registry):
|
||||
assert registry.get_skill("nonexistent_skill") is None
|
||||
|
||||
|
||||
class TestSkillRegistryLoading:
|
||||
def test_load_prompt_returns_content(self, registry):
|
||||
prompt = registry.load_prompt("enrich_hf_metadata")
|
||||
assert isinstance(prompt, str)
|
||||
assert len(prompt) > 100
|
||||
assert "base_model" in prompt
|
||||
assert "trigger_words" in prompt
|
||||
|
||||
def test_load_prompt_raises_for_unknown_skill(self, registry):
|
||||
with pytest.raises(FileNotFoundError):
|
||||
registry.load_prompt("nonexistent")
|
||||
|
||||
def test_load_handler_raises_when_handler_missing(self, registry):
|
||||
with pytest.raises(FileNotFoundError):
|
||||
registry.load_handler("enrich_hf_metadata")
|
||||
|
||||
|
||||
class TestSkillDefinition:
|
||||
def test_applies_to_model_type_with_filter(self):
|
||||
sd = SkillDefinition(
|
||||
name="test",
|
||||
title="Test",
|
||||
description="",
|
||||
llm_required=False,
|
||||
model_type_filter=["lora"],
|
||||
)
|
||||
assert sd.applies_to_model_type("lora") is True
|
||||
assert sd.applies_to_model_type("checkpoint") is False
|
||||
|
||||
def test_applies_to_model_type_without_filter(self):
|
||||
sd = SkillDefinition(
|
||||
name="test",
|
||||
title="Test",
|
||||
description="",
|
||||
llm_required=False,
|
||||
model_type_filter=None,
|
||||
)
|
||||
assert sd.applies_to_model_type("lora") is True
|
||||
assert sd.applies_to_model_type("checkpoint") is True
|
||||
|
||||
|
||||
class TestSkillPermissions:
|
||||
def test_defaults(self):
|
||||
sp = SkillPermissions()
|
||||
assert sp.write_metadata is True
|
||||
assert sp.write_previews is True
|
||||
assert sp.network_domains == ()
|
||||
Reference in New Issue
Block a user