feat: 接线feature工具到sdlc_ability(propose/list/approve/reject/verify 5工具+handler+ID前缀兜底)
This commit is contained in:
parent
df6f5cce34
commit
4abe93a8f9
@ -121,6 +121,36 @@ SDL_TOOLS = [
|
||||
parameters={"title": "Bug标题", "description": "描述", "severity": "严重程度"},
|
||||
category="task",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="propose_feature",
|
||||
description="提出新功能/需求(用户提出新需求或需求拆解时用)",
|
||||
parameters={"feature_name": "功能名称", "description": "功能描述", "iteration_id": "所属迭代(可选)", "priority": "优先级(P0/P1/P2/P3,默认P2)"},
|
||||
category="feature",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="list_features",
|
||||
description="查看当前项目功能列表",
|
||||
parameters={"status": "按状态筛选(可选)"},
|
||||
category="feature",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="approve_feature",
|
||||
description="审批通过功能(需求评审通过)",
|
||||
parameters={"feature_id": "功能ID"},
|
||||
category="feature",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="reject_feature",
|
||||
description="驳回功能(附意见)",
|
||||
parameters={"feature_id": "功能ID", "comment": "驳回意见"},
|
||||
category="feature",
|
||||
),
|
||||
ToolDefinition(
|
||||
name="verify_feature",
|
||||
description="验证功能(验收通过)",
|
||||
parameters={"feature_id": "功能ID"},
|
||||
category="feature",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@ -135,7 +165,8 @@ SDL_PROMPT = """你是「开发产线」的驾驶舱 agent,负责软件项目
|
||||
- 用户报告异常/故障 → 先用 diagnose_project 定位根因,再用 task_detail 查详情。
|
||||
- 仓库管理 → add_repo / list_repos / clone_repo。
|
||||
- 发现卡点(任务卡死、审核超时、失败、僵尸 claimed_by)时,主动定位根因并推动修复。
|
||||
- 发现「待回答问题」> 0 或角色提问时,加载 team-communication 技能按冒泡链处理(list_questions 列问题 → 能答则 answer_question → 不能答 escalate_question 沿冒泡路径转下一个处理方)。"""
|
||||
- 发现「待回答问题」> 0 或角色提问时,加载 team-communication 技能按冒泡链处理(list_questions 列问题 → 能答则 answer_question → 不能答 escalate_question 沿冒泡路径转下一个处理方)。
|
||||
- 功能/需求管理 → 用户提新需求时 propose_feature;查功能清单 list_features;需求评审/验收时 approve_feature / reject_feature / verify_feature(状态机规范见 feature 技能)。"""
|
||||
|
||||
|
||||
# ── 产线角色集(可插拔,替代硬编码 ROLE_SPECIFICS/ROLE_ALIASES/ROLE_CHAIN) ──
|
||||
@ -602,6 +633,101 @@ async def _h_add_bug(sor, p, ctx):
|
||||
return f"OK: 已提交Bug: {title}"
|
||||
|
||||
|
||||
async def _resolve_feature_id(sor, fid):
|
||||
"""功能 ID 前缀兜底:精确匹配失败且入参≥6位时,用 LIKE 前缀解析回完整 ID。"""
|
||||
if not fid:
|
||||
return ""
|
||||
recs = await sor.sqlExe(
|
||||
"SELECT id FROM sd_features WHERE id=${fid}$", {"fid": fid})
|
||||
if recs:
|
||||
return getattr(recs[0], "id", "")
|
||||
if len(fid) >= 6:
|
||||
recs = await sor.sqlExe(
|
||||
"SELECT id FROM sd_features WHERE id LIKE ${prefix}$ LIMIT 1",
|
||||
{"prefix": fid + "%"})
|
||||
if recs:
|
||||
return getattr(recs[0], "id", "")
|
||||
return ""
|
||||
|
||||
|
||||
async def _h_propose_feature(sor, p, ctx):
|
||||
pid = ctx.get("project_id", "")
|
||||
if not pid:
|
||||
return "请先切换到项目"
|
||||
name = (p.get("feature_name", "") or "").strip()
|
||||
if not name:
|
||||
return "需要功能名称"
|
||||
from .feature_capability import propose_feature
|
||||
ok, fid = await propose_feature(
|
||||
project_id=pid,
|
||||
feature_name=name,
|
||||
description=p.get("description", "") or "",
|
||||
iteration_id=p.get("iteration_id", "") or "",
|
||||
priority=p.get("priority", "P2") or "P2",
|
||||
created_by=ctx.get("user_id", "") or "",
|
||||
who="agent.main_agent",
|
||||
)
|
||||
if not ok:
|
||||
return f"ERROR: {fid}"
|
||||
return f"OK: 已提出功能「{name}」(id={fid},状态 proposed)"
|
||||
|
||||
|
||||
async def _h_list_features(sor, p, ctx):
|
||||
pid = ctx.get("project_id", "")
|
||||
if not pid:
|
||||
return "请先切换到项目"
|
||||
status = (p.get("status", "") or "").strip()
|
||||
sql = "SELECT id, feature_name, status, priority, iteration_id FROM sd_features WHERE project_id=${pid}$"
|
||||
params = {"pid": pid}
|
||||
if status:
|
||||
sql += " AND status=${status}$"
|
||||
params["status"] = status
|
||||
sql += " ORDER BY created_at DESC LIMIT 30"
|
||||
recs = await sor.sqlExe(sql, params)
|
||||
if not recs:
|
||||
return "暂无功能"
|
||||
lines = []
|
||||
for r in recs:
|
||||
lines.append(
|
||||
f"- [{getattr(r, 'status', '?')}][{getattr(r, 'priority', '') or ''}] "
|
||||
f"{getattr(r, 'feature_name', '')} (id={getattr(r, 'id', '')})")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
async def _h_approve_feature(sor, p, ctx):
|
||||
fid = (p.get("feature_id", "") or "").strip()
|
||||
if not fid:
|
||||
return "需要功能ID"
|
||||
pid = ctx.get("project_id", "")
|
||||
fid = await _resolve_feature_id(sor, fid) or fid
|
||||
from .feature_capability import approve_feature
|
||||
ok, msg = await approve_feature(fid, pid, who="agent.main_agent")
|
||||
return f"OK: {msg}" if ok else f"ERROR: {msg}"
|
||||
|
||||
|
||||
async def _h_reject_feature(sor, p, ctx):
|
||||
fid = (p.get("feature_id", "") or "").strip()
|
||||
if not fid:
|
||||
return "需要功能ID"
|
||||
pid = ctx.get("project_id", "")
|
||||
fid = await _resolve_feature_id(sor, fid) or fid
|
||||
from .feature_capability import reject_feature
|
||||
ok, msg = await reject_feature(fid, pid, who="agent.main_agent",
|
||||
comment=p.get("comment", "") or "")
|
||||
return f"OK: {msg}" if ok else f"ERROR: {msg}"
|
||||
|
||||
|
||||
async def _h_verify_feature(sor, p, ctx):
|
||||
fid = (p.get("feature_id", "") or "").strip()
|
||||
if not fid:
|
||||
return "需要功能ID"
|
||||
pid = ctx.get("project_id", "")
|
||||
fid = await _resolve_feature_id(sor, fid) or fid
|
||||
from .feature_capability import verify_feature
|
||||
ok, msg = await verify_feature(fid, pid, who="agent.main_agent")
|
||||
return f"OK: {msg}" if ok else f"ERROR: {msg}"
|
||||
|
||||
|
||||
# ── 注册能力包 ──
|
||||
|
||||
SDL_HANDLERS = {
|
||||
@ -620,6 +746,11 @@ SDL_HANDLERS = {
|
||||
"clone_repo": _h_clone_repo,
|
||||
"check_progress": _h_check_progress,
|
||||
"add_bug": _h_add_bug,
|
||||
"propose_feature": _h_propose_feature,
|
||||
"list_features": _h_list_features,
|
||||
"approve_feature": _h_approve_feature,
|
||||
"reject_feature": _h_reject_feature,
|
||||
"verify_feature": _h_verify_feature,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user