From 1fa5151d8aa36745c9d82bc65c5e93eae2a87949 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Thu, 30 Apr 2026 21:12:44 -0400 Subject: [PATCH] fix: correct V3 search filter key and response field names in ae_knowledge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Filter key is "and" not "and_filters" (V3 API format) - Entry IDs use journal_entry_id/id, not id_random (id_random is None) - Dates use updated_on/created_on, not updated_at/created_at - Total count lives in meta.data_list_count, not top-level total/count - Inject query_string="%" when and filters present but no query, since the V3 search engine requires query_string for filters to apply - Normalize tags from string to list in both entry_read and entries_list - Fix order_by to use updated_on (not updated_at) in entries_list - Correct ARCH__AE_INTEGRATION.md: and_filters → and, or_filters → or Co-Authored-By: Claude Sonnet 4.6 --- cortex/tools/ae_knowledge.py | 28 +++++++++++++++------------ documentation/ARCH__AE_INTEGRATION.md | 4 ++-- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/cortex/tools/ae_knowledge.py b/cortex/tools/ae_knowledge.py index abd2b06..339e7fd 100644 --- a/cortex/tools/ae_knowledge.py +++ b/cortex/tools/ae_knowledge.py @@ -122,7 +122,10 @@ def _sync_journal_search( if priority is not None: and_filters.append({"field": "priority", "op": "eq", "value": priority}) if and_filters: - search_body["and_filters"] = and_filters + search_body["and"] = and_filters + # query_string must be present for `and` filters to apply + if "query_string" not in search_body: + search_body["query_string"] = "%" params: dict = {} if journal_id: @@ -145,7 +148,7 @@ def _sync_journal_search( return f"Journal search error: {e}" entries = data.get("data", []) - total = data.get("total") or data.get("count") or len(entries) + total = (data.get("meta") or {}).get("data_list_count") or len(entries) if not entries: desc = query or tags or type_code or topic_code or f"journal {journal_id}" @@ -156,12 +159,11 @@ def _sync_journal_search( for entry in entries: title = entry.get("name") or "(untitled)" - entry_id = entry.get("id_random", "") + entry_id = entry.get("journal_entry_id") or entry.get("id") or "" journal_name = entry.get("journal_name") or entry.get("parent_name") or "" summary = entry.get("summary") or "" entry_tags = entry.get("tags") or [] - updated = (entry.get("updated_on") or entry.get("updated_at") or - entry.get("created_on") or entry.get("created_at") or "")[:10] + updated = (entry.get("updated_on") or entry.get("created_on") or "")[:10] content_preview = (entry.get("content") or "")[:400].replace("\n", " ") header = f"**{title}**" @@ -357,9 +359,10 @@ def _sync_journal_entry_read(entry_id: str, max_content_chars: int) -> str: title = entry.get("name") or "(untitled)" journal = entry.get("journal_name") or entry.get("parent_name") or "" summary = entry.get("summary") or "" - tags = entry.get("tags") or [] + raw_tags = entry.get("tags") or [] + tags = raw_tags if isinstance(raw_tags, list) else [t.strip() for t in str(raw_tags).split(",") if t.strip()] content = entry.get("content") or "" - updated = (entry.get("updated_at") or entry.get("created_at") or "")[:19].replace("T", " ") + updated = (entry.get("updated_on") or entry.get("created_on") or "")[:19].replace("T", " ") enabled = entry.get("enable", True) lines = [f"# {title}"] @@ -407,7 +410,7 @@ def _sync_journal_entries_list(journal_id: str, max_results: int, page: int) -> search_body: dict = { "page_size": max_results, "page": page, - "order_by": "-updated_at", + "order_by": "-updated_on", } params = {"for_obj_type": "journal", "for_obj_id": journal_id} @@ -426,7 +429,7 @@ def _sync_journal_entries_list(journal_id: str, max_results: int, page: int) -> return f"Journal entries list error: {e}" entries = data.get("data", []) - total = data.get("total") or data.get("count") or len(entries) + total = (data.get("meta") or {}).get("data_list_count") or len(entries) if not entries: return f"No entries found in journal `{journal_id}`." @@ -435,10 +438,11 @@ def _sync_journal_entries_list(journal_id: str, max_results: int, page: int) -> lines = [f"Entries in journal `{journal_id}` — showing {offset}–{offset + len(entries) - 1} of {total}:\n"] for i, entry in enumerate(entries, offset): title = entry.get("name") or "(untitled)" - entry_id = entry.get("id_random", "") - tags = entry.get("tags") or [] + entry_id = entry.get("journal_entry_id") or entry.get("id") or "" + raw_tags = entry.get("tags") or [] + tags = raw_tags if isinstance(raw_tags, list) else [t.strip() for t in str(raw_tags).split(",") if t.strip()] summary = entry.get("summary") or "" - updated = (entry.get("updated_at") or entry.get("created_at") or "")[:10] + updated = (entry.get("updated_on") or entry.get("created_on") or "")[:10] enabled = entry.get("enable", True) status = "" if enabled else " [disabled]" diff --git a/documentation/ARCH__AE_INTEGRATION.md b/documentation/ARCH__AE_INTEGRATION.md index 4fbfd80..d11feb4 100644 --- a/documentation/ARCH__AE_INTEGRATION.md +++ b/documentation/ARCH__AE_INTEGRATION.md @@ -43,11 +43,11 @@ POST /v3/crud/journal_entry/search ```json { "query_string": "fulltext search term", - "and_filters": [ + "and": [ { "field": "tags", "op": "icontains", "value": "networking" }, { "field": "created_on", "op": "gte", "value": "2026-01-01" } ], - "or_filters": [...], + "or": [...], "page_size": 20, "page": 1, "order_by": "-updated_on"