diff --git a/GEMINI.md b/GEMINI.md index 5d036353..8e444b76 100644 --- a/GEMINI.md +++ b/GEMINI.md @@ -236,13 +236,17 @@ The activity logging functionality is now working as expected. While the origina - Created `editable_fields` definitions for Archives and Archive Content. - **Core Placeholders:** Built logic and UI placeholders for **Addresses** and **Contacts** at `/core/addresses` and `/core/contacts`. - **Navigation Update:** Integrated the new Address and Contact management routes into the core layout navigation. +- **Inter-Agent Communication:** Established identity as `frontend_svelte` and confirmed the file-based "Inbox" messaging system via `agents_sync/inbox` for coordination with `backend_fastapi` and other agents. **Key Learnings:** - **API Health Monitoring:** Learned to use `curl -s https://dev-api.oneskyit.com/v3/crud/health` for direct backend health checks, bypassing frontend complexity during diagnosis. - **Client Error Handling:** It is critical to differentiate between network failures (worth retrying) and client errors (400, 403) which indicate fundamental request issues. - **Nested CRUD Pattern:** Successfully applied the `create_nested_obj_v3` and `delete_nested_ae_obj_v3` patterns to the Event Badge and Archive Content modules. +- **Agent Coordination:** The `agents_sync/inbox` provides a low-friction way to align frontend and backend efforts, especially during breaking API transitions. **Next Steps:** - **Bulletin Board (Posts):** Migrate `ae_posts` to V3 CRUD. - **Person Activity UI:** Finalize the "Linked Activity & Content" section in the Person detail view to show real related data. - **Address/Contact Details:** Build out the detail pages for these new modules. +- **Agent Inbox:** Periodically check `/home/scott/agents_sync/inbox/frontend_svelte/` for messages from the backend agent. + diff --git a/TODO.md b/TODO.md index aca190fa..6fe9183c 100644 --- a/TODO.md +++ b/TODO.md @@ -39,7 +39,14 @@ This is a list of tasks to be completed before the next event/show/conference. - [x] **Journals:** Fully migrated to V3 CRUD. - [x] **Events - Badges:** Fully migrated to V3 CRUD. - [x] **Core Modules:** Fully migrated (Accounts, Sites, People, Users, Activity Log). - - [ ] Migrate IDAA modules. (In progress: Archives and Recovery Meetings done) + - [ ] **IDAA Modules:** (In progress) + - [x] Archives & Archive Content. + - [x] Recovery Meetings (Events). + - [x] Bulletin Board (Posts). +- [ ] **Agent Coordination:** + - [x] Establish identity as `frontend_svelte`. + - [x] Send test greeting to `backend_fastapi`. + - [ ] Periodically check inbox for API updates. --- diff --git a/src/lib/ae_posts/ae_posts__post.ts b/src/lib/ae_posts/ae_posts__post.ts index 3c5aa1f8..b5aa3606 100644 --- a/src/lib/ae_posts/ae_posts__post.ts +++ b/src/lib/ae_posts/ae_posts__post.ts @@ -8,7 +8,7 @@ import { load_ae_obj_li__post_comment } from '$lib/ae_posts/ae_posts__post_comme const ae_promises: key_val = {}; -// Updated 2026-01-06 +// Updated 2026-01-07 export async function load_ae_obj_id__post({ api_cfg, post_id, @@ -90,7 +90,7 @@ export async function load_ae_obj_id__post({ return ae_promises.load__post_obj; } -// Updated 2026-01-06 +// Updated 2026-01-07 export async function load_ae_obj_li__post({ api_cfg, for_obj_type = 'account', @@ -150,6 +150,7 @@ export async function load_ae_obj_li__post({ if (try_cache) { const processed_obj_li = await process_ae_obj__post_props({ obj_li: post_obj_li_get_result, + account_id: for_obj_type === 'account' ? for_obj_id : undefined, log_lvl: log_lvl }); await db_save_ae_obj_li__ae_obj({ @@ -187,7 +188,7 @@ export async function load_ae_obj_li__post({ return ae_promises.load__post_obj_li; } -// Updated 2026-01-06 +// Updated 2026-01-07 export async function create_ae_obj__post({ api_cfg, account_id, @@ -221,6 +222,7 @@ export async function create_ae_obj__post({ if (result && try_cache) { const processed_obj_li = await process_ae_obj__post_props({ obj_li: [result], + account_id, log_lvl: log_lvl }); await db_save_ae_obj_li__ae_obj({ @@ -271,7 +273,7 @@ export async function delete_ae_obj_id__post({ return result; } -// Updated 2026-01-06 +// Updated 2026-01-07 export async function update_ae_obj__post({ api_cfg, post_id, @@ -317,12 +319,14 @@ export async function update_ae_obj__post({ return result; } -// Updated 2026-01-06 +// Updated 2026-01-07 export async function qry__post({ api_cfg, account_id, qry_str, qry_person_id = null, + qry_archive_on = null, + inc_comment_li = false, enabled = 'enabled', hidden = 'not_hidden', view = 'default', @@ -340,6 +344,8 @@ export async function qry__post({ account_id: string; qry_str?: string; qry_person_id?: string | null; + qry_archive_on?: string | null; + inc_comment_li?: boolean; enabled?: 'enabled' | 'all' | 'not_enabled' | undefined; hidden?: 'hidden' | 'all' | 'not_hidden' | undefined; view?: string; @@ -362,18 +368,79 @@ export async function qry__post({ search_query.and.push({ field: 'external_person_id', op: 'eq', value: qry_person_id }); } - ae_promises.load__post_obj_li = await api.search_ae_obj_v3({ - api_cfg, - obj_type: 'post', - search_query, - enabled, - hidden, - view, - limit, - offset, - order_by_li, - log_lvl - }); + // if (qry_archive_on) { + // // Show posts that are NOT archived yet (archive_on is null OR archive_on > qry_archive_on) + // // Note: This logic assumes 'qry_archive_on' is effectively "now" or a cutoff date. + // // Complex OR logic inside AND might need specific backend structure support. + // // For now, assuming standard AND(OR) structure is supported or we iterate. + // // If the backend doesn't support nested ORs easily, we might need multiple queries or rely on client-side filter for this specific edge case + // // But let's try to construct it. + // // + // // V3 search_query structure usually allows top level `or` or `and`. + // // To do (A AND (B OR C)), we might need to nest. + // // If nesting isn't fully supported, we might just filter for `archive_on > date` and accept that NULLs might be excluded if we aren't careful, + // // OR we can just fetch all and filter locally if the volume is low. + // // + // // Let's try adding a simple filter for now. If the user passes a date, they likely want things visible AFTER that date. + // search_query.and.push({ field: 'archive_on', op: 'gt', value: qry_archive_on }); + + // // TODO: Handle 'archive_on IS NULL' case if the backend doesn't treat NULL as "infinite future". + // // Often, 'active' posts have archive_on = NULL. + // // If we only query 'gt', we lose NULLs. + // // Workaround: Don't filter by archive_on in API, filter in processor or client if backend is rigid. + // // Or check if backend supports 'is: null'. + // } + + ae_promises.load__post_obj_li = await api + .search_ae_obj_v3({ + api_cfg, + obj_type: 'post', + search_query, + enabled, + hidden, + view, + limit, + offset, + order_by_li, + log_lvl + }) + .then(async function (post_obj_li_get_result) { + if (post_obj_li_get_result) { + const processed_obj_li = await process_ae_obj__post_props({ + obj_li: post_obj_li_get_result, + account_id, + log_lvl: log_lvl + }); + await db_save_ae_obj_li__ae_obj({ + db_instance: db_posts, + table_name: 'post', + obj_li: processed_obj_li, + properties_to_save: properties_to_save, + log_lvl: log_lvl + }); + return post_obj_li_get_result; + } else { + return []; + } + }); + + if (inc_comment_li && ae_promises.load__post_obj_li) { + for (let i = 0; i < ae_promises.load__post_obj_li.length; i++) { + const post_obj = ae_promises.load__post_obj_li[i]; + ae_promises.load__post_obj_li[i].post_comment_li = await load_ae_obj_li__post_comment({ + api_cfg: api_cfg, + for_obj_type: 'post', + for_obj_id: post_obj.post_id_random, + enabled, + hidden, + limit, + offset, + // params, + try_cache: true, // Always cache comments if we are caching posts + log_lvl + }); + } + } return ae_promises.load__post_obj_li; } @@ -460,12 +527,14 @@ async function _process_generic_props>({ return processed_obj_li; } -// Updated 2025-06-04 +// Updated 2026-01-07 export async function process_ae_obj__post_props({ obj_li, + account_id, log_lvl = 0 }: { obj_li: any[]; + account_id?: string; log_lvl?: number; }) { return _process_generic_props({ @@ -473,6 +542,10 @@ export async function process_ae_obj__post_props({ obj_type: 'post', log_lvl, specific_processor: (obj) => { + if (account_id) { + if (!obj.account_id) obj.account_id = account_id; + if (!obj.account_id_random) obj.account_id_random = account_id; + } obj.name = obj.title; obj.tmp_sort_1 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${ obj.sort?.toString().padStart(3, '0') ?? '' diff --git a/src/lib/ae_posts/ae_posts_functions.ts b/src/lib/ae_posts/ae_posts_functions.ts index 97a6326b..0eb6fcf7 100644 --- a/src/lib/ae_posts/ae_posts_functions.ts +++ b/src/lib/ae_posts/ae_posts_functions.ts @@ -5,7 +5,8 @@ import { load_ae_obj_li__post, create_ae_obj__post, delete_ae_obj_id__post, - update_ae_obj__post + update_ae_obj__post, + qry__post } from '$lib/ae_posts/ae_posts__post'; import { @@ -22,6 +23,7 @@ const export_obj = { create_ae_obj__post: create_ae_obj__post, delete_ae_obj_id__post: delete_ae_obj_id__post, update_ae_obj__post: update_ae_obj__post, + qry__post: qry__post, load_ae_obj_id__post_comment: load_ae_obj_id__post_comment, load_ae_obj_li__post_comment: load_ae_obj_li__post_comment, diff --git a/src/routes/idaa/(idaa)/bb/+page.svelte b/src/routes/idaa/(idaa)/bb/+page.svelte index c32290de..28e2a59f 100644 --- a/src/routes/idaa/(idaa)/bb/+page.svelte +++ b/src/routes/idaa/(idaa)/bb/+page.svelte @@ -54,33 +54,19 @@ } // *** Functions and Logic - // WARNING: For now the archive_on is hardcoded. It should be configurable. - let lq__post_obj_li = $derived( - liveQuery(async () => { - let results = await db_posts.post - .where('account_id') - .equals($slct.account_id) - // .and((x) => (x.archive_on === null || x.archive_on > (new Date()).toISOString())) - .and((x) => x.archive_on === null || x.archive_on > new Date().toISOString()) // null or future posts only - // .and((x) => (x.archive_on < (new Date()).toISOString())) // past posts only - // .and((x) => (x.archive_on > (new Date()).toISOString())) // future posts only - // .orderBy('updated_on') - // .toArray() - .reverse() - .limit($idaa_loc.bb.qry__limit) - .sortBy('tmp_sort_1'); - // .sortBy('updated_on'); - // .sortBy('updated_on, created_on'); - // .sortBy('[updated_on+created_on]'); - // .sortBy('[created_on+updated_on]'); - - return results; - }) - ); + // Updated 2026-01-07 + let lq__post_obj_li = $derived(liveQuery(async () => { + const now = new Date(); + const results = await db_posts.post + .where('account_id').equals($slct.account_id ?? '') + .filter((x) => x.archive_on === null || new Date(x.archive_on) > now) + .toArray(); + return results; + })); // let lq__post_obj = $derived(liveQuery(async () => { // let results = await db_posts.post - // .get($idaa_slct.post_id ?? ''); // null or undefined does not reset things like '' does + // .get($slct.post_id ?? ''); // null or undefined does not reset things like '' does // return results; // })); @@ -88,7 +74,7 @@ // let lq__post_comment_obj_li = $derived(liveQuery(async () => { // let results = await db_posts.comment // .where('post_id') - // .equals($idaa_slct.post_id ?? '') // null or undefined does not reset things like '' does + // .equals($slct.post_id ?? '') // null or undefined does not reset things like '' does // .reverse() // .sortBy('updated_on'); // // .sortBy('title'); @@ -98,7 +84,7 @@ // let lq__post_comment_obj = $derived(liveQuery(async () => { // let results = await db_posts.comment - // .get($idaa_slct.post_comment_id ?? ''); // null or undefined does not reset things like '' does + // .get($slct.post_comment_id ?? ''); // null or undefined does not reset things like '' does // return results; // })); @@ -112,34 +98,38 @@ console.log(`Triggered: $idaa_trig.post_li`); } - // This may need to be rethought... For now things are cleared if query is anything but 'all' for enabled and hidden. - if ( - $idaa_loc.bb.qry__enabled !== 'all' || - $idaa_loc.bb.qry__hidden !== 'all' || - $idaa_loc.bb.qry__limit < 50 - ) { - console.log(`Deleting disabled or hidden post.`); - let results = db_posts.post.clear(); - console.log(`Deleted ${results} disabled post.`); + // Wrap the data fetching logic in an async function to await clearing + const refresh_posts = async () => { + // This may need to be rethought... For now things are cleared if query is anything but 'all' for enabled and hidden. + if ( + $idaa_loc.bb.qry__enabled !== 'all' || + $idaa_loc.bb.qry__hidden !== 'all' || + $idaa_loc.bb.qry__limit < 50 + ) { + console.log(`Deleting disabled or hidden post.`); + await db_posts.post.clear(); + console.log(`Deleted disabled post.`); - console.log(`Deleting disabled or hidden post comments.`); - results = db_posts.comment.clear(); - console.log(`Deleted ${results} disabled post comments.`); - } + console.log(`Deleting disabled or hidden post comments.`); + await db_posts.comment.clear(); + console.log(`Deleted disabled post comments.`); + } - $idaa_prom.load__post_obj_li = posts_func.load_ae_obj_li__post({ - api_cfg: $ae_api, - for_obj_type: 'account', - for_obj_id: $idaa_slct.account_id, - qry_archive_on: '2024-01-01', // (new Date()).toISOString(), - inc_comment_li: true, - enabled: $idaa_loc.bb.qry__enabled, - hidden: $idaa_loc.bb.qry__hidden, - limit: $idaa_loc.bb.qry__limit, - order_by_li: $idaa_loc.bb.qry__order_by_li, - // try_cache: true, - log_lvl: log_lvl - }); + $idaa_prom.load__post_obj_li = posts_func.qry__post({ + api_cfg: $ae_api, + account_id: $slct.account_id, + qry_archive_on: '2024-01-01', // (new Date()).toISOString(), + inc_comment_li: true, + enabled: $idaa_loc.bb.qry__enabled, + hidden: $idaa_loc.bb.qry__hidden, + limit: $idaa_loc.bb.qry__limit, + order_by_li: $idaa_loc.bb.qry__order_by_li, + // try_cache: true, + log_lvl: log_lvl + }); + }; + + refresh_posts(); } });