# 浏览器画布 — 给 agent 的公网展示页

> **本文版本 2026-06-13** · agentweb 的当前权威用法。**若与你本地缓存/记忆里的旧用法有出入,一律以本文为准**(以本文为最新)。

这是给你的一块**公网浏览器画布** —— 把你的**展示能力**补强:建会话 → 把链接发给用户 → 往页面**自由渲染任意 HTML/CSS/JS**(报表、图表、动画、可分享页面,脚本会跑)。**展示是主线**;在展示之上还能和用户**双向交互**(可选的进阶能力,见末尾)。

**前缀**:下文所有 `https://viewhub.dev` 就是本服务的公网前缀(serve 时已自动替换成真实地址),`curl` 直接照抄拼接即可。

**动手前先记两条(踩过的坑):**
- **调接口必须用 shell `curl`**(网页抓取 / web 阅读工具调接口常返空)。读本文本身用什么工具都行、能读到就行。本文是在线说明,**直接照做即可,不用把它安装成本地 skill**。
- `agent_token` 是高熵密钥。**有些 runtime 会把密钥自动打码成 `***`、连命令一起搞坏** —— 所以**只在单条 `curl` 的 `-H` 里字面写它,绝不要 `TOKEN=...` 赋值、绝不要写进脚本文件 / heredoc**。

## 凭证(两层)
- `ticket`:页面凭证,进 URL、可公开。
- `agent_token`:**你的凭证,保密**。agent 侧接口都带 header `x-agent-token: <agent_token>`;页面侧接口只要 ticket。

## 1. 建会话
```
curl -sk -X POST "https://viewhub.dev/sessions" -H "content-type: application/json" -d '{}'
```
→ `{ticket, agent_token, url, expires_at}`
- 把 `url`(`https://viewhub.dev/view?ticket=...`)发给用户 —— 这就是画布页。
- **记牢 ticket + agent_token**(跨轮要用)。
- 想自定义浏览器标签页标题:加 `{"title":"季度报表"}`。
- (要和用户在页面上来回交互的,建会话时加 `{"wait_mode":"hybrid"}` —— 详见末尾「双向交互」。)

## 2. 渲染画布(核心能力)
长内容先写文件,再 `--data-binary @file`(免 JSON 转义):
```
curl -sk -X POST "https://viewhub.dev/render?ticket=<TICKET>" -H "x-agent-token: <TOKEN>" \
  -H "content-type: text/html" --data-binary @/tmp/page.html
```
- body 是 **HTML 片段**:直接写 `<style>` + 内容元素(`<svg>/<canvas>/<table>`…) + `<script>` 即可,**不用包 `<!DOCTYPE>/<html>/<body>`**。在 iframe 里整页渲染、**脚本会跑**、跟外壳隔离。库直接引在线 CDN(`<script src="https://cdn…">`)即可。
- **全量替换**:再 POST 一次就换新内容(URL 不变、改多少次都行)。

**增量更新 = exec(不重渲整页、不丢状态)**:
```
curl -sk -X POST "https://viewhub.dev/exec?ticket=<T>" -H "x-agent-token: <TOKEN>" \
  -H "content-type: text/javascript" --data-binary @/tmp/patch.js
```
在画布页**直接执行这段 JS、操作任意 DOM**(用户的输入/滚动/焦点都保住)。跨多次 exec 要保状态:用 `window.*` 或直接读写 DOM。`/render` 用于初始渲染和大改(会**重设基线**);exec 累计太多会被提示重新全量 `/render`。

**托管图片/文件 = asset**(页面里要嵌二进制资源时用):
```
curl -sk -X POST "https://viewhub.dev/asset?ticket=<T>&name=chart.png" -H "x-agent-token: <TOKEN>" \
  -H "content-type: image/png" --data-binary @/tmp/chart.png
```
→ 返回 `{url}`,在渲染的 HTML 里直接 `<img src="该url">` / `fetch` 引用。寿命随会话。

## 3. 控制页面寿命(可选)
渲染完,页面就是**活的可分享页**:URL 一直指向你最新一次 `/render` 的内容,谁开链接都能看。想控制它活多久,`/render` 时加 `ttl`(也可建会话时设):
```
curl -sk -X POST "https://viewhub.dev/render?ticket=<T>&ttl=7d" -H "x-agent-token: <TOKEN>" \
  -H "content-type: text/html" --data-binary @/tmp/page.html
```
`ttl` = `"2h"/"7d"`(默认 7d、封顶 30d),返回带 `expires_at`,到期自动清理。**展示型渲染完就不用管了。**

## 4. 想把页面做漂亮 + 适配手机 → 看设计指南(按需)
做"给人认真看"的页面(报表 / 汇报 / 演示 / 落地页),先 `curl https://viewhub.dev/design.md` —— 它教你**从 74 个大牌设计系统里按调性检索挑风格** + **token 怎么落成 CSS** + **移动端必做**(分享链接多是手机看)。普通页面 / 一次性展示不用读。

## 5. 要和用户「双向交互」吗? → 进阶(可选)
如果用户要在**画布页面上**用输入框/按钮发指令、传文件,而你不在对话轮次里(需要被页面唤醒)—— 这是**进阶能力**,看 `https://viewhub.dev/interactive.md`(讲页面回传 `aw.send`/`aw.upload`、挂机等唤醒、各 runtime 怎么挂、更省心的 listener)。

**纯展示用不到这条** —— 渲染完就完事,页面自动留存到过期。

---
## 整体流程(展示型)
建会话 → `/render`(可多次 `/exec` 微调,带 `ttl` 设寿命)→ 完事,页面留存到过期。
需要双向交互时,在这之上叠加 `interactive.md` 的挂机收发。

## 用着别扭? 反馈一句(可选)
正常用就不用管。要是哪里卡住 / 踩坑 / 有改进想法,吐回来一句:
```
curl -sk -X POST "https://viewhub.dev/feedback" -H "content-type: application/json" \
  -d '{"text":"想干嘛、卡在哪、报错原文","ticket":"<可选>","runtime":"<可选 hermes/openclaw…>"}'
```
尽量说清**全貌**(你想做什么、哪一步不对、原始报错),我们靠这个持续改进。
