构建插件
开发 Codex 插件完整指南
概述
本指南介绍如何从零开始开发、测试和发布一个 Codex 插件。
环境准备
安装依赖
bash
# Node.js 18+
node --version
# 安装 Codex CLI
npm install -g @openai/codex
# 安装开发工具
npm install -g typescript ts-node创建项目
bash
# 使用模板
npx create-codex-plugin my-plugin
# 或手动创建
mkdir my-plugin
cd my-plugin
npm init -y项目配置
package.json
json
{
"name": "my-plugin",
"version": "1.0.0",
"description": "我的 Codex 插件",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"test": "vitest"
},
"dependencies": {
"@openai/codex": "^2.0.0"
},
"devDependencies": {
"typescript": "^5.0.0",
"vitest": "^1.0.0"
}
}tsconfig.json
json
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"declaration": true,
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}plugin.json
json
{
"name": "my-plugin",
"displayName": "我的插件",
"version": "1.0.0",
"description": "插件描述",
"author": "Your Name",
"license": "MIT",
"homepage": "https://github.com/user/my-plugin",
"repository": "github:user/my-plugin",
"engines": {
"codex": ">=2.0.0"
},
"main": "dist/index.js"
}开发插件
基础结构
typescript
// src/index.ts
import { Plugin, Tool, Command, Context } from '@openai/codex';
export default class MyPlugin extends Plugin {
private context?: Context;
async activate(context: Context): Promise<void> {
this.context = context;
context.logger.info('插件已激活');
// 注册工具
this.registerTools();
// 注册命令
this.registerCommands();
}
async deactivate(): Promise<void> {
this.context?.logger.info('插件已停用');
}
private registerTools(): void {
const tool: Tool = {
name: 'my-tool',
description: '我的工具',
parameters: {
type: 'object',
properties: {
input: {
type: 'string',
description: '输入内容'
}
},
required: ['input']
},
execute: async (params: any) => {
return this.processInput(params.input);
}
};
this.context?.registerTool(tool);
}
private registerCommands(): void {
const command: Command = {
name: 'my-command',
description: '我的命令',
run: async (args: string[]) => {
this.context?.logger.info(`执行命令:${args.join(' ')}`);
}
};
this.context?.registerCommand(command);
}
private async processInput(input: string): Promise<any> {
// 处理逻辑
return { result: `处理了:${input}` };
}
}工具开发
typescript
// src/tools/file-reader.ts
import { Tool } from '@openai/codex';
export const fileReaderTool: Tool = {
name: 'read-file',
description: '读取文件内容',
parameters: {
type: 'object',
properties: {
path: {
type: 'string',
description: '文件路径'
}
},
required: ['path']
},
execute: async (params) => {
const fs = require('fs');
const content = fs.readFileSync(params.path, 'utf-8');
return { content };
}
};命令开发
typescript
// src/commands/lint.ts
import { Command } from '@openai/codex';
export const lintCommand: Command = {
name: 'lint',
description: '运行代码检查',
run: async (args: string[]) => {
const { execSync } = require('child_process');
try {
const output = execSync('npm run lint', { encoding: 'utf-8' });
console.log(output);
return { success: true };
} catch (error) {
console.error(error);
return { success: false, error: error.message };
}
}
};测试插件
单元测试
typescript
// tests/plugin.test.ts
import { describe, it, expect } from 'vitest';
import MyPlugin from '../src/index';
describe('MyPlugin', () => {
it('should activate', async () => {
const plugin = new MyPlugin();
const mockContext = {
logger: { info: () => {}, error: () => {} },
registerTool: () => {},
registerCommand: () => {}
};
await expect(plugin.activate(mockContext)).resolves.not.toThrow();
});
});集成测试
typescript
// tests/integration.test.ts
import { testPlugin } from '@openai/codex/test';
import MyPlugin from '../src/index';
testPlugin(MyPlugin, {
name: 'my-plugin',
tests: [
{
name: 'tool execution',
tool: 'my-tool',
input: { input: 'test' },
expected: { result: '处理了:test' }
}
]
});调试插件
本地调试
bash
# 链接插件
codex plugin link ./my-plugin
# 开发模式
npm run dev
# 在另一个终端运行 Codex
codex日志调试
typescript
this.context?.logger.debug('调试信息:', data);
this.context?.logger.info('信息:', message);
this.context?.logger.warn('警告:', warning);
this.context?.logger.error('错误:', error);打包发布
构建
bash
npm run build检查
bash
# 检查 package.json
npm pkg get
# 检查文件
npm pack --dry-run发布
bash
# 发布到 npm
npm publish
# 发布到 Codex 市场
codex plugin publish版本管理
语义化版本
MAJOR.MINOR.PATCH
- MAJOR: 不兼容更新
- MINOR: 功能更新
- PATCH: Bug 修复更新版本
bash
npm version patch # 1.0.0 -> 1.0.1
npm version minor # 1.0.1 -> 1.1.0
npm version major # 1.1.0 -> 2.0.0文档编写
README.md
markdown
# My Plugin
插件描述
## 安装
```bash
codex plugin install my-plugin使用
工具
my-tool- 工具描述
命令
my-command- 命令描述
配置
json
{
"my-plugin": {
"option": "value"
}
}许可证
MIT
## 最佳实践
### 1. 代码质量- 使用 TypeScript
- 启用严格模式
- 编写测试
- 代码审查
### 2. 错误处理
```typescript
try {
// 可能出错的代码
} catch (error) {
logger.error('操作失败:', error);
throw error;
}3. 性能优化
- 延迟加载
- 结果缓存
- 避免阻塞