fix(marketplace): address code review findings

- Fix str.format() crash when user input contains curly braces
- Fix Layer 2 passing str to find_best_agent (expects list[str])
- Fix AlignmentGuard fail-open on LLM audit failure (now fail-closed)
- Fix _config_reload_lock not initialized in create_app()
- Fix evolve_soul redundant reflector.reflect() call (reuse existing reflection)
- Fix test mocks using AsyncMock for sync find_best_agent method
- Remove unused _COMPLEXITY_CLASSIFY_PROMPT constant
This commit is contained in:
chiguyong 2026-06-10 19:21:40 +08:00
parent 8713636d50
commit bba394be38
6 changed files with 27 additions and 22 deletions

View File

@ -186,16 +186,6 @@ _CHAT_MODE_RE = re.compile(
re.IGNORECASE,
)
_COMPLEXITY_CLASSIFY_PROMPT = (
"Assess the complexity of the following user request on a scale of 0.0 to 1.0.\n"
"0.0 = trivial greeting / simple chat\n"
"0.3 = single-skill task (e.g. search, translate)\n"
"0.7 = multi-step or cross-domain task (e.g. market research + competitor analysis)\n"
"1.0 = highly complex, multi-agent collaboration needed\n\n"
'User request: "{content}"\n\n'
'Respond ONLY with a JSON object: {{"complexity": <float>}}'
)
class CostAwareRouter:
"""三层成本感知路由器。
@ -251,7 +241,13 @@ class CostAwareRouter:
if self._llm_gateway is None:
return 0.5
prompt = _COMPLEXITY_CLASSIFY_PROMPT.format(content=content)
prompt = (
'You are a complexity classifier. Rate the complexity of the user request on a scale of 0.0 to 1.0.\n'
'0.0 = trivial greeting, 0.3 = simple question, 0.5 = moderate task, '
'0.7 = complex multi-step task, 1.0 = very complex research task.\n\n'
f'User request: "{content}"\n\n'
'Respond ONLY with a JSON object: {"complexity": <float>}'
)
try:
response = await self._llm_gateway.chat(
messages=[{"role": "user", "content": prompt}],
@ -283,7 +279,10 @@ class CostAwareRouter:
"""Layer 2: 高复杂度任务通过 org_context.find_best_agent 路由。"""
if self._org_context is not None and hasattr(self._org_context, "find_best_agent"):
try:
best_agent = await self._org_context.find_best_agent(content)
# Extract capability-like keywords from content for matching
# find_best_agent expects list[str] of required capabilities
content_words = [w for w in content.split() if len(w) > 2][:5]
best_agent = self._org_context.find_best_agent(required_capabilities=content_words)
if best_agent is not None:
agent_name = best_agent if isinstance(best_agent, str) else getattr(best_agent, "name", str(best_agent))
result = SkillRoutingResult(

View File

@ -149,7 +149,7 @@ class EvolutionMixin:
# Step 2: Soul 进化检查
if memory_store is not None:
await self.evolve_soul(task, result, memory_store)
await self.evolve_soul(task, result, memory_store, reflection=reflection)
# Step 3: 如果有改进建议,触发 Prompt 优化
if not reflection.suggestions:
@ -378,6 +378,7 @@ class EvolutionMixin:
task: TaskMessage,
result: TaskResult,
memory_store: MemoryStore | None = None,
reflection: Reflection | None = None,
) -> bool:
"""Check if soul should be updated based on accumulated reflections.
@ -389,9 +390,9 @@ class EvolutionMixin:
if memory_store is None:
return False
if reflection is None:
if self._reflector is None:
return False
reflection = await self._reflector.reflect(task, result)
# 只关注低质量且有建议的反思

View File

@ -159,7 +159,11 @@ class AlignmentGuard:
)
except Exception as e:
logger.warning(f"LLM audit failed: {e}")
return AlignmentCheckResult(passed=True, checked_by="rule")
return AlignmentCheckResult(
passed=False,
violations=[f"LLM audit unavailable: {e}"],
checked_by="rule",
)
def record_interaction(self, session_id: str) -> CascadeAlert | None:
"""记录一次 agent 间交互,超过阈值返回 CascadeAlert"""

View File

@ -487,6 +487,7 @@ def create_app(
app.state.runner = BackgroundRunner(task_store=app.state.task_store)
app.state.server_config = server_config
app.state.api_key = effective_api_key
app.state._config_reload_lock = asyncio.Lock()
# Initialize session manager for Chat mode
from agentkit.session.manager import SessionManager

View File

@ -111,7 +111,7 @@ class TestCapabilityMatching:
))
# Mock find_best_agent to return the research agent
org_context.find_best_agent = AsyncMock(
org_context.find_best_agent = MagicMock(
return_value=org_context.get_agent_profile("research_agent")
)
@ -515,7 +515,7 @@ class TestFullPipeline:
skills=["market_analysis"],
current_load=0,
))
org_context.find_best_agent = AsyncMock(
org_context.find_best_agent = MagicMock(
return_value=org_context.get_agent_profile("analyst")
)

View File

@ -267,7 +267,7 @@ class TestLayer2CapabilityMatching:
"""'做市场调研+竞品分析' 复杂度 > 0.7,触发能力匹配"""
gateway = _make_llm_gateway(json.dumps({"complexity": 0.85}))
org_context = MagicMock()
org_context.find_best_agent = AsyncMock(return_value="market-researcher")
org_context.find_best_agent = MagicMock(return_value="market-researcher")
router = CostAwareRouter(llm_gateway=gateway, model="default", org_context=org_context)
result = await router.route(
@ -289,7 +289,7 @@ class TestLayer2CapabilityMatching:
agent_obj = MagicMock()
agent_obj.name = "analyst-agent"
org_context = MagicMock()
org_context.find_best_agent = AsyncMock(return_value=agent_obj)
org_context.find_best_agent = MagicMock(return_value=agent_obj)
router = CostAwareRouter(llm_gateway=gateway, model="default", org_context=org_context)
result = await router.route(