feat(block-h): plugin-contributable intents for fallback action mapper
This commit is contained in:
@@ -6,9 +6,12 @@ Supports keyword-based intent detection for common CRM operations.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import re
|
||||
from typing import Any
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Precompiled patterns for intent detection
|
||||
_PATTERNS = {
|
||||
"create_contact": re.compile(
|
||||
@@ -27,6 +30,37 @@ _PATTERNS = {
|
||||
"help": re.compile(r"\b(help|what can you do|assist)\b", re.IGNORECASE),
|
||||
}
|
||||
|
||||
# Plugin-contributed intents: pattern -> callable(query, context) -> list[dict] | None.
|
||||
# Registered via ``register_intent_pattern`` so plugins can extend the fallback
|
||||
# mapper without touching core code (Block H / HC-A).
|
||||
_CONTRIBUTED_INTENTS: list[tuple[re.Pattern[str], Any]] = []
|
||||
|
||||
|
||||
def register_intent_pattern(
|
||||
pattern: str | re.Pattern[str],
|
||||
handler: Any,
|
||||
*,
|
||||
owner: str = "",
|
||||
) -> None:
|
||||
"""Register a plugin-contributed intent for the fallback action mapper.
|
||||
|
||||
Args:
|
||||
pattern: Regex (compiled or raw string) matching the user query.
|
||||
handler: Callable ``(query, context) -> list[dict] | None`` producing
|
||||
proposed actions when the pattern matches.
|
||||
owner: Optional plugin name, used by ``unregister_intent_patterns``.
|
||||
"""
|
||||
compiled = re.compile(pattern) if isinstance(pattern, str) else pattern
|
||||
_CONTRIBUTED_INTENTS.append((compiled, handler))
|
||||
|
||||
|
||||
def unregister_intent_patterns(owner: str) -> None:
|
||||
"""Remove all intents contributed by ``owner`` (plugin deactivation)."""
|
||||
global _CONTRIBUTED_INTENTS
|
||||
_CONTRIBUTED_INTENTS = [
|
||||
entry for entry in _CONTRIBUTED_INTENTS if getattr(entry[1], "owner_tag", None) != owner
|
||||
]
|
||||
|
||||
# Name extraction patterns - using single-quoted strings to avoid escaping issues
|
||||
_NAME_PATTERNS = [
|
||||
re.compile(r"\b(?:named|called|for)\s+['\"]?([^'\".,]+)['\"]?", re.IGNORECASE),
|
||||
@@ -147,6 +181,16 @@ def map_query_to_actions(query: str, context: dict[str, Any] | None = None) -> l
|
||||
}
|
||||
)
|
||||
|
||||
# --- Plugin-contributed intents (Block H / HC-A) ---
|
||||
for pattern, handler in _CONTRIBUTED_INTENTS:
|
||||
try:
|
||||
if pattern.search(q):
|
||||
contributed = handler(query, context)
|
||||
if contributed:
|
||||
actions.extend(contributed)
|
||||
except Exception:
|
||||
logger.warning("Contributed intent handler failed", exc_info=True)
|
||||
|
||||
# --- Generic fallback ---
|
||||
if not actions:
|
||||
if _PATTERNS["help"].search(q):
|
||||
|
||||
Reference in New Issue
Block a user