refactor(synapse): backend updates, add icons module, relocate playbooks to data/playbooks

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jon
2026-07-11 07:25:08 -05:00
parent 3ec57f9140
commit f4f77c5196
24 changed files with 1820 additions and 288 deletions
Regular → Executable
+12 -42
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import asyncio
import json as _json
import logging
import threading
from typing import AsyncGenerator, Dict, List, Optional, Any
@@ -58,6 +59,7 @@ async def generate_chat_response(
system = metadata.get("system", "")
model = metadata.get("model") or "mistral"
temperature = metadata.get("temperature")
num_gpu = metadata.get("num_gpu")
messages: List[Dict[str, str]] = []
if system:
@@ -76,10 +78,11 @@ async def generate_chat_response(
try:
result = await asyncio.wait_for(
manager.chat(messages=messages, model=model, stream=False, temperature=temperature),
manager.chat(messages=messages, model=model, stream=False, temperature=temperature, num_gpu=num_gpu),
timeout=timeout,
)
response_text = result if isinstance(result, str) else str(result)
preview = response_text[:500].replace("\n", " ")
_synapse_trace(f"{preview}{'' if len(response_text) > 500 else ''}\n{'' * 50}\n")
_logger.info("generate_chat_response: completed model=%s", model)
@@ -115,30 +118,12 @@ async def _aiter_with_timeout(aiterable, timeout: Optional[float]):
# Normalizer for many return shapes
# -------------------------
async def _normalize_to_async_generator(maybe_iterable) -> AsyncGenerator[str, None]:
if hasattr(maybe_iterable, "__aiter__"):
async for item in maybe_iterable:
yield str(item)
return
if asyncio.iscoroutine(maybe_iterable):
result = await maybe_iterable
if hasattr(result, "__aiter__"):
async for item in result:
yield str(item)
return
if hasattr(result, "__iter__") and not isinstance(result, (str, bytes)):
for item in result:
yield str(item)
return
yield str(result)
return
if hasattr(maybe_iterable, "__iter__") and not isinstance(maybe_iterable, (str, bytes)):
for item in maybe_iterable:
yield str(item)
return
yield str(maybe_iterable)
# The sole caller passes manager.chat(stream=True) — an async-def call, i.e.
# a coroutine that resolves to an async generator. Await it if needed, then
# stream the tokens.
result = await maybe_iterable if asyncio.iscoroutine(maybe_iterable) else maybe_iterable
async for item in result:
yield str(item)
# -------------------------
@@ -157,6 +142,7 @@ async def stream_chat_response(
system = metadata.get("system", "")
model = metadata.get("model") or "mistral"
temperature = metadata.get("temperature")
num_gpu = metadata.get("num_gpu")
# Build messages array for /api/chat multi-turn format
messages: List[Dict[str, str]] = []
@@ -175,7 +161,7 @@ async def stream_chat_response(
_synapse_trace(f"USR: {user_message}\n{'' * 50}\n")
try:
maybe_iter = manager.chat(messages=messages, model=model, stream=True, temperature=temperature)
maybe_iter = manager.chat(messages=messages, model=model, stream=True, temperature=temperature, num_gpu=num_gpu)
async_gen = _normalize_to_async_generator(maybe_iter)
buffer_parts: list[str] = []
@@ -224,19 +210,3 @@ async def stream_chat_response(
except Exception:
_logger.exception("stream_chat_response: unexpected error during streaming")
raise
# -------------------------
# Synchronous convenience wrappers
# -------------------------
def generate_chat_response_sync(user_message: str, metadata: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None) -> Dict[str, Any]:
return asyncio.run(generate_chat_response(user_message, metadata=metadata, timeout=timeout))
def stream_chat_response_sync(user_message: str, metadata: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None):
async def _collect():
chunks = []
async for c in stream_chat_response(user_message, metadata=metadata, timeout=timeout):
chunks.append(c)
return chunks
return asyncio.run(_collect())