Files
meeting-room/meeting_room/api_client.py
Hermes 99cb5a499b Initial commit: Meeting Room v0.1.0
Multi-agent discussion framework:
- Custom/AutoGen/CrewAI backends
- Multi-provider API (role→model binding)
- Tools system (files, web, commands)
- Markdown scenarios with YAML frontmatter
- Workspace init (meeting-room init)
- Session save (--save)
2026-05-03 08:07:35 +00:00

97 lines
2.5 KiB
Python

"""Universal API client supporting multiple OpenAI-compatible providers."""
import httpx
import json
PROVIDERS = {}
def init_providers(config: dict):
global PROVIDERS
PROVIDERS = config.get("providers", {})
def _get_client(provider_name: str) -> httpx.Client:
p = PROVIDERS.get(provider_name)
if not p:
raise ValueError(f"Unknown provider: {provider_name}")
return httpx.Client(
base_url=p["base_url"],
headers={"Authorization": f"Bearer {p['api_key']}"},
timeout=120.0,
)
def chat(
provider: str,
model: str,
messages: list[dict],
temperature: float = 0.7,
tools: list[dict] | None = None,
) -> dict:
client = _get_client(provider)
payload = {
"model": model,
"messages": messages,
"temperature": temperature,
}
if tools:
payload["tools"] = tools
payload["tool_choice"] = "auto"
resp = client.post("/chat/completions", json=payload)
resp.raise_for_status()
data = resp.json()
message = data["choices"][0]["message"]
result = {
"content": message.get("content") or "",
"tool_calls": None,
}
if message.get("tool_calls"):
result["tool_calls"] = []
for tc in message["tool_calls"]:
result["tool_calls"].append({
"id": tc["id"],
"name": tc["function"]["name"],
"arguments": tc["function"]["arguments"],
})
return result
def chat_stream(
provider: str,
model: str,
messages: list[dict],
temperature: float = 0.7,
) -> str:
client = _get_client(provider)
payload = {
"model": model,
"messages": messages,
"temperature": temperature,
"stream": True,
}
full_text = ""
with client.stream("POST", "/chat/completions", json=payload) as resp:
resp.raise_for_status()
for line in resp.iter_lines():
if not line or not line.startswith("data: "):
continue
data = line[6:]
if data == "[DONE]":
break
try:
chunk = json.loads(data)
delta = chunk["choices"][0]["delta"]
if "content" in delta and delta["content"]:
print(delta["content"], end="", flush=True)
full_text += delta["content"]
except (json.JSONDecodeError, KeyError, IndexError):
continue
print()
return full_text