Qwen Code 开发指南

Qwen Code 开发指南

开发环境设置

系统要求

  1. Node.js 20+:项目需要 Node.js 20 或更高版本
  2. npm 8+:推荐使用 npm 8 或更高版本
  3. Git:用于版本控制

克隆项目

git clone git@github.com:axfinn/qwen-code.git
cd qwen-code

安装依赖

npm install

这将安装所有必要的依赖项,包括开发依赖。

项目结构回顾

Qwen Code 采用 monorepo 结构,使用 npm workspaces 管理多个包:

qwen-code/
├── packages/
│   ├── cli/          # CLI 工具
│   ├── core/         # 核心功能
│   └── ...           # 其他包
├── docs/             # 文档
├── examples/         # 示例
├── tests/            # 测试
└── ...

开发工作流

构建项目

# 构建所有包
npm run build

# 构建特定包
npm run build --workspace=@qwen-code/cli

运行测试

# 运行所有测试
npm test

# 运行单元测试
npm run test:unit

# 运行集成测试
npm run test:integration

代码检查

# 运行 ESLint
npm run lint

# 运行 TypeScript 类型检查
npm run typecheck

# 格式化代码
npm run format

完整预检

在提交代码前,运行完整的预检流程:

npm run preflight

这将依次执行构建、测试、代码检查和类型检查。

核心开发概念

TypeScript 最佳实践

Qwen Code 严格遵循 TypeScript 最佳实践:

  1. 类型安全:为所有函数和变量提供明确的类型声明
  2. 接口优于类:使用 TypeScript 接口定义对象结构
  3. 避免 any 类型:使用 unknown 或具体类型替代 any
  4. 函数式编程:优先使用数组方法如 map、filter、reduce

示例:

// 好的做法
interface User {
  id: string;
  name: string;
  email: string;
}

function getUserById(id: string): User | undefined {
  // 实现
}

// 避免的做法
function getUserById(id: any): any {
  // 实现
}

React 开发规范

CLI 部分使用 React 和 Ink 构建:

  1. 函数组件:使用函数组件和 hooks
  2. 纯渲染:保持组件渲染函数纯净
  3. 单向数据流:尊重 React 的单向数据流
  4. 避免直接状态突变:使用 setState 或 useState 更新状态
  5. 谨慎使用 effects:只在必要时使用 useEffect

示例:

import React, { useState, useEffect } from 'react';

const MyComponent: React.FC = () => {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    // 副作用处理
  }, [count]);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
};

代码组织原则

  1. 模块化:将功能拆分为小的、可重用的模块
  2. 封装:使用 ES 模块语法进行封装
  3. 避免全局状态:尽量减少全局变量的使用
  4. 清晰的命名:使用描述性的变量和函数名

工具开发指南

创建新工具

要创建一个新工具,需要实现以下接口:

interface Tool {
  name: string;
  description: string;
  parameters: {
    [key: string]: {
      type: string;
      description: string;
      required: boolean;
    };
  };
  execute: (params: any) => Promise<any>;
}

示例工具实现:

const exampleTool: Tool = {
  name: "example_tool",
  description: "这是一个示例工具",
  parameters: {
    message: {
      type: "string",
      description: "要显示的消息",
      required: true
    }
  },
  execute: async (params) => {
    return {
      result: `消息: ${params.message}`
    };
  }
};

工具注册

工具需要在核心包中注册:

// packages/core/src/tools/index.ts
import { exampleTool } from './exampleTool';

export const tools = [
  exampleTool,
  // 其他工具
];

测试策略详解

单元测试

使用 Vitest 编写单元测试,测试文件与源文件并置:

// geminiRequest.test.ts
import { describe, it, expect } from 'vitest';
import { geminiRequest } from './geminiRequest';

describe('geminiRequest', () => {
  it('应该发送正确的请求', async () => {
    // 测试实现
  });
});

集成测试

集成测试验证工具链的完整功能:

// integration-tests/readFile.test.js
import { test } from 'vitest';
import { readFile } from '../packages/core/src/tools/readFile';

test('readFile 应该正确读取文件内容', async () => {
  // 测试实现
});

测试最佳实践

  1. 测试覆盖率:确保关键功能有充分的测试覆盖
  2. 边界条件:测试边界条件和错误情况
  3. 模拟外部依赖:使用 mocking 隔离外部依赖
  4. 测试数据:使用专门的测试数据目录

调试技巧

日志记录

使用适当的日志级别记录信息:

import debug from 'debug';

const log = debug('qwen-code:tool');

log('执行工具: %s', toolName);

调试模式

通过环境变量启用调试模式:

DEBUG=qwen-code:* npm run dev

断点调试

在 VS Code 中配置调试配置:

{
  "name": "Debug Qwen Code",
  "type": "node",
  "request": "launch",
  "program": "${workspaceFolder}/packages/cli/index.ts",
  "env": {
    "DEBUG": "qwen-code:*"
  }
}

贡献指南

分支策略

  1. 主分支main 分支是稳定版本
  2. 功能分支:为每个新功能创建独立分支
  3. 修复分支:为 bug 修复创建独立分支

提交信息规范

遵循 conventional commits 规范:

feat: 添加新工具
fix: 修复文件读取错误
docs: 更新 README 文档
test: 添加单元测试
refactor: 重构核心模块

Pull Request 流程

  1. Fork 项目仓库
  2. 创建功能分支
  3. 实现功能并添加测试
  4. 运行预检确保代码质量
  5. 提交更改并推送
  6. 创建 Pull Request

代码审查

所有 Pull Request 都需要通过代码审查:

  1. 至少一名维护者审查
  2. 所有 CI 检查通过
  3. 测试覆盖率满足要求

性能优化

内存管理

  1. 及时释放资源:使用完资源后及时释放
  2. 避免内存泄漏:注意事件监听器和定时器的清理
  3. 合理使用缓存:对计算结果进行适当缓存

执行效率

  1. 异步操作:使用异步操作避免阻塞
  2. 批处理:合并多个小操作为批处理
  3. 懒加载:按需加载模块和资源

安全考虑

输入验证

对所有外部输入进行验证:

function validatePath(path: string): boolean {
  // 验证路径是否合法
  return !path.includes('..') && path.startsWith('/');
}

权限控制

  1. 最小权限原则:只授予必要的权限
  2. 沙箱隔离:在安全环境中执行潜在危险操作
  3. 审计日志:记录敏感操作

文档编写

API 文档

使用 JSDoc 注释记录 API:

/**
 * 读取文件内容
 * @param absolutePath 文件的绝对路径
 * @param limit 可选,要读取的最大行数
 * @param offset 可选,开始读取的行偏移量
 * @returns 文件内容
 */
function readFile(absolutePath: string, limit?: number, offset?: number): Promise<string> {
  // 实现
}

使用示例

为复杂功能提供使用示例:

// 示例:使用 glob 工具查找文件
const result = await glob({
  pattern: "**/*.ts",
  path: "/path/to/project"
});

发布流程

版本管理

遵循语义化版本控制:

  1. 主版本号:不兼容的API修改
  2. 次版本号:向后兼容的功能性新增
  3. 修订号:向后兼容的问题修正

发布步骤

  1. 更新版本号:

    npm version patch  # 修订版本
    npm version minor  # 次版本
    npm version major  # 主版本
    
  2. 构建项目:

    npm run build
    
  3. 运行完整测试:

    npm run preflight
    
  4. 发布到 npm:

    npm publish
    

总结

Qwen Code 的开发指南为贡献者提供了清晰的指导,涵盖了从环境设置到发布流程的各个方面。通过遵循这些指南,开发者可以高效地为项目贡献代码,同时确保代码质量和项目稳定性。

Qwen Code 不仅是一个强大的工具,也是一个开放的平台,欢迎社区的贡献和改进。希望这份开发指南能帮助您更好地理解和参与 Qwen Code 项目。