feat(production): sync all modified production files to git
Includes updates across gateway, router, node-worker, memory-service, aurora-service, swapper, sofiia-console UI and node2 infrastructure: - gateway-bot: Dockerfile, http_api.py, druid/aistalk prompts, doc_service - services/router: main.py, router-config.yml, fabric_metrics, memory_retrieval, offload_client, prompt_builder - services/node-worker: worker.py, main.py, config.py, fabric_metrics - services/memory-service: Dockerfile, database.py, main.py, requirements - services/aurora-service: main.py (+399), kling.py, quality_report.py - services/swapper-service: main.py, swapper_config_node2.yaml - services/sofiia-console: static/index.html (console UI update) - config: agent_registry, crewai_agents/teams, router_agents - ops/fabric_preflight.sh: updated preflight checks - router-config.yml, docker-compose.node2.yml: infra updates - docs: NODA1-AGENT-ARCHITECTURE, fabric_contract updated Made-with: Cursor
This commit is contained in:
@@ -20,6 +20,7 @@ import json
|
||||
import logging
|
||||
import re
|
||||
import hashlib
|
||||
from time import monotonic
|
||||
from typing import Optional, Dict, Any, List
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
@@ -41,6 +42,20 @@ PENDING_QUESTIONS_LIMIT = int(os.getenv("AGENT_PENDING_QUESTIONS_LIMIT", "5"))
|
||||
SHARED_AGRO_LIBRARY_ENABLED = os.getenv("AGROMATRIX_SHARED_LIBRARY_ENABLED", "true").lower() == "true"
|
||||
SHARED_AGRO_LIBRARY_REQUIRE_REVIEW = os.getenv("AGROMATRIX_SHARED_LIBRARY_REQUIRE_REVIEW", "true").lower() == "true"
|
||||
DOC_VERSION_PREVIEW_CHARS = int(os.getenv("DOC_VERSION_PREVIEW_CHARS", "240"))
|
||||
WARNING_THROTTLE_SECONDS = float(os.getenv("MEMORY_RETRIEVAL_WARNING_THROTTLE_S", "60") or "60")
|
||||
_warning_last_ts: Dict[str, float] = {}
|
||||
|
||||
|
||||
def _warning_throttled(key: str, message: str) -> None:
|
||||
"""Emit repetitive warnings at most once per throttle window."""
|
||||
if WARNING_THROTTLE_SECONDS <= 0:
|
||||
logger.warning(message)
|
||||
return
|
||||
now = monotonic()
|
||||
last = _warning_last_ts.get(key, 0.0)
|
||||
if now - last >= WARNING_THROTTLE_SECONDS:
|
||||
_warning_last_ts[key] = now
|
||||
logger.warning(message)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -1067,7 +1082,7 @@ class MemoryRetrieval:
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"register_pending_question failed: {e}")
|
||||
_warning_throttled("register_pending_question_failed", f"register_pending_question failed: {e}")
|
||||
return False
|
||||
|
||||
async def resolve_pending_question(
|
||||
@@ -1086,7 +1101,7 @@ class MemoryRetrieval:
|
||||
row = await conn.fetchrow(
|
||||
"""
|
||||
WITH target AS (
|
||||
SELECT id
|
||||
SELECT id, question_fingerprint
|
||||
FROM agent_pending_questions
|
||||
WHERE channel = $1
|
||||
AND chat_id = $2
|
||||
@@ -1095,17 +1110,49 @@ class MemoryRetrieval:
|
||||
AND status = 'pending'
|
||||
ORDER BY created_at ASC
|
||||
LIMIT 1
|
||||
), decision AS (
|
||||
SELECT
|
||||
t.id,
|
||||
CASE
|
||||
WHEN $5 = 'dismissed' THEN 'dismissed'
|
||||
WHEN EXISTS (
|
||||
SELECT 1
|
||||
FROM agent_pending_questions q
|
||||
WHERE q.channel = $1
|
||||
AND q.chat_id = $2
|
||||
AND q.user_id = $3
|
||||
AND q.agent_id = $4
|
||||
AND q.status = 'answered'
|
||||
AND q.question_fingerprint = t.question_fingerprint
|
||||
) THEN 'dismissed'
|
||||
ELSE 'answered'
|
||||
END AS next_status,
|
||||
CASE
|
||||
WHEN $5 = 'dismissed' THEN $5
|
||||
WHEN EXISTS (
|
||||
SELECT 1
|
||||
FROM agent_pending_questions q
|
||||
WHERE q.channel = $1
|
||||
AND q.chat_id = $2
|
||||
AND q.user_id = $3
|
||||
AND q.agent_id = $4
|
||||
AND q.status = 'answered'
|
||||
AND q.question_fingerprint = t.question_fingerprint
|
||||
) THEN 'duplicate_answered'
|
||||
ELSE $5
|
||||
END AS resolution_reason
|
||||
FROM target t
|
||||
)
|
||||
UPDATE agent_pending_questions p
|
||||
SET status = CASE WHEN $5 = 'dismissed' THEN 'dismissed' ELSE 'answered' END,
|
||||
SET status = d.next_status,
|
||||
answered_at = NOW(),
|
||||
metadata = COALESCE(p.metadata, '{}'::jsonb)
|
||||
|| jsonb_build_object(
|
||||
'resolution_reason', $5,
|
||||
'resolution_reason', d.resolution_reason,
|
||||
'answer_fingerprint', COALESCE($6, '')
|
||||
)
|
||||
FROM target t
|
||||
WHERE p.id = t.id
|
||||
FROM decision d
|
||||
WHERE p.id = d.id
|
||||
RETURNING p.id
|
||||
""",
|
||||
channel,
|
||||
@@ -1117,7 +1164,7 @@ class MemoryRetrieval:
|
||||
)
|
||||
return bool(row)
|
||||
except Exception as e:
|
||||
logger.warning(f"resolve_pending_question failed: {e}")
|
||||
_warning_throttled("resolve_pending_question_failed", f"resolve_pending_question failed: {e}")
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user