docs: update ARCH__AE_INTEGRATION with verified API behavior
- query_string required for and/or filters to apply; use "%" as wildcard
- Total count is in meta.data_list_count, not top-level
- id_random is None in responses; Vision ID convention uses {obj_type}_id
- tags comes back as string on read, not list — normalize before joining
- Replace stale "Planned: Search Improvements" with current signature + notes
- Clarify date_to boundary (lte midnight, use next day to include full day)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# Aether Platform Integration — Cortex Tool Layer
|
# Aether Platform Integration — Cortex Tool Layer
|
||||||
|
|
||||||
> Last updated: 2026-04-30
|
> Last updated: 2026-04-30
|
||||||
> Status: Active development — Journal toolset being expanded
|
> Status: Journal toolset complete — broader AE integration planned
|
||||||
|
|
||||||
This doc covers how Cortex/Inara integrates with the Aether Platform API, what's
|
This doc covers how Cortex/Inara integrates with the Aether Platform API, what's
|
||||||
implemented, what the data model looks like, and what's planned next.
|
implemented, what the data model looks like, and what's planned next.
|
||||||
@@ -54,11 +54,14 @@ POST /v3/crud/journal_entry/search
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**`query_string` vs `and_filters` on `default_qry_str`:**
|
**`query_string` vs `and` filters on `default_qry_str`:**
|
||||||
- `query_string` → triggers `MATCH(default_qry_str) AGAINST(... IN BOOLEAN MODE)` — uses the
|
- `query_string` → triggers `MATCH(default_qry_str) AGAINST(... IN BOOLEAN MODE)` — uses the
|
||||||
FULLTEXT index. Faster and supports boolean operators (`+word`, `-word`, `"phrase"`).
|
FULLTEXT index. Faster and supports boolean operators (`+word`, `-word`, `"phrase"`).
|
||||||
- `and_filters` with `icontains` on `default_qry_str` → plain `LIKE '%term%'`. Slower,
|
- `and` with `icontains` on `default_qry_str` → plain `LIKE '%term%'`. Slower, no index.
|
||||||
no index. The current implementation uses this; should be migrated to `query_string`.
|
|
||||||
|
**Important:** `query_string` must be present for `and`/`or` filters to apply. When using
|
||||||
|
filters without a keyword query, pass `query_string: "%"` as a wildcard to activate the
|
||||||
|
filter path without restricting by keyword.
|
||||||
|
|
||||||
### Supported operators
|
### Supported operators
|
||||||
| Operator | SQL | Notes |
|
| Operator | SQL | Notes |
|
||||||
@@ -83,7 +86,7 @@ POST /v3/crud/journal_entry/search
|
|||||||
|
|
||||||
### Pagination
|
### Pagination
|
||||||
`page_size` (default 10, max ~100) + `page` (1-based).
|
`page_size` (default 10, max ~100) + `page` (1-based).
|
||||||
Response includes `total` count for pagination UI.
|
Total count is in `response["meta"]["data_list_count"]` — not a top-level key.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -93,7 +96,7 @@ Full table schema from `ae_describe journal_entry --detailed`:
|
|||||||
|
|
||||||
| Field | Type | Indexed | Notes |
|
| Field | Type | Indexed | Notes |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `id_random` | varchar(22) | UNI | Public ID — use for all API calls |
|
| `id_random` | varchar(22) | UNI | DB public ID field — but API responses return this as `journal_entry_id` (the Vision ID convention: `{obj_type}_id`). `id_random` key is `None` in responses. |
|
||||||
| `journal_id` | int | MUL | FK — use `for_obj_id` param in search |
|
| `journal_id` | int | MUL | FK — use `for_obj_id` param in search |
|
||||||
| `name` | varchar(250) | MUL | Entry title |
|
| `name` | varchar(250) | MUL | Entry title |
|
||||||
| `short_name` | varchar(25) | | |
|
| `short_name` | varchar(25) | | |
|
||||||
@@ -128,7 +131,7 @@ Full table schema from `ae_describe journal_entry --detailed`:
|
|||||||
|
|
||||||
| Field | Type | Notes |
|
| Field | Type | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `id_random` | varchar(22) | Public ID |
|
| `id_random` | varchar(22) | DB field — returned in API as `journal_id` |
|
||||||
| `name` | varchar(250) | Journal name |
|
| `name` | varchar(250) | Journal name |
|
||||||
| `summary` / `description` | text | |
|
| `summary` / `description` | text | |
|
||||||
| `type_code` | varchar(25) | Journal type |
|
| `type_code` | varchar(25) | Journal type |
|
||||||
@@ -142,7 +145,7 @@ Full table schema from `ae_describe journal_entry --detailed`:
|
|||||||
| Tool | Status | Notes |
|
| Tool | Status | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `ae_journal_list` | ✅ | Lists journals with id + name |
|
| `ae_journal_list` | ✅ | Lists journals with id + name |
|
||||||
| `ae_journal_search` | ✅ improved | Keyword search; switched to fulltext in next pass |
|
| `ae_journal_search` | ✅ | Fulltext + tag/date/type/status/priority filters; paginated |
|
||||||
| `ae_journal_entry_read` | ✅ | Full content by entry_id; configurable truncation |
|
| `ae_journal_entry_read` | ✅ | Full content by entry_id; configurable truncation |
|
||||||
| `ae_journal_entries_list` | ✅ | Browse a journal newest-first; paginated |
|
| `ae_journal_entries_list` | ✅ | Browse a journal newest-first; paginated |
|
||||||
| `ae_journal_entry_create` | ✅ | Create with title, content, tags, summary |
|
| `ae_journal_entry_create` | ✅ | Create with title, content, tags, summary |
|
||||||
@@ -154,37 +157,31 @@ Full table schema from `ae_describe journal_entry --detailed`:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Planned: Search Improvements
|
## ae_journal_search — Current Signature
|
||||||
|
|
||||||
Current search uses plain `LIKE` on `default_qry_str`. Migration plan:
|
All filters are optional and combine with AND. At least one should be provided.
|
||||||
|
|
||||||
1. **Switch to `query_string`** — fulltext MATCH/AGAINST; supports boolean operators
|
|
||||||
2. **Tag filter** — `icontains` on `tags` field
|
|
||||||
3. **Date range** — `gte`/`lte` on `created_on` or `updated_on`
|
|
||||||
4. **Classification filters** — `type_code`, `topic_code`, `category_code` (exact match)
|
|
||||||
5. **Sort control** — expose `order_by` (updated, created, name, priority)
|
|
||||||
6. **Status / priority filters** — `eq` on `status`, `priority`
|
|
||||||
7. **Combined search** — keyword + any filter combination in one call
|
|
||||||
|
|
||||||
Target signature:
|
|
||||||
```python
|
```python
|
||||||
ae_journal_search(
|
ae_journal_search(
|
||||||
query: str = "", # fulltext (query_string path) — optional
|
query: str = "", # fulltext via query_string (MATCH/AGAINST)
|
||||||
journal_id: str = "", # scope to journal
|
journal_id: str = "", # scope to a specific journal
|
||||||
tags: str = "", # icontains on tags field
|
tags: str = "", # icontains on tags field
|
||||||
type_code: str = "", # eq
|
type_code: str = "", # eq on type_code
|
||||||
topic_code: str = "", # eq
|
topic_code: str = "", # eq on topic_code
|
||||||
date_from: str = "", # created_on gte (YYYY-MM-DD)
|
date_from: str = "", # created_on gte (YYYY-MM-DD)
|
||||||
date_to: str = "", # created_on lte
|
date_to: str = "", # created_on lte (YYYY-MM-DD, exclusive of time — use next day to include full day)
|
||||||
sort_by: str = "updated", # updated | created | name | priority
|
sort_by: str = "updated", # updated | created | name | priority
|
||||||
sort_order: str = "desc",
|
sort_order: str = "desc",
|
||||||
status: int | None,
|
status: int | None = None,
|
||||||
priority: int | None,
|
priority: int | None = None,
|
||||||
max_results: int = 10,
|
max_results: int = 10,
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**date_to boundary note:** `date_to='2026-01-17'` means `<= 2026-01-17 00:00:00`, which
|
||||||
|
excludes entries created later that day. Use `date_to='2026-01-18'` to include all of Jan 17.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Planned: Broader AE Platform Integration
|
## Planned: Broader AE Platform Integration
|
||||||
@@ -215,9 +212,11 @@ Complete read/write/search for Journals and Journal Entries.
|
|||||||
|
|
||||||
`tags` is stored as a raw comma-separated varchar(255), not a JSON array.
|
`tags` is stored as a raw comma-separated varchar(255), not a JSON array.
|
||||||
The API accepts a Python list on write (the `tags` PATCH key takes a list and the backend joins it).
|
The API accepts a Python list on write (the `tags` PATCH key takes a list and the backend joins it).
|
||||||
On read, it comes back as a list in the API response.
|
On read, it comes back as a **string** (e.g. `"shelterluv, api"`), not a list — normalize before
|
||||||
For filtering: use `icontains` on `tags` — e.g. `{"field": "tags", "op": "icontains", "value": "networking"}`.
|
displaying: `[t.strip() for t in tags_str.split(",") if t.strip()]`.
|
||||||
This means a tag search for "net" would match "networking" AND "subnet" — acceptable for now.
|
For filtering: use `icontains` on `tags` inside the `"and"` list, e.g.:
|
||||||
|
`{"field": "tags", "op": "icontains", "value": "networking"}`.
|
||||||
|
A tag search for "net" matches "networking" AND "subnet" — acceptable for now.
|
||||||
True per-tag filtering would require a tags junction table.
|
True per-tag filtering would require a tags junction table.
|
||||||
|
|
||||||
## Notes on `default_qry_str`
|
## Notes on `default_qry_str`
|
||||||
|
|||||||
Reference in New Issue
Block a user