@agentshouse/mdruntime 0.1.0-alpha.24 → 0.1.0-alpha.26

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.
Files changed (52) hide show
  1. package/AGENTS.md +61 -4
  2. package/dist/change-set.d.ts +4 -11
  3. package/dist/change-set.d.ts.map +1 -1
  4. package/dist/change-set.js +8 -16
  5. package/dist/change-set.js.map +1 -1
  6. package/dist/client.d.ts +9 -3
  7. package/dist/client.d.ts.map +1 -1
  8. package/dist/client.js +5 -2
  9. package/dist/client.js.map +1 -1
  10. package/dist/collection.d.ts +0 -2
  11. package/dist/collection.d.ts.map +1 -1
  12. package/dist/collection.js +0 -5
  13. package/dist/collection.js.map +1 -1
  14. package/dist/connection.d.ts +9 -5
  15. package/dist/connection.d.ts.map +1 -1
  16. package/dist/connection.js +67 -67
  17. package/dist/connection.js.map +1 -1
  18. package/dist/conversation.d.ts +7 -4
  19. package/dist/conversation.d.ts.map +1 -1
  20. package/dist/conversation.js +29 -6
  21. package/dist/conversation.js.map +1 -1
  22. package/dist/host.d.ts.map +1 -1
  23. package/dist/host.js +2 -0
  24. package/dist/host.js.map +1 -1
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js.map +1 -1
  28. package/dist/paths.d.ts +1 -0
  29. package/dist/paths.d.ts.map +1 -1
  30. package/dist/paths.js +8 -0
  31. package/dist/paths.js.map +1 -1
  32. package/dist/query.d.ts +206 -10
  33. package/dist/query.d.ts.map +1 -1
  34. package/dist/query.js +463 -14
  35. package/dist/query.js.map +1 -1
  36. package/dist/read-side.d.ts +13 -0
  37. package/dist/read-side.d.ts.map +1 -0
  38. package/dist/read-side.js +393 -0
  39. package/dist/read-side.js.map +1 -0
  40. package/dist/rows.d.ts +39 -0
  41. package/dist/rows.d.ts.map +1 -0
  42. package/dist/rows.js +85 -0
  43. package/dist/rows.js.map +1 -0
  44. package/dist/search.d.ts +61 -0
  45. package/dist/search.d.ts.map +1 -0
  46. package/dist/search.js +155 -0
  47. package/dist/search.js.map +1 -0
  48. package/dist/wire.d.ts +2 -2
  49. package/dist/wire.d.ts.map +1 -1
  50. package/dist/wire.js +2 -1
  51. package/dist/wire.js.map +1 -1
  52. package/package.json +3 -2
@@ -1,11 +1,13 @@
1
- import { rawQuery } from './query.js';
2
1
  import { verify } from '@agentshouse/mdmodel';
3
2
  import { cached, modelTypes, NO_MODEL, sameModel } from './model.js';
3
+ import { filterOf, identityOf, planOf } from './query.js';
4
+ import { createReadSide } from './read-side.js';
5
+ import { createSearchIndex, searchPlanOf } from './search.js';
4
6
  import { ROOM_CONTRACT_VERSION, VERSION_1_CAPABILITIES } from './adapter.js';
5
7
  import { bootstrapRoom } from './bootstrap.js';
6
8
  import { changeSet, mergeChangeSets } from './change-set.js';
7
9
  import { createConversationStore } from './conversation.js';
8
- import { MD_MODEL, PRESENTED, validRoot } from './collection.js';
10
+ import { MD_MODEL, validRoot } from './collection.js';
9
11
  import { createLog } from './log.js';
10
12
  import { refreshRoom } from './refresh.js';
11
13
  import { buildBatch } from './save.js';
@@ -58,6 +60,7 @@ export function createMdRuntime(options) {
58
60
  const invalidModels = new Set();
59
61
  const modelEpoch = new Map();
60
62
  const discovered = new Map();
63
+ let roomsListed = false;
61
64
  const scopedRefusals = new Map();
62
65
  function modelKey(locator, attached) {
63
66
  return `${attached} ${locator}`;
@@ -97,21 +100,32 @@ export function createMdRuntime(options) {
97
100
  const refusalListeners = new Set();
98
101
  const storageLossListeners = new Set();
99
102
  const statusListeners = new Set();
100
- const querySubscriptions = new Set();
101
103
  const queueSubscriptions = new Set();
102
104
  const roomDraftListeners = new Set();
103
105
  const presentationListeners = new Set();
106
+ const readSide = createReadSide();
104
107
  let withdrawConversations;
105
108
  let currencyQueued = false;
106
109
  const conversations = createConversationStore({
107
110
  cards: declaredCards,
108
- documents: ()=>visible({}).documents,
111
+ documents: (locator)=>readSide.query(planOf({
112
+ rooms: [
113
+ locator
114
+ ],
115
+ select: 'all'
116
+ }, roomFacts())),
109
117
  call: (name, input)=>invokeAction(name, input),
110
118
  durably,
111
119
  stream: ()=>options.adapter.conversations,
112
120
  publish: publishChangeSet,
113
121
  closed: ()=>closed
114
122
  });
123
+ const searchIndex = createSearchIndex({
124
+ documents: ()=>readSide.documents(),
125
+ document: (room, path)=>readSide.document(room, path),
126
+ messages: ()=>conversations.messages(),
127
+ message: (conversation, identity)=>conversations.message(conversation, identity)
128
+ });
115
129
  const journal = createLog();
116
130
  let notifyReady = ()=>{};
117
131
  const ready = new Promise((resolve)=>{
@@ -223,16 +237,26 @@ export function createMdRuntime(options) {
223
237
  })
224
238
  })));
225
239
  }
226
- function queryRooms() {
227
- return [
228
- ...replicas.values()
229
- ].map((replica)=>({
230
- room: replica.confirmed.record.locator,
231
- roomVersion: replica.confirmed.record.roomVersion,
232
- documents: replica.visible.collection.documents,
233
- model: modelTypes(modelOf(replica.confirmed.record.locator)),
234
- typedSelection: replica.confirmed.record.typedSelection === null ? null : modelTypes(modelOf(replica.confirmed.record.locator, 'typed-selection'))
235
- }));
240
+ function roomFacts() {
241
+ const held = [
242
+ ...rooms.values()
243
+ ].map((room)=>{
244
+ const attached = [
245
+ modelOf(room.locator),
246
+ ...room.typedSelection === null ? [] : [
247
+ modelOf(room.locator, 'typed-selection')
248
+ ]
249
+ ];
250
+ return {
251
+ locator: room.locator,
252
+ available: attached.every((model)=>model.status !== 'unavailable'),
253
+ types: attached.flatMap((model)=>model.status === 'unavailable' ? [] : Object.values(model.types))
254
+ };
255
+ });
256
+ return {
257
+ listed: roomsListed,
258
+ rooms: held
259
+ };
236
260
  }
237
261
  function emitRooms() {
238
262
  const value = listed();
@@ -259,26 +283,6 @@ export function createMdRuntime(options) {
259
283
  shown = next;
260
284
  for (const listener of statusListeners)listener(shown);
261
285
  }
262
- function visible(request) {
263
- if (options.queryBinding === null) {
264
- if (Object.keys(request).length > 0) throw new Error('query-binding-unavailable');
265
- return rawQuery(queryRooms());
266
- }
267
- return options.queryBinding(queryRooms(), {
268
- ...request,
269
- selector: {
270
- $and: [
271
- PRESENTED,
272
- request.selector ?? {}
273
- ]
274
- }
275
- });
276
- }
277
- function emitVisible() {
278
- for (const subscription of querySubscriptions){
279
- subscription.notify(visible(subscription.query));
280
- }
281
- }
282
286
  function submissionOf(batch) {
283
287
  return pendings.get(batch.id)?.submission ?? {
284
288
  state: 'waiting'
@@ -298,9 +302,13 @@ export function createMdRuntime(options) {
298
302
  if (subscription.locator === locator) subscription.notify(entries);
299
303
  }
300
304
  }
305
+ function applyChangeSet(set) {
306
+ readSide.apply(set);
307
+ searchIndex.changed(set);
308
+ }
301
309
  function publishChangeSet(set) {
310
+ applyChangeSet(set);
302
311
  if (set.rooms.length > 0) emitRooms();
303
- if (set.documents.length > 0 || set.query) emitVisible();
304
312
  for (const locator of set.queues)emitQueue(locator);
305
313
  if (set.drafts.length > 0 || set.documents.some((change)=>roomDrafts.get(change.locator)?.has(change.path) === true)) {
306
314
  publishRoomDrafts(false);
@@ -377,8 +385,7 @@ export function createMdRuntime(options) {
377
385
  }
378
386
  });
379
387
  changed.push(changeSet(locator, before, replicas.get(locator) ?? null, {
380
- room: true,
381
- query: true
388
+ room: true
382
389
  }));
383
390
  }
384
391
  publishChangeSet(mergeChangeSets(changed));
@@ -429,6 +436,7 @@ export function createMdRuntime(options) {
429
436
  }
430
437
  list(room, room.replica.admission === 'admitted' && !unreadable.has(room.locator));
431
438
  }
439
+ roomsListed = true;
432
440
  emitRooms();
433
441
  }
434
442
  function unlistedHeld(listed) {
@@ -452,7 +460,6 @@ export function createMdRuntime(options) {
452
460
  const removed = unlisted.map((locator)=>changeSet(locator, replicas.get(locator) ?? null, null, {
453
461
  room: true,
454
462
  queue: true,
455
- query: true,
456
463
  drafts: [
457
464
  ...roomDrafts.get(locator)?.keys() ?? []
458
465
  ]
@@ -569,15 +576,19 @@ export function createMdRuntime(options) {
569
576
  locators: new Set([
570
577
  ...queuedBatches.keys(),
571
578
  ...replicas.keys()
572
- ])
579
+ ]),
580
+ read: mergeChangeSets([
581
+ ...new Set([
582
+ ...previousReplicas.keys(),
583
+ ...replicas.keys()
584
+ ])
585
+ ].map((locator)=>changeSet(locator, previousReplicas.get(locator) ?? null, replicas.get(locator) ?? null)))
573
586
  };
574
587
  }
575
588
  async function readState(opened) {
576
- const { lastCompleted, locators } = await hydrate(opened);
577
- if (replicas.size > 0) {
578
- emitRooms();
579
- emitVisible();
580
- }
589
+ const { lastCompleted, locators, read } = await hydrate(opened);
590
+ applyChangeSet(read);
591
+ if (replicas.size > 0) emitRooms();
581
592
  for (const locator of locators)emitQueue(locator);
582
593
  publishRoomDrafts(false);
583
594
  return lastCompleted;
@@ -689,7 +700,6 @@ export function createMdRuntime(options) {
689
700
  replicas.set(locator, replicaOf(confirmed, kept, rewriting(), before));
690
701
  return changeSet(locator, before ?? null, replicas.get(locator) ?? null, {
691
702
  room: settling.room,
692
- query: settling.query,
693
703
  queue: kept.length !== (before?.queue.length ?? 0),
694
704
  drafts: [
695
705
  ...written.keys()
@@ -707,14 +717,12 @@ export function createMdRuntime(options) {
707
717
  if (retained === null) {
708
718
  list(room, true);
709
719
  publishChangeSet(changeSet(room.locator, prior ?? null, prior ?? null, {
710
- room: true,
711
- query: true
720
+ room: true
712
721
  }));
713
722
  return;
714
723
  }
715
724
  const set = await settle(local, room.locator, prior, retained, prior?.queue ?? [], {
716
- room: true,
717
- query: true
725
+ room: true
718
726
  });
719
727
  unreadable.delete(room.locator);
720
728
  list(room, true);
@@ -1082,8 +1090,7 @@ export function createMdRuntime(options) {
1082
1090
  id: submitted.id,
1083
1091
  outcome: acceptedOutcome
1084
1092
  },
1085
- room: true,
1086
- query: true
1093
+ room: true
1087
1094
  });
1088
1095
  unreadable.delete(room.locator);
1089
1096
  list(room, true);
@@ -1261,7 +1268,6 @@ export function createMdRuntime(options) {
1261
1268
  const previous = modelOf(room.locator, attached);
1262
1269
  const heldBefore = replicas.get(room.locator)?.confirmed.record;
1263
1270
  if (JSON.stringify(previous) === JSON.stringify(next) && (heldBefore === undefined || JSON.stringify(heldBefore.operations) === JSON.stringify(room.operations) && JSON.stringify(heldBefore.replica) === JSON.stringify(room.replica) && JSON.stringify(heldBefore.attachedModel) === JSON.stringify(room.attachedModel) && JSON.stringify(heldBefore.typedSelection) === JSON.stringify(room.typedSelection ?? null))) return;
1264
- const queryChanged = previous.status === 'unavailable' || next.status === 'unavailable' ? previous.status !== next.status : JSON.stringify(previous.types) !== JSON.stringify(next.types);
1265
1271
  if (next.status === 'unavailable') {
1266
1272
  invalidModels.add(key);
1267
1273
  liveModels.delete(key);
@@ -1300,8 +1306,7 @@ export function createMdRuntime(options) {
1300
1306
  list(room, room.replica.admission === 'admitted' && !unreadable.has(room.locator));
1301
1307
  if (held === undefined) emitRooms();
1302
1308
  else publishChangeSet(changeSet(room.locator, held, replicas.get(room.locator) ?? null, {
1303
- room: true,
1304
- query: queryChanged
1309
+ room: true
1305
1310
  }));
1306
1311
  });
1307
1312
  }
@@ -1751,7 +1756,7 @@ export function createMdRuntime(options) {
1751
1756
  refusalListeners.clear();
1752
1757
  storageLossListeners.clear();
1753
1758
  statusListeners.clear();
1754
- querySubscriptions.clear();
1759
+ readSide.close();
1755
1760
  queueSubscriptions.clear();
1756
1761
  roomDraftListeners.clear();
1757
1762
  presentationListeners.clear();
@@ -1774,8 +1779,11 @@ export function createMdRuntime(options) {
1774
1779
  slots () {
1775
1780
  return slotted();
1776
1781
  },
1777
- query (request = {}) {
1778
- return visible(request);
1782
+ query: (input)=>readSide.query(planOf(input, roomFacts())),
1783
+ async search (input) {
1784
+ const plan = searchPlanOf(input);
1785
+ const selected = plan.documents === undefined ? null : (await readSide.query(filterOf(plan.documents, roomFacts()))).documents;
1786
+ return searchIndex.search(plan, selected);
1779
1787
  },
1780
1788
  types (locator) {
1781
1789
  return {
@@ -1989,16 +1997,8 @@ export function createMdRuntime(options) {
1989
1997
  queueSubscriptions.delete(queue);
1990
1998
  };
1991
1999
  }
1992
- const subscription = {
1993
- query: second,
1994
- notify: third
1995
- };
1996
- const first = visible(subscription.query);
1997
- querySubscriptions.add(subscription);
1998
- subscription.notify(first);
1999
- return ()=>{
2000
- querySubscriptions.delete(subscription);
2001
- };
2000
+ const plan = planOf(second, roomFacts());
2001
+ return readSide.observe(plan, identityOf(plan), third);
2002
2002
  },
2003
2003
  async reauthorize () {
2004
2004
  if (refusal === null || !refusal.reauthorizationOffered) return;