@xingjisoft/neutrino 0.6.2 → 0.7.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/README.md +6 -1
- package/assets/fast-planner.txt +57 -0
- package/assets/fast-replanner.txt +28 -0
- package/dist/agents.d.ts +25 -0
- package/dist/app.d.ts +206 -0
- package/dist/app.js +15 -0
- package/dist/background.d.ts +96 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +40 -3
- package/dist/browser.d.ts +18 -0
- package/dist/clipboard.d.ts +16 -0
- package/dist/colors.d.ts +29 -0
- package/dist/compact.d.ts +52 -0
- package/dist/config.d.ts +221 -0
- package/dist/config.js +19 -7
- package/dist/cwd.d.ts +19 -0
- package/dist/fast/artifacts.d.ts +26 -0
- package/dist/fast/artifacts.js +109 -0
- package/dist/fast/engine.d.ts +78 -0
- package/dist/fast/engine.js +657 -0
- package/dist/fast/evidence.d.ts +21 -0
- package/dist/fast/evidence.js +68 -0
- package/dist/fast/planner.d.ts +10 -0
- package/dist/fast/planner.js +51 -0
- package/dist/fast/pool.d.ts +17 -0
- package/dist/fast/pool.js +78 -0
- package/dist/fast/scheduler.d.ts +54 -0
- package/dist/fast/scheduler.js +383 -0
- package/dist/fast/types.d.ts +100 -0
- package/dist/fast/types.js +21 -0
- package/dist/fast/worker.d.ts +23 -0
- package/dist/fast/worker.js +185 -0
- package/dist/header.d.ts +3 -0
- package/dist/index.d.ts +5 -0
- package/dist/llm/approval.d.ts +204 -0
- package/dist/llm/approval.js +14 -3
- package/dist/llm/client.d.ts +118 -0
- package/dist/llm/client.js +57 -8
- package/dist/llm/codeExecutor.d.ts +14 -0
- package/dist/llm/codemode.d.ts +15 -0
- package/dist/llm/context.d.ts +29 -0
- package/dist/llm/diagnostics.d.ts +91 -0
- package/dist/llm/diagnostics.js +242 -0
- package/dist/llm/plan.d.ts +148 -0
- package/dist/llm/retry.d.ts +80 -0
- package/dist/llm/risk.d.ts +21 -0
- package/dist/llm/risk.js +7 -0
- package/dist/llm/runtime.d.ts +189 -0
- package/dist/llm/runtime.js +77 -4
- package/dist/llm/search.d.ts +2 -0
- package/dist/llm/searchNetwork.d.ts +8 -0
- package/dist/llm/subagent.d.ts +112 -0
- package/dist/llm/subagent.js +4 -2
- package/dist/llm/tools.d.ts +20 -0
- package/dist/llm/tools.js +4 -1
- package/dist/llm/workspace.d.ts +6 -0
- package/dist/llm/workspace.js +271 -0
- package/dist/markdown.d.ts +58 -0
- package/dist/migration.d.ts +8 -0
- package/dist/persistence.d.ts +14 -0
- package/dist/plugins/catalog.d.ts +20 -0
- package/dist/plugins/catalog.js +45 -0
- package/dist/plugins/cli.d.ts +1 -0
- package/dist/plugins/cli.js +106 -0
- package/dist/plugins/host.d.ts +121 -0
- package/dist/plugins/host.js +450 -0
- package/dist/plugins/manager.d.ts +24 -0
- package/dist/plugins/manager.js +288 -0
- package/dist/plugins/package.d.ts +5 -0
- package/dist/plugins/package.js +53 -0
- package/dist/plugins/runner.d.ts +1 -0
- package/dist/plugins/runner.js +227 -0
- package/dist/plugins/session.d.ts +12 -0
- package/dist/plugins/session.js +97 -0
- package/dist/plugins/terminal.d.ts +22 -0
- package/dist/plugins/terminal.js +33 -0
- package/dist/plugins/types.d.ts +178 -0
- package/dist/plugins/types.js +6 -0
- package/dist/plugins/validation.d.ts +14 -0
- package/dist/plugins/validation.js +174 -0
- package/dist/plugins/web-sdk.d.ts +58 -0
- package/dist/plugins/web-sdk.js +1 -0
- package/dist/pro/agents.d.ts +34 -0
- package/dist/pro/config.d.ts +75 -0
- package/dist/pro/config.js +3 -2
- package/dist/pro/preflight.d.ts +21 -0
- package/dist/sanitize.d.ts +34 -0
- package/dist/screens/agentConversation.d.ts +28 -0
- package/dist/screens/agentHistory.d.ts +25 -0
- package/dist/screens/agentSelect.d.ts +16 -0
- package/dist/screens/chat.d.ts +292 -0
- package/dist/screens/chat.js +139 -21
- package/dist/screens/history.d.ts +23 -0
- package/dist/screens/modelSelect.d.ts +29 -0
- package/dist/screens/plugins.d.ts +29 -0
- package/dist/screens/plugins.js +196 -0
- package/dist/screens/settings.d.ts +42 -0
- package/dist/screens/start.d.ts +43 -0
- package/dist/screens/start.js +25 -17
- package/dist/screens/updatePrompt.d.ts +41 -0
- package/dist/selection.d.ts +75 -0
- package/dist/state.d.ts +26 -0
- package/dist/terminal/buffer.d.ts +47 -0
- package/dist/terminal/input.d.ts +70 -0
- package/dist/terminal/renderer.d.ts +43 -0
- package/dist/terminal/restore.d.ts +41 -0
- package/dist/terminal/screen.d.ts +57 -0
- package/dist/tray.d.ts +14 -0
- package/dist/ui.d.ts +123 -0
- package/dist/update.d.ts +71 -0
- package/dist/updateWatch.d.ts +43 -0
- package/dist/web/approvalQueue.d.ts +8 -0
- package/dist/web/approvalQueue.js +59 -0
- package/dist/web/auth.d.ts +14 -0
- package/dist/web/clientState.d.ts +16 -0
- package/dist/web/folderPicker.d.ts +34 -0
- package/dist/web/folderPicker.js +544 -0
- package/dist/web/hub.d.ts +213 -0
- package/dist/web/hub.js +14 -2
- package/dist/web/localApi.d.ts +11 -0
- package/dist/web/localApi.js +260 -0
- package/dist/web/plugins.d.ts +8 -0
- package/dist/web/plugins.js +64 -0
- package/dist/web/server.d.ts +81 -0
- package/dist/web/server.js +127 -19
- package/dist/web/service.d.ts +7 -0
- package/dist/web/service.js +1 -0
- package/dist/web/session.d.ts +176 -0
- package/dist/web/session.js +153 -19
- package/dist/web/settings.d.ts +65 -0
- package/dist/web/terminalBridge.d.ts +15 -0
- package/dist/web/terminalBridge.js +8 -2
- package/dist/width.d.ts +6 -0
- package/docs/plugins/README.md +126 -0
- package/docs/plugins/agent-sdk.md +92 -0
- package/docs/plugins/architecture.md +64 -0
- package/docs/plugins/compatibility.md +34 -0
- package/docs/plugins/development.md +55 -0
- package/docs/plugins/manifest.md +59 -0
- package/docs/plugins/manifest.schema.json +286 -0
- package/docs/plugins/security.md +53 -0
- package/docs/plugins/skills-prompts.md +69 -0
- package/docs/plugins/ui-sdk.md +109 -0
- package/examples/local-api.py +105 -0
- package/examples/plugins/cards/card.html +6 -0
- package/examples/plugins/cards/neutrino.plugin.json +42 -0
- package/examples/plugins/composer/editor.html +10 -0
- package/examples/plugins/composer/neutrino.plugin.json +10 -0
- package/examples/plugins/function-tools/agent.js +32 -0
- package/examples/plugins/function-tools/neutrino.plugin.json +15 -0
- package/examples/plugins/menus-tabs/neutrino.plugin.json +15 -0
- package/examples/plugins/menus-tabs/panel.html +6 -0
- package/examples/plugins/skills-prompts/neutrino.plugin.json +13 -0
- package/examples/plugins/skills-prompts/prompts/evidence.md +1 -0
- package/examples/plugins/skills-prompts/prompts/reviewer.md +1 -0
- package/examples/plugins/skills-prompts/skills/review/SKILL.md +8 -0
- package/examples/plugins/theme/neutrino.plugin.json +12 -0
- package/package.json +66 -42
- package/web/LOCAL-API.md +65 -0
- package/web/README.md +27 -6
- package/web/app.js +201 -32
- package/web/i18n.js +15 -0
- package/web/index.html +3 -1
- package/web/plugins.css +10 -0
- package/web/plugins.js +230 -0
- package/web/style.css +11 -2
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Agent SDK
|
|
2
|
+
|
|
3
|
+
TypeScript 类型从 `@xingjisoft/neutrino/plugin` 导入。默认沙箱只提供该模块的 `definePlugin` 辅助函数,其余依赖必须打包进入口。
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { definePlugin } from '@xingjisoft/neutrino/plugin';
|
|
7
|
+
|
|
8
|
+
export default definePlugin({
|
|
9
|
+
activate(ctx) {
|
|
10
|
+
ctx.tools.register({
|
|
11
|
+
name: 'greet',
|
|
12
|
+
description: 'Return a greeting.',
|
|
13
|
+
parameters: {
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: { name: { type: 'string' } },
|
|
16
|
+
required: ['name'],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
effects: [],
|
|
20
|
+
execute: args => `Hello ${args.name}`,
|
|
21
|
+
});
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Context 与注册
|
|
27
|
+
|
|
28
|
+
`ctx.id` 是插件 ID,`ctx.config` 是当前回合的只读配置快照,`ctx.scope` 是激活时的 profile、cwd、sessionId、role 和 request。执行函数的第二个参数是当前调用作用域;子 Agent 的 role 和 runId 应读取该参数,不要使用激活时的主 Agent role 推断权限。
|
|
29
|
+
|
|
30
|
+
`ctx.tools.register(spec)` 和 `ctx.commands.register(spec)` 接受 name、description、parameters、effects 和 execute。工具名为最多 40 字符的小写字母、数字、下划线和短横线,以字母开头;工具可声明适用的 `roles`。
|
|
31
|
+
|
|
32
|
+
工具供模型调用;命令供用户主动调用,不需要模型回合:
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
/plugin acme.example/greet {"name":"Neutrino"}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
返回字符串或 JSON 可序列化结果。工具结果最终规范化为字符串并限长。所有宿主操作必须 await。高风险工具和原生工具的参数 Schema 自动加入必填的 reason 字段。
|
|
39
|
+
|
|
40
|
+
`effects` 必填,可以是空数组,或 `filesystem.read`、`filesystem.write`、`network`、`process` 的组合。它与清单 permissions 同时检查。工具声明只读不等于任意代码获得了只读隔离;原生插件在只读 / 限定写入路径的子任务中不可用。
|
|
41
|
+
|
|
42
|
+
## 宿主能力
|
|
43
|
+
|
|
44
|
+
| 接口 | 效果 / 权限 | 返回 |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| `ctx.fs.read(path, reason)` | filesystem.read | 文件文本 |
|
|
47
|
+
| `ctx.fs.list(path, reason)` | filesystem.read | 目录文本 |
|
|
48
|
+
| `ctx.fs.write(path, content, reason)` | filesystem.write | 执行结果文本 |
|
|
49
|
+
| `ctx.net.fetch(url, reason)` | network | `{ status, body }`,仅 GET,HTTP(S),不跟随重定向,最大 1 MB |
|
|
50
|
+
| `ctx.process.run(command, reason)` | process | 命令输出 |
|
|
51
|
+
| `ctx.storage.get(key)` | storage | JSON 值或 null |
|
|
52
|
+
| `ctx.storage.set(key, value)` | storage | Promise<void> |
|
|
53
|
+
| `ctx.log(message)` | 无额外效果 | 有长度限制的诊断日志 |
|
|
54
|
+
|
|
55
|
+
文件、网络、进程能力仅在活动会话的执行回调中可用,进入相同的 TaskScope、预算、审批和取消链。路径相对于会话 cwd。storage 用于插件自己的数据,不提供任意文件访问;单值最多 256 KB、每插件最多 128 个键和 8 MiB,键只能包含字母、数字、点、下划线、短横线。
|
|
56
|
+
|
|
57
|
+
## 钩子和事件
|
|
58
|
+
|
|
59
|
+
`ctx.hooks.add(name, handler)` 注册顺序执行的钩子。输入是副本,原始用户消息和已审批参数不受原地修改影响。
|
|
60
|
+
|
|
61
|
+
| 名称 | 输入 | 允许的结果 |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| request.before | provider、model、role、toolCount | `{ systemSuffix?: string, deny?: boolean, reason?: string }` |
|
|
64
|
+
| tool.before | name、arguments | `{ deny?: boolean, reason?: string }` |
|
|
65
|
+
|
|
66
|
+
请求钩子只在工具回合调用;审批评审模型的提示词不经过插件拼接。工具钩子发生在原审批入口之前,只能收窄决策,不能把宿主拒绝变成允许,也不能修改已审批参数。钩子失败会拒绝对应操作。请求补充文本会记录到任务 journal。
|
|
67
|
+
|
|
68
|
+
`ctx.events.on(name, handler)` 注册观察器:
|
|
69
|
+
|
|
70
|
+
| 名称 | 内容 |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| turn.started | 当前原始请求 |
|
|
73
|
+
| tool.finished | 工具名、状态、证据 ID |
|
|
74
|
+
| turn.finished | 取消状态、工具证据概要 |
|
|
75
|
+
|
|
76
|
+
观察器失败记录为插件错误,不改变主任务的结果。钩子和事件没有文件、网络、进程效果,不能通过观察器偷偷启动外部操作;可以使用获授的插件 storage。处理函数应快速结束。
|
|
77
|
+
|
|
78
|
+
## 提示词、Skill、UI 与插件服务
|
|
79
|
+
|
|
80
|
+
`ctx.prompts.register(spec)` 使用与清单相同的提示词定义。`ctx.skills.register(file)` 注册包内 skill 资源。`ctx.ui.register(spec)` 使用与清单相同的 UI 定义;动态 HTML 视图路径必须出现在 `webAssets`。动态 UI 会随会话快照发布,若希望在尚未开始回合时展示,请在清单中声明。
|
|
81
|
+
|
|
82
|
+
插件之间通过命令作为服务边界:
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
const result = await ctx.services.call('acme.helper', 'summarize', { text });
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
需在 dependencies 或 optionalDependencies 中声明目标插件。被调用命令的外部效果不能超过调用方已声明的效果。循环调用和超过八层的调用会被拒绝。
|
|
89
|
+
|
|
90
|
+
## 清理
|
|
91
|
+
|
|
92
|
+
注册函数返回 `{ dispose() }`。`ctx.effect(dispose)` 可登记资源清理;activate 也可返回清理函数。effect 按逆序清理。结束回合时宿主释放注册表与进程。沙箱没有 Node 计时器、全局 fetch、文件系统或 Node 模块;异步工作通过宿主桥接完成。
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 架构、作用域与生命周期
|
|
2
|
+
|
|
3
|
+
## 组成
|
|
4
|
+
|
|
5
|
+
`src/plugins/types.ts` 是无应用启动副作用的公开 Agent SDK。`validation.ts` 校验包和配置,`manager.ts` 管理安装状态,`package.ts` 处理离线包,`host.ts` 管理回合注册表与子进程,`runner.ts` 是私有脚本进程,`session.ts` 是终端和 Web 共用的接入层。
|
|
6
|
+
|
|
7
|
+
现有终端和 Web 保留各自的输入、渲染及会话对象。两者通过 `runPluginTurn()` 创建相同的插件组合,工具发现、插件执行、提示词片段、执行策略和证据账本使用同一层逻辑。`executeTool()` 和现有工具定义函数保留为兼容入口;新增插件工具经注册表分发,内置工具继续保持原行为。
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
CLI / Web API / TUI 管理器
|
|
11
|
+
→ 受锁保护的插件状态与不可变包目录
|
|
12
|
+
→ 每回合 PluginHost
|
|
13
|
+
→ 工具 / 命令 / 提示词 / Skill / UI / 钩子注册表
|
|
14
|
+
→ 每个代码插件一个私有进程
|
|
15
|
+
→ QuickJS(默认)或明确信任的 Node ESM
|
|
16
|
+
→ 宿主能力桥接
|
|
17
|
+
→ 当前 TaskScope → 风险评估 → 原审批入口 → TaskRuntime 证据
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
浏览器读取 UI 清单时不会激活后端插件。HTML/JS 视图运行在独立 opaque-origin iframe,通过有能力检查的消息接口访问宿主。
|
|
21
|
+
|
|
22
|
+
## 状态布局
|
|
23
|
+
|
|
24
|
+
默认位于 `~/.neutrino/plugins`:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
state.json # version、revision、包指针、各 profile 配置
|
|
28
|
+
packages/<id>/<version>-<hash>/ # 安装时复制的包,不就地更新
|
|
29
|
+
data/<id>/<key>.json # 插件持久数据
|
|
30
|
+
.lock/ # 短期管理事务锁
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`NEUTRINO_HOME` 可选择独立的 Neutrino 用户数据目录;`NEUTRINO_PLUGIN_HOME` 单独覆盖插件目录。测试应使用临时目录,不修改真实用户安装。
|
|
34
|
+
|
|
35
|
+
管理写操作使用互斥锁、revision 检查和临时文件 rename。Web 保存携带读取时的 revision,并发修改返回 409,用户刷新后重试。安装前校验路径与清单,复制后再次校验完整性。
|
|
36
|
+
|
|
37
|
+
## 作用域
|
|
38
|
+
|
|
39
|
+
启用状态按 profile 保存。项目覆盖层使用规范化的真实绝对目录作为键,覆盖同 profile 的默认启用状态,并合并插件配置。项目配置来自用户通过管理器的明确操作,仓库内的任意文件不会自行启用代码。
|
|
40
|
+
|
|
41
|
+
每个回合创建一次 PluginHost。它固定已启用的包、配置和组件选择,保存插件 ID、版本、完整性散列和配置快照。该组合通过 `TaskRuntime.plugins` 由主 Agent、Pro 和子 Agent 共享。子 Agent 保留自己的角色、runId、AbortSignal 和权限,受限工具集合在子作用域内再次筛选。
|
|
42
|
+
|
|
43
|
+
终端拥有的会话在终端进程加载后端插件;后台 Web 拥有的会话在后台进程加载。浏览器不运行 Agent 后端代码。插件没有隐式的机器级常驻实例;文件监听等资源应在 activate 注册清理函数,随回合结束释放。
|
|
44
|
+
|
|
45
|
+
## 生命周期
|
|
46
|
+
|
|
47
|
+
1. 读取已启用的安装记录,解析必需依赖与兼容的可选依赖。
|
|
48
|
+
2. 按依赖顺序校验完整性、API 版本、Profile、配置和原生信任。
|
|
49
|
+
3. 启动代码插件进程,执行 `activate(ctx)`,收集有数量上限的注册项。
|
|
50
|
+
4. 校验注册项、权限、重复名称和资源路径;激活失败则撤销该插件的贡献,跳过依赖它的插件。
|
|
51
|
+
5. 发布 `turn.started`,执行普通回合或 `/plugin` 用户命令。
|
|
52
|
+
6. 发布 `turn.finished`,按逆序释放 effect 和插件进程。
|
|
53
|
+
|
|
54
|
+
`activate()` 期间注册贡献;激活完成后注册表固定。每项注册返回 `dispose()`。注册表与执行回调由同一实例拥有,卸载不会残留全局工具。
|
|
55
|
+
|
|
56
|
+
QuickJS 每个执行片段有 CPU 中断限制,内存上限 32 MiB。插件回调在没有宿主操作等待时默认 15 秒超时。等待宿主审批时暂停该计时,仍受任务取消和任务预算控制。清理最多等待一秒,然后结束进程。
|
|
57
|
+
|
|
58
|
+
宿主操作串行处理,避免一个插件中的 `Promise.all` 覆盖待处理审批。回调必须 await 宿主操作;提前返回会取消在途操作并报告错误。每回调最多 256 个宿主调用、64 个待处理调用。
|
|
59
|
+
|
|
60
|
+
## 会话和恢复
|
|
61
|
+
|
|
62
|
+
`task_run` 的可选字段记录插件版本、错误、动态 UI 元数据及最近的提示词组装。任务 journal 保留插件组合和模型可见的片段。工具结果始终保留文本形式,因此插件缺失时仍能阅读历史。
|
|
63
|
+
|
|
64
|
+
旧会话不要求迁移为新格式。恢复会话不会调用已保存的插件处理函数或重放工具账本。新回合使用当前已启用的组合。精确重建执行环境时,应恢复记录中的插件版本、散列与配置,并人工发起新的执行。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# 兼容性与迁移
|
|
2
|
+
|
|
3
|
+
## 现有 Neutrino 行为
|
|
4
|
+
|
|
5
|
+
没有已启用插件时,内置工具、模型调用、历史、压缩、计划、PTC、子 Agent、审批和 Pro 的调用入口继续保留。工具定义函数、executeTool 和 TaskRuntime 仍然存在。
|
|
6
|
+
|
|
7
|
+
启用插件后,工具通过当前回合的注册表发现;PTC 获取同一份工具描述,Pro 与子 Agent 使用相同组合。子任务再次按角色与只读 / 写入范围筛选。插件不能通过原生工具绕过受限子任务。
|
|
8
|
+
|
|
9
|
+
新增会话字段均位于可选的 task_run 插件元数据中。旧文件可直接读取;未知插件不使历史读取失败。模型上下文与显示历史继续分开;插件卡片只替换显示,工具结果的文本仍保留。
|
|
10
|
+
|
|
11
|
+
## 从私有改造迁移
|
|
12
|
+
|
|
13
|
+
| 原做法 | 插件接口 |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| 修改 tools.ts 固定工具列表与分发 | ctx.tools.register |
|
|
16
|
+
| 修改主提示词文本 | contributes.prompts / ctx.prompts.register |
|
|
17
|
+
| 在界面中插入按钮和页面 | contributes.ui / ctx.ui.register |
|
|
18
|
+
| 修改全局 CSS | contributes.theme 或插件 iframe 样式 |
|
|
19
|
+
| 修改输入框内部状态 | composer 的版本化草稿 API |
|
|
20
|
+
| 添加脚本命令 | ctx.commands.register + /plugin |
|
|
21
|
+
| 调用内部审批、文件或进程对象 | ctx.fs / ctx.net / ctx.process |
|
|
22
|
+
| 给所有会话增加全局监听器 | ctx.events.on / ctx.effect,按回合清理 |
|
|
23
|
+
|
|
24
|
+
UI 应声明适用平台。终端不解析 HTML,也不把浏览器样式当作终端渲染指令。Web 替换组件需要用户选择提供者,不根据安装顺序抢占。
|
|
25
|
+
|
|
26
|
+
## 与 DeepSeek Harness 的关系
|
|
27
|
+
|
|
28
|
+
本系统借鉴 Context、作用域、可逆注册、类型化事件和 Profile 组合。Neutrino 使用自己的包结构和 SDK,不能直接加载 Cordis/DSH 二进制插件。
|
|
29
|
+
|
|
30
|
+
迁移 DSH 插件时,将服务依赖转换为插件依赖,将模型工具转换为 tools.register,将提示词片段转换为 prompts.register,将 UI 转换为声明插槽和 iframe SDK,将清理逻辑登记为 effect。需要任意 Node API 的代码使用原生模式并明确披露信任要求,或改成受限宿主能力。
|
|
31
|
+
|
|
32
|
+
## v1 的边界
|
|
33
|
+
|
|
34
|
+
此版公开工具、命令、事件、两个流程钩子、提示词、skill、UI 和存储。模型适配器、Agent 驱动替换、任意后端自定义 HTTP 路由、机器级常驻服务和远程插件市场没有公开契约。插件可通过已公开能力实现功能增强;不要通过未记录的私有类实现这些接口。
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# 开发、打包、测试与发布
|
|
2
|
+
|
|
3
|
+
## 创建插件
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
neutrino plugin create ./my-plugin
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
命令复制文本工具示例,不覆盖现有目录。修改清单 ID、名称、版本和权限,再安装该目录。安装复制源码快照;编辑源文件后执行 update 才会进入新回合。
|
|
10
|
+
|
|
11
|
+
使用 TypeScript 时安装 Neutrino 的开发依赖并导入 `@xingjisoft/neutrino/plugin` 类型。默认沙箱可处理单文件 JS/TS;涉及第三方依赖时用项目现有构建工具打包为一个文件,不要依赖运行时下载。浏览器入口也需打包为单个 ESM。
|
|
12
|
+
|
|
13
|
+
native 后端使用 `.mjs`,或随包提供 `package.json` 且设置 `"type": "module"`。Node 不会自动把任意 `.js` 当作 ESM。使用原生依赖时将其打包或按 Node 的标准解析规则部署;安装器不复制 node_modules,也不会执行 install 脚本。
|
|
14
|
+
|
|
15
|
+
## 调试循环
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
neutrino plugin install ./my-plugin
|
|
19
|
+
neutrino plugin enable acme.my-plugin
|
|
20
|
+
neutrino plugin doctor
|
|
21
|
+
# 编辑源文件后
|
|
22
|
+
neutrino plugin update acme.my-plugin
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
doctor 激活已启用的后端、显示工具和命令及错误,然后清理实例。它没有活动会话,文件、进程和网络桥接不可用。activate 应只注册贡献,不执行用户任务。
|
|
26
|
+
|
|
27
|
+
配置表单与命令行配置走同一 Schema。通过 `ctx.log` 查看回合诊断;实际工具调用和插件提示词保存在任务 journal。遇到重复名称、未知 Schema 关键字、资源路径错误、未声明效果、原生信任失效时,优先修复清单或声明。
|
|
28
|
+
|
|
29
|
+
## 离线包
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
neutrino plugin pack ./my-plugin ./my-plugin-1.0.0.neutrino-plugin
|
|
33
|
+
neutrino plugin install ./my-plugin-1.0.0.neutrino-plugin
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
插件包是 `format: neutrino-plugin`、`version: 1` 的 JSON 容器,包含相对路径、base64 内容和完整性散列。相同目录得到相同内容;输出文件不能放进源包目录。安装器验证每个路径、大小和完整性,不执行解压脚本。包的完整性散列用于检测变化,不等于发布者签名。
|
|
37
|
+
|
|
38
|
+
更新时重新打包并替换原包文件,再执行 update。回滚恢复上一个包指针,原生信任仍按当前字节散列校验。
|
|
39
|
+
|
|
40
|
+
## 测试
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
npm run test:plugins
|
|
44
|
+
npm test
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
插件测试覆盖真实 QuickJS 执行、能力限制、原生信任、配置快照、只读子任务、宿主审批、证据、skill、提示词、包和回滚,以及本地 HTTP 管理接口。HTTP 检查需要允许监听本机回环端口。测试使用临时的 NEUTRINO_HOME / NEUTRINO_PLUGIN_HOME。
|
|
48
|
+
|
|
49
|
+
发布前至少手动验证一次浏览器与终端:启用、停用、切换 Standard/Pro、草稿冲突、视图失败恢复、运行中更新、旧会话阅读。修改 SDK 时维护已有插件示例,并确保 npm 打包结果包含 dist、web、examples/plugins 和 docs/plugins。
|
|
50
|
+
|
|
51
|
+
## 发布约定
|
|
52
|
+
|
|
53
|
+
公开版本使用语义化版本;不兼容行为提高主版本。apiVersion 与包版本分别管理。所需权限、外部效果、支持平台和原生信任要求应写在 README。分发构建后的本地目录或离线包即可;本版没有远程市场或自动依赖安装。
|
|
54
|
+
|
|
55
|
+
不要导入 dist 下的私有内部模块。新增公开方法需要同步类型、权限检查、生命周期清理、文档和行为测试。无法在卸载时撤销的全局副作用不应作为普通受限插件功能。
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# 清单与配置格式
|
|
2
|
+
|
|
3
|
+
每个包根目录必须包含 `neutrino.plugin.json`。目录和离线包使用相同结构。
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"id": "acme.example",
|
|
8
|
+
"name": "Example",
|
|
9
|
+
"version": "1.0.0",
|
|
10
|
+
"apiVersion": 1,
|
|
11
|
+
"runtime": "sandbox",
|
|
12
|
+
"entries": { "agent": "agent.js" },
|
|
13
|
+
"permissions": ["tools.register"],
|
|
14
|
+
"profiles": ["standard", "pro"],
|
|
15
|
+
"categories": ["function"],
|
|
16
|
+
"configuration": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"properties": { "label": { "type": "string", "default": "Example" } },
|
|
19
|
+
"additionalProperties": false
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
| 字段 | 约束与含义 |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| `id` | 必填、命名空间标识,例如 `acme.example`。小写字母、数字、短横线,至少两段,最长 80 字符 |
|
|
27
|
+
| `name` | 必填,1–100 字符的显示名称 |
|
|
28
|
+
| `version` | 必填,`major.minor.patch`,可包含预发布后缀 |
|
|
29
|
+
| `apiVersion` | 必填,本版只能为数字 `1` |
|
|
30
|
+
| `runtime` | `sandbox`(默认)或 `native`,只控制 Agent 代码 |
|
|
31
|
+
| `entries.agent` | 后端入口,默认受限环境支持单文件 JS / TS 模块 |
|
|
32
|
+
| `entries.web` | 可选的单文件浏览器 ES 模块,对每个视图调用其 `mount` |
|
|
33
|
+
| `entries.tui` | 预留的终端资源入口;v1 的终端页面使用 `contributes.ui[].text`,不执行此入口 |
|
|
34
|
+
| `webAssets` | 动态注册的视图可读取的文件白名单 |
|
|
35
|
+
| `profiles` | `standard` / `pro`,省略则均支持 |
|
|
36
|
+
| `permissions` | 需要的公开能力列表,未知能力报错 |
|
|
37
|
+
| `dependencies` | 必需插件 ID 到版本范围的映射 |
|
|
38
|
+
| `optionalDependencies` | 已安装并兼容时建立顺序的可选依赖 |
|
|
39
|
+
| `configuration` | 插件配置的 JSON Schema 子集 |
|
|
40
|
+
| `contributes` | UI、主题、提示词和 skill 的声明式贡献 |
|
|
41
|
+
| `description` / `license` | 可选说明与许可证 |
|
|
42
|
+
|
|
43
|
+
依赖范围支持精确版本、`^1.2.3`、`~1.2.3` 和 `*`。预发布版本按精确版本匹配。依赖需要先安装并启用,管理器不会自动执行远程安装。循环依赖会失败。停用依赖前需先停用使用它的插件;卸载前需先移除仍声明该必需依赖的包。
|
|
44
|
+
|
|
45
|
+
## 配置 Schema 子集
|
|
46
|
+
|
|
47
|
+
支持 `type`、`properties`、`required`、`additionalProperties`、`items`、`enum`、`default`、`title`、`description`、`minimum`、`maximum`、`minLength`、`maxLength`、`minItems`、`maxItems`。
|
|
48
|
+
|
|
49
|
+
`type` 必须明确,根配置和工具参数必须是 object。最多嵌套 16 层。不支持的关键字会报错,不会悄悄忽略验证。默认值应用于顶层配置字段。配置提交后完整验证,再写入文件;失败时磁盘和运行中的配置保持原值。`__proto__` 等保留键不能用作配置属性。
|
|
50
|
+
|
|
51
|
+
配置会传给插件自己的运行实例,也能在管理界面查看。不要把宿主模型 API Key 复制到配置中;本版不提供插件凭据存储接口。
|
|
52
|
+
|
|
53
|
+
## 贡献定义
|
|
54
|
+
|
|
55
|
+
UI 项包含 `id`、`slot`、`title`,可使用 `order`、`view`、`command`、`text`、`insert`、`height`、`match`、`platforms`。详见 [UI SDK](ui-sdk.md)。
|
|
56
|
+
|
|
57
|
+
提示词项包含 `id`,以及二选一的 `text` / `file`;可配置 `slot`、`order`、`roles` 和 `replace`。Skill 使用 `SKILL.md` 相对路径数组。
|
|
58
|
+
|
|
59
|
+
主题是 CSS 变量到简单值的映射。路径必须位于包内,使用正斜线;符号链接、特殊文件和路径逃逸不允许。包最多 2000 个文件、32 MiB 原始内容,清单最多 128 KB,提示词 / skill 资源最多 64 KB,浏览器单个视图最多 1 MB。
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "Neutrino Plugin Manifest v1",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": [
|
|
6
|
+
"id",
|
|
7
|
+
"name",
|
|
8
|
+
"version",
|
|
9
|
+
"apiVersion"
|
|
10
|
+
],
|
|
11
|
+
"properties": {
|
|
12
|
+
"id": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"pattern": "^[a-z][a-z0-9-]*(?:\\.[a-z][a-z0-9-]*)+$",
|
|
15
|
+
"maxLength": 80
|
|
16
|
+
},
|
|
17
|
+
"name": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"minLength": 1,
|
|
20
|
+
"maxLength": 100
|
|
21
|
+
},
|
|
22
|
+
"version": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+(?:-[a-zA-Z0-9.-]+)?$"
|
|
25
|
+
},
|
|
26
|
+
"apiVersion": {
|
|
27
|
+
"const": 1
|
|
28
|
+
},
|
|
29
|
+
"description": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"license": {
|
|
33
|
+
"type": "string"
|
|
34
|
+
},
|
|
35
|
+
"runtime": {
|
|
36
|
+
"enum": [
|
|
37
|
+
"sandbox",
|
|
38
|
+
"native"
|
|
39
|
+
],
|
|
40
|
+
"default": "sandbox"
|
|
41
|
+
},
|
|
42
|
+
"entries": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"additionalProperties": false,
|
|
45
|
+
"properties": {
|
|
46
|
+
"agent": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"minLength": 1
|
|
49
|
+
},
|
|
50
|
+
"web": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"minLength": 1
|
|
53
|
+
},
|
|
54
|
+
"tui": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"minLength": 1
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"webAssets": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"items": {
|
|
63
|
+
"type": "string"
|
|
64
|
+
},
|
|
65
|
+
"maxItems": 100
|
|
66
|
+
},
|
|
67
|
+
"profiles": {
|
|
68
|
+
"type": "array",
|
|
69
|
+
"items": {
|
|
70
|
+
"enum": [
|
|
71
|
+
"standard",
|
|
72
|
+
"pro"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"categories": {
|
|
77
|
+
"type": "array",
|
|
78
|
+
"items": {
|
|
79
|
+
"enum": [
|
|
80
|
+
"function",
|
|
81
|
+
"appearance",
|
|
82
|
+
"skill",
|
|
83
|
+
"prompt"
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"permissions": {
|
|
88
|
+
"type": "array",
|
|
89
|
+
"items": {
|
|
90
|
+
"enum": [
|
|
91
|
+
"tools.register",
|
|
92
|
+
"commands.register",
|
|
93
|
+
"prompts.contribute",
|
|
94
|
+
"hooks.register",
|
|
95
|
+
"ui.contribute",
|
|
96
|
+
"conversation.read",
|
|
97
|
+
"composer.read",
|
|
98
|
+
"composer.write",
|
|
99
|
+
"composer.submit",
|
|
100
|
+
"filesystem.read",
|
|
101
|
+
"filesystem.write",
|
|
102
|
+
"network",
|
|
103
|
+
"process",
|
|
104
|
+
"storage"
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"dependencies": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"additionalProperties": {
|
|
111
|
+
"type": "string"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"optionalDependencies": {
|
|
115
|
+
"type": "object",
|
|
116
|
+
"additionalProperties": {
|
|
117
|
+
"type": "string"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"configuration": {
|
|
121
|
+
"type": "object",
|
|
122
|
+
"description": "Bounded JSON Schema subset documented in manifest.md"
|
|
123
|
+
},
|
|
124
|
+
"contributes": {
|
|
125
|
+
"type": "object",
|
|
126
|
+
"properties": {
|
|
127
|
+
"ui": {
|
|
128
|
+
"type": "array",
|
|
129
|
+
"maxItems": 100,
|
|
130
|
+
"items": {
|
|
131
|
+
"type": "object",
|
|
132
|
+
"required": [
|
|
133
|
+
"id",
|
|
134
|
+
"slot",
|
|
135
|
+
"title"
|
|
136
|
+
],
|
|
137
|
+
"properties": {
|
|
138
|
+
"id": {
|
|
139
|
+
"type": "string",
|
|
140
|
+
"pattern": "^[a-z][a-z0-9_-]{0,39}$"
|
|
141
|
+
},
|
|
142
|
+
"slot": {
|
|
143
|
+
"enum": [
|
|
144
|
+
"app.menu",
|
|
145
|
+
"workspace.tabs",
|
|
146
|
+
"sidebar.footer",
|
|
147
|
+
"chat.header.actions",
|
|
148
|
+
"chat.composer.toolbar",
|
|
149
|
+
"chat.composer",
|
|
150
|
+
"chat.message.actions",
|
|
151
|
+
"chat.message.renderer",
|
|
152
|
+
"chat.card.plan",
|
|
153
|
+
"chat.card.tool",
|
|
154
|
+
"settings.sections"
|
|
155
|
+
]
|
|
156
|
+
},
|
|
157
|
+
"title": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"minLength": 1,
|
|
160
|
+
"maxLength": 100
|
|
161
|
+
},
|
|
162
|
+
"order": {
|
|
163
|
+
"type": "number"
|
|
164
|
+
},
|
|
165
|
+
"view": {
|
|
166
|
+
"type": "string"
|
|
167
|
+
},
|
|
168
|
+
"command": {
|
|
169
|
+
"type": "string"
|
|
170
|
+
},
|
|
171
|
+
"text": {
|
|
172
|
+
"type": "string"
|
|
173
|
+
},
|
|
174
|
+
"insert": {
|
|
175
|
+
"type": "string"
|
|
176
|
+
},
|
|
177
|
+
"height": {
|
|
178
|
+
"type": "integer",
|
|
179
|
+
"minimum": 40,
|
|
180
|
+
"maximum": 1200
|
|
181
|
+
},
|
|
182
|
+
"platforms": {
|
|
183
|
+
"type": "array",
|
|
184
|
+
"items": {
|
|
185
|
+
"enum": [
|
|
186
|
+
"web",
|
|
187
|
+
"tui"
|
|
188
|
+
]
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
"match": {
|
|
192
|
+
"type": "object",
|
|
193
|
+
"properties": {
|
|
194
|
+
"role": {
|
|
195
|
+
"type": "string"
|
|
196
|
+
},
|
|
197
|
+
"tool": {
|
|
198
|
+
"type": "string"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
"prompts": {
|
|
206
|
+
"type": "array",
|
|
207
|
+
"maxItems": 100,
|
|
208
|
+
"items": {
|
|
209
|
+
"type": "object",
|
|
210
|
+
"required": [
|
|
211
|
+
"id"
|
|
212
|
+
],
|
|
213
|
+
"oneOf": [
|
|
214
|
+
{
|
|
215
|
+
"required": [
|
|
216
|
+
"file"
|
|
217
|
+
],
|
|
218
|
+
"not": {
|
|
219
|
+
"required": [
|
|
220
|
+
"text"
|
|
221
|
+
]
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"required": [
|
|
226
|
+
"text"
|
|
227
|
+
],
|
|
228
|
+
"not": {
|
|
229
|
+
"required": [
|
|
230
|
+
"file"
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
"properties": {
|
|
236
|
+
"id": {
|
|
237
|
+
"type": "string",
|
|
238
|
+
"pattern": "^[a-z][a-z0-9_-]{0,39}$"
|
|
239
|
+
},
|
|
240
|
+
"text": {
|
|
241
|
+
"type": "string"
|
|
242
|
+
},
|
|
243
|
+
"file": {
|
|
244
|
+
"type": "string"
|
|
245
|
+
},
|
|
246
|
+
"slot": {
|
|
247
|
+
"enum": [
|
|
248
|
+
"persona",
|
|
249
|
+
"rules",
|
|
250
|
+
"context"
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
"order": {
|
|
254
|
+
"type": "number"
|
|
255
|
+
},
|
|
256
|
+
"roles": {
|
|
257
|
+
"type": "array",
|
|
258
|
+
"items": {
|
|
259
|
+
"type": "string"
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
"replace": {
|
|
263
|
+
"type": "boolean"
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
"skills": {
|
|
269
|
+
"type": "array",
|
|
270
|
+
"maxItems": 100,
|
|
271
|
+
"items": {
|
|
272
|
+
"type": "string"
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
"theme": {
|
|
276
|
+
"type": "object",
|
|
277
|
+
"maxProperties": 50,
|
|
278
|
+
"additionalProperties": {
|
|
279
|
+
"type": "string",
|
|
280
|
+
"maxLength": 100
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# 权限与执行边界
|
|
2
|
+
|
|
3
|
+
## 三类插件
|
|
4
|
+
|
|
5
|
+
声明式插件只有主题、文本、skill、提示词或静态 UI 定义,不执行 Agent 后端脚本。浏览器 HTML 视图仍含可执行代码,但使用独立的 iframe 与受限消息接口。
|
|
6
|
+
|
|
7
|
+
默认代码插件在私有进程内的 QuickJS VM 中执行。没有 Node 的 process、require、文件系统、全局 fetch 或任意模块解析。`require('@xingjisoft/neutrino/plugin')` 只返回无副作用的 definePlugin 辅助函数;其他依赖需预先打包。宿主 API 是唯一外部效果入口。
|
|
8
|
+
|
|
9
|
+
native 插件是完全信任的本机代码。它能绕开 SDK 直接访问文件、网络、环境变量和进程。子进程提供崩溃、超时和清理边界,不提供操作系统安全沙箱。启用需要对精确包散列的明确信任;新版本代码变化后需重新授予。只读或限定写入路径的子任务不执行原生工具。
|
|
10
|
+
|
|
11
|
+
## 权限清单
|
|
12
|
+
|
|
13
|
+
| 权限 | 用途 |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| tools.register / commands.register | 注册模型工具 / 用户命令 |
|
|
16
|
+
| prompts.contribute | 提示词片段与 skill |
|
|
17
|
+
| hooks.register | 注册事件或流程钩子 |
|
|
18
|
+
| ui.contribute | 页面、组件与主题 |
|
|
19
|
+
| conversation.read | 浏览器视图读取当前会话投影 |
|
|
20
|
+
| composer.read / write / submit | 读取草稿 / 修改草稿 / 提交草稿 |
|
|
21
|
+
| filesystem.read / write | 通过宿主读文件与目录 / 写文件 |
|
|
22
|
+
| network | 通过宿主进行 HTTP GET |
|
|
23
|
+
| process | 通过宿主执行命令 |
|
|
24
|
+
| storage | 读写本插件的 JSON 数据 |
|
|
25
|
+
|
|
26
|
+
启用受限插件即启用清单中展示的能力。每次调用还必须满足回调自己的 effects、当前 TaskScope、原审批策略和预算。声明权限不等于每次外部操作自动获准;例如读工作目录外的文件仍经过原审批入口。
|
|
27
|
+
|
|
28
|
+
## 数据流
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
模型选择工具
|
|
32
|
+
→ 参数 Schema 和角色检查
|
|
33
|
+
→ tool.before 收窄决策
|
|
34
|
+
→ 现有风险评估和审批
|
|
35
|
+
→ 插件执行回调
|
|
36
|
+
→ 每项实际宿主操作再检查 effects、权限、任务范围与风险
|
|
37
|
+
→ 原审批入口
|
|
38
|
+
→ TaskRuntime 执行与记录
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
纯工具不能调用文件或网络 API。一个只读工具不能靠命令执行获得写权限。子任务继承父任务限制,并可进一步收窄。跨插件服务不能增加调用方的外部效果。事件和钩子不提供文件、网络和进程效果。
|
|
42
|
+
|
|
43
|
+
## 包与浏览器
|
|
44
|
+
|
|
45
|
+
包禁止路径逃逸、符号链接和特殊文件,有文件数及大小上限。更新复制到新目录,校验完整性后再切换指针。安装不执行 npm 生命周期脚本,不从工作区文件自动启用代码。发现安装内容被修改后,宿主拒绝激活;重新安装可修复。
|
|
46
|
+
|
|
47
|
+
插件管理 API 位于现有登录检查之后,写操作继续检查同源。浏览器只读取清单声明的 view、entries.web 和 webAssets,不提供任意包文件读取接口。
|
|
48
|
+
|
|
49
|
+
iframe 不具有同源身份,CSP 禁止直接联网;消息根据窗口身份、随机 nonce、当前会话和权限进行校验。API 不暴露宿主 API Key、登录凭据、审批按钮或原始 App 对象。切换对话时释放旧视图,草稿写入使用 revision,避免过期编辑覆盖新输入。
|
|
50
|
+
|
|
51
|
+
受限执行依赖 JavaScript 引擎、Node 和浏览器的正确实现,不等于抵御所有引擎漏洞的操作系统隔离。对于不愿信任的本机代码,不启用 native 模式。
|
|
52
|
+
|
|
53
|
+
插件命令的 JSON 参数始终按数据处理。参数中出现“无需审批”或完整信任短语,不会成为跳过审批的用户授权;真实外部操作仍使用当前审批策略。
|