diff --git a/src/daemon/spawner.py b/src/daemon/spawner.py index 23c1c53..bcd1530 100644 --- a/src/daemon/spawner.py +++ b/src/daemon/spawner.py @@ -59,96 +59,44 @@ curl -s -X POST http://localhost:8083/api/mail \\ ⚠️ 不要执行任何状态转换命令(标 working/done/review/failed 等),系统会自动处理。 """ -SPAWN_PROMPT_TEMPLATE = """你收到一个 v2.6 黑板任务。请严格按照下面的步骤执行。 +SPAWN_PROMPT_TEMPLATE = """{identity_section} -## 任务信息 +## 任务 +{title} +{description} -- 项目: {project_id} -- 任务ID: {task_id} -- 标题: {title} -- 描述: {description} -- 类型: {task_type} -- 优先级: {priority} -- 必要条件: {must_haves} +项目: {project_id} | ID: {task_id} +类型: {task_type} | 优先级: {priority} +验收标准: {must_haves} {retry_context} -## 状态机(你必须遵守的状态流转) +## 你能做什么 +- 读任务详情(含依赖、讨论、产出): GET {api_base}/projects/{project_id}/tasks/{task_id}?expand=all +- 读所有活跃任务: GET {api_base}/projects/{project_id}/tasks?status=working,claimed,review +- 写产出: POST {api_base}/projects/{project_id}/tasks/{task_id}/outputs +- 写评论/交接: POST {api_base}/projects/{project_id}/tasks/{task_id}/comments +- 更新状态: POST {api_base}/projects/{project_id}/tasks/{task_id}/status +- 创建子任务: POST {api_base}/projects/{project_id}/tasks +- 认领任务: POST {api_base}/projects/{project_id}/tasks/{{{{id}}}}/claim -``` -pending → claimed → working → review → done - │ │ - │ └→ pending(驳回重做) - ├──→ failed - ├──→ blocked - └──→ cancelled +## 约束 +- 完成后必须写产出物(output)并标 review,不能无产出就提交 +- 失败了标 failed 并写明原因 +- 产出物 handoff comment ≥ 50 字符(用于系统验证) +- 禁止使用 sessions_send 直接发消息(用 Mail API 或黑板 comment) +- 安全红线: {guardrails_summary} + +### API 请求体示例 +写产出: POST .../outputs +```json +{{{{"agent": "{agent_id}", "content_type": "code", "title": "产出标题", "content_path": "/path/to/file", "summary": "简要说明"}}}} ``` -你当前处于 **{current_status}** 状态。 - -## 执行步骤 - -### 步骤 1: 开始工作 - -立即调 API 标记你已开始: -```bash -curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/status \ - -H 'Content-Type: application/json' \ - -d '{{"status": "working", "agent": "{agent_id}"}}' +写评论: POST .../comments +```json +{{{{"author": "{agent_id}", "body": "评论内容(≥50字符)", "comment_type": "handoff"}}}} ``` - -### 步骤 2: 执行任务 - -根据任务描述完成你的工作(编码/回测/数据检查/审查等)。 - -### 步骤 3: 写入产出 - -⚠️ 这一步是必须的!不写产出 = 任务没完成。 - -```bash -curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/outputs \ - -H 'Content-Type: application/json' \ - -d '{{"agent": "{agent_id}", "type": "<产出类型>", "title": "<产出标题>", "content": "<你的产出内容>", "summary": "<简要说明>"}}' -``` - -**type 必须是以下之一**: code, document, data, config, other - -如果产出太长,可以写文件后用路径引用: -```bash -curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/outputs \ - -H 'Content-Type: application/json' \ - -d '{{"agent": "{agent_id}", "type": "code", "title": "main.py", "content_path": "/path/to/file.py", "summary": "主程序"}}' -``` - -### 步骤 4: 提交完成或标记失败 - -✅ 成功完成: -```bash -curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/status \ - -H 'Content-Type: application/json' \ - -d '{{"status": "{completion_status}", "agent": "{agent_id}"}}' -``` - -❌ 无法完成: -```bash -curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/status \ - -H 'Content-Type: application/json' \ - -d '{{"status": "failed", "agent": "{agent_id}", "detail": "<失败原因>"}}' -``` - -## Fallback(API 调用失败时) - -如果 API 失败 2 次,尝试: -```bash -curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/status \ - -H 'Content-Type: application/json' \ - -d '{{"status": "failed", "agent": "{agent_id}", "detail": "API回写失败,产出在本地文件"}}' -``` - -## 参考链接 -- 查看任务完整信息: GET http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}?expand=all -- 写评论: POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/comments {{"author": "{agent_id}", "body": "..."}} -- 完整 API 契约: docs/design/agent-api-contract.md """ @@ -340,7 +288,10 @@ class AgentSpawner: # Fallback: 使用硬编码模板 # mail 任务直接 done,不走 review completion_status = "done" if project_id == "_mail" else "review" + identity_section = self._inject_agent_identity(agent_id) + guardrails_summary = self._get_guardrails_summary() return SPAWN_PROMPT_TEMPLATE.format( + identity_section=identity_section, project_id=project_id, task_id=task_id, title=title, @@ -349,11 +300,10 @@ class AgentSpawner: priority=priority, must_haves=must_haves or "(无)", agent_id=agent_id, - api_host=self.api_host, - api_port=self.api_port, - current_status=current_status or "claimed", + api_base=f"http://{self.api_host}:{self.api_port}/api", retry_context=retry_context or "", completion_status=completion_status, + guardrails_summary=guardrails_summary, ) def _build_api_section(self, project_id: str, task_id: str,