- Added AIKnowledgeActivationStatus and AIKnowledgeSyncStatus enums to models.py for managing activation and sync states. - Introduced AIKnowledgeSync class in aiknowledge_sync_utils.py for synchronizing CAIKnowledge entities with XAI Collections, including collection lifecycle management, document synchronization, and metadata updates. - Created a daily cron job (aiknowledge_full_sync_cron_step.py) to perform a full sync of CAIKnowledge entities. - Developed an event handler (aiknowledge_sync_event_step.py) to synchronize CAIKnowledge entities with XAI Collections triggered by webhooks and cron jobs. - Implemented a webhook handler (aiknowledge_update_api_step.py) to receive updates from EspoCRM for CAIKnowledge entities and enqueue sync events. - Enhanced xai_service.py with methods for collection management, document listing, and metadata updates.
74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
"""VMH Webhook - AI Knowledge Update"""
|
|
from typing import Any
|
|
from motia import FlowContext, http, ApiRequest, ApiResponse
|
|
|
|
|
|
config = {
|
|
"name": "VMH Webhook AI Knowledge Update",
|
|
"description": "Receives update webhooks from EspoCRM for CAIKnowledge entities",
|
|
"flows": ["vmh-aiknowledge"],
|
|
"triggers": [
|
|
http("POST", "/vmh/webhook/aiknowledge/update")
|
|
],
|
|
"enqueues": ["aiknowledge.sync"],
|
|
}
|
|
|
|
|
|
async def handler(request: ApiRequest, ctx: FlowContext[Any]) -> ApiResponse:
|
|
"""
|
|
Webhook handler for CAIKnowledge updates in EspoCRM.
|
|
|
|
Triggered when:
|
|
- activationStatus changes
|
|
- syncStatus changes (e.g., set to 'unclean')
|
|
- Documents linked/unlinked
|
|
"""
|
|
try:
|
|
ctx.logger.info("=" * 80)
|
|
ctx.logger.info("🔔 AI Knowledge Update Webhook")
|
|
ctx.logger.info("=" * 80)
|
|
|
|
# Extract payload
|
|
payload = request.body
|
|
|
|
# Validate required fields
|
|
knowledge_id = payload.get('entity_id') or payload.get('id')
|
|
entity_type = payload.get('entity_type', 'CAIKnowledge')
|
|
action = payload.get('action', 'update')
|
|
|
|
if not knowledge_id:
|
|
ctx.logger.error("❌ Missing entity_id in payload")
|
|
return ApiResponse(
|
|
status_code=400,
|
|
body={'success': False, 'error': 'Missing entity_id'}
|
|
)
|
|
|
|
ctx.logger.info(f"📋 Entity Type: {entity_type}")
|
|
ctx.logger.info(f"📋 Entity ID: {knowledge_id}")
|
|
ctx.logger.info(f"📋 Action: {action}")
|
|
|
|
# Enqueue sync event
|
|
await ctx.enqueue({
|
|
'topic': 'aiknowledge.sync',
|
|
'data': {
|
|
'knowledge_id': knowledge_id,
|
|
'source': 'webhook',
|
|
'action': action
|
|
}
|
|
})
|
|
|
|
ctx.logger.info(f"✅ Sync event enqueued for {knowledge_id}")
|
|
ctx.logger.info("=" * 80)
|
|
|
|
return ApiResponse(
|
|
status_code=200,
|
|
body={'success': True, 'knowledge_id': knowledge_id}
|
|
)
|
|
|
|
except Exception as e:
|
|
ctx.logger.error(f"❌ Webhook error: {e}")
|
|
return ApiResponse(
|
|
status_code=500,
|
|
body={'success': False, 'error': str(e)}
|
|
)
|