Files
agent-dashboard/docs/superpowers/specs/2026-06-02-agent-notify-remote-dashboard-design.md
T
laily 1e7efd9c3b docs: add remote dashboard design spec and implementation plan
Second-phase brainstorming: centralized HTTP server, Web dashboard,
and hook status reporting to replace deprecated local inbox.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 14:24:06 +08:00

7.7 KiB
Raw Blame History

agent-notify 第二期:远端状态仪表盘 设计规格

日期: 2026-06-02
状态: 已批准(brainstorming
目标: 各开发机 Hook 将 Agent 实时状态上报到自托管 HTTP Server,Web 页面按机器、工作目录、Agent 类型分类查看;详情含最后一次用户与 Agent 消息(各 ≤2000 字符)。


1. 背景与目标

第一期(v0.2 inbox)在本地聚合通知记录(inbox serve + SSH RemoteForward + CLI/TUI)。第二期改为中心化远端 Server + Web 仪表盘,满足:

  • 实时状态(非纯事件流):每台机器、每个工作目录、每种 Agent 类型一行当前状态
  • 上报包含 hostname + IP工作目录
  • 详情:从 hook 提供的 transcript 解析最后 user/assistant 各一条,单条最多 2000 字符
  • Web 支持按机器 / 目录 / Agent / 状态 分类筛选
  • 单机自托管,共享 Bearer Token;网络暴露由用户自行配置
  • 弃用本地 inboxHook 默认只报远端;inbox 子命令标记 deprecated,代码下个大版本再删

成功标准

  • agent-notify server 可启动 HTTP 服务(API + 内嵌 Web
  • 各机器配置 [remote] 后,Cursor/Claude hook 在发通知后上报状态,失败不影响 hook 退出码
  • Web 展示所有机器的合并视图,默认按 updated_at 降序;offline 由 server 根据 5 分钟无更新判定
  • 同一 hostname + ip + cwd + agent 仅一条记录,多会话取最近活跃

非目标(第二期)

  • 历史事件流、告警推送
  • 多用户 RBAC、每机器独立 token
  • beforeSubmitPrompt 实时更新 last_user
  • 删除 inbox 源码(仅 deprecated
  • macOS/Windows server 部署文档(实现保持可交叉编译,优先 Linux 验证)

2. 方案选择

方案 描述 结论
A 同仓库 agent-notify server + SQLite + embed Web 选用
B 独立 server 二进制 版本对齐成本高,YAGNI
C 内存态 + JSON 快照 查询与持久化弱

3. 架构

┌─────────────────┐     hook      ┌──────────────────┐
│ Cursor / Claude │ ────────────► │ agent-notify hook │
└─────────────────┘               └────────┬─────────┘
                                         │ OSC 777(不变)
                                         │ POST /api/v1/status
                                         ▼
                              ┌──────────────────────┐
                              │ agent-notify server   │
                              │  SQLite + HTTP API    │
                              │  embed Web (轮询 3s)  │
                              └──────────────────────┘

组件

  1. internal/remote — 状态模型、session_key、HTTP 上报客户端
  2. internal/transcript — 从 transcript_path jsonl 解析最后 user/assistant,截断 2000
  3. internal/hostmetahostname + 非 loopback IP 列表
  4. internal/server — SQLite store、Bearer 中间件、REST handlers、offline 计算
  5. web/ — 静态仪表盘(embed
  6. Hook 改动recordInboxreportRemote[inbox] 默认关闭并 deprecated

4. 数据模型

Session 键(合并规则 C

session_key = SHA256(hostname + "\0" + primary_ip + "\0" + cwd + "\0" + agent)[:32] hex
  • primary_ip:上报 ips 中第一个 IPv4,无则空字符串
  • 同一键 upsert 覆盖,不保留历史行
  • conversation_id 仅存字段,不拆行

状态枚举

status 含义 典型 hook
running Agent 刚产出回复 response
waiting 等待用户输入 stop
tool 工具执行中 tool
idle 长时间空闲 idle
offline 5 分钟无更新 server 计算

上报 JSONPOST /api/v1/status

{
  "hostname": "dev-box",
  "ips": ["192.168.1.10"],
  "agent": "Cursor",
  "cwd": "/home/user/proj",
  "status": "waiting",
  "event": "stop",
  "conversation_id": "uuid",
  "last_user": "…",
  "last_agent": "…",
  "updated_at": "2026-06-02T12:00:00Z"
}
  • last_user / last_agent:可选;有 transcript 时更新,截断 2000;读失败时不覆盖已有字段(server merge:空字符串不覆盖非空列)
  • updated_at:客户端 UTC;server 亦可写入 received_at

SQLite 表 sessions

类型 说明
session_key TEXT PK
hostname TEXT
ips TEXT JSON 数组
agent TEXT
cwd TEXT
status TEXT
event TEXT 最近触发事件名
conversation_id TEXT
last_user TEXT
last_agent TEXT
updated_at TEXT ISO8601
received_at TEXT server 写入

索引:hostname, cwd, agent, updated_at


5. API

方法 路径 鉴权 说明
POST /api/v1/status Bearer Upsert
GET /api/v1/status Bearer 列表;query: host, cwd, agent, status
GET /api/v1/meta Bearer distinct hosts / cwds / agents
GET /healthz 健康检查
GET / Web UI
  • Tokenserver --tokenAGENT_NOTIFY_TOKEN(启动必填)
  • 401:缺失或错误 token

6. Hook 与 Transcript

流程

hook → 通知(不变)→ build report → 解析 transcript(可选)→ POST remote
  • 失败仅 logx.Append,返回码仍为 0
  • 替换 recordInboxcfg.Remote.Enabled 为 false 时跳过上报

事件 → status

event status
stop waiting
response running
tool tool
idle idle

Transcript

  • Cursor stop payloadtranscript_path → 读 jsonl 尾部窗口(最大 256KB)→ 最后 user/assistant
  • Claude:有 path 则同逻辑;无则跳过文本
  • 字段映射:支持 role+content 或 Cursor transcript 常见行格式(实现时以实测样本为准)

机器标识

  • hostnameos.Hostname()
  • ips:网卡非 loopback IPv4(可含 IPv6),去重排序

7. Web UI

  • 内嵌静态页,GET /api/v1/status 每 3s 轮询
  • 侧栏筛选:机器(hostname + ip)、Agent、状态;工作目录可侧栏或下拉
  • 主表列:机器 | 目录(basename,完整路径 title| Agent | 状态 | 更新时间 | 详情展开(last_user / last_agent
  • Token:首次输入存 sessionStorage,请求带 Authorization
  • offline 行样式变灰(由 API 返回 status=offline

8. 配置

[remote]
enabled = true
url = "http://your-server:8080"
token = "shared-secret"
timeout_ms = 2000

[inbox]
enabled = false  # deprecated
  • install 默认写入 [remote] 占位与 [inbox] enabled = false
  • doctor 检查 remote.urlremote.token 非空(enabled 时)

命令

agent-notify server --listen :8080 --db ./agent-notify.db --token "$AGENT_NOTIFY_TOKEN"

inbox 子命令保留,执行时打印 deprecation 警告。


9. 错误处理与测试

场景 行为
远端不可达 log,通知照常
Token 错误 401
Transcript 过大 只读尾部 256KB
同键多次上报 upsert

测试:session_key 稳定、截断 2000、Bearer、offline 5min、hook 失败不影响 RunCursor/RunClaude。


10. 迁移说明

  1. 在自托管机启动 agent-notify server
  2. 各开发机 config.toml 配置 [remote]
  3. 停止依赖 inbox serve / SSH RemoteForward(可选保留至下版本删除)