use std::sync::Arc;
use async_trait::async_trait;
use serde_json::{json, Value};
use crate::error::Result;
use crate::tools::{Tool, ToolContext};
pub struct RenderHtml;
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl Tool for RenderHtml {
fn name(&self) -> &str {
"render_html"
}
fn description(&self) -> &str {
"Render an HTML document onto the visual display (a 256x144 pixel \
framebuffer the user sees). This is a snapshot text renderer, NOT \
a browser: it shows block-level text (h1-h6, p, ul/li, blockquote, \
br) laid out and word-wrapped in a bitmap font, monochrome. It does \
NOT run JavaScript, apply CSS, or load images — headings just get a \
bigger font. Pass the full HTML source as `source`. For an \
interactive or animated app, use `run_cartridge` instead. Tip: pair \
with create_file to save the same HTML as `index.html` if you want \
it to persist."
}
fn input_schema(&self) -> Value {
json!({
"type": "object",
"properties": {
"source": {
"type": "string",
"description": "the HTML document to render"
}
},
"required": ["source"]
})
}
async fn execute(&self, args: Value, _ctx: Option<Arc<ToolContext>>) -> Result<Value> {
let source = args.get("source").and_then(|v| v.as_str()).unwrap_or("");
if source.is_empty() {
return Ok(json!({ "error": "source is required" }));
}
#[cfg(all(target_arch = "wasm32", feature = "browser-app"))]
{
match crate::app::display::render_html(source) {
Ok(()) => Ok(json!({ "status": "rendered on display" })),
Err(err) => Ok(json!({
"error": "render failed",
"detail": format!("{err:?}")
})),
}
}
#[cfg(not(all(target_arch = "wasm32", feature = "browser-app")))]
{
Ok(json!({
"rendered": false,
"note": "the visual display requires the browser app"
}))
}
}
}