refactor: remove all hardcoded matching — LLM classifies project names from full list in env

This commit is contained in:
ymq 2026-08-09 23:12:47 +08:00
parent d4d59aa97e
commit 98d4f5e8ad

View File

@ -73,25 +73,10 @@ def _guess_role(title):
return 'develop'
async def _find_project(sor, name):
"""Match project by name. Exact first, then substring. Returns (record, match_type)."""
"""Exact match only — LLM has full project list in env and should pick exact name."""
if not name: return None
# Exact match
recs = await sor.sqlExe("SELECT id,name FROM sd_projects WHERE name=${n}$",{"n":name})
if recs: return recs[0]
# Substring match — find projects containing the keyword
kw = name.strip()
if len(kw) < 2: return None
allp = await sor.sqlExe("SELECT id,name FROM sd_projects ORDER BY created_at DESC",{})
matches = []
for r in (allp or []):
rn = (getattr(r,'name','') or '')
if kw in rn:
matches.append(r)
if len(matches) == 1:
return matches[0]
if len(matches) > 1:
return None # Ambiguous — caller should report options
return None
return recs[0] if recs else None
async def _load_ctx(sor, uid):
recs = await sor.sqlExe("SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$",{"u":uid})
@ -221,14 +206,8 @@ async def _exec_tool(sor, tool, params, ctx, uid, org_id):
return '可用项目:\n'+'\n'.join(lines)
proj = await _find_project(sor, name)
if not proj:
# Check if ambiguous (multiple substring matches)
kw = name.strip()
allp2 = await sor.sqlExe("SELECT name FROM sd_projects ORDER BY created_at DESC",{})
matches = [getattr(r,'name','') for r in (allp2 or []) if kw in (getattr(r,'name','') or '')]
if len(matches) > 1:
return 'FAIL: 多个匹配:\n'+'\n'.join(matches)
allp3 = await sor.sqlExe("SELECT name FROM sd_projects ORDER BY created_at DESC LIMIT 15",{})
return 'FAIL: 未找到。可用: '+', '.join([getattr(r,'name','') for r in (allp3 or [])])
allp = await sor.sqlExe("SELECT name FROM sd_projects ORDER BY created_at DESC LIMIT 15",{})
return 'FAIL: 未找到。可用: '+', '.join([getattr(r,'name','') for r in (allp or [])])
if proj.id == ctx['pid']:
return f'已在「{proj.name}」项目中,无需切换'
await _save_ctx(sor, uid, proj.id)
@ -466,7 +445,10 @@ if action == 'send_message':
return
repos_str = ', '.join([r['n'] for r in ctx['repos']]) or '无'
env_text = f"【当前项目: {ctx['pname'] or '未选择'}】— 所有操作在当前项目内完成\n工作空间: {ctx['ws'] or '未设置'} | 仓库: {repos_str}"
# Load all project names so LLM can match user's input
all_projects = await sor.sqlExe("SELECT name FROM sd_projects ORDER BY created_at DESC LIMIT 20",{})
proj_list = ', '.join([getattr(p,'name','') for p in (all_projects or [])])
env_text = f"【当前项目: {ctx['pname'] or '未选择'}】\n所有项目: {proj_list}\n工作空间: {ctx['ws'] or '未设置'} | 仓库: {repos_str}"
system = AGENT_PROMPT.replace('__TOOLS__',TOOLS_TEXT).replace('__ENV__',env_text)
msgs = [{"role":"system","content":system}]
for h in (await sor.sqlExe("SELECT role,content FROM pipeline_conversations WHERE created_by=${u}$ ORDER BY created_at ASC LIMIT 20",{"u":uid}) or []):