# Copyright (c) Meta Platforms, Inc. and affiliates. # All rights reserved. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. """Custom Gradio tab for the REPL environment.""" from __future__ import annotations import json from typing import Any, Dict, List, Optional import gradio as gr from openenv.core.env_server.types import EnvironmentMetadata def _code_block(title: str, content: str) -> str: if not content: return "" return f"**{title}:**\n```text\n{content}\n```" def _format_repl_response(data: Dict[str, Any]) -> str: """Render REPL observations in a compact Markdown view.""" observation = data.get("observation", {}) result = observation.get("result", {}) sections: List[str] = ["# REPL Session"] context_preview = observation.get("context_preview") if context_preview: sections.append(_code_block("Context Preview", context_preview)) task_prompt = observation.get("task_prompt") if task_prompt: sections.append(_code_block("Task Prompt", task_prompt)) available_variables = observation.get("available_variables") or [] if available_variables: sections.append( "**Available Variables:** " + ", ".join(f"`{name}`" for name in available_variables) ) if result.get("locals_snapshot"): sections.append( "**Locals Snapshot:**\n```json\n" + json.dumps(result["locals_snapshot"], indent=2, sort_keys=True) + "\n```" ) stdout = result.get("stdout", "") stderr = result.get("stderr", "") sections.append(_code_block("Stdout", stdout)) sections.append(_code_block("Stderr", stderr)) reward = data.get("reward") done = data.get("done") sections.append(f"**Reward:** `{reward}`") sections.append(f"**Done:** `{done}`") return "\n\n".join(section for section in sections if section) def build_repl_gradio_app( web_manager: Any, action_fields: List[Dict[str, Any]], metadata: Optional[EnvironmentMetadata], is_chat_env: bool, title: str, quick_start_md: str, ) -> gr.Blocks: """Build the REPL-specific Gradio tab.""" del action_fields, is_chat_env, metadata, quick_start_md async def reset_repl( context: str, task_prompt: str, hf_token: str, llm_model: str, ): reset_kwargs: Dict[str, Any] = {} if context.strip(): reset_kwargs["context"] = context if task_prompt.strip(): reset_kwargs["task_prompt"] = task_prompt if hf_token.strip(): reset_kwargs["hf_token"] = hf_token if llm_model.strip(): reset_kwargs["llm_model"] = llm_model try: data = await web_manager.reset_environment(reset_kwargs) state = web_manager.get_state() return ( _format_repl_response(data), json.dumps(data, indent=2, sort_keys=True), json.dumps(state, indent=2, sort_keys=True), "REPL reset complete.", ) except Exception as exc: return ("", "", "", f"Error: {exc}") async def run_code(code: str): if not code.strip(): return ("", "", "", "Enter Python code to run.") try: data = await web_manager.step_environment({"code": code}) state = web_manager.get_state() return ( _format_repl_response(data), json.dumps(data, indent=2, sort_keys=True), json.dumps(state, indent=2, sort_keys=True), "Code executed.", ) except Exception as exc: return ("", "", "", f"Error: {exc}") def get_state_sync(): try: return json.dumps(web_manager.get_state(), indent=2, sort_keys=True) except Exception as exc: return f"Error: {exc}" with gr.Blocks(title=f"{title} - REPL") as blocks: gr.Markdown( "# REPL Control Panel\n\n" "Load a problem into the REPL, execute Python, and inspect state without " "leaving the Space." ) with gr.Row(): with gr.Column(scale=2): context = gr.Textbox( label="Context", placeholder="Problem context or source text...", lines=8, ) task_prompt = gr.Textbox( label="Task Prompt", placeholder="What should the agent solve?", lines=3, ) with gr.Accordion("Optional Model Settings", open=False): hf_token = gr.Textbox( label="Hugging Face Token", placeholder="Used only for this reset; not persisted in state", type="password", ) llm_model = gr.Textbox( label="LLM Model", placeholder="Optional override for llm_query / rlm_query", ) code = gr.Textbox( label="Python Code", placeholder="count = len(context.split())", lines=10, ) with gr.Row(): reset_btn = gr.Button("Reset", variant="secondary") run_btn = gr.Button("Run", variant="primary") state_btn = gr.Button("Get state", variant="secondary") status = gr.Textbox(label="Status", interactive=False) with gr.Column(scale=3): session_view = gr.Markdown( value="# REPL Session\n\nReset the environment to start." ) raw_json = gr.Code( label="Raw JSON response", language="json", interactive=False, ) state_json = gr.Code( label="Session state", language="json", interactive=False, ) reset_btn.click( fn=reset_repl, inputs=[context, task_prompt, hf_token, llm_model], outputs=[session_view, raw_json, state_json, status], ) run_btn.click( fn=run_code, inputs=[code], outputs=[session_view, raw_json, state_json, status], ) code.submit( fn=run_code, inputs=[code], outputs=[session_view, raw_json, state_json, status], ) state_btn.click(fn=get_state_sync, outputs=[state_json]) return blocks