@astralform/js 9.5.0 → 9.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -2334,6 +2334,31 @@ declare class ChatSession {
2334
2334
  * pages, and a doubled prompt is more visible than a missing one.
2335
2335
  */
2336
2336
  prependMessages(older: Message[]): void;
2337
+ /**
2338
+ * Re-fetch the NEWEST page of the conversation list and merge it in.
2339
+ *
2340
+ * The list the sidebar renders is seeded once at `connect()` and then only
2341
+ * changed by this client's own actions (create, delete, rename) — so a row's
2342
+ * `activeJobId` is as fresh as that seed, and a job started in ANOTHER tab or
2343
+ * on another device never appears, while one that ended elsewhere stays lit
2344
+ * forever. A caller that refreshes on a trigger (the tab becoming visible, or
2345
+ * a bounded interval while any job is live) keeps the rows honest without a
2346
+ * socket per conversation.
2347
+ *
2348
+ * Merge rules, and why each is what it is:
2349
+ *
2350
+ * - the server's ORDER wins for the rows it returns: an updated conversation
2351
+ * moves to its new place, which is the whole point of the call;
2352
+ * - rows paged in EARLIER (`loadMoreConversations`) are kept — this reads page
2353
+ * 1 only, and dropping the tail would make a refresh silently truncate a
2354
+ * list the reader has already scrolled;
2355
+ * - a row the caller MINTED locally and the server does not know yet is kept
2356
+ * too (it has no server row to be refreshed by);
2357
+ * - `conversationsGeneration` is bumped, for the same reason `connect()`
2358
+ * bumps it: a page request already in flight was cut against the old head
2359
+ * and its offset no longer means what it did.
2360
+ */
2361
+ refreshConversations(): Promise<Conversation[]>;
2337
2362
  loadMoreConversations(): Promise<Conversation[]>;
2338
2363
  /**
2339
2364
  * Rename a conversation, server first.
package/dist/index.d.ts CHANGED
@@ -2334,6 +2334,31 @@ declare class ChatSession {
2334
2334
  * pages, and a doubled prompt is more visible than a missing one.
2335
2335
  */
2336
2336
  prependMessages(older: Message[]): void;
2337
+ /**
2338
+ * Re-fetch the NEWEST page of the conversation list and merge it in.
2339
+ *
2340
+ * The list the sidebar renders is seeded once at `connect()` and then only
2341
+ * changed by this client's own actions (create, delete, rename) — so a row's
2342
+ * `activeJobId` is as fresh as that seed, and a job started in ANOTHER tab or
2343
+ * on another device never appears, while one that ended elsewhere stays lit
2344
+ * forever. A caller that refreshes on a trigger (the tab becoming visible, or
2345
+ * a bounded interval while any job is live) keeps the rows honest without a
2346
+ * socket per conversation.
2347
+ *
2348
+ * Merge rules, and why each is what it is:
2349
+ *
2350
+ * - the server's ORDER wins for the rows it returns: an updated conversation
2351
+ * moves to its new place, which is the whole point of the call;
2352
+ * - rows paged in EARLIER (`loadMoreConversations`) are kept — this reads page
2353
+ * 1 only, and dropping the tail would make a refresh silently truncate a
2354
+ * list the reader has already scrolled;
2355
+ * - a row the caller MINTED locally and the server does not know yet is kept
2356
+ * too (it has no server row to be refreshed by);
2357
+ * - `conversationsGeneration` is bumped, for the same reason `connect()`
2358
+ * bumps it: a page request already in flight was cut against the old head
2359
+ * and its offset no longer means what it did.
2360
+ */
2361
+ refreshConversations(): Promise<Conversation[]>;
2337
2362
  loadMoreConversations(): Promise<Conversation[]>;
2338
2363
  /**
2339
2364
  * Rename a conversation, server first.
package/dist/index.js CHANGED
@@ -2772,6 +2772,48 @@ var ChatSession = class {
2772
2772
  if (!fresh.length) return;
2773
2773
  this.setMessages([...fresh, ...this.messages]);
2774
2774
  }
2775
+ /**
2776
+ * Re-fetch the NEWEST page of the conversation list and merge it in.
2777
+ *
2778
+ * The list the sidebar renders is seeded once at `connect()` and then only
2779
+ * changed by this client's own actions (create, delete, rename) — so a row's
2780
+ * `activeJobId` is as fresh as that seed, and a job started in ANOTHER tab or
2781
+ * on another device never appears, while one that ended elsewhere stays lit
2782
+ * forever. A caller that refreshes on a trigger (the tab becoming visible, or
2783
+ * a bounded interval while any job is live) keeps the rows honest without a
2784
+ * socket per conversation.
2785
+ *
2786
+ * Merge rules, and why each is what it is:
2787
+ *
2788
+ * - the server's ORDER wins for the rows it returns: an updated conversation
2789
+ * moves to its new place, which is the whole point of the call;
2790
+ * - rows paged in EARLIER (`loadMoreConversations`) are kept — this reads page
2791
+ * 1 only, and dropping the tail would make a refresh silently truncate a
2792
+ * list the reader has already scrolled;
2793
+ * - a row the caller MINTED locally and the server does not know yet is kept
2794
+ * too (it has no server row to be refreshed by);
2795
+ * - `conversationsGeneration` is bumped, for the same reason `connect()`
2796
+ * bumps it: a page request already in flight was cut against the old head
2797
+ * and its offset no longer means what it did.
2798
+ */
2799
+ async refreshConversations() {
2800
+ const page = await this.client.getConversations(CONVERSATION_PAGE_SIZE, 0);
2801
+ const pageIds = new Set(page.map((c) => c.id));
2802
+ const known = new Set(this.conversations.map((c) => c.id));
2803
+ this.conversationsGeneration++;
2804
+ this.conversations = [
2805
+ ...page,
2806
+ // Everything the page did not mention: older pages, and rows that exist
2807
+ // only on this client (a minted conversation the server has not been told
2808
+ // about yet).
2809
+ ...this.conversations.filter((c) => !pageIds.has(c.id))
2810
+ ];
2811
+ for (const c of page) {
2812
+ this.serverConversationIds.add(c.id);
2813
+ known.delete(c.id);
2814
+ }
2815
+ return page;
2816
+ }
2775
2817
  async loadMoreConversations() {
2776
2818
  if (this.isLoadingConversations || !this.hasMoreConversations) return [];
2777
2819
  this.isLoadingConversations = true;