From 32cd8c2e8a125234f623f1c2e5d73fdff9aa2a47 Mon Sep 17 00:00:00 2001 From: ymq Date: Sun, 23 Aug 2026 21:24:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A8=A1=E5=9D=97=E6=8A=80=E8=83=BD?= =?UTF-8?q?=E5=85=A8=E6=96=87=E5=8A=A0=E8=BD=BD=E5=89=A5=E7=A6=BB=20frontm?= =?UTF-8?q?atter=EF=BC=8C=E5=AF=B9=E9=BD=90=E5=88=86=E5=B1=82=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 模块技能作为「项目模块」scope 注入时,目录层只放名字+描述, 全文层(load_skill)剥离 frontmatter 只返回正文,与 skill_loader. to_prompt_block 行为一致。 --- pipeline_service/agent_loop.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pipeline_service/agent_loop.py b/pipeline_service/agent_loop.py index 63d331f..fce2592 100644 --- a/pipeline_service/agent_loop.py +++ b/pipeline_service/agent_loop.py @@ -649,7 +649,9 @@ def _collect_module_skills(workspace_dir): 模块仓库自带 skill/SKILL.md(架构/数据模型/挂载函数/坑位),但这些不进 skill_loader 的静态文件树,导致项目角色不知道模块怎么用。这里运行时扫描,作为「项目模块」scope - 注入技能目录 + 支持 load_skill 加载全文。返回 [{name, description, content, path}]。 + 注入技能目录 + 支持 load_skill 加载全文。返回 [{name, description, body, path}]。 + 其中 body 是剥离 frontmatter 后的正文(对齐 skill_loader.to_prompt_block 的分层导入规范: + 目录层只放名字+描述,全文层剥离 frontmatter 只返回正文)。 """ modules = [] repos_dir = os.path.join(workspace_dir, 'repos') @@ -667,8 +669,14 @@ def _collect_module_skills(workspace_dir): fm = _parse_skill_frontmatter(content) name = (fm.get('name') or entry).strip() description = (fm.get('description') or '').strip() + # 剥离 frontmatter,只保留正文(对齐 skill_loader.to_prompt_block 行为) + body = content.strip() + if body.startswith("---"): + end = body.find("---", 3) + if end != -1: + body = body[end + 3:].strip() if not description: - for line in content.split("\n"): + for line in body.split("\n"): line = line.strip() if line and not line.startswith("#") and not line.startswith("---"): description = line[:200] @@ -676,7 +684,7 @@ def _collect_module_skills(workspace_dir): modules.append({ "name": name, "description": description, - "content": content, + "body": body, "path": skill_file, "repo": entry, }) @@ -1228,12 +1236,13 @@ async def _load_skill_by_name(sor, project_id, role, org_id, name, file_path=Non merged = loader.get_merged(pipeline_id=pid, role=role, project_id=project_id, org_id=org_id or '0') if name not in merged: - # 项目模块技能(workspace repos/*/skill/SKILL.md)不在 skill_loader 静态树里,运行时补查 + # 项目模块技能(workspace repos/*/skill/SKILL.md)不在 skill_loader 静态树里,运行时补查。 + # 全文层对齐 skill_loader.to_prompt_block:剥离 frontmatter 只返回正文(body)。 try: ws = await _get_workspace_dir(sor, project_id) for m in _collect_module_skills(ws): if m['name'] == name or m['repo'] == name: - return f"## [项目模块] {m['name']}\n{m['description']}\n\n{m['content']}" + return f"## [项目模块] {m['name']}\n{m['description']}\n\n{m['body']}" except Exception: pass names = ", ".join(sorted(merged.keys())) or "(无可用技能)"