feat(v3): T22-T23 harness 级工具扩展 + 工作区选择后端
- T22 工具内核:edit_file(old_string 唯一命中才替换,防误改)、search_files (跨文件内容搜索,跳过 .git/node_modules 与二进制大文件)、run_command (allow_shell 默认关;超时+输出截断+Windows CREATE_NO_WINDOW) - T23 工作区选择(参考 deepseek-harness 打开文件夹体验):/agent/fs 磁盘目录浏览 (空 path 列 Windows 盘符)、/agent/workspaces 最近列表持久化、 POST /agent 接受 workspace(须存在目录),运行状态记录所用工作区 - 新增测试 12 项,全量 274 passed
This commit is contained in:
@@ -168,3 +168,79 @@ def test_agent_task_validation(agent_env, client):
|
||||
def test_agent_404(agent_env, client):
|
||||
assert client.get("/agent/ghost/status").status_code == 404
|
||||
assert client.get("/agent/ghost/events").json() == []
|
||||
|
||||
|
||||
# ---------------- 工作区选择(T23) ----------------
|
||||
|
||||
def test_agent_run_with_selected_workspace(agent_env, client, tmp_path):
|
||||
"""显式 workspace 应成为本次运行的工作目录(文件写进去,状态记录目录)。"""
|
||||
target = tmp_path / "my_project"
|
||||
target.mkdir()
|
||||
agent_env["set_script"]([
|
||||
{"content": None,
|
||||
"tool_calls": [{"id": "c1", "name": "write_file",
|
||||
"arguments": {"path": "build.py", "content": "print('ok')"}}],
|
||||
"usage": {"prompt_tokens": 10, "completion_tokens": 2}},
|
||||
{"content": "已写入 build.py。", "tool_calls": [], "usage": {}},
|
||||
])
|
||||
r = client.post("/agent", json={"task": "写 build.py", "workspace": str(target)})
|
||||
assert r.status_code == 200
|
||||
rid = r.json()["request_id"]
|
||||
info = _wait_done(agent_env["service"], rid)
|
||||
assert info.state == "done"
|
||||
assert (target / "build.py").read_text(encoding="utf-8") == "print('ok')"
|
||||
st = client.get(f"/agent/{rid}/status").json()
|
||||
assert st["workspace"] == str(target.resolve())
|
||||
|
||||
|
||||
def test_agent_workspace_not_exists(agent_env, client, tmp_path):
|
||||
r = client.post("/agent", json={"task": "t", "workspace": str(tmp_path / "ghost")})
|
||||
assert r.status_code == 400
|
||||
assert "不存在" in r.json()["detail"]
|
||||
|
||||
|
||||
def test_workspace_open_and_recent(agent_env, client, tmp_path):
|
||||
"""打开目录:设为当前 + 记入最近列表;支持 create 新建。"""
|
||||
d1 = tmp_path / "proj_a"
|
||||
d1.mkdir()
|
||||
r1 = client.post("/agent/workspaces", json={"path": str(d1)})
|
||||
assert r1.status_code == 200
|
||||
assert r1.json()["current"] == str(d1.resolve())
|
||||
assert str(d1.resolve()) in r1.json()["recent"]
|
||||
# create 新建
|
||||
new_dir = tmp_path / "proj_b" / "nested"
|
||||
r2 = client.post("/agent/workspaces", json={"path": str(new_dir), "create": True})
|
||||
assert r2.status_code == 200
|
||||
assert new_dir.is_dir()
|
||||
assert r2.json()["current"] == str(new_dir.resolve())
|
||||
# 不存在且不建 -> 400
|
||||
r3 = client.post("/agent/workspaces", json={"path": str(tmp_path / "nope")})
|
||||
assert r3.status_code == 400
|
||||
# 列表端点
|
||||
lst = client.get("/agent/workspaces").json()
|
||||
assert lst["current"] == str(new_dir.resolve())
|
||||
assert len(lst["recent"]) >= 2
|
||||
|
||||
|
||||
def test_fs_browse_endpoint(agent_env, client, tmp_path):
|
||||
r = client.get("/agent/fs", params={"path": str(tmp_path)})
|
||||
assert r.status_code == 200
|
||||
assert r.json()["ok"] is True
|
||||
assert "dirs" in r.json()
|
||||
r2 = client.get("/agent/fs", params={"path": str(tmp_path / "nope")})
|
||||
assert r2.json()["ok"] is False
|
||||
|
||||
|
||||
def test_agent_workspace_and_file_accept_root(agent_env, client, tmp_path):
|
||||
"""浏览/读取端点可指定 root(选中工作区)。"""
|
||||
other = tmp_path / "other_ws"
|
||||
other.mkdir()
|
||||
(other / "x.txt").write_text("外部工作区", encoding="utf-8")
|
||||
ls = client.get("/agent/workspace", params={"root": str(other)}).json()
|
||||
assert ls["ok"] is True
|
||||
assert any(e["name"] == "x.txt" for e in ls["entries"])
|
||||
f = client.get("/agent/file", params={"path": "x.txt", "root": str(other)}).json()
|
||||
assert f["content"] == "外部工作区"
|
||||
# 非法 root -> 400
|
||||
r = client.get("/agent/workspace", params={"root": str(tmp_path / "nope")})
|
||||
assert r.status_code == 400
|
||||
|
||||
Reference in New Issue
Block a user