
Codex 类 AI 编程工具已经不只是"补全一行代码",而是可以读取仓库、执行命令、修改多文件、跑测试的编码代理。工程视角下,真正决定它能不能用于生产交付的,不是模型能力上限,而是三件事:上下文是否准确、执行是否有边界、产物是否可审查。
本文从代码库上下文打包、代理执行循环、差异审查与 CI 门禁四个环节,拆解 Codex AI 工程的落地骨架。
代理最常见的问题是"看不到关键文件"或"看到太多无关文件"。工程上需要先做仓库索引和文件筛选。
from pathlib import Path
from dataclasses import dataclass
IGNORE_DIRS = {".git", "node_modules", "__pycache__", ".venv", "dist", "build"}
ALLOW_EXT = {".py", ".ts", ".tsx", ".go", ".java", ".md", ".toml", ".yaml", ".yml"}
@dataclass
class FileMeta:
path: str
size: int
tokens: int
def scan_repo(root: Path, max_files: int = 2000) -> list[FileMeta]:
files: list[FileMeta] = []
for p in root.rglob("*"):
if not p.is_file() or p.suffix not in ALLOW_EXT:
continue
if any(part in IGNORE_DIRS for part in p.parts):
continue
text = p.read_text(encoding="utf-8", errors="ignore")
tokens = len(text) // 4 # 粗略估算
files.append(FileMeta(str(p.relative_to(root)), p.stat().st_size, tokens))
if len(files) >= max_files:
break
return files
def select_context(files: list[FileMeta], keywords: list[str], budget: int = 60000) -> list[str]:
scored = []
for f in files:
score = sum(1 for k in keywords if k.lower() in f.path.lower())
scored.append((score, f))
scored.sort(key=lambda x: (-x[0], x[1].tokens))
chosen, used = [], 0
for _, f in scored:
if used + f.tokens > budget:
continue
chosen.append(f.path)
used += f.tokens
return chosen关键点:按关键词相关性排序,再按 token 预算裁剪。不要无脑把整个仓库塞进上下文,成本高且容易引入噪声。
代理不能"一次生成就结束",需要计划—执行—验证的闭环。
import subprocess, json
from dataclasses import dataclass, field
@dataclass
class Step:
goal: str
files: list[str] = field(default_factory=list)
status: str = "pending"
result: str = ""
def run_cmd(cmd: list[str], timeout: int = 60) -> dict:
try:
p = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
return {"code": p.returncode, "out": p.stdout[-4000:], "err": p.stderr[-2000:]}
except subprocess.TimeoutExpired:
return {"code": -1, "out": "", "err": "timeout"}
def verify(repo: Path) -> dict:
checks = {
"lint": run_cmd(["ruff", "check", "."]),
"type": run_cmd(["mypy", "."]),
"test": run_cmd(["pytest", "-q"]),
}
checks["ok"] = all(c["code"] == 0 for c in checks.values())
return checks
def agent_loop(plan: list[Step], repo: Path, apply_fn, max_rounds: int = 5):
for rnd in range(max_rounds):
for step in plan:
if step.status == "done":
continue
patch = apply_fn(step) # 调用模型生成补丁
step.result = patch
check = verify(repo)
if check["ok"]:
step.status = "done"
else:
step.status = "retry"
step.goal += f"\n上次失败:{check['test']['err'][:500]}"
if all(s.status == "done" for s in plan):
return plan
return plan要点:每步都要跑 lint、类型检查、测试;失败信息回填到下一步提示词,让代理自我修正。轮次要有上限,避免无限循环烧钱。
代理生成的多文件改动,必须先转成可审查的 diff,再决定是否合并。
import difflib
from pathlib import Path
def make_diff(old: str, new: str, path: str) -> str:
return "".join(difflib.unified_diff(
old.splitlines(keepends=True),
new.splitlines(keepends=True),
fromfile=f"a/{path}",
tofile=f"b/{path}",
))
def summarize(diff: str) -> dict:
added = sum(1 for l in diff.splitlines() if l.startswith("+") and not l.startswith("+++"))
removed = sum(1 for l in diff.splitlines() if l.startswith("-") and not l.startswith("---"))
return {"added": added, "removed": removed, "files": diff.count("--- ")}审查清单:是否改了无关文件、是否引入新依赖、是否绕过权限校验、是否吞异常、是否删除测试、是否包含硬编码密钥。
代理提交同样要过 CI,不能有"AI 特权"。
name: ci
on: [push, pull_request]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- run: pip install ruff mypy pytest pytest-cov bandit pip-audit
- run: ruff check .
- run: mypy .
- run: pytest --cov=app --cov-fail-under=80
- run: bandit -r app
- run: pip-audit安全边界:
.env、密钥、用户数据目录。rm -rf、curl | sh 等危险操作。Codex AI 工程的专业性,不在于让模型写多少代码,而在于把代理放进一条可控的工程链路:上下文准确打包、执行有边界、失败可回填、产物可审查、CI 可拦截。代码可以简单,但权限、日志、测试、门禁和合规不能省。先把最小闭环跑通,再扩展到多仓库、多语言和复杂任务编排。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。