独立进程沙箱
require 白名单仅 path / os / fs / util / url / events,网络、子进程、worker 一律拒绝。
AUTHORING
能力包 = 工具 + 声明:代码只提供工具与数据,界面是数据不是代码——小诺中枢按你的贡献声明渲染全部 UI。本页是完整开发文档,左侧菜单按章节导航。
能力包不自带 UI,只注册工具 + 可选声明视图/命令;用户只通过小诺中枢的消息框交互,UI 由中枢统一渲染。一句话:插件带数据和意图进场,不带 UI 进场——用户在标准位置发现能力,用标准组件消费产出。
两条路线:让小诺替你写(Agent 驱动闭环),或照最小骨架手写。
Agent 驱动:描述需求(方案模糊时小诺先列配方目录让你报编号选关)→ create_plugin 建骨架 → write_file 写代码与黄金用例(你逐行 Diff 审阅)→ test_plugin 试玩(临时沙箱出记分板,修订零打扰,全绿再落盘)→ ask_user 确认 → apply_plugin 激活。确认卡由统一确认总线托管(多项裁决排队逐张处理,新确认静默入队),且只出现在当前对话——新建/切换对话后回原对话处理。
手写:按下方骨架建目录 → 放入本地市场目录(resources/plugin-market 或 userData/plugin-market)→ 插件页一键安装。
{
"id": "my-pack",
"name": "我的能力包",
"version": "0.1.0",
"description": "做什么",
"usage": "给用户看的使用说明:怎么入口、说什么指令、典型场景。强烈建议填写。",
"entry": "index.js",
"permissions": ["agent:tools", "db:read", "file:write"],
"agentTools": [{ "name": "my_tool" }],
"views": [{ "name": "my_table" }]
}
module.exports = {
id: 'my-pack',
name: '我的能力包',
version: '0.1.0',
description: '做什么',
async activate(context) {
// 声明视图(可选;须在 manifest "views" 登记——manifest 是唯一事实源)
context.registerViewSchema({ name: 'my_table', description: '我的表格', schemaType: 'table' })
// 注册工具(能力包与中枢交互的唯一通道;须在 manifest "agentTools" 登记)
context.registerAgentTool(
{
name: 'my_tool',
description: '工具描述(LLM 据此决定何时调用)',
parameters: { type: 'object', properties: {}, required: [] }
},
async (args) => {
const data = await doSomething(args)
return {
output: '给 LLM 看的文字结果',
ui: { intent: 'show_view', view: { title: '我的表格', columns: [{ key: 'name', label: '名称' }], rows: data } }
}
}
)
},
async deactivate() { /* 工具注销由 PluginHost 兜底 */ },
}
# 改 plugins/<your-pack>/ 源码后同步到本地插件目录(只复制,不激活)
node scripts/sync-plugins.mjs
# 然后在应用「插件」页打开开关激活
分发两轨:仓库 plugins/ 下的第一方能力包与宿主同仓演进、随应用发版,不走社区市场;社区插件源码不入主仓,推自己仓库打 knomi-plugin topic 被扫描发现。两轨互不混用。
| 字段 | 说明 |
|---|---|
id | 全局唯一标识,社区市场按 id 去重 |
name | 显示名 |
version | 语义化版本;git 来源插件在线更新按它对账 |
description | 一句话描述 |
usage | 给用户看的使用说明,强烈建议填写 |
entry | 入口 JS,导出 activate(context) 与 deactivate() |
permissions | 权限声明——声明 ≠ 授予 |
contributions | 贡献声明:扩展点 + 槽位 + 视图 |
configSchema | 用户可配置项(设置面板自动生成表单) |
agentTools | 注册的 Agent 工具名单——代码 registerAgentTool 必须在此登记,manifest 是唯一事实源(未登记属准入漏洞,宽限期告警) |
views | 注册的视图名单——代码 registerViewSchema 必须在此登记(独立字段,不进 contributions) |
depends | 依赖的其他插件 id 列表(见「发布与更新」) |
platforms | 平台适用声明(win32/darwin/linux/android/ios/harmonyos)——缺省全平台;不在声明列表的平台插件页置灰且不可启用,市场不展示 |
用 registerAgentTool(def, executor) 注册工具(需 agent:tools 权限),LLM 在对话中按 description 决定调用。执行器返回 { output, error?, ui? }——output 给 LLM 看,ui 声明 UI 行为:渲染是确定性的,无需 LLM 措辞。
| 意图 | ui payload | 渲染行为 |
|---|---|---|
start_practice | { questions, title? } | 内容区切做题模式,逐题作答、判分/自评回流 |
show_view | { view } | 经别名适配进 Deck 单卡宿主渲染(表格/表单/图表全卡片词汇;notify/quiz 类归位为意图) |
show_dashboard | { stats } | 跳转学习报告插件页(统计唯一承载于能力包页) |
open_document | { filePath } | 编辑器打开文档 |
notify | { type, message } | 轻量通知 |
open_settings | { group?, section? } | 打开设置页指定节:group=顶级分组 key,section=节地址(如 agent-hooks)——深链激活对应 tab 并高亮到节 |
request_permission | 中枢自动生成 | 权限卡(允许/仅本次/拒绝) |
show_queue | { questions, title? } | 产出进入标准复习队列,按调度器到期呈现 |
show_in_editor_panel | { view, documentId? } | 注入编辑器「相关」侧板标准槽位 |
add_graph_menu | { label, action, nodeIdMatch? } | 图谱节点右键菜单追加标准项 |
add_stage_action | { stage, slot, label, view? } | 阶段标准位置的行动按钮 |
report_outcome | PluginRunOutcome | 执行结果回传健康分,必调,缺失计失败 |
声明-执行绑定:UI 意图携带的 stage/point/slot 必须匹配本插件已通过激活校验的 contributions,否则中枢丢弃该意图并计入遥测。权限被拒时中枢自动把 PermissionDenied 转为 request_permission 权限卡,授权后自动重试原消息——插件无需处理。
contributions[] 声明插件向哪个学习闭环阶段贡献什么能力——能力挂在哪里由平台决定:
{
"id": "my-quiz-pack",
"permissions": ["db:write", "ai:chat"],
"contributions": [
{
"stage": "practice", // 六阶段之一
"point": "practice.generator", // 扩展点 ID(ingest/organize/practice/feedback/schedule/view)
"action": "生成选择题", // 用户可见的能力名
"view": "progress_list", // 产出用什么标准组件呈现
"slot": "review.empty_state" // 平台挂载槽位
}
]
}
标准槽位在应用中的位置(编号对应下表;2 号 collect.toolbar 已退役,采集入口归剪藏插件页):
| stage | slot | 呈现位置 | 策略 |
|---|---|---|---|
| workspace | 1editor.header_right | 编辑器工具栏右端挂载条动作按钮(appliesTo 词汇挂载必填;每词汇平铺 ≤2、超出溢出「更多」) | 聚合 |
| collect | 2collect.toolbar | 已退役(2026-09-28):渲染宿主随全局工作面去插件挂载移除,采集入口归剪藏插件页 | 聚合 |
| collect | 3collect.source_list | 剪藏/导入对话框「来源」列表 | 聚合 |
| organize | 4organize.editor_panel | 编辑器「相关」侧板 | 聚合 |
| organize | 5organize.graph_menu | 图谱节点右键菜单 | 聚合 |
| practice | 6review.empty_state | 复习页空态行动按钮 | 聚合 |
| practice | 7review.queue | 标准复习队列 | 数据汇入 |
| analyze | 8analyze.board | 学习中心看板标准卡位 | 聚合 |
| feedback | 9feedback.card | 做题卡片反馈区 | 数据汇入 |
另有独占型扩展点(按 key 互斥):file.handler(知识库文件点击入口,key=扩展名/MIME)、schedule.strategy(全局单 key)。
校验规则:stage/point 必须指向已注册扩展点,view 必须在视图词汇表内,slot 必须属于该 stage——不合法拒绝激活并在插件页给出原因。
编辑器工具栏右端的入口按钮是自包含声明:启用即出现、停用即消失;点击统一打开居中 Modal 操作窗口(与碎片确认卡同款窗口语义,历史 dock 停靠呈现已退役)。标准配方三步——manifest 声明入口(按钮 / panel id / appliesTo 词汇挂载)→ activate 里 registerPanel 声明面板(表单 schema)→ 实现 submit 方法。
async activate(context) {
context.registerPanel({
id: 'my-clip.form', // 面板 id(供 manifest 的 panel 字段引用)
label: '网页剪藏', // 弹窗/停靠标题
surface: 'modal', // 统一居中 Modal 窗口(dock 停靠已退役;历史声明兼容但渲染一律 Modal)
view: 'form', // 声明式视图(词汇表内)
fields: [
{ key: 'url', label: '网页地址', type: 'text', required: true },
{ key: 'dirPath', label: '保存到', type: 'target_dir' }, // 平台语义字段
],
submitLabel: '剪藏并打开',
submit: 'saveClip', // 提交调用的插件方法名(经 plugin:invoke)
})
}
async saveClip(params) {
const filePath = join(params.dirPath || fallback, 'clip.md')
await this._ctx.writeFile(filePath, md) // 需 file:write
return { filePath, title: '剪藏结果' } // 返回 filePath 自动打开文档
}
{ "contributions": [
{ "point": "tray.menu", "action": "今日晨报", "method": "generateFromTray" }
] }
method 必填(缺省拒绝激活)。返回契约 { ok?, docPath?, focus?, message?, error? }——主进程统一以系统通知反馈,docPath 存在时点击通知直达文档。命名建议用名词条目(如「今日晨报」),多态行为写进 usage 与通知文案。
{ "contributions": [
{ "point": "shortcut.bind", "key": "Ctrl+Alt+R", "action": "立即检查复习提醒", "method": "checkNowFromTray" }
] }
key 必填(Electron accelerator);被其他应用占用时该键跳过并审计——建议同插件声明多个备用键位。返回契约与 tray.menu 相同。壳层自带 Ctrl+Shift+K / Ctrl+Shift+V,避免声明这两个。
{ "contributions": [
{ "point": "nav.entry", "slot": "nav.sidebar", "key": "learning-report",
"action": "学习报告", "method": "pageLearningReport" }
] }
{ "contributions": [
{ "point": "agent.preset", "key": "出题官", "action": "出题官",
"routeHint": "出题/练习/测验类请求委派给我:…",
"systemPrompt": "你是 Knownest 的出题官……(角色定义全文,必填)" }
] }
systemPrompt 必填非空(激活期拒绝空预设)。插件预设是只读资产:设置页不管理,仅会话下拉带「插件」标记;与用户/内置预设同名让位跳过。角色定位是「叠加细则」,不要复述平台纪律(如出题接地纪律的权威源在内置 persona)。
插件页/右栏面板/工具 show_view 全部走同一套 cards 卡片词汇(由公共渲染器 Deck 统一渲染);下表 10 个 schemaType 自 v2.5 起转为别名兼容表(注册校验保留、自动映射到对应卡片),新开发请直接产出 cards。组件视觉由中枢统一实现,插件不写 CSS。
每个视图组件独立一页:点左侧菜单,就能看到该组件的全部形态、必需字段与用法代码。
结构化列表 · 必需字段 columns, rows
// cards 形态(推荐)
ui: { intent: 'show_view', view: { title: '文档列表', cards: [{ type: 'table', columns, rows }] } }
// 旧 schemaType 'table'(columns/rows 直映)自动兼容,零改动指标卡 · 必需字段 label, value
// cards 形态(推荐)
ui: { intent: 'show_view', view: { cards: [{ type: 'stats', items: [{ label: '掌握度', value: '82%' }, …] }] } }
// 旧 schemaType 'stat_card' 自动映射;show_dashboard 意图是跳学习报告页({stats}),不是渲染指标卡进度/队列条目 · 必需字段 items[{label, state}]
// cards 形态(推荐):进度条目即表格卡,state 列渲染 tones 色标
view: { cards: [{ type: 'table', columns: [{ key: 'label', label: '项目', tier: 'essential' }, { key: 'state', label: '状态' }], rows: [{ label: '已掌握', state: 'done' }, …] }] }
// 旧 schemaType 'progress_list'(items[{label,state}])自动映射做题卡片内容 · 必需字段 question, type
Attention 机制的本质是什么?
记忆的衰减遵循 曲线。
ui: { intent: 'start_practice', questions: [{ id, type: 'single_choice' | 'cloze', question, options, answer, sourceSnippet }] }
// 做题卡无 cards 形态——旧 schemaType 'quiz_card' 自动归位为此意图原文引用块(题目溯源) · 必需字段 snippet, documentId
// cards 形态(推荐):原文引用 = markdown 卡引用块
view: { cards: [{ type: 'markdown', content: '> 真实原文片段\n> —— notes/attention.md · ¶12' }] }
// 旧 schemaType 'source_quote'(snippet, documentId)自动映射为引用块+来源行变更对比确认 · 必需字段 changes[]
// cards 形态(推荐):变更对比 = markdown 卡 diff 代码块(「确认」属平台写确认流)
view: { cards: [{ type: 'markdown', content: '```diff\n# config.json\n- before\n+ after\n```' }] }
// 旧 schemaType 'diff_view'(changes[{path,before,after}])自动转换可执行项列表 · 必需字段 items[{label, action}]
// cards 形态(推荐):可执行项 = 表格卡 + 行动作
view: { cards: [{ type: 'table', columns: [{ key: 'label', label: '可执行项' }], rows: [{ label: '生成题目', action: 'generate' }], rowAction: { label: '执行', method: 'runAction', paramKey: 'action' } }] }
// 旧 schemaType 'action_list'(items[{label, action}])自动映射为表格卡+行动作图表 · 必需字段 data, chartType
// cards 形态(推荐)——注意字段名是 data,不是 series
view: { cards: [{ type: 'chart', chartType: 'line' | 'pie' | 'radar', data: [{ label, value }] }] }
// 旧 schemaType 'chart'(series)自动改名映射;radar 可加 highlight 标注主色轴参数表单 · 必需字段 fields[]
// cards 形态(推荐)
view: { cards: [{ type: 'form', title: '参数', fields: [{ key, label, type: 'text' | 'select' | 'target_dir' }], submitLabel: '提交' }] }
// 旧 schemaType 'form'(fields+submit)自动映射;交互面板场景用 registerPanel(见「挂载形态」)轻量通知 · 必需字段 type, message
ui: { intent: 'notify', type: 'success' | 'info' | 'warning' | 'error', message }
// 轻通知无 cards 形态——旧 schemaType 'notify' 自动归位为此意图页内多 Tab 分区组合各型卡片(v2.2) · 必需字段 tabs[{key, title, cards}]
{ type: 'tabs', tabs: [
{ key: 'tabA', title: 'Tab A', cards: [...同 cards 词汇] },
{ key: 'tabB', title: 'Tab B', cards: [...] },
] }Markdown 渲染(与编辑器预览同管线) · 必需字段 content
代码 等全要素,与编辑器预览共用同一渲染管线。{ type: 'markdown', title: '标题', content: '**Markdown** 文本' }密集画布(导航树/图谱/文件树)以注册视图进场:词汇通道管结构与动作,画布本体仍是组件 · 必需字段 view
{ type: 'view', view: 'knowledge.navigator', props: { focusNode: '...' }, height: 400 }在 plugin.json 声明配置数据结构,设置页由应用统一渲染表单——插件不写 UI。配置值持久化于 plugin_kv 的 config 命名空间(plugin_id 强制隔离,随快照迁移)。
"configSchema": [
{ "key": "endpoint", "label": "服务地址", "type": "string", "default": "https://api.example.com" },
{ "key": "mode", "label": "模式", "type": "select",
"options": [{ "value": "fast", "label": "快速" }, { "value": "deep", "label": "深度" }] },
{ "key": "presets", "label": "预设", "type": "list",
"item": [
{ "key": "id", "label": "ID", "type": "string", "required": true },
{ "key": "prompt", "label": "提示词", "type": "text", "required": true }
] }
]
未声明默认只读(file:read + db:read + agent:tools);激活时用户逐项确认:允许 / 仅本次 / 拒绝;被拒时中枢自动展示权限卡,授权后重试原消息。做题入库(insertQuestion)需 db:write,且 sourceSnippet 必填真实原文片段;作答回流由渲染进程 IPC 处理,能力包无需参与。
require 白名单仅 path / os / fs / util / url / events,网络、子进程、worker 一律拒绝。
唯一通道是 net:http 宿主代理:仅 http(s),20 秒超时、8MB 上限、全量审计。
单插件最多 20 个工具;storage 每值 ≤ 1MB、每插件 ≤ 50MB,超限抛错并入审计。
activate 卡死超 90 秒或心跳 15 秒失联,宿主击杀并自动回滚。
插件持久化唯二合法位置,两者都自动随全量快照与云端同步——不需要也不允许自建导出/导入,更不要写 userData 旁路文件。
| 位置 | 用途 | 快照迁移 |
|---|---|---|
context.storage | 结构化状态:配置值、会话、草稿、缓存 | 随全量快照 |
context.writeFile | 文档类产出(进索引) | 随全量快照 |
五个只读原语读取知识库结构化本体(体系树/画像/关系/概念),v2.14 起并入统一数据资产目录(原 ctx.ontology* 门退役):kernel/ontology-get(点查)、kernel/ontology-neighbors(邻域图)、kernel/ontology-subtree(双树子树切片)、kernel/ontology-search(标题与标引词检索)、kernel/ontology-path(概念先修链与文档桥)。消费走统一门 ctx.invokeAsset('kernel/ontology-…', method, [input]),均需 db:read 权限。
plugin.json 顶层可选声明 ontologyScope: { categories: ["类目路径前缀"], repos: ["仓库名"] }——声明即钳制:宿主对每个响应按类目/仓库后过滤(范围外文档被剔除,ontologyGet 返回 found:false + OUT_OF_SCOPE);未声明 = 全库只读(多词条 OR、双维 AND;未来收紧为「未声明即拒绝」会随发版公告)。词汇封闭只增不破:资产 id/method/objectRef type/kinds 不删不改,新能力只追加。
插件需要周期性后台任务(定时检查/定点生成/轮询催办)时,在 plugin.json 顶层声明 schedules,不要自滚 setInterval——宿主统一托管:到点直接调用你导出的 method,任务自动进「后台任务台账」(设置页可见、可立即运行),并享受忙时让路与错过补跑。
"schedules": [
{
"id": "auto-weave",
"every": "1h",
"missPolicy": "skip",
"method": "runAutoWeave",
"description": "自动织网检查"
}
]
插件不只有 UI——你维护/产出的数据本身就是能力。在 plugin.json 顶层声明 provides.data(数据资产)与 consumes(数据粒度消费),即进入全局「数据资产目录」:能力地图「数据资产」Tab(默认视图)、Agent 的 list_data_assets 工具、其他插件的 consumes 都以此为唯一发现面。创建插件时回答物模型三问:你有什么数据 / 你怎么被发现 / 你消费什么。
"provides": {
"data": [
{
"id": "error-analyses",
"title": "错因归因记录",
"schema": "行字段: questionId, category, reactionMs, answeredAt",
"method": "listAnalyses",
"events": ["mistake-analyzer.error-analyses.changed"],
"version": 1
}
]
},
"consumes": [
{ "asset": "kernel/fragments", "optional": true }
]
插件不用写任何 i18n 代码——在 plugin.json 顶层声明可选 i18n 词典(源文为键),平台在渲染端按当前界面语言替换你贡献与页面载荷里的 UI 文案;未命中恒等回退原文,中文用户零词典零行为变化。
"i18n": {
"en-US": {
"题库": "Question Bank",
"开始做题": "Start Practice"
}
}
每次工具执行必须经 report_outcome 回传结果遥测:
const result = await doGenerate(args)
context.reportOutcome({
status: 'partial', // success | partial | failed
produced: { itemsValid: 8, itemsRejected: 4,
rejectReasons: ['missing_source_snippet', 'schema_mismatch'] },
cost: { llmCalls: 2, tokens: 5300, durationMs: 8200 },
userAction: 'pending' // pending|accepted|rejected|modified
})
健康分每周按可靠性 / 采纳率 / 学习贡献 / 负反馈率计算;低分插件自动生成「插件体检」任务——Agent 拉取 rejectReasons 与差评样本定位问题 → 修复 → 黄金用例回归 → 健康分对比。连续两周期低于阈值,插件页亮黄灯并建议停用。遥测缺失本身计为一次 failed。
把插件推送到自己的 Git 仓库并添加 GitHub topic knomi-plugin。社区市场程序化扫描:Search API 按 star 降序拉取 → 逐仓库校验 plugin.json(id/name/version/entry 必填)→ 校验通过才展示,结果缓存 10 分钟。
{ "id": "mistake-analyzer", "depends": ["quiz-maker"] }
平台对仓库文件的写/删/改统一经写漏斗广播单一事件源(doc:changed),知识树、图谱、面板与插件订阅同一事件多路消费。你的插件用 ctx.onDocChanged 订阅——依赖的文件被删除会收到 type: 'delete',重命名是 delete+write 两条事件,按下方语义处理就不会「文件没了插件还不知道」。
| API | 语义 | 坑 |
|---|---|---|
ctx.readFile(path) | 仅返回已入库文档内容;未入库路径返回空串不抛错 | 不要用空串判断文件不存在——存在性判断改用 ctx.query 查 documents 表 |
ctx.query(...) | 返回行字段为驼峰命名(file_path → filePath) | 按 SQL 原始列名取值会得到 undefined |
ctx.timers.setInterval | 宿主托管:停用/卸载自动清理,interval 下限 1 秒 | 勿自滚 setInterval 兜底——会绕过停用清理 |
ctx.onDocChanged(cb) | 订阅文档变更推送(v2.6):文件写/删/改即时回调 {filePath, type: 'write'|'delete'}(rename=旧路径 delete+新路径 write),返回取消订阅函数;file:read 权限门控,未授权激活期订阅即抛(fail-closed) | 事件只作刷新信号——用 filePath 回拉权威数据,勿缓存副本;写文件仍走 ctx.writeFile 正常漏斗(防自激循环须自行判重);回调在插件子进程本地执行——事件经宿主总线按需转发,未订阅的沙箱不被唤醒 |
ctx.getDocuments() | 返回 camelCase 行(filePath,非 file_path) | 按 SQL 原始蛇形列名取值会得到 undefined |
ctx.invokePluginMethod / ctx.invoke | 仅内置插件可用(plugin:manage 门控);沙箱 RPC 清单不含 invokePluginMethod | 沙箱插件做同插件内动作直调内部函数即可——自重入经互调通道必被拒 |
ctx.invokeAsset | 统一数据资产门(v2.14,详见上方「本体数据读取」与「数据资产契约」节):kernel/* 直调内核资产(本体族按插件 ontologyScope 声明钳制);其他 provider/asset 等价互调 | 视图=查询的投影,不要绕过资产自拼 SQL 重建本体形状(表结构非契约会漂移);范围外文档被宿主静默剔除(ontology-get 返回 found:false + OUT_OF_SCOPE),不是缺陷 |
需要用户拍板的事项由平台统一确认总线托管——待裁决事项排队、同一时刻只弹队头一张卡、新确认静默入队不打扰、可最小化稍后处理(当前首消费方=碎片落点确认卡)。能力包暂无确认卡贡献点:需要用户澄清用 ask_user,写文件的把关走平台 Diff 确认流。两类确认卡都有会话隔离保证——只在发起它的对话弹出,新建/切换对话后回原对话处理,不会窜到别的对话。
Knownest 是多面板应用,文件与业务数据在面板间相互关联——平台用事件解耦这种联动。能力包可订阅下方四族事件,据此做「收件箱收到新碎片自动分类」「仓库变更重建索引」这类有意思的插件。事件只作刷新信号:收到后用 ctx.readFile / ctx.query 回拉权威数据,不要缓存副本,也不要基于事件直接改文件(写操作仍走 ctx.writeFile 正常漏斗,防自激循环须自行判重)。
| 事件(订阅 API) | 载荷 | 触发时机 |
|---|---|---|
doc-changedctx.onDocChanged(cb) | {filePath, type: 'write'|'delete'} | 仓库目录内文件写入/新建/删除;重命名是 delete+write 两条事件;编辑器保存、插件写文件、碎片落盘共用同一写漏斗 |
inbox-changedctx.onInboxChanged(cb) | {domain:'inbox', type, filePath, status?, title?} | arrived=碎片落盘(手机投递/桌面新增);renamed=标题改名;status=加工状态流转(pending / processing / needs-confirm / processed,含产物被删后的回退) |
repo-changedctx.onRepoChanged(cb) | {domain:'repo', type, repoId, name} | added=仓库登记成功;removed=仓库移除成功(sys-hub 系统仓不可删,不会产生 removed) |
ontology-changedctx.onOntologyChanged(cb) | {domain:'ontology', type:'changed', reason, conceptId?} | tree=体系树投影变化(聚合后一次);relation=文档关系边增删;concept=概念/关系状态机流转。收到后用 ctx.ontology* 原语回拉权威数据 |
四个事件族订阅语义一致:首次订阅向宿主报备(按需转发,未订阅的沙箱不被事件唤醒);回调在插件子进程本地执行;插件停用/卸载自动清理;file:read 权限未授权时激活期订阅即抛(fail-closed)。
平台内部还有渲染层与主进程自用的事件通道(doc:changed 微批广播、碎片加工进度/报告/确认卡、插件启停、系统仓同步、应用更新、体系树版本信号)以及调度域产品事件(domain:'schedule',task.started/finished/failed——声明式任务的执行生命周期,FR-169 目录成员;台账数字以 schedule:list 为权威)——它们由平台内置面消费,插件不可直接使用,列此仅供理解产品全貌。
module.exports = {
async activate(ctx) {
// 收件箱哨兵:新碎片到达即触发(自动分类 / 提醒 / 统计)
ctx.onInboxChanged((e) => {
if (e.type !== 'arrived') return
ctx.readFile(e.filePath).then((content) => { /* 回拉权威数据后处理 */ })
})
},
}
| 插件 | 示范点 |
|---|---|
| text-clipper | workspace.action 全链路:modal + form + target_dir + submit 返回 filePath |
| morning-report | tray.menu 托盘挂载;nav.entry v2 复合页 + detail 下钻 + tabs 双分区 |
| study-reminder | shortcut.bind 快捷键与备用键位 |
| study-analytics | nav.entry v3 全声明式学习报告页(summary+今日焦点+三 Tab,capability 去练/detail 错题回看) |
| quiz-maker | start_practice 就地做题;agent.preset「出题官」 |
| knomi-agent | MCP 一等工具桥(mcp__server__tool 直调)+ agent.preset 内置人设 + configSchema(agent_presets) |
Knownest 支持将知识库中的文档与题目打包为 .knomi-share 文件(ADR-024 附录 A),接收方导入后即可直接练习。你的作答记录与复习进度不随包分享。
导出:知识体系 Tab → 「导出分享包」→ 勾选目录 → 选择 license 与署名 → 生成文件。导入:知识体系 Tab → 「导入分享包」→ 选择 .knomi-share 文件 → 预览确认 → 题目立即可练。
发布与订阅:将 .knomi-share 上传到你自己的 GitHub 公开仓库(根目录含 manifest.json),通过分享中枢插件(share-hub)订阅他人的知识包仓库,一键检查更新。
所有授权与导出操作均可在设置页「数据与授权」查看审计记录。你的作答与复习进度永远只在本地。
Knownest 的商业边界由 ADR-024(商业边界宪法)约束:本地数据的一切能力——知识库、出题复习、Agent(自带 Key 的 BYOK 模式)、插件生态、知识包导出导入、Anki 通道——永久免费,不做任何本地功能解锁付费。
未来的订阅服务只有一类:在本地能力之上的增值服务(内容供给、零知识加密同步、分享托管),且必须通过「零知识或显式发布」测试——服务器只见到密文或你主动公开的内容。付费插件=服务配额包装,不卖本地功能。默认零遥测:任何统计上报都需要你在设置中显式开启。