105 lines
3.6 KiB
Python
105 lines
3.6 KiB
Python
"""
|
||
pipeline-service: slash_commands — 通用 slash 命令(core 内核,产线无关)
|
||
|
||
handler 签名:async def handler(args, ctx) -> str
|
||
ctx = {project_id, user_id, pipeline_id, workspace_dir, model_name, config, executor}
|
||
|
||
通用 slash 命令(任何产线都可用):/help /status /reset /tools /skills /model
|
||
产线 slash 命令(SDLC 的 /tasks /diagnose 等)在 sdlc_ability 注册。
|
||
"""
|
||
|
||
import json
|
||
import logging
|
||
|
||
from pipeline_core import SlashCommand, register_slash_command, get_slash_commands
|
||
|
||
logger = logging.getLogger("pipeline.slash_commands")
|
||
|
||
|
||
async def _h_help(args, ctx):
|
||
visible = get_slash_commands(ctx.get("pipeline_id", ""), ctx.get("role", ""))
|
||
lines = ["可用命令:"]
|
||
for name in sorted(visible):
|
||
cmd = visible[name]
|
||
hint = f" {cmd.args_hint}" if cmd.args_hint else ""
|
||
lines.append(f" /{name}{hint} — {cmd.description}")
|
||
return "\n".join(lines)
|
||
|
||
|
||
async def _h_status(args, ctx):
|
||
executor = ctx.get("executor")
|
||
if not executor:
|
||
return "ERROR: 无 executor 上下文"
|
||
# 复用能力包诊断工具(SDLC 产线 → diagnose_project;其他产线 → 通用状态)
|
||
r = await executor._execute_ability_tool("diagnose_project", {})
|
||
if r is None:
|
||
r = await executor._execute_ability_tool("check_progress", {})
|
||
if r is None:
|
||
return "当前项目无状态诊断工具"
|
||
return r
|
||
|
||
|
||
async def _h_reset(args, ctx):
|
||
executor = ctx.get("executor")
|
||
if not executor:
|
||
return "ERROR: 无 executor 上下文"
|
||
executor._msgs = []
|
||
executor._turn_count = 0
|
||
executor._tool_call_count = 0
|
||
executor._todos = []
|
||
return "OK: 会话已重置(清空历史 + 任务清单)"
|
||
|
||
|
||
async def _h_tools(args, ctx):
|
||
cfg = ctx.get("config")
|
||
if not cfg:
|
||
return "无工具配置"
|
||
lines = ["可用工具:"]
|
||
for t in cfg.tools:
|
||
if getattr(t, "enabled", True):
|
||
params = ", ".join(f"{k}" for k in (t.parameters or {}).keys())
|
||
lines.append(f" - {t.name}({params}) — {t.description}")
|
||
return "\n".join(lines)
|
||
|
||
|
||
async def _h_skills(args, ctx):
|
||
executor = ctx.get("executor")
|
||
if not executor or not executor._skill_loader:
|
||
return "技能系统未启用"
|
||
merged = executor._skill_loader.get_merged(
|
||
pipeline_id=ctx.get("pipeline_id", ""),
|
||
role=ctx.get("role", ""),
|
||
project_id=ctx.get("project_id", ""),
|
||
org_id=executor.org_id,
|
||
user_id=ctx.get("user_id", ""),
|
||
)
|
||
if not merged:
|
||
return "暂无可用技能"
|
||
# 限数量:只列前 20 个(按 scope + 名字排序),提示总数,避免 216 个全倒出来
|
||
items = sorted(merged.items(), key=lambda kv: (kv[1].scope, kv[0]))
|
||
lines = [f"可用技能(共 {len(items)} 个,仅列前 20,按需用 load_skill 加载正文):"]
|
||
for name, s in items[:20]:
|
||
lines.append(f" - [{s.scope}] {name} — {s.description[:100]}")
|
||
return "\n".join(lines)
|
||
|
||
|
||
async def _h_model(args, ctx):
|
||
return f"当前模型: {ctx.get('model_name', '未知')}"
|
||
|
||
|
||
# ── 注册通用 slash 命令 ──
|
||
|
||
def register_general_slash_commands():
|
||
for cmd in [
|
||
SlashCommand("help", "列出可用命令", _h_help, "global"),
|
||
SlashCommand("status", "诊断当前项目状态", _h_status, "global"),
|
||
SlashCommand("reset", "重置会话(清空历史)", _h_reset, "global"),
|
||
SlashCommand("tools", "列出可用工具", _h_tools, "global"),
|
||
SlashCommand("skills", "列出可用技能", _h_skills, "global"),
|
||
SlashCommand("model", "显示当前模型", _h_model, "global"),
|
||
]:
|
||
register_slash_command(cmd)
|
||
|
||
|
||
register_general_slash_commands()
|