agent-interact

Installation
SKILL.md

Agent Interact

核心原则:任何需要用户看到、确认、或输入的内容,都应该通过本 Skill 弹出可视化窗口。 不要把重要信息埋在终端输出中——用户可能看不到。

为 AI Agent 提供可视化的用户交互能力。交互弹框通过 pywebview(系统 WKWebView)独立窗口弹出,置顶显示在屏幕最前面。所有 dialog 关闭后服务自动退出,无需手动 stop。

快速开始

# 安装(安装依赖 + 构建前端)
node skills/agent-interact/tool.js install

# 全局安装(复制到 ~/.cursor/skills/ + 安装依赖 + 构建)
node skills/agent-interact/tool.js install '{"target":"~/.cursor/skills/agent-interact"}'

# 更新(从源码覆盖 + 清理重装 + 重新构建)
node skills/agent-interact/tool.js update '{"target":"~/.cursor/skills/agent-interact"}'

# 启动服务(同时启动 Electron)
node skills/agent-interact/tool.js start

# 发送弹框(Electron 窗口自动弹出)
node skills/agent-interact/tool.js dialog '{"type":"confirm","title":"选择环境","options":[{"id":"dev","label":"开发"},{"id":"prod","label":"生产"}]}'

CLI 命令

node skills/agent-interact/tool.js start          # 启动服务 + Electron
node skills/agent-interact/tool.js stop           # 停止服务 + Electron
node skills/agent-interact/tool.js status         # 检查服务和 Electron 状态
node skills/agent-interact/tool.js dialog '<JSON>' # 发送弹框(Electron 窗口自动弹出)

交互类型(7 种预定义 + custom 通用渲染)

confirm — 确认选择

node skills/agent-interact/tool.js dialog '{"type":"confirm","title":"请选择","options":[{"id":"a","label":"选项A"},{"id":"b","label":"选项B"}]}'

wait — 等待操作

node skills/agent-interact/tool.js dialog '{"type":"wait","title":"等待验证","message":"请完成指纹验证后点击确认","confirmText":"已完成"}'

chart — 图表展示

支持 line/bar/pie/doughnut/radar。

node skills/agent-interact/tool.js dialog '{"type":"chart","title":"分析","chartType":"line","data":{"labels":["Mon","Tue","Wed"],"datasets":[{"label":"P99","data":[120,150,90]}]}}'

notification — 通知提醒(非阻塞)

推送通知后立即返回,不等待用户响应。

node skills/agent-interact/tool.js dialog '{"type":"notification","level":"success","title":"部署完成","message":"v2.0 已部署","autoClose":5}'

form — 表单输入

Agent 需要用户填写结构化数据。

node skills/agent-interact/tool.js dialog '{"type":"form","title":"数据库配置","fields":[{"id":"host","label":"主机","type":"text","default":"localhost"},{"id":"port","label":"端口","type":"number","default":5432},{"id":"db","label":"数据库","type":"select","options":["postgres","mysql"]}]}'

approval — 审批门控

Agent 执行敏感操作前需要用户审批。

node skills/agent-interact/tool.js dialog '{"type":"approval","title":"确认删除","message":"即将删除 production 数据库","severity":"critical","details":{"action":"DROP TABLE","database":"production"}}'

progress — 进度展示

展示多步骤任务的实时进度。

node skills/agent-interact/tool.js dialog '{"type":"progress","title":"部署进度","steps":[{"id":"build","label":"构建","status":"completed"},{"id":"test","label":"测试","status":"running"},{"id":"deploy","label":"部署","status":"pending"}],"percent":45}'

custom — 通用渲染(自由编排)

当预定义类型无法满足需求时,使用 custom 类型自由编排弹框内容。通过 JSON 描述 content 数组,前端动态递归渲染。

顶层结构

{
  "type": "custom",
  "title": "标题",
  "content": [ /* CustomNode 数组 */ ],
  "actions": [ /* 按钮数组,可选 */ ]
}

组件属性速查表

展示类:

kind 必填属性 可选属性
text value: string
heading value: string level: 1|2|3|4
divider
alert value: string level: "info"|"warning"|"error"|"success"
badge value: string variant: "default"|"success"|"warning"|"error"
code value: string language: string
image src: string(仅 https) alt: string
kv items: [{key, value}]
progress percent: number label: string

数据类:

kind 必填属性 可选属性
table columns: string[], rows: string[][] sortable: boolean
chart chartType: "line"|"bar"|"pie"|"doughnut"|"radar", data: {labels, datasets}

输入类(id 必填,数据随 action 提交):

kind 必填属性 可选属性
input id, label required, placeholder, default
textarea id, label required, placeholder, default
select id, label, options: string[] required, default
checkbox id, label default: boolean

布局类(通过 children 嵌套其他组件):

kind 必填属性 可选属性
row children: CustomNode[] gap: "sm"|"md"|"lg"
column children: CustomNode[] gap: "sm"|"md"|"lg"
grid children: CustomNode[] columns: 2|3|4, gap: "sm"|"md"|"lg"
section children: CustomNode[] title: string
group children: CustomNode[]

actions 字段

字段 默认值 说明
id 按钮标识(必填)
label 按钮文本(必填)
variant "default" "default"|"destructive"|"outline"|"secondary"|"ghost"
submit true 是否提交表单数据
requireValid false 是否要求输入校验通过才能提交
closeOnSubmit true 提交后是否关闭弹框

响应协议(用户点击按钮后返回):

{
  "dialogId": "d-xxx",
  "action": "按钮id",
  "data": { "输入字段id": "用户输入值" },
  "valid": true,
  "errors": []
}

示例 1:部署确认(alert + kv + input)

node skills/agent-interact/tool.js dialog '{"type":"custom","title":"确认部署到生产环境","content":[{"kind":"alert","value":"即将部署到生产环境,请仔细确认","level":"error"},{"kind":"kv","items":[{"key":"版本","value":"v2.3.1"},{"key":"分支","value":"release/2.3.1"},{"key":"变更文件","value":"23 个"}]},{"kind":"divider"},{"kind":"input","id":"reason","label":"部署原因","placeholder":"请输入部署原因(必填)","required":true}],"actions":[{"id":"deploy","label":"确认部署","variant":"destructive","submit":true,"requireValid":true},{"id":"cancel","label":"取消","variant":"outline","submit":false}]}'

示例 2:API 分析报告(table + chart + text)

node skills/agent-interact/tool.js dialog '{"type":"custom","title":"API 性能分析","content":[{"kind":"alert","value":"检测到 2 个端点响应时间异常","level":"warning"},{"kind":"table","columns":["端点","P50 (ms)","P99 (ms)","错误率"],"rows":[["/api/users","45","320","0.1%"],["/api/orders","120","890","2.3%"],["/api/products","30","95","0%"]]},{"kind":"chart","chartType":"bar","data":{"labels":["/api/users","/api/orders","/api/products"],"datasets":[{"label":"P99 (ms)","data":[320,890,95]}]}},{"kind":"divider"},{"kind":"text","value":"建议:/api/orders 的 P99 接近 1 秒,建议检查数据库查询和 N+1 问题。"}],"actions":[{"id":"optimize","label":"开始优化"},{"id":"later","label":"稍后处理","variant":"outline"}]}'

示例 3:数据对比(heading + group + badge)

node skills/agent-interact/tool.js dialog '{"type":"custom","title":"优化前后对比","content":[{"kind":"heading","value":"优化前","level":3},{"kind":"group","children":[{"kind":"badge","value":"P50: 120ms","variant":"warning"},{"kind":"badge","value":"P99: 890ms","variant":"error"},{"kind":"badge","value":"错误率: 2.3%","variant":"error"}]},{"kind":"heading","value":"优化后","level":3},{"kind":"group","children":[{"kind":"badge","value":"P50: 45ms","variant":"success"},{"kind":"badge","value":"P99: 150ms","variant":"success"},{"kind":"badge","value":"错误率: 0.1%","variant":"success"}]},{"kind":"divider"},{"kind":"text","value":"优化措施:添加了数据库索引,启用了查询缓存。"}],"actions":[{"id":"ok","label":"了解"}]}'

Schema 校验:服务端使用 Ajv 严格校验,未知 kind 或格式错误直接返回 400 + 错误路径。收到 400 时仅修正报错路径字段,不重写整份 JSON。

性能限制content 最多 40 项,嵌套深度 ≤ 4,表格 ≤ 200 行,图表 ≤ 1000 点。

HTTP API

Agent 也可以直接调用 REST API:

  • POST http://127.0.0.1:7890/api/dialog — 创建弹框(阻塞直到用户响应)
  • GET http://127.0.0.1:7890/api/status — 服务状态
  • GET http://127.0.0.1:7890/api/dialogs — 活跃弹框列表
  • DELETE http://127.0.0.1:7890/api/dialog/:id — 取消弹框

强制使用场景(必须弹框)

以下场景中,必须使用 agent-interact 弹框,不允许仅在终端输出:

场景 类型 为什么必须弹框
任务完成,需要展示结果报告 custom/notification 用户可能不在看终端,弹窗确保看到
存在多个方案需要用户选择 confirm 终端选择体验差,弹窗更直观
即将执行不可逆/高风险操作 approval 必须确保用户明确知情并确认
需要用户填写多个参数 form 结构化表单比终端问答更高效
需要用户在外部系统操作后继续 wait 弹窗置顶提醒用户回来确认
数据分析完成,有图表/表格要展示 chart/custom 可视化数据必须用窗口展示
多步骤任务进行中 progress 实时进度条比终端日志更清晰
需要用户审阅优化建议并决策 custom 对比展示 + 选择按钮

典型触发时机

  • 部署完成后 → notification(成功/失败通知)
  • 分析完成后 → custom(结果报告 + 图表 + 建议)
  • 发现多个选项时 → confirm(让用户选择)
  • 需要参数时 → form(收集结构化输入)
  • 执行危险操作前 → approval(审批门控)
  • 回放优化建议生成后 → custom(展示优化项 + 应用/跳过按钮)
  • 长任务执行中 → progress(实时进度更新)

不应弹框的情况

  • 能自动判断的不要问用户(如只有一个选项)
  • 不要每一步都弹框确认(过度交互)
  • 低风险操作不要用 approval(用 confirm 或直接执行)
  • 需要多字段输入时不要用 confirm(用 form)
  • 简单的一句话回复不需要弹框(直接在对话中回复即可)

窗口行为

  • 弹出方式:pywebview(系统 WKWebView)独立窗口,置顶显示
  • 关闭行为:用户操作后窗口自动关闭;所有 dialog 关闭后服务进程自动退出
  • notification:走系统原生通知(osascript),不弹窗口
  • 自动退出:最后一个 dialog 关闭后 500ms,服务和 pywebview 进程自动终止

技术栈

  • 窗口:pywebview(系统 WKWebView,约 5MB)
  • 后端:Node.js + Express + ws
  • 前端:Vite + Vue 3 + TypeScript + shadcn-vue + Tailwind CSS v4
  • 图表:Chart.js + vue-chartjs
Related skills
Installs
1
GitHub Stars
4
First Seen
Apr 7, 2026