feat: add Mermaid overlay support for agents to inject positioned diagrams
- Agents can send RenderMermaid with Mermaid source + canvas position to create SVG texture overlays that coexist with other elements - MermaidOverlay struct holds source, rendered SVG, SvgRenderer, and lazy-loaded egui texture at a specific canvas position/size - Server handles rendering via mermaid-rs, parses SVG for dimensions, sends overlay data through DrawingCommand channel to GUI thread - Canvas renders overlays as positioned textures between base SVG and drawing elements, with proper pan/zoom transforms - New MCP tool render_mermaid for agent access - Overlays cleared on undo/redo/checkout to stay consistent with history - 29 tests passing, clippy clean
This commit is contained in:
@@ -187,9 +187,27 @@ pub struct BooleanOpParam {
|
||||
pub stroke_width: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
|
||||
pub struct RenderMermaidParam {
|
||||
#[schemars(description = "Session ID to target. If omitted, uses the active session.")]
|
||||
pub session_id: Option<String>,
|
||||
#[schemars(description = "Mermaid diagram source code (e.g., 'flowchart LR\\n A-->B')")]
|
||||
pub mermaid_source: String,
|
||||
#[schemars(description = "X position on canvas (default: 0)")]
|
||||
pub x: Option<f32>,
|
||||
#[schemars(description = "Y position on canvas (default: 0)")]
|
||||
pub y: Option<f32>,
|
||||
#[schemars(description = "Override width (default: natural SVG width)")]
|
||||
pub width: Option<f32>,
|
||||
#[schemars(description = "Override height (default: natural SVG height)")]
|
||||
pub height: Option<f32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, schemars::JsonSchema)]
|
||||
pub struct BatchParam {
|
||||
#[schemars(description = "JSON array of request objects. Each object must have a 'type' field and the same parameters as individual tool calls. Example: [{\"type\": \"CreateDrawingElement\", \"shape_type\": \"rectangle\", \"x\": 0, \"y\": 0, \"width\": 100, \"height\": 100}, {\"type\": \"CreateDrawingElement\", \"shape_type\": \"ellipse\", \"center_x\": 200, \"center_y\": 200, \"radius_x\": 50, \"radius_y\": 50}]")]
|
||||
#[schemars(
|
||||
description = "JSON array of request objects. Each object must have a 'type' field and the same parameters as individual tool calls. Example: [{\"type\": \"CreateDrawingElement\", \"shape_type\": \"rectangle\", \"x\": 0, \"y\": 0, \"width\": 100, \"height\": 100}, {\"type\": \"CreateDrawingElement\", \"shape_type\": \"ellipse\", \"center_x\": 200, \"center_y\": 200, \"radius_x\": 50, \"radius_y\": 50}]"
|
||||
)]
|
||||
pub requests_json: String,
|
||||
}
|
||||
|
||||
@@ -527,6 +545,26 @@ impl AgCanvasServer {
|
||||
self.call_agcanvas(&request).await
|
||||
}
|
||||
|
||||
#[tool(
|
||||
name = "render_mermaid",
|
||||
description = "Render a Mermaid diagram (flowchart, sequence, etc.) as an SVG overlay at a specific position on the canvas. The diagram appears as a visual element that can coexist with other shapes and diagrams."
|
||||
)]
|
||||
async fn render_mermaid(
|
||||
&self,
|
||||
Parameters(params): Parameters<RenderMermaidParam>,
|
||||
) -> Result<CallToolResult, McpError> {
|
||||
let request = serde_json::json!({
|
||||
"type": "RenderMermaid",
|
||||
"session_id": params.session_id,
|
||||
"mermaid_source": params.mermaid_source,
|
||||
"x": params.x,
|
||||
"y": params.y,
|
||||
"width": params.width,
|
||||
"height": params.height,
|
||||
});
|
||||
self.call_agcanvas(&request).await
|
||||
}
|
||||
|
||||
#[tool(
|
||||
description = "Send multiple Augmented Canvas operations in one request. Accepts a JSON array of request objects and returns one response per operation in a BatchResult."
|
||||
)]
|
||||
|
||||
Reference in New Issue
Block a user