- 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
57 lines
2.8 KiB
Markdown
57 lines
2.8 KiB
Markdown
# 项目目录树(完整版)
|
||
|
||
问题:任务内 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` 翻译)。
|