Merge branch 'review/pr-361'
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
from fastapi import APIRouter, Depends, HTTPException
|
from fastapi import APIRouter, Depends, HTTPException
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, Optional
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
@@ -182,7 +183,13 @@ async def set_task_status(
|
|||||||
feedback_text=completion_notes
|
feedback_text=completion_notes
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass # Don't block response on memory update failure
|
logger.warning(
|
||||||
|
"Task memory outcome recording failed for user_id={} task_id={} error_class={} error_message={}",
|
||||||
|
user_id,
|
||||||
|
task_id,
|
||||||
|
type(e).__name__,
|
||||||
|
str(e),
|
||||||
|
)
|
||||||
|
|
||||||
plan_for_date = db.query(DailyWorkflowPlan).filter(DailyWorkflowPlan.id == task.plan_id).first()
|
plan_for_date = db.query(DailyWorkflowPlan).filter(DailyWorkflowPlan.id == task.plan_id).first()
|
||||||
plan_date = plan_for_date.date if plan_for_date and plan_for_date.date else ""
|
plan_date = plan_for_date.date if plan_for_date and plan_for_date.date else ""
|
||||||
|
|||||||
@@ -368,9 +368,15 @@ class RealTimeSemanticMonitor:
|
|||||||
|
|
||||||
# Using StrategyArchitect for pillar/gap analysis
|
# Using StrategyArchitect for pillar/gap analysis
|
||||||
if hasattr(self.strategy_agent, 'find_semantic_gaps'):
|
if hasattr(self.strategy_agent, 'find_semantic_gaps'):
|
||||||
# This method requires competitor indices, which is complex to get here without full context.
|
logger.warning(
|
||||||
# Let's use the SIF service directly for lighter weight insights or call the agent's high level method.
|
"Skipping direct semantic gap method invocation for user_id={} due to missing competitor index context",
|
||||||
pass
|
self.user_id,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
"Strategy agent missing find_semantic_gaps for user_id={}, using dashboard-context fallback",
|
||||||
|
self.user_id,
|
||||||
|
)
|
||||||
|
|
||||||
# Alternative: Query SIF directly for "content gaps" if they are indexed as such
|
# Alternative: Query SIF directly for "content gaps" if they are indexed as such
|
||||||
# Or generate them now via LLM + SIF Context
|
# Or generate them now via LLM + SIF Context
|
||||||
@@ -422,6 +428,17 @@ class RealTimeSemanticMonitor:
|
|||||||
source_agent="Strategy Architect Agent"
|
source_agent="Strategy Architect Agent"
|
||||||
))
|
))
|
||||||
|
|
||||||
|
if not ai_insights:
|
||||||
|
logger.warning(
|
||||||
|
"Dashboard context returned no ai_insights for user_id={}, insight generation is degraded",
|
||||||
|
self.user_id,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.warning(
|
||||||
|
"SEO dashboard context unavailable for user_id={}, using fallback insight only",
|
||||||
|
self.user_id,
|
||||||
|
)
|
||||||
|
|
||||||
except Exception as agent_err:
|
except Exception as agent_err:
|
||||||
logger.warning(f"Agent insight generation failed: {agent_err}")
|
logger.warning(f"Agent insight generation failed: {agent_err}")
|
||||||
|
|
||||||
@@ -514,8 +531,13 @@ class RealTimeSemanticMonitor:
|
|||||||
dedupe_key=dedupe_key,
|
dedupe_key=dedupe_key,
|
||||||
)
|
)
|
||||||
db.close()
|
db.close()
|
||||||
except Exception:
|
except Exception as alert_err:
|
||||||
pass
|
logger.warning(
|
||||||
|
"Unable to persist semantic alerts for user_id={} error_class={} error_message={}",
|
||||||
|
self.user_id,
|
||||||
|
type(alert_err).__name__,
|
||||||
|
str(alert_err),
|
||||||
|
)
|
||||||
await self._send_alerts(alerts)
|
await self._send_alerts(alerts)
|
||||||
|
|
||||||
async def get_cache_stats(self) -> Dict[str, Any]:
|
async def get_cache_stats(self) -> Dict[str, Any]:
|
||||||
|
|||||||
@@ -30,6 +30,17 @@ class TaskMemoryService:
|
|||||||
self.user_id = user_id
|
self.user_id = user_id
|
||||||
self.db = db
|
self.db = db
|
||||||
self.intelligence = TxtaiIntelligenceService(user_id)
|
self.intelligence = TxtaiIntelligenceService(user_id)
|
||||||
|
self._metrics_counters: Dict[str, int] = {}
|
||||||
|
|
||||||
|
def _increment_metric(self, metric_name: str, increment: int = 1) -> None:
|
||||||
|
"""Increment lightweight in-memory counters for observability hooks."""
|
||||||
|
self._metrics_counters[metric_name] = self._metrics_counters.get(metric_name, 0) + increment
|
||||||
|
logger.debug(
|
||||||
|
"TaskMemory metric updated user_id={} metric={} value={}",
|
||||||
|
self.user_id,
|
||||||
|
metric_name,
|
||||||
|
self._metrics_counters[metric_name],
|
||||||
|
)
|
||||||
|
|
||||||
def _compute_hash(self, title: str, description: str) -> str:
|
def _compute_hash(self, title: str, description: str) -> str:
|
||||||
"""Compute a consistent hash for task deduplication."""
|
"""Compute a consistent hash for task deduplication."""
|
||||||
@@ -154,8 +165,16 @@ class TaskMemoryService:
|
|||||||
f"Filtering redundant task (semantic {top_score:.2f}, history status={history_status}): {p.title}"
|
f"Filtering redundant task (semantic {top_score:.2f}, history status={history_status}): {p.title}"
|
||||||
)
|
)
|
||||||
is_semantic_duplicate = True
|
is_semantic_duplicate = True
|
||||||
except Exception:
|
except Exception as semantic_err:
|
||||||
pass
|
self._increment_metric("semantic_filter_failures")
|
||||||
|
self._increment_metric("semantic_filter_degraded_path_taken")
|
||||||
|
logger.warning(
|
||||||
|
"Semantic filter degraded for user_id={} proposal_title={} error_class={} error_message={}",
|
||||||
|
self.user_id,
|
||||||
|
getattr(p, "title", ""),
|
||||||
|
type(semantic_err).__name__,
|
||||||
|
str(semantic_err),
|
||||||
|
)
|
||||||
|
|
||||||
if not is_semantic_duplicate:
|
if not is_semantic_duplicate:
|
||||||
filtered.append(p)
|
filtered.append(p)
|
||||||
|
|||||||
Reference in New Issue
Block a user