插件开发示例
本页面展示了如何为 XAI-SDK 开发自定义插件,包括插件架构、开发流程、最佳实践和完整示例。
📋 插件类型
提供商插件 (Provider Plugins)
连接不同的 AI 服务提供商
适配器插件 (Adapter Plugins)
适配不同的前端框架和环境
功能插件 (Feature Plugins)
扩展 SDK 的核心功能
中间件插件 (Middleware Plugins)
处理请求和响应的中间层
🏗️ 插件架构
基础插件接口
typescript
// src/types/plugin.ts
export interface XAIPlugin {
name: string;
version: string;
description?: string;
dependencies?: string[];
// 插件生命周期方法
initialize?(sdk: XAI_SDK): Promise<void> | void;
activate?(sdk: XAI_SDK): Promise<void> | void;
deactivate?(sdk: XAI_SDK): Promise<void> | void;
destroy?(): Promise<void> | void;
// 插件配置
configure?(config: PluginConfig): void;
// 插件能力声明
capabilities?: PluginCapabilities;
}
export interface PluginConfig {
[key: string]: any;
}
export interface PluginCapabilities {
providers?: string[];
adapters?: string[];
features?: string[];
middleware?: string[];
}
export abstract class BasePlugin implements XAIPlugin {
abstract name: string;
abstract version: string;
description?: string;
dependencies?: string[];
capabilities?: PluginCapabilities;
protected sdk?: XAI_SDK;
protected config?: PluginConfig;
async initialize(sdk: XAI_SDK): Promise<void> {
this.sdk = sdk;
console.log(`Plugin ${this.name} initialized`);
}
async activate(sdk: XAI_SDK): Promise<void> {
console.log(`Plugin ${this.name} activated`);
}
async deactivate(sdk: XAI_SDK): Promise<void> {
console.log(`Plugin ${this.name} deactivated`);
}
async destroy(): Promise<void> {
this.sdk = undefined;
this.config = undefined;
console.log(`Plugin ${this.name} destroyed`);
}
configure(config: PluginConfig): void {
this.config = { ...this.config, ...config };
}
}
🚀 快速开始
创建基础插件
typescript
// src/plugins/my-custom-plugin.ts
import { BasePlugin, XAI_SDK } from 'xai-sdk';
export class MyCustomPlugin extends BasePlugin {
name = 'my-custom-plugin';
version = '1.0.0';
description = '我的自定义插件示例';
capabilities = {
features: ['custom-feature']
};
async initialize(sdk: XAI_SDK): Promise<void> {
await super.initialize(sdk);
// 注册自定义方法
sdk.registerMethod('customMethod', this.customMethod.bind(this));
// 注册事件监听器
sdk.on('beforeRequest', this.onBeforeRequest.bind(this));
sdk.on('afterResponse', this.onAfterResponse.bind(this));
}
private async customMethod(input: string): Promise<string> {
return `Custom processing: ${input}`;
}
private onBeforeRequest(request: any): void {
console.log('Before request:', request);
// 可以修改请求
request.headers = {
...request.headers,
'X-Custom-Header': 'my-plugin'
};
}
private onAfterResponse(response: any): void {
console.log('After response:', response);
// 可以处理响应
}
}
使用插件
typescript
// src/main.ts
import { XAI_SDK } from 'xai-sdk';
import { MyCustomPlugin } from './plugins/my-custom-plugin';
const sdk = new XAI_SDK();
const plugin = new MyCustomPlugin();
// 注册插件
await sdk.registerPlugin(plugin);
// 初始化 SDK
await sdk.initialize();
// 使用插件提供的方法
const result = await sdk.customMethod('Hello World');
console.log(result); // "Custom processing: Hello World"
📚 详细示例
1. 提供商插件示例
typescript
// src/plugins/custom-ai-provider.ts
import { BasePlugin, XAI_SDK, AIProvider, ChatRequest, ChatResponse } from 'xai-sdk';
export interface CustomAIConfig {
apiKey: string;
baseURL: string;
model?: string;
timeout?: number;
}
export class CustomAIProvider extends BasePlugin implements AIProvider {
name = 'custom-ai-provider';
version = '1.0.0';
description = '自定义 AI 服务提供商';
capabilities = {
providers: ['custom-ai']
};
private apiKey: string = '';
private baseURL: string = '';
private model: string = 'default';
private timeout: number = 30000;
configure(config: CustomAIConfig): void {
super.configure(config);
this.apiKey = config.apiKey;
this.baseURL = config.baseURL;
this.model = config.model || 'default';
this.timeout = config.timeout || 30000;
}
async initialize(sdk: XAI_SDK): Promise<void> {
await super.initialize(sdk);
if (!this.apiKey || !this.baseURL) {
throw new Error('CustomAI provider requires apiKey and baseURL');
}
// 注册为提供商
sdk.registerProvider('custom-ai', this);
}
async chat(request: ChatRequest): Promise<ChatResponse> {
const response = await fetch(`${this.baseURL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
'User-Agent': 'XAI-SDK/1.0.0'
},
body: JSON.stringify({
model: this.model,
messages: request.messages,
max_tokens: request.maxTokens,
temperature: request.temperature,
stream: request.stream
}),
signal: AbortSignal.timeout(this.timeout)
});
if (!response.ok) {
throw new Error(`CustomAI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return {
id: data.id,
content: data.choices[0]?.message?.content || '',
role: 'assistant',
model: data.model,
usage: {
promptTokens: data.usage?.prompt_tokens || 0,
completionTokens: data.usage?.completion_tokens || 0,
totalTokens: data.usage?.total_tokens || 0
},
finishReason: data.choices[0]?.finish_reason || 'stop'
};
}
async stream(request: ChatRequest): Promise<AsyncIterable<ChatResponse>> {
const response = await fetch(`${this.baseURL}/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
'Accept': 'text/event-stream'
},
body: JSON.stringify({
model: this.model,
messages: request.messages,
max_tokens: request.maxTokens,
temperature: request.temperature,
stream: true
})
});
if (!response.ok) {
throw new Error(`CustomAI API error: ${response.status}`);
}
return this.parseStreamResponse(response);
}
private async* parseStreamResponse(response: Response): AsyncIterable<ChatResponse> {
const reader = response.body?.getReader();
if (!reader) throw new Error('No response body');
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
buffer = lines.pop() || '';
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') return;
try {
const parsed = JSON.parse(data);
const delta = parsed.choices[0]?.delta;
if (delta?.content) {
yield {
id: parsed.id,
content: delta.content,
role: 'assistant',
model: parsed.model,
finishReason: parsed.choices[0]?.finish_reason
};
}
} catch (e) {
console.warn('Failed to parse SSE data:', data);
}
}
}
}
} finally {
reader.releaseLock();
}
}
async validateConnection(): Promise<boolean> {
try {
const response = await fetch(`${this.baseURL}/models`, {
headers: {
'Authorization': `Bearer ${this.apiKey}`
}
});
return response.ok;
} catch {
return false;
}
}
}
2. 中间件插件示例
typescript
// src/plugins/logging-middleware.ts
import { BasePlugin, XAI_SDK, MiddlewareContext, MiddlewareNext } from 'xai-sdk';
export interface LoggingConfig {
level: 'debug' | 'info' | 'warn' | 'error';
includeRequestBody?: boolean;
includeResponseBody?: boolean;
maxBodyLength?: number;
}
export class LoggingMiddleware extends BasePlugin {
name = 'logging-middleware';
version = '1.0.0';
description = '请求和响应日志中间件';
capabilities = {
middleware: ['request', 'response']
};
private level: string = 'info';
private includeRequestBody: boolean = false;
private includeResponseBody: boolean = false;
private maxBodyLength: number = 1000;
configure(config: LoggingConfig): void {
super.configure(config);
this.level = config.level;
this.includeRequestBody = config.includeRequestBody ?? false;
this.includeResponseBody = config.includeResponseBody ?? false;
this.maxBodyLength = config.maxBodyLength ?? 1000;
}
async initialize(sdk: XAI_SDK): Promise<void> {
await super.initialize(sdk);
// 注册请求中间件
sdk.use('request', this.requestMiddleware.bind(this));
// 注册响应中间件
sdk.use('response', this.responseMiddleware.bind(this));
}
private async requestMiddleware(context: MiddlewareContext, next: MiddlewareNext): Promise<void> {
const startTime = Date.now();
context.metadata = { ...context.metadata, startTime };
this.log('info', 'Request started', {
method: context.request.method,
url: context.request.url,
headers: this.sanitizeHeaders(context.request.headers),
body: this.includeRequestBody ? this.truncateBody(context.request.body) : undefined
});
try {
await next();
} catch (error) {
this.log('error', 'Request failed', {
error: error instanceof Error ? error.message : String(error),
duration: Date.now() - startTime
});
throw error;
}
}
private async responseMiddleware(context: MiddlewareContext, next: MiddlewareNext): Promise<void> {
await next();
const duration = Date.now() - (context.metadata?.startTime || 0);
this.log('info', 'Response received', {
status: context.response?.status,
headers: this.sanitizeHeaders(context.response?.headers),
body: this.includeResponseBody ? this.truncateBody(context.response?.body) : undefined,
duration: `${duration}ms`
});
}
private sanitizeHeaders(headers: Record<string, string> = {}): Record<string, string> {
const sanitized = { ...headers };
// 隐藏敏感信息
const sensitiveKeys = ['authorization', 'x-api-key', 'cookie'];
for (const key of sensitiveKeys) {
if (sanitized[key.toLowerCase()]) {
sanitized[key.toLowerCase()] = '[REDACTED]';
}
}
return sanitized;
}
private truncateBody(body: any): string {
if (!body) return '';
const str = typeof body === 'string' ? body : JSON.stringify(body);
return str.length > this.maxBodyLength
? str.substring(0, this.maxBodyLength) + '...[truncated]'
: str;
}
private log(level: string, message: string, data?: any): void {
const timestamp = new Date().toISOString();
const logEntry = {
timestamp,
level,
plugin: this.name,
message,
...data
};
switch (level) {
case 'debug':
console.debug('[XAI-SDK]', logEntry);
break;
case 'info':
console.info('[XAI-SDK]', logEntry);
break;
case 'warn':
console.warn('[XAI-SDK]', logEntry);
break;
case 'error':
console.error('[XAI-SDK]', logEntry);
break;
}
}
}
3. 缓存插件示例
typescript
// src/plugins/cache-plugin.ts
import { BasePlugin, XAI_SDK, ChatRequest, ChatResponse } from 'xai-sdk';
export interface CacheConfig {
ttl?: number; // 缓存时间(毫秒)
maxSize?: number; // 最大缓存条目数
storage?: 'memory' | 'localStorage' | 'sessionStorage';
keyGenerator?: (request: ChatRequest) => string;
}
interface CacheEntry {
data: ChatResponse;
timestamp: number;
ttl: number;
}
export class CachePlugin extends BasePlugin {
name = 'cache-plugin';
version = '1.0.0';
description = '响应缓存插件';
capabilities = {
features: ['caching']
};
private ttl: number = 5 * 60 * 1000; // 5分钟
private maxSize: number = 100;
private storage: 'memory' | 'localStorage' | 'sessionStorage' = 'memory';
private keyGenerator: (request: ChatRequest) => string;
private memoryCache = new Map<string, CacheEntry>();
constructor() {
super();
this.keyGenerator = this.defaultKeyGenerator;
}
configure(config: CacheConfig): void {
super.configure(config);
this.ttl = config.ttl ?? this.ttl;
this.maxSize = config.maxSize ?? this.maxSize;
this.storage = config.storage ?? this.storage;
this.keyGenerator = config.keyGenerator ?? this.keyGenerator;
}
async initialize(sdk: XAI_SDK): Promise<void> {
await super.initialize(sdk);
// 拦截 chat 方法
const originalChat = sdk.chat.bind(sdk);
sdk.chat = this.createCachedMethod(originalChat);
// 定期清理过期缓存
setInterval(() => this.cleanupExpiredEntries(), 60000); // 每分钟清理一次
}
private createCachedMethod(originalMethod: (request: ChatRequest) => Promise<ChatResponse>) {
return async (request: ChatRequest): Promise<ChatResponse> => {
// 流式请求不缓存
if (request.stream) {
return originalMethod(request);
}
const cacheKey = this.keyGenerator(request);
// 尝试从缓存获取
const cached = this.getFromCache(cacheKey);
if (cached) {
console.log(`Cache hit for key: ${cacheKey}`);
return { ...cached, fromCache: true };
}
// 缓存未命中,调用原方法
console.log(`Cache miss for key: ${cacheKey}`);
const response = await originalMethod(request);
// 存储到缓存
this.setToCache(cacheKey, response);
return response;
};
}
private defaultKeyGenerator(request: ChatRequest): string {
const key = {
messages: request.messages,
maxTokens: request.maxTokens,
temperature: request.temperature,
model: request.model
};
return this.hashObject(key);
}
private hashObject(obj: any): string {
const str = JSON.stringify(obj, Object.keys(obj).sort());
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash; // 转换为32位整数
}
return hash.toString(36);
}
private getFromCache(key: string): ChatResponse | null {
switch (this.storage) {
case 'memory':
return this.getFromMemoryCache(key);
case 'localStorage':
return this.getFromWebStorage(localStorage, key);
case 'sessionStorage':
return this.getFromWebStorage(sessionStorage, key);
default:
return null;
}
}
private setToCache(key: string, data: ChatResponse): void {
const entry: CacheEntry = {
data,
timestamp: Date.now(),
ttl: this.ttl
};
switch (this.storage) {
case 'memory':
this.setToMemoryCache(key, entry);
break;
case 'localStorage':
this.setToWebStorage(localStorage, key, entry);
break;
case 'sessionStorage':
this.setToWebStorage(sessionStorage, key, entry);
break;
}
}
private getFromMemoryCache(key: string): ChatResponse | null {
const entry = this.memoryCache.get(key);
if (!entry) return null;
if (Date.now() - entry.timestamp > entry.ttl) {
this.memoryCache.delete(key);
return null;
}
return entry.data;
}
private setToMemoryCache(key: string, entry: CacheEntry): void {
// 检查缓存大小限制
if (this.memoryCache.size >= this.maxSize) {
// 删除最旧的条目
const oldestKey = this.memoryCache.keys().next().value;
this.memoryCache.delete(oldestKey);
}
this.memoryCache.set(key, entry);
}
private getFromWebStorage(storage: Storage, key: string): ChatResponse | null {
try {
const item = storage.getItem(`xai-cache-${key}`);
if (!item) return null;
const entry: CacheEntry = JSON.parse(item);
if (Date.now() - entry.timestamp > entry.ttl) {
storage.removeItem(`xai-cache-${key}`);
return null;
}
return entry.data;
} catch {
return null;
}
}
private setToWebStorage(storage: Storage, key: string, entry: CacheEntry): void {
try {
storage.setItem(`xai-cache-${key}`, JSON.stringify(entry));
} catch (error) {
console.warn('Failed to store cache entry:', error);
}
}
private cleanupExpiredEntries(): void {
const now = Date.now();
// 清理内存缓存
for (const [key, entry] of this.memoryCache.entries()) {
if (now - entry.timestamp > entry.ttl) {
this.memoryCache.delete(key);
}
}
// 清理 Web Storage(仅在浏览器环境)
if (typeof window !== 'undefined') {
this.cleanupWebStorage(localStorage);
this.cleanupWebStorage(sessionStorage);
}
}
private cleanupWebStorage(storage: Storage): void {
const keysToRemove: string[] = [];
for (let i = 0; i < storage.length; i++) {
const key = storage.key(i);
if (key?.startsWith('xai-cache-')) {
try {
const item = storage.getItem(key);
if (item) {
const entry: CacheEntry = JSON.parse(item);
if (Date.now() - entry.timestamp > entry.ttl) {
keysToRemove.push(key);
}
}
} catch {
keysToRemove.push(key);
}
}
}
keysToRemove.forEach(key => storage.removeItem(key));
}
// 公共方法:清空缓存
clearCache(): void {
this.memoryCache.clear();
if (typeof window !== 'undefined') {
// 清空 localStorage 中的缓存
const keysToRemove: string[] = [];
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key?.startsWith('xai-cache-')) {
keysToRemove.push(key);
}
}
keysToRemove.forEach(key => localStorage.removeItem(key));
// 清空 sessionStorage 中的缓存
keysToRemove.length = 0;
for (let i = 0; i < sessionStorage.length; i++) {
const key = sessionStorage.key(i);
if (key?.startsWith('xai-cache-')) {
keysToRemove.push(key);
}
}
keysToRemove.forEach(key => sessionStorage.removeItem(key));
}
}
// 公共方法:获取缓存统计
getCacheStats(): { size: number; hitRate: number } {
// 这里可以实现更详细的统计逻辑
return {
size: this.memoryCache.size,
hitRate: 0 // 需要实现命中率统计
};
}
}
🧪 插件测试
单元测试示例
typescript
// src/plugins/__tests__/cache-plugin.test.ts
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { CachePlugin } from '../cache-plugin';
import { XAI_SDK } from 'xai-sdk';
describe('CachePlugin', () => {
let plugin: CachePlugin;
let sdk: XAI_SDK;
let mockChat: ReturnType<typeof vi.fn>;
beforeEach(() => {
plugin = new CachePlugin();
sdk = new XAI_SDK();
mockChat = vi.fn();
sdk.chat = mockChat;
});
afterEach(() => {
plugin.clearCache();
});
it('should cache responses', async () => {
const request = {
messages: [{ role: 'user', content: 'Hello' }],
maxTokens: 100,
temperature: 0.7
};
const response = {
id: 'test-1',
content: 'Hello there!',
role: 'assistant'
};
mockChat.mockResolvedValue(response);
await plugin.initialize(sdk);
// 第一次调用
const result1 = await sdk.chat(request);
expect(result1).toEqual(response);
expect(mockChat).toHaveBeenCalledTimes(1);
// 第二次调用应该从缓存返回
const result2 = await sdk.chat(request);
expect(result2).toEqual({ ...response, fromCache: true });
expect(mockChat).toHaveBeenCalledTimes(1); // 没有再次调用
});
it('should not cache stream requests', async () => {
const request = {
messages: [{ role: 'user', content: 'Hello' }],
stream: true
};
const response = {
id: 'test-1',
content: 'Hello there!',
role: 'assistant'
};
mockChat.mockResolvedValue(response);
await plugin.initialize(sdk);
await sdk.chat(request);
await sdk.chat(request);
expect(mockChat).toHaveBeenCalledTimes(2);
});
it('should expire cached entries', async () => {
plugin.configure({ ttl: 100 }); // 100ms TTL
const request = {
messages: [{ role: 'user', content: 'Hello' }],
maxTokens: 100
};
const response = {
id: 'test-1',
content: 'Hello there!',
role: 'assistant'
};
mockChat.mockResolvedValue(response);
await plugin.initialize(sdk);
// 第一次调用
await sdk.chat(request);
expect(mockChat).toHaveBeenCalledTimes(1);
// 等待缓存过期
await new Promise(resolve => setTimeout(resolve, 150));
// 第二次调用应该重新请求
await sdk.chat(request);
expect(mockChat).toHaveBeenCalledTimes(2);
});
});
集成测试示例
typescript
// src/plugins/__tests__/plugin-integration.test.ts
import { describe, it, expect, beforeEach } from 'vitest';
import { XAI_SDK } from 'xai-sdk';
import { CachePlugin } from '../cache-plugin';
import { LoggingMiddleware } from '../logging-middleware';
import { CustomAIProvider } from '../custom-ai-provider';
describe('Plugin Integration', () => {
let sdk: XAI_SDK;
beforeEach(() => {
sdk = new XAI_SDK();
});
it('should work with multiple plugins', async () => {
const cachePlugin = new CachePlugin();
const loggingPlugin = new LoggingMiddleware();
const providerPlugin = new CustomAIProvider();
// 配置插件
cachePlugin.configure({ ttl: 60000 });
loggingPlugin.configure({ level: 'info' });
providerPlugin.configure({
apiKey: 'test-key',
baseURL: 'https://api.example.com'
});
// 注册插件
await sdk.registerPlugin(cachePlugin);
await sdk.registerPlugin(loggingPlugin);
await sdk.registerPlugin(providerPlugin);
// 初始化 SDK
await sdk.initialize();
// 验证插件已注册
expect(sdk.getRegisteredPlugins()).toHaveLength(3);
expect(sdk.hasPlugin('cache-plugin')).toBe(true);
expect(sdk.hasPlugin('logging-middleware')).toBe(true);
expect(sdk.hasPlugin('custom-ai-provider')).toBe(true);
});
it('should handle plugin dependencies', async () => {
// 创建有依赖关系的插件
class DependentPlugin extends BasePlugin {
name = 'dependent-plugin';
version = '1.0.0';
dependencies = ['cache-plugin'];
async initialize(sdk: XAI_SDK): Promise<void> {
if (!sdk.hasPlugin('cache-plugin')) {
throw new Error('Required plugin cache-plugin not found');
}
await super.initialize(sdk);
}
}
const cachePlugin = new CachePlugin();
const dependentPlugin = new DependentPlugin();
await sdk.registerPlugin(cachePlugin);
await sdk.registerPlugin(dependentPlugin);
await expect(sdk.initialize()).resolves.not.toThrow();
});
});
📖 最佳实践
1. 插件设计原则
typescript
// ✅ 好的插件设计
export class WellDesignedPlugin extends BasePlugin {
name = 'well-designed-plugin';
version = '1.0.0';
// 明确声明能力
capabilities = {
features: ['feature-a', 'feature-b']
};
// 提供配置验证
configure(config: PluginConfig): void {
this.validateConfig(config);
super.configure(config);
}
private validateConfig(config: PluginConfig): void {
if (!config.requiredField) {
throw new Error('requiredField is required');
}
}
// 优雅的错误处理
async initialize(sdk: XAI_SDK): Promise<void> {
try {
await super.initialize(sdk);
await this.setupPlugin();
} catch (error) {
console.error(`Failed to initialize ${this.name}:`, error);
throw error;
}
}
private async setupPlugin(): Promise<void> {
// 插件特定的初始化逻辑
}
// 清理资源
async destroy(): Promise<void> {
await this.cleanup();
await super.destroy();
}
private async cleanup(): Promise<void> {
// 清理插件资源
}
}
2. 错误处理
typescript
export class RobustPlugin extends BasePlugin {
name = 'robust-plugin';
version = '1.0.0';
async initialize(sdk: XAI_SDK): Promise<void> {
try {
await super.initialize(sdk);
// 注册错误处理器
sdk.on('error', this.handleError.bind(this));
} catch (error) {
// 记录错误但不阻止其他插件
console.error(`Plugin ${this.name} initialization failed:`, error);
// 可以选择性地重新抛出错误
if (this.isRequired) {
throw error;
}
}
}
private handleError(error: Error, context?: any): void {
console.error(`Error in ${this.name}:`, error, context);
// 可以实现错误恢复逻辑
this.attemptRecovery(error);
}
private attemptRecovery(error: Error): void {
// 实现错误恢复逻辑
}
}
3. 性能优化
typescript
export class OptimizedPlugin extends BasePlugin {
name = 'optimized-plugin';
version = '1.0.0';
private cache = new Map();
private debounceTimers = new Map();
// 使用防抖优化频繁调用
debounce(key: string, fn: Function, delay: number): void {
const existingTimer = this.debounceTimers.get(key);
if (existingTimer) {
clearTimeout(existingTimer);
}
const timer = setTimeout(() => {
fn();
this.debounceTimers.delete(key);
}, delay);
this.debounceTimers.set(key, timer);
}
// 使用缓存避免重复计算
async expensiveOperation(input: string): Promise<string> {
if (this.cache.has(input)) {
return this.cache.get(input);
}
const result = await this.performExpensiveOperation(input);
this.cache.set(input, result);
return result;
}
private async performExpensiveOperation(input: string): Promise<string> {
// 执行昂贵的操作
return `processed: ${input}`;
}
async destroy(): Promise<void> {
// 清理定时器
for (const timer of this.debounceTimers.values()) {
clearTimeout(timer);
}
this.debounceTimers.clear();
// 清理缓存
this.cache.clear();
await super.destroy();
}
}
📦 插件发布
package.json 配置
json
{
"name": "@my-org/xai-sdk-plugin-example",
"version": "1.0.0",
"description": "Example plugin for XAI-SDK",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist",
"README.md",
"LICENSE"
],
"keywords": [
"xai-sdk",
"plugin",
"ai",
"machine-learning"
],
"peerDependencies": {
"xai-sdk": "^1.0.0"
},
"devDependencies": {
"xai-sdk": "^1.0.0",
"typescript": "^5.0.0",
"vitest": "^1.0.0"
},
"scripts": {
"build": "tsc",
"test": "vitest",
"prepublishOnly": "npm run build && npm test"
}
}
TypeScript 配置
json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"declaration": true,
"outDir": "dist",
"rootDir": "src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
📝 相关资源
💡 提示: 插件开发需要深入理解 XAI-SDK 的架构和生命周期。建议先从简单的功能插件开始,逐步掌握更复杂的提供商和中间件插件开发。