From f30165f21708585f443acd0307eba4b812215d76 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Thu, 21 May 2026 00:14:10 +0800 Subject: [PATCH] auto-sync: 2026-05-21 00:14:10 --- src/api/blackboard_routes.py | 55 ++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/api/blackboard_routes.py b/src/api/blackboard_routes.py index fc98cb2..96660a0 100644 --- a/src/api/blackboard_routes.py +++ b/src/api/blackboard_routes.py @@ -66,13 +66,32 @@ async def get_task(project_id: str, task_id: str, @router.post("/tasks") async def create_task(project_id: str, body: Dict[str, Any]): bb = _bb(project_id) - # v2.8: title 为空时自动生成 + # ID: 后端生成 {project_id_prefix}-{date}-{seq} + task_id = body.get("id") + if not task_id: + import re + from datetime import datetime + prefix = re.sub(r'[^a-z0-9]', '-', project_id.lower()).strip('-')[:20] + date_str = datetime.now().strftime('%Y%m%d') + # seq: 查当前项目最大 seq + try: + max_id_row = bb._conn.execute( + "SELECT id FROM tasks WHERE id LIKE ? ORDER BY id DESC LIMIT 1", + (f"{prefix}-{date_str}-%",) + ).fetchone() + seq = int(max_id_row[0].split('-')[-1]) + 1 if max_id_row else 1 + except Exception: + seq = 1 + task_id = f"{prefix}-{date_str}-{seq:04d}" + + # Title: LLM 生成(如果前端没传) title = body.get("title", "") if not title or not title.strip(): desc = body.get("description", "") or "" - title = (desc[:30] + "…") if len(desc) > 30 else (desc or "新军令") + title = await _generate_title(desc) or ((desc[:30] + "…") if len(desc) > 30 else (desc or "新军令")) + task = Task( - id=body["id"], title=title, + id=task_id, title=title, description=body.get("description"), task_type=body.get("task_type", "coding"), priority=body.get("priority", 5), @@ -88,6 +107,36 @@ async def create_task(project_id: str, body: Dict[str, Any]): return {"ok": True, "task_id": task.id, "title": task.title} +async def _generate_title(description: str) -> str | None: + """调用 LLM 生成简短标题""" + if not description or len(description) < 5: + return None + try: + from openai import OpenAI + import os + client = OpenAI( + base_url=os.environ.get("OPENAI_BASE_URL", "https://open.bigmodel.cn/api/paas/v4"), + api_key=os.environ.get("OPENAI_API_KEY", ""), + ) + resp = client.chat.completions.create( + model=os.environ.get("MOZIPLUS_TITLE_MODEL", "glm-4-flash"), + messages=[ + {"role": "system", "content": "你是一个任务标题生成器。根据用户的需求描述,生成一个简洁的中文标题(5-15字),只输出标题,不要任何其他内容。"}, + {"role": "user", "content": description[:500]}, + ], + max_tokens=50, + temperature=0.3, + timeout=10, + ) + title = resp.choices[0].message.content.strip().strip('"').strip("'") + if title and len(title) <= 30: + return title + except Exception as e: + import logging + logging.getLogger("moziplus-v2").warning(f"Title generation failed: {e}") + return None + + @router.get("/tasks/{task_id}/progress") async def task_progress(project_id: str, task_id: str): """Task Stage 进度(含子 Task 统计)"""