开发插件:贡献点
星汉的插件之间可以互相组合能力,机制叫贡献点:一个插件声明一个”点”,
其它插件向这个点投递纯数据”投稿”,点的所有者决定怎么用这些数据。最常见的
玩法是给编辑器的 AI 能力添砖加瓦——而且最简单的插件只需要一个
plugin.json 文件,一行代码都不用写。
最小可用示例:给选中文字加一个 AI 动作
Section titled “最小可用示例:给选中文字加一个 AI 动作”在 Markdown / 智能文档里选中一段文字会弹出气泡,✨ 旁边的每个动作按钮都可能 来自不同的插件。加一个”译成英文”动作的完整插件长这样:
// 目录结构:my-translate/plugin.json + my-translate/ui/index.html(占位说明页){ "id": "yourname.my-translate", "name": "我的翻译", "version": "0.1.0", "runtime": "static", "ui": "ui", "capabilities": [], "contributes": { "contributions": [ { "point": "xinghan.richtext-field/selection-actions", "data": { "id": "translate-en", "icon": "🌐", "title": "译成英文", "order": 30, "prompt": "把这段翻译成英文", "hints": "把用户选中的文档片段翻译成地道的英文。只输出译文本身,不要解释;保留 markdown 行内格式。" } } ] }}装上之后,选中文字的气泡里就多了一个 🌐 按钮——弹窗、流式输出、替换选区这些 交互全由编辑器内置的执行引擎完成,你的投稿只回答”做什么”:
hints是给 AI 的系统提示(这个动作”怎么做”)prompt可选:填了就是一键动作(点击立即执行),不填则等用户输入指令icon单个 emoji,order排序权重(小者靠前)
| 点 | 投什么 | 出现在哪 |
|---|---|---|
xinghan.richtext-field/selection-actions | 选段 AI 动作(如上) | Markdown/智能文档的选中气泡 |
xinghan.agent-anthropic/skills | AgentSkill(知识+快捷指令+工具) | 主聊天 / 编辑点 AI 微面板 |
给编辑点 AI 微面板投速查
Section titled “给编辑点 AI 微面板投速查”公式配置、选项配置这些编辑现场都有一个 ✨ 微面板。投一条
surfaces: ["micro-panel"] 的 skill,就能给指定现场加快捷指令和领域知识:
{ "point": "xinghan.agent-anthropic/skills", "data": { "id": "formula-tips", "name": "公式小抄", "description": "公式微面板的函数速查", "instructions": "写公式时优先用 IF/AND/OR 组合;日期差用 DATEDIF(开始, 结束, \"d\")。", "quickChips": ["写一个逾期天数公式(今天减截止日期)"], "surfaces": ["micro-panel"], "scope": { "fieldType": "formula" } }}scope.fieldType限定现场(formula行内公式 /crosslookup跨表公式 /select选项字段),scope.nodeType用于非字段现场(如automation); 都不填则全局可用quickChips渲染成一键 chip,instructions并进该现场的 AI 提示词 (多个投稿合计有长度预算,超出会被截断——长知识请投主聊天 skill)
给主聊天 agent 投知识与工具
Section titled “给主聊天 agent 投知识与工具”surfaces: ["main-chat"] 的 skill 进 agent 的技能目录(渐进披露:目录常驻、
全文按需加载)。带后端进程的插件还可以投工具——声明纯数据,执行时宿主
回调你插件的 /_agent/execute-tool。跨插件投稿的工具 v1 只放行只读
(effect.kind: "readonly"),写入面等沙箱治理开放后再扩。
插件还能定义一张表怎么看——日历、画廊、地图、甘特都是”同一张表的另一种
投影”。声明一个 tableViews 贡献,「新建视图」菜单里就会多出你的视图类型:
"contributes": { "tableViews": [ { "viewKey": "cards", "name": { "zh-CN": "卡片视图" }, "icon": "🃏", "entry": "ui/index.html" } ]}用户建了这种视图后,视图激活时编辑区渲染你的 entry 页面(iframe),宿主会:
- 推
context/init:context.tableNodeId是当前表、context.viewId是视图 id - 推
theme/init:tokens字段带全套主题变量(--background/--foreground/--border等,值是完整颜色)——写进:root就自动跟随亮暗色 - 应答数据 RPC(postMessage,
id必须是数字):ui/dataEngine.getFields、ui/dataEngine.queryRecords(v1 只读——展示归 插件,编辑归内核)、ui/openRecordList(把行交回宿主弹层,点条目跳转定位)
有构建的插件直接用 @xinghan/plugin-sdk/ui 的
ui.dataEngineGetFields / ui.dataEngineQueryRecords / ui.openRecordList;
零构建的单文件插件抄样板 card-view(内联 postMessage 桥约 40 行)。
声明自己的贡献点
Section titled “声明自己的贡献点”你的插件也可以开放自己的扩展面给别人投稿:
"contributes": { "contributionPoints": [ { "point": "yourname.my-plugin/my-actions", "schema": { "required": [{ "key": "id", "type": "string" }] } } ]}- 点名必须以自己的插件 id 为前缀(所有权即命名空间,防抢注)
schema做顶层必填字段浅校验,不合格的投稿会被拒并计入统计- 消费端(你的 UI)用只读端点拉有序快照:
GET /plugins/_meta/contributions?point=yourname.my-plugin/my-actions——响应里每条投稿带pluginId和人类可读的pluginName,方便标注归属
- 投稿是纯数据:单条 ≤64KB,每插件对每点 ≤64 条
- 投稿可以先于点声明(挂起,点声明后自动转正)——插件加载顺序无关
- 插件卸载/停用时它的投稿和点整体退场,重新加载自动恢复
- 静态插件(
runtime: "static")只有 manifest 这一条投稿途径;带后端进程的 插件还可以走运行时 API(cap.contributions.*),两者等价
把插件目录放进 ~/xinghan/plugins/ 后在设置里重载插件(或打包 zip 走扩展
市场的「从本地安装」)。投稿被拒时原因写在插件宿主日志
(~/xinghan/logs/plugin-host.log)里,搜 [contributions]。