eptan's picture
Upload folder using huggingface_hub
19da990 verified
"""
FastAPI application for the CrisisInbox Environment.
Usage:
uvicorn server.app:app --reload --host 0.0.0.0 --port 8000
uv run --project . server
"""
import json as _json
from typing import Any, Dict, Union
from pydantic import Field
from openenv.core.env_server.http_server import create_app
from openenv.core.env_server.mcp_types import (
CallToolAction,
CallToolObservation,
ListToolsAction,
)
from openenv.core.env_server.types import Action
try:
from .crisis_inbox_environment import CrisisInboxEnvironment
except ImportError:
from server.crisis_inbox_environment import CrisisInboxEnvironment
class MCPAction(Action):
"""Action class that deserializes both ListToolsAction and CallToolAction.
Exposes tool_name and arguments fields so the OpenEnv web UI renders
an interactive form. Also routes ListToolsAction via model_validate
for programmatic clients.
"""
model_config = Action.model_config.copy()
model_config["extra"] = "allow"
type: str = Field(default="call_tool", description="Action type: 'call_tool' or 'list_tools'")
tool_name: str = Field(
default="get_inbox",
description="Tool to call: get_inbox, read_message, respond_to_message, get_status, advance_time",
)
arguments: Dict[str, Any] = Field(
default_factory=dict,
description='Tool arguments as JSON (e.g. {"message_id": "msg_001"} or {"message_id": "msg_001", "response": "On my way"})',
)
@classmethod
def model_validate(cls, obj: Any, **kwargs: Any) -> Action:
if isinstance(obj, dict):
action_type = obj.get("type", "")
if action_type == "list_tools":
return ListToolsAction(**obj)
# Parse arguments if the web UI sent them as a JSON string
args = obj.get("arguments", {})
if isinstance(args, str):
try:
obj = {**obj, "arguments": _json.loads(args) if args.strip() else {}}
except _json.JSONDecodeError:
obj = {**obj, "arguments": {}}
if action_type == "call_tool" or "tool_name" in obj:
obj.setdefault("type", "call_tool")
return CallToolAction(**{k: v for k, v in obj.items()
if k in ("type", "tool_name", "arguments", "metadata")})
return super().model_validate(obj, **kwargs)
app = create_app(
CrisisInboxEnvironment,
MCPAction,
CallToolObservation,
env_name="crisis_inbox",
)
# Mount Gradio demo UI at /demo
try:
import gradio as gr
from server.demo_ui import build_demo
except ImportError:
try:
from .demo_ui import build_demo
import gradio as gr
except ImportError:
build_demo = None
if build_demo is not None:
demo = build_demo()
app = gr.mount_gradio_app(app, demo, path="/demo")
def main(host: str = "0.0.0.0", port: int = 8000):
import uvicorn
uvicorn.run(app, host=host, port=port)
if __name__ == "__main__":
main()