人工智能大模型LLM 网关AI Agent即时通讯【免费下载链接】openclaw-zero-tokenOpenClaw: Use All Major AI Models NO API Token! Claude/ChatGPT/Gemini/DeepSeek/Doubao/Grok/Qwen/Manus/Kimi项目地址https://gitcode.com/gh_mirrors/op/openclaw-zero-token点击查看免费下载在 OpenClaw 中src/plugin-sdk/是插件与核心core之间的公共契约public contractbundled 插件和第三方插件都通过它的 subpath 导入类型与辅助函数而不是直接触碰核心内部实现。本文围绕仓库中plugin-sdk/CLAUDE.md这份边界规约展开结合 入口清单脚本、entrypoints.ts、API 基线 与若干边界测试用例说明这套“窄 subpath 单一清单 可验证边界”的设计是如何落地、如何被自动化检查守护的读完你可以掌握如何正确引用 plugin-sdk 子路径、新增公开 subpath 时必须同步哪些位置、以及仓库用哪些测试与脚本把“不越界”变成硬约束。一、定位plugin-sdk 目录是“公开契约”而非普通目录plugin-sdk/CLAUDE.md开篇即给出定位声明This directory is the public contract between plugins and core. Changes here can affect bundled plugins and third-party plugins.这意味着对该目录的任何改动新增导出、改名、删文件都会波及仓库内所有 bundled 插件和外部第三方插件因此它有一套独立于普通业务代码的变更纪律。从源码结构看这个契约的物理形态是src/plugin-sdk/下的约 300 个文件根入口 index.ts刻意保持极小的共享类型面文件头注释明确写着 “Keep this entry intentionally tiny”每个功能域一个同名 subpath 文件如 core.ts、provider-entry.ts、telegram.ts契约守护文件entrypoints.ts、api-baseline.ts以及一组*-guardrails.test.ts、subpaths.test.ts等边界测试。二、Single Source of Truth文档与定义文件清单规约文档把“事实来源”分为两类。写作时需特别注意文档中列出的 5 个 SDK 专题文档docs/plugins/sdk-overview.md、docs/plugins/sdk-entrypoints.md、docs/plugins/sdk-runtime.md、docs/plugins/sdk-migration.md、docs/plugins/architecture.md在当前仓库快照的 docs/plugins 目录下并不存在该目录实际包含 manifest.md、community.md 等与主题最接近、且确实存在于仓库中的规划文档是 docs/refactor/plugin-sdk.md它完整描述了“SDK Runtime 两层架构”的目标设计。以下引用以该文档和规约原文为准并按谨慎口径说明。文档列出的 7 个定义文件全部真实存在各自职责如下定义文件职责package.json声明./plugin-sdk/*的 npmexports映射每个 subpath 都指向./dist/plugin-sdk/entry.d.tstypes与./dist/plugin-sdk/entry.jsdefaultscripts/lib/plugin-sdk-entrypoints.jsonsubpath 入口的单一清单manifest当前含 238 个条目首项为index其后是core、provider-setup、telegram、discord等src/plugin-sdk/entrypoints.ts读取上述 JSON 清单派生入口源文件映射、包导入规格、exports 表与 dist 产物列表src/plugin-sdk/api-baseline.ts基于 TypeScript Compiler API 生成 API 导出基线用于检测公共 API 漂移src/plugin-sdk/plugin-entry.ts提供definePluginEntry规范入口辅助函数src/plugin-sdk/core.ts通道channel类插件的类型与辅助函数面src/plugin-sdk/provider-entry.ts提供defineSingleProviderPluginEntry用于单一 provider 插件的快速装配2.1 入口清单如何“驱动一切”entrypoints.ts 全文只有 38 行却是整个 subpath 体系的枢纽import pluginSdkEntryList from ../../scripts/lib/plugin-sdk-entrypoints.json with { type: json }; export const pluginSdkEntrypoints [...pluginSdkEntryList]; export const pluginSdkSubpaths pluginSdkEntrypoints.filter((entry) entry ! index); /** Map every SDK entrypoint name to its source file path inside the repo. */ export function buildPluginSdkEntrySources(entries: readonly string[] pluginSdkEntrypoints) { return Object.fromEntries(entries.map((entry) [entry, src/plugin-sdk/${entry}.ts])); } /** List the public package specifiers that should resolve to plugin SDK entrypoints. */ export function buildPluginSdkSpecifiers() { return pluginSdkEntrypoints.map((entry) entry index ? openclaw/plugin-sdk : openclaw/plugin-sdk/${entry}, ); } /** Build the package.json exports map for all plugin SDK subpaths. */ export function buildPluginSdkPackageExports() { return Object.fromEntries( pluginSdkEntrypoints.map((entry) [ entry index ? ./plugin-sdk : ./plugin-sdk/${entry}, { types: ./dist/plugin-sdk/${entry}.d.ts, default: ./dist/plugin-sdk/${entry}.js, }, ]), ); }从这段实现可以读出设计要点JSON manifest 是唯一事实来源。入口名到源文件路径的映射是纯约定的src/plugin-sdk/entry.ts不扫描目录、不做推断避免“目录里有文件但没暴露”或“暴露了但没有源文件”的漂移。四种派生视图buildPluginSdkEntrySources源文件路径、buildPluginSdkSpecifiers公开导入规格如openclaw/plugin-sdk/telegram、buildPluginSdkPackageExportspackage.json exports 表、listPluginSdkDistArtifacts构建产物dist/plugin-sdk/entry.js/.d.ts清单。任何一处分叉都会被后文的同步测试抓到。2.2 package.json exports 与清单的强同步index.test.ts 中有一条测试直接断言package.json的./plugin-sdk/*exports 必须等于buildPluginSdkPackageExports()的计算结果it(keeps package.json plugin-sdk exports synced with the manifest, async () { // ... const currentPluginSdkExports Object.fromEntries( Object.entries(packageJson.exports ?? {}).filter(([key]) key.startsWith(./plugin-sdk)), ); expect(currentPluginSdkExports).toEqual(buildPluginSdkPackageExports()); });这与规约文档“Expanding The Boundary”一节的要求一一对应新增或变更公开 subpath 时package.jsonexports 必须与 scripts/lib/plugin-sdk-entrypoints.json、entrypoints.ts 保持对齐。当前 package.json 中已能看到./plugin-sdk、./plugin-sdk/core、./plugin-sdk/telegram、./plugin-sdk/provider-entry等条目每条都是typesdefault双映射。三、四条 Boundary Rules 逐条拆解规约文档的“Boundary Rules”一节给出四条纪律每一条在仓库里都有可验证的守护机制。3.1 优先窄的、目的明确的 subpath而不是宽泛的便捷 re-export规则原文“Prefer narrow, purpose-built subpaths over broad convenience re-exports.”从源码结构看这条规则落实在 index.ts 的自我约束上根入口只导出类型ChannelPlugin、OpenClawPluginApi、PluginRuntime等和少量必要符号且带一条弃用标记/** deprecated Use OpenClawConfig instead */的ClawdbotConfig别名说明连根入口的“存量宽导出”都在被逐步收窄。更硬的证据在 index.test.tsit(keeps the root runtime surface intentionally small, async () { const runtimeExports await readIndexRuntimeExports(); expect([...runtimeExports].toSorted()).toEqual([ delegateCompactionToRuntime, emptyPluginConfigSchema, onDiagnosticEvent, registerContextEngine, ]); });测试用正则遍历index.ts的export { ... } from与export * from链断言根入口的运行时导出白名单恰好只有 4 个符号。另有does not expose runtime modules用例index.test.ts维护一份禁止出现在根入口的符号黑名单包括chunkMarkdownText、buildMentionRegexes、monitorTelegramProvider、sendMessageSlack、probeSignal等——这些能力都被要求走专用 subpath如telegram、slack或各*-runtime而不是从根入口“顺路”拿到。3.2 不暴露src/channels/**、src/agents/**、src/plugins/**等内部实现规则原文“Do not expose implementation convenience fromsrc/channels/**,src/agents/**,src/plugins/**, or other internals unless you are intentionally promoting a supported public contract.”这条由仓库根目录的 extension-plugin-sdk-boundary.test.ts 与scripts/check-extension-plugin-sdk-boundary.mjs联合守护。该测试对三种越界模式分别断言清单inventory为空src-outside-plugin-sdkextensions/**不允许 import 落在 plugin-sdk 之外的src/**路径plugin-sdk-internal禁止通过相对路径绕过如从某 subpath 文件再../摸到 SDK 内部relative-outside-package禁止用相对导入跨出包边界。const srcOutsideInventoryPromise collectExtensionPluginSdkBoundaryInventory(src-outside-plugin-sdk); // ... it(stays empty and sorted, async () { const inventory await srcOutsideInventoryPromise; expect(inventory).toEqual([]); // ... });“stays empty”的写法值得注意它不是“检查当前没有越界”而是把清单本身锁死为空集任何一次新增越界导入都会让清单变非空、测试直接失败——这正是规约所要求的“intentionally promoting a supported public contract”才允许破例的落地方式。3.3 优先api.runtime或聚焦的 SDK facade而非让扩展直接摸宿主内部规则原文“Preferapi.runtimeor a focused SDK facade over telling extensions to reach into host internals directly.”这条规则背后的架构在 docs/refactor/plugin-sdk.md 中被完整描述为两层结构Plugin SDK编译期、稳定、可发布类型、辅助函数、配置工具无运行时状态、无副作用Plugin Runtime执行面、注入式所有触碰核心运行时行为的能力统一经OpenClawPluginApi.runtime注入插件永远不 importsrc/**。运行时注入点在 src/plugins/types.ts 中可以确认export type OpenClawPluginApi { // ... /** * In-process runtime helpers for trusted native plugins. * * This surface is broader than hooks. Prefer hooks for third-party * automation/integration unless you need native registry integration. */ runtime: PluginRuntime; // ... };即插件注册函数拿到的是api对象需要文本分片、回复派发、路由解析、配对、媒体处理等宿主能力时走api.runtime.channel.*等命名空间而不是import { ... } from openclaw/...之外的深层路径。docs/refactor/plugin-sdk.md 的 Phase 5 还规划了 lint 规则 / CI 检查“noextensions/**imports fromsrc/**”与 3.2 节的 inventory 测试互为表里。3.4 bundled 插件助手必须经extensions/id/api.tssrc/plugin-sdk/id.tsfacade 暴露规则原文当 core 或测试需要 bundled 插件的助手函数时应通过extensions/id/api.ts与配套的src/plugin-sdk/id.tsfacade 暴露而不是直接 importextensions/id/src/**或extensions/id/onboard.js。配套的自动化护栏在 src/plugin-sdk/plugin-entry-guardrails.test.tsconst CORE_PLUGIN_ENTRY_IMPORT_RE /import\s*\{[^}]*\bdefinePluginEntry\b[^}]*\}\s*from\s*openclaw\/plugin-sdk\/core/; it(keeps bundled extension entry modules off direct definePluginEntry imports from core, async () { // 遍历 extensions/ 下所有插件目录的 index.ts // 命中上述正则即记为失败 expect(failures).toEqual([]); });它要求 bundled 插件入口不得直接从openclaw/plugin-sdk/core导入definePluginEntry而应使用 plugin-entry.ts 暴露的规范入口辅助函数/** * Canonical entry helper for non-channel plugins. * * Use this for provider, tool, command, service, memory, and context-engine * plugins. Channel plugins should use defineChannelPluginEntry(...) from * openclaw/plugin-sdk/core so they inherit the channel capability wiring. */ export function definePluginEntry({ id, name, description, kind, configSchema, register }): DefinedPluginEntryprovider 类插件则有对应的defineSingleProviderPluginEntryprovider-entry.ts它把 API Key 认证方法createProviderApiKeyAuthMethod、环境变量归并resolveEnvVars、wizard 装配resolveWizardSetup等样板封装掉插件作者只需声明provider配置块。四、API 基线让“公共 API 漂移”可审计规约文档把 “API baseline and export checks” 列为新增 subpath 时必须对齐的一项。其实现是 api-baseline.tsexport type PluginSdkApiBaseline { generatedBy: scripts/generate-plugin-sdk-api-baseline.ts; modules: PluginSdkApiModule[]; }; const GENERATED_BY scripts/generate-plugin-sdk-api-baseline.ts as const; const DEFAULT_JSON_OUTPUT docs/.generated/plugin-sdk-api-baseline.json; const DEFAULT_STATEFILE_OUTPUT docs/.generated/plugin-sdk-api-baseline.jsonl;其工作方式从源码结构看用ts.findConfigFile定位tsconfig.json通过ts.createProgram建立全仓库类型程序api-baseline.ts对每个入口模块的每个导出符号记录exportName、kindclass/function/interface/type/enum/namespace/const/variable/unknown、declaration文本与精确到行的源码位置PluginSdkApiExport 类型定义将绝对路径的声明导入规格归一化为仓库相对路径normalizeDeclarationImportSpecifier保证基线文件跨机器可 diff输出 JSON / JSONL 两份基线产物到docs/.generated/由scripts/generate-plugin-sdk-api-baseline.ts生成。这意味着任何一次对 subpath 导出集合的增删改都会体现在基线 diff 中——“删除或重命名公开导出”不再是一次无感知的顺手清理而是留下可审查记录的显式动作恰好呼应规约最后一条Breaking removals or renames are major-version work, not drive-by cleanup.五、Expanding The Boundary扩张纪律的完整清单规约文档“Expanding The Boundary”一节给出三条扩张纪律可以整理成一份可操作的清单默认只做向后兼容的增量变更Additive, backwards-compatible changes are the default。新增或变更公开 subpath 时五处必须同步docs/plugins/*下的文档scripts/lib/plugin-sdk-entrypoints.json清单src/plugin-sdk/entrypoints.ts派生逻辑通常是零改动package.json的exports由buildPluginSdkPackageExports()的同步测试守护;API 基线与导出检查docs/.generated/plugin-sdk-api-baseline.json 各*.test.ts。bundled provider 的 onboarding / config 助手更新“生成的插件 facade”即src/plugin-sdk/id.ts系列而不是让 core 测试或命令去触碰私有 extension 文件。破坏性删除或改名 major-version 级工作禁止搭车式清理。此外还有两条由package.jsonscripts 固化下来的 CI 级检查与上述清单配套见 package.json 的check与 lint 定义lint:plugins:no-monolithic-plugin-sdk-entry-imports运行 scripts/check-no-monolithic-plugin-sdk-entry-imports.ts防止代码退化为“一个大入口全量导入”的旧模式强制走窄 subpathpnpm build/build:plugin-sdk:dts构建时先跑copy-plugin-sdk-root-alias.mjs与write-plugin-sdk-entry-dts.ts为每个入口写出dist/plugin-sdk/entry.d.ts与listPluginSdkDistArtifacts()声明的产物一一对应。六、小结一套可验证的契约工程把plugin-sdk/CLAUDE.md的文本与仓库实现对照后可以看到它并不是一份停留在纸面的规范规约条款仓库中的验证机制根入口保持极小index.test.ts 白名单断言仅 4 个运行时符号subpath 清单单一来源entrypoints.ts 派生 exports/specifiers/dist 产物index.test.ts断言 package.json 同步禁止插件越界 importextension-plugin-sdk-boundary.test.ts 三种模式 inventory 恒为空插件入口走规范 helperplugin-entry-guardrails.test.ts 正则扫描extensions/*/index.ts公共 API 漂移可审计api-baseline.ts 生成带行号的导出基线对插件开发者而言日常结论很直接只从openclaw/plugin-sdk/subpath的窄入口导入如openclaw/plugin-sdk/provider-entry、openclaw/plugin-sdk/telegram运行时能力经注入的api.runtime获取对核心维护者而言任何一次触碰该目录的改动都应以“清单、exports、文档、基线四处一致”作为合并前提。附关键文件索引边界规约plugin-sdk/CLAUDE.md与 src/plugin-sdk/CLAUDE.md、src/plugin-sdk/AGENTS.md 内容一致架构规划docs/refactor/plugin-sdk.md入口清单scripts/lib/plugin-sdk-entrypoints.json、src/plugin-sdk/entrypoints.ts根入口与测试src/plugin-sdk/index.ts、src/plugin-sdk/index.test.ts、src/plugin-sdk/subpaths.test.ts入口 helpersrc/plugin-sdk/plugin-entry.ts、src/plugin-sdk/provider-entry.ts、src/plugin-sdk/core.tsAPI 基线src/plugin-sdk/api-baseline.ts边界守护extension-plugin-sdk-boundary.test.ts、src/plugin-sdk/plugin-entry-guardrails.test.ts、scripts/check-no-monolithic-plugin-sdk-entry-imports.ts赞分享人工智能大模型LLM 网关AI Agent即时通讯【免费下载链接】openclaw-zero-tokenOpenClaw: Use All Major AI Models NO API Token! Claude/ChatGPT/Gemini/DeepSeek/Doubao/Grok/Qwen/Manus/Kimi项目地址https://gitcode.com/gh_mirrors/op/openclaw-zero-token点击查看免费下载相关推荐OpenClaw 插件边界Extensions Boundary权威指南Plugin SDK 契约、边界规则与扩展机制OpenClaw 插件边界Extensions Boundary权威指南Plugin SDK 契约、边界规则与扩展机制 本文围绕仓库根目录 AGENTS.人工智能大模型LLM 网关AI Agent即时通讯OpenClaw 扩展边界规范内置插件如何通过 Plugin SDK 与清单契约与核心解耦OpenClaw 扩展边界规范内置插件如何通过 Plugin SDK 与清单契约与核心解耦 本文基于 OpenClaw 仓库中的扩展边界规范文档 extensAI 应用AI Agent交互助手后端即时通讯网关OpenClaw Plugin SDK 边界契约从 plugin-sdk/AGENTS.md 到公共入口点的完整治理指南OpenClaw Plugin SDK 边界契约从 plugin sdk/AGENTS.md 到公共入口点的完整治理指南 本文以 OpenClaw 仓库中的人工智能大模型LLM 网关AI Agent即时通讯上一篇gh_mirrors/tr/training-data-analyst项目中的版本控制最佳实践下一篇为什么选择spacy-llm对比传统NLP方法的5大优势创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考