TimeLens 第三方小组件开发指南
本文档介绍 Kernel 与 Gateway 重写后的当前第三方小组件运行时。
当前范围
首批支持沙箱 JavaScript/TypeScript、ESM 入口、createWidget()/mount()、Gateway 查询、待办写入、小组件状态、订阅、本地 API、同意提示、权限撤销、限流、生命周期和审计。v1/v2 清单仍通过兼容适配器可用。
远程分发、Java Host、完整网络/媒体代理尚未提供;client.fetch() 与 client.loadMedia() 是预留 API。
目录与 Manifest v4
widgets/
my-widget/
manifest.json
index.js
assets/{
"manifest_version": "v4",
"widget_type": "sample_hello",
"name": "Sample Hello Widget",
"publisher": "Example Publisher",
"entry": "index.js",
"runtime": { "language": "javascript", "version": "ES2022", "entry": "index.js" },
"ui": { "model": "web-sandbox" },
"capabilities": ["metrics.summary.read"]
}v4 要求版本、唯一类型、名称、发布者、运行时语言/版本/入口、UI 模型和能力数组。当前 JavaScript 加载器还要求顶层 entry,应与 runtime.entry 一致。尺寸、图标、签名、CSP、资源配额、能力说明、请求域名和媒体来源可选。
能力与同意
特权调用统一经过 Widget Gateway。缺少授权时返回可恢复拒绝,Host 展示同意提示;只有用户允许后才重试一次。小组件中心支持撤销单项或全部 Scope。
| Scope | 访问范围 |
|---|---|
screen-time:read | 使用、专注、目标、分类、会话等查询 |
todo:read / todo:write | 读取或修改待办 |
browser:read | 浏览器活动查询 |
settings:write | 写入专注模式 |
local-api:call | 调用带 Scope 的本地 API |
入口与 Context
export function createWidget() {
let root;
return {
async mount(container, context) {
root = document.createElement("div");
root.textContent = `Hello from ${context.widgetType}`;
container.appendChild(root);
console.log(await context.client.query("metrics"));
},
unmount() { root?.remove(); root = null; },
};
}也支持直接导出 mount(container, context) 和可选的 unmount()。Context 包含 widgetId、widgetType、新的 client、兼容用 channel 和生命周期回调。新组件应使用 client,channel 仅用于迁移。
WidgetClient
const metrics = await context.client.query("metrics", { start, end });
const value = await context.client.getState("selected-range");
await context.client.setState("selected-range", "today");
const todo = await context.client.addTodo("Review screen time");
const handle = await context.client.subscribe("focus-started", console.log);
await context.client.unsubscribe(handle);命名空间为 metrics、sessions、categories、projects、tags、goals、rules、focus、todos、browser。本地 API 仍可使用 context.channel.localApiCall({ method, path, scopes })。
错误、生命周期与测试
Gateway 状态包括 success、denied、revoked、throttled、timed_out、degraded、error。WidgetGatewayError 提供 code、scope、recoverable,可用 isConsentRequired() 判断同意失败。请在 unmount 中释放订阅;当前每个实例每分钟最多 60 次 channel 请求。
将目录放入应用数据 widgets,以开发模式启动,打开小组件中心添加并测试同意提示和权限矩阵。开发模式提供“小组件开发调试台”时,可模拟 Gateway 响应并重新加载本地入口。
阅读英文指南 · 参阅 v1/v2 迁移说明 和 src-tauri/widget-contract/manifest-v4.schema.json。
最后更新:2026-08-27 · TimeLens 小组件运行时重写