@agentshouse/mdruntime 0.1.0-alpha.3 → 0.1.0-alpha.31

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 (128) hide show
  1. package/AGENTS.md +178 -0
  2. package/dist/adapter.d.ts +150 -18
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/adapter.js +2 -1
  5. package/dist/adapter.js.map +1 -1
  6. package/dist/bootstrap.d.ts +7 -7
  7. package/dist/bootstrap.d.ts.map +1 -1
  8. package/dist/bootstrap.js +13 -9
  9. package/dist/bootstrap.js.map +1 -1
  10. package/dist/change-set.d.ts +33 -0
  11. package/dist/change-set.d.ts.map +1 -0
  12. package/dist/change-set.js +89 -0
  13. package/dist/change-set.js.map +1 -0
  14. package/dist/change.d.ts +10 -0
  15. package/dist/change.d.ts.map +1 -1
  16. package/dist/change.js.map +1 -1
  17. package/dist/client.d.ts +72 -0
  18. package/dist/client.d.ts.map +1 -0
  19. package/dist/client.js +231 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/collection.d.ts +22 -12
  22. package/dist/collection.d.ts.map +1 -1
  23. package/dist/collection.js +88 -30
  24. package/dist/collection.js.map +1 -1
  25. package/dist/connection.d.ts +90 -20
  26. package/dist/connection.d.ts.map +1 -1
  27. package/dist/connection.js +1776 -194
  28. package/dist/connection.js.map +1 -1
  29. package/dist/conversation.d.ts +72 -0
  30. package/dist/conversation.d.ts.map +1 -0
  31. package/dist/conversation.js +529 -0
  32. package/dist/conversation.js.map +1 -0
  33. package/dist/durability.d.ts +9 -0
  34. package/dist/durability.d.ts.map +1 -0
  35. package/dist/durability.js +11 -0
  36. package/dist/durability.js.map +1 -0
  37. package/dist/file.d.ts +20 -0
  38. package/dist/file.d.ts.map +1 -0
  39. package/dist/file.js +149 -0
  40. package/dist/file.js.map +1 -0
  41. package/dist/host.d.ts +13 -0
  42. package/dist/host.d.ts.map +1 -0
  43. package/dist/host.js +205 -0
  44. package/dist/host.js.map +1 -0
  45. package/dist/identity.d.ts +3 -0
  46. package/dist/identity.d.ts.map +1 -0
  47. package/dist/identity.js +23 -0
  48. package/dist/identity.js.map +1 -0
  49. package/dist/index.d.ts +15 -6
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +1 -0
  52. package/dist/index.js.map +1 -1
  53. package/dist/log.d.ts +5 -0
  54. package/dist/log.d.ts.map +1 -0
  55. package/dist/log.js +15 -0
  56. package/dist/log.js.map +1 -0
  57. package/dist/memory.d.ts +17 -2
  58. package/dist/memory.d.ts.map +1 -1
  59. package/dist/memory.js +201 -15
  60. package/dist/memory.js.map +1 -1
  61. package/dist/model.d.ts +56 -0
  62. package/dist/model.d.ts.map +1 -0
  63. package/dist/model.js +37 -0
  64. package/dist/model.js.map +1 -0
  65. package/dist/observation.d.ts +25 -0
  66. package/dist/observation.d.ts.map +1 -0
  67. package/dist/observation.js +92 -0
  68. package/dist/observation.js.map +1 -0
  69. package/dist/outcome.d.ts +34 -0
  70. package/dist/outcome.d.ts.map +1 -0
  71. package/dist/outcome.js +3 -0
  72. package/dist/outcome.js.map +1 -0
  73. package/dist/overlay.d.ts +2 -0
  74. package/dist/overlay.d.ts.map +1 -1
  75. package/dist/overlay.js +107 -1
  76. package/dist/overlay.js.map +1 -1
  77. package/dist/paths.d.ts +0 -1
  78. package/dist/paths.d.ts.map +1 -1
  79. package/dist/paths.js +0 -4
  80. package/dist/paths.js.map +1 -1
  81. package/dist/query.d.ts +209 -0
  82. package/dist/query.d.ts.map +1 -0
  83. package/dist/query.js +467 -0
  84. package/dist/query.js.map +1 -0
  85. package/dist/read-side.d.ts +14 -0
  86. package/dist/read-side.d.ts.map +1 -0
  87. package/dist/read-side.js +451 -0
  88. package/dist/read-side.js.map +1 -0
  89. package/dist/refresh.d.ts +2 -2
  90. package/dist/refresh.d.ts.map +1 -1
  91. package/dist/refresh.js +8 -6
  92. package/dist/refresh.js.map +1 -1
  93. package/dist/replica.d.ts +22 -3
  94. package/dist/replica.d.ts.map +1 -1
  95. package/dist/replica.js +170 -8
  96. package/dist/replica.js.map +1 -1
  97. package/dist/room-draft.d.ts +124 -0
  98. package/dist/room-draft.d.ts.map +1 -0
  99. package/dist/room-draft.js +406 -0
  100. package/dist/room-draft.js.map +1 -0
  101. package/dist/rows.d.ts +39 -0
  102. package/dist/rows.d.ts.map +1 -0
  103. package/dist/rows.js +100 -0
  104. package/dist/rows.js.map +1 -0
  105. package/dist/save.d.ts +11 -2
  106. package/dist/save.d.ts.map +1 -1
  107. package/dist/save.js +104 -128
  108. package/dist/save.js.map +1 -1
  109. package/dist/search.d.ts +61 -0
  110. package/dist/search.d.ts.map +1 -0
  111. package/dist/search.js +155 -0
  112. package/dist/search.js.map +1 -0
  113. package/dist/status.d.ts +9 -1
  114. package/dist/status.d.ts.map +1 -1
  115. package/dist/status.js +7 -4
  116. package/dist/status.js.map +1 -1
  117. package/dist/store.d.ts +87 -15
  118. package/dist/store.d.ts.map +1 -1
  119. package/dist/store.js +436 -54
  120. package/dist/store.js.map +1 -1
  121. package/dist/transfer.d.ts +5 -0
  122. package/dist/transfer.d.ts.map +1 -1
  123. package/dist/transfer.js.map +1 -1
  124. package/dist/wire.d.ts +64 -0
  125. package/dist/wire.d.ts.map +1 -0
  126. package/dist/wire.js +142 -0
  127. package/dist/wire.js.map +1 -0
  128. package/package.json +14 -4
@@ -0,0 +1,529 @@
1
+ import { conversationChangeSet } from './change-set.js';
2
+ import { declaredFile } from './file.js';
3
+ function ordered(left, right) {
4
+ if (left.position !== right.position) return left.position < right.position ? -1 : 1;
5
+ if (left.identity !== right.identity) return left.identity < right.identity ? -1 : 1;
6
+ return 0;
7
+ }
8
+ function merged(held, arriving) {
9
+ const byIdentity = new Map(held.map((message)=>[
10
+ message.identity,
11
+ message
12
+ ]));
13
+ for (const message of arriving)byIdentity.set(message.identity, message);
14
+ return [
15
+ ...byIdentity.values()
16
+ ].sort(ordered);
17
+ }
18
+ function acceptedMessage(value) {
19
+ if (typeof value !== 'object' || value === null) return null;
20
+ const record = value;
21
+ if (typeof record.identity !== 'string' || typeof record.turn !== 'string' || typeof record.position !== 'string' || typeof record.text !== 'string') {
22
+ return null;
23
+ }
24
+ return {
25
+ identity: record.identity,
26
+ turn: record.turn,
27
+ position: record.position,
28
+ text: record.text,
29
+ message: structuredClone(record.message)
30
+ };
31
+ }
32
+ function historyPage(result) {
33
+ if (result.kind !== 'action') return null;
34
+ const answer = result.result;
35
+ if (typeof answer !== 'object' || answer === null) return null;
36
+ const record = answer;
37
+ if (!Array.isArray(record.messages)) return null;
38
+ if (record.next !== undefined && typeof record.next !== 'string') return null;
39
+ const messages = [];
40
+ for (const entry of record.messages){
41
+ const message = acceptedMessage(entry);
42
+ if (message === null) return null;
43
+ messages.push(message);
44
+ }
45
+ return {
46
+ messages,
47
+ ...record.next === undefined ? {} : {
48
+ next: record.next
49
+ }
50
+ };
51
+ }
52
+ function turnOf(result) {
53
+ if (result.kind !== 'action') return null;
54
+ const answer = result.result;
55
+ if (typeof answer !== 'object' || answer === null) return null;
56
+ const record = answer;
57
+ return typeof record.turn === 'string' ? record.turn : null;
58
+ }
59
+ function limitOf(options) {
60
+ const { limit } = options;
61
+ if (limit === undefined) return undefined;
62
+ if (!Number.isInteger(limit) || limit < 0) {
63
+ throw new Error(`conversation limit must be a non-negative integer, got ${String(limit)}`);
64
+ }
65
+ return limit;
66
+ }
67
+ export function createConversationStore(deps) {
68
+ const messages = new Map();
69
+ const reads = new Map();
70
+ const drafts = new Map();
71
+ const sending = new Map();
72
+ const behind = new Set();
73
+ const gaps = new Map();
74
+ const growing = new Map();
75
+ const summaries = new Map();
76
+ const views = new Map();
77
+ let replicated = new Set();
78
+ let handedReplicated;
79
+ let handedViewed;
80
+ function viewOf(conversation, limit) {
81
+ const held = messages.get(conversation) ?? [];
82
+ const shown = limit === undefined ? held : held.slice(Math.max(0, held.length - limit));
83
+ const draft = drafts.get(conversation);
84
+ return {
85
+ conversation,
86
+ messages: shown.map(({ identity, turn, text, message })=>({
87
+ identity,
88
+ turn,
89
+ text,
90
+ message: structuredClone(message)
91
+ })),
92
+ growingText: growing.get(conversation) ?? null,
93
+ summary: structuredClone(summaries.get(conversation) ?? null),
94
+ chatDraft: draft === undefined || draft.turn !== null || sending.get(conversation)?.draft === draft ? null : {
95
+ text: draft.text,
96
+ files: [
97
+ ...draft.files
98
+ ]
99
+ }
100
+ };
101
+ }
102
+ function emit(conversation) {
103
+ if (deps.closed()) return;
104
+ for (const view of views.values()){
105
+ if (view.conversation !== conversation) continue;
106
+ const ready = [
107
+ ...view.watchers
108
+ ].filter((watcher)=>watcher.ready);
109
+ if (ready.length === 0) continue;
110
+ const value = viewOf(conversation, view.limit);
111
+ for (const watcher of ready)watcher.notify(value);
112
+ }
113
+ }
114
+ function viewed() {
115
+ return [
116
+ ...new Set([
117
+ ...views.values()
118
+ ].map((view)=>view.conversation))
119
+ ].sort();
120
+ }
121
+ function handViewed() {
122
+ const stream = deps.stream();
123
+ if (stream === undefined) return;
124
+ const open = viewed();
125
+ const named = JSON.stringify(open);
126
+ if (named === handedViewed) return;
127
+ handedViewed = named;
128
+ stream.view(open);
129
+ }
130
+ function handReplicated() {
131
+ const stream = deps.stream();
132
+ if (stream === undefined) return;
133
+ const held = [
134
+ ...replicated
135
+ ].sort();
136
+ const named = JSON.stringify(held);
137
+ if (named === handedReplicated) return;
138
+ handedReplicated = named;
139
+ stream.replicate(held);
140
+ }
141
+ async function documented() {
142
+ const declaration = deps.cards();
143
+ if (declaration === undefined) return [];
144
+ const { documents } = await deps.documents(declaration.locator);
145
+ return documents.filter((document)=>typeof document.type === 'string');
146
+ }
147
+ function carded(documents) {
148
+ const declaration = deps.cards();
149
+ if (declaration === undefined) return [];
150
+ const cards = [];
151
+ for (const card of documents){
152
+ if (card.type !== declaration.type) continue;
153
+ const identity = card.fields[declaration.identity];
154
+ if (typeof identity === 'string') cards.push({
155
+ conversation: identity,
156
+ card
157
+ });
158
+ }
159
+ return cards;
160
+ }
161
+ async function remove(leaving) {
162
+ await deps.durably(async (local)=>{
163
+ await local.dropConversations(leaving);
164
+ const removed = [];
165
+ const changed = [];
166
+ for (const conversation of leaving){
167
+ for (const message of messages.get(conversation) ?? []){
168
+ removed.push({
169
+ conversation,
170
+ identity: message.identity
171
+ });
172
+ }
173
+ if (messages.has(conversation) || drafts.has(conversation) || growing.has(conversation) || summaries.has(conversation)) {
174
+ changed.push(conversation);
175
+ }
176
+ messages.delete(conversation);
177
+ reads.delete(conversation);
178
+ drafts.delete(conversation);
179
+ behind.delete(conversation);
180
+ growing.delete(conversation);
181
+ summaries.delete(conversation);
182
+ }
183
+ if (changed.length > 0) deps.publish(conversationChangeSet(removed, changed));
184
+ });
185
+ }
186
+ function gap(conversation) {
187
+ gaps.set(conversation, (gaps.get(conversation) ?? 0) + 1);
188
+ behind.add(conversation);
189
+ }
190
+ function keep(conversation, message) {
191
+ return deps.durably(async (local)=>{
192
+ if (!replicated.has(conversation)) return;
193
+ const read = reads.get(conversation);
194
+ const advances = read !== undefined && !behind.has(conversation) && (read === null || message.position > read);
195
+ const sealed = drafts.get(conversation)?.turn === message.turn;
196
+ await local.keepMessages({
197
+ conversation,
198
+ messages: [
199
+ message
200
+ ],
201
+ ...advances ? {
202
+ read: message.position
203
+ } : {},
204
+ sealed
205
+ });
206
+ messages.set(conversation, merged(messages.get(conversation) ?? [], [
207
+ message
208
+ ]));
209
+ if (advances) reads.set(conversation, message.position);
210
+ if (sealed) drafts.delete(conversation);
211
+ if (growing.get(conversation)?.turn === message.turn) growing.delete(conversation);
212
+ deps.publish(conversationChangeSet([
213
+ {
214
+ conversation,
215
+ identity: message.identity
216
+ }
217
+ ], [
218
+ conversation
219
+ ]));
220
+ });
221
+ }
222
+ async function readHistory(conversation) {
223
+ const generation = gaps.get(conversation) ?? 0;
224
+ const from = reads.get(conversation);
225
+ const arriving = [];
226
+ let after = from ?? undefined;
227
+ for(;;){
228
+ const result = await deps.call('conversation.history', {
229
+ conversation,
230
+ ...after === undefined ? {} : {
231
+ after
232
+ }
233
+ });
234
+ const page = historyPage(result);
235
+ if (page === null) return result;
236
+ arriving.push(...page.messages);
237
+ if (page.next === undefined) break;
238
+ after = page.next;
239
+ }
240
+ await deps.durably(async (local)=>{
241
+ if (!replicated.has(conversation)) return;
242
+ const newest = arriving.reduce((top, message)=>top === null || message.position > top ? message.position : top, from ?? null);
243
+ const turn = drafts.get(conversation)?.turn;
244
+ const sealed = arriving.some((message)=>message.turn === turn);
245
+ await local.keepMessages({
246
+ conversation,
247
+ messages: arriving,
248
+ read: newest,
249
+ sealed
250
+ });
251
+ messages.set(conversation, merged(messages.get(conversation) ?? [], arriving));
252
+ reads.set(conversation, newest);
253
+ if (sealed) drafts.delete(conversation);
254
+ const growingTurn = growing.get(conversation)?.turn;
255
+ if (arriving.some((message)=>message.turn === growingTurn)) growing.delete(conversation);
256
+ if ((gaps.get(conversation) ?? 0) === generation) behind.delete(conversation);
257
+ if (arriving.length > 0 || sealed) {
258
+ deps.publish(conversationChangeSet(arriving.map((message)=>({
259
+ conversation,
260
+ identity: message.identity
261
+ })), [
262
+ conversation
263
+ ]));
264
+ }
265
+ });
266
+ return null;
267
+ }
268
+ function withDraft(conversation, next) {
269
+ return deps.durably(async (local)=>{
270
+ const following = next(drafts.get(conversation));
271
+ if (following === undefined) return;
272
+ if (following === null) {
273
+ await local.dropChatDraft(conversation);
274
+ drafts.delete(conversation);
275
+ } else {
276
+ await local.keepChatDraft(following);
277
+ drafts.set(conversation, following);
278
+ }
279
+ deps.publish(conversationChangeSet([], [
280
+ conversation
281
+ ]));
282
+ });
283
+ }
284
+ function invoke(name, conversation, extra = {}) {
285
+ return deps.call(name, {
286
+ conversation,
287
+ ...extra
288
+ });
289
+ }
290
+ const surface = {
291
+ async list () {
292
+ const declaration = deps.cards();
293
+ if (declaration === undefined) return [];
294
+ const documents = await documented();
295
+ const entries = carded(documents).map(({ conversation, card })=>({
296
+ conversation,
297
+ card,
298
+ agent: documents.find((document)=>document.backlinks.some((backlink)=>backlink.path === card.path && backlink.field === declaration.agent)) ?? null
299
+ }));
300
+ entries.sort((left, right)=>left.conversation < right.conversation ? -1 : 1);
301
+ return entries;
302
+ },
303
+ async read (conversation, options = {}) {
304
+ const limit = limitOf(options);
305
+ return deps.durably(()=>Promise.resolve(viewOf(conversation, limit)));
306
+ },
307
+ create (input) {
308
+ return deps.call('conversation.create', input);
309
+ },
310
+ async send (conversation) {
311
+ const draft = drafts.get(conversation);
312
+ const pending = draft === undefined ? undefined : {
313
+ draft
314
+ };
315
+ if (pending !== undefined) {
316
+ sending.set(conversation, pending);
317
+ deps.publish(conversationChangeSet([], [
318
+ conversation
319
+ ]));
320
+ }
321
+ try {
322
+ const files = await Promise.all((draft?.files ?? []).map(async (file)=>({
323
+ ...await declaredFile(file),
324
+ blob: file.blob
325
+ })));
326
+ const result = await invoke('conversation.send', conversation, {
327
+ text: draft?.text ?? '',
328
+ files
329
+ });
330
+ const turn = turnOf(result);
331
+ if (turn === null || draft === undefined) return result;
332
+ await withDraft(conversation, (current)=>{
333
+ if (current !== draft) return undefined;
334
+ const sealed = (messages.get(conversation) ?? []).some((message)=>message.turn === turn);
335
+ return sealed ? null : {
336
+ ...draft,
337
+ turn
338
+ };
339
+ });
340
+ return result;
341
+ } finally{
342
+ if (pending !== undefined && sending.get(conversation) === pending) {
343
+ sending.delete(conversation);
344
+ if (drafts.get(conversation) === draft) {
345
+ deps.publish(conversationChangeSet([], [
346
+ conversation
347
+ ]));
348
+ }
349
+ }
350
+ }
351
+ },
352
+ answer (conversation, answer) {
353
+ return invoke('conversation.answer', conversation, {
354
+ answer
355
+ });
356
+ },
357
+ interrupt (conversation) {
358
+ return invoke('conversation.interrupt', conversation);
359
+ },
360
+ kill (conversation) {
361
+ return invoke('conversation.kill', conversation);
362
+ },
363
+ async cancel (conversation, turn) {
364
+ const result = await invoke('conversation.cancel', conversation, {
365
+ turn
366
+ });
367
+ if (result.kind !== 'action') return result;
368
+ await withDraft(conversation, (current)=>current === undefined || current.turn !== turn ? undefined : {
369
+ ...current,
370
+ turn: null
371
+ });
372
+ return result;
373
+ },
374
+ delete (conversation) {
375
+ return invoke('conversation.delete', conversation);
376
+ }
377
+ };
378
+ const chatDraft = {
379
+ write (conversation, draft) {
380
+ return withDraft(conversation, ()=>({
381
+ conversation,
382
+ text: draft.text,
383
+ files: [
384
+ ...draft.files
385
+ ],
386
+ turn: null
387
+ }));
388
+ },
389
+ discard (conversation) {
390
+ return withDraft(conversation, (current)=>current === undefined ? undefined : null);
391
+ }
392
+ };
393
+ return {
394
+ surface,
395
+ chatDraft,
396
+ hydrate (held, stored) {
397
+ messages.clear();
398
+ reads.clear();
399
+ for (const entry of held){
400
+ messages.set(entry.conversation, [
401
+ ...entry.messages
402
+ ].sort(ordered));
403
+ if (entry.read !== undefined) reads.set(entry.conversation, entry.read);
404
+ }
405
+ drafts.clear();
406
+ for (const record of stored)drafts.set(record.conversation, record);
407
+ },
408
+ async reconcile () {
409
+ const named = new Set(carded(await documented()).map((entry)=>entry.conversation));
410
+ const leaving = [
411
+ ...new Set([
412
+ ...replicated,
413
+ ...messages.keys(),
414
+ ...reads.keys(),
415
+ ...drafts.keys()
416
+ ])
417
+ ].filter((conversation)=>!named.has(conversation));
418
+ for (const conversation of named){
419
+ if (!replicated.has(conversation)) behind.add(conversation);
420
+ }
421
+ replicated = named;
422
+ handReplicated();
423
+ if (leaving.length > 0) await remove(leaving);
424
+ },
425
+ async catchUp (progress) {
426
+ for (const conversation of [
427
+ ...behind
428
+ ].sort()){
429
+ if (deps.closed()) return;
430
+ if (!replicated.has(conversation)) continue;
431
+ const failed = await readHistory(conversation);
432
+ if (failed?.kind === 'transport-uncertainty') progress.reachable = false;
433
+ }
434
+ if (behind.size > 0) progress.complete = false;
435
+ },
436
+ current () {
437
+ return behind.size === 0;
438
+ },
439
+ reconnected () {
440
+ for (const conversation of replicated)gap(conversation);
441
+ },
442
+ watch (conversation, options, deliver) {
443
+ const limit = limitOf(options);
444
+ const key = JSON.stringify([
445
+ conversation,
446
+ limit ?? null
447
+ ]);
448
+ const view = views.get(key) ?? {
449
+ conversation,
450
+ limit,
451
+ watchers: new Set()
452
+ };
453
+ views.set(key, view);
454
+ const watcher = {
455
+ notify: deliver,
456
+ ready: false
457
+ };
458
+ view.watchers.add(watcher);
459
+ handViewed();
460
+ void deps.durably(()=>Promise.resolve()).then(()=>{
461
+ if (deps.closed() || !view.watchers.has(watcher)) return;
462
+ watcher.ready = true;
463
+ watcher.notify(viewOf(conversation, limit));
464
+ }).catch(()=>{});
465
+ return ()=>{
466
+ if (!view.watchers.delete(watcher)) return;
467
+ if (view.watchers.size === 0) views.delete(key);
468
+ if (!viewed().includes(conversation)) {
469
+ growing.delete(conversation);
470
+ summaries.delete(conversation);
471
+ }
472
+ handViewed();
473
+ };
474
+ },
475
+ changed (set) {
476
+ for (const conversation of set.conversations)emit(conversation);
477
+ },
478
+ receive (event) {
479
+ if (deps.closed()) return;
480
+ const { conversation } = event;
481
+ if (event.kind === 'gap') {
482
+ if (replicated.has(conversation)) gap(conversation);
483
+ return;
484
+ }
485
+ if (event.kind === 'growing-text') {
486
+ if (!viewed().includes(conversation)) return;
487
+ growing.set(conversation, {
488
+ turn: event.turn,
489
+ text: event.text
490
+ });
491
+ emit(conversation);
492
+ return;
493
+ }
494
+ if (event.kind === 'session-summary') {
495
+ if (!viewed().includes(conversation)) return;
496
+ summaries.set(conversation, structuredClone(event.summary));
497
+ emit(conversation);
498
+ return;
499
+ }
500
+ const arriving = acceptedMessage(event.message);
501
+ if (arriving === null || !replicated.has(conversation)) return;
502
+ void keep(conversation, arriving).catch(()=>{});
503
+ },
504
+ messages () {
505
+ return [
506
+ ...messages
507
+ ].flatMap(([conversation, held])=>held.map(({ identity, text })=>({
508
+ conversation,
509
+ identity,
510
+ text
511
+ })));
512
+ },
513
+ message (conversation, identity) {
514
+ const held = messages.get(conversation)?.find((message)=>message.identity === identity);
515
+ return held === undefined ? null : {
516
+ conversation,
517
+ identity,
518
+ text: held.text
519
+ };
520
+ },
521
+ close () {
522
+ views.clear();
523
+ growing.clear();
524
+ summaries.clear();
525
+ }
526
+ };
527
+ }
528
+
529
+ //# sourceMappingURL=conversation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/conversation.ts"],"sourcesContent":["import type {\n AcceptedMessage,\n ConversationAction,\n ConversationCards,\n ConversationEvent,\n ConversationHistoryPage,\n ConversationMessage,\n ConversationStream,\n} from './adapter.js';\nimport { conversationChangeSet, type ChangeSet, type MessageChange } from './change-set.js';\nimport { declaredFile, type ChatDraftFile } from './file.js';\nimport type { CallResult } from './outcome.js';\nimport type { DocumentResult, QueryDocument } from './query.js';\nimport type { SearchedMessage } from './search.js';\nimport type { CycleProgress } from './status.js';\nimport type { ChatDraftRecord, HeldConversation, RuntimeStore } from './store.js';\n\nexport type ConversationEntry = {\n conversation: string;\n card: Required<QueryDocument>;\n agent: Required<QueryDocument> | null;\n};\n\nexport type GrowingText = { turn: string; text: string };\n\nexport type ChatDraft = {\n text: string;\n files: readonly ChatDraftFile[];\n};\n\nexport type ConversationOptions = { limit?: number };\n\nexport type ConversationView = {\n conversation: string;\n messages: readonly ConversationMessage[];\n growingText: GrowingText | null;\n summary: unknown;\n chatDraft: ChatDraft | null;\n};\n\nexport type ConversationSurface = {\n list(): Promise<readonly ConversationEntry[]>;\n read(conversation: string, options?: ConversationOptions): Promise<ConversationView>;\n create(input: unknown): Promise<CallResult>;\n send(conversation: string): Promise<CallResult>;\n answer(conversation: string, answer: unknown): Promise<CallResult>;\n interrupt(conversation: string): Promise<CallResult>;\n kill(conversation: string): Promise<CallResult>;\n cancel(conversation: string, turn: string): Promise<CallResult>;\n delete(conversation: string): Promise<CallResult>;\n};\n\nexport type ChatDraftSurface = {\n write(conversation: string, draft: ChatDraft): Promise<void>;\n discard(conversation: string): Promise<void>;\n};\n\nexport type ConversationDependencies = {\n cards(): ConversationCards | undefined;\n documents(locator: string): Promise<DocumentResult>;\n call(name: ConversationAction, input: unknown): Promise<CallResult>;\n durably<T>(work: (local: RuntimeStore) => Promise<T>): Promise<T>;\n stream(): ConversationStream | undefined;\n publish(set: ChangeSet): void;\n closed(): boolean;\n};\n\nexport type ConversationStore = {\n surface: ConversationSurface;\n chatDraft: ChatDraftSurface;\n hydrate(held: readonly HeldConversation[], drafts: readonly ChatDraftRecord[]): void;\n reconcile(): Promise<void>;\n catchUp(progress: CycleProgress): Promise<void>;\n current(): boolean;\n reconnected(): void;\n watch(\n conversation: string,\n options: ConversationOptions,\n deliver: (view: ConversationView) => void,\n ): () => void;\n changed(set: ChangeSet): void;\n receive(event: ConversationEvent): void;\n messages(): readonly SearchedMessage[];\n message(conversation: string, identity: string): SearchedMessage | null;\n close(): void;\n};\n\ntype Watcher = {\n notify: (view: ConversationView) => void;\n ready: boolean;\n};\n\ntype Sending = { draft: ChatDraftRecord };\n\ntype SharedView = {\n conversation: string;\n limit: number | undefined;\n watchers: Set<Watcher>;\n};\n\nfunction ordered(left: AcceptedMessage, right: AcceptedMessage): number {\n if (left.position !== right.position) return left.position < right.position ? -1 : 1;\n if (left.identity !== right.identity) return left.identity < right.identity ? -1 : 1;\n return 0;\n}\n\nfunction merged(\n held: readonly AcceptedMessage[],\n arriving: readonly AcceptedMessage[],\n): readonly AcceptedMessage[] {\n const byIdentity = new Map(held.map((message) => [message.identity, message]));\n for (const message of arriving) byIdentity.set(message.identity, message);\n return [...byIdentity.values()].sort(ordered);\n}\n\nfunction acceptedMessage(value: unknown): AcceptedMessage | null {\n if (typeof value !== 'object' || value === null) return null;\n const record = value as Partial<Record<keyof AcceptedMessage, unknown>>;\n if (\n typeof record.identity !== 'string' ||\n typeof record.turn !== 'string' ||\n typeof record.position !== 'string' ||\n typeof record.text !== 'string'\n ) {\n return null;\n }\n return {\n identity: record.identity,\n turn: record.turn,\n position: record.position,\n text: record.text,\n message: structuredClone(record.message),\n };\n}\n\nfunction historyPage(result: CallResult): ConversationHistoryPage | null {\n if (result.kind !== 'action') return null;\n const answer = result.result;\n if (typeof answer !== 'object' || answer === null) return null;\n const record = answer as { messages?: unknown; next?: unknown };\n if (!Array.isArray(record.messages)) return null;\n if (record.next !== undefined && typeof record.next !== 'string') return null;\n const messages: AcceptedMessage[] = [];\n for (const entry of record.messages) {\n const message = acceptedMessage(entry);\n if (message === null) return null;\n messages.push(message);\n }\n return { messages, ...(record.next === undefined ? {} : { next: record.next }) };\n}\n\nfunction turnOf(result: CallResult): string | null {\n if (result.kind !== 'action') return null;\n const answer = result.result;\n if (typeof answer !== 'object' || answer === null) return null;\n const record = answer as { turn?: unknown };\n return typeof record.turn === 'string' ? record.turn : null;\n}\n\nfunction limitOf(options: ConversationOptions): number | undefined {\n const { limit } = options;\n if (limit === undefined) return undefined;\n if (!Number.isInteger(limit) || limit < 0) {\n throw new Error(`conversation limit must be a non-negative integer, got ${String(limit)}`);\n }\n return limit;\n}\n\nexport function createConversationStore(deps: ConversationDependencies): ConversationStore {\n const messages = new Map<string, readonly AcceptedMessage[]>();\n const reads = new Map<string, string | null>();\n const drafts = new Map<string, ChatDraftRecord>();\n const sending = new Map<string, Sending>();\n const behind = new Set<string>();\n const gaps = new Map<string, number>();\n const growing = new Map<string, GrowingText>();\n const summaries = new Map<string, unknown>();\n const views = new Map<string, SharedView>();\n let replicated: ReadonlySet<string> = new Set();\n let handedReplicated: string | undefined;\n let handedViewed: string | undefined;\n\n function viewOf(conversation: string, limit: number | undefined): ConversationView {\n const held = messages.get(conversation) ?? [];\n const shown = limit === undefined ? held : held.slice(Math.max(0, held.length - limit));\n const draft = drafts.get(conversation);\n return {\n conversation,\n messages: shown.map(({ identity, turn, text, message }) => ({\n identity,\n turn,\n text,\n message: structuredClone(message),\n })),\n growingText: growing.get(conversation) ?? null,\n summary: structuredClone(summaries.get(conversation) ?? null),\n chatDraft:\n draft === undefined || draft.turn !== null || sending.get(conversation)?.draft === draft\n ? null\n : { text: draft.text, files: [...draft.files] },\n };\n }\n\n function emit(conversation: string) {\n if (deps.closed()) return;\n for (const view of views.values()) {\n if (view.conversation !== conversation) continue;\n const ready = [...view.watchers].filter((watcher) => watcher.ready);\n if (ready.length === 0) continue;\n const value = viewOf(conversation, view.limit);\n for (const watcher of ready) watcher.notify(value);\n }\n }\n\n function viewed(): readonly string[] {\n return [...new Set([...views.values()].map((view) => view.conversation))].sort();\n }\n\n function handViewed() {\n const stream = deps.stream();\n if (stream === undefined) return;\n const open = viewed();\n const named = JSON.stringify(open);\n if (named === handedViewed) return;\n handedViewed = named;\n stream.view(open);\n }\n\n function handReplicated() {\n const stream = deps.stream();\n if (stream === undefined) return;\n const held = [...replicated].sort();\n const named = JSON.stringify(held);\n if (named === handedReplicated) return;\n handedReplicated = named;\n stream.replicate(held);\n }\n\n async function documented(): Promise<readonly Required<QueryDocument>[]> {\n const declaration = deps.cards();\n if (declaration === undefined) return [];\n const { documents } = await deps.documents(declaration.locator);\n return documents.filter(\n (document): document is Required<QueryDocument> => typeof document.type === 'string',\n );\n }\n\n function carded(\n documents: readonly Required<QueryDocument>[],\n ): readonly { conversation: string; card: Required<QueryDocument> }[] {\n const declaration = deps.cards();\n if (declaration === undefined) return [];\n const cards: { conversation: string; card: Required<QueryDocument> }[] = [];\n for (const card of documents) {\n if (card.type !== declaration.type) continue;\n const identity = card.fields[declaration.identity];\n if (typeof identity === 'string') cards.push({ conversation: identity, card });\n }\n return cards;\n }\n\n async function remove(leaving: readonly string[]) {\n await deps.durably(async (local) => {\n await local.dropConversations(leaving);\n const removed: MessageChange[] = [];\n const changed: string[] = [];\n for (const conversation of leaving) {\n for (const message of messages.get(conversation) ?? []) {\n removed.push({ conversation, identity: message.identity });\n }\n if (\n messages.has(conversation) ||\n drafts.has(conversation) ||\n growing.has(conversation) ||\n summaries.has(conversation)\n ) {\n changed.push(conversation);\n }\n messages.delete(conversation);\n reads.delete(conversation);\n drafts.delete(conversation);\n behind.delete(conversation);\n growing.delete(conversation);\n summaries.delete(conversation);\n }\n if (changed.length > 0) deps.publish(conversationChangeSet(removed, changed));\n });\n }\n\n function gap(conversation: string) {\n gaps.set(conversation, (gaps.get(conversation) ?? 0) + 1);\n behind.add(conversation);\n }\n\n function keep(conversation: string, message: AcceptedMessage) {\n return deps.durably(async (local) => {\n if (!replicated.has(conversation)) return;\n const read = reads.get(conversation);\n const advances =\n read !== undefined &&\n !behind.has(conversation) &&\n (read === null || message.position > read);\n const sealed = drafts.get(conversation)?.turn === message.turn;\n await local.keepMessages({\n conversation,\n messages: [message],\n ...(advances ? { read: message.position } : {}),\n sealed,\n });\n messages.set(conversation, merged(messages.get(conversation) ?? [], [message]));\n if (advances) reads.set(conversation, message.position);\n if (sealed) drafts.delete(conversation);\n if (growing.get(conversation)?.turn === message.turn) growing.delete(conversation);\n deps.publish(\n conversationChangeSet([{ conversation, identity: message.identity }], [conversation]),\n );\n });\n }\n\n async function readHistory(conversation: string): Promise<CallResult | null> {\n const generation = gaps.get(conversation) ?? 0;\n const from = reads.get(conversation);\n const arriving: AcceptedMessage[] = [];\n let after = from ?? undefined;\n for (;;) {\n const result = await deps.call('conversation.history', {\n conversation,\n ...(after === undefined ? {} : { after }),\n });\n const page = historyPage(result);\n if (page === null) return result;\n arriving.push(...page.messages);\n if (page.next === undefined) break;\n after = page.next;\n }\n await deps.durably(async (local) => {\n if (!replicated.has(conversation)) return;\n const newest = arriving.reduce<string | null>(\n (top, message) => (top === null || message.position > top ? message.position : top),\n from ?? null,\n );\n const turn = drafts.get(conversation)?.turn;\n const sealed = arriving.some((message) => message.turn === turn);\n await local.keepMessages({ conversation, messages: arriving, read: newest, sealed });\n messages.set(conversation, merged(messages.get(conversation) ?? [], arriving));\n reads.set(conversation, newest);\n if (sealed) drafts.delete(conversation);\n const growingTurn = growing.get(conversation)?.turn;\n if (arriving.some((message) => message.turn === growingTurn)) growing.delete(conversation);\n if ((gaps.get(conversation) ?? 0) === generation) behind.delete(conversation);\n if (arriving.length > 0 || sealed) {\n deps.publish(\n conversationChangeSet(\n arriving.map((message) => ({ conversation, identity: message.identity })),\n [conversation],\n ),\n );\n }\n });\n return null;\n }\n\n function withDraft(\n conversation: string,\n next: (draft: ChatDraftRecord | undefined) => ChatDraftRecord | null | undefined,\n ): Promise<void> {\n return deps.durably(async (local) => {\n const following = next(drafts.get(conversation));\n if (following === undefined) return;\n if (following === null) {\n await local.dropChatDraft(conversation);\n drafts.delete(conversation);\n } else {\n await local.keepChatDraft(following);\n drafts.set(conversation, following);\n }\n deps.publish(conversationChangeSet([], [conversation]));\n });\n }\n\n function invoke(\n name: ConversationAction,\n conversation: string,\n extra: Readonly<Record<string, unknown>> = {},\n ): Promise<CallResult> {\n return deps.call(name, { conversation, ...extra });\n }\n\n const surface: ConversationSurface = {\n async list() {\n const declaration = deps.cards();\n if (declaration === undefined) return [];\n const documents = await documented();\n const entries: ConversationEntry[] = carded(documents).map(({ conversation, card }) => ({\n conversation,\n card,\n agent:\n documents.find((document) =>\n document.backlinks.some(\n (backlink) => backlink.path === card.path && backlink.field === declaration.agent,\n ),\n ) ?? null,\n }));\n entries.sort((left, right) => (left.conversation < right.conversation ? -1 : 1));\n return entries;\n },\n async read(conversation: string, options: ConversationOptions = {}) {\n const limit = limitOf(options);\n return deps.durably(() => Promise.resolve(viewOf(conversation, limit)));\n },\n create(input: unknown) {\n return deps.call('conversation.create', input);\n },\n async send(conversation: string) {\n const draft = drafts.get(conversation);\n const pending: Sending | undefined = draft === undefined ? undefined : { draft };\n if (pending !== undefined) {\n sending.set(conversation, pending);\n deps.publish(conversationChangeSet([], [conversation]));\n }\n try {\n const files = await Promise.all(\n (draft?.files ?? []).map(async (file) => ({\n ...(await declaredFile(file)),\n blob: file.blob,\n })),\n );\n const result = await invoke('conversation.send', conversation, {\n text: draft?.text ?? '',\n files,\n });\n const turn = turnOf(result);\n if (turn === null || draft === undefined) return result;\n await withDraft(conversation, (current) => {\n if (current !== draft) return undefined;\n const sealed = (messages.get(conversation) ?? []).some(\n (message) => message.turn === turn,\n );\n return sealed ? null : { ...draft, turn };\n });\n return result;\n } finally {\n if (pending !== undefined && sending.get(conversation) === pending) {\n sending.delete(conversation);\n if (drafts.get(conversation) === draft) {\n deps.publish(conversationChangeSet([], [conversation]));\n }\n }\n }\n },\n answer(conversation: string, answer: unknown) {\n return invoke('conversation.answer', conversation, { answer });\n },\n interrupt(conversation: string) {\n return invoke('conversation.interrupt', conversation);\n },\n kill(conversation: string) {\n return invoke('conversation.kill', conversation);\n },\n async cancel(conversation: string, turn: string) {\n const result = await invoke('conversation.cancel', conversation, { turn });\n if (result.kind !== 'action') return result;\n await withDraft(conversation, (current) =>\n current === undefined || current.turn !== turn ? undefined : { ...current, turn: null },\n );\n return result;\n },\n delete(conversation: string) {\n return invoke('conversation.delete', conversation);\n },\n };\n\n const chatDraft: ChatDraftSurface = {\n write(conversation: string, draft: ChatDraft) {\n return withDraft(conversation, () => ({\n conversation,\n text: draft.text,\n files: [...draft.files],\n turn: null,\n }));\n },\n discard(conversation: string) {\n return withDraft(conversation, (current) => (current === undefined ? undefined : null));\n },\n };\n\n return {\n surface,\n chatDraft,\n hydrate(held, stored) {\n messages.clear();\n reads.clear();\n for (const entry of held) {\n messages.set(entry.conversation, [...entry.messages].sort(ordered));\n if (entry.read !== undefined) reads.set(entry.conversation, entry.read);\n }\n drafts.clear();\n for (const record of stored) drafts.set(record.conversation, record);\n },\n async reconcile() {\n const named = new Set(carded(await documented()).map((entry) => entry.conversation));\n const leaving = [\n ...new Set([...replicated, ...messages.keys(), ...reads.keys(), ...drafts.keys()]),\n ].filter((conversation) => !named.has(conversation));\n for (const conversation of named) {\n if (!replicated.has(conversation)) behind.add(conversation);\n }\n replicated = named;\n handReplicated();\n if (leaving.length > 0) await remove(leaving);\n },\n async catchUp(progress) {\n for (const conversation of [...behind].sort()) {\n if (deps.closed()) return;\n if (!replicated.has(conversation)) continue;\n const failed = await readHistory(conversation);\n if (failed?.kind === 'transport-uncertainty') progress.reachable = false;\n }\n if (behind.size > 0) progress.complete = false;\n },\n current() {\n return behind.size === 0;\n },\n reconnected() {\n for (const conversation of replicated) gap(conversation);\n },\n watch(conversation, options, deliver) {\n const limit = limitOf(options);\n const key = JSON.stringify([conversation, limit ?? null]);\n const view = views.get(key) ?? { conversation, limit, watchers: new Set<Watcher>() };\n views.set(key, view);\n const watcher: Watcher = { notify: deliver, ready: false };\n view.watchers.add(watcher);\n handViewed();\n void deps\n .durably(() => Promise.resolve())\n .then(() => {\n if (deps.closed() || !view.watchers.has(watcher)) return;\n watcher.ready = true;\n watcher.notify(viewOf(conversation, limit));\n })\n .catch(() => {});\n return () => {\n if (!view.watchers.delete(watcher)) return;\n if (view.watchers.size === 0) views.delete(key);\n if (!viewed().includes(conversation)) {\n growing.delete(conversation);\n summaries.delete(conversation);\n }\n handViewed();\n };\n },\n changed(set) {\n for (const conversation of set.conversations) emit(conversation);\n },\n receive(event) {\n if (deps.closed()) return;\n const { conversation } = event;\n if (event.kind === 'gap') {\n if (replicated.has(conversation)) gap(conversation);\n return;\n }\n if (event.kind === 'growing-text') {\n if (!viewed().includes(conversation)) return;\n growing.set(conversation, { turn: event.turn, text: event.text });\n emit(conversation);\n return;\n }\n if (event.kind === 'session-summary') {\n if (!viewed().includes(conversation)) return;\n summaries.set(conversation, structuredClone(event.summary));\n emit(conversation);\n return;\n }\n const arriving = acceptedMessage(event.message);\n if (arriving === null || !replicated.has(conversation)) return;\n void keep(conversation, arriving).catch(() => {});\n },\n messages() {\n return [...messages].flatMap(([conversation, held]) =>\n held.map(({ identity, text }) => ({ conversation, identity, text })),\n );\n },\n message(conversation, identity) {\n const held = messages.get(conversation)?.find((message) => message.identity === identity);\n return held === undefined ? null : { conversation, identity, text: held.text };\n },\n close() {\n views.clear();\n growing.clear();\n summaries.clear();\n },\n };\n}\n"],"names":["conversationChangeSet","declaredFile","ordered","left","right","position","identity","merged","held","arriving","byIdentity","Map","map","message","set","values","sort","acceptedMessage","value","record","turn","text","structuredClone","historyPage","result","kind","answer","Array","isArray","messages","next","undefined","entry","push","turnOf","limitOf","options","limit","Number","isInteger","Error","String","createConversationStore","deps","reads","drafts","sending","behind","Set","gaps","growing","summaries","views","replicated","handedReplicated","handedViewed","viewOf","conversation","get","shown","slice","Math","max","length","draft","growingText","summary","chatDraft","files","emit","closed","view","ready","watchers","filter","watcher","notify","viewed","handViewed","stream","open","named","JSON","stringify","handReplicated","replicate","documented","declaration","cards","documents","locator","document","type","carded","card","fields","remove","leaving","durably","local","dropConversations","removed","changed","has","delete","publish","gap","add","keep","read","advances","sealed","keepMessages","readHistory","generation","from","after","call","page","newest","reduce","top","some","growingTurn","withDraft","following","dropChatDraft","keepChatDraft","invoke","name","extra","surface","list","entries","agent","find","backlinks","backlink","path","field","Promise","resolve","create","input","send","pending","all","file","blob","current","interrupt","kill","cancel","write","discard","hydrate","stored","clear","reconcile","keys","catchUp","progress","failed","reachable","size","complete","reconnected","watch","deliver","key","then","catch","includes","conversations","receive","event","flatMap","close"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type RuntimeShell = {
2
+ persistentStorage: boolean;
3
+ generation: string | null;
4
+ keepGeneration(value: string): void | Promise<void>;
5
+ dropGeneration(): void | Promise<void>;
6
+ };
7
+ export declare function detectStorageLoss(stored: string | null, reported: string | null): string | null;
8
+ export declare function nextGeneration(stored: string | null, reported: string | null): string;
9
+ //# sourceMappingURL=durability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"durability.d.ts","sourceRoot":"","sources":["../src/durability.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,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;CACxC,CAAC;AAEF,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"}
@@ -0,0 +1,11 @@
1
+ const STORAGE_LOSS_STATEMENT = 'Unsynchronized Room Drafts and Pending Changes were lost.';
2
+ export function detectStorageLoss(stored, reported) {
3
+ if (reported === null || reported === stored) return null;
4
+ return STORAGE_LOSS_STATEMENT;
5
+ }
6
+ export function nextGeneration(stored, reported) {
7
+ if (stored !== null && (reported === null || reported === stored)) return stored;
8
+ return crypto.randomUUID();
9
+ }
10
+
11
+ //# sourceMappingURL=durability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/workspace/packages/mdruntime/src/durability.ts"],"sourcesContent":["const STORAGE_LOSS_STATEMENT = 'Unsynchronized Room Drafts and Pending Changes were lost.';\n\nexport type RuntimeShell = {\n persistentStorage: boolean;\n generation: string | null;\n keepGeneration(value: string): void | Promise<void>;\n dropGeneration(): void | Promise<void>;\n};\n\nexport function detectStorageLoss(stored: string | null, reported: string | null): string | null {\n if (reported === null || reported === stored) return null;\n return STORAGE_LOSS_STATEMENT;\n}\n\nexport function nextGeneration(stored: string | null, reported: string | null): string {\n if (stored !== null && (reported === null || reported === stored)) return stored;\n return crypto.randomUUID();\n}\n"],"names":["STORAGE_LOSS_STATEMENT","detectStorageLoss","stored","reported","nextGeneration","crypto","randomUUID"],"mappings":"AAAA,MAAMA,yBAAyB;AAS/B,OAAO,SAASC,kBAAkBC,MAAqB,EAAEC,QAAuB;IAC9E,IAAIA,aAAa,QAAQA,aAAaD,QAAQ,OAAO;IACrD,OAAOF;AACT;AAEA,OAAO,SAASI,eAAeF,MAAqB,EAAEC,QAAuB;IAC3E,IAAID,WAAW,QAASC,CAAAA,aAAa,QAAQA,aAAaD,MAAK,GAAI,OAAOA;IAC1E,OAAOG,OAAOC,UAAU;AAC1B"}
package/dist/file.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ export type ChatDraftFile = {
2
+ name: string;
3
+ blob: Blob;
4
+ };
5
+ export type FileDeclaration = {
6
+ name: string;
7
+ mediaType: string;
8
+ byteLength: number;
9
+ contentHash: string;
10
+ width?: number;
11
+ height?: number;
12
+ };
13
+ export type Extent = {
14
+ width: number;
15
+ height: number;
16
+ };
17
+ export declare function extentOf(bytes: Uint8Array): Extent | null;
18
+ export declare function hexDigest(digest: ArrayBuffer): string;
19
+ export declare function declaredFile(file: ChatDraftFile): Promise<FileDeclaration>;
20
+ //# sourceMappingURL=file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../src/file.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AA2GvD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAQzD;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAErD;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAUhF"}