☰
Kun 扩展 API 指南:@kun/extension-api 的框架中立公共契约、Host Client 与 Manifest Schema
2026/10/12 5:21:49 网站建设 项目流程
  • 人工智能
  • AI Agent
  • 自主智能体
  • 桌面应用
  • MCP Clients

【免费下载链接】Kun

Local-first AI agent workspace for coding, writing, design, research, and automation — one runtime for desktop GUI and TUI.

项目地址:https://gitcode.com/gh_mirrors/de/Kun
点击查看免费下载

本文围绕 Kun 开源仓库中 packages/extension-api/README.md 展开,深入讲解 Kun 扩展开发所依赖的公共 SDK 包@kun/extension-api:如何在仓库内或独立项目中安装与构建、如何用ExtensionContext与ExtensionHostClient编写扩展、配置/认证/密钥如何分界,以及ExtensionManifestSchema如何成为 Manifest JSON Schema 的运行时真源。读完本文,你将掌握基于 Kun 扩展 API v1 编写、校验、测试和打包扩展的完整技术路径,并理解其底层的 Host Transport 协议与版本协商机制。

@kun/extension-api是 Kun 扩展体系中的框架中立(framework-neutral)、稳定公共契约(stable public contracts)与 Host 客户端(Host client)包。它的核心承诺是:不依赖 React 或 Electron,扩展作者只需要面向这一层契约编程;同时,ExtensionManifestSchema作为schema/kun-extension.schema.json的规范运行时源(canonical runtime source),保证类型、运行时校验与 JSON Schema 三者始终同源一致。本文所有内容均可在当前仓库中直接核对:包入口见 packages/extension-api/src/index.ts,Schema 生成物见 packages/extension-api/schema/kun-extension.schema.json。

一、包定位与设计原则

@kun/extension-api的职责可以从 packages/extension-api/package.json 中读出全貌:

{ "name": "@kun/extension-api", "version": "1.5.0", "description": "Stable framework-neutral API for Kun extensions", "type": "module", "sideEffects": false, "main": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" }, "./manifest.schema.json": "./schema/kun-extension.schema.json" }, "files": ["dist", "schema", "fixtures", "README.md"], "engines": { "node": ">=20" } }

关键设计点:

  • 单一公开入口:唯一受支持的入口是@kun/extension-api,另有只读的@kun/extension-api/manifest.schema.json子路径。不要导入src/*、dist/*或其它未声明 subpath,即使文件存在于开发仓库中也没有 SemVer 保证(详见 docs/extensions/api-reference.md)。
  • 运行时 Schema 即真源:以Schema结尾的导出(如ExtensionManifestSchema、AgentRunSchema、ToolResultSchema)是运行时校验值(基于zod),同名或相邻的 TypeScript 类型描述通过校验后的静态形状。
  • 唯一依赖:运行时依赖仅zod,这是包保持框架中立、可被 Node 与 Webview 两端共同引用的基础。
  • ESM only:"type": "module"且exports只提供import条件。

ExtensionManifestSchema与 JSON Schema 的“同源”关系由 packages/extension-api/scripts/generate-manifest-schema.mjs 维持:构建后运行schema:generate从 Zod Schema 生成schema/kun-extension.schema.json,schema:check用于发布门禁校验二者一致性(见package.json中的prepack: npm run schema:check)。这意味着你在kun-extension.json中能写的字段,与parseExtensionManifest在运行时接受的字段,永远来自同一份定义。

二、安装模式:仓库工作区与独立项目

关联文档给出了两条安装路径,分别对应“参与仓库开发”与“独立开发扩展”两种场景。

2.1 仓库内安装(npm workspace)

在 Kun 仓库根目录执行:

npm ci npm run build --workspace @kun/extension-api

npm ci依据根目录 package-lock.json 安装全部 workspace 依赖;npm run build --workspace @kun/extension-api会执行tsc -p tsconfig.build.json(见 packages/extension-api/package.json 的build脚本),把src/编译到dist/。之后可在测试中直接引用该 workspace 包。

2.2 独立项目安装(public registry)

对仓库外的独立扩展项目,需要先确认公共 registry 上确实存在该产物,再按名安装:

npm view @kun/extension-api@1.5.0 version npm install @kun/extension-api@^1.5.0

只有第一条命令返回版本号时才执行安装。如果返回E404,说明当前配置的 registry 没有该制品;此时应使用仓库内的扩展示例工作流,不要在需要移植的扩展里添加仓库相对的file:依赖——那会破坏可移植性。这一点在 docs/extensions/quick-start.md 中同样强调:只有当前模板所需的命令都返回版本时才继续。

2.3 独立扩展开发环境确认

开始前先确认环境就绪:

kun --version kun extension --help node --version

Kun CLI 来自 Kun 安装本身;npm 上无 scope 的同名kun包并不是 Kun Agent CLI。

三、最小扩展:activate 与 ExtensionContext

关联文档中的最小示例注册了一条命令:

import type { ExtensionContext } from '@kun/extension-api' export async function activate(context: ExtensionContext) { context.subscriptions.add( await context.commands.registerCommand('hello', async () => ({ ok: true })) ) }

activate是 Node 入口(Manifest 的main字段)导出的约定函数。真正打开 View、调用命令或工具时,Kun 才触发对应激活事件并调用activate,把 Host 创建好的ExtensionContext传入。

3.1 ExtensionContext 的完整服务面

ExtensionContext的完整定义在 packages/extension-api/src/extension-context.ts,它继承了ActivationContextData(包含extension身份、apiVersion、capabilities、permissions、可选的workspaceContext、activationEvent与initialState),并提供如下只读服务:

属性公开契约
subscriptions,onDidError生命周期释放与结构化扩展错误
commands声明过的命令注册、执行与 handler disposal
storage,configuration扩展/工作区隔离状态与声明式设置;不保存秘密
network受 permission/domain/account 约束的 Broker fetch
secrets需storage.secrets的 Node Host 受保护字符串存储;View 不可直接访问
uitheme、locale、View state、Host message、通知和主会话上下文挂载
agent,threads需agent.capacity.read的全局容量;扩展自有 Agent run、事件、steer/cancel 与 thread projection
rooms需rooms.read的房间、消息、任务与事件只读投影
toolsManifest 声明工具的注册、progress、cancellation 与 bounded result
modelProviders自定义 Provider adapter 的 probe/listModels/stream/cancel/countTokens
authenticationredacted account、受保护认证 session、authenticated fetch 与显式 secret reveal
media受保护选择、不透明 handle、bounded metadata/probe、View resource lease 与 brokered FFmpeg job 创建
jobs扩展自有 durable job 的 get/list/subscribe/cancel
workspace,workspaceContext已授权 root 内的文件操作与当前 workspace/trust 投影

这些服务接口的类型定义集中在 packages/extension-api/src/services.ts。createExtensionContext(transport, data)函数接收一个HostTransport与激活数据,内部实例化ExtensionHostClient并把它订阅进DisposableStore(见 packages/extension-api/src/extension-context.ts)。

3.2 生命周期与资源释放

subscriptions是一个DisposableStore,其实现位于 packages/extension-api/src/lifecycle.ts:add()接受Disposable或纯函数,clear()/dispose()按逆序释放所有资源,并把释放过程中的错误聚合成AggregateError抛出。因此,所有registerCommand、registerTool、registerProvider返回的Disposable都应加入context.subscriptions,Host 在扩展停用时会统一释放。

四、配置、认证与密钥的边界

关联文档明确了两条安全边界,这也是编写扩展时最容易出错的地方:

Declared non-secret settings are available fromcontext.configuration; Provider credentials must usecontext.authenticationand the Host-owned protected account flow. Node and Webview clients receive the same scoped configuration API.

4.1 声明式配置(context.configuration)

ConfigurationApi(packages/extension-api/src/services.ts)提供:

  • get<T>(sectionId, key):读取声明式设置值;
  • update(sectionId, key, value):写入;
  • keys(sectionId):枚举;
  • onDidChange:订阅ConfigurationChangeEvent(携带sectionId、key、scope与value)。

Manifest 中通过contributes.settings声明设置 Section(id、title、properties、scope: "global" | "workspace",默认workspace)。Node 与 Webview 客户端拿到的是同一套 scoped configuration API——Webview 也通过context.configuration或 React 模板的useConfiguration读取设置,但设置中不允许放秘密。

4.2 认证与密钥(context.authentication / context.secrets)

  • Provider 凭据一律走context.authentication与 Host 拥有的受保护账号流程(protected account flow):listAccounts、createSession、getSession、cancelSession、deleteAccount、authenticatedFetch、revealSecret。
  • context.secrets(SecretStorageApi)是 Host 保护的、扩展隔离的秘密字符串存储,只对Node Extension Host可用,需要storage.secrets权限;Authenticated View 不能直接访问,必须把依赖秘密的工作路由到声明的命令。

这一点有测试直接佐证:packages/extension-api/test/secrets.test.ts 用TestTransport验证secrets.get/set/delete走的是受保护的secrets.*方法,并断言请求列表不含任何storage.*方法——即秘密永远不会投影进普通存储。

4.3 权限模型

Manifest 的permissions是精确字符串数组,在 packages/extension-api/src/permissions.ts 中分为两类:

  • 静态权限(STATIC_PERMISSIONS):如commands.register、ui.views、webview、agent.run、tools.register、providers.register、storage.secrets、workspace.read/write、media.*、jobs.manage等;
  • 作用域权限:accounts.use|manage|secrets.read:<providerId>与network:<hostname>/network:*.example.com(permissionMatches支持*.前缀的子域通配匹配)。

原则是最小权限:只声明扩展真正需要的权限;新增权限的包版本不会继承旧同意,用户必须在受保护窗口重新确认。

五、ExtensionHostClient 与 HostTransport 协议

Node 入口通常直接拿到 Host 创建的ExtensionContext;Webview 则使用 Host 提供的窄HostTransport自己创建客户端:

import { ExtensionHostClient, type HostTransport } from '@kun/extension-api' export function createViewClient(transport: HostTransport): ExtensionHostClient { return new ExtensionHostClient(transport) }

5.1 HostTransport 抽象

HostTransport(packages/extension-api/src/services.ts)是扩展与 Host 之间的 wire 抽象:

  • request(method, params?, options?):请求-响应调用,支持AbortSignal与timeoutMs;
  • notify(method, params?):单向通知;
  • sendStream?(requestId, payload, terminal?):可选的应答确认流;
  • onNotification(listener):订阅 Host 推送;
  • registerHandler(method, handler):注册扩展侧 handler,供 Host 反向调用。

5.2 ExtensionHostClient 的内部机制

ExtensionHostClient(packages/extension-api/src/client.ts)在构造时把全部 API 面组装到 transport 之上:commands、storage、secrets、configuration、network、ui、agent、rooms、threads、tools、modelProviders、authentication、media、jobs、workspace。几个值得注意的实现细节:

  • 通知分发:#handleNotification根据 method 分发ui.themeChanged、ui.localeChanged、ui.message、configuration.changed、modelProviders.statusChanged、agent.event、jobs.event等;非法通知会触发ExtensionApiError(codePROTOCOL_ERROR)。
  • 订阅缓冲:agent.subscribe与jobs.subscribe在客户端维护订阅状态与orphan event 缓冲——事件先于监听器注册到达时先缓冲,首个监听器挂载后按sequence顺序回放,防止丢事件;同时用MAX_ORPHAN_AGENT_SUBSCRIPTIONS/MAX_ORPHAN_JOB_SUBSCRIPTIONS限制无主缓冲规模。
  • 工具注册:tools.registerTool(declaration, handler)先向 Host 注册,再通过transport.registerHandler('tools.invoke:<registrationId>')接收调用,handler 的返回值统一经ToolResultSchema规范化。
  • Provider 注册:modelProviders.registerProvider(declaration, adapter)委托给 packages/extension-api/src/client-provider-registration.ts 中的registerProvider。

5.3 工具契约要点

扩展工具(ExtensionToolDeclarationSchema,见 packages/extension-api/src/tools.ts)声明id、description、inputSchema,可选outputSchema、sideEffects(none|read|write|external|destructive,默认none)、idempotent(默认 false)与maxOutputBytes(1 KiB–1 MiB)。outputSchema描述并验证ToolResult.content,而不是整个ToolResultenvelope;省略它只表示不启用额外输出结构校验,并不会关闭输出上限。handler 上下文提供cancellation(CancellationToken)与reportProgress()。

六、Manifest Schema:运行时真源

6.1 顶层结构与两种入口形态

ExtensionManifestSchema(packages/extension-api/src/manifest.ts)是 union 结构:

  • Node 形态:必含main,可选browser;
  • Browser-only 形态:必含browser,main被禁用,且contributes不能声明commands、agentProfiles、tools、modelProviders、authentication(这些都需要 Node handler)。

顶层公共字段包括:manifestVersion(v1 固定为1)、apiVersion、name、publisher、version、可选displayName/description/icon/localizations/license/homepage、必填engines: { kun: "<semver range>" }、activationEvents、contributes、permissions、stateSchemaVersion、可选signature(ed25519)。完整字段约束见 docs/extensions/manifest.md 的“顶层字段”表。

parseExtensionManifest(value)就是ExtensionManifestSchema.parse的封装,是运行时校验入口。

6.2 激活事件双向校验

v1 支持的激活事件:onStartup、onView:<id>、onCommand:<id>、onTool:<id>、onProvider:<id>、onAuthentication:<id>、onAgentProfile:<id>。SuperRefine 会做双向检查(packages/extension-api/src/manifest.ts):

  • 每个 View/command/tool/Provider/authentication/Agent profile 贡献必须声明对应事件(或扩展明确使用onStartup);
  • 每个非 startup 事件也必须指向真实存在的贡献——拼错的事件不会被降级处理。

6.3 贡献点与隐含权限

contributes支持的键(packages/extension-api/src/manifest.ts):commands、views.containers、views.leftSidebar/rightSidebar/auxiliaryPanel/editorTab/fullPage、actions.topBar/composer/message、message.resultPreviews、settings、contextMenus、notifications、agentProfiles、tools、modelProviders、authentication、hostContentScripts。

MANIFEST_CONTRIBUTION_PERMISSION_REQUIREMENTS(packages/extension-api/src/manifest.ts)定义了贡献点与最小权限的映射,例如commands → commands.register、任意views.*→ui.views + webview、tools → tools.register、modelProviders → providers.register、hostContentScripts → hostDom。requiredManifestPermissions()据此计算,Schema 在解析时强制执行——缺失必要权限的 Manifest 直接校验失败(测试见 packages/extension-api/test/manifest.test.ts 的requires permissions implied by entrypoints and contributions)。

另外两个有意思的强校验:

  • webview.external必须同时拥有至少一个network:<hostname>grant;带externalBrowser的 View,其每个 site 的 hostname 必须匹配显式network:grant(site URL 还必须是 credential-free 的 HTTPS 默认端口 URL);
  • modelProviders[].authenticationProviderId必须指向本 Manifest 声明的 authentication 贡献。

6.4 本地化覆盖

localizations把最多 32 个 BCP 47 语言标签映射为纯文本显示覆盖(packages/extension-api/src/manifest-localization.ts)。resolveExtensionManifestLocale()先按大小写不敏感完整标签匹配,再逐级回退语言标签(zh-Hans-CN→zh-Hans→zh),最后回退基础 Manifest;且只覆盖显示文案——身份、激活事件、权限、路径、Schema 与指令始终以基础 Manifest 为准(本地化引用未声明贡献会被拒绝,测试见 packages/extension-api/test/manifest.test.ts 的 locale 用例)。

七、API 版本协商与兼容性

7.1 协商算法

packages/extension-api/src/compatibility.ts 实现negotiateApiVersion():Host 声明supportedApiVersions与capabilitiesByVersion,扩展声明declaredApiVersion与requiredCapabilities。协商结果有三种失败码与一种成功态:

  • API_MAJOR_UNSUPPORTED:声明 major 不在支持窗口;
  • API_MINOR_UNSUPPORTED:声明 minor 高于 Host 支持的 minor;
  • CAPABILITY_REQUIRED:要求的 capability 在该协商版本中不可用;
  • 成功:返回negotiatedApiVersion、capabilities与adapter(current/previous,用于判断走哪个 major 的 adapter)。

Kun 支持当前 API major 与前一个 major(当前为 v1,因此只支持 1)。同一安装中不同 major 的扩展可以同时激活,各自使用协商契约;能力缺失时 SDK 暴露 unavailable 或结构化错误,required capability 缺失会在代码执行前 fail closed。

7.2 协商 fixtures

packages/extension-api/fixtures/api-major-negotiation.json 与 packages/extension-api/fixtures/api-minor-negotiation.json 是协商场景的固定输入,配合测试验证 major/minor 边界行为。

7.3 六个版本维度

Manifest 中的version、manifestVersion、apiVersion、engines.kun、stateSchemaVersion与私有的rpcVersion是相互独立的版本维度(详见 docs/extensions/versioning-and-migrations.md):改变一个维度不隐式改变其它维度;rpcVersion不属于第三方 API,Manifest 不声明、扩展不导入。stateSchemaVersion只在持久化状态结构需要迁移时提高,并通过main导出的migrateState(state, context)事务化迁移。

八、测试与验证

包内测试(packages/extension-api/test/)覆盖多个契约面:

  • manifest.test.ts:Manifest 解析、安全默认值、localization 覆盖、权限推导、外部 Webview 授权、激活事件引用;
  • secrets.test.ts:秘密存储不投影进普通存储;
  • agent-run-options.test.ts、capacity-rooms.test.ts、composer-context.test.ts、media-jobs.test.ts、chart.test.ts。

运行测试:

npm run test --workspace @kun/extension-api

发布前的 Schema 一致性门禁:

npm run schema:generate --workspace @kun/extension-api # 重新生成 JSON Schema npm run schema:check --workspace @kun/extension-api # 校验生成物与运行时 Schema 一致

prepack脚本自动执行schema:check,保证发布的.tgz中 JSON Schema 与ExtensionManifestSchema永远同步。

九、从 SDK 到完整扩展:推荐路径

@kun/extension-api只是公共契约层;一个完整扩展通常还配合另外两个 SDK 与宿主 CLI:

包用途
@kun/extension-apiManifest、生命周期、Host client、Agent、工具、Provider、账号、存储、网络、UI、media、job 与 artifact 契约
@kun/extension-react基于ExtensionHostClient的 React Provider、hooks 与状态组件(ExtensionViewProvider、useTheme、useConfiguration等)
@kun/extension-testFake Host/transport/service 与ExtensionTestHarness,提供确定性的媒体与 job fake

完整的开发闭环(脚手架 → 构建 → 测试 → 验证 → 安装 → 日志)参见 docs/extensions/quick-start.md:

npx create-kun-extension hello-sidebar --template react --publisher acme --name hello-sidebar npm install npm run build && npm test && npm run validate kun extension install --development . kun extension reload acme.hello-sidebar npm run pack kun extension install ./dist/acme.hello-sidebar-0.1.0.kunx kun extension logs acme.hello-sidebar

仓库内的扩展示例(如hello-sidebar、tool-provider、streaming-model-provider、agent-assistant等)是可直接对照的完整实现;docs/extensions/api-reference.md 是中文 API 参考与生成导出清单,docs/extensions/manifest.md 是 Manifest 字段级参考,docs/extensions/security-and-resources.md 讲解权限与资源边界。

结语

@kun/extension-api的定位可以概括为三句话:框架中立(不依赖 React/Electron,Node 与 Webview 共用同一契约)、Schema 同源(ExtensionManifestSchema与kun-extension.schema.json由同一份 Zod 定义生成)、稳定可迁移(单一公开入口 + SemVer + API major 协商窗口)。无论你是要在仓库内为 Kun 贡献扩展,还是为独立项目编写可移植的.kunx,从本文的安装命令、activate骨架与 Manifest 校验规则出发,都能快速进入正轨。

  • 人工智能
  • AI Agent
  • 自主智能体
  • 桌面应用
  • MCP Clients

【免费下载链接】Kun

Local-first AI agent workspace for coding, writing, design, research, and automation — one runtime for desktop GUI and TUI.

项目地址:https://gitcode.com/gh_mirrors/de/Kun
点击查看免费下载

相关推荐

上一篇:Vue-codemod:Vue2到Vue3迁移的完整解决方案
下一篇:如何为YTPro贡献代码:新手开发者的完整贡献指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询