@pluxel/runtime
v1.0.0
Published
Pluxel runtime kernel, control plane, and web SDK
Readme
@pluxel/runtime
插件实现包本身允许不存在时,用 type-only import 和 opaque optional ref 声明增强能力:
import type { AuditPlugin } from 'pluxel-plugin-audit'
import { definePluginRef } from '@pluxel/runtime'
const Audit = definePluginRef<AuditPlugin>()
this.plugins.use(Audit, (audit) => audit.registerSource(this))ref 与 plugins.use() 由 semantic pass lower 成 optional definition edge。ref 不 import、安装、注册或默认运行 package;
provider absent、当前未运行或 start-failed 不阻塞 consumer,running generation 出现、消失或 replacement 时 Core 用正常 graph plan
重启 consumer closure。plugins.use() 只允许在 init() 中直接调用,callback 必须同步,返回资源进入 generation effects。
所有 runtime plugin owner protocol 使用结构化 PluginNodeAddress。class name、constructor 与 displayName 只用于
代码或展示,不作为 RuntimeState、config、logging、HTTP、Workbench、commands 或 persistence identity。
definition address 标识源码实现,node address 再区分 default/fork 部署;对应 Slot 只是同一 address 在 Core registry 内的
引用 key。公开诊断/CLI 使用可逆 reference,HTTP/Workbench 使用可读 v1 route,短 label 只在当前 catalog revision 内用于展示。
Management status 保持 identity 与 execution 分离:package/source label、搜索和 canonical reference 都从 address 派生;
execution 只描述当前 definition 来自 static bundle、fixed catalog、dynamic fixed import 还是 mutable entry,以及更新边界是
deployment、catalog HMR、host reload、manual reload 或 definition HMR。source-graph 表示源码依赖图参与 HMR,entry-only 表示只承诺 entry
替换,不承诺 package 内部源码热更新。Source/built 分类只接受 raw lowering 或 active built closure 的 exact positive semantic
fact;文件扩展名、路径和“未匹配 source”都不能充当证据,缺失或冲突时保持 unreported。
recentUpdate 区分成功 applied、旧 catalog 仍为 authority 的 retained-previous、新 catalog 已为 authority 但 commit/lifecycle
有异常的 applied-with-issues,以及 full application reload 通过 fresh compensation host 恢复 previous definition 的
restored-previous。失败 artifact fact generation 会 rollback,失败 Plugin generation 的 partial effects 也会清理;两者都不改变
canonical identity。这些是只读诊断,不提供在线 execution-mode 切换,也不向 browser 暴露 filesystem path 或 module ID。
插件通过 owner-bound ctx.commands.register(command) 发布命令。返回值同时是保留精确 input/output 类型的 executable
registration 与幂等 disposer;registration 自动进入当前 generation effects,也可手动撤销。每个 root 只有一个 command
registry,Runtime 的 list()、snapshot()、subscribe() 和 throwing execute() 直接委托它,不复制 catalog 状态。
CommandsService 只增加 owner execution gate;generation stop 时由 Core 统一关闭 admission、abort 并等待已接纳调用,再
drain effects。
Carrier provider 可在 init() 中调用 this.ctx.commands.createMount<CarrierContext>(),并在自己的领域
registerCommand() 内使用 mount.bind(directCommand, install) 将 exact command implementation 交给 router 或 SDK。
Mount 通过 dependency caller view 自动区分 provider owner 与 publication owner,执行期间同时持有两侧 generation
admission,并把同步 installer 返回的 registration 归入 publication owner effects。它不是 secondary registry,不提供
lookup/snapshot/execute,也不接受会跟随 compatible catalog replacement 的 installed handle;root catalog 与 carrier
publication 必须分别显式注册。
Runtime 不定义 Agent、Toolset 或 provider adapter。需要 Agent allowlist 时安装普通官方 Plugin
@pluxel/agent-tools;它把 Toolset/assignment 放进标准 Plugin config,并在这个唯一 registry 上生成受限 catalog。
外部 Agent adapter 也应是普通 Plugin,通过 constructor dependency 消费它,而不是取得 Runtime 特例。
单独构建的 Node ESM entry 使用 defineNodeModule(import.meta.url, literal) 声明,并通过
ctx.nodeModules.use(declaration, setup) 消费。首次 load/setup 会阻塞插件启动;开发期 staged replacement 与 owner
cleanup 由 runtime 管理。artifact 不定义 worker 或任务协议。
CPU-bound / thread-safe native 工作使用 defineWorkerTask<Input, Output>() 和 ctx.workers.run()。所有插件共享一个
root-owned、lazy、bounded、owner-fair 的 worker-thread pool;插件不依赖具体 pool 实现。输入输出必须可 structured clone,
插件 stop 会取消并等待已接纳工作及 running worker 的真实退出。caller cancellation 可以先结束公开 Promise,但对应 active slot
只在 worker termination settle 后归还。run(..., { transfer: [buffer] }) 可把大型 ArrayBuffer ownership 立即转入已接纳任务,
避免第二次字节复制;buffer 会同步 detach,后续失败不回滚。默认 admission snapshot 也可显式改成
inputOwnership: 'borrowed',由 caller 保持输入到 Promise settle 并省略重复 clone。普通异步 I/O 与短小 native 调用不应
为了“统一”而额外跨线程。
如果输入预算 walk/snapshot 本身较重,使用 ctx.workers.runPrepared(task, prepare, options):runtime 先完成同一
global/per-owner fair admission 并保留一个 execution slot,之后才在 host 调用 cooperative prepare(signal),再 dispatch
其 cloneable 返回值。queue full 不会执行 prepare;callback error 保留领域类型。它不支持 transfer,默认 snapshot prepared
value;明确 borrow-until-settle 时可选 inputOwnership: 'borrowed'。
Runtime 保持业务 HTTP 与 optional Workbench 正交。Workbench 作者面只有固定 definition、Direct View API、 Attachment 和 owner-bound publication:
import type { RpcTarget } from '@pluxel/runtime/capnweb'
import { workbench } from '@pluxel/runtime/workbench'
interface ExampleApi extends RpcTarget {
snapshot(): ExampleSnapshot
}
export const ExampleWorkbench = workbench.define({
settings: workbench.view<ExampleApi>({
renderer: workbench.entry(import.meta.url, './ui/settings.tsx'),
placement: workbench.tab({ label: 'Settings' }),
}),
})
this.ctx.workbench?.publish(ExampleWorkbench, {
settings: ({ principal, signal }) => new ExampleTarget(this, { principal, signal }),
})普通 snapshot/watch renderer 用专用 scope module 绑定 exact descriptor 并声明 resources:
// ui/settings.scope.ts
import { createWorkbenchRenderer } from '@pluxel/runtime/workbench/react'
import { ExampleWorkbench } from '../workbench.js'
export const settingsScope = createWorkbenchRenderer(ExampleWorkbench.settings)
export const settingsQuery = settingsScope.query(({ api }) => ({
queryKey: ['example', 'settings'] as const,
queryFn: () => api.snapshot(),
}))
// ui/settings.tsx
import { SettingsPage } from './settings-page.js'
import { settingsScope } from './settings.scope.js'
export default settingsScope.render(SettingsPage)Scope/resource 是 module-scoped declaration;每次 Bridge mount 创建独立 renderer owner,并随 opened handle 一起清理。
Snapshot/watch、mutation、portable detach 与低层 escape hatch 的完整契约只在
Workbench 作者文档维护;内部所有权、admission 与 teardown 不变量见
Workbench 架构。Shell 的 Management client 位于 /web,Plugin renderer resource 位于
/workbench/react;两者共用 transport,但不共享 facade、cache 或生命周期。
跨 Plugin UI 使用 Attachment:provider 声明 renderer/API,consumer 用 attachment.place(...) 决定位置,并在
publication binding 中传入 constructor-injected provider Plugin。Collection、account、font 等动态数据仍是 Plugin
领域对象,不按 item 创建 Workbench entry。
公开入口:
@pluxel/runtime:唯一 Plugin 作者入口,转发 core API 并增加 runtime capabilities;@pluxel/runtime/services/vault:Vault 的公开 type-only API;backend 只由 host 顶层vaultobject 安装;@pluxel/runtime/capnweb:固定 Cap’n WebRpcTarget/RpcStub和 WebSocket session bridge;@pluxel/runtime/workbench:browser-safe definition、View、Attachment、placement 和 publication types;@pluxel/runtime/workbench/react:renderer scope、query/mutation、低层 exact descriptor hook、host facade 与 declarative Pane Kit;@pluxel/runtime/workbench/client:conforming Shell 的 layout/opened-handle client 与 portable DTO detach;@pluxel/runtime/web:portable Runtime session、Management API 和严格校验的 wire DTO;@pluxel/runtime/web/react:Management client 的 React Context adapter。
Management control 把持久策略与本次进程生命周期分开:client.plugins.setAutoStart() 只修改 RuntimeState 的
autoStart,client.plugins.applyLifecycleCommands() 只执行 start | stop | restart。公开状态分别返回
autoStart、process-local sessionIntent、desiredState、activationReason 和 observed lifecycleState;调用方
不能用 auto-start policy 猜测 Plugin 是否正在运行。
Workbench document 只创建一条 /__pluxel/runtime/session WebSocket。认证 challenge、Management、Workbench
layout/openEntry、Plugin API、logs follow 和 observer 都使用同一个 Cap’n Web object graph。认证/publication epoch
失效或 socket broken 时完整 reload;同一 document 不 feature reconnect,也不切换备用 API transport。
MF2 manifest 和 remote JS/CSS 仍由 HTTP 提供;浏览器写入 HttpOnly cookie 使用一个 same-origin、single-use
cookie-commit POST。这些端点不承载 Management 或 Plugin RPC。
宿主只通过顶层 workbench: { enabled: true } 安装 Workbench Plane。关闭后不创建 registry、compiler、watcher、
MF producer route 或 session transport,插件业务 HTTP 和生命周期不受影响。Workbench 启用时同时安装 Management Plane;
关闭 Workbench 后只有显式提供顶层 management: true 才安装 headless management;management 不接受 object。
Plugin catalog sections 按 committed declaration 的 provider role、package-root、source direct parent-directory 依次自动派生;
不读取 dependency edges 或运行状态。用户布局只作为 Management persistence 中的 definition-family 偏好覆盖。
Management 访问由真实 socket peer 和 ctx.managementAccess 上唯一 running provider 决定:真实 loopback peer 取得 Runtime
recovery principal;remote/unknown 必须使用可信 physical HTTPS carrier,并由 ready provider 完成认证,否则 fail closed。
官方 @pluxel/auth 提供 OIDC、password 与 password+TOTP。自定义 provider 只取得建立 authentication session 所需的
request metadata 和 owner-bound signal,不取得 Management operation body。
生产 static Node listener 默认通过 HTTP 监听 0.0.0.0,公网 TLS 由 ingress、反向代理或部署平台终止。Runtime 不从
forwarding headers 推断物理 TLS;内建 Node launcher 默认只通过 loopback/SSH tunnel 管理,需要 remote Management 的平台
集成必须提供自身能证明 HTTPS 的 application carrier。不安全的 remote Management session 会在 provider callback 前拒绝。
完整 Workbench 作者用法见 docs/workbench/index.md,内部不变量见
engineering/WORKBENCH.md。
