@agentshouse/mdruntime 0.1.0-cf08ada271a7f → 0.1.0-cf0c43fc48aad

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 (168) hide show
  1. package/README.md +12 -12
  2. package/dist/acceptance.d.ts.map +1 -1
  3. package/dist/acceptance.js +25 -35
  4. package/dist/act-lanes.d.ts +30 -0
  5. package/dist/act-lanes.d.ts.map +1 -0
  6. package/dist/act-lanes.js +225 -0
  7. package/dist/actions.d.ts +8 -2
  8. package/dist/actions.d.ts.map +1 -1
  9. package/dist/actions.js +116 -65
  10. package/dist/adapter.d.ts +11 -4
  11. package/dist/adapter.d.ts.map +1 -1
  12. package/dist/client.d.ts +6 -17
  13. package/dist/client.d.ts.map +1 -1
  14. package/dist/client.js +26 -11
  15. package/dist/compile.d.ts +2 -0
  16. package/dist/compile.d.ts.map +1 -1
  17. package/dist/compile.js +17 -4
  18. package/dist/connection.d.ts.map +1 -1
  19. package/dist/connection.js +15 -10
  20. package/dist/conversation-live.d.ts +7 -2
  21. package/dist/conversation-live.d.ts.map +1 -1
  22. package/dist/conversation-live.js +6 -3
  23. package/dist/conversation.d.ts +25 -5
  24. package/dist/conversation.d.ts.map +1 -1
  25. package/dist/conversation.js +157 -76
  26. package/dist/discovery.d.ts.map +1 -1
  27. package/dist/discovery.js +18 -45
  28. package/dist/durability.d.ts +3 -0
  29. package/dist/durability.d.ts.map +1 -1
  30. package/dist/entry.js +1 -1
  31. package/dist/expectation.d.ts +25 -14
  32. package/dist/expectation.d.ts.map +1 -1
  33. package/dist/expectation.js +51 -20
  34. package/dist/failure.d.ts +2 -0
  35. package/dist/failure.d.ts.map +1 -1
  36. package/dist/failure.js +3 -0
  37. package/dist/host.d.ts.map +1 -1
  38. package/dist/host.js +29 -7
  39. package/dist/index.d.ts +9 -7
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +7 -5
  42. package/dist/install.d.ts +2 -3
  43. package/dist/install.d.ts.map +1 -1
  44. package/dist/install.js +9 -22
  45. package/dist/lifecycle.d.ts +1 -1
  46. package/dist/lifecycle.d.ts.map +1 -1
  47. package/dist/lifecycle.js +32 -26
  48. package/dist/listing.d.ts +4 -9
  49. package/dist/listing.d.ts.map +1 -1
  50. package/dist/listing.js +21 -51
  51. package/dist/locks.d.ts +2 -4
  52. package/dist/locks.d.ts.map +1 -1
  53. package/dist/locks.js +8 -38
  54. package/dist/lost.d.ts.map +1 -1
  55. package/dist/lost.js +7 -19
  56. package/dist/media.js +1 -1
  57. package/dist/memory.d.ts.map +1 -1
  58. package/dist/memory.js +36 -17
  59. package/dist/messages.d.ts +9 -2
  60. package/dist/messages.d.ts.map +1 -1
  61. package/dist/messages.js +20 -10
  62. package/dist/models.d.ts.map +1 -1
  63. package/dist/models.js +15 -32
  64. package/dist/opened.d.ts +1 -1
  65. package/dist/opened.d.ts.map +1 -1
  66. package/dist/opened.js +2 -2
  67. package/dist/opening.d.ts.map +1 -1
  68. package/dist/opening.js +3 -9
  69. package/dist/outcome.d.ts +3 -0
  70. package/dist/outcome.d.ts.map +1 -1
  71. package/dist/outcome.js +15 -0
  72. package/dist/overlay.d.ts +3 -0
  73. package/dist/overlay.d.ts.map +1 -1
  74. package/dist/overlay.js +8 -4
  75. package/dist/page-metadata.d.ts +8 -0
  76. package/dist/page-metadata.d.ts.map +1 -0
  77. package/dist/page-metadata.js +19 -0
  78. package/dist/parts.d.ts +2 -9
  79. package/dist/parts.d.ts.map +1 -1
  80. package/dist/parts.js +6 -14
  81. package/dist/preparation.d.ts.map +1 -1
  82. package/dist/preparation.js +15 -21
  83. package/dist/presence.d.ts +52 -0
  84. package/dist/presence.d.ts.map +1 -0
  85. package/dist/presence.js +220 -0
  86. package/dist/queries.d.ts +1 -1
  87. package/dist/queries.d.ts.map +1 -1
  88. package/dist/queries.js +23 -13
  89. package/dist/questions.d.ts +0 -5
  90. package/dist/questions.d.ts.map +1 -1
  91. package/dist/questions.js +0 -7
  92. package/dist/queue.d.ts +2 -1
  93. package/dist/queue.d.ts.map +1 -1
  94. package/dist/queue.js +26 -31
  95. package/dist/reach.d.ts.map +1 -1
  96. package/dist/reach.js +62 -18
  97. package/dist/react.d.ts +5 -4
  98. package/dist/react.d.ts.map +1 -1
  99. package/dist/react.js +28 -5
  100. package/dist/reads.d.ts +3 -1
  101. package/dist/reads.d.ts.map +1 -1
  102. package/dist/reads.js +5 -1
  103. package/dist/recovery.d.ts +3 -1
  104. package/dist/recovery.d.ts.map +1 -1
  105. package/dist/recovery.js +29 -7
  106. package/dist/refusal.d.ts.map +1 -1
  107. package/dist/refusal.js +2 -4
  108. package/dist/retried.d.ts +30 -0
  109. package/dist/retried.d.ts.map +1 -0
  110. package/dist/retried.js +72 -0
  111. package/dist/room-draft.d.ts +2 -2
  112. package/dist/room-draft.d.ts.map +1 -1
  113. package/dist/room-draft.js +24 -19
  114. package/dist/runtime.d.ts +4 -2
  115. package/dist/runtime.d.ts.map +1 -1
  116. package/dist/save.d.ts +1 -0
  117. package/dist/save.d.ts.map +1 -1
  118. package/dist/save.js +105 -55
  119. package/dist/saves.d.ts.map +1 -1
  120. package/dist/saves.js +8 -11
  121. package/dist/seed.js +2 -2
  122. package/dist/shown.d.ts +2 -2
  123. package/dist/shown.d.ts.map +1 -1
  124. package/dist/shown.js +14 -23
  125. package/dist/socket/lanes.d.ts +12 -4
  126. package/dist/socket/lanes.d.ts.map +1 -1
  127. package/dist/socket/lanes.js +34 -8
  128. package/dist/socket.d.ts +3 -5
  129. package/dist/socket.d.ts.map +1 -1
  130. package/dist/socket.js +3 -14
  131. package/dist/source.d.ts +0 -7
  132. package/dist/source.d.ts.map +1 -1
  133. package/dist/store/records.d.ts +7 -3
  134. package/dist/store/records.d.ts.map +1 -1
  135. package/dist/store/records.js +12 -2
  136. package/dist/store.d.ts +10 -5
  137. package/dist/store.d.ts.map +1 -1
  138. package/dist/store.js +37 -12
  139. package/dist/stored.d.ts +1 -0
  140. package/dist/stored.d.ts.map +1 -1
  141. package/dist/stored.js +5 -5
  142. package/dist/surface.d.ts +1 -1
  143. package/dist/surface.d.ts.map +1 -1
  144. package/dist/surface.js +9 -13
  145. package/dist/sync.d.ts.map +1 -1
  146. package/dist/sync.js +63 -58
  147. package/dist/tables.d.ts +6 -3
  148. package/dist/tables.d.ts.map +1 -1
  149. package/dist/tables.js +34 -10
  150. package/dist/wire.d.ts +47 -3
  151. package/dist/wire.d.ts.map +1 -1
  152. package/dist/wire.js +12 -1
  153. package/package.json +3 -3
  154. package/dist/attempt.d.ts +0 -16
  155. package/dist/attempt.d.ts.map +0 -1
  156. package/dist/attempt.js +0 -70
  157. package/dist/job.d.ts +0 -5
  158. package/dist/job.d.ts.map +0 -1
  159. package/dist/job.js +0 -7
  160. package/dist/log.d.ts +0 -6
  161. package/dist/log.d.ts.map +0 -1
  162. package/dist/log.js +0 -14
  163. package/dist/socket/rooms.d.ts +0 -41
  164. package/dist/socket/rooms.d.ts.map +0 -1
  165. package/dist/socket/rooms.js +0 -90
  166. package/dist/store/fences.d.ts +0 -16
  167. package/dist/store/fences.d.ts.map +0 -1
  168. package/dist/store/fences.js +0 -26
@@ -11,6 +11,7 @@ import { runningLine } from './parts.js';
11
11
  import { record, text } from './read.js';
12
12
  import { openQuestion, questionAsked } from './questions.js';
13
13
  import { untilAnswered } from './recovery.js';
14
+ import { retrying } from './retried.js';
14
15
  import { capped, FROM_START, messageOrder, precedes } from './windows.js';
15
16
  export function unheldView(conversation) {
16
17
  return {
@@ -25,12 +26,17 @@ export function unheldView(conversation) {
25
26
  starting: null,
26
27
  state: null,
27
28
  link: null,
29
+ deliveryWaiting: [],
28
30
  deliveryUnknown: [],
29
31
  chatDraft: null,
32
+ dismissedSuggestion: null,
30
33
  };
31
34
  }
32
35
  export const SESSION_STARTED = 'Session started';
33
36
  const NEW_CHAT = 'new:';
37
+ const LISTING = 'listing';
38
+ const AGENTS = 'agents';
39
+ export const CATCHING_UP = 'catching-up';
34
40
  export const HISTORY_CONVERSATIONS = 64;
35
41
  export function newChat(agent) {
36
42
  return `${NEW_CHAT}${agent}`;
@@ -74,7 +80,7 @@ function frameOf(asked, messages, more, total) {
74
80
  };
75
81
  }
76
82
  function newestOf(arriving, from) {
77
- return arriving.reduce((top, message) => (top === null || message.position > top ? message.position : top), from);
83
+ return arriving.reduce((top, message) => (top === null || message.change > top ? message.change : top), from);
78
84
  }
79
85
  function acceptedMessage(value) {
80
86
  if (typeof value !== 'object' || value === null)
@@ -83,6 +89,7 @@ function acceptedMessage(value) {
83
89
  if (typeof record.identity !== 'string' ||
84
90
  typeof record.turn !== 'string' ||
85
91
  typeof record.position !== 'string' ||
92
+ typeof record.change !== 'string' ||
86
93
  typeof record.text !== 'string') {
87
94
  return null;
88
95
  }
@@ -90,6 +97,7 @@ function acceptedMessage(value) {
90
97
  identity: record.identity,
91
98
  turn: record.turn,
92
99
  position: record.position,
100
+ change: record.change,
93
101
  text: record.text,
94
102
  message: structuredClone(record.message),
95
103
  };
@@ -191,17 +199,17 @@ function withSubmitted(draft, submitted) {
191
199
  const { submitted: _held, ...unsent } = draft;
192
200
  return submitted.length === 0 ? unsent : { ...unsent, submitted };
193
201
  }
194
- function prepended(draft, said) {
195
- return { text: [said.text, draft.text].filter((one) => one !== '').join('\n') };
202
+ export function joinedDraft(first, second) {
203
+ return [first, second].filter((one) => one !== '').join('\n');
196
204
  }
197
205
  function returned(draft, submission, others) {
198
206
  return withSubmitted({
199
207
  conversation: draft.conversation,
200
- ...prepended(draft, submission),
208
+ text: joinedDraft(submission.text, draft.text),
201
209
  revision: chatDraftRevision(),
202
210
  }, others);
203
211
  }
204
- function viewOf(alive, conversation, held, frame, draft, ended) {
212
+ function viewOf(alive, conversation, held, frame, draft, ended, dismissed) {
205
213
  const facts = alive.liveOf(conversation);
206
214
  return {
207
215
  conversation,
@@ -221,8 +229,10 @@ function viewOf(alive, conversation, held, frame, draft, ended) {
221
229
  starting: facts.starting,
222
230
  state: sessionOf(facts, held, ended),
223
231
  link: facts.link === null ? null : { ...facts.link },
232
+ deliveryWaiting: [...facts.deliveryWaiting],
224
233
  deliveryUnknown: [...facts.deliveryUnknown],
225
234
  chatDraft: draft === null || unwritten(draft) ? null : { text: draft.text, revision: draft.revision },
235
+ dismissedSuggestion: dismissed,
226
236
  };
227
237
  }
228
238
  function sessionOf(facts, held, ended) {
@@ -242,13 +252,14 @@ function emit(alive, conversation) {
242
252
  if (alive.deps.closed())
243
253
  return;
244
254
  for (const view of alive.views()) {
245
- const { window, draft, ended } = view.held.now();
255
+ const { window, draft, ended, dismissed } = view.held.now();
246
256
  if (view.conversation !== conversation || window === null)
247
257
  continue;
248
258
  const ready = view.ready();
249
259
  if (ready.length === 0)
250
260
  continue;
251
- const value = viewOf(alive, conversation, window, sharedFrame(view, window), draft, ended);
261
+ const frame = sharedFrame(view, window);
262
+ const value = viewOf(alive, conversation, window, frame, draft, ended, dismissed);
252
263
  for (const watcher of ready)
253
264
  watcher.notify(value);
254
265
  }
@@ -397,7 +408,7 @@ async function told(alive) {
397
408
  try {
398
409
  while (alive.held.now().listOwed && !alive.deps.closed()) {
399
410
  alive.held.set({ listOwed: false });
400
- const value = await untilAnswered(() => entries(alive), alive.closing);
411
+ const value = await untilAnswered(retrying(alive.deps.retries, 'conversations', LISTING, () => entries(alive)), alive.closing, () => true, alive.deps.recovery);
401
412
  if (alive.deps.closed())
402
413
  return;
403
414
  if (value === null)
@@ -440,15 +451,24 @@ export function conversationsLearned(alive) {
440
451
  shownList(alive, (list) => alive.agentListeners.welcome(agents(alive, list)));
441
452
  }
442
453
  function agents(alive, list) {
443
- const named = new Map();
444
- for (const agent of alive.held.now().listedAgents ?? [])
445
- named.set(agent.agent, agent);
454
+ const read = new Map((alive.held.now().listedAgents ?? []).map((one) => [one.agent, one]));
455
+ const named = new Map(read);
446
456
  for (const entry of list) {
447
457
  named.set(entry.agent, { name: entry.agentName, retired: entry.agentRetired });
448
458
  }
449
459
  return [...named]
450
460
  .filter(([, agent]) => !agent.retired)
451
- .map(([identity, agent]) => ({ identity, name: agent.name }))
461
+ .map(([identity, agent]) => {
462
+ const held = read.get(identity);
463
+ return held === undefined
464
+ ? { identity, name: agent.name }
465
+ : {
466
+ identity,
467
+ name: agent.name,
468
+ cli: held.cli,
469
+ environment: structuredClone(held.environment),
470
+ };
471
+ })
452
472
  .sort((left, right) => left.name === right.name
453
473
  ? left.identity.localeCompare(right.identity)
454
474
  : left.name.localeCompare(right.name));
@@ -465,7 +485,7 @@ function readAgents(alive) {
465
485
  if (!alive.deps.online() || (!agentListeners.waiting() && !agentListeners.told())) {
466
486
  return 'done';
467
487
  }
468
- const listed = await read();
488
+ const listed = await retrying(alive.deps.retries, 'conversations', AGENTS, read)();
469
489
  if (listed === null)
470
490
  return 'done';
471
491
  alive.held.set({ listedAgents: listed });
@@ -524,6 +544,7 @@ function openingEnded(alive) {
524
544
  starting: facts.has('starting') ? QUIET.starting : held.starting,
525
545
  state: facts.has('state') ? QUIET.state : held.state,
526
546
  link: facts.has('link') ? QUIET.link : held.link,
547
+ deliveryWaiting: facts.has('deliveryWaiting') ? QUIET.deliveryWaiting : held.deliveryWaiting,
527
548
  deliveryUnknown: facts.has('deliveryUnknown') ? QUIET.deliveryUnknown : held.deliveryUnknown,
528
549
  });
529
550
  emit(alive, conversation);
@@ -555,19 +576,13 @@ function handReplicated(alive) {
555
576
  }
556
577
  async function remove(alive, leaving) {
557
578
  await alive.deps.durably(async (local) => {
558
- const kept = new Set([
559
- ...(await local.conversations(leaving)).map(({ conversation }) => conversation),
560
- ...(await local.chatDrafts())
561
- .filter(({ conversation }) => leaving.includes(conversation))
562
- .map(({ conversation }) => conversation),
563
- ]);
564
- await local.dropConversations(leaving);
579
+ const kept = new Set(await local.dropConversations(leaving));
565
580
  const changed = [];
566
581
  for (const conversation of leaving) {
567
582
  if (kept.has(conversation) || alive.liveHeld(conversation) !== undefined) {
568
583
  changed.push(conversation);
569
584
  }
570
- shownDraft(alive, conversation, null);
585
+ heldInViews(alive, conversation, { draft: null, dismissed: null });
571
586
  alive.forget(conversation);
572
587
  setLive(alive, conversation, null);
573
588
  await slide(alive, local, conversation, null);
@@ -639,14 +654,12 @@ function keep(alive, conversation, message) {
639
654
  if (!alive.held.now().replicated.has(conversation))
640
655
  return;
641
656
  const read = (await readsOf(local, [conversation])).get(conversation)?.read;
642
- const advances = read !== undefined &&
643
- !alive.behind(conversation) &&
644
- (read === null || message.position > read);
657
+ const advances = read !== undefined && !alive.behind(conversation) && (read === null || message.change > read);
645
658
  await sealed(alive, local, conversation, new Set([message.turn]));
646
659
  await local.keepMessages({
647
660
  conversation,
648
661
  messages: [message],
649
- ...(advances ? { read: { at: message.position, partial: false } } : {}),
662
+ ...(advances ? { read: { at: message.change, partial: false } } : {}),
650
663
  });
651
664
  sealTurns(alive, conversation, new Set([message.turn]));
652
665
  await slide(alive, local, conversation, [message]);
@@ -767,13 +780,16 @@ function heard(alive, event) {
767
780
  return;
768
781
  }
769
782
  if (event.kind === 'deliveries') {
770
- live(alive, conversation, { deliveryUnknown: [...event.unknown] });
783
+ live(alive, conversation, {
784
+ deliveryWaiting: [...event.waiting],
785
+ deliveryUnknown: [...event.unknown],
786
+ });
771
787
  return;
772
788
  }
773
789
  const arriving = acceptedMessage(event.message);
774
790
  if (arriving === null)
775
791
  return;
776
- alive.heardAt(conversation, arriving.position);
792
+ alive.heardAt(conversation, arriving.change);
777
793
  if (alive.held.now().replicated.has(conversation)) {
778
794
  if (alive.deps.full()) {
779
795
  alive.gapOpened(conversation);
@@ -791,19 +807,27 @@ function heard(alive, event) {
791
807
  emit(alive, conversation);
792
808
  }
793
809
  async function kept(alive, local, conversation, following) {
794
- const shown = following === null || empty(following) ? null : following;
795
- if (shown === null)
810
+ const draft = following === null || empty(following) ? null : following;
811
+ if (draft === null)
796
812
  await local.dropChatDraft(conversation);
797
813
  else
798
- await local.keepChatDrafts([shown]);
799
- shownDraft(alive, conversation, shown);
814
+ await local.keepChatDrafts([draft]);
815
+ heldInViews(alive, conversation, { draft });
800
816
  }
801
- function shownDraft(alive, conversation, draft) {
817
+ function heldInViews(alive, conversation, held) {
802
818
  for (const view of alive.views()) {
803
819
  if (view.conversation === conversation)
804
- view.held.set({ draft });
820
+ view.held.set(held);
805
821
  }
806
822
  }
823
+ async function factOf(local, name) {
824
+ return Object.fromEntries((await local.conversationFacts())
825
+ .filter((fact) => fact.name === name)
826
+ .map(({ conversation, value }) => [conversation, value]));
827
+ }
828
+ async function dismissedIn(local, conversation) {
829
+ return (await factOf(local, 'dismissedSuggestion'))[conversation] ?? null;
830
+ }
807
831
  async function draftAt(local, conversation) {
808
832
  return (await local.chatDraft(conversation)) ?? undefined;
809
833
  }
@@ -834,9 +858,9 @@ function moved(alive, agent, operation, to) {
834
858
  : [{ ...unsent, conversation: to }];
835
859
  const left = { ...(taken.length === 0 ? unsent : blank), moves: [...earlier, operation] };
836
860
  await local.keepChatDrafts([left, ...taken]);
837
- shownDraft(alive, from, left);
861
+ heldInViews(alive, from, { draft: left });
838
862
  for (const one of taken)
839
- shownDraft(alive, to, one);
863
+ heldInViews(alive, to, { draft: one });
840
864
  alive.deps.publish(conversationChangeSet([from, to]));
841
865
  });
842
866
  }
@@ -867,13 +891,10 @@ async function submitted(alive, conversation, operation, draft) {
867
891
  });
868
892
  return submission;
869
893
  }
870
- async function dispatched(alive, conversation, submission) {
894
+ async function dispatched(alive, conversation, submission, resent = false) {
871
895
  const dispatch = alive.sendingBegan(submission.operation);
872
896
  try {
873
- const result = await invoke(alive, 'conversations/send', conversation, {
874
- operation_id: submission.operation,
875
- text: submission.text,
876
- });
897
+ const result = await invoke(alive, 'conversations/send', conversation, submission.operation, { text: submission.text }, { step: 'sending', instance: `message ${submission.operation}` });
877
898
  dispatch.set({ answered: result.kind !== 'transport-uncertainty' });
878
899
  if (result.kind === 'revoked-authorization')
879
900
  return result;
@@ -881,6 +902,7 @@ async function dispatched(alive, conversation, submission) {
881
902
  alive.deps.unanswered();
882
903
  return result;
883
904
  }
905
+ alive.deps.heard(submission.operation, resent);
884
906
  const turn = answered(result, 'message_id');
885
907
  await withDraft(alive, conversation, async (current, local) => {
886
908
  const held = current?.submitted?.find((one) => one.operation === submission.operation);
@@ -900,8 +922,8 @@ async function dispatched(alive, conversation, submission) {
900
922
  alive.sendingEnded(submission.operation, dispatch);
901
923
  }
902
924
  }
903
- function invoke(alive, name, conversation, extra = { operation_id: changeBatchIdentity() }) {
904
- return alive.deps.call(name, { conversation_id: conversation, ...extra });
925
+ function invoke(alive, name, conversation, operation, extra = {}, attempt) {
926
+ return alive.deps.call(name, { conversation_id: conversation, operation_id: operation, ...extra }, attempt);
905
927
  }
906
928
  export function conversationSurface(alive) {
907
929
  return {
@@ -922,7 +944,7 @@ export function conversationSurface(alive) {
922
944
  return alive.deps.durably(async (local) => {
923
945
  const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before, phrase);
924
946
  const total = asked.total ? await local.messageCount(conversation, phrase) : null;
925
- return structuredClone(viewOf(alive, conversation, messages, frameOf(asked, messages, more, total), (await local.chatDraft(conversation)) ?? null, await endedIn(alive, conversation)));
947
+ return structuredClone(viewOf(alive, conversation, messages, frameOf(asked, messages, more, total), (await local.chatDraft(conversation)) ?? null, await endedIn(alive, conversation), await dismissedIn(local, conversation)));
926
948
  });
927
949
  },
928
950
  async create(input) {
@@ -959,40 +981,88 @@ export function conversationSurface(alive) {
959
981
  }
960
982
  return OFFLINE;
961
983
  },
962
- answer(conversation, answer) {
963
- return invoke(alive, 'conversations/interaction/answer', conversation, {
964
- operation_id: changeBatchIdentity(),
965
- ...answer,
984
+ answer(conversation, answer, operation) {
985
+ return invoke(alive, 'conversations/interaction/answer', conversation, operation, answer);
986
+ },
987
+ interrupt(conversation, operation) {
988
+ return invoke(alive, 'conversations/interrupt', conversation, operation);
989
+ },
990
+ kill(conversation, operation) {
991
+ return invoke(alive, 'conversations/kill', conversation, operation);
992
+ },
993
+ delete(conversation, operation) {
994
+ return invoke(alive, 'conversations/delete', conversation, operation);
995
+ },
996
+ takeOut(conversation, message, operation) {
997
+ return invoke(alive, 'conversations/take-out', conversation, operation, {
998
+ message_id: message,
999
+ });
1000
+ },
1001
+ decide({ request, room, message }, decision, operation) {
1002
+ return alive.deps.call('agent-functions/decide', {
1003
+ room_ref: room,
1004
+ request,
1005
+ ...(message === undefined ? {} : { message }),
1006
+ decision,
1007
+ operation_id: operation,
1008
+ });
1009
+ },
1010
+ rename(conversation, name, operation) {
1011
+ return invoke(alive, 'conversations/rename', conversation, operation, { name });
1012
+ },
1013
+ option(conversation, option, value, operation) {
1014
+ return invoke(alive, 'conversations/option/set', conversation, operation, { option, value });
1015
+ },
1016
+ retry(conversation, message, operation) {
1017
+ return invoke(alive, 'conversations/retry', conversation, operation, {
1018
+ message_id: message,
966
1019
  });
967
1020
  },
968
- interrupt(conversation) {
969
- return invoke(alive, 'conversations/interrupt', conversation);
1021
+ async pins() {
1022
+ return (await (await alive.deps.local()).facts()).chatPins;
970
1023
  },
971
- kill(conversation) {
972
- return invoke(alive, 'conversations/kill', conversation);
1024
+ pin(figures) {
1025
+ return alive.deps.durably((local) => local.fact('chatPins', [...figures]));
973
1026
  },
974
- delete(conversation) {
975
- return invoke(alive, 'conversations/delete', conversation);
1027
+ async openedTurns() {
1028
+ return factOf(await alive.deps.local(), 'openedTurn');
1029
+ },
1030
+ openTurn(conversation, turn) {
1031
+ return alive.deps.durably((local) => local.keepConversationFact({ conversation, name: 'openedTurn', value: turn }));
1032
+ },
1033
+ dismissSuggestion(conversation, suggestion) {
1034
+ return alive.deps.durably(async (local) => {
1035
+ if ((await dismissedIn(local, conversation)) === suggestion)
1036
+ return;
1037
+ await local.keepConversationFact({
1038
+ conversation,
1039
+ name: 'dismissedSuggestion',
1040
+ value: suggestion,
1041
+ });
1042
+ heldInViews(alive, conversation, { dismissed: suggestion });
1043
+ alive.deps.publish(conversationChangeSet([conversation]));
1044
+ });
976
1045
  },
977
1046
  };
978
1047
  }
1048
+ function rewritten(alive, conversation, text, revision = chatDraftRevision()) {
1049
+ return withDraft(alive, conversation, (current) => ({
1050
+ conversation,
1051
+ text: text(current?.text ?? ''),
1052
+ revision,
1053
+ ...(current === undefined ? {} : pending(current)),
1054
+ }));
1055
+ }
979
1056
  export function chatDraftSurface(alive) {
980
1057
  return {
981
- write(conversation, draft, revision = chatDraftRevision()) {
982
- return withDraft(alive, conversation, (current) => ({
983
- conversation,
984
- text: draft.text,
985
- revision,
986
- ...(current === undefined ? {} : pending(current)),
987
- }));
1058
+ write(conversation, draft, revision) {
1059
+ return rewritten(alive, conversation, () => draft.text, revision);
988
1060
  },
989
1061
  prepend(conversation, draft) {
990
- return withDraft(alive, conversation, (current) => ({
991
- conversation,
992
- ...(current === undefined ? { text: draft.text } : prepended(current, draft)),
993
- revision: chatDraftRevision(),
994
- ...(current === undefined ? {} : pending(current)),
995
- }));
1062
+ return rewritten(alive, conversation, (held) => joinedDraft(draft.text, held));
1063
+ },
1064
+ append(conversation, draft) {
1065
+ return rewritten(alive, conversation, (held) => joinedDraft(held, draft.text));
996
1066
  },
997
1067
  discard(conversation) {
998
1068
  return withDraft(alive, conversation, (current) => current === undefined
@@ -1012,9 +1082,9 @@ export async function reconcileConversations(alive) {
1012
1082
  if (!alive.known())
1013
1083
  return;
1014
1084
  const local = await alive.deps.local();
1015
- const [held, kept, { conversationList }] = await Promise.all([
1085
+ const [held, stored, { conversationList }] = await Promise.all([
1016
1086
  local.conversations(),
1017
- local.chatDrafts(),
1087
+ local.storedConversations(),
1018
1088
  local.facts(),
1019
1089
  ]);
1020
1090
  const list = conversationList ?? [];
@@ -1022,9 +1092,7 @@ export async function reconcileConversations(alive) {
1022
1092
  const named = new Set(entries.keys());
1023
1093
  const reads = new Map(held.map((one) => [one.conversation, one]));
1024
1094
  const { replicated } = alive.held.now();
1025
- const leaving = [
1026
- ...new Set([...replicated, ...reads.keys(), ...kept.map(({ conversation }) => conversation)]),
1027
- ].filter((conversation) => !named.has(conversation) &&
1095
+ const leaving = [...new Set([...replicated, ...stored])].filter((conversation) => !named.has(conversation) &&
1028
1096
  !alive.isCreating(conversation) &&
1029
1097
  (!conversation.startsWith(NEW_CHAT) || retiredChat(conversation, list)));
1030
1098
  for (const conversation of named) {
@@ -1061,6 +1129,17 @@ export async function catchUpConversations(alive, progress) {
1061
1129
  if (!alive.current())
1062
1130
  progress.complete = false;
1063
1131
  }
1132
+ export async function holdsSubmission(alive, operation) {
1133
+ if (alive.sending(operation))
1134
+ return true;
1135
+ const local = await alive.deps.local();
1136
+ for (const { conversation } of await local.chatDrafts()) {
1137
+ const held = (await local.chatDraft(conversation))?.submitted;
1138
+ if (held?.some((one) => one.operation === operation && one.turn === null) === true)
1139
+ return true;
1140
+ }
1141
+ return false;
1142
+ }
1064
1143
  export async function resendConversations(alive, progress) {
1065
1144
  const local = await alive.deps.local();
1066
1145
  const tried = new Set();
@@ -1072,7 +1151,7 @@ export async function resendConversations(alive, progress) {
1072
1151
  if (alive.deps.closed())
1073
1152
  return;
1074
1153
  tried.add(submission.operation);
1075
- const result = await dispatched(alive, conversation, submission);
1154
+ const result = await dispatched(alive, conversation, submission, true);
1076
1155
  if (result.kind === 'revoked-authorization')
1077
1156
  return;
1078
1157
  if (result.kind === 'transport-uncertainty') {
@@ -1092,22 +1171,24 @@ export function watchConversation(alive, conversation, options, deliver) {
1092
1171
  const { view, watcher } = alive.viewJoined(key, conversation, asked, deliver);
1093
1172
  const { held } = view;
1094
1173
  const reading = new AbortController();
1095
- void untilAnswered(() => alive.deps.durably(async (local) => {
1174
+ void untilAnswered(retrying(alive.deps.retries, 'reading', `window ${key}`, () => alive.deps.durably(async (local) => {
1096
1175
  if (held.now().window !== null)
1097
1176
  return;
1098
1177
  const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
1099
1178
  held.set({ draft: (await local.chatDraft(conversation)) ?? null });
1100
1179
  held.set({ ended: await endedIn(alive, conversation) });
1180
+ held.set({ dismissed: await dismissedIn(local, conversation) });
1101
1181
  held.set({ window: messages });
1102
1182
  held.set({ more });
1103
1183
  held.set({ total: asked.total ? await local.messageCount(conversation) : null });
1104
- }), reading.signal)
1184
+ })), reading.signal)
1105
1185
  .then(() => {
1106
1186
  if (alive.deps.closed() || !view.admit(watcher))
1107
1187
  return;
1108
- const { window, draft, ended } = held.now();
1188
+ const { window, draft, ended, dismissed } = held.now();
1109
1189
  const shown = window ?? [];
1110
- watcher.notify(viewOf(alive, conversation, shown, sharedFrame(view, shown), draft, ended));
1190
+ const frame = sharedFrame(view, shown);
1191
+ watcher.notify(viewOf(alive, conversation, shown, frame, draft, ended, dismissed));
1111
1192
  })
1112
1193
  .catch(() => { });
1113
1194
  return () => {
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,cAAc,EACd,MAAM,EAEP,MAAM,cAAc,CAAC;AAStB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkB/C,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,GAAG,IAAI,CAsB1E;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAqEpC;AAUD,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,iBAI1F;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,SAAS,cAAc,EAAE,GAAG,IAAI,CAAC,CA+D3C"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,SAAS,EACT,cAAc,EACd,MAAM,EAEP,MAAM,cAAc,CAAC;AAOtB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAkB/C,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,MAAM,GAAG,IAAI,CAsB1E;AAED,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,SAAS,cAAc,EAAE,EAChC,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,GACvB,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CA0CpC;AAYD,wBAAsB,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,iBAI1F;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,SAAS,GAAG,IAAI,GACtB,OAAO,CAAC,SAAS,cAAc,EAAE,GAAG,IAAI,CAAC,CA+D3C"}
package/dist/discovery.js CHANGED
@@ -1,7 +1,5 @@
1
1
  import { validRoot } from './collection.js';
2
- import { declared } from './declaration.js';
3
- import { admitted, list, listHeld } from './listing.js';
4
- import { confirmLocks, lockedRooms, relocked } from './locks.js';
2
+ import { lockedRooms, relocked } from './locks.js';
5
3
  import { loseRooms } from './lost.js';
6
4
  import { cachedModels } from './models.js';
7
5
  import { beneath } from './paths.js';
@@ -38,61 +36,34 @@ export function malformed(listed) {
38
36
  return null;
39
37
  }
40
38
  export async function applyDiscovery(runtime, found, started, left) {
41
- const { store, socket } = runtime;
42
- const { rooms } = socket;
39
+ const { store, socket, presence } = runtime;
43
40
  const lockedBefore = await lockedRooms(runtime);
44
41
  const local = await store.open();
45
- const stillFenced = new Set(await local.fences());
42
+ const fenced = new Set(await local.fences());
46
43
  const relisting = found
47
44
  .map(({ locator }) => locator)
48
- .filter((locator) => {
49
- const fence = store.fences.of(locator);
50
- return stillFenced.has(locator) && (fence === undefined || fence.at < started);
51
- });
52
- const relisted = relisting.length === 0
45
+ .filter((locator) => fenced.has(locator) && presence.liftable(locator, started));
46
+ const unfenced = relisting.length === 0
53
47
  ? new Set()
54
48
  : await store.durably((held) => held.unfence(relisting));
55
- for (const { locator } of found) {
56
- const fence = store.fences.of(locator);
57
- if (fence === undefined || fence.at >= started)
58
- continue;
59
- if (relisted.has(locator) || (!stillFenced.has(locator) && !fence.written)) {
60
- store.fences.lift(locator);
61
- }
62
- }
49
+ const clear = found.filter(({ locator }) => !fenced.has(locator) || unfenced.has(locator));
50
+ for (const { locator } of clear)
51
+ presence.lift(locator, started, unfenced.has(locator));
63
52
  const kept = await local.held();
64
53
  await loseRooms(runtime, found
65
54
  .filter((room) => room.replica.admission !== 'admitted' &&
66
55
  (kept.held.has(room.locator) || store.installs.of(room.locator).transfer !== null))
67
56
  .map((room) => room.locator));
68
- const listed = found.filter(({ locator }) => !store.fences.has(locator) && (!stillFenced.has(locator) || relisted.has(locator)));
69
- const listedLocatorsNow = new Set(listed.map((room) => room.locator));
70
- for (const locator of listedLocatorsNow)
71
- rooms.stand(locator, { refusal: null });
72
- if (left === undefined)
73
- rooms.undiscoverAll();
74
- for (const room of listed)
75
- rooms.discover(room);
76
57
  const named = new Set(found.map((room) => room.locator));
77
58
  await loseRooms(runtime, left ??
78
59
  [
79
60
  ...new Set([
80
- ...rooms.declarations().keys(),
61
+ ...presence.rooms().map(({ locator }) => locator),
81
62
  ...kept.held,
82
63
  ...store.installs.transferring(),
83
64
  ]),
84
65
  ].filter((locator) => !named.has(locator)));
85
- const held = await store.rooms(listed.map((room) => room.locator));
86
- for (const room of listed) {
87
- const record = held.get(room.locator)?.record;
88
- if (record !== undefined && record.declaration.replica.selection !== room.replica.selection) {
89
- listHeld(runtime, room.locator);
90
- continue;
91
- }
92
- const declaration = declared(room);
93
- list(runtime, room.locator, declaration, admitted(runtime, room.locator, declaration));
94
- }
95
- confirmLocks(runtime, listed);
66
+ const listed = presence.list(clear, { whole: left === undefined, live: socket.isOpen() });
96
67
  socket.session.set({ roomsListed: true });
97
68
  emitRooms(runtime);
98
69
  await relocked(runtime, lockedBefore);
@@ -102,10 +73,11 @@ async function asked({ socket }, authorized) {
102
73
  try {
103
74
  return (await socket.discover(authorized)) ?? { kind: 'transport-uncertainty' };
104
75
  }
105
- catch {
106
- return { kind: 'transport-uncertainty' };
76
+ catch (failure) {
77
+ return { kind: 'transport-uncertainty', failure };
107
78
  }
108
79
  }
80
+ const DISCOVERY = 'discovery';
109
81
  export async function signIn(runtime, local, signedIn) {
110
82
  if (JSON.stringify(signedIn) === JSON.stringify((await local.facts()).member))
111
83
  return;
@@ -113,7 +85,7 @@ export async function signIn(runtime, local, signedIn) {
113
85
  emitMember(runtime, signedIn);
114
86
  }
115
87
  export async function discoverRooms(runtime, local, progress, live, found) {
116
- const { socket, journal } = runtime;
88
+ const { socket } = runtime;
117
89
  const { session } = socket;
118
90
  const { closed, authorization } = session.now();
119
91
  if (closed || authorization === undefined) {
@@ -131,7 +103,10 @@ export async function discoverRooms(runtime, local, progress, live, found) {
131
103
  socket.notifyReady();
132
104
  return null;
133
105
  }
134
- journal.record(`connection discover ${result.kind}`);
106
+ if (result.kind === 'transport-uncertainty')
107
+ runtime.retries.uncertain('connection', DISCOVERY, result);
108
+ if (result.kind === 'discovery')
109
+ runtime.retries.succeeded('connection', DISCOVERY);
135
110
  if (result.kind === 'transport-uncertainty') {
136
111
  await cachedModels(runtime, local);
137
112
  progress.reachable = false;
@@ -140,7 +115,6 @@ export async function discoverRooms(runtime, local, progress, live, found) {
140
115
  return null;
141
116
  }
142
117
  if (result.kind === 'contract-unavailable') {
143
- journal.record(`connection contract unavailable ${result.code}`);
144
118
  await refuse(runtime, 'missing-required-guarantee', {
145
119
  code: result.code,
146
120
  fields: result.fields,
@@ -156,7 +130,6 @@ export async function discoverRooms(runtime, local, progress, live, found) {
156
130
  }
157
131
  const invalid = malformed(result.rooms);
158
132
  if (invalid !== null) {
159
- journal.record(invalid);
160
133
  await refuse(runtime, 'missing-required-guarantee');
161
134
  socket.notifyReady();
162
135
  return null;
@@ -1,4 +1,5 @@
1
1
  import type { Persistence } from './readiness.js';
2
+ import type { RetriedFailure, Step } from './retried.js';
2
3
  export type UnsentKind = 'pending-change' | 'call' | 'room-draft' | 'chat-draft';
3
4
  export type UnsentWork = {
4
5
  readonly kind: UnsentKind;
@@ -20,6 +21,8 @@ export type RuntimeShell = {
20
21
  cleanUp?(): Promise<number>;
21
22
  measure?(measured: (app: string, code: AppCode | null) => void): Promise<HeldCode>;
22
23
  reset(): Promise<void>;
24
+ retried?(failure: RetriedFailure): void;
25
+ succeeded?(step: Step): void;
23
26
  };
24
27
  export declare function refusedForSpace(error: unknown): boolean;
25
28
  export declare function detectStorageLoss(stored: string | null, reported: string | null): string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"durability.d.ts","sourceRoot":"","sources":["../src/durability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIlD,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC;AAEjF,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,MAAM,MAAM,OAAO,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE3F,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,cAAc,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAMvD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG/F;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGrF"}
1
+ {"version":3,"file":"durability.d.ts","sourceRoot":"","sources":["../src/durability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAIzD,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,MAAM,GAAG,YAAY,GAAG,YAAY,CAAC;AAEjF,MAAM,MAAM,UAAU,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,MAAM,MAAM,OAAO,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,QAAQ,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE3F,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,cAAc,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,CAAC,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IACxC,SAAS,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAMvD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAG/F;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAGrF"}
package/dist/entry.js CHANGED
@@ -145,7 +145,7 @@ export function entryScope(rooms, roomTypes, connection) {
145
145
  change: null,
146
146
  written: null,
147
147
  })));
148
- return { locator: room.locator, key };
148
+ return { locator: room.locator, key, composition };
149
149
  });
150
150
  const planned = { listed: true, rooms: held };
151
151
  return {