准备
- Node.js 18+、UniFlow 桌面端 1.3.0+
- 插件 SDK:
@uniflow/plugin-sdk(包里带命令行工具uniflow-plugin)
SDK 发布到 npm 之前,用本机的 SDK 目录代替
npx uniflow-plugin:node <SDK 目录>/cli/uniflow-plugin.mjs <命令>。init生成的项目会自动用file:依赖指向这份 SDK。
1. 生成项目
npx uniflow-plugin init my-timer # 纯 TypeScript 面板(专注计时示例)
npx uniflow-plugin init due-soon --template react # React + Tailwind 面板(作业倒计时示例)
cd my-timer && npm install生成的项目结构:
my-timer/
plugin.json 插件声明:id、版本、作者、权限、命令(action / kind / 是否给 UniMind)、面板
src/main.ts 命令实现:export default definePlugin({ commands: [...] })
panel/main.ts 面板入口(有面板时)
panel/styles.css 面板样式(构建时自动带上;有 tailwind.config.cjs 时经 Tailwind 生成)
locales/en.json 文案(英文必需)
locales/zh.json 中文文案(可选,但官方要求中英都有)
icon.svg 图标(可选)
README.md 插件库「详情」里显示
CHANGELOG.md 插件库「更新记录」里显示
test/main.test.ts 单元测试2. 写一个命令
import { clean, definePlugin, InputError, type PluginCommand } from '@uniflow/plugin-sdk'
const countDue: PluginCommand<{ days?: number }> = {
action: 'count_due', // plugin.json 里要声明同名 action
titleKey: 'commands.countDue', // 按钮 / 撤销记录上的名字(locales 里的 key)
description: 'Count assignments due in the next N days (default 7).', // 给模型看,英文
parameters: { // JSON Schema 子集;每一层 object 都要 additionalProperties:false
type: 'object',
properties: { days: { type: 'integer', minimum: 1, maximum: 60 } },
additionalProperties: false,
},
describe: (args, ctx) => ctx.t('describe.countDue', { days: args.days ?? 7 }),
async run(args, ctx) {
const until = ctx.now().getTime() + (args.days ?? 7) * 86_400_000
const list = await ctx.assignments!.list() // 需要 context.read:assignments 权限
return { count: list.filter((a) => a.dueDate && Date.parse(a.dueDate) <= until && a.status !== 'done').length }
},
}
export default definePlugin({ commands: [countDue] })plugin.json:
{
"id": "duecount",
"version": "1.0.0",
"author": { "name": "Ada" },
"permissions": ["context.read:assignments"],
"commands": [{ "action": "count_due", "kind": "read" }]
}3. 在应用里跑起来
npm run dev # 构建到 dist/,之后每次保存自动重新构建在 UniFlow:侧边栏 插件 › 开发者 › 加载开发中的插件…,选项目里的 dist/ 文件夹。
插件立即出现在插件库里(标着「开发中」),命令进入 UniMind 的工具清单。改代码保存后插件自动重载。
试一试:在 UniMind 里问「接下来一周我有几份作业要交?」
4. 测试
npm testimport { createTestHost } from '@uniflow/plugin-sdk/testing'
const host = createTestHost({ pluginJson, definition: plugin, locales: { en }, assignments: [...] })
const r = await host.run('count_due', { days: 3 })5. 打包分发
npm run pack # → duecount-1.0.0.uniplugin