Add danbooru-mcp auto-start, git sync, status API endpoints, navbar status indicators, and LLM format retry

- app.py: add subprocess import; add _ensure_mcp_repo() to clone/pull
  danbooru-mcp from https://git.liveaodh.com/aodhan/danbooru-mcp into
  tools/danbooru-mcp/ at startup; add ensure_mcp_server_running() which
  calls _ensure_mcp_repo() then starts the Docker container if not running;
  add GET /api/status/comfyui and GET /api/status/mcp health endpoints;
  fix call_llm() to retry up to 3 times on unexpected response format
  (KeyError/IndexError), logging the raw response and prompting the LLM
  to respond with valid JSON before each retry
- templates/layout.html: add ComfyUI and MCP status dot indicators to
  navbar; add polling JS that checks both endpoints on load and every 30s
- static/style.css: add .service-status, .status-dot, .status-ok,
  .status-error, .status-checking styles and status-pulse keyframe animation
- .gitignore: add tools/ to exclude the cloned danbooru-mcp repo
This commit is contained in:
Aodhan Collins
2026-03-03 00:57:27 +00:00
parent 0b8802deb5
commit ae7ba961c1
1194 changed files with 17475 additions and 3268 deletions

View File

@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""
Migration: add lora_weight_min / lora_weight_max to every entity JSON.
For each JSON file in the target directories we:
- Read the existing lora_weight value (default 1.0 if missing)
- Write lora_weight_min = lora_weight (if not already set)
- Write lora_weight_max = lora_weight (if not already set)
- Leave lora_weight in place (the resolver still uses it as a fallback)
Directories processed (skip data/checkpoints — no LoRA weight there):
data/characters/
data/clothing/
data/actions/
data/styles/
data/scenes/
data/detailers/
data/looks/
"""
import glob
import json
import os
import sys
DIRS = [
'data/characters',
'data/clothing',
'data/actions',
'data/styles',
'data/scenes',
'data/detailers',
'data/looks',
]
dry_run = '--dry-run' in sys.argv
updated = 0
skipped = 0
errors = 0
for directory in DIRS:
pattern = os.path.join(directory, '*.json')
for path in sorted(glob.glob(pattern)):
try:
with open(path, 'r', encoding='utf-8') as f:
data = json.load(f)
lora = data.get('lora')
if not isinstance(lora, dict):
skipped += 1
continue
weight = float(lora.get('lora_weight', 1.0))
changed = False
if 'lora_weight_min' not in lora:
lora['lora_weight_min'] = weight
changed = True
if 'lora_weight_max' not in lora:
lora['lora_weight_max'] = weight
changed = True
if changed:
if not dry_run:
with open(path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
f.write('\n')
print(f" [{'DRY' if dry_run else 'OK'}] {path} weight={weight}")
updated += 1
else:
skipped += 1
except Exception as e:
print(f" [ERR] {path}: {e}", file=sys.stderr)
errors += 1
print(f"\nDone. updated={updated} skipped={skipped} errors={errors}")
if dry_run:
print("(dry-run — no files were written)")