feat: agent definition v2 (registry, persistence, developerInstructions channel)

Registry: POST /tasks accepts agent_name, loading <name>.json
from repo-root agents/ (traversal-guarded, skill-pack re-validated);
agent and agent_name together is a 400. Persistence: tasks gains
agent_name/agent_version/agent_instructions (migrate + PG schema),
returned by GET /tasks; stored prompt stays clean. Channel: local
and docker dispatch pass --developer-instructions to host.py
dispatch -> create_thread(developerInstructions=...); run/fork do
not re-send. Cloud executor has no such channel, so the worker
falls back to the v1 marked header in the in-memory dispatch
prompt only (DB prompt stays clean). Goal/coordinator tasks
still reject instructions.

Tests: test_agent_def_v2.py (7 tests) + updated v1 suite.
This commit is contained in:
host committed 2026-11-04 18:01:44 +00:00
1 parent 7bb3c37a10
commit 1672ab9ff2
8 files changed
+361 -35

No files matched your search

+13 -5
View File
@@ -1,4 +1,6 @@
"""声明式 agent 定义 v1 单测:解析、校验、解析到任务字段、建任务入口。
"""声明式 agent 定义 v1/v2 单测:解析、校验、解析到任务字段、建任务入口。
v2 改动:prompt 不再拼头,指令落库(见 test_agent_def_v2.py)。
运行(在仓库根目录下):
python3 -m unittest discover -s cloud/tests -p "test_agent_def.py" -v
@@ -168,7 +170,9 @@ class ServerAgentTestCase(unittest.TestCase):
self.assertEqual(status, 200)
return data["tasks"]
def test_agent_fills_fields_and_header(self):
def test_agent_fills_fields_and_stores_instructions(self):
# v2:prompt 保持干净,指令落库,不再拼头(v1 行为已
# 被 v2 替换,见 agent_def.py 的 v2 边界说明)。
status, task = self._req("POST", "/tasks", {
"project_id": self.project["id"], "prompt": "do research",
"agent": _agent()}, self.owner_key)
@@ -179,10 +183,14 @@ class ServerAgentTestCase(unittest.TestCase):
self.assertEqual(task["executor"], "docker")
self.assertEqual(task["agent"]["name"], "research-brief")
self.assertEqual(task["agent"]["skills"], ["live-info"])
self.assertEqual(task["agent_name"], "research-brief")
self.assertEqual(task["agent_version"], "v1")
self.assertEqual(task["agent_instructions"],
"Cite sources and dates.")
stored = self._list_tasks()[0]
self.assertTrue(stored["prompt"].startswith(
"[Agent: research-brief v1]\nCite sources and dates.\n\n"))
self.assertTrue(stored["prompt"].endswith("do research"))
self.assertEqual(stored["prompt"], "do research")
self.assertEqual(stored["agent_instructions"],
"Cite sources and dates.")
def test_explicit_body_wins_over_agent(self):
status, task = self._req("POST", "/tasks", {