fix(agent): unify logging API + add molecular-cot coverage to agent module
Phase 1 — API unification: - Replace direct log() from cot_logger with canonical logger.reason/reflect/explore across _confirmation.py, _persistence.py, _tool_resolver.py, app.py Phase 2 — Gap filling: - tools.py: add REASON/REFLECT/EXPLORE to 17 C3 tool functions (was 0 logs) - app.py agent_handler (C4): add lifecycle REASON on entry, REFLECT on exit, EXPLORE on OutputParserException + general exception - langgraph_setup.py create_agent (C4): add REASON with model/config_source, EXPLORE on env-var/InMemorySaver fallback, REFLECT on graph compilation - _tool_resolver.py infer_tool_from_text (C3, 13 branches): REASON on inference - _persistence.py: REFLECT on save_conversation success, EXPLORE on prefetch Phase 3 — Plain log migration: - middleware.py: plain logger.info() -> logger.reason() - run.py: 7 plain logger.info/warning/error -> molecular REASON/EXPLORE Phase 4 — Cleanup: - cot_logger.py: deprecate MarkerLogger (@DEPRECATED + @REPLACED_BY) - molecular-cot-logging SKILL.md: remove cot_span Section IV (never implemented), renumber sections V-VII -> IV-VI, add cot_span rejection rationale Verification: pytest 27/27, axiom rebuild 5844/2993/0 warnings
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
from typing import Any
|
||||
|
||||
from src.agent.tools import get_all_tools
|
||||
from src.core.cot_logger import log
|
||||
from src.core.logger import logger
|
||||
|
||||
# #region AgentChat.ToolResolver.Sets [C:1] [TYPE Constants] [SEMANTICS agent-chat,tools,sets]
|
||||
# @ingroup AgentChat
|
||||
@@ -56,7 +56,11 @@ def known_agent_tool_names() -> set[str]:
|
||||
try:
|
||||
return {str(tool_obj.name) for tool_obj in get_all_tools() if getattr(tool_obj, "name", None)}
|
||||
except Exception as exc:
|
||||
log("AgentChat.ToolResolver", "EXPLORE", "tool catalog lookup failed", {"error": str(exc)})
|
||||
logger.explore(
|
||||
"tool catalog lookup failed",
|
||||
payload={"error": str(exc)},
|
||||
extra={"src": "AgentChat.ToolResolver"},
|
||||
)
|
||||
return _SAFE_AGENT_TOOLS | _GUARDED_AGENT_TOOLS | _DANGEROUS_AGENT_TOOLS
|
||||
# #endregion AgentChat.ToolResolver.KnownNames
|
||||
|
||||
@@ -105,39 +109,46 @@ def coerce_tool_call(tool_call: Any) -> tuple[str | None, dict[str, Any]]:
|
||||
# uses keyword matching to guess the user's intent and auto-trigger HITL.
|
||||
def infer_tool_from_text(text: str) -> str | None:
|
||||
lowered = (text or "").lower()
|
||||
inferred: str | None = None
|
||||
if any(word in lowered for word in ["окруж", "environment", "env"]):
|
||||
return "list_environments"
|
||||
if any(word in lowered for word in ["maintenance", "обслуж", "баннер"]):
|
||||
inferred = "list_environments"
|
||||
elif any(word in lowered for word in ["maintenance", "обслуж", "баннер"]):
|
||||
if any(word in lowered for word in ["start", "созда", "запусти", "начни"]):
|
||||
return "start_maintenance"
|
||||
if any(word in lowered for word in ["end", "закрой", "заверши", "останов"]):
|
||||
return "end_maintenance"
|
||||
return "list_maintenance_events"
|
||||
if any(word in lowered for word in ["дашборд", "dashboard", "dashboards", "дашборды"]):
|
||||
return "search_dashboards"
|
||||
if any(word in lowered for word in ["здоров", "health", "статус системы", "system status"]):
|
||||
return "get_health_summary"
|
||||
if any(word in lowered for word in ["задач", "task", "таск"]):
|
||||
return "get_task_status"
|
||||
if any(word in lowered for word in ["llm", "provider", "провайдер", "модель"]):
|
||||
return "list_llm_providers"
|
||||
if any(word in lowered for word in ["branch", "ветк"]):
|
||||
return "create_branch"
|
||||
if any(word in lowered for word in ["commit", "коммит"]):
|
||||
return "commit_changes"
|
||||
if any(word in lowered for word in ["deploy", "депло", "разверн"]):
|
||||
return "deploy_dashboard"
|
||||
if any(word in lowered for word in ["миграц", "migration", "migrate"]):
|
||||
return "execute_migration"
|
||||
if any(word in lowered for word in ["backup", "бэкап", "резерв"]):
|
||||
return "run_backup"
|
||||
if any(word in lowered for word in ["валидац", "validation", "validate"]):
|
||||
return "run_llm_validation"
|
||||
if any(word in lowered for word in ["документ", "documentation", "docs"]):
|
||||
return "run_llm_documentation"
|
||||
if any(word in lowered for word in ["инструмент", "tool", "capabilit", "умеешь", "можешь"]):
|
||||
return "show_capabilities"
|
||||
return None
|
||||
inferred = "start_maintenance"
|
||||
elif any(word in lowered for word in ["end", "закрой", "заверши", "останов"]):
|
||||
inferred = "end_maintenance"
|
||||
else:
|
||||
inferred = "list_maintenance_events"
|
||||
elif any(word in lowered for word in ["дашборд", "dashboard", "dashboards", "дашборды"]):
|
||||
inferred = "search_dashboards"
|
||||
elif any(word in lowered for word in ["здоров", "health", "статус системы", "system status"]):
|
||||
inferred = "get_health_summary"
|
||||
elif any(word in lowered for word in ["задач", "task", "таск"]):
|
||||
inferred = "get_task_status"
|
||||
elif any(word in lowered for word in ["llm", "provider", "провайдер", "модель"]):
|
||||
inferred = "list_llm_providers"
|
||||
elif any(word in lowered for word in ["branch", "ветк"]):
|
||||
inferred = "create_branch"
|
||||
elif any(word in lowered for word in ["commit", "коммит"]):
|
||||
inferred = "commit_changes"
|
||||
elif any(word in lowered for word in ["deploy", "депло", "разверн"]):
|
||||
inferred = "deploy_dashboard"
|
||||
elif any(word in lowered for word in ["миграц", "migration", "migrate"]):
|
||||
inferred = "execute_migration"
|
||||
elif any(word in lowered for word in ["backup", "бэкап", "резерв"]):
|
||||
inferred = "run_backup"
|
||||
elif any(word in lowered for word in ["валидац", "validation", "validate"]):
|
||||
inferred = "run_llm_validation"
|
||||
elif any(word in lowered for word in ["документ", "documentation", "docs"]):
|
||||
inferred = "run_llm_documentation"
|
||||
elif any(word in lowered for word in ["инструмент", "tool", "capabilit", "умеешь", "можешь"]):
|
||||
inferred = "show_capabilities"
|
||||
|
||||
if inferred:
|
||||
logger.reason("Tool inferred from user text",
|
||||
payload={"tool": inferred, "text_preview": (text or "")[:80]},
|
||||
extra={"src": "AgentChat.ToolResolver.InferFromText"})
|
||||
return inferred
|
||||
# #endregion AgentChat.ToolResolver.InferFromText
|
||||
|
||||
|
||||
@@ -155,7 +166,11 @@ def extract_tool_call_from_state(state, user_text: str = "") -> tuple[str | None
|
||||
if tool_name:
|
||||
return (str(tool_name), tool_args)
|
||||
except Exception as exc:
|
||||
log("AgentChat.ToolResolver", "EXPLORE", "tool_call extraction failed", {"error": str(exc)})
|
||||
logger.explore(
|
||||
"tool_call extraction failed",
|
||||
payload={"error": str(exc)},
|
||||
extra={"src": "AgentChat.ToolResolver"},
|
||||
)
|
||||
|
||||
if getattr(state, "next", None):
|
||||
node_or_tool = str(state.next[0])
|
||||
@@ -164,7 +179,11 @@ def extract_tool_call_from_state(state, user_text: str = "") -> tuple[str | None
|
||||
|
||||
inferred_tool = infer_tool_from_text(user_text)
|
||||
if inferred_tool:
|
||||
log("AgentChat.ToolResolver", "EXPLORE", "tool_call inferred from user text", {"tool": inferred_tool})
|
||||
logger.explore(
|
||||
"tool_call inferred from user text",
|
||||
payload={"tool": inferred_tool},
|
||||
extra={"src": "AgentChat.ToolResolver"},
|
||||
)
|
||||
return (inferred_tool, {})
|
||||
return (None, {})
|
||||
# #endregion AgentChat.ToolResolver.ExtractFromState
|
||||
|
||||
Reference in New Issue
Block a user