wire llms, ui tweaks
This commit is contained in:
@@ -148,10 +148,25 @@ async def run_fce(
|
||||
}
|
||||
|
||||
t0 = time.time()
|
||||
notification_text = await mcp.call_tool("passenger", "generate_notification", {"context": context})
|
||||
raw_result = await mcp.call_tool("passenger", "generate_notification", {"context": context})
|
||||
latency = int((time.time() - t0) * 1000)
|
||||
await emit("tool_call_end", tool="generate_notification", latency_ms=latency, is_live=False)
|
||||
|
||||
# Parse structured response (text + provider)
|
||||
llm_provider = "template"
|
||||
if isinstance(raw_result, dict) and "text" in raw_result:
|
||||
notification_text = raw_result["text"]
|
||||
llm_provider = raw_result.get("provider", "unknown")
|
||||
elif isinstance(raw_result, str):
|
||||
try:
|
||||
parsed = json.loads(raw_result)
|
||||
notification_text = parsed.get("text", raw_result)
|
||||
llm_provider = parsed.get("provider", "unknown")
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
notification_text = raw_result
|
||||
else:
|
||||
notification_text = str(raw_result)
|
||||
|
||||
await emit("node_exit", node="synthesize")
|
||||
|
||||
# ── Node 4: Format Output ──
|
||||
@@ -164,14 +179,15 @@ async def run_fce(
|
||||
if airport_status:
|
||||
data_sources.append("faa_status_live")
|
||||
if crew_notes:
|
||||
data_sources.append("get_crew_notes")
|
||||
data_sources.append("crew_notes")
|
||||
|
||||
notification = {
|
||||
"flight_id": flight_id,
|
||||
"type": "DELAY_NOTIFICATION" if status == "DELAYED" else f"{status}_NOTIFICATION",
|
||||
"status": status,
|
||||
"delay_minutes": delay_minutes,
|
||||
"notification_text": notification_text if isinstance(notification_text, str) else str(notification_text),
|
||||
"notification_text": notification_text,
|
||||
"llm_provider": llm_provider,
|
||||
"generated_at": datetime.now(timezone.utc).isoformat(),
|
||||
"data_sources": data_sources,
|
||||
"human_approved": True, # auto-approve in demo
|
||||
|
||||
@@ -242,7 +242,7 @@ async def run_handover(
|
||||
hub_label = ", ".join(target_hubs) if len(target_hubs) < 5 else "ALL HUBS"
|
||||
|
||||
t0 = time.time()
|
||||
brief_text = await mcp.call_tool("ops", "generate_narrative", {
|
||||
raw_result = await mcp.call_tool("ops", "generate_narrative", {
|
||||
"context": {
|
||||
"hub": hub_label,
|
||||
"shift_time": shift_time,
|
||||
@@ -254,6 +254,22 @@ async def run_handover(
|
||||
latency = int((time.time() - t0) * 1000)
|
||||
await emit("tool_call_end", tool="generate_narrative", latency_ms=latency, is_live=False)
|
||||
|
||||
# Parse structured response
|
||||
import json as _json
|
||||
llm_provider = "template"
|
||||
if isinstance(raw_result, dict) and "text" in raw_result:
|
||||
brief_text = raw_result["text"]
|
||||
llm_provider = raw_result.get("provider", "unknown")
|
||||
elif isinstance(raw_result, str):
|
||||
try:
|
||||
parsed = _json.loads(raw_result)
|
||||
brief_text = parsed.get("text", raw_result)
|
||||
llm_provider = parsed.get("provider", "unknown")
|
||||
except (_json.JSONDecodeError, TypeError):
|
||||
brief_text = raw_result
|
||||
else:
|
||||
brief_text = str(raw_result)
|
||||
|
||||
await emit("node_exit", node="synthesize")
|
||||
|
||||
# ── Node 4: Format Output ──
|
||||
@@ -263,7 +279,8 @@ async def run_handover(
|
||||
result = {
|
||||
"type": "HANDOVER_BRIEF",
|
||||
"hubs": target_hubs,
|
||||
"brief_text": brief_text if isinstance(brief_text, str) else str(brief_text),
|
||||
"brief_text": brief_text,
|
||||
"llm_provider": llm_provider,
|
||||
"summary": {
|
||||
"immediate_count": len(immediate),
|
||||
"monitor_count": len(monitor),
|
||||
|
||||
@@ -11,20 +11,38 @@ from typing import Any
|
||||
from fastmcp import Client
|
||||
|
||||
|
||||
# Server configurations for stdio transport
|
||||
SERVERS = {
|
||||
"shared": {
|
||||
def _env() -> dict:
|
||||
"""Forward LLM-related env vars to MCP server subprocesses."""
|
||||
import os
|
||||
|
||||
env = {}
|
||||
for key in (
|
||||
"LLM_PROVIDER", "GROQ_API_KEY", "GROQ_MODEL",
|
||||
"ANTHROPIC_API_KEY", "ANTHROPIC_MODEL",
|
||||
"OPENAI_API_KEY", "OPENAI_BASE_URL", "OPENAI_MODEL",
|
||||
"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_DEFAULT_REGION",
|
||||
"BEDROCK_MODEL_ID", "USE_BEDROCK",
|
||||
"PATH",
|
||||
):
|
||||
val = os.getenv(key)
|
||||
if val:
|
||||
env[key] = val
|
||||
return env
|
||||
|
||||
|
||||
def _server_config(module: str) -> dict:
|
||||
"""Build server config with current env vars (called at connect time, not import time)."""
|
||||
return {
|
||||
"command": "uv",
|
||||
"args": ["run", "python", "-m", "mcp_servers.shared"],
|
||||
},
|
||||
"ops": {
|
||||
"command": "uv",
|
||||
"args": ["run", "python", "-m", "mcp_servers.ops"],
|
||||
},
|
||||
"passenger": {
|
||||
"command": "uv",
|
||||
"args": ["run", "python", "-m", "mcp_servers.passenger"],
|
||||
},
|
||||
"args": ["run", "python", "-m", module],
|
||||
"env": _env(),
|
||||
}
|
||||
|
||||
|
||||
SERVER_MODULES = {
|
||||
"shared": "mcp_servers.shared",
|
||||
"ops": "mcp_servers.ops",
|
||||
"passenger": "mcp_servers.passenger",
|
||||
}
|
||||
|
||||
# Agent profiles — which servers each agent connects to
|
||||
@@ -43,9 +61,9 @@ class MCPMultiClient:
|
||||
async def connect(self, server_names: list[str]) -> None:
|
||||
"""Connect to the specified MCP servers."""
|
||||
for name in server_names:
|
||||
if name not in SERVERS:
|
||||
raise ValueError(f"Unknown server: {name}. Available: {list(SERVERS.keys())}")
|
||||
config = {"mcpServers": {"default": SERVERS[name]}}
|
||||
if name not in SERVER_MODULES:
|
||||
raise ValueError(f"Unknown server: {name}. Available: {list(SERVER_MODULES.keys())}")
|
||||
config = {"mcpServers": {"default": _server_config(SERVER_MODULES[name])}}
|
||||
client = Client(config)
|
||||
await client.__aenter__()
|
||||
self._clients[name] = client
|
||||
|
||||
Reference in New Issue
Block a user