工作台 Widget 管理
本 skill 负责 Widget 生命周期管理(创建脚手架、查询、验证编译)。编码细节(SDK API、组件写法、安全沙箱)在 generate-dynamic-widget skill 中,需要写代码时先 LoadSkill(skillName: "generate-dynamic-widget")。
工具清单
| 工具 | 职责 | 只读 |
|---|---|---|
WidgetInit |
生成 widget 脚手架目录(~/.openloaf/dynamic-widgets/<id>/) |
否 |
WidgetList |
列出所有已创建的 widget | 是 |
WidgetGet |
读取单个 widget 详情 | 是 |
WidgetCheck |
编译 widget(TypeScript)+ 触发实时预览刷新 | 是 |
GenerateWidget |
Widget 代码生成(详见 generate-dynamic-widget skill) |
否 |
Read |
Widget 代码读取(常驻工具) | 是 |
Edit |
Widget 代码编辑(常驻工具) | 否 |
加载:
Read/Edit始终可用;WidgetInit/WidgetList/WidgetGet/WidgetCheck/GenerateWidget调用前须先ToolSearch(names: "WidgetInit,WidgetList,WidgetGet,WidgetCheck,GenerateWidget")激活 schema。
决策树
用户想要 Widget
├── 已有 Widget?
│ ├── 是 → WidgetList → WidgetGet → Read → 了解现状
│ │ └── 需要改代码 → ToolSearch(names: "generate-dynamic-widget")
│ │ └── Edit → WidgetCheck
│ └── 否 → 创建新 Widget(见下方流程)
└── 只是查询/浏览?
└── WidgetList / WidgetGet 即可
修改 vs 重建决策
当用户想要变更已有 Widget 时:
- 修改现有(Edit):用户说"加个 X 功能"、"改下颜色"、"多显示一个字段" → 在现有代码上增量修改
- 重新创建(WidgetInit):根本性变更,例如从"天气组件"变成"股票行情"、整体架构/布局完全不同 → 新建 Widget 替换
创建新 Widget(必须按顺序)
WidgetInit— 生成脚手架目录- 为什么先 init?因为它创建正确的目录结构(
~/.openloaf/dynamic-widgets/<id>/)、package.json 和类型桩文件。跳过此步直接写文件会导致编译器找不到类型定义。
- 为什么先 init?因为它创建正确的目录结构(
ToolSearch(names: "generate-dynamic-widget")— 加载编码规范Write— 写入 widget.tsx(前端组件)Write— 写入 functions.ts(服务端函数,按需)WidgetCheck— 编译 + 触发实时预览- 为什么最后必须 check?因为它执行 TypeScript 编译并通知前端刷新预览。不调用 check,用户看到的仍是旧内容。
修改已有 Widget
WidgetList→WidgetGet→Read— 定位并读取源码Edit— 精确替换修改WidgetCheck— 编译验证
WidgetCheck 编译失败恢复
当 WidgetCheck 返回编译错误时:
- 读取错误信息 — 关注 TypeScript 错误行号和描述
- 常见错误及修复:
Cannot find module 'xxx'→ widget.tsx 只能 importreact、react/jsx-runtime、@openloaf/widget-sdk,删除禁用的导入Type 'xxx' is not assignable→ 检查 SDK 类型定义,确认 props/state 类型匹配JSX element type does not have any construct→ 检查组件导出是否正确(必须export default)
- 用
Edit修复 → 再次WidgetCheck,直到编译通过
Widget 能力边界
适合做的事情:
- 数据展示(图表、统计卡片、列表)
- 简单交互(按钮、切换、输入框)
- 定时轮询 API 获取数据(通过 functions.ts 服务端函数)
- 静态或低频更新内容(天气、日历、待办、时钟、番茄钟)
不适合做的事情:
- 复杂多页面流程(应使用独立页面)
- 重计算任务(服务端函数有 10 秒超时限制)
- 实时 WebSocket 长连接(沙箱不支持)
- 需要访问本地文件系统的操作(安全沙箱隔离)
关键约束
- Widget 代码目录:
~/.openloaf/dynamic-widgets/<widget-id>/ widget.tsx只能 import:react、react/jsx-runtime、@openloaf/widget-sdkfunctions.ts在 Server 端执行,10 秒超时- 敏感信息(API Key 等)通过 Widget 目录下
.env注入,禁止硬编码