NeovateCode - 完整学习教程

NeovateCode - 完整学习教程

教程级别: 从零到一 预计学习时间: 6-8 小时 前置知识: 基本的命令行操作能力、至少一种编程语言(JavaScript/TypeScript 优先)、了解 LLM API 的基本概念

环境搭建指南

系统要求

  • 操作系统:Windows 10+、macOS 10.15+、主流 Linux 发行版
  • 运行时/依赖版本:Node.js 18+(推荐 LTS 版本)、npm 8+ 或 pnpm 或 yarn
  • 网络:需要互联网连接(用于调用 LLM API)
  • 硬件:8GB+ RAM(推荐 16GB),2GB+ 可用磁盘空间

安装步骤

# 步骤 1:确认 Node.js 版本
node --version
# 应输出 v18.x.x 或更高版本

# 步骤 2:全局安装 NeovateCode
npm install -g @neovate/code

# 也可以使用 pnpm 或 yarn
# pnpm add -g @neovate/code
# yarn global add @neovate/code

验证安装

# 验证安装成功
neovate-code --version

# 查看帮助信息
neovate-code --help

执行结果:

neovate-code v1.x.x
Usage: neovate-code [options]

Options:
  --interactive, -i    启动交互模式
  --prompt <text>      无头模式:直接执行任务
  --model <name>       指定 LLM 模型
  --model-select       交互式选择模型
  --list-models        列出可用模型
  --login              配置 API Key
  --help               显示帮助信息
  --version            显示版本号

首次配置 API Key

# 方式 1:交互式配置(推荐)
neovate-code --login

# 方式 2:通过环境变量配置
export OPENAI_API_KEY='sk-your-openai-key-here'
export ANTHROPIC_API_KEY='sk-ant-your-anthropic-key-here'

# 方式 3:通过配置文件配置
mkdir -p ~/.neovate
cat > ~/.neovate/config.json << 'EOF'
{
  "providers": {
    "openai": {
      "apiKey": "sk-your-openai-key-here",
      "baseURL": "https://api.openai.com/v1"
    }
  },
  "defaultProvider": "openai",
  "defaultModel": "gpt-4-turbo"
}
EOF

第一部分:入门篇

1.1 理解 NeovateCode 的两种运行模式

概念讲解:

NeovateCode 提供两种核心运行模式:交互模式(Interactive Mode)和无头模式(Headless Mode)。

  • 交互模式:在终端中与 AI 进行多轮对话,适合探索性开发和复杂任务。你可以逐步描述需求、追问细节、查看 AI 的执行计划并确认后再应用变更。
  • 无头模式:通过 --prompt 参数一次性传入任务描述,AI 直接执行并返回结果,适合 CI/CD 集成和脚本自动化。

两种模式共享相同的底层智能体引擎,区别仅在于输入输出的交互方式。

代码示例:

# 示例 1:启动交互模式
neovate-code --interactive

# 在交互模式中的对话示例:
# > 帮我创建一个简单的 HTTP 服务器
# AI: 我将为您创建一个基于 Node.js 的 HTTP 服务器...
#    - 创建 server.js
#    是否继续? (y/n)
# > y
# AI: ✓ server.js 已创建
#    服务器监听在 http://localhost:3000

# 示例 2:无头模式执行相同任务
neovate-code --prompt "创建一个简单的 Node.js HTTP 服务器,监听 3000 端口,返回 Hello World"

# 示例 3:查看可用命令
neovate-code --help

执行结果:

# 交互模式输出
NeovateCode Interactive Mode
Model: gpt-4-turbo
Provider: openai
Type your instruction or 'exit' to quit.

> 帮我创建一个简单的 HTTP 服务器

AI: 我将创建一个 Node.js HTTP 服务器:
  1. 创建 server.js - 基础 HTTP 服务器
  是否继续?(y/n): y

  ✓ server.js 已创建
  代码已写入 server.js

# 无头模式输出
Task: 创建一个简单的 Node.js HTTP 服务器,监听 3000 端口,返回 Hello World

✓ Analyzing project context...
✓ Generating execution plan...
✓ Creating server.js...
✓ Task completed successfully

Files created:
  - server.js (42 bytes)

练习题: 1. 使用交互模式创建一个 Python 的 "Hello World" 脚本,观察 AI 的执行步骤 2. 使用无头模式执行同样的任务,对比两种模式的输出差异


1.2 第一个代码生成任务

概念讲解:

代码生成是 NeovateCode 最核心的能力。它不仅能生成单个函数,还能理解项目上下文生成完整的模块。NeovateCode 的工作流程是:解析指令 → 扫描项目上下文 → 调用 LLM 规划 → 生成代码 → 写入文件。

在开始之前,我们先创建一个练习用的项目目录,然后让 NeovateCode 在其中工作。

代码示例:

# 步骤 1:创建练习项目
mkdir -p ~/neovate-practice && cd ~/neovate-practice

# 步骤 2:初始化项目
npm init -y

# 步骤 3:使用无头模式生成一个工具函数模块
neovate-code --prompt "在 src/utils.js 中创建以下工具函数:
1. formatDate(date) - 格式化日期为 YYYY-MM-DD
2. capitalize(str) - 将字符串首字母大写
3. debounce(fn, delay) - 函数防抖
每个函数需要包含 JSDoc 注释"

# 步骤 4:查看生成的文件
cat src/utils.js

执行结果:

# 步骤 3 的输出
Task: 创建工具函数模块

✓ Analyzing project context...
✓ Generating execution plan...
✓ Creating src/utils.js...
✓ Task completed successfully

Files created:
  - src/utils.js (1,204 bytes)

# 步骤 4 的输出(生成的代码示例)
/**
 * 格式化日期为 YYYY-MM-DD 格式
 * @param {Date} date - 要格式化的日期对象
 * @returns {string} 格式化后的日期字符串
 */
function formatDate(date) {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

/**
 * 将字符串首字母大写
 * @param {string} str - 输入字符串
 * @returns {string} 首字母大写的字符串
 */
function capitalize(str) {
  if (!str) return str;
  return str.charAt(0).toUpperCase() + str.slice(1);
}

/**
 * 函数防抖
 * @param {Function} fn - 要防抖的函数
 * @param {number} delay - 延迟毫秒数
 * @returns {Function} 防抖后的函数
 */
function debounce(fn, delay) {
  let timer = null;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

module.exports = { formatDate, capitalize, debounce };

练习题: 1. 使用 NeovateCode 生成一个包含增删改查(CRUD)操作的数组管理模块 2. 尝试让 NeovateCode 为已生成的 utils.js 添加新的工具函数


第二部分:进阶篇

2.1 多 LLM 供应商配置与切换

详细讲解:

NeovateCode 的核心优势之一是支持多 LLM 供应商。通过配置文件,你可以同时配置多个供应商,并在执行任务时灵活切换。这在以下场景特别有用:

  • 成本优化:简单任务使用低成本模型(如 GPT-3.5),复杂任务使用高性能模型(如 GPT-4 或 Claude)
  • 供应商冗余:当某个供应商 API 故障时,快速切换到备用供应商
  • 模型对比:对同一任务使用不同模型,对比生成质量

NeovateCode 支持 20+ 供应商和通过 OpenRouter 接入的 400+ 模型。

代码示例:

# 步骤 1:创建多供应商配置文件
mkdir -p ~/.neovate
cat > ~/.neovate/config.json << 'CONFIGEOF'
{
  "providers": {
    "openai": {
      "apiKey": "sk-your-openai-key",
      "baseURL": "https://api.openai.com/v1"
    },
    "anthropic": {
      "apiKey": "sk-ant-your-anthropic-key",
      "baseURL": "https://api.anthropic.com"
    },
    "openrouter": {
      "apiKey": "sk-or-your-openrouter-key",
      "baseURL": "https://openrouter.ai/api/v1"
    }
  },
  "defaultProvider": "openai",
  "defaultModel": "gpt-4-turbo",
  "performance": {
    "timeout": 30000,
    "maxTokens": 4096,
    "temperature": 0.7
  }
}
CONFIGEOF

# 步骤 2:列出所有可用模型
neovate-code --list-models

# 步骤 3:使用不同模型执行同一任务(对比效果)
# 使用 OpenAI GPT-4
neovate-code --model gpt-4-turbo --prompt "实现一个二叉搜索树,包含插入、查找和删除方法"

# 使用 Anthropic Claude
neovate-code --model claude-sonnet-4-20250514 --prompt "实现一个二叉搜索树,包含插入、查找和删除方法"

# 步骤 4:交互式选择模型
neovate-code --model-select --interactive

执行结果:

# --list-models 输出示例
Available Models:

OpenAI:
  - gpt-4-turbo (default)
  - gpt-4o
  - gpt-3.5-turbo

Anthropic:
  - claude-sonnet-4-20250514
  - claude-haiku-4-5-20251001

OpenRouter (400+ models):
  - google/gemini-pro
  - meta-llama/llama-3-70b
  - deepseek/deepseek-coder
  ...

# --model-select 交互输出
? Select a model:
  ❯ gpt-4-turbo (openai)
    claude-sonnet-4-20250514 (anthropic)
    gpt-3.5-turbo (openai) [cost-saving]
    deepseek/deepseek-coder (openrouter) [cost-saving]

注意事项: - 不同模型的 API 调用费用差异巨大。GPT-4 约为 $0.03/1K tokens,而 GPT-3.5 约为 $0.001/1K tokens。简单任务(如格式化代码、添加注释)不需要使用最贵的模型。 - OpenRouter 的 API Key 需要在 openrouter.ai 单独注册,不支持直接使用 OpenAI 或 Anthropic 的 Key。 - 配置文件中存储了明文 API Key,务必确保 ~/.neovate/config.json 的文件权限为 600(仅所有者可读写):chmod 600 ~/.neovate/config.json - 如果同时配置了多个供应商,确保每个 Key 都是有效的。无效的 Key 不会报错提示,直到实际使用时才会失败。

练习题: 1. 配置至少 2 个 LLM 供应商,并使用 --list-models 查看可用模型列表 2. 对同一编程任务分别使用高成本模型和低成本模型执行,对比生成代码的质量差异


2.2 使用无头模式进行自动化 Bug 修复

详细讲解:

无头模式(Headless Mode)是 NeovateCode 的特色功能,特别适合在自动化工作流中使用。通过 --prompt 参数传入任务描述,NeovateCode 会自动分析代码、定位问题、生成修复并写入文件。

无头模式的核心价值在于可以集成到 CI/CD 管道中,实现自动化的代码质量保障。例如,在代码提交后自动运行 NeovateCode 检查并修复已知的代码问题。

代码示例:

# 步骤 1:创建一个包含 Bug 的示例文件
cat > ~/neovate-practice/src/buggy.js << 'BUGEOF'
// 用户管理模块 - 包含多个 Bug 待修复
function getUsers() {
  // Bug 1: 缺少 async 关键字,但使用了 await
  const response = await fetch('/api/users');
  return response.json();
}

function calculateTotal(items) {
  let total = 0;
  for (let i = 0; i <= items.length; i++) {
    // Bug 2: 数组越界(应该是 i < items.length)
    total += items[i].price * items[i].quantity;
  }
  return total;
}

function validateEmail(email) {
  // Bug 3: 正则表达式缺少锚点
  const regex = /[\w.+-]+@[\w-]+\.[\w.]+/;
  return regex.test(email);
}

module.exports = { getUsers, calculateTotal, validateEmail };
BUGEOF

# 步骤 2:使用无头模式修复 Bug
neovate-code --prompt "检查并修复 src/buggy.js 中的所有 Bug,包括:
1. getUsers 函数缺少 async 关键字
2. calculateTotal 函数的数组越界问题
3. validateEmail 函数的正则表达式缺少锚点
修复后请保留原有注释并添加修复说明"

# 步骤 3:查看修复结果
cat ~/neovate-practice/src/buggy.js

执行结果:

# 步骤 2 的输出
Task: 检查并修复 src/buggy.js 中的 Bug

✓ Reading file: src/buggy.js
✓ Analyzing code for issues...
✓ Found 3 issues to fix
✓ Applying fixes...
✓ Task completed successfully

Changes applied:
  - getUsers(): Added async keyword [Bug 1]
  - calculateTotal(): Fixed loop condition i <= to i < [Bug 2]
  - validateEmail(): Added anchors ^ and $ to regex [Bug 3]

# 步骤 3 修复后的文件示例
// 用户管理模块 - Bug 已修复
// [修复] 添加了 async 关键字以支持 await
async function getUsers() {
  const response = await fetch('/api/users');
  return response.json();
}

function calculateTotal(items) {
  let total = 0;
  // [修复] 修正循环条件,避免数组越界
  for (let i = 0; i < items.length; i++) {
    total += items[i].price * items[i].quantity;
  }
  return total;
}

function validateEmail(email) {
  // [修复] 添加正则锚点 ^ 和 $,确保完整匹配
  const regex = /^[\w.+-]+@[\w-]+\.[\w.]+$/;
  return regex.test(email);
}

module.exports = { getUsers, calculateTotal, validateEmail };

注意事项: - 无头模式会直接修改文件,建议在执行前确保项目已提交到 Git,以便随时回滚。可使用 git add -A && git commit -m "backup before neovate fix" 做快照。 - 对于大型文件,无头模式的 Bug 定位准确度可能下降。建议按函数或模块粒度执行修复任务,而非一次性修复整个文件。 - 无头模式不提供确认步骤,所有修改会直接写入文件。在关键代码上建议先使用交互模式预览变更计划。

练习题: 1. 创建一个包含至少 3 个不同类型 Bug(语法错误、逻辑错误、性能问题)的文件,使用无头模式修复 2. 尝试不指定具体 Bug 描述,仅写 "修复所有 Bug",观察 NeovateCode 能否自动发现并修复问题


第三部分:高级篇

3.1 代码审查与测试生成

详细讲解:

NeovateCode 的代码审查功能可以自动检测代码中的潜在问题,包括安全漏洞、性能瓶颈、编码规范违反和可维护性问题。测试生成功能可以基于现有代码自动创建单元测试。

这两个功能常配合使用:先进行代码审查发现质量问题,再为关键模块生成测试用例以防止回归。

代码示例:

# 步骤 1:创建一个需要审查的代码文件
cat > ~/neovate-practice/src/auth.js << 'AUTHEOF'
// 用户认证模块
const jwt = require('jsonwebtoken');

const SECRET = "hardcoded-secret-key";

function login(username, password) {
  if (username === "admin" && password === "password123") {
    const token = jwt.sign({ user: username }, SECRET);
    return { success: true, token: token };
  }
  return { success: false };
}

function checkAccess(userRole, resource) {
  if (userRole === "admin") {
    return true;
  }
  return false;
}

function hashPassword(password) {
  // 简单的哈希实现
  let hash = 0;
  for (let i = 0; i < password.length; i++) {
    hash = ((hash << 5) - hash) + password.charCodeAt(i);
    hash = hash & hash;
  }
  return hash.toString();
}

module.exports = { login, checkAccess, hashPassword };
AUTHEOF

# 步骤 2:执行代码审查
neovate-code --prompt "对 src/auth.js 进行全面的代码审查,检查以下维度:
1. 安全漏洞(硬编码密钥、弱密码、不安全的哈希)
2. 错误处理(是否处理了异常情况)
3. 代码质量(命名规范、函数职责单一性)
4. 可维护性(是否易于扩展和修改)
请生成详细的审查报告"

# 步骤 3:为模块生成测试
neovate-code --prompt "为 src/auth.js 生成完整的单元测试文件 src/auth.test.js,
使用 Jest 测试框架,覆盖以下场景:
1. login 函数:成功登录、失败登录、空参数
2. checkAccess 函数:管理员访问、普通用户访问、空角色
3. hashPassword 函数:正常密码、空密码、特殊字符密码
目标覆盖率 80%+"

# 步骤 4:查看生成的测试文件
cat ~/neovate-practice/src/auth.test.js

执行结果:

# 步骤 2 审查报告示例

=== Code Review Report: src/auth.js ===

[CRITICAL] Security Issues:
  1. Line 4: Hardcoded secret key "hardcoded-secret-key"
     → Recommendation: Use environment variable process.env.JWT_SECRET
  2. Line 7: Hardcoded admin credentials
     → Recommendation: Use database lookup with hashed passwords
  3. Line 22-28: Insecure hash function (simple character hash)
     → Recommendation: Use bcrypt or argon2 for password hashing

[WARNING] Error Handling:
  4. Line 6-11: No error handling for jwt.sign() failure
     → Recommendation: Wrap in try-catch
  5. Line 6: No input validation for username/password
     → Recommendation: Add type and length checks

[INFO] Code Quality:
  6. Line 14-19: checkAccess is overly simple, no resource-level access control
  7. SECRET variable naming could be more descriptive (JWT_SECRET)

Overall Score: 3/10 (Critical security issues found)

# 步骤 4 生成的测试文件示例
const { login, checkAccess, hashPassword } = require('./auth');

describe('login', () => {
  test('should return success for valid credentials', () => {
    const result = login('admin', 'password123');
    expect(result.success).toBe(true);
    expect(result.token).toBeDefined();
  });

  test('should return failure for invalid credentials', () => {
    const result = login('user', 'wrongpassword');
    expect(result.success).toBe(false);
    expect(result.token).toBeUndefined();
  });

  test('should return failure for empty parameters', () => {
    expect(login('', '').success).toBe(false);
    expect(login(null, null).success).toBe(false);
  });
});

describe('checkAccess', () => {
  test('should grant access to admin', () => {
    expect(checkAccess('admin', 'any-resource')).toBe(true);
  });

  test('should deny access to non-admin', () => {
    expect(checkAccess('user', 'protected-resource')).toBe(false);
  });

  test('should handle empty role', () => {
    expect(checkAccess('', 'resource')).toBe(false);
  });
});

describe('hashPassword', () => {
  test('should return string hash for valid password', () => {
    const hash = hashPassword('mypassword');
    expect(typeof hash).toBe('string');
    expect(hash.length).toBeGreaterThan(0);
  });

  test('should return hash for empty password', () => {
    const hash = hashPassword('');
    expect(typeof hash).toBe('string');
  });

  test('should produce consistent hashes', () => {
    const hash1 = hashPassword('test123');
    const hash2 = hashPassword('test123');
    expect(hash1).toBe(hash2);
  });

  test('should handle special characters', () => {
    const hash = hashPassword('p@ss!w0rd#$%');
    expect(typeof hash).toBe('string');
    expect(hash.length).toBeGreaterThan(0);
  });
});

注意事项: - 代码审查结果的质量高度依赖所选的 LLM 模型。复杂的安全漏洞分析建议使用 GPT-4 或 Claude Sonnet 等高性能模型。 - 自动生成的测试通常能覆盖主要路径,但边界条件可能不完整。建议人工审查并补充边界测试。 - 对于大型项目,批量审查(--review-all --dir src/)可能需要较长时间和较高的 API 调用成本。

3.2 性能优化与成本控制

  • 优化策略 1:按任务复杂度选择模型
# 简单任务(格式化、注释、小修改)使用低成本模型
neovate-code --model gpt-3.5-turbo --prompt "为 src/utils.js 中的函数添加 JSDoc 注释"

# 复杂任务(架构设计、重构、多文件修改)使用高性能模型
neovate-code --model gpt-4-turbo --prompt "将 src/ 目录下的 CommonJS 模块重构为 ES Modules"
  • 优化策略 2:限制上下文范围减少 Token 消耗
# 指定特定文件而非整个项目
neovate-code --prompt "修复 Bug" --file src/specific-module.js

# 排除不需要的目录
# 在 ~/.neovate/config.json 中配置 ignorePatterns

配置文件中添加忽略模式:

{
  "ignorePatterns": [
    "**/node_modules/**",
    "**/dist/**",
    "**/coverage/**",
    "**/*.min.js"
  ]
}

3.3 最佳实践

  1. 始终在 Git 管理下使用:NeovateCode 会直接修改文件,务必在每次使用前确保工作区干净(git status 无未提交更改),或在执行前创建备份提交。
  2. 分步执行复杂任务:将大型重构任务分解为多个小步骤,每步验证后再执行下一步,避免一次性大量修改导致难以回滚。
  3. 审查 AI 生成的代码:AI 生成的代码可能包含逻辑错误或不符合项目规范,始终进行人工审查后再合并。
  4. 保护 API Key 安全:不要将 ~/.neovate/config.json 提交到版本控制,使用 chmod 600 限制文件权限。
  5. 利用项目级配置:在项目的 package.json 中添加 NeovateCode 配置,确保团队成员使用一致的模型和参数设置。
// package.json 中的项目级配置示例
{
  "name": "my-project",
  "neovate": {
    "enabled": true,
    "defaultModel": "gpt-4-turbo",
    "testCoverage": 80,
    "codeStandards": "strict",
    "ignorePatterns": [
      "**/node_modules/**",
      "**/dist/**"
    ]
  }
}

第四部分:实战项目

项目需求

构建一个「迷你代码质量检查器(Mini Code Quality Checker)」—— 一个 Node.js 命令行工具,能够扫描指定目录下的 JavaScript 文件,使用 NeovateCode 的无头模式对每个文件进行代码审查,汇总生成质量报告。

功能需求: 1. 递归扫描指定目录下的 .js 文件 2. 对每个文件调用 NeovateCode 进行代码审查 3. 收集审查结果并按严重程度分类(Critical/Warning/Info) 4. 生成汇总报告,包含文件级和项目级的质量评分 5. 支持输出 JSON 和文本两种格式的报告

项目设计

  • 技术选型: Node.js + 文件系统模块(fs/path)+ 子进程调用(child_process)
  • 架构设计: 扫描器(Scanner)→ 审查器(Reviewer)→ 报告器(Reporter)三阶段管道
  • 知识点覆盖: 无头模式自动化、多文件批处理、结果解析、配置管理

完整实现代码

// mini-quality-checker.js
// 迷你代码质量检查器 - 使用 NeovateCode 无头模式自动化代码审查

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

// ==================== 配置 ====================
const CONFIG = {
  // 扫描配置
  scanDir: process.argv[2] || '.',           // 要扫描的目录
  filePattern: /\.js$/,                       // 文件匹配模式
  ignoreDirs: ['node_modules', 'dist', 'coverage', '.git'],  // 忽略的目录

  // NeovateCode 配置
  model: process.argv[3] || 'gpt-3.5-turbo', // 使用的模型(简单任务用低成本模型)
  reviewPrompt: '对以下代码进行代码审查,只检查安全漏洞和明显 Bug。' +
    '输出格式:每行一个发现,格式为 [级别] 位置: 描述。' +
    '级别分为 CRITICAL/WARNING/INFO。如果没有问题,输出 PASS。',

  // 输出配置
  outputFile: process.argv[4] || null,         // 输出文件路径(可选)
};

// ==================== 扫描器:递归查找 JS 文件 ====================
function scanFiles(dir) {
  const results = [];
  const entries = fs.readdirSync(dir, { withFileTypes: true });

  for (const entry of entries) {
    const fullPath = path.join(dir, entry.name);

    // 跳过忽略的目录
    if (entry.isDirectory()) {
      if (!CONFIG.ignoreDirs.includes(entry.name)) {
        results.push(...scanFiles(fullPath));
      }
      continue;
    }

    // 匹配文件模式
    if (entry.isFile() && CONFIG.filePattern.test(entry.name)) {
      results.push(fullPath);
    }
  }

  return results;
}

// ==================== 审查器:调用 NeovateCode 审查单个文件 ====================
function reviewFile(filePath) {
  try {
    // 构造 NeovateCode 无头模式命令
    const escapedPrompt = CONFIG.reviewPrompt.replace(/"/g, '\\"');
    const command = `neovate-code --model ${CONFIG.model} --prompt "${escapedPrompt}" --file "${filePath}"`;

    // 执行命令并捕获输出
    const output = execSync(command, {
      encoding: 'utf-8',
      timeout: 60000,        // 超时 60 秒
      maxBuffer: 1024 * 1024  // 最大输出 1MB
    });

    return {
      file: filePath,
      status: 'success',
      findings: parseFindings(output),
      rawOutput: output
    };
  } catch (error) {
    return {
      file: filePath,
      status: 'error',
      findings: [],
      error: error.message
    };
  }
}

// ==================== 解析审查结果 ====================
function parseFindings(output) {
  const findings = [];
  const lines = output.split('\n');

  for (const line of lines) {
    const trimmed = line.trim();
    if (!trimmed) continue;

    // 解析格式:[CRITICAL] src/file.js:10: 描述
    const match = trimmed.match(/\[(CRITICAL|WARNING|INFO)\]\s*(.+?):\s*(.+)/);
    if (match) {
      findings.push({
        level: match[1],
        location: match[2],
        description: match[3]
      });
    } else if (trimmed === 'PASS') {
      // 文件通过审查,无问题
      return [];
    }
  }

  return findings;
}

// ==================== 报告器:生成汇总报告 ====================
function generateReport(results) {
  // 统计数据
  const totalFiles = results.length;
  const successFiles = results.filter(r => r.status === 'success').length;
  const errorFiles = results.filter(r => r.status === 'error').length;

  const allFindings = results.flatMap(r => r.findings);
  const criticalCount = allFindings.filter(f => f.level === 'CRITICAL').length;
  const warningCount = allFindings.filter(f => f.level === 'WARNING').length;
  const infoCount = allFindings.filter(f => f.level === 'INFO').length;

  // 计算质量评分(满分 100,每个 CRITICAL -10,WARNING -3,INFO -1)
  const deduction = criticalCount * 10 + warningCount * 3 + infoCount * 1;
  const score = Math.max(0, 100 - deduction);

  // 构建报告
  const report = {
    summary: {
      totalFiles,
      successFiles,
      errorFiles,
      score,
      findings: {
        critical: criticalCount,
        warning: warningCount,
        info: infoCount,
        total: allFindings.length
      }
    },
    details: results.map(r => ({
      file: r.file,
      status: r.status,
      findings: r.findings,
      error: r.error || null
    }))
  };

  return report;
}

// ==================== 格式化输出 ====================
function formatTextReport(report) {
  const lines = [];
  const s = report.summary;

  lines.push('========================================');
  lines.push('   Mini Code Quality Checker Report');
  lines.push('========================================');
  lines.push('');
  lines.push(`扫描文件数: ${s.totalFiles}`);
  lines.push(`成功审查:   ${s.successFiles}`);
  lines.push(`审查失败:   ${s.errorFiles}`);
  lines.push('');
  lines.push(`质量评分:   ${s.score}/100`);
  lines.push(`  CRITICAL: ${s.findings.critical} (每个 -10 分)`);
  lines.push(`  WARNING:  ${s.findings.warning} (每个 -3 分)`);
  lines.push(`  INFO:     ${s.findings.info} (每个 -1 分)`);
  lines.push('');
  lines.push('----------------------------------------');
  lines.push('详细发现:');
  lines.push('----------------------------------------');

  for (const detail of report.details) {
    lines.push('');
    lines.push(`文件: ${detail.file} [${detail.status}]`);

    if (detail.status === 'error') {
      lines.push(`  错误: ${detail.error}`);
      continue;
    }

    if (detail.findings.length === 0) {
      lines.push('  ✓ 无问题');
    } else {
      for (const f of detail.findings) {
        lines.push(`  [${f.level}] ${f.location}: ${f.description}`);
      }
    }
  }

  lines.push('');
  lines.push('========================================');
  return lines.join('\n');
}

// ==================== 主流程 ====================
function main() {
  console.log('Mini Code Quality Checker');
  console.log(`扫描目录: ${CONFIG.scanDir}`);
  console.log(`使用模型: ${CONFIG.model}`);
  console.log('');

  // 步骤 1:扫描文件
  console.log('[1/3] 扫描文件...');
  const files = scanFiles(path.resolve(CONFIG.scanDir));
  console.log(`找到 ${files.length} 个 JavaScript 文件`);

  if (files.length === 0) {
    console.log('未找到可审查的文件。');
    return;
  }

  // 步骤 2:审查每个文件
  console.log('[2/3] 审查文件(这可能需要一些时间)...');
  const results = [];
  for (let i = 0; i < files.length; i++) {
    const file = files[i];
    console.log(`  [${i + 1}/${files.length}] 审查: ${path.basename(file)}`);
    const result = reviewFile(file);
    results.push(result);
  }

  // 步骤 3:生成报告
  console.log('[3/3] 生成报告...');
  const report = generateReport(results);

  // 输出文本报告
  const textReport = formatTextReport(report);
  console.log('');
  console.log(textReport);

  // 可选:输出 JSON 报告到文件
  if (CONFIG.outputFile) {
    fs.writeFileSync(CONFIG.outputFile, JSON.stringify(report, null, 2), 'utf-8');
    console.log(`JSON 报告已保存到: ${CONFIG.outputFile}`);
  }
}

// 运行
main();

执行结果:

Mini Code Quality Checker
扫描目录: /home/user/neovate-practice
使用模型: gpt-3.5-turbo

[1/3] 扫描文件...
找到 4 个 JavaScript 文件
[2/3] 审查文件(这可能需要一些时间)...
  [1/4] 审查: server.js
  [2/4] 审查: utils.js
  [3/4] 审查: buggy.js
  [4/4] 审查: auth.js
[3/3] 生成报告...

========================================
   Mini Code Quality Checker Report
========================================

扫描文件数: 4
成功审查:   4
审查失败:   0

质量评分:   67/100
  CRITICAL: 2 (每个 -10 分)
  WARNING:  4 (每个 -3 分)
  INFO:     5 (每个 -1 分)

----------------------------------------
详细发现:
----------------------------------------

文件: /home/user/neovate-practice/src/auth.js [success]
  [CRITICAL] Line 4: 硬编码的密钥 "hardcoded-secret-key"
  [CRITICAL] Line 22-28: 不安全的自定义哈希函数
  [WARNING] Line 7: 硬编码的管理员凭据
  [WARNING] Line 6: 缺少输入验证

文件: /home/user/neovate-practice/src/buggy.js [success]
  [WARNING] Line 3: 函数声明缺少 async 但使用了 await
  [WARNING] Line 9: 循环条件可能导致数组越界
  [INFO] Line 16: 正则表达式缺少锚点

文件: /home/user/neovate-practice/src/utils.js [success]
  [INFO] 建议添加输入参数的类型检查
  ✓ 无严重问题

文件: /home/user/neovate-practice/src/server.js [success]
  [INFO] 建议添加错误处理中间件
  [INFO] 建议使用环境变量配置端口号

========================================

代码解析

本项目综合运用了教程中的以下知识点:

  1. 无头模式自动化(知识点 1.1 + 2.2):通过 execSync 调用 neovate-code --prompt 命令,实现无需人工干预的自动化代码审查。对应代码在 reviewFile() 函数中,构造命令行调用并捕获输出。

  2. 多 LLM 配置(知识点 2.1):通过命令行参数和配置对象支持模型选择,简单任务默认使用低成本模型(gpt-3.5-turbo),用户可通过参数切换到高性能模型。对应代码在 CONFIG 对象的 model 字段。

  3. 代码审查(知识点 3.1):使用 NeovateCode 的审查功能,对扫描到的每个文件执行自动化审查,并解析结构化的审查结果。对应代码在 reviewFile()parseFindings() 函数中。

  4. 性能优化(知识点 3.2):通过 ignoreDirs 排除 node_modules 等不需要审查的目录,减少扫描范围和 API 调用次数;通过可配置的模型选择实现成本控制。对应代码在 CONFIG.ignoreDirsscanFiles() 函数中。

扩展挑战

  1. 添加并行审查功能:使用 Node.js 的 child_process.exec(异步版本)和 Promise.all 并行审查多个文件,提升扫描速度
  2. 添加增量审查模式:只审查 Git 暂存区中已修改的文件(通过 git diff --name-only 获取文件列表),适合集成到 pre-commit 钩子中
  3. 添加报告对比功能:保存历史报告并与当前报告对比,追踪代码质量趋势

第五部分:常见问题与排查指南

常见错误及解决方案

错误信息 原因 解决方案
command not found: neovate-code 未全局安装或 PATH 未配置 运行 npm install -g @neovate/code,或使用 npx @neovate/code 代替
Error: API key not configured 未设置 LLM API Key 运行 neovate-code --login 或设置环境变量 export OPENAI_API_KEY=sk-...
Error: 401 Unauthorized API Key 无效或已过期 检查 API Key 是否正确,是否在对应平台的有效期内
Error: 429 Too Many Requests API 调用频率超过限制 降低请求频率,或升级 API 付费计划。可在配置中增加 timeout
Error: Model not found 指定的模型名称不正确 运行 neovate-code --list-models 查看可用模型列表,确认模型名称拼写
TimeoutError: Request timed out LLM API 响应超时 增加配置中的 timeout 值(默认 30000ms),或检查网络连接
Error: Cannot read file 指定的文件路径不存在 检查文件路径是否正确,使用绝对路径或相对于当前目录的路径
SyntaxError in generated code AI 生成的代码包含语法错误 使用交互模式逐步生成并验证,或切换到更高质量的模型
Error: Config file parse error 配置文件 JSON 格式错误 使用 node -e "console.log(JSON.parse(require('fs').readFileSync('~/.neovate/config.json')))" 验证 JSON 格式
Permission denied: ~/.neovate/config.json 配置文件权限问题 运行 chmod 600 ~/.neovate/config.json 修正权限

调试技巧

  1. 使用 --verbose 模式查看详细日志:在命令后添加 --verbose--debug 标志,可以看到完整的 API 请求和响应内容,帮助定位问题。例如:neovate-code --verbose --prompt "测试"

  2. 检查配置文件有效性:使用 Node.js 直接解析配置文件,确认 JSON 格式正确且字段完整:

node -e "const c = require('/path/to/config.json'); console.log('Providers:', Object.keys(c.providers)); console.log('Default:', c.defaultModel)"
  1. 隔离测试:当 NeovateCode 行为异常时,先用最简单的任务测试基本功能是否正常:
# 测试基本连接
neovate-code --prompt "输出 Hello World" --model gpt-3.5-turbo

# 测试不同模型
neovate-code --prompt "输出 Hello World" --model claude-sonnet-4-20250514

# 如果上述都失败,检查网络和 API Key
curl https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY"

第六部分:学习路线推荐

官方文档推荐阅读顺序

  1. GitHub README - 快速入门指南、安装步骤、基本命令 — 重点:理解两种运行模式和基本命令
  2. 配置文档 - 多供应商配置、模型选择、项目级配置 — 重点:掌握 config.json 的结构和配置方法
  3. 高级用法 - MCP 集成、自定义智能体、批量处理 — 重点:理解扩展机制和自动化能力

推荐进阶资源

  • Aider 官方文档(https://aider.chat/docs/) — Aider 是 NeovateCode 最接近的开源竞品,学习 Aider 的设计理念有助于理解 AI 代码智能体的通用模式
  • Model Context Protocol 规范(https://modelcontextprotocol.io/) — MCP 是 NeovateCode 支持的扩展协议,理解 MCP 有助于利用 NeovateCode 的扩展能力
  • 《AI 辅助编程实战》 — 系统学习 AI 编码工具的使用方法和最佳实践,涵盖多种工具的对比和实际应用场景

信息来源