@agentshouse/mdruntime 0.1.0-ce5c5bb29be5a → 0.1.0-ce6bc9239a3ee

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 (201) hide show
  1. package/README.md +2 -2
  2. package/dist/acceptance.d.ts +26 -0
  3. package/dist/acceptance.d.ts.map +1 -0
  4. package/dist/acceptance.js +384 -0
  5. package/dist/adapter.d.ts +81 -49
  6. package/dist/adapter.d.ts.map +1 -1
  7. package/dist/attached-model.d.ts +3 -10
  8. package/dist/attached-model.d.ts.map +1 -1
  9. package/dist/attached-model.js +21 -56
  10. package/dist/bootstrap.d.ts +9 -5
  11. package/dist/bootstrap.d.ts.map +1 -1
  12. package/dist/bootstrap.js +209 -75
  13. package/dist/chain.d.ts +2 -1
  14. package/dist/chain.d.ts.map +1 -1
  15. package/dist/change.d.ts +1 -0
  16. package/dist/change.d.ts.map +1 -1
  17. package/dist/chat-types.d.ts +3 -0
  18. package/dist/chat-types.d.ts.map +1 -0
  19. package/dist/chat-types.js +2 -0
  20. package/dist/client.d.ts +16 -6
  21. package/dist/client.d.ts.map +1 -1
  22. package/dist/client.js +3 -1
  23. package/dist/collection.d.ts +2 -1
  24. package/dist/collection.d.ts.map +1 -1
  25. package/dist/compile.d.ts +6 -6
  26. package/dist/compile.d.ts.map +1 -1
  27. package/dist/compile.js +262 -318
  28. package/dist/connection.d.ts +20 -44
  29. package/dist/connection.d.ts.map +1 -1
  30. package/dist/connection.js +1438 -3393
  31. package/dist/context.d.ts +2 -0
  32. package/dist/context.d.ts.map +1 -0
  33. package/dist/context.js +7 -0
  34. package/dist/conversation-row.d.ts +33 -0
  35. package/dist/conversation-row.d.ts.map +1 -0
  36. package/dist/conversation-row.js +47 -0
  37. package/dist/conversation.d.ts +26 -17
  38. package/dist/conversation.d.ts.map +1 -1
  39. package/dist/conversation.js +441 -307
  40. package/dist/durability.d.ts +6 -0
  41. package/dist/durability.d.ts.map +1 -1
  42. package/dist/entry.d.ts +2 -2
  43. package/dist/entry.d.ts.map +1 -1
  44. package/dist/entry.js +17 -7
  45. package/dist/figures.d.ts +48 -0
  46. package/dist/figures.d.ts.map +1 -0
  47. package/dist/figures.js +197 -0
  48. package/dist/host.d.ts +4 -6
  49. package/dist/host.d.ts.map +1 -1
  50. package/dist/host.js +22 -26
  51. package/dist/identity.d.ts +0 -1
  52. package/dist/identity.d.ts.map +1 -1
  53. package/dist/identity.js +0 -3
  54. package/dist/index.d.ts +18 -8
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +5 -1
  57. package/dist/install.d.ts +86 -0
  58. package/dist/install.d.ts.map +1 -0
  59. package/dist/install.js +537 -0
  60. package/dist/job.d.ts +33 -0
  61. package/dist/job.d.ts.map +1 -0
  62. package/dist/job.js +54 -0
  63. package/dist/live.d.ts +5 -4
  64. package/dist/live.d.ts.map +1 -1
  65. package/dist/live.js +63 -22
  66. package/dist/log.d.ts +1 -0
  67. package/dist/log.d.ts.map +1 -1
  68. package/dist/memory.d.ts +11 -4
  69. package/dist/memory.d.ts.map +1 -1
  70. package/dist/memory.js +171 -81
  71. package/dist/messages.d.ts +27 -3
  72. package/dist/messages.d.ts.map +1 -1
  73. package/dist/messages.js +97 -19
  74. package/dist/model.d.ts +2 -9
  75. package/dist/model.d.ts.map +1 -1
  76. package/dist/model.js +0 -9
  77. package/dist/observation.d.ts +2 -2
  78. package/dist/observation.d.ts.map +1 -1
  79. package/dist/observation.js +7 -2
  80. package/dist/outcome.d.ts +1 -0
  81. package/dist/outcome.d.ts.map +1 -1
  82. package/dist/outcome.js +3 -0
  83. package/dist/overlay.d.ts +1 -0
  84. package/dist/overlay.d.ts.map +1 -1
  85. package/dist/overlay.js +11 -0
  86. package/dist/parts.d.ts +59 -0
  87. package/dist/parts.d.ts.map +1 -0
  88. package/dist/parts.js +118 -0
  89. package/dist/query.d.ts +14 -209
  90. package/dist/query.d.ts.map +1 -1
  91. package/dist/query.js +3 -505
  92. package/dist/questions.d.ts +32 -0
  93. package/dist/questions.d.ts.map +1 -0
  94. package/dist/questions.js +118 -0
  95. package/dist/reach.d.ts +12 -12
  96. package/dist/reach.d.ts.map +1 -1
  97. package/dist/reach.js +182 -136
  98. package/dist/react.d.ts +5 -2
  99. package/dist/react.d.ts.map +1 -1
  100. package/dist/read.d.ts +7 -0
  101. package/dist/read.d.ts.map +1 -0
  102. package/dist/read.js +17 -0
  103. package/dist/readiness.d.ts +0 -2
  104. package/dist/readiness.d.ts.map +1 -1
  105. package/dist/reads.d.ts +36 -0
  106. package/dist/reads.d.ts.map +1 -0
  107. package/dist/reads.js +136 -0
  108. package/dist/recovery.d.ts.map +1 -1
  109. package/dist/recovery.js +9 -1
  110. package/dist/refresh.d.ts +6 -4
  111. package/dist/refresh.d.ts.map +1 -1
  112. package/dist/refresh.js +32 -4
  113. package/dist/replica.d.ts +8 -8
  114. package/dist/replica.d.ts.map +1 -1
  115. package/dist/replica.js +50 -15
  116. package/dist/room-draft.d.ts +4 -3
  117. package/dist/room-draft.d.ts.map +1 -1
  118. package/dist/room-draft.js +65 -52
  119. package/dist/room-drafts.d.ts +29 -0
  120. package/dist/room-drafts.d.ts.map +1 -0
  121. package/dist/room-drafts.js +216 -0
  122. package/dist/rows.d.ts +14 -21
  123. package/dist/rows.d.ts.map +1 -1
  124. package/dist/rows.js +48 -184
  125. package/dist/save.d.ts.map +1 -1
  126. package/dist/save.js +11 -8
  127. package/dist/saves.d.ts +96 -0
  128. package/dist/saves.d.ts.map +1 -0
  129. package/dist/saves.js +999 -0
  130. package/dist/search.d.ts +12 -63
  131. package/dist/search.d.ts.map +1 -1
  132. package/dist/search.js +9 -52
  133. package/dist/seed.d.ts +16 -2
  134. package/dist/seed.d.ts.map +1 -1
  135. package/dist/seed.js +66 -0
  136. package/dist/socket/admission.d.ts +7 -0
  137. package/dist/socket/admission.d.ts.map +1 -0
  138. package/dist/socket/admission.js +39 -0
  139. package/dist/socket/answers.d.ts +6 -0
  140. package/dist/socket/answers.d.ts.map +1 -0
  141. package/dist/socket/answers.js +20 -0
  142. package/dist/socket/reads.d.ts +10 -0
  143. package/dist/socket/reads.d.ts.map +1 -0
  144. package/dist/socket/reads.js +31 -0
  145. package/dist/socket.d.ts +43 -0
  146. package/dist/socket.d.ts.map +1 -0
  147. package/dist/socket.js +96 -0
  148. package/dist/source.d.ts +61 -0
  149. package/dist/source.d.ts.map +1 -0
  150. package/dist/source.js +81 -0
  151. package/dist/status.d.ts +0 -2
  152. package/dist/status.d.ts.map +1 -1
  153. package/dist/status.js +0 -6
  154. package/dist/store/fences.d.ts +16 -0
  155. package/dist/store/fences.d.ts.map +1 -0
  156. package/dist/store/fences.js +26 -0
  157. package/dist/store/installs.d.ts +30 -0
  158. package/dist/store/installs.d.ts.map +1 -0
  159. package/dist/store/installs.js +34 -0
  160. package/dist/store/records.d.ts +212 -0
  161. package/dist/store/records.d.ts.map +1 -0
  162. package/dist/store/records.js +408 -0
  163. package/dist/store/room-held.d.ts +8 -0
  164. package/dist/store/room-held.d.ts.map +1 -0
  165. package/dist/store/room-held.js +17 -0
  166. package/dist/store/watchers.d.ts +15 -0
  167. package/dist/store/watchers.d.ts.map +1 -0
  168. package/dist/store/watchers.js +36 -0
  169. package/dist/store/writes.d.ts +24 -0
  170. package/dist/store/writes.d.ts.map +1 -0
  171. package/dist/store/writes.js +125 -0
  172. package/dist/store.d.ts +78 -145
  173. package/dist/store.d.ts.map +1 -1
  174. package/dist/store.js +117 -367
  175. package/dist/stored.d.ts +58 -32
  176. package/dist/stored.d.ts.map +1 -1
  177. package/dist/stored.js +264 -187
  178. package/dist/tables.d.ts +107 -25
  179. package/dist/tables.d.ts.map +1 -1
  180. package/dist/tables.js +193 -47
  181. package/dist/tallies.d.ts +18 -0
  182. package/dist/tallies.d.ts.map +1 -0
  183. package/dist/tallies.js +129 -0
  184. package/dist/validation.d.ts.map +1 -1
  185. package/dist/validation.js +7 -4
  186. package/dist/windows.d.ts +1 -12
  187. package/dist/windows.d.ts.map +1 -1
  188. package/dist/windows.js +2 -75
  189. package/dist/wire.d.ts +15 -4
  190. package/dist/wire.d.ts.map +1 -1
  191. package/dist/wire.js +6 -1
  192. package/package.json +2 -2
  193. package/dist/fence.d.ts +0 -6
  194. package/dist/fence.d.ts.map +0 -1
  195. package/dist/fence.js +0 -10
  196. package/dist/fulltext.d.ts +0 -27
  197. package/dist/fulltext.d.ts.map +0 -1
  198. package/dist/fulltext.js +0 -370
  199. package/dist/words.d.ts +0 -19
  200. package/dist/words.d.ts.map +0 -1
  201. package/dist/words.js +0 -156
package/dist/memory.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { documentFacts, parse } from '@agentshouse/mdmodel';
2
+ import { NO_ROOM_TYPES, schemaTypes } from './attached-model.js';
1
3
  import { sameChange } from './overlay.js';
2
4
  const ATTACHMENTS = 'attachments';
3
5
  function lastName(path) {
@@ -5,7 +7,6 @@ function lastName(path) {
5
7
  }
6
8
  const FIXTURE_RETENTION = {
7
9
  history: { kind: 'duration', seconds: 1 },
8
- outcome: 604_800,
9
10
  refreshHorizon: 1,
10
11
  };
11
12
  function declaredRetention(value) {
@@ -52,15 +53,16 @@ export function createMemoryAdapter(options = {}) {
52
53
  const listeners = new Set();
53
54
  const modeObservers = new Set();
54
55
  const scripted = new Map();
55
- const unsealed = new Map();
56
- const sealed = new Set();
57
56
  const sentTurns = new Map();
58
57
  const historyPageSize = options.historyPageSize;
59
58
  const attached = new Map();
60
59
  const linked = new WeakMap();
61
- let held = [];
60
+ const carried = new Map();
62
61
  let expiring = [];
62
+ let openings = 0;
63
+ const declaredRooms = new Set();
63
64
  let replicated = [];
65
+ let heldCursor = null;
64
66
  let issued = 0;
65
67
  function scriptConversations(entries) {
66
68
  scripted.clear();
@@ -101,8 +103,35 @@ export function createMemoryAdapter(options = {}) {
101
103
  return path;
102
104
  }
103
105
  }
106
+ const saved = new WeakMap();
107
+ function factsAt(room, path, content) {
108
+ const types = schemaTypes(room.model?.kind === 'model' ? room.model.snapshot.schema : null, NO_ROOM_TYPES);
109
+ let held = saved.get(types);
110
+ if (held === undefined) {
111
+ held = new Map();
112
+ saved.set(types, held);
113
+ }
114
+ const key = `${path}\u0000${content}`;
115
+ if (!held.has(key)) {
116
+ const facts = documentFacts(path, parse(content, path), { types });
117
+ held.set(key, facts === null ? null : JSON.parse(JSON.stringify(facts)));
118
+ }
119
+ return held.get(key);
120
+ }
121
+ function factsIn(room, paths) {
122
+ const facts = {};
123
+ for (const path of paths) {
124
+ const content = room.documents?.[path];
125
+ const held = room.facts?.[path] ?? (content === undefined ? null : factsAt(room, path, content));
126
+ if (held !== null)
127
+ facts[path] = held;
128
+ }
129
+ return facts;
130
+ }
104
131
  function retain(entries) {
105
132
  for (const room of entries) {
133
+ for (const [path, content] of Object.entries(room.documents ?? {}))
134
+ factsAt(room, path, content);
106
135
  note(room.locator, room);
107
136
  const versions = served.get(room.locator) ?? new Map();
108
137
  versions.set(room.roomVersion, room);
@@ -135,10 +164,14 @@ export function createMemoryAdapter(options = {}) {
135
164
  roomVersion: room.roomVersion,
136
165
  ...(opening ? { models: modelsOf(room) } : {}),
137
166
  documents: named(room.documents ?? {}, taken),
167
+ facts: factsIn(room, taken),
138
168
  revisions: named(room.revisions ?? {}, [...taken, ...targets]),
139
169
  ...(room.fileIds === undefined
140
170
  ? {}
141
171
  : { fileIds: named(room.fileIds, [...taken, ...targets]) }),
172
+ ...(room.created === undefined
173
+ ? {}
174
+ : { created: named(room.created, [...taken, ...targets]) }),
142
175
  changes: named(room.changes ?? {}, [...taken, ...targets]),
143
176
  binaryFiles: named(room.binaryFiles ?? {}, targets),
144
177
  ...(opening && room.folders !== undefined ? { folders: room.folders } : {}),
@@ -155,18 +188,19 @@ export function createMemoryAdapter(options = {}) {
155
188
  ...(folderRemovals.length === 0 ? {} : { folderRemovals }),
156
189
  };
157
190
  }
158
- function advancement(room, from, at) {
191
+ function advancement(room, from, at, whole = false) {
159
192
  const current = room.documents ?? {};
160
193
  const previous = from.documents ?? {};
161
194
  const currentTargets = new Set(Object.keys(room.binaryFiles ?? {}));
162
195
  const previousTargets = new Set(Object.keys(from.binaryFiles ?? {}));
163
196
  const headMoved = (path) => room.revisions?.[path] !== from.revisions?.[path] ||
164
197
  room.fileIds?.[path] !== from.fileIds?.[path] ||
198
+ room.created?.[path] !== from.created?.[path] ||
165
199
  !sameChange(room.changes?.[path], from.changes?.[path]);
166
200
  const changed = Object.keys(current)
167
201
  .filter((path) => current[path] !== previous[path] || headMoved(path))
168
202
  .sort();
169
- const size = pageSize ?? changed.length;
203
+ const size = whole ? changed.length : (pageSize ?? changed.length);
170
204
  const taken = changed.slice(at, at + size);
171
205
  const next = at + taken.length;
172
206
  const opening = at === 0;
@@ -182,10 +216,14 @@ export function createMemoryAdapter(options = {}) {
182
216
  roomVersion: room.roomVersion,
183
217
  ...(models === undefined ? {} : { models }),
184
218
  documents: named(current, taken),
219
+ facts: factsIn(room, taken),
185
220
  revisions: named(room.revisions ?? {}, [...taken, ...targets]),
186
221
  ...(room.fileIds === undefined
187
222
  ? {}
188
223
  : { fileIds: named(room.fileIds, [...taken, ...targets]) }),
224
+ ...(room.created === undefined
225
+ ? {}
226
+ : { created: named(room.created, [...taken, ...targets]) }),
189
227
  changes: named(room.changes ?? {}, [...taken, ...targets]),
190
228
  binaryFiles: named(room.binaryFiles ?? {}, targets),
191
229
  ...(opening ? foldersMoved(room, from) : {}),
@@ -198,6 +236,26 @@ export function createMemoryAdapter(options = {}) {
198
236
  ...(pageToken === undefined ? {} : { pageToken }),
199
237
  };
200
238
  }
239
+ function carry(locator) {
240
+ const at = carried.get(locator);
241
+ const current = rooms.find((entry) => entry.locator === locator);
242
+ if (at === undefined || current === undefined || current.roomVersion === at)
243
+ return;
244
+ const from = served.get(locator)?.get(at);
245
+ carried.set(locator, current.roomVersion);
246
+ if (from === undefined)
247
+ return;
248
+ const page = advancement(current, from, 0, true);
249
+ for (const observer of observers) {
250
+ observer({
251
+ kind: 'room-change',
252
+ locator,
253
+ from: at,
254
+ roomVersion: current.roomVersion,
255
+ read: async () => page,
256
+ });
257
+ }
258
+ }
201
259
  function pageOf(conversation, after) {
202
260
  const messages = conversation.messages ?? [];
203
261
  const first = typeof after === 'string' ? messages.findIndex((message) => message.position > after) : 0;
@@ -212,16 +270,13 @@ export function createMemoryAdapter(options = {}) {
212
270
  : {}),
213
271
  };
214
272
  }
215
- function historiesOf(input) {
216
- const asked = input?.conversations;
217
- if (!Array.isArray(asked))
218
- return { kind: 'rejected', code: 'invalid_request', fields: {}, retryable: false };
273
+ function historiesOf(request) {
219
274
  const histories = [];
220
- for (const entry of asked) {
221
- const conversation = typeof entry.conversation === 'string' ? scripted.get(entry.conversation) : undefined;
275
+ for (const entry of request.conversations) {
276
+ const conversation = scripted.get(entry.conversation);
222
277
  if (conversation === undefined)
223
278
  continue;
224
- const outcome = conversation.outcomes?.['conversation.history'];
279
+ const outcome = conversation.outcomes?.history;
225
280
  if (outcome !== undefined)
226
281
  return outcome;
227
282
  histories.push(pageOf(conversation, entry.after));
@@ -232,15 +287,13 @@ export function createMemoryAdapter(options = {}) {
232
287
  function conversationAction(request) {
233
288
  const name = request.name;
234
289
  const input = (request.input ?? {});
235
- if (name === 'conversation.history')
236
- return historiesOf(request.input);
237
- if (name === 'conversation.create') {
290
+ if (name === 'conversations/create') {
238
291
  issued += 1;
239
292
  const conversation = `conversation-${issued}`;
240
293
  scripted.set(conversation, { conversation });
241
- return { kind: 'action', result: { conversation } };
294
+ return { kind: 'action', result: { conversation_id: conversation } };
242
295
  }
243
- const named = typeof input.conversation === 'string' ? input.conversation : '';
296
+ const named = typeof input.conversation_id === 'string' ? input.conversation_id : '';
244
297
  const conversation = scripted.get(named);
245
298
  if (conversation === undefined) {
246
299
  return {
@@ -253,36 +306,28 @@ export function createMemoryAdapter(options = {}) {
253
306
  const outcome = conversation.outcomes?.[name];
254
307
  if (outcome !== undefined)
255
308
  return outcome;
256
- if (name === 'conversation.send') {
309
+ if (name === 'conversations/send') {
257
310
  const operation = typeof input.operation_id === 'string' ? input.operation_id : null;
258
311
  const answered = operation === null ? undefined : sentTurns.get(operation);
259
312
  if (answered !== undefined)
260
- return { kind: 'action', result: { turn: answered } };
313
+ return { kind: 'action', result: { message_id: answered } };
261
314
  issued += 1;
262
315
  const turn = `turn-${issued}`;
263
- unsealed.set(turn, named);
264
316
  if (operation !== null)
265
317
  sentTurns.set(operation, turn);
266
- return { kind: 'action', result: { turn } };
267
- }
268
- if (name === 'conversation.cancel') {
269
- const turn = typeof input.turn === 'string' ? input.turn : '';
270
- if (sealed.has(turn) || !unsealed.has(turn)) {
271
- return { kind: 'rejected', code: 'turn-sealed', fields: { turn }, retryable: false };
272
- }
273
- unsealed.delete(turn);
274
- return { kind: 'action', result: { turn, cancelled: true } };
318
+ return { kind: 'action', result: { message_id: turn } };
275
319
  }
276
- if (name === 'conversation.delete')
320
+ if (name === 'conversations/delete')
277
321
  scripted.delete(named);
278
- return { kind: 'action', result: { conversation: named } };
322
+ return { kind: 'action', result: { conversation_id: named } };
279
323
  }
280
324
  function announceList() {
281
325
  const entries = [...scripted.values()].flatMap(({ conversation, listed, messages = [] }) => listed === undefined
282
326
  ? []
283
327
  : [{ conversation, ...listed, newest: messages.at(-1)?.position ?? null }]);
284
- for (const listener of listeners)
285
- listener({ kind: 'list', entries });
328
+ for (const listener of listeners) {
329
+ listener({ kind: 'list', entries, whole: true, more: false, cursor: null });
330
+ }
286
331
  }
287
332
  function discovery() {
288
333
  return {
@@ -294,9 +339,42 @@ export function createMemoryAdapter(options = {}) {
294
339
  ...(options.member === undefined ? {} : { member: options.member }),
295
340
  };
296
341
  }
342
+ function discovered() {
343
+ return resolveScript(scripts.discover, discovery, undefined).then((answer) => {
344
+ if (answer.kind === 'discovery')
345
+ for (const room of answer.rooms)
346
+ note(room.locator, room);
347
+ return answer;
348
+ });
349
+ }
350
+ function opened(notify) {
351
+ const opening = ++openings;
352
+ notify({ kind: 'opened' });
353
+ void discovered()
354
+ .catch(() => ({ kind: 'transport-uncertainty' }))
355
+ .then((answer) => {
356
+ if (opening !== openings)
357
+ return;
358
+ if (answer.kind !== 'discovery') {
359
+ openings += 1;
360
+ carried.clear();
361
+ const revoked = answer.kind === 'revoked-authorization';
362
+ notify({ kind: 'closed', revoked, lost: !revoked, authorityChanged: false });
363
+ return;
364
+ }
365
+ declaredRooms.clear();
366
+ for (const room of answer.rooms)
367
+ declaredRooms.add(room.locator);
368
+ notify({ kind: 'discovered', discovery: answer });
369
+ });
370
+ }
371
+ function emitAll(event) {
372
+ for (const observer of observers)
373
+ observer(event);
374
+ }
297
375
  return {
298
- ...(options.exhaustiveDiscovery === undefined ? {} : { exhaustiveDiscovery: true }),
299
376
  ...(options.roomTypes === undefined ? {} : { roomTypes: options.roomTypes }),
377
+ ...(options.typedPaths === undefined ? {} : { typedPaths: options.typedPaths }),
300
378
  setRooms(next) {
301
379
  rooms = [...next];
302
380
  retain(rooms);
@@ -305,33 +383,37 @@ export function createMemoryAdapter(options = {}) {
305
383
  scriptConversations(next);
306
384
  },
307
385
  open() {
386
+ carried.clear();
308
387
  announceList();
309
- for (const observer of observers)
310
- observer({ kind: 'opened' });
388
+ opened(emitAll);
311
389
  },
312
- close({ revoked = false, lost = !revoked } = {}) {
313
- for (const observer of observers)
314
- observer({ kind: 'closed', revoked, lost });
390
+ close({ revoked = false, lost = !revoked, authorityChanged = false } = {}) {
391
+ openings += 1;
392
+ carried.clear();
393
+ emitAll({ kind: 'closed', revoked, lost, authorityChanged });
315
394
  },
316
395
  expire(locators) {
317
396
  expiring = [...locators];
318
397
  },
319
- notifyRoomVersion({ locator, roomVersion }) {
320
- for (const observer of observers)
321
- observer({ kind: 'room-version', locator, roomVersion });
398
+ notifyRoomVersion({ locator }) {
399
+ carry(locator);
322
400
  },
323
- notifyAuthorityChanged(scope) {
324
- for (const observer of observers) {
325
- observer(scope === undefined
326
- ? { kind: 'authority-changed' }
327
- : { kind: 'authority-changed', scope });
328
- }
401
+ notifyAuthorityChanged(locators) {
402
+ const named = new Set(locators ?? [...declaredRooms, ...rooms.map((room) => room.locator)]);
403
+ const listed = rooms.filter((room) => named.has(room.locator));
404
+ const left = [...named].filter((locator) => !listed.some((room) => room.locator === locator));
405
+ for (const room of listed)
406
+ declaredRooms.add(room.locator);
407
+ for (const locator of left)
408
+ declaredRooms.delete(locator);
409
+ emitAll({
410
+ kind: 'authority-changed',
411
+ rooms: listed.map(declared),
412
+ left,
413
+ ...(options.member === undefined ? {} : { member: options.member }),
414
+ });
329
415
  },
330
416
  notifyConversation(event) {
331
- if (event.kind === 'accepted-message') {
332
- sealed.add(event.message.turn);
333
- unsealed.delete(event.message.turn);
334
- }
335
417
  for (const listener of listeners)
336
418
  listener(event);
337
419
  },
@@ -340,21 +422,31 @@ export function createMemoryAdapter(options = {}) {
340
422
  observer(mode);
341
423
  },
342
424
  heldRooms() {
343
- return held;
425
+ return [...carried.keys()].sort();
344
426
  },
345
427
  replicatedConversations() {
346
428
  return replicated;
347
429
  },
430
+ heldConversationCursor() {
431
+ return heldCursor;
432
+ },
348
433
  conversations: {
349
434
  replicate(next) {
350
435
  replicated = [...next];
351
436
  },
437
+ hold(cursor) {
438
+ heldCursor = cursor;
439
+ },
352
440
  observe(notify) {
353
441
  listeners.add(notify);
354
442
  return () => {
355
443
  listeners.delete(notify);
356
444
  };
357
445
  },
446
+ history: (request) => Promise.resolve(historiesOf(request)),
447
+ ...(options.agents === undefined
448
+ ? {}
449
+ : { agents: () => Promise.resolve(structuredClone(options.agents)) }),
358
450
  },
359
451
  serviceMode: {
360
452
  observe(notify) {
@@ -366,30 +458,30 @@ export function createMemoryAdapter(options = {}) {
366
458
  },
367
459
  roomStream: {
368
460
  hold(asked) {
369
- held = asked.map((room) => room.locator);
370
- const expired = expiring.filter((locator) => held.includes(locator));
371
- expiring = [];
372
- const moved = asked.flatMap((room) => {
461
+ const named = asked.map((room) => room.locator);
462
+ const unknown = asked.flatMap((room) => {
373
463
  const current = rooms.find((entry) => entry.locator === room.locator);
464
+ const version = room.roomVersion;
374
465
  return current === undefined ||
375
- expired.includes(room.locator) ||
376
- current.roomVersion === room.roomVersion
466
+ (version !== null &&
467
+ (current.roomVersion === version || served.get(room.locator)?.has(version) === true))
377
468
  ? []
378
- : [{ locator: room.locator, roomVersion: current.roomVersion }];
469
+ : [room.locator];
379
470
  });
471
+ const expired = [
472
+ ...new Set([...expiring.filter((locator) => named.includes(locator)), ...unknown]),
473
+ ];
474
+ expiring = expiring.filter((locator) => !named.includes(locator));
380
475
  queueMicrotask(() => {
381
- for (const observer of observers) {
382
- for (const room of moved)
383
- observer({ kind: 'room-version', ...room });
384
- observer({ kind: 'opening', expired });
385
- }
386
- });
387
- },
388
- reopen() {
389
- queueMicrotask(() => {
390
- for (const observer of observers) {
391
- observer({ kind: 'closed', revoked: false, lost: false });
476
+ for (const room of asked) {
477
+ if (expired.includes(room.locator) || room.roomVersion === null)
478
+ carried.delete(room.locator);
479
+ else {
480
+ carried.set(room.locator, room.roomVersion);
481
+ carry(room.locator);
482
+ }
392
483
  }
484
+ emitAll({ kind: 'caught-up', expired });
393
485
  });
394
486
  },
395
487
  observe(notify) {
@@ -398,11 +490,14 @@ export function createMemoryAdapter(options = {}) {
398
490
  if (!observers.has(notify))
399
491
  return;
400
492
  if (options.unopened === true) {
401
- notify({ kind: 'closed', revoked: false, lost: true });
493
+ notify({ kind: 'closed', revoked: false, lost: true, authorityChanged: false });
402
494
  return;
403
495
  }
404
496
  announceList();
405
- notify({ kind: 'opened' });
497
+ opened((event) => {
498
+ if (observers.has(notify))
499
+ notify(event);
500
+ });
406
501
  });
407
502
  return () => {
408
503
  observers.delete(notify);
@@ -419,12 +514,7 @@ export function createMemoryAdapter(options = {}) {
419
514
  return resolveScript(scripts.authorize, () => ({}), undefined);
420
515
  },
421
516
  async discover(_authorization) {
422
- return resolveScript(scripts.discover, discovery, undefined).then((answer) => {
423
- if (answer.kind === 'discovery')
424
- for (const room of answer.rooms)
425
- note(room.locator, room);
426
- return answer;
427
- });
517
+ return discovered();
428
518
  },
429
519
  reached,
430
520
  follows(locator, roomVersion, next) {
@@ -538,7 +628,7 @@ export function createMemoryAdapter(options = {}) {
538
628
  },
539
629
  async action(_authorization, request) {
540
630
  return resolveScript(scripts.action, () => {
541
- if (request.name.startsWith('conversation.'))
631
+ if (request.name.startsWith('conversations/'))
542
632
  return conversationAction(request);
543
633
  return { kind: 'rejected', code: 'unscripted-action', fields: {}, retryable: false };
544
634
  }, request).then((answer) => {
@@ -1,6 +1,9 @@
1
1
  import type { AcceptedMessage } from './adapter.js';
2
+ import type { JobMarker } from './job.js';
2
3
  import type { Connection } from './tables.js';
3
4
  export declare const MESSAGE_TABLES: readonly string[];
5
+ export declare const ROWS = "WITH chosen AS (\n SELECT listed.value AS conversation,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'assistant' ORDER BY position DESC, identity DESC LIMIT 1) AS answer,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND text <> '' ORDER BY position DESC, identity DESC LIMIT 1) AS said,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'house' ORDER BY position, identity LIMIT 1) AS opened,\n (SELECT id FROM conversation_messages WHERE conversation = listed.value AND json_extract(message, '$.role') = 'house' AND json_extract(message, '$.waiting') = 1 ORDER BY position, identity LIMIT 1) AS asking\n FROM json_each(?) AS listed\n )\n SELECT chosen.conversation AS conversation,\n substr(said.text, 1, 512) AS said_text,\n json_extract(said.message, '$.role') AS said_role,\n json_extract(said.message, '$.accepted_at') AS said_at,\n substr(json_extract(answer.message, '$.failure'), 1, 512) AS failure,\n json_extract(opened.message, '$.source') AS opened_source,\n json_extract(opened.message, '$.sender') AS opened_sender,\n asking.identity AS asking_identity,\n substr(asking.text, 1, 512) AS asking_text,\n json_extract(asking.message, '$.accepted_at') AS asking_at,\n json_extract(asking.message, '$.source') AS asking_source,\n json_extract(asking.message, '$.sender') AS asking_sender\n FROM chosen\n LEFT JOIN conversation_messages said ON said.id = chosen.said\n LEFT JOIN conversation_messages answer ON answer.id = chosen.answer\n LEFT JOIN conversation_messages opened ON opened.id = chosen.opened\n LEFT JOIN conversation_messages asking ON asking.id = chosen.asking";
6
+ export declare const JOB_MARKERS = "SELECT json_extract(part.value, '$.text') AS said,\n json_extract(message, '$.accepted_at') AS at\n FROM conversation_messages, json_each(message, '$.parts') AS part\n WHERE conversation = ? AND instr(message, '\"marker\":\"job\"') > 0\n AND json_extract(part.value, '$.type') = 'marker'\n AND json_extract(part.value, '$.marker') = 'job'\n ORDER BY position, identity, part.key";
4
7
  export type HeldConversation = {
5
8
  readonly conversation: string;
6
9
  readonly read: string | null | undefined;
@@ -10,6 +13,25 @@ export type MessageWindow = {
10
13
  readonly messages: AcceptedMessage[];
11
14
  readonly more: boolean;
12
15
  };
16
+ export type HeldSource = {
17
+ readonly source: unknown;
18
+ readonly sender: string | null;
19
+ };
20
+ export type HeldRow = {
21
+ readonly conversation: string;
22
+ readonly said: {
23
+ readonly text: string;
24
+ readonly role: string | null;
25
+ readonly at: string | null;
26
+ } | null;
27
+ readonly failure: string | null;
28
+ readonly opened: HeldSource | null;
29
+ readonly asking: (HeldSource & {
30
+ readonly identity: string;
31
+ readonly text: string;
32
+ readonly at: string | null;
33
+ }) | null;
34
+ };
13
35
  export type ConversationWrite = {
14
36
  readonly conversation: string;
15
37
  readonly messages: readonly AcceptedMessage[];
@@ -18,10 +40,12 @@ export type ConversationWrite = {
18
40
  readonly partial: boolean;
19
41
  };
20
42
  };
21
- export declare function heldConversations(connection: Connection): HeldConversation[];
43
+ export declare function heldConversations(connection: Connection, conversations: readonly string[] | null): HeldConversation[];
22
44
  export declare function keptMessages(connection: Connection, { conversation, messages, read }: ConversationWrite): null;
23
- export declare function messageWindow(connection: Connection, conversation: string, limit: number, before: readonly [string, string] | null): MessageWindow;
24
- export declare function messageCount(connection: Connection, conversation: string): number;
45
+ export declare function messageWindow(connection: Connection, conversation: string, limit: number, before: readonly [string, string] | null, phrase: string | null): MessageWindow;
46
+ export declare function messageCount(connection: Connection, conversation: string, phrase: string | null): number;
47
+ export declare function conversationRows(connection: Connection, conversations: readonly string[]): HeldRow[];
48
+ export declare function jobMarkers(connection: Connection, conversation: string): JobMarker[];
25
49
  export declare function turnArrived(connection: Connection, conversation: string, turn: string): boolean;
26
50
  export declare function droppedMessages(connection: Connection, conversations: readonly string[]): void;
27
51
  export declare function forgottenMessages(connection: Connection): void;
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAM3C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7F,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3E,CAAC;AAMF,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAmB5E;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,iBAAiB,GAClD,IAAI,CAoCN;AAYD,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GACvC,aAAa,CAUf;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAMjF;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAO/F;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAW9F;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAG9D"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"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"}