refactor: tighten backend, flows, frontend, tests; push flows to Langflow
This commit is contained in:
parent
6688fb08c6
commit
06ab25fb47
31 changed files with 783 additions and 358 deletions
|
|
@ -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:
|
||||
|
|
|
|||
40
backend/scripts/push_flows_to_langflow.py
Normal file
40
backend/scripts/push_flows_to_langflow.py
Normal 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())
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue