nkds

导航

 

MonkeyCode开源完全指南:从源码到部署的深度解析(2026版)

"当一家安全大厂决定把核心AI编程产品开源——这不仅仅是一次技术开放,更是对整个企业级AI开发领域的一次降维打击" —— 本文将全面剖析MonkeyCode的开源架构、技术实现细节,以及如何从源码开始构建属于你自己的企业级AI编程平台。


一、为什么MonkeyCode选择开源?

🔍 开源背景:长亭科技的战略决策

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

公司背景:
┌─────────────────────────────────────┐
│ 公司名称:长亭科技(Chaitin)        │
│ 成立时间:2014年                     │
│ 核心能力:网络安全/攻防研究/AI安全   │
│ 行业地位:国内顶尖网络安全厂商       │
│ 代表产品:雷池WAF/牧云主机安全       │
│ 新品:MonkeyCode AI编程平台          │
└─────────────────────────────────────┘

为什么选择AGPL-3.0开源?

原因1:技术自信
→ "我们的核心壁垒不是代码,是安全领域的
   深度积累和持续迭代能力"
→ 开源代码 ≠ 开源核心竞争力

原因2:生态建设
→ 希望更多开发者参与共建
→ 形成社区驱动的创新飞轮
→ 类似于Linux基金会的成功模式

原因3:信任建立
→ 企业客户需要可审计的代码
→ 开源 = 透明 = 信任
→ 对金融/政府/军工客户尤其重要

原因4:市场教育
→ 降低企业使用门槛
→ 让更多人体验SDD+MonkeyScan的价值
→ 用免费开源版引流,增值服务变现

💡 关键洞察:MonkeyCode的开源不是"无奈之举"
   而是"战略选择"——用开源换市场、换信任、换生态

二、开源协议:AGPL-3.0详解

📜 AGPL-3.0(GNU Affero General Public License v3)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

什么是AGPL-3.0?
┌──────────────────────────────────────────┐
│ AGPL-3.0 是GPL v3的增强版本              │
│                                          │
│ 核心特点:                                │
│ ✅ 自由使用:个人/商业均可免费使用        │
│ ✅ 自由修改:可以修改源代码               │
│ ✅ 自由分发:可以重新发布                 │
│ ✅ 网络使用条款:通过网络提供服务时       │
│    也必须开源修改后的代码                │
│                                          │
│ 与GPL v3的区别:                          │
│ GPL: 仅在分发二进制时需开源              │
│ AGPL: 即使不分发(如SaaS服务)也需开源   │
└──────────────────────────────────────────┘

对企业用户意味着什么?

✅ 可以做的事:
├── 免费使用MonkeyCode的全部功能
├── 在内网私有化部署(无需联网)
├── 修改源代码适配内部系统
├── 集成到现有的DevOps流水线
├── 基于MonkeyCode开发内部工具
└── 在团队内部自由分发

⚠️ 需要注意的限制:
├── 如果修改了源代码并对外提供SaaS服务
│   → 必须公开你的修改部分
├── 不能移除AGPL-3.0的版权声明和许可证
├── 派生作品必须继续使用AGPL-3.0协议
└── 不能将代码闭源后以专有软件形式销售

❌ 常见误解澄清:
✗ "用了AGPL代码,我的商业项目也必须开源"
  → 错误!只有你对MonkeyCode本身的修改才需要开源
  → 你自己的业务代码不受影响

✗ "AGPL不能用于商业用途"
  → 错误!AGPL明确允许商业使用
  → MongoDB、MongoDB Enterprise等都是AGPL

💡 实际建议:
对于大多数企业用户来说,
AGPL-3.0的限制几乎不影响正常使用。
只要你不是要把MonkeyCode改个名字当自己的产品卖,
就可以放心大胆地用。

三、MonkeyCode开源架构全景

🏗️ 技术架构图

┌─────────────────────────────────────────────────────┐
│                  MonkeyCode 架构                    │
│                                                     │
│  ┌───────────────────────────────────────────────┐  │
│  │           前端层 (Frontend)                    │  │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐         │  │
│  │  │ Web UI  │ │ VS Code  │ │ CLI     │         │  │
│  │  │ (React) │ │ Plugin  │ │(Terminal)│         │  │
│  │  └─────────┘ └─────────┘ └─────────┘         │  │
│  └──────────────────┬────────────────────────────┘  │
│                     │ HTTP / WebSocket             │
│  ┌──────────────────▼────────────────────────────┐  │
│  │           API网关层 (Gateway)                   │  │
│  │  认证授权 | 限流熔断 | 路由转发 | 日志审计      │  │
│  └──────────────────┬────────────────────────────┘  │
│                     │                              │
│  ┌──────────────────▼────────────────────────────┐  │
│  │           核心引擎层 (Core Engine)              │  │
│  │                                              │  │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐      │  │
│  │  │ SDD引擎  │ │ Agent引擎│ │ 安全引擎  │      │  │
│  │  │(规范驱动)│ │(任务编排)│ │(扫描)    │      │  │
│  │  └──────────┘ └──────────┘ └──────────┘      │  │
│  │                                              │  │
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐      │  │
│  │  │ LLM调度器│ │ 代码索引 │ │ Git集成  │      │  │
│  │  │(多模型)  │ │(AST/RAG) │ │(操作)    │      │  │
│  │  └──────────┘ └──────────┘ └──────────┘      │  │
│  └──────────────────┬────────────────────────────┘  │
│                     │                              │
│  ┌──────────────────▼────────────────────────────┐  │
│  │           数据层 (Data Layer)                   │  │
│  │  PostgreSQL │ Redis │ MinIO(S3) │ SQLite       │  │
│  └───────────────────────────────────────────────┘  │
│                                                     │
│  ┌───────────────────────────────────────────────┐  │
│  │           外部集成层 (Integrations)            │  │
│  │  MCP Server │ GitHub/GitLab │ CI/CD │ LDAP    │  │
│  └───────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────┘

四、源码目录结构解读

📁 MonkeyCode 源码结构(简化版)

monkeycode/
├── 📄 LICENSE                    # AGPL-3.0 协议文件
├── 📄 README.md                  # 项目介绍和快速开始
├── 📄 CONTRIBUTING.md            # 贡献指南
├── 📄 .sdd.yaml                  # 项目自身的SDD规范(元编程!)
│
├── 📁 backend/                   # 后端核心服务
│   ├── api/                      # API接口定义
│   │   ├── handlers/             # 请求处理器
│   │   ├── middleware/           # 中间件(认证/日志/限流)
│   │   └── schemas/              # 请求/响应数据模型
│   │
│   ├── core/                     # 核心业务逻辑
│   │   ├── sdd/                  # ★ SDD规范驱动引擎
│   │   │   ├── parser.py         # .sdd.yaml 解析器
│   │   │   ├── validator.py      # 规则验证器
│   │   │   ├── generator.py      # 规范化代码生成器
│   │   │   └── templates/        # 代码模板库
│   │   │
│   │   ├── agent/                # ★ Agent任务编排引擎
│   │   │   ├── orchestrator.py   # 任务协调器
│   │   │   ├── executor.py       # 任务执行器
│   │   │   ├── planner.py        # 任务规划器
│   │   │   └── tools/            # 工具集(文件/Git/终端...)
│   │   │
│   │   ├── security/             # ★ MonkeyScan安全扫描引擎
│   │   │   ├── scanners/         # 各类扫描器
│   │   │   │   ├── sql_injection.py
│   │   │   │   ├── xss.py
│   │   │   │   ├── secret_leakage.py
│   │   │   │   ├── dependency_vuln.py
│   │   │   │   └── ...
│   │   │   ├── rules/            # 扫描规则库
│   │   │   └── reporter.py       # 报告生成器
│   │   │
│   │   ├── llm/                  # LLM模型调度层
│   │   │   ├── provider.py       # 多Provider抽象
│   │   │   ├── context_manager.py# 上下文管理
│   │   │   └── prompt_templates/ # Prompt模板
│   │   │
│   │   └── git/                  # Git操作封装
│   │       ├── operations.py     # Commit/Push/PR等
│   │       └── diff_analyzer.py  # 差异分析
│   │
│   ├── models/                   # 数据模型
│   ├── services/                 # 业务服务层
│   ├── utils/                    # 工具函数
│   └── main.py                   # 入口文件
│
├── 📁 frontend/                  # 前端Web界面
│   ├── src/
│   │   ├── components/           # UI组件
│   │   ├── pages/                # 页面
│   │   ├── stores/               # 状态管理
│   │   └── hooks/                # React Hooks
│   └── package.json
│
├── 📁 vscode-extension/          # VS Code插件
│   ├── src/
│   │   ├── extension.ts          # 插件入口
│   │   ├── panels/               # 面板组件
│   │   └── commands/             # 命令注册
│   └── package.json
│
├── 📁 cli/                       # 命令行工具
│   ├── monkeycode.py             # CLI入口
│   └── commands/                 # 子命令定义
│
├── 📁 deploy/                    # 部署相关
│   ├── docker/                   # Docker配置
│   │   ├── Dockerfile
│   │   └── docker-compose.yaml
│   ├── kubernetes/               # K8s部署清单
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── configmap.yaml
│   └── scripts/                  # 部署脚本
│       ├── install.sh
│       └── upgrade.sh
│
├── 📁 tests/                     # 测试套件
│   ├── unit/                     # 单元测试
│   ├── integration/              # 集成测试
│   └── e2e/                      # 端到端测试
│
├── 📁 docs/                      # 文档
│   ├── architecture.md           # 架构文档
│   ├── api/                      # API文档
│   ├── sdd-guide.md              # SDD规范编写指南
│   └── deployment.md             # 部署文档
│
└── 📁 examples/                  # 示例和模板
    ├── sdd-templates/            # SDD规范模板
    │   ├── python-best-practices.sdd.yaml
    │   ├── typescript-standard.sdd.yaml
    │   └── go-enterprise.sdd.yaml
    └── workflows/                # 工作流示例
        ├── issue-to-pr.yaml
        └── code-review-auto.yaml

五、从零开始:本地构建与运行

🛠️ 本地开发环境搭建

前置要求:
├── Python 3.11+
├── Node.js 18+
├── PostgreSQL 15+
├── Redis 7+
├── Git
└── Docker(可选,用于容器化部署)

步骤1:克隆仓库
git clone https://github.com/chaitin/monkeycode.git
cd monkeycode

步骤2:创建虚拟环境
python -m venv venv
source venv/bin/activate  # Linux/Mac
# 或 venv\Scripts\activate  # Windows

步骤3:安装Python依赖
pip install -r requirements.txt

步骤4:配置环境变量
cp .env.example .env
# 编辑.env文件,填入以下关键配置:

# 数据库连接
DATABASE_URL=postgresql://user:pass@localhost:5432/monkeycode

# Redis连接
REDIS_URL=redis://localhost:6379/0

# LLM API配置(支持多种Provider)
LLM_PROVIDER=openai  # 可选: openai/deepseek/qwen/gemini
OPENAI_API_KEY=sk-your-key-here
# 或 DEEPSEEK_API_KEY / QWEN_API_KEY 等

# 其他配置
SECRET_KEY=your-secret-key-for-signing
ALLOWED_ORIGINS=http://localhost:3000

步骤5:初始化数据库
alembic upgrade head

步骤6:启动后端服务
python -m backend.main
# 服务默认运行在 http://localhost:8000

步骤7:启动前端(另开终端)
cd frontend
npm install
npm run dev
# 前端默认运行在 http://localhost:3000

步骤8:访问验证
打开浏览器访问 http://localhost:3000
看到MonkeyCode登录页面 → 成功!🎉

💡 快速启动(Docker方式):
docker-compose up -d
一键启动全部服务(PostgreSQL + Redis + 后端 + 前端)
适合快速体验,不适合二次开发

六、核心模块源码解读

6.1 SDD引擎:规范驱动的灵魂

# backend/core/sdd/parser.py — SDD规范解析器(简化版)

import yaml
from pathlib import Path
from dataclasses import dataclass, field
from typing import Optional, List, Dict, Any

@dataclass
class NamingConvention:
    """命名规范"""
    variables: str = "camelCase"
    functions: str = "camelCase"
    classes: str = "PascalCase"
    constants: str = "UPPER_SNAKE_CASE"
    files: str = "kebab-case"

@dataclass
class CodeStructure:
    """代码结构限制"""
    max_lines_per_file: int = 500
    max_lines_per_function: int = 80
    max_nesting_depth: int = 4
    max_parameters: int = 5
    max_cyclomatic_complexity: int = 15

@dataclass
class SecurityRule:
    """安全规则"""
    no_hardcoded_secrets: str = "error"  # error/warning/info/off
    no_eval_usage: str = "error"
    sql_parameterized_only: str = "warning"
    input_validation_required: str = "error"
    dependency_scan_on_save: bool = True

@dataclass
class TestingRequirement:
    """测试要求"""
    min_code_coverage: float = 80.0
    test_naming_convention: str = "given_when_then"
    no_skipped_tests_in_ci: bool = True

@dataclass
class SDDSpec:
    """完整的SDD规范定义"""
    project_name: str = ""
    version: str = "1.0.0"
    language: str = ""
    
    naming: NamingConvention = field(default_factory=NamingConvention)
    structure: CodeStructure = field(default_factory=CodeStructure)
    security: SecurityRule = field(default_factory=SecurityRule)
    testing: TestingRequirement = field(default_factory=TestingRequirement)
    
    custom_rules: List[Dict[str, Any]] = field(default_factory=list)


class SDDParser:
    """SDD YAML文件解析器"""
    
    def __init__(self):
        self._cache: Dict[str, SDDSpec] = {}
    
    def parse(self, file_path: Path) -> SDDSpec:
        """
        解析.sdd.yaml文件,返回SDDSpec对象
        
        Args:
            file_path: .sdd.yaml文件路径
            
        Returns:
            SDDSpec对象
        """
        if str(file_path) in self._cache:
            return self._cache[str(file_path)]
        
        if not file_path.exists():
            raise FileNotFoundError(f"SDD file not found: {file_path}")
        
        with open(file_path, 'r', encoding='utf-8') as f:
            raw_data = yaml.safe_load(f) or {}
        
        spec = self._build_spec(raw_data)
        self._cache[str(file_path)] = spec
        
        return spec
    
    def _build_spec(self, raw: Dict) -> SDDSpec:
        """从原始字典构建SDDSpec对象"""
        return SDDSpec(
            project_name=raw.get('project', {}).get('name', ''),
            version=raw.get('project', {}).get('version', '1.0.0'),
            language=raw.get('project', {}).get('language', ''),
            
            naming=NamingConvention(**raw.get('coding_standards', {})
                                      .get('naming_conventions', {})),
            structure=CodeStructure(**raw.get('coding_standards', {})
                                       .get('code_structure', {})),
            security=SecurityRule(**raw.get('security_rules', {})),
            testing=TestingRequirement(**raw.get('testing_requirements', {})),
            custom_rules=raw.get('custom_rules', [])
        )
    
    def validate_syntax(self, file_path: Path) -> List[str]:
        """验证SDD文件的语法正确性"""
        errors = []
        try:
            self.parse(file_path)
        except yaml.YAMLError as e:
            errors.append(f"YAML syntax error: {e}")
        except Exception as e:
            errors.append(f"Parse error: {e}")
        return errors


# 使用示例:
if __name__ == "__main__":
    parser = SDDParser()
    spec = parser.parse(Path(".sdd.yaml"))
    print(f"Project: {spec.project_name}")
    print(f"Naming: variables={spec.naming.variables}, "
          f"classes={spec.naming.classes}")
    print(f"Max lines/function: {spec.structure.max_lines_per_function}")
    print(f"Min coverage: {spec.testing.min_code_coverage}%")

6.2 Agent引擎:自主执行的内核

# backend/core/agent/orchestrator.py — Agent任务协调器(简化版)

import asyncio
from typing import List, Optional, Any, Dict
from enum import Enum
from dataclasses import dataclass, field
from datetime import datetime


class TaskStatus(Enum):
    PENDING = "pending"
    PLANNING = "planning"
    EXECUTING = "executing"
    REVIEWING = "reviewing"
    SCANNING = "scanning"
    TESTING = "testing"
    COMPLETED = "completed"
    FAILED = "failed"


@dataclass
class SubTask:
    """子任务定义"""
    id: str
    description: str
    task_type: str  # code_generation / test / scan / git_operation
    status: TaskStatus = TaskStatus.PENDING
    result: Optional[Any] = None
    error: Optional[str] = None
    dependencies: List[str] = field(default_factory=list)


@dataclass
class AgentTask:
    """Agent完整任务"""
    id: str
    title: str
    description: str
    subtasks: List[SubTask] = field(default_factory=list)
    status: TaskStatus = TaskStatus.PENDING
    created_at: datetime = field(default_factory=datetime.now)
    completed_at: Optional[datetime] = None
    metadata: Dict[str, Any] = field(default_factory=dict)


class AgentOrchestrator:
    """
    Agent任务协调器 —— MonkeyCode的核心大脑
    
    负责任务拆解、执行调度、结果汇总
    """
    
    def __init__(self, sdd_spec, llm_client, security_engine, git_client):
        self.sdd = sdd_spec
        self.llm = llm_client
        self.security = security_engine
        self.git = git_client
        self._task_history: List[AgentTask] = []
    
    async def execute_task(self, task_description: str,
                           repo_path: str,
                           issue_metadata: Dict = None) -> AgentTask:
        """
        执行一个完整的Agent任务
        
        流程:
        1. 分析需求 → 拆解为子任务
        2. 按依赖关系依次执行子任务
        3. 每个子任务完成后进行质量检查
        4. 全部通过后提交PR
        """
        # 创建主任务
        task = AgentTask(
            id=self._generate_id(),
            title=f"Auto: {task_description[:50]}",
            description=task_description,
            metadata={"repo_path": repo_path, "issue": issue_metadata}
        )
        
        # Phase 1: 任务规划
        task.status = TaskStatus.PLANNING
        subtasks = await self._plan_tasks(task_description, repo_path)
        task.subtasks = subtasks
        
        # Phase 2: 顺序执行子任务
        task.status = TaskStatus.EXECUTING
        for st in subtasks:
            await self._execute_subtask(st, task)
            if st.status == TaskStatus.FAILED:
                task.status = TaskStatus.FAILED
                break
        
        # Phase 3: 最终检查与提交
        if task.status != TaskStatus.FAILED:
            await self._final_review(task)
            pr_url = await self._create_pull_request(task)
            task.status = TaskStatus.COMPLETED
            task.metadata["pr_url"] = pr_url
        
        task.completed_at = datetime.now()
        self._task_history.append(task)
        return task
    
    async def _plan_tasks(self, description: str, 
                          repo_path: str) -> List[SubTask]:
        """使用LLM分析需求并拆解子任务"""
        prompt = f"""
你是任务规划专家。根据以下需求和SDD规范,拆解具体的执行步骤。

需求描述:
{description}

SDD规范要点:
- 语言: {self.sdd.language}
- 最大函数行数: {self.sdd.structure.max_lines_per_function}
- 最小覆盖率: {self.sdd.testing.min_code_coverage}%
- 安全规则: {self.sdd.security}

请输出JSON格式的子任务列表,每个子任务包含:
id, description, type, dependencies[]
"""
        result = await self.llm.chat(prompt)
        # 解析LLM返回的任务列表...
        return self._parse_subtasks(result)
    
    async def _execute_subtask(self, subtask: SubTask, 
                                parent_task: AgentTask):
        """执行单个子任务"""
        subtask.status = self._get_executing_status(subtask.task_type)
        
        try:
            if subtask.task_type == "code_generation":
                subtask.result = await self._generate_code(subtask, parent_task)
            elif subtask.task_type == "test":
                subtask.result = await self._run_tests(subtask)
            elif subtask.task_type == "scan":
                subtask.result = await self._security_scan(subtask)
            elif subtask.task_type == "git_operation":
                subtask.result = await self._git_operation(subtask)
            
            subtask.status = TaskStatus.COMPLETED
        except Exception as e:
            subtask.error = str(e)
            subtask.status = TaskStatus.FAILED
            raise
    
    async def _create_pull_request(self, task: AgentTask) -> str:
        """创建Pull Request"""
        branch_name = f"auto/{task.id}"
        commit_msg = f"feat(agent): {task.title}"
        
        pr_url = await self.git.create_pr(
            branch=branch_name,
            title=f"[Agent] {task.title}",
            body=self._generate_pr_body(task),
            auto_merge=False  # 需要人工审核
        )
        return pr_url

6.3 MonkeyScan:安全扫描引擎

# backend/core/security/scanners/sql_injection.py — SQL注入检测器(简化版)

import re
import ast
from typing import List, Tuple, Optional
from dataclasses import dataclass
from enum import Enum


class Severity(Enum):
    CRITICAL = "critical"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"
    INFO = "info"


@dataclass
class Vulnerability:
    """漏洞发现记录"""
    rule_id: str
    severity: Severity
    title: str
    description: str
    file_path: str
    line_number: int
    column: int
    code_snippet: str
    remediation: str  # 修复建议


class SQLInjectionScanner:
    """
    SQL注入漏洞扫描器
    
    检测模式:
    1. 字符串拼接SQL(最危险)
    2. f-string格式化SQL
    3. %格式化SQL
    4. string.format() SQL
    5. 未参数化的execute()调用
    """
    
    # 危险模式正则表达式
    DANGEROUS_PATTERNS = [
        # f"SELECT * FROM users WHERE id = {user_input}"
        (r'f["\'].*(?:SELECT|INSERT|UPDATE|DELETE|FROM|WHERE).*\{',
         "f-string SQL concatenation", Severity.CRITICAL),
         
        # "SELECT * FROM users WHERE id = " + user_id
        (r'(?:SELECT|INSERT|UPDATE|DELETE)\s.+[\+\*]\s*\w+',
         "string concatenation in SQL", Severity.CRITICAL),
         
        # cursor.execute("SELECT * FROM t WHERE id=" + val)
        (r'\.execute\s*\(\s*["\'].*(?:SELECT|INSERT|UPDATE).*["\'].*[\+\%]',
         "unparameterized execute()", Severity.HIGH),
         
        # "SELECT * FROM t WHERE id=%s" % (user_input,)
        (r'["\'].*(?:SELECT|INSERT|UPDATE).*%[sd].*["\']',
         "% formatting in SQL query", Severity.HIGH),
    ]
    
    # 安全模式(白名单)
    SAFE_PATTERNS = [
        r'\.execute\(.*%(?:s|d)',  # 参数化查询 %s/%d
        r'\$[12]',                  # $1/$2 占位符
        r':\w+',                    # :name 参数绑定
        r'\?',                      # ? 占位符
    ]
    
    def __init__(self):
        self._findings: List[Vulnerability] = []
    
    def scan_file(self, file_path: str, content: str) -> List[Vulnerability]:
        """扫描单个文件中的SQL注入风险"""
        self._findings = []
        lines = content.split('\n')
        
        for line_num, line in enumerate(lines, 1):
            # 先检查是否是安全模式
            if any(re.search(safe, line) for safe in self.SAFE_PATTERNS):
                continue
            
            # 检查危险模式
            for pattern, desc, severity in self.DANGEROUS_PATTERNS:
                match = re.search(pattern, line, re.IGNORECASE)
                if match:
                    vuln = Vulnerability(
                        rule_id="SQLI-001",
                        severity=severity,
                        title=f"Potential SQL Injection: {desc}",
                        description=(
                            f"Detected unsafe SQL construction that may be "
                            f"vulnerable to SQL injection attacks. "
                            f"Use parameterized queries instead."
                        ),
                        file_path=file_path,
                        line_number=line_num,
                        column=match.start(),
                        code_snippet=line.strip(),
                        remediation=(
                            "Replace string concatenation with parameterized queries:\n"
                            "# Before (vulnerable):\n"
                            'cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")\n\n'
                            "# After (safe):\n"
                            'cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))'
                        )
                    )
                    self._findings.append(vuln)
        
        return self._findings
    
    def generate_report(self) -> dict:
        """生成扫描报告"""
        by_severity = {}
        for v in self._findings:
            key = v.severity.value
            by_severity[key] = by_severity.get(key, 0) + 1
        
        return {
            "scanner": "SQLInjectionScanner",
            "total_findings": len(self._findings),
            "by_severity": by_severity,
            "findings": [
                {
                    "rule_id": f.rule_id,
                    "severity": f.severity.value,
                    "file": f.file_path,
                    "line": f.line_number,
                    "title": f.title,
                    "remediation": f.remediation
                }
                for f in sorted(self._findings, 
                                 key=lambda x: x.severity.value)
            ]
        }

七、Docker容器化部署

# docker-compose.yaml — 一键部署方案

version: '3.8'

services:
  # PostgreSQL数据库
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: monkeycode
      POSTGRES_USER: mc_user
      POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme_in_production}
    volumes:
      - pg_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U mc_user"]
      interval: 10s
      timeout: 5s
      retries: 5

  # Redis缓存
  redis:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD:-changeme}
    volumes:
      - redis_data:/data
    ports:
      - "6379:6379"

  # MonkeyCode后端服务
  monkeycode-api:
    build:
      context: .
      dockerfile: deploy/docker/Dockerfile.api
    environment:
      DATABASE_URL: postgresql://mc_user:${DB_PASSWORD:-changeme}@postgres:5432/monkeycode
      REDIS_URL: redis://:${REDIS_PASSWORD:-changeme}@redis:6379/0
      LLM_PROVIDER: ${LLM_PROVIDER:-deepseek}
      DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY}
      SECRET_KEY: ${SECRET_KEY:-change-me-to-random-string}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
    ports:
      - "8000:8000"
    volumes:
      - ./config:/app/config  # 挂载配置目录
      - ./workspace:/app/workspace  # 工作区挂载
    restart: unless-stopped

  # MonkeyCode前端
  monkeycode-web:
    build:
      context: .
      dockerfile: deploy/docker/Dockerfile.web
    environment:
      VITE_API_BASE_URL: http://localhost:8000
    depends_on:
      - monkeycode-api
    ports:
      - "3000:80"
    restart: unless-stopped

volumes:
  pg_data:
  redis_data:

# 使用方法:
# 1. 复制 .env.example 为 .env 并填写配置
# 2. docker-compose up -d
# 3. 访问 http://localhost:3000

八、Kubernetes生产级部署

# kubernetes/deployment.yaml — K8s部署清单(关键部分)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: monkeycode-api
  labels:
    app: monkeycode
    component: api
spec:
  replicas: 3  # 生产环境建议3副本
  selector:
    matchLabels:
      app: monkeycode
      component: api
  template:
    metadata:
      labels:
        app: monkeycode
        component: api
    spec:
      containers:
      - name: api
        image: chaitin/monkeycode:v1.2.0
        ports:
        - containerPort: 8000
        envFrom:
        - configMapRef:
            name: monkeycode-config
        - secretRef:
            name: monkeycode-secrets
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8000
          initialDelaySeconds: 5
          periodSeconds: 5
        volumeMounts:
        - name: workspace
          mountPath: /app/workspace
      volumes:
      - name: workspace
        persistentVolumeClaim:
          claimName: monkeycode-workspace-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: monkeycode-api-service
spec:
  selector:
    app: monkeycode
    component: api
  ports:
  - port: 80
    targetPort: 8000
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: monkeycode-ingress
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - monkeycode.yourcompany.com
    secretName: monkeycode-tls
  rules:
  - host: monkeycode.yourcompany.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: monkeycode-api-service
            port:
              number: 80

九、社区贡献指南

🤝 如何参与MonkeyCode开源社区

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

贡献方式一:报告Bug
┌─────────────────────────────────────┐
│ 1. 访问 GitHub Issues              │
│ 2. 搜索是否已有相同问题             │
│ 3. 创建新Issue,包含:              │
│    • 复现步骤(尽可能详细)         │
│    • 期望行为 vs 实际行为           │
│    • 环境信息(OS/Python版本等)    │
│    • 相关日志或截图                 │
└─────────────────────────────────────┘

贡献方式二:提交代码
┌─────────────────────────────────────┐
│ 1. Fork 仓库到你的GitHub账号        │
│ 2. 创建特性分支:git checkout -b    │
│    feature/my-cool-feature         │
│ 3. 编写代码 + 单元测试              │
│ 4. 确保所有测试通过:pytest         │
│ 5. 提交Commit(遵循Conventional    │
│    Commits规范)                    │
│ 6. 推送到你的Fork                   │
│ 7. 创建 Pull Request               │
│ 8. 等待CI通过和Maintainer Review    │
└─────────────────────────────────────┘

贡献方式三:完善文档
├── 补充API文档的使用示例
├── 翻译文档到其他语言
├── 编写教程和最佳实践
├── 改进错误提示信息
└── 添加代码注释

贡献方式四:分享SDD规范模板
├── 提交行业最佳实践的.sdd.yaml模板
├── 分享你的团队编码规范
├── 贡献安全扫描规则
└── 提供工作流配置示例

贡献方式五:推广社区
├── 写博客分享使用经验
├── 在技术会议上演示
├── 回答GitHub Issues上的问题
├── 帮助新人上手
└── 在社交媒体上传播

💡 贡献者激励:
→ 优秀贡献者会被列入CONTRIBUTORS.md
→ 有机会成为Maintainer
→ 企业贡献者可获得技术支持优先权
→ 年度评选Top Contributor

十、常见问题FAQ

❓ Q1: MonkeyCode开源版和云端版有什么区别?
A: 核心功能100%一致。主要区别:
   - 云端版:开箱即用,官方运维,送200元额度
   - 开源版:自行部署,数据完全自控,无限制
   - 企业版(付费):专属支持+高级功能+SLA保障

❓ Q2: 开源版的性能能达到商用级别吗?
A: 可以。开源版就是云端版的同一套代码。
   性能取决于你的硬件配置和LLM Provider选择。
   实测:8核16G服务器可支撑50人团队日常使用。

❓ Q3: 如何获取LLM API Key?推荐哪个Provider?
A: 注册即送的选项:
   - DeepSeek:性价比最高(¥1/百万Token)
   - 通义千问:阿里云生态集成好
   - Gemini:Google免费层慷慨
   - MonkeyCode支持同时配置多个Provider做负载均衡

❓ Q4: 内网隔离环境能部署吗?
A: 完全可以!这是MonkeyCode开源的核心价值之一。
   所有组件均可离线部署,只需确保:
   - LLM API可达(或部署本地模型)
   - 包含依赖的Docker镜像可导入内网

❓ Q5: 从Cline/Windsurf迁移到MonkeyCode难吗?
A: 不难。核心差异在于:
   - Cline/Windsurf:个人工具,无规范约束
   - MonkeyCode:团队工具,SDD规范统一标准
   迁移主要是建立.sdd规范文件的过程,
   通常1-2天即可完成团队迁移。

❓ Q6: MonkeyScan的安全规则可以自定义吗?
A: 可以!开源版包含完整的规则编辑能力:
   - 内置200+条安全规则(覆盖OWASP Top 10)
   - 支持YAML格式的自定义规则
   - 支持正则匹配和AST分析两种模式
   - 社区持续贡献新规则

📌 总结

MonkeyCode开源不仅仅是一份源码——它是一个完整的企业级AI编程平台的蓝图。从SDD规范驱动引擎到MonkeyScan安全扫描,从Agent自动编排到Git Pipeline集成,每一个核心模块都清晰可见、可审计、可定制。对于追求代码安全和工程规范的企业团队来说,MonkeyCode开源版不仅是一个免费的AI编程工具,更是一套经过实战检验的研发流程标准化方案。而这一切,都在AGPL-3.0协议下自由可用。


🔗 系列导航

  • [第1篇/共30篇 — MonkeyCode开源系列开篇]
  • [下一篇:《AGPL-3.0协议深度解读:企业使用的权利与义务》]

本文基于MonkeyCode开源源码实测撰写,更多开源深度文章请关注本系列。

posted on 2026-07-08 16:01  MonkeyCode  阅读(49)  评论(0)    收藏  举报