feat: natural language queries respect UI filters (v1.2.0)
- AskRequest now accepts optional filter fields: services, actor, operation, result, start, end, include_tags, exclude_tags - ask_question merges NL-extracted constraints with explicit UI filters - Frontend sends active filter state with every ask request - Show filter hint below ask input when filters are active - Add tests for service+result filtering and actor filtering in /api/ask Bump version to 1.2.0
This commit is contained in:
@@ -104,7 +104,17 @@ def _extract_entity(question: str) -> str | None:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _build_event_query(entity: str | None, start: str | None, end: str | None) -> dict:
|
||||
def _build_event_query(
|
||||
entity: str | None,
|
||||
start: str | None,
|
||||
end: str | None,
|
||||
services: list[str] | None = None,
|
||||
actor: str | None = None,
|
||||
operation: str | None = None,
|
||||
result: str | None = None,
|
||||
include_tags: list[str] | None = None,
|
||||
exclude_tags: list[str] | None = None,
|
||||
) -> dict:
|
||||
filters = []
|
||||
|
||||
if start or end:
|
||||
@@ -128,6 +138,28 @@ def _build_event_query(entity: str | None, start: str | None, end: str | None) -
|
||||
}
|
||||
)
|
||||
|
||||
if services:
|
||||
filters.append({"service": {"$in": services}})
|
||||
if actor:
|
||||
actor_safe = re.escape(actor)
|
||||
filters.append(
|
||||
{
|
||||
"$or": [
|
||||
{"actor_display": {"$regex": actor_safe, "$options": "i"}},
|
||||
{"actor_upn": {"$regex": actor_safe, "$options": "i"}},
|
||||
{"actor.user.userPrincipalName": {"$regex": actor_safe, "$options": "i"}},
|
||||
]
|
||||
}
|
||||
)
|
||||
if operation:
|
||||
filters.append({"operation": {"$regex": re.escape(operation), "$options": "i"}})
|
||||
if result:
|
||||
filters.append({"result": {"$regex": re.escape(result), "$options": "i"}})
|
||||
if include_tags:
|
||||
filters.append({"tags": {"$all": include_tags}})
|
||||
if exclude_tags:
|
||||
filters.append({"tags": {"$not": {"$all": exclude_tags}}})
|
||||
|
||||
return {"$and": filters} if filters else {}
|
||||
|
||||
|
||||
@@ -253,7 +285,17 @@ async def ask_question(body: AskRequest, user: dict = Depends(require_auth)):
|
||||
start = (now - timedelta(days=7)).isoformat().replace("+00:00", "Z")
|
||||
end = now.isoformat().replace("+00:00", "Z")
|
||||
|
||||
query = _build_event_query(entity, start, end)
|
||||
query = _build_event_query(
|
||||
entity,
|
||||
start,
|
||||
end,
|
||||
services=body.services,
|
||||
actor=body.actor,
|
||||
operation=body.operation,
|
||||
result=body.result,
|
||||
include_tags=body.include_tags,
|
||||
exclude_tags=body.exclude_tags,
|
||||
)
|
||||
|
||||
try:
|
||||
cursor = events_collection.find(query).sort([("timestamp", -1)]).limit(LLM_MAX_EVENTS)
|
||||
|
||||
Reference in New Issue
Block a user