跳转到主要内容
本篇展示一个完整的插件示例,基于 飞书 平台实现。 示例包含插件功能、配置、代码结构、接口实现、增强点等内容,帮助你理解如何在 Xpert AI 平台 开发类似的集成插件。

背景介绍

Xpert AI 插件系统允许开发者通过 插件扩展 平台功能。以飞书文档为例,我们希望实现以下场景:
  • 系统集成:接入飞书应用的 AppID、AppSecret 等凭证,完成鉴权。
  • 文档加载:从飞书的文件夹或文档 API 中获取文档内容。
  • 知识管理:将文档转化为可供 Xpert AI 知识库和智能体使用的结构化内容。
  • 扩展策略:通过策略(Strategy)接口规范,实现接入、文档源、文档转换的扩展点。
最终效果是:用户只需配置好飞书集成信息,Xpert AI 就能自动从飞书文档中读取内容,并将其纳入 AI 对话和知识库之中。

1. 克隆插件模版

我们提供了一个 插件开发起点模版,方便快速构建新的插件:
git clone git@github.com:xpert-ai/xpert-plugins-starter.git lark
cd lark
安装依赖:
npm install
使用 nx 新建一个插件库,其中 packages/lark 是插件代码在项目中的目录,@xpert-ai/plugin-lark 是插件 npm 包名:
npx nx g @nx/js:lib packages/lark \
  --publishable \
  --importPath=@xpert-ai/plugin-lark \
  --bundler=tsc \
  --unitTestRunner=jest \
  --linter=eslint
确认插件信息:
npx nx show project @xpert-ai/plugin-lark
✅ 这里我们生成了一个名为 @xpert-ai/plugin-lark 的插件,它将承载飞书文档的所有集成功能。

2. 插件入口代码

插件的入口代码主要包含 元信息(meta)、配置(config)、生命周期函数(register/onStart/onStop)
import { z } from 'zod';
import { type XpertPlugin } from '@xpert-ai/plugin-sdk';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { initI18n } from './lib/i18n.js';
import { LarkModule } from './lib/lark.module.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const ConfigSchema = z.object({});

const plugin: XpertPlugin<z.infer<typeof ConfigSchema>> = {
  meta: {
    name: '@xpert-ai/plugin-lark',
    version: '1.0.0',
    category: 'doc-source',
    displayName: 'Lark Plugin',
    description: 'Integrate Lark functionality',
    keywords: ['lark', 'feishu', 'document source'],
    author: 'Xpert AI team',
  },
  config: {
    schema: ConfigSchema,
  },
  register(ctx) {
    ctx.logger.log('register lark plugin');
    initI18n(join(__dirname, '../src'));
    return { module: LarkModule, global: true };
  },
  async onStart(ctx) {
    ctx.logger.log('lark plugin started');
  },
  async onStop(ctx) {
    ctx.logger.log('lark plugin stopped');
  },
};

export default plugin;

核心要点

  1. meta:定义插件的基本信息(名字、版本、分类、关键词等)。
  2. config:描述插件的配置 Schema,用户可在 UI 中输入配置等(预留机制,暂未实现)。
  3. register:注册 LarkModule,将插件挂载到 NestJS 模块体系。
  4. onStart/onStop:插件的生命周期回调。

3. NestJS 模块结构

插件实际是一个 NestJS 模块LarkModule),它将不同的 策略类(Strategy)、控制器(Controller)或者服务(Service) 注册进来。
import chalk from 'chalk';
import { XpertServerPlugin, IOnPluginBootstrap, IOnPluginDestroy } from '@xpert-ai/plugin-sdk';
import { LarkIntegrationStrategy } from './integration.strategy.js';
import { LarkController } from './lark.controller.js';
import { LarkSourceStrategy } from './source.strategy.js';
import { LarkDocTransformerStrategy } from './transformer.strategy.js';

@XpertServerPlugin({
	controllers: [LarkController],
	providers: [
		LarkIntegrationStrategy,
		LarkSourceStrategy,
		LarkDocTransformerStrategy
	]
})
export class LarkModule implements IOnPluginBootstrap, IOnPluginDestroy {
	onPluginBootstrap(): void {
		console.log(chalk.green(`${LarkModule.name} is being bootstrapped...`));
	}
	onPluginDestroy(): void {
		console.log(chalk.green(`${LarkModule.name} is being destroyed...`));
	}
}
✅ 这里的 Strategy 就是插件的扩展点,例如:
  • LarkIntegrationStrategy:处理与飞书系统的集成。
  • LarkSourceStrategy:定义如何从飞书加载文档。
  • LarkDocTransformerStrategy:定义如何将文档转化为知识库可用的格式。

4. API 接口

控制器 用于暴露插件的 REST 接口。例如:测试连接飞书。
@Post('test')
async connect(@Body() integration: IIntegration) {
  try {
    const botInfo = await this.integrationStrategy.validateConfig(integration.options)
    return integration
  } catch (err) {
    throw new ForbiddenException('Credentials failed')
  }
}
调用 /lark/test 接口时(目前是测试系统集成连通性的默认路径规则,后续会改成统一验证接口),系统会去验证配置是否正确(AppID/AppSecret 是否有效)。

5. 插件增强点

5.1 系统集成增强

系统集成策略 LarkIntegrationStrategy 用于处理飞书应用凭证验证,获取机器人信息等。 关键逻辑:
async validateConfig(config: TLarkIntegrationConfig) {
  if (!config.appId || !config.appSecret) {
    throw new Error('App ID and Secret required')
  }
  const larkClient = new LarkClient({ options: config } as IIntegration)
  const botInfo = await larkClient.getBotInfo()
  if (!botInfo) throw new ForbiddenException('Bot permission denied')
  return botInfo
}
✅ 这里使用 LarkClient 封装飞书 OpenAPI 请求。

5.2 文档源增强

文档源策略 LarkSourceStrategy 定义如何从飞书中获取文档列表。
  • 配置参数:文件夹 Token、文档类型(docx/sheet/file等)。
  • 加载逻辑:调用 client.listDriveFiles(folderToken),返回 Document[]

5.3 文档转换增强

文档转换策略 LarkDocTransformerStrategy 定义如何将文档内容转化为知识库条目。
  • 调用飞书 API 获取文档正文。
  • 将正文切分为 Document(可供向量化)。
  • 输出为 IKnowledgeDocument 格式。

5.4 客户端封装

所有 API 请求都通过 LarkClient 统一封装 @larksuiteoapi/node-sdk 功能,提供以下方法:
  • getBotInfo() 获取机器人信息
  • listDriveFiles(folderToken) 列出文件夹内容
  • getDocumentContent(docToken) 获取文档正文
  • getAllDocsInFolder(folderToken) 递归获取所有文档
这样,插件的 策略层只需调用 Client 方法,无需关心 API 细节。

6. 开发流程总结

  1. 准备模版:克隆插件模版并生成插件项目。
  2. 编写入口:定义插件 meta、config 和生命周期。
  3. 构建模块:在 LarkModule 中注册控制器和策略类。
  4. 实现策略
    • 集成策略:处理 AppID、Secret 验证。
    • 文档源策略:从飞书获取文档。
    • 转换策略:把文档转化为知识库内容。
  5. 封装客户端:统一管理飞书 API 调用。
  6. 测试接口:通过 /lark/test 验证集成是否正常。

7. 构建、发布与 npm 发布流程

当我们完成了 @xpert-ai/plugin-lark 插件的开发,就可以通过 Nx 提供的构建与发布工具链 将其构建并发布到 npm 仓库。整个流程分为以下几个步骤:

7.1 构建插件

执行构建命令:
npx nx build @xpert-ai/plugin-lark
  • 该命令会调用 Nx 的构建器(默认使用 TypeScript 编译器 tsc),将源码编译为 JavaScript。
  • 构建结果会输出到:
    packages/lark/dist
    
  • 输出目录中的内容就是可发布的产物(包含 index.js、类型声明 .d.ts 等)。

7.2 版本管理

为了确保 npm 包的迭代规范,需要正确维护插件版本号。 推荐使用 Nx 提供的 release 流程 自动管理版本:

自动 bump 版本

npx nx release patch @xpert-ai/plugin-lark
  • patch:修复版本号(例如 1.0.0 → 1.0.1)
  • minor:小版本更新(例如 1.0.0 → 1.1.0)
  • major:大版本更新(例如 1.0.0 → 2.0.0)
命令会自动:
  1. 修改 package.json 中的版本号。
  2. 更新 CHANGELOG.md
  3. 生成对应的 Git tag。
如果不使用 nx release,也可以手动修改 package.jsonversion 字段。

7.3 发布到 npm

构建和版本 bump 完成后,就可以执行发布命令:
npx nx run @xpert-ai/plugin-lark:nx-release-publish --access public --otp=<one-time-password-if-needed>
  • --access public 指定包为公开发布(适用于 @xpert-ai 这种 npm scope 下的包)。
  • --otp=<code> 如果 npm 账号开启了 双因素认证 (2FA),需要输入一次性密码 (OTP)。
⚠️ 注意:发布前请确认 package.json 中以下字段是否正确:
  • main:指向构建产物入口,例如 "dist/index.js"
  • types:指向类型声明,例如 "dist/index.d.ts"
  • files:确保只包含需要发布的文件(例如 "dist/**/*"
  • publishConfig:可定义默认发布权限(如 "access": "public"

7.4 最终流程示例

综合上述步骤,发布 @xpert-ai/plugin-lark 插件的完整命令如下:
# 1. 构建插件
npx nx build @xpert-ai/plugin-lark

# 2. 自动 bump 版本(此处为 patch 版本)
npx nx release patch @xpert-ai/plugin-lark

# 3. 发布到 npm
npx nx run @xpert-ai/plugin-lark:nx-release-publish --access public --otp=<one-time-password-if-needed>
执行成功后,npm 上就能看到最新的 @xpert-ai/plugin-lark 版本。 🎉

8. 最终使用效果

完成插件开发后,你可以在 Xpert AI 平台中:
  • 配置飞书 AppID/AppSecret
  • 选择文档文件夹和类型
  • 自动加载飞书文档内容
  • 将文档转化为知识库,支持 AI 对话和智能体分析