xopcbot 扩展系统
xopcbot 提供了一个轻量级但功能强大的扩展系统。
特性
- 🏗️ 三级存储架构 - Workspace / Global / Bundled
- 🔌 Extension SDK - 官方 SDK,统一导入路径
- ⚡ TypeScript 原生 - 通过 jiti 即时加载,无需编译
- 📦 多源安装 - 支持 npm、本地目录、Git 仓库
快速开始
安装扩展
方式一:使用 CLI(推荐)
bash
# 从 npm 安装到 workspace
xopcbot extension install xopcbot-extension-hello
# 安装到 global(跨项目共享)
xopcbot extension install xopcbot-extension-hello --global
# 从本地目录安装
xopcbot extension install ./my-local-extension
# 查看已安装扩展
xopcbot extension list
# 移除扩展
xopcbot extension remove hello方式二:手动安装
bash
# Global 目录
cd ~/.xopcbot/extensions
git clone https://github.com/your/extension.git
# 或 Workspace 目录
cd workspace/.extensions
git clone https://github.com/your/extension.git启用扩展
在 ~/.xopcbot/config.json 中配置:
json
{
"extensions": {
"enabled": ["hello", "echo"],
"hello": { "greeting": "Hi there!" },
"echo": true
}
}配置格式说明:
| 字段 | 类型 | 说明 |
|---|---|---|
enabled | string[] | 要启用的扩展 ID 列表 |
disabled | string[] | (可选)禁用的扩展 ID 列表 |
[extension-id] | object | boolean | 扩展特定配置 |
示例配置:
json
{
"extensions": {
"enabled": ["telegram-channel", "weather-tool", "echo"],
"disabled": ["deprecated-extension"],
"telegram-channel": {
"token": "bot-token-here",
"webhookUrl": "https://example.com/webhook"
},
"weather-tool": {
"apiKey": "weather-api-key",
"defaultCity": "Beijing"
},
"echo": true
}
}enabled数组中的扩展会被加载- 扩展 ID 作为 key 可以配置扩展特定的选项
- 如果扩展不需要配置,可以设为
true
创建新扩展
bash
# 创建扩展脚手架
xopcbot extension create my-extension --name "My Extension" --kind utility
# 支持的 kind: channel|provider|memory|tool|utility这将创建:
package.json- npm 配置index.ts- 扩展入口(TypeScript,使用 xopcbot/extension-sdk)xopcbot.extension.json- 扩展清单README.md- 文档模板
三级存储架构
xopcbot 支持三级扩展存储,按优先级从高到低:
| 级别 | 路径 | 用途 | 优先级 |
|---|---|---|---|
| Workspace | workspace/.extensions/ | 项目私有扩展 | ⭐⭐⭐ 最高 |
| Global | ~/.xopcbot/extensions/ | 用户级共享扩展 | ⭐⭐ 中 |
| Bundled | xopcbot/extensions/ | 内置扩展 | ⭐ 最低 |
优先级规则
- Workspace 扩展可以覆盖 Global 和 Bundled 同名扩展
- Global 扩展可以覆盖 Bundled 同名扩展
- 适合场景:
- Workspace:项目特定的定制扩展
- Global:常用的共享扩展(如 telegram-channel)
- Bundled:随 xopcbot 发布的官方扩展
Global 扩展目录
bash
# 默认位置
~/.xopcbot/extensions/
# 自定义位置(环境变量)
export XOPCBOT_GLOBAL_EXTENSIONS=/path/to/global/extensionsExtension SDK
xopcbot 提供官方 Extension SDK,统一导出所有扩展开发所需的类型和接口。
使用 SDK
typescript
// 推荐方式:使用官方 SDK
import type { ExtensionApi, ExtensionDefinition } from 'xopcbot/extension-sdk';
// 不推荐使用内部路径
// import type { ... } from 'xopcbot/extensions'; ❌导出的类型
typescript
// 核心类型
import type {
ExtensionDefinition, // 扩展定义
ExtensionApi, // 扩展 API
ExtensionLogger, // 日志接口
} from 'xopcbot/extension-sdk';
// 工具
import type {
ExtensionTool, // 工具定义
ExtensionToolContext, // 工具上下文
} from 'xopcbot/extension-sdk';
// 钩子
import type {
ExtensionHookEvent, // 钩子事件类型
ExtensionHookHandler, // 钩子处理器
HookOptions, // 钩子选项
} from 'xopcbot/extension-sdk';
// 通道
import type {
ChannelExtension, // 通道扩展
OutboundMessage, // 出站消息
} from 'xopcbot/extension-sdk';
// 命令
import type {
ExtensionCommand, // 命令定义
CommandContext, // 命令上下文
CommandResult, // 命令结果
} from 'xopcbot/extension-sdk';
// 服务
import type {
ExtensionService, // 服务定义
ServiceContext, // 服务上下文
} from 'xopcbot/extension-sdk';SDK 路径解析
在底层,xopcbot 使用 jiti 配置路径别名:
typescript
// jiti 配置
{
alias: {
'xopcbot/extension-sdk': './src/extension-sdk/index.ts'
}
}这意味着扩展开发时无需关心 xopcbot 源码位置,SDK 路径会自动解析。
这将创建:
- `package.json` - npm 配置
- `index.ts` - 扩展入口(TypeScript,支持 jiti 即时加载)
- `xopcbot.extension.json` - 扩展清单
- `README.md` - 文档模板
## CLI 命令参考
### extension install
安装扩展。
```bash
# 从 npm 安装
xopcbot extension install <package-name>
# 安装特定版本
xopcbot extension install my-extension@1.0.0
# 从本地目录安装
xopcbot extension install ./local-extension-dir
xopcbot extension install /absolute/path/to/extension
# 设置超时时间(默认 120 秒)
xopcbot extension install slow-extension --timeout 300000安装流程:
- 下载/复制扩展文件
- 验证
xopcbot.extension.json清单 - 安装依赖(如有
package.json依赖) - 复制到工作区
.extensions/目录
extension list
列出所有已安装扩展。
bash
xopcbot extension list输出示例:
📦 Installed Extensions
════════════════════════════════════════════════════════════
📁 Telegram Channel
ID: telegram-channel
Version: 1.2.0
Path: /home/user/.xopcbot/workspace/.extensions/telegram-channel
📁 My Custom Extension
ID: my-custom-extension
Version: 0.1.0
Path: /home/user/.xopcbot/workspace/.extensions/my-custom-extensionextension remove / uninstall
移除已安装扩展。
bash
xopcbot extension remove <extension-id>
xopcbot extension uninstall <extension-id>注意:移除扩展后,如果已启用,还需要从配置文件中删除。
extension info
查看扩展详情。
bash
xopcbot extension info <extension-id>extension create
创建新扩展脚手架。
bash
xopcbot extension create <extension-id> [options]
Options:
--name <name> 扩展显示名称
--description <desc> 扩展描述
--kind <kind> 扩展类型: channel|provider|memory|tool|utility示例:
bash
# 创建一个工具类扩展
xopcbot extension create weather-tool --name "Weather Tool" --kind tool
# 创建一个通道类扩展
xopcbot extension create discord-channel --name "Discord Channel" --kind channel扩展结构
Manifest 文件
每个扩展必须包含一个 xopcbot.extension.json 文件:
json
{
"id": "my-extension",
"name": "My Extension",
"description": "A description of my extension",
"version": "1.0.0",
"main": "index.js",
"configSchema": {
"type": "object",
"properties": {
"option1": {
"type": "string",
"default": "value"
}
}
}
}扩展入口文件
javascript
// index.js
import type { ExtensionApi } from 'xopcbot-extension-sdk';
const extension = {
id: 'my-extension',
name: 'My Extension',
description: 'Description here',
version: '1.0.0',
// Called when extension is registered
register(api: ExtensionApi) {
// Register tool
api.registerTool({...});
// Register command
api.registerCommand({...});
// Register hook
api.registerHook('message_received', async (event, ctx) => {...});
// 注册 HTTP 路由
api.registerHttpRoute('/my-route', async (req, res) => {...});
},
// Called when extension is enabled
activate(api: ExtensionApi) {
console.log('Extension activated');
},
// Called when extension is disabled
deactivate(api: ExtensionApi) {
console.log('Extension deactivated');
},
};
export default extension;核心概念
工具 (Tools)
扩展可以注册自定义工具供 Agent 使用:
javascript
api.registerTool({
name: 'my_tool',
description: 'Do something useful',
parameters: {
type: 'object',
properties: {
input: { type: 'string', description: 'Input value' }
},
required: ['input']
},
async execute(params) {
const input = params.input;
// Perform operation
return `Result: ${input}`;
}
});钩子 (Hooks)
钩子允许扩展在各个生命周期点拦截和修改行为:
| 钩子 | 时机 | 用途 |
|---|---|---|
before_agent_start | Agent 启动前 | 修改系统提示 |
agent_end | Agent 完成后 | 后处理结果 |
message_received | 收到消息时 | 消息预处理 |
message_sending | 发送消息前 | 拦截/修改消息内容 |
message_sent | 消息发送后 | 发送日志 |
before_tool_call | 工具调用前 | 参数验证 |
after_tool_call | 工具调用后 | 结果处理 |
session_start | 会话开始 | 初始化 |
session_end | 会话结束 | 清理 |
gateway_start | 网关启动 | 配置 |
gateway_stop | 网关关闭 | 清理 |
javascript
// message_sending hook - intercept or modify AI sent messages
api.registerHook('message_sending', async (event, ctx) => {
const { to, content } = event;
// 1. Block message sending (e.g., content moderation)
if (content.includes('敏感信息')) {
return {
cancel: true,
cancelReason: 'Content contains sensitive information'
};
}
// 2. Modify message content (e.g., add signature, replace content)
if (content.includes('{{signature}}')) {
return {
content: content.replace('{{signature}}', '\n\n— Sent by AI Assistant')
};
}
// 3. Block for specific chat
if (to === 'blocked-chat-id') {
return {
cancel: true,
cancelReason: 'This chat is blocked'
};
}
});
// before_tool_call hook - block or modify tool calls
api.registerHook('before_tool_call', async (event, ctx) => {
const { toolName, params } = event;
// Block dangerous operations
if (toolName === 'delete_file' || toolName === 'execute_command') {
return {
block: true,
blockReason: 'This operation is disabled for safety'
};
}
// Modify parameters
if (toolName === 'write_file' && params.path?.includes('/etc/')) {
return {
params: { ...params, path: params.path.replace('/etc/', '/safe/') }
};
}
});命令 (Commands)
注册自定义命令:
javascript
api.registerCommand({
name: 'status',
description: 'Check extension status',
acceptArgs: false,
requireAuth: true,
handler: async (args, ctx) => {
return {
content: 'Extension is running!',
success: true
};
}
});HTTP 路由
javascript
api.registerHttpRoute('/my-extension/status', async (req, res) => {
res.json({ status: 'running', extension: 'my-extension' });
});网关方法
javascript
api.registerGatewayMethod('my-extension.status', async (params) => {
return { status: 'running' };
});后台服务
javascript
api.registerService({
id: 'my-service',
start(context) {
// Start background task
this.interval = setInterval(() => {
// Scheduled task
}, 60000);
},
stop(context) {
if (this.interval) {
clearInterval(this.interval);
}
}
});配置管理
定义配置模式
json
{
"configSchema": {
"type": "object",
"properties": {
"apiKey": {
"type": "string",
"description": "API Key for the service"
},
"maxResults": {
"type": "number",
"default": 10
}
},
"required": ["apiKey"]
}
}访问配置
javascript
const apiKey = api.extensionConfig.apiKey;
const maxResults = api.extensionConfig.maxResults || 10;日志记录
javascript
api.logger.debug('Detailed debug information');
api.logger.info('General information');
api.logger.warn('Warning message');
api.logger.error('Error message');路径解析
javascript
// Resolve workspace path
const configPath = api.resolvePath('config.json');
// Resolve extension relative path
const dataPath = api.resolvePath('./data.json');事件系统
javascript
// Emit event
api.emit('my-event', { key: 'value' });
// Listen for event
api.on('other-event', (data) => {
console.log('Received:', data);
});
// Remove listener
api.off('my-event', handler);完整示例
javascript
import type { ExtensionApi } from 'xopcbot-extension-sdk';
const extension = {
id: 'example',
name: 'Example Extension',
description: 'A complete example extension',
version: '1.0.0',
configSchema: {
type: 'object',
properties: {
enabled: { type: 'boolean', default: true }
}
},
register(api) {
// Register tool
api.registerTool({
name: 'example_tool',
description: 'Example tool',
parameters: {
type: 'object',
properties: { input: { type: 'string' } },
required: ['input']
},
async execute(params) {
return `Processed: ${params.input}`;
}
});
// Register hook
api.registerHook('message_received', async (event) => {
console.log('Received:', event.content);
});
// Register command
api.registerCommand({
name: 'example',
description: 'Example command',
handler: async (args) => {
return { content: 'Example!', success: true };
}
});
},
activate(api) {
console.log('Extension activated');
},
deactivate(api) {
console.log('Extension deactivated');
}
};
export default extension;发布扩展
- 创建
xopcbot.extension.jsonmanifest - 创建
index.js入口文件 - 推送到 GitHub 或发布到 npm
bash
# 发布到 npm(公开发布)
npm publish --access public
# 如果使用 scoped 包名(推荐)
# package.json: { "name": "@yourname/xopcbot-extension-name" }
npm publish --access public最佳实践
- 错误处理:所有异步操作都应使用 try/catch
- 日志记录:使用 API 的日志系统而非 console
- 资源清理:在
deactivate中释放资源 - 配置验证:使用 JSON Schema 验证配置
- 版本管理:遵循语义化版本