name: canvas description: “在连接的Otto节点(Mac应用、iOS、Android)上显示HTML内容。用于游戏、可视化、仪表板和交互式演示。”
Canvas技能
在连接的Otto节点(Mac应用、iOS、Android)上显示HTML内容。
概述
画布工具让您在任何连接节点的画布视图上呈现web内容。适用于:
- 显示游戏、可视化、仪表板
- 展示生成的HTML内容
- 交互式演示
工作原理
架构
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ 画布主机服务器 │────▶│ 节点桥接器 │────▶│ 节点应用 │
│ (HTTP服务器) │ │ (TCP服务器) │ │ (Mac/iOS/ │
│ 端口18793 │ │ 端口18790 │ │ Android) │
└─────────────────┘ └──────────────────┘ └─────────────┘
- 画布主机服务器:从
canvasHost.root目录提供静态HTML/CSS/JS文件 - 节点桥接器:将画布URL通信给连接的节点
- 节点应用:在WebView中渲染内容
Tailscale集成
画布主机服务器基于gateway.bind设置绑定:
| 绑定模式 | 服务器绑定到 | 画布URL使用 |
|---|---|---|
loopback |
127.0.0.1 | localhost(仅本地) |
lan |
LAN接口 | LAN IP地址 |
tailnet |
Tailscale接口 | Tailscale主机名 |
auto |
最佳可用 | Tailscale > LAN > loopback |
关键点: canvasHostHostForBridge源自bridgeHost。当绑定到Tailscale时,节点接收的URL类似:
http://<tailscale-hostname>:18793/__otto__/canvas/<file>.html
这就是为什么localhost URL不工作——节点从桥接器接收Tailscale主机名!
操作
| 操作 | 描述 |
|---|---|
present |
显示画布,可选目标URL |
hide |
隐藏画布 |
navigate |
导航到新URL |
eval |
在画布中执行JavaScript |
snapshot |
捕获画布截图 |
配置
在~/.otto/otto.json中:
{
"canvasHost": {
"enabled": true,
"port": 18793,
"root": "/Users/you/agent/canvas",
"liveReload": true
},
"gateway": {
"bind": "auto"
}
}
实时重载
当liveReload: true(默认)时,画布主机:
- 监视根目录变化(通过chokidar)
- 将WebSocket客户端注入HTML文件
- 文件变化时自动重载连接的画布
适用于开发!
工作流程
1. 创建HTML内容
将文件放入画布根目录(默认~/agent/canvas/):
cat > ~/agent/canvas/my-game.html << 'HTML'
<!DOCTYPE html>
<html>
<head><title>My Game</title></head>
<body>
<h1>Hello Canvas!</h1>
</body>
</html>
HTML
2. 找到您的画布主机URL
检查网关绑定方式:
cat ~/.otto/otto.json | jq '.gateway.bind'
然后构建URL:
- loopback:
http://127.0.0.1:18793/__otto__/canvas/<file>.html - lan/tailnet/auto:
http://<hostname>:18793/__otto__/canvas/<file>.html
找到Tailscale主机名:
tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//'
3. 找到连接的节点
otto nodes list
查找具有画布功能的Mac/iOS/Android节点。
4. 呈现内容
canvas action:present node:<node-id> target:<full-url>
示例:
canvas action:present node:mac-63599bc4-b54d-4392-9048-b97abd58343a target:http://peters-mac-studio-1.sheep-coho.ts.net:18793/__otto__/canvas/snake.html
5. 导航、截图或隐藏
canvas action:navigate node:<node-id> url:<new-url>
canvas action:snapshot node:<node-id>
canvas action:hide node:<node-id>
调试
白屏/内容未加载
原因: 服务器绑定与节点期望的URL不匹配。
调试步骤:
- 检查服务器绑定:
cat ~/.otto/otto.json | jq '.gateway.bind' - 检查画布端口:
lsof -i :18793 - 直接测试URL:
curl http://<hostname>:18793/__otto__/canvas/<file>.html
解决方案: 使用与绑定模式匹配的完整主机名,而不是localhost。
"node required"错误
始终指定node:<node-id>参数。
"node not connected"错误
节点离线。使用otto nodes list查找在线节点。
内容未更新
如果实时重载不工作:
- 检查配置中
liveReload: true - 确保文件在画布根目录
- 检查日志中的监视器错误
URL路径结构
画布主机从/__otto__/canvas/前缀提供内容:
http://<host>:18793/__otto__/canvas/index.html → ~/agent/canvas/index.html
http://<host>:18793/__otto__/canvas/games/snake.html → ~/agent/canvas/games/snake.html
/__otto__/canvas/前缀由CANVAS_HOST_PATH常量定义。
提示
- 保持HTML自包含(内联CSS/JS)以获得最佳效果
- 使用默认index.html作为测试页面(包含桥接诊断)
- 画布持续直到
hide或导航离开 - 实时重载使开发快速——只需保存即可更新!
- A2UI JSON推送正在开发中——暂时使用HTML文件