refactor: tighten backend, flows, frontend, tests; push flows to Langflow

This commit is contained in:
Jonas Miederer 2026-09-28 15:58:00 +02:00
parent 6688fb08c6
commit 06ab25fb47
31 changed files with 783 additions and 358 deletions

View file

@ -10,21 +10,20 @@ from __future__ import annotations
import argparse
import json
import sys
import urllib.request
import httpx
def post(api: str, path: str, body: dict) -> dict:
request = urllib.request.Request(
api.rstrip("/") + path,
data=json.dumps(body).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urllib.request.urlopen(request) as response:
return {"status": response.status, "body": json.loads(response.read())}
except urllib.error.HTTPError as exc:
return {"status": exc.code, "body": exc.read().decode()[:2000]}
response = httpx.post(api.rstrip("/") + path, json=body, timeout=60.0)
try:
payload = response.json()
except ValueError:
payload = response.text[:2000]
return {"status": response.status_code, "body": payload}
except httpx.HTTPError as exc:
return {"status": 0, "body": str(exc)[:2000]}
def main() -> int:

View file

@ -0,0 +1,40 @@
"""Push canonical backend/flows/*.json into Langflow via API (no restart)."""
from __future__ import annotations
import asyncio
import json
import os
from pathlib import Path
from app.flows.langflow_client import LangflowClient, LangflowError
from app.settings import settings
async def main() -> None:
base = os.environ.get("LANGFLOW_URL", "http://localhost:7860")
key = settings.langflow_api_key or os.environ.get("LANGFLOW_API_KEY", "")
print(f"Langflow: {base} key_len={len(key)}")
client = LangflowClient(base, api_key=key)
try:
flows = await client.list_flows()
print(f"existing: {len(flows)} flows")
for f in flows[:20]:
print(" -", f.get("name"), f.get("id"))
except LangflowError as exc:
print(f"list failed: {exc}")
return
flows_dir = Path(settings.flows_dir)
for path in sorted(flows_dir.glob("*.json")):
if path.name.startswith("."):
continue
doc = json.loads(path.read_text(encoding="utf-8"))
try:
result = await client.upsert_flow(doc)
print(f"pushed {path.name} id={result.get('id', 'ok')}")
except LangflowError as exc:
print(f"push {path.name} failed: {exc}")
if __name__ == "__main__":
asyncio.run(main())

View file

@ -42,8 +42,28 @@ async def run_sync(flows_dir: Path) -> SyncReport:
session.close()
async def run_full_pass(flows_dir: Path) -> SyncReport:
"""Single orchestration: Langflow pull + file sync (shared with API)."""
reset_engine()
session = Session(get_engine())
try:
lfx = LfxClient(settings.lfx_url, api_key=settings.lfx_api_key or None)
langflow = LangflowClient(settings.langflow_url, api_key=settings.langflow_api_key)
return await sync.sync_full_pass(session, lfx, langflow, flows_dir)
finally:
session.close()
async def main_async(args) -> int:
flows_dir = Path(args.dir or settings.flows_dir)
if args.pull and args.sync:
try:
report = await run_full_pass(flows_dir)
except FileNotFoundError as exc:
print(f"ERROR: {exc}", file=sys.stderr)
return 2
print(report.model_dump_json(indent=2))
return 1 if report.errors else 0
if args.pull:
pulled = await pull_from_langflow(flows_dir)
print(json.dumps(pulled, indent=2, ensure_ascii=False))