code agent
code agent
目的
实现基本代码读写能力,供text2agent及自进化(optimizer)使用来对agent源码进行编辑。
skill定义
两个skill(text2agent, optimizer)分别构建和读取代码上下文及轨迹上下文,实现对agent的从0生成和优化:
text2agent定义
Input:
prompt
agent模板:gaia_agent、ppt_agent
Agent标准写法
Output:
agent目录
xxx_agent.py
mcp_config.py
流程:
optimizer定义
Input:
prompt
agent模板:gaia_agent、ppt_agent
Agent标准写法
Output:
agent目录
xxx_agent.py
mcp_config.py
流程:
code 编辑方案
Code ASisTant - A unified code assistant framework based on Tree-sitter, designed specifically for agent code understanding and optimization. Adopts a three-tier hierarchical indexing architecture to provide LLMs with precise code understanding and modification capabilities.
1 | ┌─────────────────────────────────────────────────────────┐ |
接口(tools)
Serves as the integration bridge between the CAST framework and the AWorld ecosystem:
工作流集成
三层架构支持渐进式细化工作流:
- 预处理阶段:
1 | └─> 扫描代码库 → 生成 L1(全景图)+ L2(骨架) |
- (未实现)轨迹集成:
1 | └─> 解析执行日志 → 映射到代码结构 → 标注 L1 |
- 分析阶段:
1 | └─> optimizer Agent 读取 L1 + L2 + Reward(user input) → 识别问题区域 |
- 调查阶段:
1 | └─> Agent 使用 L2 签名定位特定函数/类 |
- 修改阶段:
1 | └─> Agent 调用 read_file() 获取 L3 代码 → 生成修复 |
main.py (入口点, 已执行)
- class Agent:
- run() (调用 1 次) → 调用 planner.py/plan()
planner.py (逻辑核心, 已执行)
- class Planner:
- plan() (调用 1 次) → 调用 tools.py/search()
tools.py (工具库, 已执行)
- search() (调用 2 次)
memory.py (未执行 - 已剪枝以节省空间)
config.py (配置, 只读)
应用场景:大型代码库快速架构理解、核心模块识别、依赖分析、问题定位。
L2 - 接口骨架层(SkeletonLayer)
功能:提供接口级概览(不含实现细节),支持精确代码定位和 API 理解。
核心组件:
class SkeletonLayer:
file_skeletons: Dict[Path, str] # 文件骨架代码(仅签名)
symbol_signatures: Dict[str, str] # 符号签名映射
line_mappings: Dict[Path, Dict[int, int]] # 行号映射(原始 → 骨架)
docstring_index: Dict[str, str] # 文档字符串索引
技术实现:
AST 提取:使用 Tree-sitter 或 Python ast 模块解析源码
签名保留:保留所有 import、class 定义和 def 声明
文档保留:保留所有 docstring(理解设计意图的关键)
实现移除:函数体替换为 pass 或 …,或仅保留前 5 行
行号标注:标记每行的原始行号(如 (Line 105))
输出示例:
File: planner.py
(Line 1) import openai
(Line 3) class Planner:
(Line 4) “””处理任务分解。”””
(Line 5) def init(self, model_name):
(Line 6) …
(Line 8) def plan(self, task_description: str) -> list:
(Line 9) “””
(Line 10) 根据描述生成步骤列表。
(Line 11) “””
(Line 12) … # 实现已隐藏
核心特性:完整 API 概览、设计意图保留、精确位置映射、token 消耗仅为原代码的 5-10%。
应用场景:接口级代码理解、函数签名快速识别、设计模式分析、问题精确定位。
L3 - 源码实现层(ImplementationLayer)
功能:提供完整源码实现,支持精确代码定位和精准修改。
核心组件:
class ImplementationLayer:
code_nodes: Dict[Path, CodeNode] # 完整代码节点(含实现)
symbol_references: Dict[str, List[Location]] # 符号引用位置
modification_history: List[Patch] # 代码修改历史
访问模式:优化器 Agent 通过工具调用按需访问 L3:
Agent 在 L1/L2 中定位问题,然后请求特定代码
read_file(file=”planner.py”, start_line=12, end_line=50)
核心特性:完整源码、精确符号位置、引用关系分析、支持精准代码替换。
应用场景:问题定位后的精确修改、特定函数实现检查、代码重构优化、最小上下文开销的 bug 修复。
基于轨迹的优化(未实现)
CAST 的关键创新是将执行轨迹数据集成到上下文展示优化中:
轨迹映射
CAST 将轨迹解析并映射到代码结构:
解析轨迹:提取堆栈跟踪、执行函数调用和错误位置
映射到代码结构:将轨迹事件关联到 L1/L2 中的具体代码位置
可视化标注:直接在代码结构上标记问题区域(如 [ERROR: Timeout] 标注在 tools.py 旁)
效果:优化器 Agent 无需阅读数千行日志即可立即看到问题位置
动态剪枝
当 Agent 有 100 个文件但仅执行了 3 个时:
执行分析:识别实际调用的文件/函数
上下文剪枝:在 L1/L2 中隐藏或折叠未使用文件
Token 减少:上下文长度减少 70-90%
聚焦增强:优化器 Agent 专注于”案发现场”代码路径
searcher - 代码读取
Search Engine Layer (searchers/)
和文件系统的cat、grep等读文件命令逻辑一致
coder - 代码编辑
coder (coders/)
1. dmp_coder
dmp表示diff match patch,patch里既包含偏移量,又带有代码上下文作为参照物,这二者都可能出错,很脆弱,如下图就是生成了一个错误的格式:
2. op_coder
按行插入、替换、删除,指定文件、位置、代码进行插入:
[
{
“type”: “insert”,
“file_path”: “ppt_generator_agent.py”,
“after_line”: 753,
“content”: [
“”,
“ def print_html_to_terminal(self, html_content: str, max_lines: int = 50) -> Dict[str, Any]:”,
“ """“,
“ 向terminal打印HTML内容”,
“”,
“ Args:”,
“ html_content (str): 要打印的HTML内容”,
“ max_lines (int): 最大打印行数,默认50行”,
“”,
“ Returns:”,
“ Dict[str, Any]: 打印操作的结果”,
“ """“,
“ try:”,
“ lines = html_content.split(‘\n’)”,
“ total_lines = len(lines)”,
“”,
“ print("=" * 80)”,
“ print("📄 PPT HTML 内容预览")”,
“ print("=" * 80)”,
“”,
“ # 打印HTML内容(限制行数)”,
“ for i, line in enumerate(lines[:max_lines]):”,
“ print(f"{i+1:4d}: {line}")”,
“”,
“ if total_lines > max_lines:”,
“ print(f"… (省略了 {total_lines - max_lines} 行)")”,
“”,
“ print("=" * 80)”,
“ print(f"✅ HTML内容已打印到terminal (总共 {total_lines} 行,显示了前 {min(max_lines, total_lines)} 行)")”,
“”,
“ logger.info(f"HTML内容已打印到terminal,总行数: {total_lines}")”,
“”,
“ return {“,
“ ‘success’: True,”,
“ ‘total_lines’: total_lines,”,
“ ‘displayed_lines’: min(max_lines, total_lines),”,
“ ‘message’: f’HTML内容已成功打印到terminal (显示 {min(max_lines, total_lines)}/{total_lines} 行)’”,
“ }”,
“”,
“ except Exception as e:”,
“ error_msg = f"打印HTML内容到terminal时发生错误: {str(e)}"“,
“ logger.error(error_msg)”,
“ print(f"❌ {error_msg}")”,
“ return {“,
“ ‘success’: False,”,
“ ‘message’: error_msg,”,
“ ‘error_details’: str(e)”,
“ }”
]
}
]
3. search_replace
{
“operation”: {
“type”: “search_replace”,
“file_path”: “相对文件路径”,
“search”: “要搜索的代码文本”,
“replace”: “替换后的代码文本”,
“exact_match_only”: true
}
}
四层匹配策略(按优先级):
完全精确匹配:逐行完全一致比较(最安全)
内部精确匹配:去除前后空白后匹配
空白符灵活匹配:忽略缩进差异,标准化后匹配
相似性模糊匹配:基于difflib的相似度匹配(10%容错)
安全机制:
自动创建.bak备份文件
执行前参数和文件存在性验证
失败时自动从备份恢复
支持dry_run预检查模式
4. 行号偏移问题
在开发 Coding Agent(如 Aider, OpenDevin 或自定义的自动修复工具)时,“行号漂移(Line Drift)”是一个经典难题。如果 Agent 计划在第 10 行插入 5 行,那么原先的第 20 行就变成了第 25 行,后续操作如果还盯着“第 20 行”就会改错地方。
主流框架和工业界通常采用以下四种策略来解决这个问题:
4.1. 1. 倒序操作策略 (Bottom-up Approach)
这是最简单、成本最低的方案。如果 Agent 一次性给出了多个修改建议:
做法:将所有修改任务按行号从大到小(从文件末尾向开头)进行排序。
原理:修改文件下方的内容,不会影响上方内容的行号。
优点:逻辑极简,不需要复杂的坐标转换。
4.2. 2. 偏移量追踪 (Offset Tracking / Delta Mapping)
这是 IDE(如 VS Code)和版本控制系统常用的算法。
做法:维护一个全局的 delta(偏移值)。
原理:
初始 delta = 0。
第一次操作:在第 行插入 行,则 delta 增加 。
第二次操作:如果 Agent 想修改原始文件的第 行,实际应用的位置是 。
局限:如果 Agent 的修改不仅是新增,还有删除,计算会变得稍微复杂一些。
4.3. 3. 基于语义的“搜索-替换”块 (Search & Replace Blocks)
这是目前 LLM Agent 框架(如 Aider)最主流的做法。 放弃行号,改用上下文匹配。
做法:要求 LLM 给出一段“旧代码块”和一段“新代码块”。
流程:
Agent 输出:SEARCH: [这段旧代码] REPLACE: [这段新代码]。
框架在目标文件中模糊搜索 SEARCH 段落。
找到匹配位置后进行替换。
优点:彻底摆脱行号依赖。即便行号偏了 100 行,只要代码内容唯一,就能定位成功。
4.4. 4. 虚拟文件系统与 AST 操作 (Structural Editing)
对于更高级的 Agent,会使用抽象语法树(AST)。
做法:将代码解析成树状结构,操作具体的“函数节点”或“类节点”,而不是操作“第几行”。
流程:
把代码转为 AST。
在树上增删改节点。
将 AST 重新生成(Print)回代码字符串。
优点:极其稳健,不会因为多一个空格或换行就报错。
4.5. 框架实践对比
如果你的 Agent 逻辑是:思考 -> 输出多个 Patch -> 一次性应用:
请务必使用 策略 1(倒序应用)。这是防止补丁冲突最快的方法。
如果你的 Agent 逻辑是:思考 -> 修改 A -> 思考 -> 修改 B:
那么每一步修改后,你应该重新读取文件内容提供给 Agent,或者使用 策略 3(搜索替换)。
| Tool | Description | Integration Interface |
|---|---|---|
| cast_analysis_tool.py | Code analysis and structure extraction | ANALYZE_REPOSITORY, SEARCH_AST |
| cast_search_tool.py | Search functionality tools | GREP_SEARCH, GLOB_SEARCH, READ_FILE |
| cast_coder_tool.py | Code modification and deployment tools | GENERATE_SNAPSHOT, DEPLOY_PATCHES, DEPLOY_OPS, SEARCH_REPLACE |
| 类型 | 功能描述 | 实现类 |
|---|---|---|
| GREP | 文本内容搜索 | GrepSearcher |
| GLOB | 文件模式匹配 | GlobSearcher |
| READ | 文件内容读取 | ReadSearcher |
| 类型 | 功能描述 | 实现类 |
|---|---|---|
| GREP | 文本内容搜索 | GrepSearcher |
| GLOB | 文件模式匹配 | GlobSearcher |
| READ | 文件内容读取 | ReadSearcher |
| 框架/工具 | 核心策略 | 备注 |
|---|---|---|
| Aider | Search/Replace Blocks | 这种方式对 LLM 最友好,因为它不需要 LLM 具备精准计数的能力(LLM 经常数错行)。 |
| Git / Patch | Context-based (Unified Diff) | 利用 @@ 块前后的上下文进行“模糊匹配(Fuzzing)”,允许小范围偏移。 |
| OpenDevin | File Editor Tool | 通常封装了 sed 或自定义的 insert_line 函数,内部维护文件状态,每步操作后立即刷新文件内容。 |