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开源源码实测撰写,更多开源深度文章请关注本系列。
浙公网安备 33010602011771号