兼容性记录
兼容性工作的顺序如下,并按接口表面记录了保留内容、保留原因以及可移除条件。属于 Plugin SDK migration 指南的一部分。
兼容性策略¶
外部插件兼容性工作遵循以下顺序:
- 添加新契约。
- 通过兼容性适配器保留旧行为的接线。
- 发出诊断或警告,指明旧路径及其替代项。
- 在测试中覆盖两条路径。
- 记录弃用说明和迁移路径。
- 仅在宣布的迁移窗口结束后移除,通常是在主要版本中。
保留的辅助契约¶
Discord 和 llama.cpp 保留其声明的 OpenClaw 2026.9.2 宿主支持。当这些导出可用时,它们使用较新的 prepared-expiry、DM-policy 细化和 live-catalog 结果辅助函数,并为 2026.9.2 SDK 提供插件本地回退。这些回退通过旧版 SDK 验证器保留 Discord 的时间戳验证、空闲优先的过期平局处理,以及根/账户 DM-policy 验证,并保留 llama.cpp 的就绪、认证被拒绝和不可用目录结果(附带凭据配置归属)。它们不会重试或抑制来自可用较新辅助函数的错误。仅当声明的插件 API 下限不再包含 2026.9.2 时,才移除这些回退;在更改无条件 SDK 导入之前,针对该最低宿主测试已构建的插件导入。
Voice Call 也保留其声明的 2026.9.2 宿主支持。其实时升级处理程序将两个 HTTP 拒绝响应保留在本地,因为该 SDK 没有 websocket-runtime 子路径。拒绝字节在套接字销毁之前刷新,套接字错误保留其正常清理行为。仅当声明的插件 API 下限排除 2026.9.2 时,才移除此本地传输兼容性代码。
保留的兼容性入口点保持其已发布的调用者名称:inbound-envelope 使用 resolveStorePath,provider-catalog-runtime 导出 resolvePluginProviders,并且 agent-runtime 的 resolveThinkingDefaultWithRuntimeCatalog 接受 loadModelCatalog。
resolvePluginProviders 保持同步,并返回现有的提供方数组。当它从拥有的检查借用时,Gateway 生命周期或可执行 CLI 调用会保留底层资源,直到其实际工作和清理完成。在宿主关闭之前完成使用这些提供方的调用;保留数组并不授权在宿主退役后使用。已释放的检查保持退役状态,通过该检查的新查找会被拒绝。OpenClaw 宿主之外的调用者保留此 SDK 契约的独立进程生命周期;进程退出并不保证异步插件处置。
释放检查会放弃检查自身的主张。如果 SDK 宿主仍借用同一来源,最终处置属于该宿主。宿主在拆卸期间报告后续的处置失败;这些失败不能追溯更改已返回的检查结果。内部提供方解析器不会获取此兼容性生命周期。
text-chunking 保留用于 isInsideCode 的带 start 和 end 偏移的位置式 CodeRegion 输入。findCodeRegions 返回的区域额外包含解析器拥有的 block 元数据;提供自己范围的调用者无需提供它。
WebSocket 选项和构造函数¶
websocket-runtime 保留 OpenClaw 2026.9.6 中发布的 ws.ClientOptions 别名和 WebSocket 构造函数签名。宿主内部的 TLS 类型修正不得更改插件回调类型或构造函数重载。对此公共契约进行源不兼容的修正需要已批准的、带版本的 SDK 迁移。
Gateway 工作进程环境创建¶
来自 core 和 gateway-runtime 的 GatewayRequestHandlerOptions 保留 OpenClaw 2026.9.5 中发布的工作进程环境创建契约。当 context.workerEnvironmentService 可用时,其 create 方法按以下顺序接受位置参数:profileId、idempotencyKey、machineClass?、executionMode?、projectPath?、signal?、os? 和 runSetupScript?。幂等重试和调用者取消在宿主升级过程中保持其现有行为。更改此契约需要明确批准的 SDK 迁移。
Harness 尝试结果迁移¶
在 OpenClaw 2026.8.1 中,来自 openclaw/plugin-sdk/agent-harness-runtime 的 EmbeddedRunAttemptResult 要求规范的 terminal 字段。针对 2026.7 直接别名编写的源代码,在使用 aborted、timedOut 和 promptError 等旧字段构造结果时必须迁移;保留别名名称并不会使这些旧构造函数保持源兼容。
在迁移旧结果生产者时,使用同一子路径中的 AgentHarnessAttemptResult。该联合类型同时接受旧字段和规范结果,宿主生命周期会在核心消费之前规范化旧结果。新生产者应构造 terminal;联合类型的消费者在读取之前必须收窄结果。当前 EmbeddedRunAttemptResult 契约保持 terminal 为必填。
模型提供方结果兼容性¶
openclaw/plugin-sdk/models-provider-runtime 保留 v2026.7.1-2 中发布的 ModelsProviderData 构造形状和 buildModelsProviderData 返回签名,包括返回该形状的类型化适配器。这些契约将持续受支持,直到明确批准的 SDK 破坏性边界。
在转发模型选择时调用 buildPreparedModelsProviderData。其结果包含必需的 modelCatalog,其中带有所选物理路由元数据。两个构建器使用同一个元数据生产者;调用者必须向前传递已准备的行,而不是从 ID 重新构造它们。
两个构建器都会返回当前已发布的菜单行,而不会等待完整发现。在后台继续获取时,结果可能不完整;pendingProviders 标识仍在刷新的提供方。保持已知选项可用,并在菜单重新打开时再次调用构建器。等待菜单构建器并不保证完整清单。在请求清单获取时,使用目录的显式刷新操作,而不是将菜单读取视为获取。
对于所选模型,使用同一 SDK 子路径中的 getModelsRuntimeChoices(data, provider, model)。非空数组包含该模型符合条件的运行时选项。空数组表示当前观察结果不允许该模型使用任何运行时。undefined 表示选项未知:该模型没有观察结果,调用方提供了旧的结果形状,或者 data.isCurrent() 报告已准备的所有者已退役。不要将任一结果替换为 provider 默认值或根据名称推断的运行时。在重新选择之前,通过其所属目录刷新已退役的数据。
省略 model 会返回 provider 的浏览并集。该并集不会为 provider 中的每个模型授权运行时。在为会话浏览时,将 sessionEntry 传递给 builder,使其 profile 偏好、显式 profile 固定和运行时覆盖参与选项。保留已准备的物理行,并通过常规 command 所有者重新验证选择;显示的选项不是使用已退役的代或绕过会话锁的授权。
Provider 插件可以通过 prepareSyntheticAuth 发布原生登录存在性,使用 nativeAuth: { runtime, mode },其中 mode 为 api-key、oauth 或 token。这些事实仅适用于已准备的代中指定的运行时。它们不提供 provider bearer 凭据,也不授权将其导入 OpenClaw profile。可选的 pluginRoot 上下文来自 plugin loader;使用它从该插件的安装中解析已声明的依赖项。
内存读取缺失结果¶
内存管理器现在对成功摘录返回 status: "ok",当允许的文件缺失时返回 status: "not_found"。这使空文件和空范围与缺失文件保持区分,而无需依赖分页元数据。
在注册时,来自较旧外部内存管理器的每个无状态结果都保留其旧的成功读取语义,并变为 status: "ok",包括没有范围元数据的空结果。只有显式的 status: "not_found" 报告缺失。新的生产者必须为缺失文件发出该状态;注册输入规范化在下一个 Plugin SDK 主要版本之前仍可用。
配置记录迁移¶
使用来自 openclaw/plugin-sdk/runtime-doctor-migrations 的 mergeMissing(canonical, legacy) 来填充未定义字段,而不替换已编写的值。它会就地填充现有嵌套记录,并保留已编写的数组、null 和标量。缺失值按引用赋值;调用方负责任何将迁移与其输入隔离所需的克隆。
该辅助函数在合并的每个层级都会跳过未定义的源值以及 __proto__、prototype 和 constructor 键。它不会递归清理新赋值的子树。
插件状态迁移声明¶
捆绑插件应在 openclaw.plugin.json 的 doctorContract.stateMigrations 下列出每个迁移,并从其 doctor-contract artifact 中导出匹配的 stateMigrations 数组。保持 ID、顺序、doctorOnly 标志和阶段完全一致。只读 Doctor 规划使用候选捆绑的描述符来记录确切的插件所有者,而无需加载插件。
已安装的外部插件 artifact 不属于 copied-state 或候选内容标识。copied-state 规划会拒绝它们的迁移,包括包含描述符数组的 manifest,直到候选验证单独绑定这些 artifact。旧值 true 继续为非规划 Doctor 流程定位它们的动态 contract。
基于计划的迁移可以使用来自 openclaw/plugin-sdk/runtime-doctor-migrations 的 definePluginDoctorMigrationFromPlans(...),以保留现有的移动、复制、预览和插件状态导入行为。
迁移可以提供只读的 collectBackupResources 回调,包括通过 definePluginDoctorMigrationFromPlans(...)。返回类型为 sqlite、file 或 directory 的绝对路径,包括尚不存在的目标。在清点期间,切勿打开可写存储或运行迁移。当 requireLocalResources 为 true 时,拒绝远程或未列出的数据,而不是将不完整的清点点报为完整。
恢复清点收集器会为每个没有回调的插件报告一个类型化的 undeclared-migration-resources 警告;其私有状态不包含在恢复集中。格式错误的声明和无效清点仍然会失败。收集不会捕获或恢复数据、授权迁移,或替代 updater 必需的捕获检查。
对于单文件导入,defineLegacyJsonStateMigration(...) 会跳过缺失的源(ENOENT)以及插件解析器以 null 拒绝的值。其他读取错误和无效 JSON 会到达 Doctor 的检测或迁移警告;源保持未修改,以便操作员可以修复并重试。
当迁移需要规范会话所有权证据时,使用 phase: "after-session-repair"。常规 Doctor 会检测这些迁移;--fix 会在 SQLite 维护所有权下,于会话修复后应用它们。上下文提供有界的 readPluginStateEntriesInKeyRange 和 readSessionIdentityEvidenceBatch 读取,以及仅在围栏修复期间可用的 deletePluginStateEntriesIfUnchanged。保留未知或模糊的所有权。仅删除观察到的原始行;维护结束后保留的回调不能授权后续写入。
受信任的捆绑插件和官方插件还可以使用可选的 inspectCronJobs 和 repairCronJobs 上下文方法,用于显式 cron 迁移。检查是非创建性的,并返回每个持久化分区的原始定义、行 ID、顺序、验证结果和存储键。repairCronJobs(inventory, changes) 仅在离线修复期间可用:它会保存经过验证的共享状态 SQLite 备份,重新检查当前权限和已检查的定义,然后在一个事务中应用所有选定的替换或删除。替换会保留行 ID、分区、顺序和运行时状态。删除使用常规 cron scratch 和 grant 清理。结果报告 changed 和保留的 backupPath;无操作不会创建备份。插件对其自身的历史任务进行分类,并保留模糊的行。较旧的主机可能省略这些方法,因此迁移必须检查可用性。
这些辅助函数遵循 原生插件信任模型: 符合条件的插件以主机权限运行,并拥有历史任务分类。 主机强制校验安装来源、离线修复权限、未变更的定义、已验证的备份以及原子持久化。该 API 不保证相互不信任的原生插件之间的隔离。
setup 入口的 legacyStateMigrations 选项和功能标志、
setupFeatures.legacyStateMigrations、
BundledChannelLegacyStateMigrationDetector 以及
ChannelPlugin.lifecycle.detectLegacyStateMigrations 仍通过一个 doctor-pipeline 适配器对外部插件保持支持,但已弃用。移除计划:仅在已发布插件读取器扫描未发现剩余使用者时,才在 OpenClaw 2027.1 之后移除该适配器。
AuthStorage SQLite 迁移¶
AuthStorage.forAgent(agentDir) 是主机会话存储的规范构造函数。它通过 agent 的
openclaw-agent.sqlite auth-profile 行持久化 provider 默认凭据,并且从不创建 auth.json。
Harness 插件以 params.authStorage 的形式接收已准备好的存储实例。
AuthStorage.create(authPath) 仍作为面向现有插件的具名弃用适配器保留。该路径仅用于推导所属 agent 目录;
该适配器读写 SQLite,而不是具名 JSON 文件。请立即迁移到
forAgent(...)。接受路径参数的形式会发出
AUTH_STORAGE_CREATE_DEPRECATED,并且如果已发布插件读取器扫描干净,则可在
2026-10-01 之后移除。
FileAuthStorageBackend 是内部 SQLite 支持适配器,不是导出的
Plugin SDK 后端。它不能从
openclaw/plugin-sdk/agent-sessions 作为具名导入使用。Harness 插件应使用
主机准备好的 params.authStorage;构造存储的主机代码应
使用 AuthStorage.forAgent(agentDir)。该内部适配器会发出
FILE_AUTH_STORAGE_BACKEND_DEPRECATED,并且从不读取或写入旧版
文件。其内部弃用窗口不会保留以前的 SDK 导入。
如果某个 manifest 字段仍被接受,请继续使用它,直到文档和 诊断信息另有说明。新代码应优先使用文档中说明的替代项; 现有插件不应在普通 minor 版本发布期间被破坏。
带日期的兼容性注册表还跟踪不属于某个旧版子路径的已发布注解。除非下表列出了更晚的日期,否则这些记录 使用 2026-10-01 作为最早审查日期;移除仍需要最后一列中的读取器 条件。
| 兼容性代码 | 替代项 | 移除条件 |
|---|---|---|
plugin-sdk-broad-runtime-barrels |
聚焦的能力子路径 | 不再存在对七个列出的 broad barrels 的 bundled 或 published 导入。 |
plugin-sdk-provider-owned-helper-shims |
Provider 本地 auth/model/replay/OAuth/stream API | 每个列出的 helper 都已在官方 provider 中迁移,并且不存在于已发布插件中。 |
message-presentation-legacy-bridges |
MessagePresentation 和 channel presentation 渲染器 |
生产者和官方 channel 包不再发出或读取旧版交互式回复。 |
plugin-sdk-focused-compat-aliases |
每个 @deprecated 注解中命名的聚焦替代项 |
每个列出的别名都没有 bundled 和 published 读取器。 |
agent-harness-terminal-result-aliases |
AgentHarnessAttemptResult.terminal 和 visibleReplies |
Harness 插件不再读取旧版 terminal 布尔值或 sourceVisibleReplies。 |
official-plugin-export-aliases |
规范的 Google Meet 测试、presentation 渲染器以及主机拥有的 Discord 超时行为 | 最低支持的官方插件包不再导入这些别名。 |
memory-host-compatibility-aliases |
规范的 memory 表和准备好的运行时配置 | Memory 集成不再传递 table 覆盖项或调用旧版 loadConfig。 |
plugin-runtime-api-compat-aliases |
命名空间化的插件 API 和聚焦的运行时方法 | 所有列出的扁平 API/运行时别名都没有读取器。 |
plugin-provider-manifest-compat-aliases |
Manifest 拥有的 kind/setup 元数据和模型目录注册 | Provider 不再发布运行时 kind 或旧版目录钩子。 |
agent-harness-credential-prompt-string-argument |
选项对象 { controlToolsAvailable } |
弃用和警告从 2026-09-09 开始;支持到 2026-11-30。在该日期之后,一旦调用方迁移,即可移除。 |
已发布 channel 设置兼容性¶
通过 2026.7.1 发布的 Slack、Discord、Signal 和 Microsoft Teams 包从
openclaw/plugin-sdk/bundled-channel-config-schema 导入 channel 特定的配置 schema。已发布的 Slack 和
Discord 包还从 openclaw/plugin-sdk/setup-runtime 导入 createLegacyCompatChannelDmPolicy 和
promptLegacyChannelAllowFromForAccount。
这些导出仍可作为已弃用的运行时兼容适配器使用。
新插件和重新发布的插件应在本地管理其配置模式和设置策略,
使用来自 channel-config-schema 和
setup-runtime 的通用原语。只有当最低受支持的已发布包版本
不再导入这些兼容导出时,才能移除它们。
通道设置输入字段兼容性¶
ChannelSetupInput 现在仅永久保留跨通道设置信封的类型。
通道特定字段仍保留在已弃用的兼容层中并带有类型,以便在插件作者将这些字段
迁移到插件本地设置输入类型时,现有外部插件仍可编译。
OpenClaw 不发布主要版本。2026-07-22 的一次注册表扫描检查了 426 个已发布的树外通道插件,并移除了 21 个没有读取方的字段。 保留的 22 个字段均有已知的已发布读取方。只要没有已发布插件读取某个字段, 就会立即删除该字段;随着插件作者迁移到插件本地设置输入类型, 保留集合会缩小。
同一次扫描移除了 23 个没有已发布依赖方的旧版未声明适配器提升键。
六个通用键和仅用于设置的 rooms 键保留。
随着已发布插件声明 singleAccountKeysToMove,该集合也会缩小。
共享类型没有索引签名。插件拥有的键仍可能存在于运行时输入对象上; 请在插件本地交叉类型中声明它们,或通过所属插件的设置模式对其进行收窄。
code |
owner |
replacement |
移除条件 |
|---|---|---|---|
plugin-sdk-channel-setup-input-fields |
channel |
将 ChannelSetupInput 与声明所属通道字段的插件本地类型相交 |
当已发布插件注册表扫描没有读取方时删除字段 |
旧版未声明适配器提升层遵循相同的读取方驱动策略。
请声明 singleAccountKeysToMove,即使插件不需要额外提升键,也包含空数组,
以便共享回退机制可以逐个键退役。
验证读取方¶
- 使用每个
nextCursor分页遍历https://clawhub.ai/api/v1/packages?family=code-plugin&limit=100,并保留categories包含channels的包。 - 从
npm search --json --searchlimit=1000 "openclaw channel plugin"添加 npm 候选项。从 GitHub 代码搜索openclaw/plugin-sdk/channel-setup、openclaw/plugin-sdk/setup和openclaw/plugin-sdk/core添加仅源码候选项。 - 解析每个候选项的最新已发布版本。运行
npm pack <package>@<version> --json --pack-destination <temp-dir>,解包它,并检查随附的distJavaScript 和声明中直接读取或解构读取字段的情况。当包没有 npm 发布版本时,下载 ClawHub 工件。 - 记录包、版本、字段或提升键以及匹配文件。只有当没有已发布插件工件读取某个字段或键时,才可删除该字段或键。保留字段和键列表旁代码注释中的读取方名称,并与扫描保持同步。
这仅是源码/类型兼容记录。注册表条目具有
removeAfter: 2026-10-01,但设置输入运行时对象和行为未改变。
该日期启动审查;每个字段保留到其已发布工件读取方数量为零。
使用 pnpm plugins:boundary-report 审计当前迁移队列:
| 标志 | 效果 |
|---|---|
--summary(或 pnpm plugins:boundary-report:summary) |
紧凑计数而非完整详情。 |
--json |
机器可读报告。 |
--owner <id> |
筛选到一个兼容所有者。 |
--fail-on-eligible-compat |
对于在 removeAfter 次日 00:00 UTC 起生效的带日期 deprecated 记录,以非零退出。 |
pnpm plugins:boundary-report:ci 以兼容失败标志运行。
对于带日期的 deprecated 记录,removeAfter 是最终兼容日:
2026-09-01 在 2026-09-02T00:00:00Z 时变为符合条件,而不是在 9 月 1 日开始时。
removal-pending 记录是独立的:它们在其 removeAfter 日期 00:00 UTC 到期审查,
并随阻塞项一起报告,但不会触发此失败标志。两种状态都不授权自动移除。
已弃用记录通常具有明确的 removeAfter 日期。绑定到版本边界的契约
则声明 removalGate;
next-plugin-sdk-major 是已批准的主要版本门,而不是待定的所有者决定,
且永远不会按日期符合条件。没有这两个字段的记录显示为
no-date,并在其所有者发布门之前保持不符合条件。报告
显示日期或命名门,统计本地代码/文档引用,列出
removal-pending 记录及其阻塞项和表面令牌读取方引用,
并总结私有内存宿主 SDK 桥接。这些读取方引用是分诊信号,
而不是已发布工件证明。
媒体旧版投影¶
media-legacy-projection 兼容记录涵盖旧的并行媒体字段、负载构建器、
钩子元数据别名和媒体模板名称。其已批准的 removeAfter 日期为
2026-10-01(在事实优先替代方案发布后两个发布列车)。
移除还要求届时进行干净的已发布插件工件扫描;请在日期前迁移。
未使用的 buildChannelTurnMediaPayload 别名已从
openclaw/plugin-sdk/channel-inbound 中移除。其规范的
buildChannelInboundMediaPayload 导出在上述兼容窗口内仍然可用。新的入口代码应直接传递有序的媒体事实。
对于通道入口,请将单数/复数 MediaPath、MediaUrl、
MediaType、MediaPaths、MediaUrls、MediaTypes、
MediaTranscribedIndexes、MediaWorkspaceDir 和 MediaStaged 替换为有序事实:
import { toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
const media = toInboundMediaFacts([
{ path: saved.path, url: nativeUrl, contentType: saved.contentType, messageId },
]);
const ctx = finalizeInboundContext({ Body: caption, media });
在 inbound_claim 和 message_received 钩子中使用 event.media。如果远程
媒体未在本地暂存,请使用 event.originalMedia 用于身份/诊断,并等待
event.media;event.mediaStagingPending 用于区分该状态。不要从
event.metadata 读取已弃用的单数/复数属性。
对于 CLI 媒体模型,请将 {{MediaPath}}、{{MediaUrl}}、{{MediaType}}
和 {{MediaDir}} 替换为 {{AttachmentPath}}、{{AttachmentUrl}}、
{{AttachmentContentType}} 和 {{AttachmentDir}}。当附件位置重要时,使用
{{AttachmentIndex}}。
对于本地媒体读取策略,请从
openclaw/plugin-sdk/media-local-roots 导入 getAgentScopedMediaLocalRoots(...) 或
getAgentScopedMediaLocalRootsForSources(...)。
openclaw/plugin-sdk/agent-media-payload 外观及其
buildAgentMediaPayload(...) 投影已弃用。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw