Files
codex-app-server/docs/project-tree.md
T
host ce7fb3afd6 feat: project directory tree + first-round snapshot
- cloud/tree.py: structured worktree tree (dirs first, ignore
  .git/node_modules, symlinks not followed, entry/depth
  truncation flags, text render for injection)
- GET /tasks/{id}/tree with /files auth + worktree resolution,
  max_depth 1..5, max_entries 1..500, escape 400, missing 404,
  cloud/cross-host 409
- MCP get_task_tree translating to the new endpoint
- worker first-round injection of a repo-checkout top-level
  snapshot (2 layers, 120 entries) after repo resolution,
  labelled as checkout snapshot not worktree; skipped for
  coordinator/resume/fork, silent when no host source
- docs/project-tree.md; tests for tree, endpoint, injection,
  MCP translation
2026-10-30 14:46:11 +08:00

2.8 KiB
Raw Blame History

项目目录树(完整版)

问题:任务内 agent 本来就能用 shell ls/find 看 worktree, 但每次都要自己探路(费轮次/token),大项目噪音大、输出 是纯文本;任务外的 LLM(编辑器、协调方)只能用 get_task_files 一层一层列/读,没有“一眼看结构”的入口。

本批补三处,共用 cloud/tree.py,不改 codex 本体:

1. 结构化目录树工具

  • REST:GET /tasks/{id}/tree?path=&max_depth=&max_entries=
    • 权限与 worktree 解析与 /files 同款:viewer+ 可读; cloud 任务与跨机 worktree 一律 409,解析不到 404。
    • max_depth 1..5(缺省 3),max_entries 1..500 (缺省 200),非法整数 400,不静默回落。
    • 只含名、类型(dir/file/symlink)、大小,不读文件内容。
  • MCP:get_task_tree(cloud/mcp_server.py),参数同上, 直译为上述 REST 调用,服务端错误原样透传为 isError。

2. 首轮注入顶层结构

worker 在 run_one 里 _apply_project_repo 之后调 _apply_tree_injection:只改内存副本,原 prompt/goal 不落库;goal 任务同时改内存里的 goal。

时序诚实点(不要把这条改回“worktree 快照”): 认领时任务 worktree 还没建出来(派发时 host.py 才按检出 建 worktree),所以注入贴的是仓库检出顶层快照, worktree 正是由它建出;注入文本里明写这一点,附件 seed 与 agent 新建文件不在快照内。来源只认宿主上已存在 的目录:非租户/环境任务用 task["repo"],租户任务用 tenants_root/<safe>/<safe> 检出,repo_url 为空的租户 任务用 _tenant_dirs 的 test_repo;都找不到时静默跳过, 绝不炸掉认领。

跳过:协调员任务、续跑与断点续跑、分支任务 (forked_from:其 worktree 来自分支,不是检出快照)。 上限:2 层、120 条(tree.INJECTION_*),深层用 shell 或 get_task_tree 再查;空目录不贴空章节。

3. 安全与截断规则(tree.py)

  • 相对路径 only:绝对路径、.. 逃逸、符号链接逃逸 一律拒绝;目录内的符号链接列为 symlink、不跟进。
  • .git 永远不列;默认还忽略 node_modules、 __pycache__、.venv、venv 等。.gitignore 不解析。
  • 遍历顺序确定(目录在前、同类按名排序),条数到顶 置 truncated=True;被 max_depth 或条数截断的目录 children_truncated=True,与空目录(children=[] 且 children_truncated=False)可区分。

单测:cloud/tests/test_tree.py(结构/忽略/链接/截断/ 渲染)、test_server_task_tree.py(端点/权限/错误码)、 test_worker_tree_injection.py(注入/跳过/内存副本)、 test_mcp_server.py(get_task_tree 翻译)。