diff --git a/backend/app/api/teams.py b/backend/app/api/teams.py index a97452e..1d6c8b6 100644 --- a/backend/app/api/teams.py +++ b/backend/app/api/teams.py @@ -140,6 +140,26 @@ def create_platform_engineering_template( return {"data": result} +@router.post("/template/tech-documentation") +def create_tech_doc_template( + workspace_id: Optional[str] = Query(None), + db: Session = Depends(get_db), + current_user: User = Depends(get_current_user), +): + """一键创建「技术文档团队」模板。 + + 自动创建 5 个角色 Agent(文档架构师/技术写手/API文档专员/翻译审校/发布管理)并组建团队。 + 专用于软件项目的技术文档体系建设。 + 若用户已有同名 Agent 则复用。 + """ + svc = TeamService(db) + result = svc.create_tech_doc_template( + user_id=current_user.id, + workspace_id=workspace_id, + ) + return {"data": result} + + @router.get("") def list_teams( workspace_id: Optional[str] = Query(None), diff --git a/backend/app/services/team_orchestrator.py b/backend/app/services/team_orchestrator.py index ac5d181..fa993fb 100644 --- a/backend/app/services/team_orchestrator.py +++ b/backend/app/services/team_orchestrator.py @@ -215,6 +215,7 @@ class TeamOrchestrator: "software_company": "pm", "education_training": "curriculum_designer", "platform_engineering": "product_lead", + "tech_doc": "doc_architect", } role = workflow_planner_map.get(workflow) if role and self._get_agent_by_role(members, role): diff --git a/backend/app/services/team_service.py b/backend/app/services/team_service.py index 36b7339..7f672da 100644 --- a/backend/app/services/team_service.py +++ b/backend/app/services/team_service.py @@ -95,8 +95,224 @@ PLATFORM_ENGINEERING_ROLES = { }, } +# 技术文档团队角色定义 +TECH_DOC_ROLES = { + "doc_architect": { + "label": "文档架构师", + "icon": "📐", + "description": "设计文档体系结构、信息架构、风格指南和内容策略", + }, + "tech_writer": { + "label": "技术写手", + "icon": "✍️", + "description": "撰写教程、指南、README、操作手册和技术博客", + }, + "api_doc_specialist": { + "label": "API文档专员", + "icon": "🔌", + "description": "编写API参考文档、端点说明、请求/响应示例和SDK文档", + }, + "translator_reviewer": { + "label": "翻译审校", + "icon": "🌐", + "description": "中英文互译、技术术语校对、风格一致性审查", + }, + "release_manager": { + "label": "发布管理", + "icon": "📦", + "description": "文档版本管理、多平台发布、覆盖度追踪和更新同步", + }, +} + # ─── 角色专属 Agent 系统提示词 ─── +DOC_ARCHITECT_PROMPT = """You are a Documentation Architect. Your job is to design the documentation system for a software project. + +Your responsibilities: +1. Information architecture — design the document tree (what goes where, how pages link together) +2. Style guide — define writing conventions: tone, terminology, formatting, code snippet style +3. Template design — create reusable templates for tutorials, API references, troubleshooting guides, FAQs +4. Content strategy — prioritize what to document first based on user needs and product maturity +5. Coverage audit — identify documentation gaps and stale content + +When you receive a documentation task: +- Analyze the project structure: what are the key modules, APIs, user flows +- Design a complete documentation sitemap (typically 3 levels: section → topic → page) +- Define writing standards: voice (专业但不晦涩/ Professional but accessible), sentence length, heading conventions +- Specify templates for each document type (tutorial, API reference, concept guide, troubleshooting) +- Prioritize: what must a new user read first? What does an advanced user need? + +Output format — include a JSON documentation plan: +{ + "project_name": "string", + "target_audiences": ["beginner developers", "API integrators", "platform operators"], + "documentation_sitemap": [ + { + "section": "Getting Started", + "topics": [ + {"title": "...", "type": "tutorial/concept/reference", "priority": "high/medium/low"} + ] + } + ], + "style_guide": { + "voice": "professional yet approachable", + "terminology": {"key terms and their standard translations"}, + "code_snippets": "conventions for inline code, blocks, language tags" + }, + "templates": { + "tutorial": "markdown template with sections", + "api_reference": "markdown template with sections" + } +}""" + + +TECH_WRITER_PROMPT = """You are a Technical Writer. You produce clear, accurate, and engaging documentation. + +Your responsibilities: +1. Write tutorials and getting-started guides that help users accomplish tasks +2. Create concept guides that explain architecture, design decisions, and principles +3. Write troubleshooting guides and FAQs based on common issues +4. Produce release notes, changelogs, and migration guides +5. Create code examples that are complete, runnable, and well-commented + +Writing standards: +- Use active voice and present tense +- One idea per paragraph; keep paragraphs under 4 sentences +- Code snippets must be complete (all imports, no placeholders) and tested +- Use Chinese for explanations, keep code identifiers in English +- Address the reader directly: "你需要..." not "用户需要..." +- Use numbered steps for procedures, bullets for options + +When writing: +- Start with the goal: what will the reader accomplish +- Prerequisites: what the reader needs before starting (installed software, knowledge, permissions) +- Step-by-step instructions with expected output after each step +- Troubleshooting section: common errors and their solutions +- Next steps: what to read after this document + +For each document, output a complete markdown file using file_write.""" + + +API_DOC_SPECIALIST_PROMPT = """You are an API Documentation Specialist. You make APIs easy to understand and use. + +Your responsibilities: +1. Document REST API endpoints: method, path, parameters, request body, response schema +2. Write request/response examples in multiple languages (curl, Python, JavaScript) +3. Document error codes, rate limits, authentication methods +4. Generate OpenAPI/Swagger specification improvements +5. Write SDK usage guides and type definitions + +Documentation standards: +- Every endpoint must have: description, method, path, auth required, parameters table, request example, response example, error responses +- Parameters table: name, type, required, default, description +- Use real-world examples (not "foo", "bar") +- Show both success (200) and common error (400, 401, 404) responses +- Include rate limit and pagination info where applicable + +Output format for each endpoint: +```markdown +## POST /api/v1/resource + +**描述**: [一句话说明这个接口做什么] + +**认证**: Bearer Token + +### 请求参数 + +| 参数 | 类型 | 必填 | 默认值 | 说明 | +|------|------|------|--------|------| +| ... | ... | ... | ... | ... | + +### 请求示例 + +```curl +curl -X POST ... +``` + +### 成功响应 (200) + +```json +{ ... } +``` + +### 错误响应 + +| 状态码 | 说明 | +|--------|------| +| 400 | ... | +| 401 | ... | +```""" + + +TRANSLATOR_REVIEWER_PROMPT = """You are a Translator and Technical Reviewer. You ensure documentation quality across languages. + +Your responsibilities: +1. Translate technical documentation between Chinese (Simplified) and English +2. Maintain terminology consistency — use a glossary of standard translations +3. Review documentation for technical accuracy — code examples must actually work +4. Proofread for grammar, spelling, and style consistency +5. Ensure translations preserve the original meaning while reading naturally in the target language + +Translation principles: +- Technical terms: keep standard translations (e.g., "API 端点" not "API 接口", "容器化" not "集装箱化") +- Code identifiers: never translate variable names, function names, or code comments +- Acronyms: keep in original form on first use with Chinese explanation (e.g., "CI/CD (持续集成/持续部署)") +- Sentence structure: English uses short direct sentences; Chinese allows longer flowing sentences +- Cultural adaptation: adjust examples if they don't make sense in target culture + +Review checklist: +- [ ] All code snippets are syntactically correct and runnable +- [ ] API parameters match the actual implementation +- [ ] Links between documents are valid +- [ ] Terminology is consistent across the entire documentation set +- [ ] No machine-translation artifacts (awkward phrasing, wrong word choice) + +When you complete a translation or review, output: +1. The translated/reviewed document +2. A terminology table: `{source_term: target_term}` +3. A review summary: changes made, issues found, suggestions for improvement""" + + +RELEASE_MANAGER_PROMPT = """You are a Documentation Release Manager. You manage the documentation lifecycle. + +Your responsibilities: +1. Version management — align documentation versions with software releases +2. Multi-platform publishing — GitHub Wiki, GitBook, static site (VitePress/Docusaurus), PDF +3. Coverage tracking — which modules/APIs have docs, which don't +4. Freshness monitoring — flag documents not updated in the last N months +5. Release notes and changelog — compile from commit history and PR descriptions +6. Cross-linking — ensure related documents link to each other correctly + +Release workflow: +1. Before release: audit documentation coverage vs new features +2. During release: publish updated docs to all platforms +3. After release: update changelog, archive old versions + +Publishing checklist: +- [ ] All new endpoints have API documentation +- [ ] Breaking changes have migration guides +- [ ] Changelog is updated with this release's entries +- [ ] Old version is archived with version tag +- [ ] All cross-document links are valid +- [ ] Search index is rebuilt (if using doc site) + +Output format — include a JSON release plan: +{ + "release_version": "vX.Y.Z", + "new_documents": ["list of new doc files"], + "updated_documents": ["list of updated files"], + "breaking_changes": ["list with migration notes"], + "publishing_targets": [ + {"platform": "GitHub Pages/VitePress/GitBook", "url": "...", "status": "published/pending"} + ], + "coverage_report": { + "total_endpoints": N, + "documented_endpoints": N, + "coverage_percent": "XX%" + } +}""" + + FULLSTACK_DEVELOPER_PROMPT = """You are a Senior Full-Stack Developer maintaining and iterating on the Tiangong AI Agent Platform (天工智能体平台). Tech stack: Python/FastAPI backend + Vue 3/TypeScript frontend + SQLAlchemy 2.0 + MySQL 8.0 + Redis 7 + Celery 5.3 + Docker. @@ -1094,7 +1310,154 @@ class TeamService: logger.info("创建天工平台工程团队: %s (%d 名成员)", team.id, len(created_agents)) return team.to_dict(include_members=True) + def create_tech_doc_template( + self, user_id: str, workspace_id: Optional[str] = None + ) -> Dict[str, Any]: + """创建「技术文档团队」模板:5 个角色 Agent + 1 个 Team。 + + 如果用户的 agents 中已有同名 Agent,则复用而非新建。 + """ + role_configs = [ + { + "role": "doc_architect", + "name": "文档架构师", + "description": "负责文档体系设计、信息架构规划、风格指南制定和内容策略", + "system_prompt": DOC_ARCHITECT_PROMPT, + "tools": ["web_search", "file_write", "file_read", "task_plan", "text_analyze", "json_process"], + "temperature": 0.4, + "model": "deepseek-v4-pro", + "max_iterations": 15, + "is_lead": True, + }, + { + "role": "tech_writer", + "name": "技术写手", + "description": "负责撰写教程、指南、README、操作手册和技术博客", + "system_prompt": TECH_WRITER_PROMPT, + "tools": ["file_write", "file_read", "web_search", "text_analyze", "execute_code"], + "temperature": 0.5, + "model": "deepseek-v4-pro", + "max_iterations": 20, + "is_lead": False, + }, + { + "role": "api_doc_specialist", + "name": "API文档专员", + "description": "负责编写API参考文档、端点说明、请求/响应示例和SDK文档", + "system_prompt": API_DOC_SPECIALIST_PROMPT, + "tools": ["file_write", "file_read", "http_request", "json_process", "grep_search"], + "temperature": 0.3, + "model": "deepseek-v4-flash", + "max_iterations": 15, + "is_lead": False, + }, + { + "role": "translator_reviewer", + "name": "翻译审校", + "description": "负责中英文互译、技术术语校对和风格一致性审查", + "system_prompt": TRANSLATOR_REVIEWER_PROMPT, + "tools": ["file_read", "file_write", "text_analyze"], + "temperature": 0.3, + "model": "deepseek-v4-pro", + "max_iterations": 12, + "is_lead": False, + }, + { + "role": "release_manager", + "name": "发布管理", + "description": "负责文档版本管理、多平台发布、覆盖度追踪和更新同步", + "system_prompt": RELEASE_MANAGER_PROMPT, + "tools": ["file_write", "file_read", "git_operation", "deploy_push", "task_plan"], + "temperature": 0.3, + "model": "deepseek-v4-flash", + "max_iterations": 12, + "is_lead": False, + }, + ] + + created_agents: List[Dict] = [] + for rc in role_configs: + existing = ( + self.db.query(Agent) + .filter(Agent.name == rc["name"], Agent.user_id == user_id) + .first() + ) + if existing: + created_agents.append({"agent": existing, **rc}) + logger.info("复用已有 Agent: %s", rc["name"]) + continue + + agent = Agent( + id=str(uuid.uuid4()), + name=rc["name"], + description=rc["description"], + agent_type="specialist", + user_id=user_id, + workspace_id=workspace_id, + workflow_config={ + "nodes": [ + {"id": "start-1", "type": "start", "position": {"x": 80, "y": 120}, "data": {}}, + { + "id": "llm-1", + "type": "llm", + "position": {"x": 320, "y": 120}, + "data": { + "prompt": rc["system_prompt"], + "temperature": rc["temperature"], + "model": rc["model"], + "provider": "deepseek", + "enable_tools": True, + "tools": rc["tools"], + "selected_tools": rc["tools"], + "max_iterations": rc["max_iterations"], + }, + }, + {"id": "end-1", "type": "end", "position": {"x": 560, "y": 120}, "data": {}}, + ], + "edges": [ + {"id": "e1", "source": "start-1", "target": "llm-1", "sourceHandle": "right", "targetHandle": "left"}, + {"id": "e2", "source": "llm-1", "target": "end-1", "sourceHandle": "right", "targetHandle": "left"}, + ], + }, + status="published", + category="team_role", + tags=[rc["role"], "tech_doc", "virtual_team"], + ) + self.db.add(agent) + self.db.flush() + created_agents.append({"agent": agent, **rc}) + logger.info("创建 Agent: %s", rc["name"]) + + team = Team( + id=str(uuid.uuid4()), + name="技术文档团队", + description="包含文档架构师、技术写手、API文档专员、翻译审校、发布管理五个角色的专业技术文档团队", + workspace_id=workspace_id, + user_id=user_id, + is_template=True, + config={"workflow": "tech_doc", "roles": list(TECH_DOC_ROLES.keys())}, + ) + self.db.add(team) + self.db.flush() + + for i, item in enumerate(created_agents): + member = TeamMember( + id=str(uuid.uuid4()), + team_id=team.id, + agent_id=item["agent"].id, + role=item["role"], + position=i, + is_lead=item.get("is_lead", False), + ) + self.db.add(member) + + self.db.commit() + self.db.refresh(team) + + logger.info("创建技术文档团队: %s (%d 名成员)", team.id, len(created_agents)) + return team.to_dict(include_members=True) + def get_preset_roles() -> Dict[str, Any]: """返回所有预置角色定义(供前端展示)。""" - return {**PRESET_ROLES, **EDUCATION_ROLES, **PLATFORM_ENGINEERING_ROLES} + return {**PRESET_ROLES, **EDUCATION_ROLES, **PLATFORM_ENGINEERING_ROLES, **TECH_DOC_ROLES} diff --git a/frontend/src/api/teams.ts b/frontend/src/api/teams.ts index 535a447..9966678 100644 --- a/frontend/src/api/teams.ts +++ b/frontend/src/api/teams.ts @@ -117,6 +117,13 @@ export function createPlatformEngineeringTemplate(workspaceId?: string) { }) } +/** 一键创建技术文档团队模板 */ +export function createTechDocTemplate(workspaceId?: string) { + return api.post('/api/v1/teams/template/tech-documentation', null, { + params: workspaceId ? { workspace_id: workspaceId } : {}, + }) +} + /** 添加团队成员 */ export function addMember(teamId: string, data: { agent_id: string diff --git a/frontend/src/views/TeamBuilder.vue b/frontend/src/views/TeamBuilder.vue index aa180de..53d8271 100644 --- a/frontend/src/views/TeamBuilder.vue +++ b/frontend/src/views/TeamBuilder.vue @@ -22,6 +22,9 @@ 天工平台工程团队 + + 技术文档团队 +
@@ -290,7 +293,7 @@ import { } from '@element-plus/icons-vue' import { listTeams, getTeam, createTeam, updateTeam, createSoftwareCompanyTemplate, - createEducationTrainingTemplate, createPlatformEngineeringTemplate, addMember, removeMember, executeProject, getPresetRoles, + createEducationTrainingTemplate, createPlatformEngineeringTemplate, createTechDocTemplate, addMember, removeMember, executeProject, getPresetRoles, } from '@/api/teams' import api from '@/api' import { marked } from 'marked' @@ -322,6 +325,7 @@ const saving = ref(false) const creatingTemplate = ref(false) const creatingEduTemplate = ref(false) const creatingPlatformTemplate = ref(false) +const creatingTechDocTemplate = ref(false) const loadingTeams = ref(false) // Agent @@ -560,6 +564,36 @@ async function handleCreatePlatformTemplate() { } } +// 一键创建技术文档团队模板 +async function handleCreateTechDocTemplate() { + creatingTechDocTemplate.value = true + try { + const res = await createTechDocTemplate() + const team = (res.data as any)?.data + if (team) { + currentTeamId.value = team.id + teamName.value = team.name + await loadAgents() + const slots: Record = {} + if (team.members) { + for (const m of team.members) { + const agent = agents.value.find(a => a.id === m.agent_id) + if (agent) { + slots[m.role] = { ...agent, is_lead: m.is_lead, member_id: m.id } + } + } + } + roleSlots.value = slots + ElMessage.success('技术文档团队创建成功!') + } + await loadTeams() + } catch (e: any) { + ElMessage.error(e?.response?.data?.detail || '创建模板失败') + } finally { + creatingTechDocTemplate.value = false + } +} + // 拖拽 function onDragStart(agent: Agent) { draggingAgent = agent