[moz] impl(§22): P0 Phase 1 Discussion Broadcast #124
+43
-30
@@ -103,7 +103,7 @@ SPAWN_PROMPT_TEMPLATE = """{identity_section}
|
||||
"""
|
||||
|
||||
|
||||
DISCUSSION_PROMPT_TEMPLATE = """你被 spawn 来参与讨论。这是一个四相循环的讨论环节。
|
||||
DISCUSSION_PROMPT_TEMPLATE = """你被 spawn 来参与 Gitea Issue 讨论。
|
||||
|
||||
## 讨论主题
|
||||
|
||||
@@ -119,14 +119,19 @@ DISCUSSION_PROMPT_TEMPLATE = """你被 spawn 来参与讨论。这是一个四
|
||||
|
||||
## 你必须做什么
|
||||
|
||||
读完需求后,在黑板 comment 回应(必须,不是可选):
|
||||
读完需求后,在 Gitea Issue comment 回应(必须,不是可选):
|
||||
|
||||
1.【定位】这个需求和你有什么关系?你的专业能力能贡献什么?
|
||||
2.【建议】你对实现方案有什么建议?(技术选型、数据来源、实现路径)
|
||||
3.【认领】如果你需要参与,创建 sub task 并在 parent task comment 注册:
|
||||
- 创建 sub task: POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks
|
||||
body: {{"title": "...", "description": "...", "task_type": "...", "parent_task": "{task_id}", "must_haves": "{{\"capability\": \"...\"}}"}}
|
||||
- 创建后在 parent task comment: "[你的角色名] 我创建了 sub: 任务名,我负责 简述"
|
||||
3.【认领】如果你需要参与,创建 sub Issue 并在 parent Issue comment 注册:
|
||||
- 创建 sub Issue:
|
||||
```bash
|
||||
curl -X POST http://192.168.2.154:3000/api/v1/repos/{repo}/issues \
|
||||
-H "Authorization: token <your-token>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{{"title": "[moz][sub][parent #{issue_number}] 任务名", "body": "Parent: #{issue_number}\n## 任务\n...", "assignees": ["{agent_id}"]}}'
|
||||
```
|
||||
- 创建后在 parent Issue comment: "[角色名] 我创建了 sub Issue #N: 任务名,我负责 简述"
|
||||
4.【风险】如果你发现风险、不合理的假设、或遗漏的环节,直接提出
|
||||
|
||||
⚠️ 每个 agent 必须 comment。即使你认为和自己无关,也要说明原因——这证明你读过并思考过了。
|
||||
@@ -139,33 +144,28 @@ DISCUSSION_PROMPT_TEMPLATE = """你被 spawn 来参与讨论。这是一个四
|
||||
例:[关羽] 这个策略需要风控,连亏 3 天应暂停。
|
||||
例:[赵云] 数据已就绪,2024-08 缺失已补齐。
|
||||
|
||||
## 黑板 API
|
||||
## Gitea API
|
||||
|
||||
- 读黑板:GET http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}?expand=all
|
||||
- 写 comment:POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/comments
|
||||
body: {{"author": "{agent_id}", "body": "内容"}}
|
||||
- 创建 sub task:POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks
|
||||
- 认领任务:POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{{sub_task_id}}/claim
|
||||
- 读 Issue: GET http://192.168.2.154:3000/api/v1/repos/{repo}/issues/{issue_number}
|
||||
- 读 Issue comments: GET http://192.168.2.154:3000/api/v1/repos/{repo}/issues/{issue_number}/comments
|
||||
- 写 comment: POST http://192.168.2.154:3000/api/v1/repos/{repo}/issues/{issue_number}/comments
|
||||
body: {{"body": "内容"}}
|
||||
- 创建 sub Issue: POST http://192.168.2.154:3000/api/v1/repos/{repo}/issues
|
||||
|
||||
## 行为准则
|
||||
|
||||
1. **你是自主的。**读黑板、思考、行动,不要等指令。
|
||||
2. **不重复别人的工作。**动手前先读黑板看谁在做什么(Separation)。
|
||||
3. **保持方向对齐。**你的产出方向和 parent goal 对齐,不确定时 @pangtong-fujunshi(Alignment)。
|
||||
4. **产出可共享。**产出写入黑板,让其他人能看到你的成果(Cohesion)。
|
||||
5. **不越界。**安全红线不要碰,超出能力的 @ 庞统升级(Boundary)。
|
||||
6. **随时讨论。**执行过程中需要协作时 @ 对应 Agent,讨论是灵活的不是固定阶段的。
|
||||
1. **你是自主的。** 读 Issue、思考、行动,不要等指令。
|
||||
2. **不重复别人的工作。** 动手前先读 Issue comment 看谁在做什么(Separation)。
|
||||
3. **保持方向对齐。** 你的产出方向和 parent goal 对齐,不确定时 @pangtong-fujunshi(Alignment)。
|
||||
4. **产出可共享。** 产出写入 Gitea Issue/PR,让其他人能看到你的成果(Cohesion)。
|
||||
5. **不越界。** 安全红线不要碰,超出能力的 @ 庞统升级(Boundary)。
|
||||
6. **随时讨论。** 执行过程中需要协作时 @ 对应 Agent,讨论是灵活的不是固定阶段的。
|
||||
|
||||
## 讨论完成后
|
||||
|
||||
- 如果讨论收敛到可执行的任务,直接创建 sub task
|
||||
- 如果有分歧或不确定,在黑板上写 comment @ 庞统裁决
|
||||
- 标记完成:
|
||||
```bash
|
||||
curl -X POST http://{api_host}:{api_port}/api/projects/{project_id}/tasks/{task_id}/status \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{{"status": "done", "agent": "{agent_id}"}}'
|
||||
```
|
||||
- 如果讨论收敛到可执行的任务,直接创建 sub Issue(assign 自己)
|
||||
- 如果有分歧或不确定,在 Issue comment @pangtong-fujunshi 裁决
|
||||
- 标记完成(在 parent Issue comment 写总结)
|
||||
"""
|
||||
|
||||
|
||||
@@ -407,9 +407,22 @@ curl -X POST http://{self.api_host}:{self.api_port}/api/projects/{project_id}/ta
|
||||
def _build_discussion_prompt(self, task_id: str, title: str,
|
||||
description: str, must_haves: str,
|
||||
project_id: str, agent_id: str) -> str:
|
||||
"""构建讨论类 spawn prompt(§3.3 框架 + Boids)"""
|
||||
"""构建讨论类 spawn prompt(§22.2 Gitea API 版本)"""
|
||||
goal_snapshot = description or title
|
||||
constraints = must_haves or "(无特殊约束)"
|
||||
|
||||
# 从 must_haves 解析 issue 上下文
|
||||
repo = "sanguo/sanguo_moziplus_v2"
|
||||
issue_number = ""
|
||||
constraints = "(无特殊约束)"
|
||||
try:
|
||||
meta = json.loads(must_haves) if must_haves else {}
|
||||
ctx = meta.get("context", {})
|
||||
repo = ctx.get("repo", repo)
|
||||
issue_number = str(ctx.get("issue_number", ""))
|
||||
if meta.get("steps"):
|
||||
constraints = "\n".join(meta["steps"])
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
pass
|
||||
|
||||
agent_identity = self._inject_agent_identity(agent_id)
|
||||
return DISCUSSION_PROMPT_TEMPLATE.format(
|
||||
@@ -419,8 +432,8 @@ curl -X POST http://{self.api_host}:{self.api_port}/api/projects/{project_id}/ta
|
||||
task_id=task_id,
|
||||
agent_id=agent_id,
|
||||
agent_identity=agent_identity,
|
||||
api_host=self.api_host,
|
||||
api_port=self.api_port,
|
||||
repo=repo,
|
||||
issue_number=issue_number,
|
||||
)
|
||||
|
||||
def _inject_agent_identity(self, agent_id: str) -> str:
|
||||
|
||||
+43
-2
@@ -1161,10 +1161,43 @@ Parent Task ID: {parent_task.id}
|
||||
if t.id not in self._broadcast_tracker:
|
||||
self._broadcast_tracker[t.id] = BroadcastRound(task_id=t.id)
|
||||
|
||||
# 分离 discussion tasks 和普通 claim tasks
|
||||
discussion_tasks = []
|
||||
claim_tasks = []
|
||||
for t in broadcastable:
|
||||
action_type = self._get_task_action_type(t)
|
||||
if action_type == "issue_discussion":
|
||||
discussion_tasks.append(t)
|
||||
else:
|
||||
claim_tasks.append(t)
|
||||
|
||||
spawned = []
|
||||
for agent_id in idle_agents:
|
||||
prompt = self._build_claim_prompt(
|
||||
agent_id, broadcastable, project_id)
|
||||
prompts_to_send = []
|
||||
|
||||
# discussion tasks: 每个 task 独立构建 discussion prompt
|
||||
for t in discussion_tasks:
|
||||
disc_prompt = self.spawner._build_discussion_prompt(
|
||||
task_id=t.id,
|
||||
title=t.title,
|
||||
description=t.description or "",
|
||||
must_haves=t.must_haves or "",
|
||||
project_id=project_id,
|
||||
agent_id=agent_id,
|
||||
)
|
||||
prompts_to_send.append(disc_prompt)
|
||||
|
||||
# claim tasks: 按原逻辑批量构建 claim prompt
|
||||
if claim_tasks:
|
||||
claim_prompt = self._build_claim_prompt(
|
||||
agent_id, claim_tasks, project_id)
|
||||
prompts_to_send.append(claim_prompt)
|
||||
|
||||
# 合并 prompt(如果有多种类型)
|
||||
if not prompts_to_send:
|
||||
continue
|
||||
prompt = "\n\n---\n\n".join(prompts_to_send)
|
||||
|
||||
try:
|
||||
session_id = await self.spawner.spawn_full_agent(
|
||||
agent_id=agent_id,
|
||||
@@ -1187,6 +1220,14 @@ Parent Task ID: {parent_task.id}
|
||||
|
||||
return spawned
|
||||
|
||||
def _get_task_action_type(self, task) -> str:
|
||||
"""从 task.must_haves JSON 中提取 action_type"""
|
||||
try:
|
||||
meta = json.loads(task.must_haves) if task.must_haves else {}
|
||||
return meta.get("action_type", "")
|
||||
except (json.JSONDecodeError, TypeError, AttributeError):
|
||||
return ""
|
||||
|
||||
def _build_claim_prompt(self, agent_id: str, tasks: list,
|
||||
project_id: str) -> str:
|
||||
"""#03: 广播认领 prompt(身份+专长注入)"""
|
||||
|
||||
Reference in New Issue
Block a user