mirror of
https://github.com/rookiestar28/ComfyUI-OpenClaw.git
synced 2026-08-14 00:48:07 +00:00
93 lines
2.8 KiB
Python
93 lines
2.8 KiB
Python
"""
|
|
Preset Service Models (F22).
|
|
"""
|
|
|
|
import json
|
|
import time
|
|
import uuid
|
|
from dataclasses import asdict, dataclass, field
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
try:
|
|
from ..tenant_context import DEFAULT_TENANT_ID, normalize_tenant_id
|
|
except Exception: # pragma: no cover
|
|
DEFAULT_TENANT_ID = "default"
|
|
|
|
def normalize_tenant_id(value, *, field_name="tenant_id"): # type: ignore
|
|
text = str(value or "").strip().lower()
|
|
if not text:
|
|
raise ValueError(f"{field_name} must be non-empty")
|
|
return text
|
|
|
|
|
|
@dataclass
|
|
class Preset:
|
|
"""
|
|
Represents a Moltbot Preset (Local-First).
|
|
Used for prompts, settings, or variations.
|
|
"""
|
|
|
|
id: str
|
|
name: str
|
|
category: str = "general" # e.g., "prompt", "parameters", "full"
|
|
tags: List[str] = field(default_factory=list)
|
|
content: Dict[str, Any] = field(default_factory=dict)
|
|
tenant_id: str = DEFAULT_TENANT_ID
|
|
|
|
created_at: float = field(default_factory=time.time)
|
|
updated_at: float = field(default_factory=time.time)
|
|
|
|
@classmethod
|
|
def new(
|
|
cls,
|
|
name: str,
|
|
content: Dict[str, Any],
|
|
category: str = "general",
|
|
tags: List[str] = None,
|
|
):
|
|
return cls(
|
|
id=str(uuid.uuid4()),
|
|
name=name,
|
|
content=content,
|
|
category=category,
|
|
tags=tags or [],
|
|
tenant_id=DEFAULT_TENANT_ID,
|
|
)
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return asdict(self)
|
|
|
|
def validate_content(self) -> None:
|
|
"""
|
|
Milestone E: Validate content schema based on category.
|
|
Raises ValueError if invalid.
|
|
"""
|
|
if self.category == "prompt":
|
|
# Must have positive/negative prompts
|
|
if not isinstance(self.content, dict):
|
|
raise ValueError("Content must be a JSON object")
|
|
if "positive" not in self.content or "negative" not in self.content:
|
|
raise ValueError(
|
|
"Prompt preset must contain 'positive' and 'negative' fields"
|
|
)
|
|
|
|
elif self.category == "params":
|
|
# Must have 'params' object
|
|
if not isinstance(self.content, dict):
|
|
raise ValueError("Content must be a JSON object")
|
|
if "params" not in self.content or not isinstance(
|
|
self.content["params"], dict
|
|
):
|
|
raise ValueError("Params preset must contain a 'params' dictionary")
|
|
|
|
# 'general' category is freeform, no validation needed
|
|
|
|
@staticmethod
|
|
def from_dict(data: Dict[str, Any]) -> "Preset":
|
|
if "tenant_id" not in data:
|
|
data = dict(data)
|
|
data["tenant_id"] = DEFAULT_TENANT_ID
|
|
preset = Preset(**data)
|
|
preset.tenant_id = normalize_tenant_id(preset.tenant_id, field_name="tenant_id")
|
|
return preset
|