@xiongtao.xt/tau-plugins 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/SYNC.md CHANGED
@@ -1,37 +1,37 @@
1
- # 同步存储插件
2
-
3
- 需要 SDK 0.10.0 及以上,以及包含渲染端同步注册支持的 Tau 0.59.0 客户端构建。插件只在渲染进程执行,沿用main.js入口,不声明manifest.sync,也不提供Node后台产物。
4
-
5
- ## 注册与职责
6
-
7
- 在activate(context)中调用context.sync.register({ id: context.pluginId, name, create })。一个插件注册一个提供方,create(config)根据本次任务的JSON配置返回下列五个方法;停用或激活失败时注册自动回收。create在真正发起任务时调用,打开配置页不会连接存储服务。
8
-
9
- | 方法 | 返回值 | 用途 |
10
- | ------------------------------- | ------------------------- | ---------------------------------------------------- |
11
- | uploadFile(name, bytes) | Promise<boolean> | 普通上传 |
12
- | downloadFile(name) | Promise<Uint8Array> | 读取对象 |
13
- | fileExists(name) | Promise<boolean> | 检查对象是否存在 |
14
- | listFiles(prefix?) | Promise<RemoteFileInfo[]> | 内部完成分页,返回相对路径、名称、大小及可选修改时间 |
15
- | createFileIfAbsent(name, bytes) | Promise<boolean> | 按远端原子条件创建对象 |
16
-
17
- SyncProvider、SyncProviderDefinition和RemoteFileInfo类型从@tau/plugins/sync导入。该模块仅提供纯契约与声明辅助函数,不是Node执行入口。
18
-
19
- 客户端负责同步内容、对象命名、版本提交、冲突、资源计划和恢复。插件负责存储服务请求,不增加能力声明、服务商探测或独立同步引擎。条件创建不能用先查询再覆盖替代;请求失败后由客户端按原提交规则核验结果。
20
-
21
- ## 网络与依赖
22
-
23
- 通过context.fetch发送请求。它由宿主提供网络传输,并与插件生命周期关联。签名、URL与协议逻辑在插件内执行;浏览器可用的SDK可以把自己的HTTP传输接到context.fetch。
24
-
25
- 普通npm依赖随main.js按浏览器目标打包;不导入fs、http、Node Buffer或其他Node内置模块,不借用宿主node_modules,不另打包Node依赖目录。保留模板external配置。
26
-
27
- ## 配置界面
28
-
29
- 通过context.settings.register({ id: "sync", title, target: "sync", component })将配置表单挂在“设置→同步”。每个插件注册一个同步配置分区。
30
-
31
- 组件从PluginSettingsProps.syncConfig.value读取配置,通过await syncConfig.save(config)保存。字段和校验由插件定义;失败时保留输入并展示错误。凭据不要写入日志或工作区context.storage;宿主按插件ID在本机应用级保存配置。
32
-
33
- 客户端每次任务固定配置。关闭设置页不影响任务,停用插件保留配置;运行中的任务阻止停用和卸载。窗口关闭或崩溃时任务不会转移到Node进程继续执行。CLI不再提供同步功能。
34
-
35
- ## 从旧同步示例升级
36
-
37
- SDK0.9.0的manifest.sync/sync.js示例已撤回。将存储实现作为普通模块由main.js导入,在activate内注册,并改用浏览器兼容依赖及context.fetch;删除manifest.sync,重新打包。不要通过其他字段恢复Node入口。
1
+ # 同步存储插件
2
+
3
+ 需要 SDK 0.10.0 及以上,以及包含渲染端同步注册支持的 Tau 0.59.0 客户端构建。插件只在渲染进程执行,沿用main.js入口,不声明manifest.sync,也不提供Node后台产物。
4
+
5
+ ## 注册与职责
6
+
7
+ 在activate(context)中调用context.sync.register({ id: context.pluginId, name, create })。一个插件注册一个提供方,create(config)根据本次任务的JSON配置返回下列五个方法;停用或激活失败时注册自动回收。create在真正发起任务时调用,打开配置页不会连接存储服务。
8
+
9
+ | 方法 | 返回值 | 用途 |
10
+ | ------------------------------- | ------------------------- | ---------------------------------------------------- |
11
+ | uploadFile(name, bytes) | Promise<boolean> | 普通上传 |
12
+ | downloadFile(name) | Promise<Uint8Array> | 读取对象 |
13
+ | fileExists(name) | Promise<boolean> | 检查对象是否存在 |
14
+ | listFiles(prefix?) | Promise<RemoteFileInfo[]> | 内部完成分页,返回相对路径、名称、大小及可选修改时间 |
15
+ | createFileIfAbsent(name, bytes) | Promise<boolean> | 按远端原子条件创建对象 |
16
+
17
+ SyncProvider、SyncProviderDefinition和RemoteFileInfo类型从@tau/plugins/sync导入。该模块仅提供纯契约与声明辅助函数,不是Node执行入口。
18
+
19
+ 客户端负责同步内容、对象命名、版本提交、冲突、资源计划和恢复。插件负责存储服务请求,不增加能力声明、服务商探测或独立同步引擎。条件创建不能用先查询再覆盖替代;请求失败后由客户端按原提交规则核验结果。
20
+
21
+ ## 网络与依赖
22
+
23
+ 通过context.fetch发送请求。它由宿主提供网络传输,并与插件生命周期关联。签名、URL与协议逻辑在插件内执行;浏览器可用的SDK可以把自己的HTTP传输接到context.fetch。
24
+
25
+ 普通npm依赖随main.js按浏览器目标打包;不导入fs、http、Node Buffer或其他Node内置模块,不借用宿主node_modules,不另打包Node依赖目录。保留模板external配置。
26
+
27
+ ## 配置界面
28
+
29
+ 通过context.settings.register({ id: "sync", title, target: "sync", component })将配置表单挂在“设置→同步”。每个插件注册一个同步配置分区。
30
+
31
+ 组件从PluginSettingsProps.syncConfig.value读取配置,通过await syncConfig.save(config)保存。字段和校验由插件定义;失败时保留输入并展示错误。凭据不要写入日志或工作区context.storage;宿主按插件ID在本机应用级保存配置。
32
+
33
+ 客户端每次任务固定配置。关闭设置页不影响任务,停用插件保留配置;运行中的任务阻止停用和卸载。窗口关闭或崩溃时任务不会转移到Node进程继续执行。CLI不再提供同步功能。
34
+
35
+ ## 从旧同步示例升级
36
+
37
+ SDK0.9.0的manifest.sync/sync.js示例已撤回。将存储实现作为普通模块由main.js导入,在activate内注册,并改用浏览器兼容依赖及context.fetch;删除manifest.sync,重新打包。不要通过其他字段恢复Node入口。
package/TTS.md CHANGED
@@ -1,20 +1,20 @@
1
- # 语音提供方
2
-
3
- 需要 SDK 0.13.0 和包含语音插件能力的 Tau 0.59.0 客户端。
4
-
5
- 在activate中调用context.tts.register({id: context.pluginId, name, create})。create(config, modelId)同步创建任务实例,固定该账号配置和模型,不发送网络请求。每个插件可对应多个用户账号,不能用插件全局变量保存“当前API Key”。
6
-
7
- | 方法或字段 | 职责 |
8
- | -------------------------------------------------- | ----------------------------------------------------------------------------------- |
9
- | getVoices(signal) | 返回id、name、type(system/cloned/custom)、可选description组成的音色数组 |
10
- | synthesize({text,voiceId,options},signal) | 返回{audio:Uint8Array,mime:string};options仅含speed、volume、pitch |
11
- | cloneVoice({file,requestedId?,name?},signal),可选 | 每次一个{name,mimeType,content}参考文件,返回实际创建的音色;不返回上传文件ID或void |
12
- | textInstructions,可选 | 当前模型的合成文本规则;供宿主播客脚本使用,缺省为纯文本 |
13
-
14
- 请求使用context.fetch并传入方法收到的signal。服务商超时用AbortSignal.any组合,不能覆盖取消信号;退避等待也须取消,不把AbortError当作可重试错误。
15
-
16
- 配置通过settings.register的target:"tts"挂载。组件接收ttsConfig.instanceId、value、models和save(value,models),只保存当前账号,不自动选为默认,不覆盖同插件其他账号。模型项为{id,label?};用户可填写自定义模型。保存失败保留表单并显示错误,不另存一份凭据到context.storage。
17
-
18
- 需要公开上传参考音频时调用context.upload.uploadRemote(file,{signal}),复用用户选定的远端上传配置。本地模式明确报错;MiniMax自有文件上传不需要图床。不要自行选择用户的上传插件、读取上传凭据或修改桶权限。
19
-
20
- 主进程只转发数据和提供宿主能力。插件在主窗口渲染进程执行,不使用Node后台入口。宿主负责音频播放、合并和保存;插件不直接写笔记或文件。
1
+ # 语音提供方
2
+
3
+ 需要 SDK 0.13.0 和包含语音插件能力的 Tau 0.59.0 客户端。
4
+
5
+ 在activate中调用context.tts.register({id: context.pluginId, name, create})。create(config, modelId)同步创建任务实例,固定该账号配置和模型,不发送网络请求。每个插件可对应多个用户账号,不能用插件全局变量保存“当前API Key”。
6
+
7
+ | 方法或字段 | 职责 |
8
+ | -------------------------------------------------- | ----------------------------------------------------------------------------------- |
9
+ | getVoices(signal) | 返回id、name、type(system/cloned/custom)、可选description组成的音色数组 |
10
+ | synthesize({text,voiceId,options},signal) | 返回{audio:Uint8Array,mime:string};options仅含speed、volume、pitch |
11
+ | cloneVoice({file,requestedId?,name?},signal),可选 | 每次一个{name,mimeType,content}参考文件,返回实际创建的音色;不返回上传文件ID或void |
12
+ | textInstructions,可选 | 当前模型的合成文本规则;供宿主播客脚本使用,缺省为纯文本 |
13
+
14
+ 请求使用context.fetch并传入方法收到的signal。服务商超时用AbortSignal.any组合,不能覆盖取消信号;退避等待也须取消,不把AbortError当作可重试错误。
15
+
16
+ 配置通过settings.register的target:"tts"挂载。组件接收ttsConfig.instanceId、value、models和save(value,models),只保存当前账号,不自动选为默认,不覆盖同插件其他账号。模型项为{id,label?};用户可填写自定义模型。保存失败保留表单并显示错误,不另存一份凭据到context.storage。
17
+
18
+ 需要公开上传参考音频时调用context.upload.uploadRemote(file,{signal}),复用用户选定的远端上传配置。本地模式明确报错;MiniMax自有文件上传不需要图床。不要自行选择用户的上传插件、读取上传凭据或修改桶权限。
19
+
20
+ 主进程只转发数据和提供宿主能力。插件在主窗口渲染进程执行,不使用Node后台入口。宿主负责音频播放、合并和保存;插件不直接写笔记或文件。
package/UPLOAD.md CHANGED
@@ -1,35 +1,35 @@
1
- # 资源上传插件
2
-
3
- 需要 SDK 0.12.0 和包含资源上传插件能力的 Tau 0.59.0 客户端。上传返回正文可直接引用的 HTTP(S) 地址;数据库和资源目录同步使用 SYNC.md 的另一套接口。
4
-
5
- SDK 0.13.0 增加第三个signal参数与context.upload.uploadRemote(file,{signal})。提供方应将signal合并进context.fetch请求;调用方使用uploadRemote时,本地目标明确报错,不自动更换存储。signal取消会结束等待并通知提供方,不代表撤回已经上传的远端对象。
6
-
7
- 在 activate 中注册提供方:
8
-
9
- ```tsx
10
- context.upload.register({
11
- id: context.pluginId,
12
- name: "我的资源存储",
13
- async upload(file, config, signal) {
14
- // 用 context.fetch 请求服务商,认证与路径由本次 config 决定。
15
- // file.name 已唯一命名,file.mimeType 是 MIME,file.content 为 Uint8Array。
16
- return uploadToStorage(context.fetch, file, config, signal);
17
- },
18
- });
19
- context.settings.register({
20
- id: "upload",
21
- title: "我的资源存储",
22
- target: "upload",
23
- component: UploadSettings,
24
- });
25
- ```
26
-
27
- UploadSettings 接收 PluginSettingsProps。读取 uploadConfig.value,在用户保存时调用 await uploadConfig.save(config),宿主保存并选中该提供方;不要将同一份上传配置再存到 context.storage。配置是 JsonValue,读取时自行校验字段并给出错误提示。组件在资源存储设置页显示;插件详情页提供跳转入口。
28
-
29
- 每个插件只能注册一个上传提供方,id 必须等于 context.pluginId。宿主负责压缩、文件唯一命名、本地保存和跨窗口转发。插件只负责远端上传和返回资源地址,不读取用户文件路径,也不修改笔记内容。
30
-
31
- 请求通过 context.fetch 发送,失败抛出错误,不返回空地址或吞掉失败。停用插件会取消上下文请求并拒绝迟到结果。插件在渲染进程执行,不使用 Node 模块或额外后台入口。
32
-
33
- 返回地址必须长期可引用;不要返回短期签名 URL。桶或仓库的公开读取策略由用户配置,上传成功不等于匿名用户可以访问。不要自动修改用户桶权限。需要自定义公开域名时由插件设置提供,按对象路径返回完整 URL。
34
-
35
- 完成后验证:本地模式不调用插件、远端上传成功及失败、保存配置、停用、独立窗口上传、重启恢复。README.md 应说明如何配置公开访问和常见服务商错误。
1
+ # 资源上传插件
2
+
3
+ 需要 SDK 0.12.0 和包含资源上传插件能力的 Tau 0.59.0 客户端。上传返回正文可直接引用的 HTTP(S) 地址;数据库和资源目录同步使用 SYNC.md 的另一套接口。
4
+
5
+ SDK 0.13.0 增加第三个signal参数与context.upload.uploadRemote(file,{signal})。提供方应将signal合并进context.fetch请求;调用方使用uploadRemote时,本地目标明确报错,不自动更换存储。signal取消会结束等待并通知提供方,不代表撤回已经上传的远端对象。
6
+
7
+ 在 activate 中注册提供方:
8
+
9
+ ```tsx
10
+ context.upload.register({
11
+ id: context.pluginId,
12
+ name: "我的资源存储",
13
+ async upload(file, config, signal) {
14
+ // 用 context.fetch 请求服务商,认证与路径由本次 config 决定。
15
+ // file.name 已唯一命名,file.mimeType 是 MIME,file.content 为 Uint8Array。
16
+ return uploadToStorage(context.fetch, file, config, signal);
17
+ },
18
+ });
19
+ context.settings.register({
20
+ id: "upload",
21
+ title: "我的资源存储",
22
+ target: "upload",
23
+ component: UploadSettings,
24
+ });
25
+ ```
26
+
27
+ UploadSettings 接收 PluginSettingsProps。读取 uploadConfig.value,在用户保存时调用 await uploadConfig.save(config),宿主保存并选中该提供方;不要将同一份上传配置再存到 context.storage。配置是 JsonValue,读取时自行校验字段并给出错误提示。组件在资源存储设置页显示;插件详情页提供跳转入口。
28
+
29
+ 每个插件只能注册一个上传提供方,id 必须等于 context.pluginId。宿主负责压缩、文件唯一命名、本地保存和跨窗口转发。插件只负责远端上传和返回资源地址,不读取用户文件路径,也不修改笔记内容。
30
+
31
+ 请求通过 context.fetch 发送,失败抛出错误,不返回空地址或吞掉失败。停用插件会取消上下文请求并拒绝迟到结果。插件在渲染进程执行,不使用 Node 模块或额外后台入口。
32
+
33
+ 返回地址必须长期可引用;不要返回短期签名 URL。桶或仓库的公开读取策略由用户配置,上传成功不等于匿名用户可以访问。不要自动修改用户桶权限。需要自定义公开域名时由插件设置提供,按对象路径返回完整 URL。
34
+
35
+ 完成后验证:本地模式不调用插件、远端上传成功及失败、保存配置、停用、独立窗口上传、重启恢复。README.md 应说明如何配置公开访问和常见服务商错误。
package/VIDEO.md CHANGED
@@ -1,65 +1,65 @@
1
- # 视频提供方
2
-
3
- 需要 SDK 0.22.0 和支持该能力的客户端。通过 `context.video.register({ id: context.pluginId, name, create })` 注册,每个插件一个提供方。视频来源可以是视频网站,也可以是自建的视频服务(如 NAS)。
4
-
5
- 启用后,编辑器、白板、项目视频笔记和学习资料的「添加视频」中会出现以 `name` 命名的入口。用户从该入口粘贴视频链接,客户端先用 `matches` 确认链接属于本插件,再调用 `resolve`。
6
-
7
- 插件只负责视频来源本身的知识:识别链接、查询标题与可选清晰度、给出真实的流地址和所需请求头。选择弹窗、下载进度、合并音视频、缓存和播放都由客户端完成,插件不提供这些界面,也不传输视频字节。
8
-
9
- ## 实例
10
-
11
- `create(config)` 按当前插件配置同步创建实例,不发网络请求。实例需要实现四个方法:
12
-
13
- - `matches(url)`:同步判断链接是否属于本来源,不访问网络。链接属于其他已启用插件时,客户端会提示用户改用对应入口。
14
- - `resolve(url, signal)`:返回 `{ title, cover?, variants, defaultVariant? }`。`variants` 是可选清晰度(至少一项),每项为 `{ label, hint?, ref }`。
15
- - `cacheKey(ref)`:返回稳定的缓存身份,应包含清晰度。视频已缓存时客户端不再调用 `getPlayback`,可以离线播放。
16
- - `getPlayback(ref, signal)`:每次缓存前现取播放源,可以返回会过期的直链。
17
-
18
- ## 视频引用
19
-
20
- 用户选中的 `ref` 原样写入文档和数据库,以后只能通过它找回视频。它必须是可长期保存的 JSON,例如视频 ID 加清晰度,不要放会过期的直链、Cookie 或令牌。`type`、`title`、`thumbnail` 三个键由客户端占用,引用中不要使用。
21
-
22
- ## 播放源
23
-
24
- `getPlayback` 返回以下三种之一:
25
-
26
- - `{ kind: "file", stream }`:单个音视频合一的文件。
27
- - `{ kind: "split", video, audio }`:音视频分离的流,客户端分别下载后无损合并。
28
- - `{ kind: "extract", url, videoFormat?, audioFormat?, proxy? }`:交给客户端内置的视频解析器下载,格式 ID 来自 `context.services.videoExtractor.probe`。
29
-
30
- `stream` 为 `{ url, headers? }`。需要 Referer、Cookie 等请求头时放在 `headers` 中,客户端只在下载时使用,不写入文档或缓存索引。网络请求使用 `context.fetch` 并传入方法的 signal,它可以设置这些请求头。
31
-
32
- ## 视频解析服务
33
-
34
- `context.services.videoExtractor.probe(url, { proxy?, signal? })` 返回 `{ title, cover?, duration?, formats }`,`formats` 每项包含 `id`、`videoOnly`、`audioOnly`、`ext`、`width`、`height`、`fps`、`bitrate`、`size`、`note`。插件根据格式列表组织清晰度,再返回 `kind: "extract"` 的播放源;插件不能自行启动外部程序。
35
-
36
- ## 配置
37
-
38
- 账号、Cookie 或代理通过 `context.settings.register({ id, title, target: "video", component })` 注册配置视图,挂载在「设置 · 账号与连接 · 在线视频」。组件接收 `PluginSettingsProps.videoConfig`:`value` 和 `save(value)`,每个插件一份配置,保存后下一次调用 `create` 即读到新值。保存失败时保留草稿,成功后才提示已保存。
39
-
40
- 插件停用或调用方取消时,进行中的请求会收到取消信号,迟到的结果被丢弃。插件未启用时,已保存的视频显示需要启用插件的提示,原数据保留。移动端和发布站点不运行插件,插件提供的视频在那里只显示说明。
41
-
42
- ## 注册与验证
43
-
44
- 注册放在 `activate` 中,实例的四个方法由来源适配实现,并使用 SDK 类型检查返回值:
45
-
46
- ```ts
47
- import type { JsonValue, PluginContext, VideoInstance } from "@tau/plugins";
48
-
49
- export function registerVideoSource(
50
- context: PluginContext,
51
- createSource: (config: JsonValue) => VideoInstance
52
- ) {
53
- return context.video.register({
54
- id: context.pluginId,
55
- name: "我的视频来源",
56
- create: createSource,
57
- });
58
- }
59
- ```
60
-
61
- 在 manifest 中声明 `categories: ["video"]`,便于用户从插件中心筛选;分类本身不注册提供方。解析输入、网络响应与持久化的 ref 都要校验;`defaultVariant` 是从 0 开始的索引,缺省时宿主使用第一项。不要把 `cacheKey` 简化为本次的签名直链,账号刷新或直链过期不应改变同一视频清晰度的缓存身份。
62
-
63
- 验证应覆盖:来源不匹配、格式为空、链接过期后重新取源、音视频分离、已缓存时离线播放、账号更新、取消与停用。单文件流须能由宿主直接下载;需要视频解析器处理的页面使用 `kind: "extract"`。具体网站的限制与认证失败由插件返回可读错误,不返回虚假的可播放结果。
64
-
65
- SDK 0.23.0 删除的是 `services.ffmpeg.probe` 本地媒体探测,`services.videoExtractor.probe` 保留;区别与 FFmpeg 转换接口见 [SERVICES.md](SERVICES.md)。
1
+ # 视频提供方
2
+
3
+ 需要 SDK 0.22.0 和支持该能力的客户端。通过 `context.video.register({ id: context.pluginId, name, create })` 注册,每个插件一个提供方。视频来源可以是视频网站,也可以是自建的视频服务(如 NAS)。
4
+
5
+ 启用后,编辑器、白板、项目视频笔记和学习资料的「添加视频」中会出现以 `name` 命名的入口。用户从该入口粘贴视频链接,客户端先用 `matches` 确认链接属于本插件,再调用 `resolve`。
6
+
7
+ 插件只负责视频来源本身的知识:识别链接、查询标题与可选清晰度、给出真实的流地址和所需请求头。选择弹窗、下载进度、合并音视频、缓存和播放都由客户端完成,插件不提供这些界面,也不传输视频字节。
8
+
9
+ ## 实例
10
+
11
+ `create(config)` 按当前插件配置同步创建实例,不发网络请求。实例需要实现四个方法:
12
+
13
+ - `matches(url)`:同步判断链接是否属于本来源,不访问网络。链接属于其他已启用插件时,客户端会提示用户改用对应入口。
14
+ - `resolve(url, signal)`:返回 `{ title, cover?, variants, defaultVariant? }`。`variants` 是可选清晰度(至少一项),每项为 `{ label, hint?, ref }`。
15
+ - `cacheKey(ref)`:返回稳定的缓存身份,应包含清晰度。视频已缓存时客户端不再调用 `getPlayback`,可以离线播放。
16
+ - `getPlayback(ref, signal)`:每次缓存前现取播放源,可以返回会过期的直链。
17
+
18
+ ## 视频引用
19
+
20
+ 用户选中的 `ref` 原样写入文档和数据库,以后只能通过它找回视频。它必须是可长期保存的 JSON,例如视频 ID 加清晰度,不要放会过期的直链、Cookie 或令牌。`type`、`title`、`thumbnail` 三个键由客户端占用,引用中不要使用。
21
+
22
+ ## 播放源
23
+
24
+ `getPlayback` 返回以下三种之一:
25
+
26
+ - `{ kind: "file", stream }`:单个音视频合一的文件。
27
+ - `{ kind: "split", video, audio }`:音视频分离的流,客户端分别下载后无损合并。
28
+ - `{ kind: "extract", url, videoFormat?, audioFormat?, proxy? }`:交给客户端内置的视频解析器下载,格式 ID 来自 `context.services.videoExtractor.probe`。
29
+
30
+ `stream` 为 `{ url, headers? }`。需要 Referer、Cookie 等请求头时放在 `headers` 中,客户端只在下载时使用,不写入文档或缓存索引。网络请求使用 `context.fetch` 并传入方法的 signal,它可以设置这些请求头。
31
+
32
+ ## 视频解析服务
33
+
34
+ `context.services.videoExtractor.probe(url, { proxy?, signal? })` 返回 `{ title, cover?, duration?, formats }`,`formats` 每项包含 `id`、`videoOnly`、`audioOnly`、`ext`、`width`、`height`、`fps`、`bitrate`、`size`、`note`。插件根据格式列表组织清晰度,再返回 `kind: "extract"` 的播放源;插件不能自行启动外部程序。
35
+
36
+ ## 配置
37
+
38
+ 账号、Cookie 或代理通过 `context.settings.register({ id, title, target: "video", component })` 注册配置视图,挂载在「设置 · 账号与连接 · 在线视频」。组件接收 `PluginSettingsProps.videoConfig`:`value` 和 `save(value)`,每个插件一份配置,保存后下一次调用 `create` 即读到新值。保存失败时保留草稿,成功后才提示已保存。
39
+
40
+ 插件停用或调用方取消时,进行中的请求会收到取消信号,迟到的结果被丢弃。插件未启用时,已保存的视频显示需要启用插件的提示,原数据保留。移动端和发布站点不运行插件,插件提供的视频在那里只显示说明。
41
+
42
+ ## 注册与验证
43
+
44
+ 注册放在 `activate` 中,实例的四个方法由来源适配实现,并使用 SDK 类型检查返回值:
45
+
46
+ ```ts
47
+ import type { JsonValue, PluginContext, VideoInstance } from "@tau/plugins";
48
+
49
+ export function registerVideoSource(
50
+ context: PluginContext,
51
+ createSource: (config: JsonValue) => VideoInstance
52
+ ) {
53
+ return context.video.register({
54
+ id: context.pluginId,
55
+ name: "我的视频来源",
56
+ create: createSource,
57
+ });
58
+ }
59
+ ```
60
+
61
+ 在 manifest 中声明 `categories: ["video"]`,便于用户从插件中心筛选;分类本身不注册提供方。解析输入、网络响应与持久化的 ref 都要校验;`defaultVariant` 是从 0 开始的索引,缺省时宿主使用第一项。不要把 `cacheKey` 简化为本次的签名直链,账号刷新或直链过期不应改变同一视频清晰度的缓存身份。
62
+
63
+ 验证应覆盖:来源不匹配、格式为空、链接过期后重新取源、音视频分离、已缓存时离线播放、账号更新、取消与停用。单文件流须能由宿主直接下载;需要视频解析器处理的页面使用 `kind: "extract"`。具体网站的限制与认证失败由插件返回可读错误,不返回虚假的可播放结果。
64
+
65
+ SDK 0.23.0 删除的是 `services.ffmpeg.probe` 本地媒体探测,`services.videoExtractor.probe` 保留;区别与 FFmpeg 转换接口见 [SERVICES.md](SERVICES.md)。
package/WHITEBOARD.md CHANGED
@@ -1,115 +1,115 @@
1
- # 白板插件
2
-
3
- 白板作者接口需要 SDK 0.8.0 及包含白板扩展支持的 Tau 客户端。SDK 0.7.0 不提供此能力。
4
-
5
- 插件定义中声明 `whiteboardExtensions`,manifest 增加 `whiteboard: true`。使用 `@tau/plugins/whiteboard` 导入定义函数和类型,并将该模块保留为构建 external,由宿主提供实现。一个 main.js 同时包含声明、渲染与交互,不生成另一个渲染入口。
6
-
7
- ```tsx
8
- import { definePlugin } from "@tau/plugins";
9
- import { defineElement, defineWhiteboardExtension } from "@tau/plugins/whiteboard";
10
-
11
- declare const __PLUGIN_META__: { id: string; name: string; version: string };
12
- const type = `${__PLUGIN_META__.id}.box`;
13
- const extension = defineWhiteboardExtension({
14
- id: __PLUGIN_META__.id,
15
- elements: [
16
- defineElement({
17
- type,
18
- render: ({ element }) => (
19
- <rect
20
- x={element.x}
21
- y={element.y}
22
- width={element.width}
23
- height={element.height}
24
- fill="var(--tau-accent)"
25
- />
26
- ),
27
- create: {
28
- gesture: "click",
29
- defaultSize: [160, 90],
30
- after: "select",
31
- build: ({ rect }) => ({ id: crypto.randomUUID(), type, ...rect, data: {} }),
32
- },
33
- }),
34
- ],
35
- create: () => ({
36
- tools: [
37
- {
38
- id: `${__PLUGIN_META__.id}.create`,
39
- element: type,
40
- label: "插入方块",
41
- order: 90,
42
- group: "drawing",
43
- icon: () => (
44
- <svg viewBox="0 0 24 24">
45
- <rect x={3} y={5} width={18} height={14} fill="currentColor" />
46
- </svg>
47
- ),
48
- },
49
- ],
50
- }),
51
- });
52
- export default definePlugin({ ...__PLUGIN_META__, whiteboardExtensions: [extension] });
53
- ```
54
-
55
- ## 契约
56
-
57
- - `elements` 在扩展顶层静态声明,禁止放到 `create` 返回值中。元素类型必须以完整插件 ID 加点开头,扩展 ID 为插件 ID 或其子命名空间。
58
- - `create(api)` 每个画布单独执行,返回 `tools`、`inspectors`、`commands` 等交互贡献。状态放在实例闭包,不能放在模块顶层跨画布共享。
59
- - 元素私有字段放在 `data`,通过 `defineElement<TData>` 和可选同步 Standard Schema 校验约束;通用位置和尺寸仍在元素顶层。
60
- - 属性修改走 `api.updateElement`,结构操作走 `api.submit`;这些入口统一处理只读、历史及生命周期。不要修改返回的快照。
61
- - 元素组件可用 `useWhiteboardAPI()` 获取所属扩展的受控 API,不接触内部 Board。声明求值阶段不得读取 DOM。
62
- - `activate` 随画布显示运行,停驻会清理;`dispose` 在真正销毁时运行。插件整体启用/停用/更新在重启后改变静态装配,不热替换打开中的画布。
63
- - 找不到插件时保留节点并显示未知元素占位,重新安装并启用后恢复。保存、复制不能丢弃未知节点。
64
-
65
- ## 通用展示与交互
66
-
67
- ### 创建前选择参数
68
-
69
- 第三方工具集中在「扩展工具」菜单;可选的 `panel` 让用户先选择参数,再调用 `run(payload)`。面板可以通过 `useWhiteboardAPI()` 获取所属扩展的 API。
70
-
71
- ```tsx
72
- panel: ({ run }) => (
73
- <button onClick={() => run({ label: "新方块" })}>创建新方块</button>
74
- ),
75
- ```
76
-
77
- 创建工具在 `element.create.build` 的 `options` 中读取这些参数,命令工具在命令的 `payload` 中读取。宿主管理返回、关闭与面板卸载,执行后自动关闭;返回或关闭不会执行工具。关闭后的迟到 `run` 调用被忽略。面板抛错时显示错误并保留返回入口。没有 `panel` 的工具仍点击即执行;不要用只供内置工具栏使用的 `component` 代替它,也不要在面板内创建第二套画布指针监听。
78
-
79
- ### 元素声明
80
-
81
- 以下声明放在 `defineElement` 内,仍使用同一个插件入口:
82
-
83
- ```ts
84
- interaction: {
85
- resize: { handles: "corners", preserveAspectRatio: true },
86
- connect: "rect",
87
- },
88
- presentation: {
89
- label: "我的图形",
90
- getName: element => element.data.label,
91
- },
92
- sketch: true,
93
- schematic: element => [{
94
- kind: "rect", x: element.x, y: element.y,
95
- w: element.width, h: element.height, r: 3, fill: "var(--tau-accent)",
96
- }],
97
- ```
98
-
99
- - `resize.handles` 可选 corners 或 all,默认 all;`preserveAspectRatio` 默认为 false,Shift 仍可启用等比。内核生成手柄,负责吸附、单步撤销、取消和生命周期,不要再给元素额外画一套缩放手柄。
100
- - `connect: "rect"` 使用矩形连接点,包括相对位置绑定;不声明则不生成连接控件。
101
- - `presentation.icon` 为可选图标组件,接收 className、size、strokeWidth。`getName` 接收只读快照,手动 name 优先;无法生成时回退 label。
102
- - 声明 `sketch:true` 后,在元素组件调用 `useSketch(element)` 获取 enabled/level/seed;页面切换会更新组件,元素覆盖仍由宿主解析。不要自行维护全局画风状态。
103
- - `SketchPaths` 渲染已有手绘路径;`sketch` 命名空间提供 createRandom、distance、polylineToD、resample、wobble、inkOutline、inkSize、loopStroke、handTextClass。复用宿主纯算法,不从白板内部目录复制实现。
104
- - `usePageSketch()` 读取所属页面的画风;`sketch.hashSeed(text)` 为预览图生成稳定种子。`AttrPopover`、`AttrToggle`、`OptionGrid`、`Seg` 供属性面板使用,`SketchPopover` 提供与宿主相同的元素笔触设置。
105
- - `schematic(element, { dark })` 返回纯图元数组,用于列表与导出弹窗的简略预览;字段类型见 SchematicShape。不能调用 hook、修改元素或依赖某个画布已打开。实际图像导出仍使用完整画布渲染,不使用简略投影替代。
106
-
107
- 构建 Tailwind 工具类时可导入 `@tau/plugins/tailwind.css`,其中仅包含语义类名映射,主题变量由客户端提供。不要引入未公开的宿主主题包。
108
-
109
- ## 私有偏好
110
-
111
- 需要记住用户选择时,在扩展中声明 `requires: [IPluginStorage]`,通过 `api.getService(IPluginStorage)` 获取存储。`IPluginStorage` 从 `@tau/plugins/whiteboard` 导入,接口与 `PluginContext.storage` 相同:异步 `get(key)`、`set(key, JSON值)`、`delete(key)`。
112
-
113
- 宿主按插件真实归属与当前工作区绑定存储,插件不能传入其他插件 ID。画布隐藏、关闭或只读时拒绝交互存储操作;插件失活、工作区切换后,旧实例也不能继续写入。异步读写应捕获错误,并在面板卸载后忽略迟到结果。重新打开白板后绑定当前激活实例。
114
-
115
- 只在 `create(api)`、工具面板、属性交互和 `element.create.build` 中使用这项服务。静态渲染与 `schematic` 必须只依据元素数据及明确输入,不依赖存储、DOM 或插件 activate 时序。读取不存在的偏好时使用默认值;读取失败不能伪装成空数据后覆盖原值。
1
+ # 白板插件
2
+
3
+ 白板作者接口需要 SDK 0.8.0 及包含白板扩展支持的 Tau 客户端。SDK 0.7.0 不提供此能力。
4
+
5
+ 插件定义中声明 `whiteboardExtensions`,manifest 增加 `whiteboard: true`。使用 `@tau/plugins/whiteboard` 导入定义函数和类型,并将该模块保留为构建 external,由宿主提供实现。一个 main.js 同时包含声明、渲染与交互,不生成另一个渲染入口。
6
+
7
+ ```tsx
8
+ import { definePlugin } from "@tau/plugins";
9
+ import { defineElement, defineWhiteboardExtension } from "@tau/plugins/whiteboard";
10
+
11
+ declare const __PLUGIN_META__: { id: string; name: string; version: string };
12
+ const type = `${__PLUGIN_META__.id}.box`;
13
+ const extension = defineWhiteboardExtension({
14
+ id: __PLUGIN_META__.id,
15
+ elements: [
16
+ defineElement({
17
+ type,
18
+ render: ({ element }) => (
19
+ <rect
20
+ x={element.x}
21
+ y={element.y}
22
+ width={element.width}
23
+ height={element.height}
24
+ fill="var(--tau-accent)"
25
+ />
26
+ ),
27
+ create: {
28
+ gesture: "click",
29
+ defaultSize: [160, 90],
30
+ after: "select",
31
+ build: ({ rect }) => ({ id: crypto.randomUUID(), type, ...rect, data: {} }),
32
+ },
33
+ }),
34
+ ],
35
+ create: () => ({
36
+ tools: [
37
+ {
38
+ id: `${__PLUGIN_META__.id}.create`,
39
+ element: type,
40
+ label: "插入方块",
41
+ order: 90,
42
+ group: "drawing",
43
+ icon: () => (
44
+ <svg viewBox="0 0 24 24">
45
+ <rect x={3} y={5} width={18} height={14} fill="currentColor" />
46
+ </svg>
47
+ ),
48
+ },
49
+ ],
50
+ }),
51
+ });
52
+ export default definePlugin({ ...__PLUGIN_META__, whiteboardExtensions: [extension] });
53
+ ```
54
+
55
+ ## 契约
56
+
57
+ - `elements` 在扩展顶层静态声明,禁止放到 `create` 返回值中。元素类型必须以完整插件 ID 加点开头,扩展 ID 为插件 ID 或其子命名空间。
58
+ - `create(api)` 每个画布单独执行,返回 `tools`、`inspectors`、`commands` 等交互贡献。状态放在实例闭包,不能放在模块顶层跨画布共享。
59
+ - 元素私有字段放在 `data`,通过 `defineElement<TData>` 和可选同步 Standard Schema 校验约束;通用位置和尺寸仍在元素顶层。
60
+ - 属性修改走 `api.updateElement`,结构操作走 `api.submit`;这些入口统一处理只读、历史及生命周期。不要修改返回的快照。
61
+ - 元素组件可用 `useWhiteboardAPI()` 获取所属扩展的受控 API,不接触内部 Board。声明求值阶段不得读取 DOM。
62
+ - `activate` 随画布显示运行,停驻会清理;`dispose` 在真正销毁时运行。插件整体启用/停用/更新在重启后改变静态装配,不热替换打开中的画布。
63
+ - 找不到插件时保留节点并显示未知元素占位,重新安装并启用后恢复。保存、复制不能丢弃未知节点。
64
+
65
+ ## 通用展示与交互
66
+
67
+ ### 创建前选择参数
68
+
69
+ 第三方工具集中在「扩展工具」菜单;可选的 `panel` 让用户先选择参数,再调用 `run(payload)`。面板可以通过 `useWhiteboardAPI()` 获取所属扩展的 API。
70
+
71
+ ```tsx
72
+ panel: ({ run }) => (
73
+ <button onClick={() => run({ label: "新方块" })}>创建新方块</button>
74
+ ),
75
+ ```
76
+
77
+ 创建工具在 `element.create.build` 的 `options` 中读取这些参数,命令工具在命令的 `payload` 中读取。宿主管理返回、关闭与面板卸载,执行后自动关闭;返回或关闭不会执行工具。关闭后的迟到 `run` 调用被忽略。面板抛错时显示错误并保留返回入口。没有 `panel` 的工具仍点击即执行;不要用只供内置工具栏使用的 `component` 代替它,也不要在面板内创建第二套画布指针监听。
78
+
79
+ ### 元素声明
80
+
81
+ 以下声明放在 `defineElement` 内,仍使用同一个插件入口:
82
+
83
+ ```ts
84
+ interaction: {
85
+ resize: { handles: "corners", preserveAspectRatio: true },
86
+ connect: "rect",
87
+ },
88
+ presentation: {
89
+ label: "我的图形",
90
+ getName: element => element.data.label,
91
+ },
92
+ sketch: true,
93
+ schematic: element => [{
94
+ kind: "rect", x: element.x, y: element.y,
95
+ w: element.width, h: element.height, r: 3, fill: "var(--tau-accent)",
96
+ }],
97
+ ```
98
+
99
+ - `resize.handles` 可选 corners 或 all,默认 all;`preserveAspectRatio` 默认为 false,Shift 仍可启用等比。内核生成手柄,负责吸附、单步撤销、取消和生命周期,不要再给元素额外画一套缩放手柄。
100
+ - `connect: "rect"` 使用矩形连接点,包括相对位置绑定;不声明则不生成连接控件。
101
+ - `presentation.icon` 为可选图标组件,接收 className、size、strokeWidth。`getName` 接收只读快照,手动 name 优先;无法生成时回退 label。
102
+ - 声明 `sketch:true` 后,在元素组件调用 `useSketch(element)` 获取 enabled/level/seed;页面切换会更新组件,元素覆盖仍由宿主解析。不要自行维护全局画风状态。
103
+ - `SketchPaths` 渲染已有手绘路径;`sketch` 命名空间提供 createRandom、distance、polylineToD、resample、wobble、inkOutline、inkSize、loopStroke、handTextClass。复用宿主纯算法,不从白板内部目录复制实现。
104
+ - `usePageSketch()` 读取所属页面的画风;`sketch.hashSeed(text)` 为预览图生成稳定种子。`AttrPopover`、`AttrToggle`、`OptionGrid`、`Seg` 供属性面板使用,`SketchPopover` 提供与宿主相同的元素笔触设置。
105
+ - `schematic(element, { dark })` 返回纯图元数组,用于列表与导出弹窗的简略预览;字段类型见 SchematicShape。不能调用 hook、修改元素或依赖某个画布已打开。实际图像导出仍使用完整画布渲染,不使用简略投影替代。
106
+
107
+ 构建 Tailwind 工具类时可导入 `@tau/plugins/tailwind.css`,其中仅包含语义类名映射,主题变量由客户端提供。不要引入未公开的宿主主题包。
108
+
109
+ ## 私有偏好
110
+
111
+ 需要记住用户选择时,在扩展中声明 `requires: [IPluginStorage]`,通过 `api.getService(IPluginStorage)` 获取存储。`IPluginStorage` 从 `@tau/plugins/whiteboard` 导入,接口与 `PluginContext.storage` 相同:异步 `get(key)`、`set(key, JSON值)`、`delete(key)`。
112
+
113
+ 宿主按插件真实归属与当前工作区绑定存储,插件不能传入其他插件 ID。画布隐藏、关闭或只读时拒绝交互存储操作;插件失活、工作区切换后,旧实例也不能继续写入。异步读写应捕获错误,并在面板卸载后忽略迟到结果。重新打开白板后绑定当前激活实例。
114
+
115
+ 只在 `create(api)`、工具面板、属性交互和 `element.create.build` 中使用这项服务。静态渲染与 `schematic` 必须只依据元素数据及明确输入,不依赖存储、DOM 或插件 activate 时序。读取不存在的偏好时使用默认值;读取失败不能伪装成空数据后覆盖原值。
@@ -46,7 +46,7 @@ var PLUGIN_CATEGORIES = [
46
46
  { id: "blog-publish", label: "\u535A\u5BA2\u53D1\u5E03" },
47
47
  { id: "ai", label: "AI" },
48
48
  { id: "voice", label: "\u8BED\u97F3" },
49
- { id: "video", label: "\u5728\u7EBF\u89C6\u9891" },
49
+ { id: "video", label: "\u89C6\u9891" },
50
50
  { id: "page", label: "\u9875\u9762" }
51
51
  ];
52
52
  var PLUGIN_KEYWORD_LIMIT = 5;
package/package.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  isPluginPermission,
15
15
  validateBackendManifest,
16
16
  validatePluginManifest
17
- } from "./client/chunk-R3YIHOWT.js";
17
+ } from "./client/chunk-ECEBBIHP.js";
18
18
  export {
19
19
  PLUGIN_AI_CAPABILITIES,
20
20
  PLUGIN_CATEGORIES,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiongtao.xt/tau-plugins",
3
- "version": "0.29.0",
3
+ "version": "0.31.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  PLUGIN_SHARED_MODULES,
3
3
  validatePluginManifest
4
- } from "./client/chunk-R3YIHOWT.js";
4
+ } from "./client/chunk-ECEBBIHP.js";
5
5
 
6
6
  // packages/plugins/src/rendering.ts
7
7
  var PLUGIN_RENDER_VERSION = 1;
@@ -25,7 +25,7 @@ export declare const PLUGIN_CATEGORIES: readonly [{
25
25
  readonly label: "语音";
26
26
  }, {
27
27
  readonly id: "video";
28
- readonly label: "在线视频";
28
+ readonly label: "视频";
29
29
  }, {
30
30
  readonly id: "page";
31
31
  readonly label: "页面";