diff --git a/wwwroot/api/cockpit_chat.dspy b/wwwroot/api/cockpit_chat.dspy index aab7aca..3eb6a5c 100644 --- a/wwwroot/api/cockpit_chat.dspy +++ b/wwwroot/api/cockpit_chat.dspy @@ -25,6 +25,43 @@ DEFAULT_SYSTEM_PROMPT = """你是一个专业的软件开发 Agent,名为「 - 环境部署和验证""" +def _load_skills(skills_dir): + """Scan skills_dir for SKILL.md files and return their content.""" + skills = [] + if not skills_dir: + return skills + try: + for name in os.listdir(skills_dir): + skill_path = os.path.join(skills_dir, name) + skill_md = os.path.join(skill_path, 'SKILL.md') + if os.path.isdir(skill_path) and os.path.isfile(skill_md): + try: + with open(skill_md, 'r') as f: + content = f.read() + # Truncate very large skills + if len(content) > 8000: + content = content[:8000] + '\n\n... (truncated)' + skills.append({'name': name, 'content': content}) + except Exception: + pass + except Exception: + pass + return skills + + +def _build_skills_prompt(skills): + """Build skill context string for injection into system prompt.""" + if not skills: + return '' + lines = ['\n\n## 可用的开发技能(Skills)\n'] + lines.append('以下是企业定义的开发规范和最佳实践,请在开发过程中严格遵循:\n') + for s in skills: + lines.append(f'### {s["name"]}') + lines.append(s['content']) + lines.append('') + return '\n'.join(lines) + + async def _load_agent_settings(sor, uid): """Load user's agent settings, return defaults if not set.""" recs = await sor.sqlExe( @@ -54,7 +91,7 @@ async def _load_context(sor, uid): {"uid": uid} ) ctx = {'project_id': '', 'iteration_id': '', 'project_name': '', 'iteration_name': '', - 'workspace_dir': '', 'workspace_root': '', 'skills_dir': '', 'repos': []} + 'workspace_dir': '', 'workspace_root': '', 'skills_dir': '', 'skills': [], 'repos': []} if recs: r = recs[0] ctx['project_id'] = getattr(r, 'current_project_id', '') or '' @@ -74,6 +111,9 @@ async def _load_context(sor, uid): if orgs: ctx['workspace_root'] = getattr(orgs[0], 'workspace_root', '') or '' ctx['skills_dir'] = getattr(orgs[0], 'skills_dir', '') or '' + # Load enterprise skills + if ctx['skills_dir']: + ctx['skills'] = _load_skills(ctx['skills_dir']) # Load repos repos = await sor.sqlExe( "SELECT repo_name, repo_url, default_branch, local_path FROM sd_project_repos WHERE project_id=${pid}$", @@ -442,7 +482,12 @@ if action == 'send_message': for t in tasks: try: - task_msgs = [{"role": "system", "content": settings['system_prompt']}] + # Build system prompt with skills injected + sp = settings['system_prompt'] + skills_prompt = _build_skills_prompt(ctx.get('skills', [])) + if skills_prompt: + sp = sp + skills_prompt + task_msgs = [{"role": "system", "content": sp}] prompt_parts = [f"请完成:{t.title}"] prompt_parts.append('\\n'.join(repo_lines)) prompt_parts.append("请在关联仓库中直接修改代码文件,完成后提供变更摘要。")