@agentshouse/mdruntime 0.1.0-ce15a88ae8478 → 0.1.0-ce41fec66d91b

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 (196) hide show
  1. package/README.md +10 -8
  2. package/dist/adapter.d.ts +71 -59
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/attached-model.d.ts +2 -1
  5. package/dist/attached-model.d.ts.map +1 -1
  6. package/dist/attached-model.js +28 -4
  7. package/dist/binary.d.ts +0 -5
  8. package/dist/binary.d.ts.map +1 -1
  9. package/dist/binary.js +1 -1
  10. package/dist/bootstrap.d.ts +16 -8
  11. package/dist/bootstrap.d.ts.map +1 -1
  12. package/dist/bootstrap.js +142 -94
  13. package/dist/client.d.ts +8 -10
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/client.js +54 -8
  16. package/dist/collection.d.ts +5 -3
  17. package/dist/collection.d.ts.map +1 -1
  18. package/dist/collection.js +24 -19
  19. package/dist/compile.d.ts.map +1 -1
  20. package/dist/compile.js +95 -30
  21. package/dist/connection.d.ts +8 -8
  22. package/dist/connection.d.ts.map +1 -1
  23. package/dist/connection.js +1304 -1071
  24. package/dist/conversation.d.ts +13 -11
  25. package/dist/conversation.d.ts.map +1 -1
  26. package/dist/conversation.js +244 -136
  27. package/dist/durability.d.ts +1 -5
  28. package/dist/durability.d.ts.map +1 -1
  29. package/dist/durability.js +5 -0
  30. package/dist/entry.d.ts +1 -0
  31. package/dist/entry.d.ts.map +1 -1
  32. package/dist/entry.js +1 -1
  33. package/dist/file.d.ts +2 -11
  34. package/dist/file.d.ts.map +1 -1
  35. package/dist/file.js +6 -4
  36. package/dist/fulltext.d.ts.map +1 -1
  37. package/dist/fulltext.js +8 -6
  38. package/dist/host.d.ts +3 -4
  39. package/dist/host.d.ts.map +1 -1
  40. package/dist/host.js +40 -20
  41. package/dist/index.d.ts +10 -10
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +4 -3
  44. package/dist/media.d.ts +8 -0
  45. package/dist/media.d.ts.map +1 -0
  46. package/dist/media.js +218 -0
  47. package/dist/memory.d.ts +9 -6
  48. package/dist/memory.d.ts.map +1 -1
  49. package/dist/memory.js +175 -98
  50. package/dist/model.d.ts +6 -1
  51. package/dist/model.d.ts.map +1 -1
  52. package/dist/model.js +7 -10
  53. package/dist/observation.d.ts +1 -0
  54. package/dist/observation.d.ts.map +1 -1
  55. package/dist/observation.js +1 -1
  56. package/dist/outcome.d.ts +13 -6
  57. package/dist/outcome.d.ts.map +1 -1
  58. package/dist/outcome.js +16 -5
  59. package/dist/overlay.js +1 -1
  60. package/dist/paths.d.ts +1 -0
  61. package/dist/paths.d.ts.map +1 -1
  62. package/dist/paths.js +4 -0
  63. package/dist/query.d.ts +6 -0
  64. package/dist/query.d.ts.map +1 -1
  65. package/dist/reach.d.ts +8 -3
  66. package/dist/reach.d.ts.map +1 -1
  67. package/dist/reach.js +67 -51
  68. package/dist/readiness.d.ts +13 -14
  69. package/dist/readiness.d.ts.map +1 -1
  70. package/dist/readiness.js +2 -8
  71. package/dist/recovery.d.ts +1 -0
  72. package/dist/recovery.d.ts.map +1 -1
  73. package/dist/recovery.js +26 -0
  74. package/dist/refresh.d.ts +10 -4
  75. package/dist/refresh.d.ts.map +1 -1
  76. package/dist/refresh.js +85 -30
  77. package/dist/replica.d.ts +5 -5
  78. package/dist/replica.d.ts.map +1 -1
  79. package/dist/replica.js +4 -7
  80. package/dist/room-draft.d.ts +18 -2
  81. package/dist/room-draft.d.ts.map +1 -1
  82. package/dist/room-draft.js +73 -6
  83. package/dist/rows.d.ts +15 -6
  84. package/dist/rows.d.ts.map +1 -1
  85. package/dist/rows.js +102 -74
  86. package/dist/save.d.ts +2 -0
  87. package/dist/save.d.ts.map +1 -1
  88. package/dist/save.js +13 -7
  89. package/dist/shared.d.ts +0 -1
  90. package/dist/shared.d.ts.map +1 -1
  91. package/dist/shared.js +0 -10
  92. package/dist/status.d.ts +4 -3
  93. package/dist/status.d.ts.map +1 -1
  94. package/dist/status.js +3 -1
  95. package/dist/store.d.ts +20 -26
  96. package/dist/store.d.ts.map +1 -1
  97. package/dist/store.js +27 -51
  98. package/dist/stored.d.ts +10 -18
  99. package/dist/stored.d.ts.map +1 -1
  100. package/dist/stored.js +209 -193
  101. package/dist/tables.d.ts +28 -35
  102. package/dist/tables.d.ts.map +1 -1
  103. package/dist/tables.js +58 -50
  104. package/dist/transfer.d.ts +0 -5
  105. package/dist/transfer.d.ts.map +1 -1
  106. package/dist/validation.d.ts +3 -4
  107. package/dist/validation.d.ts.map +1 -1
  108. package/dist/validation.js +35 -96
  109. package/dist/wire.d.ts +5 -9
  110. package/dist/wire.d.ts.map +1 -1
  111. package/dist/wire.js +2 -3
  112. package/dist/words.d.ts.map +1 -1
  113. package/dist/words.js +8 -2
  114. package/package.json +11 -18
  115. package/AGENTS.md +0 -319
  116. package/dist/chat/acts.d.ts +0 -33
  117. package/dist/chat/acts.d.ts.map +0 -1
  118. package/dist/chat/acts.js +0 -36
  119. package/dist/chat/context.d.ts +0 -3
  120. package/dist/chat/context.d.ts.map +0 -1
  121. package/dist/chat/context.js +0 -10
  122. package/dist/chat/earlier.d.ts +0 -10
  123. package/dist/chat/earlier.d.ts.map +0 -1
  124. package/dist/chat/earlier.js +0 -54
  125. package/dist/chat/house.d.ts +0 -25
  126. package/dist/chat/house.d.ts.map +0 -1
  127. package/dist/chat/house.js +0 -38
  128. package/dist/chat/input.d.ts +0 -11
  129. package/dist/chat/input.d.ts.map +0 -1
  130. package/dist/chat/input.js +0 -92
  131. package/dist/chat/kit.d.ts +0 -61
  132. package/dist/chat/kit.d.ts.map +0 -1
  133. package/dist/chat/kit.js +0 -123
  134. package/dist/chat/lasting.d.ts +0 -6
  135. package/dist/chat/lasting.d.ts.map +0 -1
  136. package/dist/chat/lasting.js +0 -19
  137. package/dist/chat/list.d.ts +0 -28
  138. package/dist/chat/list.d.ts.map +0 -1
  139. package/dist/chat/list.js +0 -103
  140. package/dist/chat/markdown.d.ts +0 -21
  141. package/dist/chat/markdown.d.ts.map +0 -1
  142. package/dist/chat/markdown.js +0 -246
  143. package/dist/chat/message.d.ts +0 -7
  144. package/dist/chat/message.d.ts.map +0 -1
  145. package/dist/chat/message.js +0 -254
  146. package/dist/chat/messages.d.ts +0 -35
  147. package/dist/chat/messages.d.ts.map +0 -1
  148. package/dist/chat/messages.js +0 -210
  149. package/dist/chat/name.d.ts +0 -7
  150. package/dist/chat/name.d.ts.map +0 -1
  151. package/dist/chat/name.js +0 -37
  152. package/dist/chat/opened.d.ts +0 -12
  153. package/dist/chat/opened.d.ts.map +0 -1
  154. package/dist/chat/opened.js +0 -19
  155. package/dist/chat/overlay.d.ts +0 -32
  156. package/dist/chat/overlay.d.ts.map +0 -1
  157. package/dist/chat/overlay.js +0 -103
  158. package/dist/chat/parts.d.ts +0 -58
  159. package/dist/chat/parts.d.ts.map +0 -1
  160. package/dist/chat/parts.js +0 -120
  161. package/dist/chat/pieces.d.ts +0 -62
  162. package/dist/chat/pieces.d.ts.map +0 -1
  163. package/dist/chat/pieces.js +0 -1110
  164. package/dist/chat/process.d.ts +0 -20
  165. package/dist/chat/process.d.ts.map +0 -1
  166. package/dist/chat/process.js +0 -32
  167. package/dist/chat/provider.d.ts +0 -70
  168. package/dist/chat/provider.d.ts.map +0 -1
  169. package/dist/chat/provider.js +0 -635
  170. package/dist/chat/question.d.ts +0 -9
  171. package/dist/chat/question.d.ts.map +0 -1
  172. package/dist/chat/question.js +0 -69
  173. package/dist/chat/questions.d.ts +0 -31
  174. package/dist/chat/questions.d.ts.map +0 -1
  175. package/dist/chat/questions.js +0 -111
  176. package/dist/chat/read.d.ts +0 -5
  177. package/dist/chat/read.d.ts.map +0 -1
  178. package/dist/chat/read.js +0 -13
  179. package/dist/chat/ready.d.ts +0 -37
  180. package/dist/chat/ready.d.ts.map +0 -1
  181. package/dist/chat/ready.js +0 -93
  182. package/dist/chat/room-file.d.ts +0 -8
  183. package/dist/chat/room-file.d.ts.map +0 -1
  184. package/dist/chat/room-file.js +0 -72
  185. package/dist/chat/steady.d.ts +0 -3
  186. package/dist/chat/steady.d.ts.map +0 -1
  187. package/dist/chat/steady.js +0 -26
  188. package/dist/chat/style.d.ts +0 -4
  189. package/dist/chat/style.d.ts.map +0 -1
  190. package/dist/chat/style.js +0 -307
  191. package/dist/chat.d.ts +0 -15
  192. package/dist/chat.d.ts.map +0 -1
  193. package/dist/chat.js +0 -8
  194. package/dist/reads.d.ts +0 -11
  195. package/dist/reads.d.ts.map +0 -1
  196. package/dist/reads.js +0 -98
@@ -1,8 +1,9 @@
1
1
  import { conversationChangeSet } from './change-set.js';
2
2
  import { runtimeError } from './failure.js';
3
- import { declaredFile } from './file.js';
3
+ import { refusedForSpace } from './durability.js';
4
4
  import { changeBatchIdentity, chatDraftRevision } from './identity.js';
5
5
  import { OFFLINE } from './outcome.js';
6
+ import { untilAnswered } from './recovery.js';
6
7
  import { capped, cursorOf, decodedCursor, FROM_START, messageOrder, precedes } from './windows.js';
7
8
  const QUIET = {
8
9
  turn: null,
@@ -11,6 +12,7 @@ const QUIET = {
11
12
  commands: [],
12
13
  options: [],
13
14
  starting: null,
15
+ subagents: [],
14
16
  link: null,
15
17
  deliveryUnknown: [],
16
18
  };
@@ -20,6 +22,7 @@ const FACTS = [
20
22
  'commands',
21
23
  'options',
22
24
  'starting',
25
+ 'subagents',
23
26
  'link',
24
27
  'deliveryUnknown',
25
28
  ];
@@ -33,6 +36,7 @@ export function unheldView(conversation) {
33
36
  commands: [],
34
37
  options: [],
35
38
  starting: null,
39
+ subagents: [],
36
40
  link: null,
37
41
  deliveryUnknown: [],
38
42
  chatDraft: null,
@@ -40,6 +44,7 @@ export function unheldView(conversation) {
40
44
  }
41
45
  export const SESSION_STARTED = 'Session started';
42
46
  const NEW_CHAT = 'new:';
47
+ export const HISTORY_CONVERSATIONS = 64;
43
48
  export function newChat(agent) {
44
49
  return `${NEW_CHAT}${agent}`;
45
50
  }
@@ -209,6 +214,12 @@ function askedOf(options) {
209
214
  return { limit: capped(limit), after, before: beforeOf(after), total: total === true };
210
215
  }
211
216
  const EXPIRED = { kind: 'rejected', code: 'expired', fields: {}, retryable: false };
217
+ const DURABLE_WRITE = {
218
+ kind: 'rejected',
219
+ code: 'durable-write',
220
+ fields: {},
221
+ retryable: true,
222
+ };
212
223
  function unwritten(draft) {
213
224
  return draft.text === '';
214
225
  }
@@ -248,13 +259,19 @@ export function createConversationStore(deps) {
248
259
  const unsent = new Map();
249
260
  const views = new Map();
250
261
  const listing = new Map();
262
+ let relisting = null;
263
+ let listCursor = null;
251
264
  const creations = new Set();
252
265
  const listWatchers = new Set();
266
+ const unlisted = new Set();
253
267
  let listKnown = false;
268
+ let listHeld = false;
269
+ let listKept = false;
254
270
  const agentWatchers = new Set();
255
- let agentNames = new Map();
256
- let retiredAgents = new Set();
257
- let agentsRead = null;
271
+ const unnamed = new Set();
272
+ let agentsShown = null;
273
+ let listedAgents = null;
274
+ let agentsReading = false;
258
275
  let replicated = new Set();
259
276
  let handedReplicated;
260
277
  function liveOf(conversation) {
@@ -278,6 +295,7 @@ export function createConversationStore(deps) {
278
295
  commands: structuredClone(facts.commands),
279
296
  options: structuredClone(facts.options),
280
297
  starting: facts.starting,
298
+ subagents: structuredClone(facts.subagents),
281
299
  link: facts.link === null ? null : { ...facts.link },
282
300
  deliveryUnknown: [...facts.deliveryUnknown],
283
301
  chatDraft: draft === undefined || unwritten(draft)
@@ -333,7 +351,7 @@ export function createConversationStore(deps) {
333
351
  function entries() {
334
352
  return [...listing.values()].map((entry) => ({
335
353
  conversation: entry.conversation,
336
- agent: { identity: entry.agent, name: agentNames.get(entry.agent) ?? null },
354
+ agent: { identity: entry.agent, name: entry.agentName },
337
355
  name: entry.name,
338
356
  created: entry.created,
339
357
  finished: entry.finished,
@@ -343,25 +361,100 @@ export function createConversationStore(deps) {
343
361
  started: lives.get(entry.conversation)?.turn?.started ?? null,
344
362
  }));
345
363
  }
364
+ function keepList() {
365
+ if (!listKnown || listKept)
366
+ return;
367
+ listKept = true;
368
+ queueMicrotask(() => {
369
+ listKept = false;
370
+ if (deps.closed())
371
+ return;
372
+ const entries = [...listing.values()];
373
+ const cursor = listCursor;
374
+ void deps
375
+ .durably(async (local) => {
376
+ await local.fact('conversationList', entries);
377
+ await local.fact('conversationCursor', cursor);
378
+ })
379
+ .catch(() => { });
380
+ });
381
+ }
382
+ function listed(entry) {
383
+ listing.set(entry.conversation, { ...entry });
384
+ creations.delete(entry.conversation);
385
+ }
346
386
  function emitList() {
347
- if (deps.closed() || listWatchers.size === 0)
387
+ if (deps.closed())
348
388
  return;
349
- const value = entries();
350
- for (const watcher of listWatchers)
351
- watcher(value);
389
+ if (listWatchers.size > 0) {
390
+ const value = entries();
391
+ for (const watcher of listWatchers)
392
+ watcher(value);
393
+ }
394
+ emitAgents();
395
+ learned();
396
+ }
397
+ function learned() {
398
+ if (deps.closed())
399
+ return;
400
+ if (!listKnown && !listHeld && deps.stream() !== undefined && deps.online())
401
+ return;
402
+ if (unlisted.size > 0) {
403
+ const value = entries();
404
+ for (const watcher of [...unlisted]) {
405
+ unlisted.delete(watcher);
406
+ listWatchers.add(watcher);
407
+ watcher(value);
408
+ }
409
+ }
410
+ if (unnamed.size > 0) {
411
+ const value = agents();
412
+ for (const watcher of [...unnamed]) {
413
+ unnamed.delete(watcher);
414
+ agentWatchers.add(watcher);
415
+ watcher(value);
416
+ }
417
+ }
352
418
  }
353
419
  function agents() {
354
- return [...agentNames]
355
- .filter(([identity]) => !retiredAgents.has(identity))
356
- .map(([identity, name]) => ({ identity, name }))
420
+ const named = new Map();
421
+ for (const agent of listedAgents ?? [])
422
+ named.set(agent.agent, agent);
423
+ for (const entry of listing.values()) {
424
+ named.set(entry.agent, { name: entry.agentName, retired: entry.agentRetired });
425
+ }
426
+ return [...named]
427
+ .filter(([, agent]) => !agent.retired)
428
+ .map(([identity, agent]) => ({ identity, name: agent.name }))
357
429
  .sort((left, right) => left.name === right.name
358
430
  ? left.identity.localeCompare(right.identity)
359
431
  : left.name.localeCompare(right.name));
360
432
  }
433
+ function readAgents() {
434
+ const stream = deps.stream();
435
+ if (stream?.agents === undefined || !deps.online() || agentsReading)
436
+ return;
437
+ agentsReading = true;
438
+ void stream
439
+ .agents()
440
+ .then((read) => {
441
+ if (read === null)
442
+ return;
443
+ listedAgents = read;
444
+ emitAgents();
445
+ }, () => { })
446
+ .finally(() => {
447
+ agentsReading = false;
448
+ });
449
+ }
361
450
  function emitAgents() {
362
451
  if (deps.closed() || agentWatchers.size === 0)
363
452
  return;
364
453
  const value = agents();
454
+ const shown = JSON.stringify(value);
455
+ if (shown === agentsShown)
456
+ return;
457
+ agentsShown = shown;
365
458
  for (const watcher of agentWatchers)
366
459
  watcher(value);
367
460
  }
@@ -377,55 +470,11 @@ export function createConversationStore(deps) {
377
470
  if (stateOf(conversation) !== before || next?.turn?.started !== began)
378
471
  emitList();
379
472
  }
380
- async function readAgents() {
381
- const declaration = deps.agents();
382
- if (declaration === undefined)
383
- return;
384
- const names = new Map();
385
- const retired = new Set();
386
- let covered = null;
387
- for (let after;;) {
388
- const read = await deps.documents(declaration, after);
389
- if ('pending' in read)
390
- return;
391
- const coverage = JSON.stringify(read.coverage);
392
- if (covered !== null && coverage !== covered)
393
- return readAgents();
394
- covered = coverage;
395
- for (const document of read.documents) {
396
- const identity = document.fields?.[declaration.identity];
397
- const name = document.fields?.[declaration.name];
398
- if (typeof identity !== 'string' || typeof name !== 'string')
399
- continue;
400
- names.set(identity, name);
401
- const ended = declaration.retired === undefined ? null : document.fields?.[declaration.retired];
402
- if (ended !== undefined && ended !== null)
403
- retired.add(identity);
404
- }
405
- if (read.next === undefined)
406
- break;
407
- after = read.next;
408
- }
409
- const named = JSON.stringify([...names]) !== JSON.stringify([...agentNames]);
410
- if (!named && JSON.stringify([...retired]) === JSON.stringify([...retiredAgents]))
411
- return;
412
- agentNames = names;
413
- retiredAgents = retired;
414
- if (named)
415
- emitList();
416
- emitAgents();
417
- const ended = [...drafts.keys()].filter(retiredChat);
418
- if (ended.length > 0)
419
- await remove(ended);
420
- }
421
473
  function retiredChat(conversation) {
422
- return (conversation.startsWith(NEW_CHAT) && retiredAgents.has(conversation.slice(NEW_CHAT.length)));
423
- }
424
- function agentsReady() {
425
- agentsRead ??= readAgents().catch(() => {
426
- agentsRead = null;
427
- });
428
- return agentsRead;
474
+ if (!conversation.startsWith(NEW_CHAT))
475
+ return false;
476
+ const agent = conversation.slice(NEW_CHAT.length);
477
+ return [...listing.values()].some((entry) => entry.agent === agent && entry.agentRetired);
429
478
  }
430
479
  function live(conversation, change) {
431
480
  const owed = unsent.get(conversation);
@@ -448,6 +497,7 @@ export function createConversationStore(deps) {
448
497
  commands: facts.has('commands') ? QUIET.commands : held.commands,
449
498
  options: facts.has('options') ? QUIET.options : held.options,
450
499
  starting: facts.has('starting') ? QUIET.starting : held.starting,
500
+ subagents: facts.has('subagents') ? QUIET.subagents : held.subagents,
451
501
  link: facts.has('link') ? QUIET.link : held.link,
452
502
  deliveryUnknown: facts.has('deliveryUnknown')
453
503
  ? QUIET.deliveryUnknown
@@ -501,6 +551,20 @@ export function createConversationStore(deps) {
501
551
  deps.publish(conversationChangeSet(changed));
502
552
  });
503
553
  }
554
+ function missed(conversation) {
555
+ const read = reads.get(conversation);
556
+ const newest = listing.get(conversation)?.newest;
557
+ return (read === undefined ||
558
+ newest === undefined ||
559
+ partials.has(conversation) ||
560
+ (newest !== null && (read === null || newest > read)));
561
+ }
562
+ function noted(conversation, message) {
563
+ const entry = listing.get(conversation);
564
+ if (entry === undefined || (entry.newest !== null && entry.newest >= message.position))
565
+ return;
566
+ listing.set(conversation, { ...entry, newest: message.position });
567
+ }
504
568
  function gap(conversation) {
505
569
  gaps.set(conversation, (gaps.get(conversation) ?? 0) + 1);
506
570
  behind.add(conversation);
@@ -529,12 +593,13 @@ export function createConversationStore(deps) {
529
593
  }
530
594
  async function readHistories(conversations, ended) {
531
595
  const generations = new Map(conversations.map((one) => [one, gaps.get(one) ?? 0]));
532
- let asking = conversations.map((conversation) => ({
596
+ let waiting = conversations.map((conversation) => ({
533
597
  conversation,
534
598
  after: reads.get(conversation) ?? undefined,
535
599
  }));
536
- while (asking.length > 0) {
537
- const result = await deps.call('conversation.history', {
600
+ while (waiting.length > 0) {
601
+ const asking = waiting.slice(0, HISTORY_CONVERSATIONS);
602
+ const result = await deps.history({
538
603
  conversations: asking.map(({ conversation, after }) => ({
539
604
  conversation,
540
605
  ...(after === undefined ? {} : { after }),
@@ -557,7 +622,7 @@ export function createConversationStore(deps) {
557
622
  if (!following.some((next) => next.conversation === conversation))
558
623
  ended(conversation);
559
624
  }
560
- asking = following;
625
+ waiting = [...waiting.slice(HISTORY_CONVERSATIONS), ...following];
561
626
  }
562
627
  return null;
563
628
  }
@@ -637,6 +702,10 @@ export function createConversationStore(deps) {
637
702
  live(conversation, { starting: event.step });
638
703
  return;
639
704
  }
705
+ if (event.kind === 'subagents') {
706
+ live(conversation, { subagents: structuredClone(event.subagents) });
707
+ return;
708
+ }
640
709
  if (event.kind === 'link') {
641
710
  live(conversation, { link: { connected: event.connected } });
642
711
  return;
@@ -648,8 +717,16 @@ export function createConversationStore(deps) {
648
717
  const arriving = acceptedMessage(event.message);
649
718
  if (arriving === null)
650
719
  return;
720
+ noted(conversation, arriving);
651
721
  if (replicated.has(conversation)) {
652
- void keep(conversation, arriving).catch(() => { });
722
+ if (deps.full()) {
723
+ gap(conversation);
724
+ return;
725
+ }
726
+ void keep(conversation, arriving).catch((error) => {
727
+ if (refusedForSpace(error))
728
+ gap(conversation);
729
+ });
653
730
  return;
654
731
  }
655
732
  if (sealTurns(conversation, new Set([arriving.turn])))
@@ -734,20 +811,21 @@ export function createConversationStore(deps) {
734
811
  });
735
812
  }
736
813
  async function dispatched(conversation, submission) {
737
- const dispatch = {};
814
+ const dispatch = { answered: false };
738
815
  sending.set(submission.operation, dispatch);
739
816
  try {
740
- const result = await invoke('conversation.send', conversation, {
741
- text: submission.text,
817
+ const result = await invoke('conversations/send', conversation, {
742
818
  operation_id: submission.operation,
819
+ text: submission.text,
743
820
  });
821
+ dispatch.answered = result.kind !== 'transport-uncertainty';
744
822
  if (result.kind === 'revoked-authorization')
745
823
  return result;
746
824
  if (result.kind !== 'action' && result.retryable) {
747
825
  deps.unanswered();
748
826
  return result;
749
827
  }
750
- const turn = answered(result, 'turn');
828
+ const turn = answered(result, 'message_id');
751
829
  await withDraft(conversation, async (current, local) => {
752
830
  const held = current?.submitted?.find((one) => one.operation === submission.operation);
753
831
  if (current === undefined || held === undefined || held.turn !== null)
@@ -767,13 +845,20 @@ export function createConversationStore(deps) {
767
845
  sending.delete(submission.operation);
768
846
  }
769
847
  }
770
- function invoke(name, conversation, extra = {}) {
771
- return deps.call(name, { conversation, ...extra });
848
+ function invoke(name, conversation, extra = { operation_id: changeBatchIdentity() }) {
849
+ return deps.call(name, { conversation_id: conversation, ...extra });
772
850
  }
773
851
  const surface = {
774
- async list() {
775
- await agentsReady();
776
- return entries();
852
+ list() {
853
+ return new Promise((settle) => {
854
+ const answer = (listed) => {
855
+ unlisted.delete(answer);
856
+ listWatchers.delete(answer);
857
+ settle(listed);
858
+ };
859
+ unlisted.add(answer);
860
+ learned();
861
+ });
777
862
  },
778
863
  async read(conversation, options = {}) {
779
864
  const asked = askedOf(options);
@@ -784,8 +869,8 @@ export function createConversationStore(deps) {
784
869
  });
785
870
  },
786
871
  async create(input) {
787
- const result = await deps.call('conversation.create', input);
788
- const conversation = answered(result, 'conversation');
872
+ const result = await deps.call('conversations/create', input);
873
+ const conversation = answered(result, 'conversation_id');
789
874
  if (conversation === null)
790
875
  return result;
791
876
  if (!listing.has(conversation))
@@ -796,8 +881,17 @@ export function createConversationStore(deps) {
796
881
  return result;
797
882
  },
798
883
  async send(conversation, operation = changeBatchIdentity(), draft) {
884
+ if (deps.full())
885
+ return DURABLE_WRITE;
799
886
  if (deps.online()) {
800
- const { submission, earlier } = await submitted(conversation, operation, draft);
887
+ const held = await submitted(conversation, operation, draft).catch((error) => {
888
+ if (refusedForSpace(error))
889
+ return null;
890
+ throw error;
891
+ });
892
+ if (held === null)
893
+ return DURABLE_WRITE;
894
+ const { submission, earlier } = held;
801
895
  if (!earlier || !deps.expired(operation))
802
896
  return dispatched(conversation, submission);
803
897
  await forgotten(conversation, submission);
@@ -810,38 +904,20 @@ export function createConversationStore(deps) {
810
904
  }
811
905
  return OFFLINE;
812
906
  },
813
- async attach(room, file) {
814
- if (!deps.online())
815
- return OFFLINE;
816
- return deps.call('conversation.attach', {
817
- room,
818
- ...(await declaredFile(file)),
819
- blob: file.blob,
820
- });
821
- },
822
907
  answer(conversation, answer) {
823
- return invoke('conversation.answer', conversation, { answer });
908
+ return invoke('conversations/interaction/answer', conversation, {
909
+ operation_id: changeBatchIdentity(),
910
+ ...answer,
911
+ });
824
912
  },
825
913
  interrupt(conversation) {
826
- return invoke('conversation.interrupt', conversation);
914
+ return invoke('conversations/interrupt', conversation);
827
915
  },
828
916
  kill(conversation) {
829
- return invoke('conversation.kill', conversation);
830
- },
831
- async cancel(conversation, turn) {
832
- const result = await invoke('conversation.cancel', conversation, { turn });
833
- if (result.kind !== 'action')
834
- return result;
835
- await withDraft(conversation, (current) => {
836
- const held = current?.submitted?.find((one) => one.turn === turn);
837
- if (current === undefined || held === undefined)
838
- return undefined;
839
- return returned(current, held, current.submitted.filter((one) => one !== held));
840
- });
841
- return result;
917
+ return invoke('conversations/kill', conversation);
842
918
  },
843
919
  delete(conversation) {
844
- return invoke('conversation.delete', conversation);
920
+ return invoke('conversations/delete', conversation);
845
921
  },
846
922
  };
847
923
  const chatDraft = {
@@ -870,7 +946,15 @@ export function createConversationStore(deps) {
870
946
  return {
871
947
  surface,
872
948
  chatDraft,
873
- hydrate(held, kept) {
949
+ hydrate(held, kept, list, cursor) {
950
+ if (list !== null && !listKnown) {
951
+ listing.clear();
952
+ for (const entry of list)
953
+ listing.set(entry.conversation, { ...entry });
954
+ listHeld = true;
955
+ listCursor = cursor;
956
+ deps.stream()?.hold(cursor);
957
+ }
874
958
  stored.clear();
875
959
  reads.clear();
876
960
  partials.clear();
@@ -884,6 +968,8 @@ export function createConversationStore(deps) {
884
968
  drafts.clear();
885
969
  for (const record of kept)
886
970
  drafts.set(record.conversation, record);
971
+ if (listHeld)
972
+ learned();
887
973
  },
888
974
  async reconcile() {
889
975
  if (!listKnown)
@@ -895,7 +981,7 @@ export function createConversationStore(deps) {
895
981
  !creations.has(conversation) &&
896
982
  (!conversation.startsWith(NEW_CHAT) || retiredChat(conversation)));
897
983
  for (const conversation of named) {
898
- if (!replicated.has(conversation))
984
+ if (!replicated.has(conversation) && missed(conversation))
899
985
  behind.add(conversation);
900
986
  }
901
987
  replicated = named;
@@ -904,6 +990,11 @@ export function createConversationStore(deps) {
904
990
  await remove(leaving);
905
991
  },
906
992
  async catchUp(progress) {
993
+ if (deps.full()) {
994
+ if (behind.size > 0)
995
+ progress.complete = false;
996
+ return;
997
+ }
907
998
  const owed = (conversation) => behind.has(conversation) && replicated.has(conversation);
908
999
  const read = async (conversations) => {
909
1000
  if (conversations.length === 0 || deps.closed())
@@ -952,12 +1043,11 @@ export function createConversationStore(deps) {
952
1043
  known() {
953
1044
  return listKnown;
954
1045
  },
955
- reconnected() {
956
- for (const conversation of replicated)
957
- gap(conversation);
958
- },
959
1046
  reopened() {
960
- sending.clear();
1047
+ relisting = null;
1048
+ for (const [operation, dispatch] of sending)
1049
+ if (!dispatch.answered)
1050
+ sending.delete(operation);
961
1051
  },
962
1052
  lost() {
963
1053
  catching.clear();
@@ -976,15 +1066,15 @@ export function createConversationStore(deps) {
976
1066
  views.set(key, view);
977
1067
  const watcher = { notify: deliver, ready: false };
978
1068
  view.watchers.add(watcher);
979
- void deps
980
- .durably(async (local) => {
1069
+ const reading = new AbortController();
1070
+ void untilAnswered(() => deps.durably(async (local) => {
981
1071
  if (view.window !== null)
982
1072
  return;
983
1073
  const { messages, more } = await local.messageWindow(conversation, asked.limit, asked.before);
984
1074
  view.window = messages;
985
1075
  view.more = more;
986
1076
  view.total = asked.total ? await local.messageCount(conversation) : null;
987
- })
1077
+ }), reading.signal)
988
1078
  .then(() => {
989
1079
  if (deps.closed() || !view.watchers.has(watcher))
990
1080
  return;
@@ -994,6 +1084,7 @@ export function createConversationStore(deps) {
994
1084
  })
995
1085
  .catch(() => { });
996
1086
  return () => {
1087
+ reading.abort();
997
1088
  if (!view.watchers.delete(watcher))
998
1089
  return;
999
1090
  if (view.watchers.size === 0)
@@ -1001,61 +1092,76 @@ export function createConversationStore(deps) {
1001
1092
  };
1002
1093
  },
1003
1094
  watchList(deliver) {
1004
- listWatchers.add(deliver);
1005
- void agentsReady().then(() => {
1006
- if (!deps.closed() && listWatchers.has(deliver))
1007
- deliver(entries());
1008
- });
1095
+ unlisted.add(deliver);
1096
+ learned();
1009
1097
  return () => {
1098
+ unlisted.delete(deliver);
1010
1099
  listWatchers.delete(deliver);
1011
1100
  };
1012
1101
  },
1013
1102
  watchAgents(deliver) {
1014
- agentWatchers.add(deliver);
1015
- void agentsReady().then(() => {
1016
- if (!deps.closed() && agentWatchers.has(deliver))
1017
- deliver(agents());
1018
- });
1103
+ unnamed.add(deliver);
1104
+ learned();
1105
+ readAgents();
1019
1106
  return () => {
1107
+ unnamed.delete(deliver);
1020
1108
  agentWatchers.delete(deliver);
1021
1109
  };
1022
1110
  },
1111
+ learned,
1023
1112
  changed(set) {
1024
1113
  for (const conversation of set.conversations)
1025
1114
  emit(conversation);
1026
- const declaration = deps.agents();
1027
- if (declaration !== undefined &&
1028
- set.documents.some((change) => change.locator === declaration.locator)) {
1029
- agentsRead = readAgents().catch(() => {
1030
- agentsRead = null;
1031
- });
1032
- }
1033
1115
  },
1034
1116
  receive(event) {
1035
1117
  if (deps.closed())
1036
1118
  return false;
1037
1119
  if (event.kind === 'list' || event.kind === 'listed' || event.kind === 'unlisted') {
1038
1120
  if (event.kind === 'list') {
1039
- listing.clear();
1121
+ if (event.whole)
1122
+ relisting ??= new Map();
1040
1123
  for (const entry of event.entries) {
1041
- listing.set(entry.conversation, { ...entry });
1042
- creations.delete(entry.conversation);
1124
+ if (relisting === null)
1125
+ listed(entry);
1126
+ else
1127
+ relisting.set(entry.conversation, { ...entry });
1043
1128
  }
1129
+ if (event.more)
1130
+ return false;
1131
+ if (relisting !== null) {
1132
+ listing.clear();
1133
+ for (const entry of relisting.values())
1134
+ listed(entry);
1135
+ relisting = null;
1136
+ }
1137
+ listCursor = event.cursor;
1138
+ deps.stream()?.hold(event.cursor);
1044
1139
  listKnown = true;
1140
+ for (const conversation of replicated) {
1141
+ if (!listing.has(conversation))
1142
+ continue;
1143
+ if (!missed(conversation))
1144
+ behind.delete(conversation);
1145
+ else if (!behind.has(conversation))
1146
+ gap(conversation);
1147
+ }
1045
1148
  openingEnded();
1046
1149
  }
1047
1150
  else if (event.kind === 'listed') {
1048
- listing.set(event.entry.conversation, { ...event.entry });
1049
- creations.delete(event.entry.conversation);
1151
+ listed(event.entry);
1152
+ relisting?.set(event.entry.conversation, { ...event.entry });
1050
1153
  }
1051
1154
  else {
1052
1155
  listing.delete(event.conversation);
1156
+ relisting?.delete(event.conversation);
1053
1157
  }
1158
+ keepList();
1054
1159
  emitList();
1055
- return (event.kind !== 'list' &&
1160
+ return ((event.kind !== 'list' &&
1056
1161
  listKnown &&
1057
1162
  (listing.size !== replicated.size ||
1058
- [...listing.keys()].some((conversation) => !replicated.has(conversation))));
1163
+ [...listing.keys()].some((conversation) => !replicated.has(conversation)))) ||
1164
+ (listKnown && [...drafts.keys()].some(retiredChat)));
1059
1165
  }
1060
1166
  heard(event);
1061
1167
  return false;
@@ -1071,7 +1177,9 @@ export function createConversationStore(deps) {
1071
1177
  lives.clear();
1072
1178
  unsent.clear();
1073
1179
  listWatchers.clear();
1180
+ unlisted.clear();
1074
1181
  agentWatchers.clear();
1182
+ unnamed.clear();
1075
1183
  },
1076
1184
  };
1077
1185
  }
@@ -1,16 +1,12 @@
1
1
  import type { Persistence } from './readiness.js';
2
- export type StorageEstimate = {
3
- readonly usage: number;
4
- readonly total: number;
5
- };
6
2
  export type RuntimeShell = {
7
3
  persistence: Persistence;
8
4
  generation: string | null;
9
5
  keepGeneration(value: string): void | Promise<void>;
10
6
  dropGeneration(): void | Promise<void>;
11
- estimate?(): Promise<StorageEstimate | null>;
12
7
  cleanUp?(): Promise<number>;
13
8
  };
9
+ export declare function refusedForSpace(error: unknown): boolean;
14
10
  export declare function detectStorageLoss(stored: string | null, reported: string | null): string | null;
15
11
  export declare function nextGeneration(stored: string | null, reported: string | null): string;
16
12
  //# sourceMappingURL=durability.d.ts.map