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:
+16
-8
@@ -32,10 +32,13 @@ STATE_DONE = "done"
|
||||
STATE_FAILED = "failed"
|
||||
|
||||
AGENT_SYSTEM_PROMPT = (
|
||||
"你是端云协同 LLM 系统中的智能体(Agent)。你拥有工作区文件工具:"
|
||||
"list_dir(列目录)、read_file(读文件)、write_file(写文件)。"
|
||||
"像程序员助手一样工作:先列目录/读文件了解现状,需要时再写文件;"
|
||||
"任务完成或给出结论后,直接输出给用户的最终答复(中文,不要再调用工具)。"
|
||||
"你是端云协同 LLM 系统中的智能体(Agent),正在操作用户选择的**真实项目工作目录**。"
|
||||
"你拥有的工具:list_dir(列目录)、read_file(读文件)、write_file(写文件/新建)、"
|
||||
"edit_file(精确替换编辑:old_string 须唯一匹配)、search_files(跨文件搜索内容)、"
|
||||
"run_command(执行 shell 命令,仅当系统开启 allow_shell 时可用,否则不要尝试)。"
|
||||
"像编程助手一样工作:先列目录/搜索了解项目结构,读文件核对原文后再用 edit_file 小步修改"
|
||||
"(或 write_file 新建),需要时运行命令验证。任务完成或给出结论后,"
|
||||
"直接输出给用户的最终答复(中文,不要再调用工具)。"
|
||||
)
|
||||
|
||||
|
||||
@@ -125,6 +128,7 @@ class AgentRunInfo:
|
||||
prompt_tokens: int = 0
|
||||
completion_tokens: int = 0
|
||||
pool_id: str = ""
|
||||
workspace: str = "" # 本次运行使用的工作区根目录(绝对路径)
|
||||
asyncio_task: Optional[asyncio.Task] = field(default=None, repr=False)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
@@ -141,6 +145,7 @@ class AgentRunInfo:
|
||||
"prompt_tokens": self.prompt_tokens,
|
||||
"completion_tokens": self.completion_tokens,
|
||||
"pool_id": self.pool_id,
|
||||
"workspace": self.workspace,
|
||||
}
|
||||
|
||||
|
||||
@@ -163,12 +168,13 @@ class AgentService:
|
||||
return self._dir(request_id) / "status.json"
|
||||
|
||||
# ---------- 注册与查询 ----------
|
||||
def register(self, request_id: str, task: str, model: str, pool_id: str) -> Optional[AgentRunInfo]:
|
||||
def register(self, request_id: str, task: str, model: str, pool_id: str,
|
||||
workspace: str = "") -> Optional[AgentRunInfo]:
|
||||
running = [r for r in self._runs.values() if r.state == STATE_RUNNING]
|
||||
if len(running) >= self.max_running:
|
||||
return None
|
||||
info = AgentRunInfo(request_id=request_id, task=task, model=model,
|
||||
pool_id=pool_id, started_at=time.time())
|
||||
pool_id=pool_id, workspace=workspace, started_at=time.time())
|
||||
self._runs[request_id] = info
|
||||
self._dir(request_id).mkdir(parents=True, exist_ok=True)
|
||||
self._write_status(info)
|
||||
@@ -179,9 +185,11 @@ class AgentService:
|
||||
|
||||
# ---------- 执行 ----------
|
||||
async def run(self, info: AgentRunInfo, chat: Any, workspace_dir: str | Path,
|
||||
max_rounds: int = 8, token_cap: int = 0) -> None:
|
||||
max_rounds: int = 8, token_cap: int = 0,
|
||||
allow_shell: bool = False, shell_timeout_s: int = 20) -> None:
|
||||
"""执行智能体任务(由调用方包成后台协程)。"""
|
||||
tools = WorkspaceTools(workspace_dir)
|
||||
tools = WorkspaceTools(workspace_dir, allow_shell=allow_shell,
|
||||
shell_timeout_s=shell_timeout_s)
|
||||
loop = ToolLoop(tools, chat, max_rounds=max_rounds, token_cap=token_cap,
|
||||
on_event=self._make_event_writer(info))
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user