@agentshouse/mdruntime 0.1.0-c1cc928d1d256 → 0.1.0-c1ffd2bc60355

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 (257) hide show
  1. package/AGENTS.md +296 -232
  2. package/README.md +21 -10
  3. package/dist/adapter.d.ts +123 -32
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/attached-model.d.ts +4 -1
  6. package/dist/attached-model.d.ts.map +1 -1
  7. package/dist/attached-model.js +13 -3
  8. package/dist/attempt.d.ts +16 -0
  9. package/dist/attempt.d.ts.map +1 -0
  10. package/dist/attempt.js +70 -0
  11. package/dist/binary.d.ts +18 -0
  12. package/dist/binary.d.ts.map +1 -0
  13. package/dist/binary.js +8 -0
  14. package/dist/bootstrap.d.ts +36 -5
  15. package/dist/bootstrap.d.ts.map +1 -1
  16. package/dist/bootstrap.js +187 -45
  17. package/dist/chain.d.ts +11 -0
  18. package/dist/chain.d.ts.map +1 -0
  19. package/dist/chain.js +64 -0
  20. package/dist/change-set.d.ts +9 -14
  21. package/dist/change-set.d.ts.map +1 -1
  22. package/dist/change-set.js +11 -56
  23. package/dist/change.d.ts +45 -0
  24. package/dist/change.d.ts.map +1 -1
  25. package/dist/change.js +34 -0
  26. package/dist/chat/acts.d.ts +33 -0
  27. package/dist/chat/acts.d.ts.map +1 -0
  28. package/dist/chat/acts.js +36 -0
  29. package/dist/chat/context.d.ts +3 -0
  30. package/dist/chat/context.d.ts.map +1 -0
  31. package/dist/chat/context.js +10 -0
  32. package/dist/chat/earlier.d.ts +10 -0
  33. package/dist/chat/earlier.d.ts.map +1 -0
  34. package/dist/chat/earlier.js +54 -0
  35. package/dist/chat/house.d.ts +25 -0
  36. package/dist/chat/house.d.ts.map +1 -0
  37. package/dist/chat/house.js +38 -0
  38. package/dist/chat/input.d.ts +11 -0
  39. package/dist/chat/input.d.ts.map +1 -0
  40. package/dist/chat/input.js +92 -0
  41. package/dist/chat/kit.d.ts +61 -0
  42. package/dist/chat/kit.d.ts.map +1 -0
  43. package/dist/chat/kit.js +123 -0
  44. package/dist/chat/lasting.d.ts +6 -0
  45. package/dist/chat/lasting.d.ts.map +1 -0
  46. package/dist/chat/lasting.js +19 -0
  47. package/dist/chat/list.d.ts +28 -0
  48. package/dist/chat/list.d.ts.map +1 -0
  49. package/dist/chat/list.js +103 -0
  50. package/dist/chat/markdown.d.ts +20 -0
  51. package/dist/chat/markdown.d.ts.map +1 -0
  52. package/dist/chat/markdown.js +229 -0
  53. package/dist/chat/message.d.ts +7 -0
  54. package/dist/chat/message.d.ts.map +1 -0
  55. package/dist/chat/message.js +254 -0
  56. package/dist/chat/messages.d.ts +35 -0
  57. package/dist/chat/messages.d.ts.map +1 -0
  58. package/dist/chat/messages.js +210 -0
  59. package/dist/chat/name.d.ts +7 -0
  60. package/dist/chat/name.d.ts.map +1 -0
  61. package/dist/chat/name.js +37 -0
  62. package/dist/chat/opened.d.ts +12 -0
  63. package/dist/chat/opened.d.ts.map +1 -0
  64. package/dist/chat/opened.js +19 -0
  65. package/dist/chat/overlay.d.ts +32 -0
  66. package/dist/chat/overlay.d.ts.map +1 -0
  67. package/dist/chat/overlay.js +103 -0
  68. package/dist/chat/parts.d.ts +58 -0
  69. package/dist/chat/parts.d.ts.map +1 -0
  70. package/dist/chat/parts.js +120 -0
  71. package/dist/chat/pieces.d.ts +62 -0
  72. package/dist/chat/pieces.d.ts.map +1 -0
  73. package/dist/chat/pieces.js +1110 -0
  74. package/dist/chat/process.d.ts +20 -0
  75. package/dist/chat/process.d.ts.map +1 -0
  76. package/dist/chat/process.js +32 -0
  77. package/dist/chat/provider.d.ts +70 -0
  78. package/dist/chat/provider.d.ts.map +1 -0
  79. package/dist/chat/provider.js +635 -0
  80. package/dist/chat/question.d.ts +9 -0
  81. package/dist/chat/question.d.ts.map +1 -0
  82. package/dist/chat/question.js +69 -0
  83. package/dist/chat/questions.d.ts +31 -0
  84. package/dist/chat/questions.d.ts.map +1 -0
  85. package/dist/chat/questions.js +111 -0
  86. package/dist/chat/read.d.ts +5 -0
  87. package/dist/chat/read.d.ts.map +1 -0
  88. package/dist/chat/read.js +13 -0
  89. package/dist/chat/ready.d.ts +37 -0
  90. package/dist/chat/ready.d.ts.map +1 -0
  91. package/dist/chat/ready.js +93 -0
  92. package/dist/chat/room-file.d.ts +8 -0
  93. package/dist/chat/room-file.d.ts.map +1 -0
  94. package/dist/chat/room-file.js +72 -0
  95. package/dist/chat/steady.d.ts +3 -0
  96. package/dist/chat/steady.d.ts.map +1 -0
  97. package/dist/chat/steady.js +26 -0
  98. package/dist/chat/style.d.ts +4 -0
  99. package/dist/chat/style.d.ts.map +1 -0
  100. package/dist/chat/style.js +307 -0
  101. package/dist/chat.d.ts +15 -0
  102. package/dist/chat.d.ts.map +1 -0
  103. package/dist/chat.js +8 -0
  104. package/dist/client.d.ts +33 -14
  105. package/dist/client.d.ts.map +1 -1
  106. package/dist/client.js +74 -19
  107. package/dist/collection.d.ts +9 -13
  108. package/dist/collection.d.ts.map +1 -1
  109. package/dist/collection.js +47 -56
  110. package/dist/compile.d.ts +16 -0
  111. package/dist/compile.d.ts.map +1 -0
  112. package/dist/compile.js +721 -0
  113. package/dist/connection.d.ts +57 -19
  114. package/dist/connection.d.ts.map +1 -1
  115. package/dist/connection.js +3561 -663
  116. package/dist/conversation.d.ts +41 -12
  117. package/dist/conversation.d.ts.map +1 -1
  118. package/dist/conversation.js +585 -180
  119. package/dist/digest.d.ts +7 -0
  120. package/dist/digest.d.ts.map +1 -0
  121. package/dist/digest.js +113 -0
  122. package/dist/durability.d.ts +5 -1
  123. package/dist/durability.d.ts.map +1 -1
  124. package/dist/durability.js +5 -0
  125. package/dist/entry.d.ts +19 -0
  126. package/dist/entry.d.ts.map +1 -0
  127. package/dist/entry.js +151 -0
  128. package/dist/expectation.d.ts +21 -0
  129. package/dist/expectation.d.ts.map +1 -0
  130. package/dist/expectation.js +70 -0
  131. package/dist/failure.d.ts +13 -0
  132. package/dist/failure.d.ts.map +1 -0
  133. package/dist/failure.js +19 -0
  134. package/dist/fence.d.ts +6 -0
  135. package/dist/fence.d.ts.map +1 -0
  136. package/dist/fence.js +10 -0
  137. package/dist/file.d.ts +2 -10
  138. package/dist/file.d.ts.map +1 -1
  139. package/dist/file.js +3 -120
  140. package/dist/fulltext.d.ts +27 -0
  141. package/dist/fulltext.d.ts.map +1 -0
  142. package/dist/fulltext.js +368 -0
  143. package/dist/host.d.ts +15 -3
  144. package/dist/host.d.ts.map +1 -1
  145. package/dist/host.js +132 -22
  146. package/dist/identity.d.ts +4 -0
  147. package/dist/identity.d.ts.map +1 -1
  148. package/dist/identity.js +16 -1
  149. package/dist/index.d.ts +20 -9
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/index.js +8 -0
  152. package/dist/live.d.ts +22 -0
  153. package/dist/live.d.ts.map +1 -0
  154. package/dist/live.js +123 -0
  155. package/dist/memory.d.ts +11 -4
  156. package/dist/memory.d.ts.map +1 -1
  157. package/dist/memory.js +92 -27
  158. package/dist/messages.d.ts +28 -0
  159. package/dist/messages.d.ts.map +1 -0
  160. package/dist/messages.js +90 -0
  161. package/dist/model.d.ts +7 -4
  162. package/dist/model.d.ts.map +1 -1
  163. package/dist/model.js +10 -1
  164. package/dist/name.d.ts +4 -0
  165. package/dist/name.d.ts.map +1 -0
  166. package/dist/name.js +122 -0
  167. package/dist/observation.d.ts +19 -2
  168. package/dist/observation.d.ts.map +1 -1
  169. package/dist/observation.js +113 -12
  170. package/dist/open.d.ts +2 -0
  171. package/dist/open.d.ts.map +1 -0
  172. package/dist/open.js +1 -0
  173. package/dist/opened.d.ts +22 -0
  174. package/dist/opened.d.ts.map +1 -0
  175. package/dist/opened.js +107 -0
  176. package/dist/outcome.d.ts +62 -3
  177. package/dist/outcome.d.ts.map +1 -1
  178. package/dist/outcome.js +67 -1
  179. package/dist/overlay.d.ts +15 -5
  180. package/dist/overlay.d.ts.map +1 -1
  181. package/dist/overlay.js +136 -180
  182. package/dist/query.d.ts +64 -4
  183. package/dist/query.d.ts.map +1 -1
  184. package/dist/query.js +51 -7
  185. package/dist/reach.d.ts +11 -4
  186. package/dist/reach.d.ts.map +1 -1
  187. package/dist/reach.js +203 -59
  188. package/dist/react.d.ts +12 -8
  189. package/dist/react.d.ts.map +1 -1
  190. package/dist/react.js +8 -17
  191. package/dist/readiness.d.ts +64 -0
  192. package/dist/readiness.d.ts.map +1 -0
  193. package/dist/readiness.js +33 -0
  194. package/dist/reads.d.ts +11 -0
  195. package/dist/reads.d.ts.map +1 -0
  196. package/dist/reads.js +100 -0
  197. package/dist/recovery.d.ts +25 -0
  198. package/dist/recovery.d.ts.map +1 -0
  199. package/dist/recovery.js +198 -0
  200. package/dist/refresh.d.ts +19 -8
  201. package/dist/refresh.d.ts.map +1 -1
  202. package/dist/refresh.js +127 -55
  203. package/dist/replica.d.ts +60 -33
  204. package/dist/replica.d.ts.map +1 -1
  205. package/dist/replica.js +318 -152
  206. package/dist/room-draft.d.ts +41 -9
  207. package/dist/room-draft.d.ts.map +1 -1
  208. package/dist/room-draft.js +186 -37
  209. package/dist/rows.d.ts +30 -35
  210. package/dist/rows.d.ts.map +1 -1
  211. package/dist/rows.js +116 -67
  212. package/dist/save.d.ts +71 -4
  213. package/dist/save.d.ts.map +1 -1
  214. package/dist/save.js +815 -146
  215. package/dist/search.d.ts +41 -29
  216. package/dist/search.d.ts.map +1 -1
  217. package/dist/search.js +37 -105
  218. package/dist/seed.d.ts +16 -0
  219. package/dist/seed.d.ts.map +1 -0
  220. package/dist/seed.js +75 -0
  221. package/dist/shared.d.ts +16 -0
  222. package/dist/shared.d.ts.map +1 -0
  223. package/dist/shared.js +431 -0
  224. package/dist/status.d.ts +6 -2
  225. package/dist/status.d.ts.map +1 -1
  226. package/dist/status.js +0 -8
  227. package/dist/store.d.ts +124 -61
  228. package/dist/store.d.ts.map +1 -1
  229. package/dist/store.js +358 -354
  230. package/dist/stored.d.ts +145 -0
  231. package/dist/stored.d.ts.map +1 -0
  232. package/dist/stored.js +567 -0
  233. package/dist/tables.d.ts +354 -0
  234. package/dist/tables.d.ts.map +1 -0
  235. package/dist/tables.js +624 -0
  236. package/dist/turn.d.ts +9 -0
  237. package/dist/turn.d.ts.map +1 -0
  238. package/dist/turn.js +75 -0
  239. package/dist/validation.d.ts +30 -0
  240. package/dist/validation.d.ts.map +1 -0
  241. package/dist/validation.js +162 -0
  242. package/dist/windows.d.ts +22 -0
  243. package/dist/windows.d.ts.map +1 -0
  244. package/dist/windows.js +89 -0
  245. package/dist/wire.d.ts +168 -33
  246. package/dist/wire.d.ts.map +1 -1
  247. package/dist/wire.js +67 -31
  248. package/dist/words.d.ts +19 -0
  249. package/dist/words.d.ts.map +1 -0
  250. package/dist/words.js +150 -0
  251. package/package.json +34 -16
  252. package/dist/attachment.d.ts +0 -3
  253. package/dist/attachment.d.ts.map +0 -1
  254. package/dist/attachment.js +0 -8
  255. package/dist/read-side.d.ts +0 -18
  256. package/dist/read-side.d.ts.map +0 -1
  257. package/dist/read-side.js +0 -433
package/dist/query.js CHANGED
@@ -1,16 +1,29 @@
1
1
  import { pointerFacts, } from '@agentshouse/mdmodel';
2
2
  import { referenceField } from './model.js';
3
3
  import { normalize } from './paths.js';
4
+ import { decodedCursor } from './windows.js';
4
5
  export class QueryError extends Error {
6
+ code;
7
+ retryable = false;
5
8
  constructor(code, at, problem) {
6
9
  super(`${code} at ${at}: ${problem}`);
10
+ this.code = code;
7
11
  }
8
12
  }
9
13
  const RANGE = ['$gt', '$gte', '$lt', '$lte'];
10
14
  const SINGLE = ['$eq', '$ne', '$in', '$nin', '$all', '$size', '$exists'];
11
- const FILTER = ['rooms', 'types', 'where', 'pathPrefix', 'hop', 'backlinks'];
15
+ const FILTER = ['rooms', 'types', 'where', 'pathPrefix', 'folder', 'paths', 'hop', 'backlinks'];
12
16
  const RELATED = ['types', 'where', 'pathPrefix', 'field'];
13
- const PARTS = ['fields', 'sections', 'preamble', 'markdown', 'backlinks', 'change'];
17
+ const PARTS = [
18
+ 'fields',
19
+ 'sections',
20
+ 'preamble',
21
+ 'markdown',
22
+ 'backlinks',
23
+ 'change',
24
+ 'fileId',
25
+ 'revision',
26
+ ];
14
27
  const ORDER = ['by', 'direction', 'nulls', 'stringSort', 'locale', 'localeOptions'];
15
28
  const CALENDAR_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
16
29
  const STRAY_ESCAPE = /~(?![01])/u;
@@ -57,6 +70,13 @@ function names(input, at) {
57
70
  invalid(at, 'expects a list of names');
58
71
  return [...new Set(listed)].sort();
59
72
  }
73
+ function pathsOf(input) {
74
+ const listed = list(input, 'paths');
75
+ if (listed.some((item) => typeof item !== 'string' || item === '' || normalize(item) !== item)) {
76
+ invalid('paths', 'expects a list of Paths');
77
+ }
78
+ return [...new Set(listed)].sort();
79
+ }
60
80
  function directory(input, at) {
61
81
  if (typeof input !== 'string' || normalize(input) !== input) {
62
82
  invalid(at, 'expects a normalized directory');
@@ -276,15 +296,16 @@ function backlinksOf(facts, rooms, input) {
276
296
  return { types, where, pathPrefix, field };
277
297
  }
278
298
  function keyPlan(typed, input, at, path) {
279
- if (input === 'room' || input === 'type' || (path && input === 'path'))
299
+ if (input === 'room' || input === 'type' || input === 'folder' || (path && input === 'path')) {
280
300
  return { of: input };
301
+ }
281
302
  if (plain(input) && Object.hasOwn(input, 'field') && Object.keys(input).length === 1) {
282
303
  if (specs(typed, input.field, place(at, 'field')).some(several)) {
283
304
  invalid(place(at, 'field'), 'a path that can hold several values');
284
305
  }
285
306
  return { of: 'field', field: input.field };
286
307
  }
287
- return invalid(at, path ? 'expects room, path, type or a field' : 'expects room, type or a field');
308
+ return invalid(at, path ? 'expects room, path, type, folder or a field' : 'expects room, type, folder or a field');
288
309
  }
289
310
  function direction(input, at) {
290
311
  if (input === undefined)
@@ -346,7 +367,7 @@ function parts(typed, input, at, fields) {
346
367
  });
347
368
  return named;
348
369
  }
349
- function flag(input, at) {
370
+ export function flag(input, at) {
350
371
  if (input === undefined)
351
372
  return false;
352
373
  if (input !== true)
@@ -374,6 +395,8 @@ function documentShape(typed, input) {
374
395
  markdown: true,
375
396
  backlinks: true,
376
397
  change: true,
398
+ fileId: true,
399
+ revision: true,
377
400
  orderBy,
378
401
  };
379
402
  }
@@ -388,6 +411,8 @@ function documentShape(typed, input) {
388
411
  markdown: flag(select.markdown, 'select.markdown'),
389
412
  backlinks: flag(select.backlinks, 'select.backlinks'),
390
413
  change: flag(select.change, 'select.change'),
414
+ fileId: flag(select.fileId, 'select.fileId'),
415
+ revision: flag(select.revision, 'select.revision'),
391
416
  orderBy,
392
417
  };
393
418
  }
@@ -418,20 +443,36 @@ export function planOf(input, facts, reach = null) {
418
443
  invalid('select', 'a grouped query selects nothing');
419
444
  if (!grouped && input.select === undefined)
420
445
  invalid('select', 'a Document query must select');
421
- known(input, [...FILTER, 'orderBy', 'limit', grouped ? 'groupBy' : 'select'], '');
446
+ known(input, [...FILTER, 'orderBy', 'limit', 'after', 'total', grouped ? 'groupBy' : 'select'], '');
422
447
  const limit = limitOf(input.limit);
423
448
  const rooms = input.rooms === undefined ? null : names(input.rooms, 'rooms');
424
449
  const { typed, ...root } = scope(facts, rooms, input, '');
450
+ const shape = grouped ? groupShape(typed, input) : documentShape(typed, input);
425
451
  return {
452
+ key: queryKey(input),
426
453
  rooms,
427
454
  reach,
455
+ locked: [],
428
456
  root,
457
+ folder: input.folder === undefined ? null : directory(input.folder, 'folder'),
458
+ paths: input.paths === undefined ? null : pathsOf(input.paths),
429
459
  hop: input.hop === undefined ? null : hopOf(facts, rooms, typed, input.hop),
430
460
  backlinks: input.backlinks === undefined ? null : backlinksOf(facts, rooms, input.backlinks),
431
- shape: grouped ? groupShape(typed, input) : documentShape(typed, input),
461
+ shape,
432
462
  limit,
463
+ after: continuationOf(input.after, shape.orderBy.length + 1),
464
+ total: flag(input.total, 'total'),
433
465
  };
434
466
  }
467
+ function continuationOf(input, arity) {
468
+ if (input === undefined)
469
+ return null;
470
+ const values = typeof input === 'string' ? decodedCursor(input) : null;
471
+ if (values === null || (values.length !== 0 && values.length !== arity)) {
472
+ invalid('after', 'expects the next an earlier result of this query returned');
473
+ }
474
+ return { text: input, values: values.length === 0 ? null : values };
475
+ }
435
476
  export function limitOf(input) {
436
477
  if (input === undefined)
437
478
  return null;
@@ -446,6 +487,9 @@ export function filterOf(input, facts, reach = null) {
446
487
  known(input, FILTER, '');
447
488
  return planOf({ ...input, select: {} }, facts, reach);
448
489
  }
490
+ export function queryKey(query) {
491
+ return canonical(query);
492
+ }
449
493
  function canonical(value) {
450
494
  if (Array.isArray(value))
451
495
  return `[${value.map(canonical).join(',')}]`;
package/dist/reach.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- import type { MdRuntime, RuntimeTopic } from './connection.js';
1
+ import type { MdRuntime, ReadinessPort, RuntimeTopic } from './connection.js';
2
2
  import type { Plan, PlanReach, QueryResult } from './query.js';
3
- import type { SearchResult } from './search.js';
3
+ import type { Readiness } from './readiness.js';
4
+ import { type SearchResult } from './search.js';
4
5
  export type ReachedDocument = {
5
6
  readonly room: string;
6
7
  readonly path: string;
@@ -18,12 +19,18 @@ export type RuntimeView = {
18
19
  };
19
20
  export type NarrowedView = RuntimeView & {
20
21
  narrow(reach: PortReach | null): void;
22
+ facts(port: ReadinessPort): void;
21
23
  };
22
24
  export type Reachable = RuntimeView & {
23
25
  plan(input: unknown, reach: PortReach | null): Plan;
24
26
  query(plan: Plan): Promise<QueryResult>;
25
27
  watchPlan(plan: Plan, deliver: (message: unknown) => void): () => void;
26
- search(input: unknown, reach: PortReach | null): Promise<SearchResult>;
28
+ search(input: unknown, reach: PortReach | null, locked: readonly string[]): Promise<SearchResult>;
29
+ watchReadiness(port: ReadinessPort, reach: PortReach | null, deliver: (readiness: Readiness) => void): () => void;
30
+ locked(room: string): boolean;
31
+ lockedRooms(): readonly string[];
32
+ watchLocks(notify: () => void): () => void;
33
+ located(room: string, path: string, destination: string): ReachedDocument | null;
27
34
  };
28
35
  export declare function holds(reach: PortReach | null, room: string): boolean;
29
36
  export declare function governs(reach: PortReach | null, room: {
@@ -36,5 +43,5 @@ export declare function governs(reach: PortReach | null, room: {
36
43
  readonly selection: boolean;
37
44
  };
38
45
  export declare function planReach(reach: PortReach | null): PlanReach | null;
39
- export declare function narrowed(runtime: Reachable, given: PortReach | null): NarrowedView;
46
+ export declare function narrowed(runtime: Reachable, given: PortReach | null, told: ReadinessPort): NarrowedView;
40
47
  //# sourceMappingURL=reach.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,SAAS,EAAe,YAAY,EAAc,MAAM,iBAAiB,CAAC;AAMjG,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAI/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,MAAM,MAAM,eAAe,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/E,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE,SAAS,eAAe,EAAE,CAAC;IAC/C,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAEjD,MAAM,MAAM,KAAK,GAAG,CAClB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,OAAO,KACb,MAAM,IAAI,CAAC;AAEhB,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAE1D,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG;IAAE,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAA;CAAE,CAAC;AAEnF,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG;IACpC,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;IACpD,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACxC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvE,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;CACxE,CAAC;AA2BF,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAMpE;AAMD,wBAAgB,OAAO,CACrB,KAAK,EAAE,SAAS,GAAG,IAAI,EACvB,IAAI,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,cAAc,EAAE;QAAE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAA;CAAE,GAC/F;IAAE,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAU/D;AAcD,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CASnE;AA8ED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,YAAY,CAgKlF"}
1
+ {"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"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"}
package/dist/reach.js CHANGED
@@ -1,28 +1,31 @@
1
1
  import { unheldView } from './conversation.js';
2
2
  import { modelTypes, NO_MODEL } from './model.js';
3
- import { applied, observing } from './observation.js';
3
+ import { changeOf, digestApplied, digestOf, observing, } from './observation.js';
4
+ import { runtimeError } from './failure.js';
5
+ import { failure, lockedRoom, ROOM_LOCKED, undeclared, UNREADABLE, } from './outcome.js';
4
6
  import { beneath } from './paths.js';
5
- import { reconciled } from './read-side.js';
6
- import { moveTarget, readParts } from './room-draft.js';
7
+ import { moveTarget, readParts, staleWrite, } from './room-draft.js';
7
8
  import { documentKey } from './rows.js';
9
+ import { undeclaredSearch } from './search.js';
8
10
  const UNHELD_TYPES = { collection: modelTypes(NO_MODEL), typedSelection: null };
9
- const UNDECLARED = { kind: 'undeclared' };
10
- function undeclared() {
11
- return Promise.resolve(UNDECLARED);
11
+ function unconversed(name) {
12
+ return () => Promise.resolve(undeclared(name));
12
13
  }
13
14
  const NO_CONVERSATION = {
14
15
  list: () => Promise.resolve([]),
15
16
  read: (conversation) => Promise.resolve(unheldView(conversation)),
16
- create: undeclared,
17
- send: undeclared,
18
- answer: undeclared,
19
- interrupt: undeclared,
20
- kill: undeclared,
21
- cancel: undeclared,
22
- delete: undeclared,
17
+ create: unconversed('conversation.create'),
18
+ send: unconversed('conversation.send'),
19
+ attach: unconversed('conversation.attach'),
20
+ answer: unconversed('conversation.answer'),
21
+ interrupt: unconversed('conversation.interrupt'),
22
+ kill: unconversed('conversation.kill'),
23
+ cancel: unconversed('conversation.cancel'),
24
+ delete: unconversed('conversation.delete'),
23
25
  };
24
26
  const NO_CHAT_DRAFT = {
25
27
  write: () => Promise.resolve(),
28
+ prepend: () => Promise.resolve(),
26
29
  discard: () => Promise.resolve(),
27
30
  };
28
31
  export function holds(reach, room) {
@@ -74,7 +77,7 @@ function typesWithin(reach, room, types) {
74
77
  };
75
78
  }
76
79
  function moves(reach, room, move) {
77
- return move === undefined || covers(reach, room, moveTarget(move));
80
+ return move === undefined || covers(reach, move.room ?? room, moveTarget(move));
78
81
  }
79
82
  function draftWithin(reach, draft) {
80
83
  return covers(reach, draft.room, draft.path) && moves(reach, draft.room, draft.parts.move);
@@ -88,7 +91,7 @@ function shownDraft(reach, draft) {
88
91
  function writeWithin(reach, write) {
89
92
  return write.outcome === 'written'
90
93
  ? { outcome: 'written', roomDraft: shownDraft(reach, write.roomDraft) }
91
- : { outcome: 'stale', current: shownDraft(reach, write.current) };
94
+ : staleWrite(shownDraft(reach, write.current));
92
95
  }
93
96
  function savedWithin(reach, room, result) {
94
97
  if (reach === null || result.outcome === 'saved')
@@ -107,76 +110,120 @@ function savedWithin(reach, room, result) {
107
110
  function statusWithin(reach, status) {
108
111
  return {
109
112
  ...status,
110
- attentionRequired: status.attentionRequired.filter((entry) => covers(reach, entry.room, entry.path)),
113
+ attentionRequired: status.attentionRequired.filter((entry) => 'refusal' in entry ? wholly(reach, entry.room) : covers(reach, entry.room, entry.path)),
111
114
  };
112
115
  }
113
116
  function queueWithin(reach, room, entries) {
114
- return entries.filter(({ batch }) => batch.changes.every((change) => covers(reach, room, change.path) &&
115
- (change.kind !== 'move' || covers(reach, room, change.to))));
117
+ return entries
118
+ .filter(({ batch }) => batch.changes.every((change) => covers(reach, room, change.path) &&
119
+ (change.kind !== 'move' || covers(reach, room, change.to))))
120
+ .map((entry) => {
121
+ const { between, ...batch } = entry.batch;
122
+ if (between === undefined)
123
+ return entry;
124
+ return wholly(reach, between.source.room) && wholly(reach, between.destination.room)
125
+ ? entry
126
+ : { ...entry, batch };
127
+ });
116
128
  }
117
129
  function unreached(room) {
118
- return new Error(`No Local Replica for ${room}`);
130
+ return runtimeError('room-not-held', `No Local Replica for ${room}`);
119
131
  }
120
- export function narrowed(runtime, given) {
132
+ function lockedError(room) {
133
+ return runtimeError(ROOM_LOCKED, `${room} is locked until House confirms its access`, true);
134
+ }
135
+ function deviceUnreached() {
136
+ return runtimeError('device-unreached', 'Only the panel cleans up this device');
137
+ }
138
+ export function narrowed(runtime, given, told) {
121
139
  const { md, watch } = runtime;
122
140
  let reach = given;
141
+ let port = told;
123
142
  const open = new Set();
124
- function following(begin) {
143
+ function following(begin, locking = false) {
125
144
  let stop = begin();
126
145
  const restart = () => {
127
146
  stop();
128
147
  stop = begin();
129
148
  };
130
149
  open.add(restart);
150
+ const unwatch = locking ? runtime.watchLocks(restart) : () => { };
131
151
  return () => {
132
152
  open.delete(restart);
153
+ unwatch();
133
154
  stop();
134
155
  };
135
156
  }
157
+ const unlocking = (rooms) => {
158
+ const locked = (rooms ?? []).filter((room) => runtime.locked(room));
159
+ return locked.length === 0
160
+ ? null
161
+ : { pending: locked.map((room) => ({ room, awaits: 'unlock' })) };
162
+ };
163
+ const unlocked = (entries) => entries.filter((entry) => !runtime.locked(entry.room));
164
+ const intoLocked = (held) => held.some((move) => move?.room !== undefined && runtime.locked(move.room));
136
165
  const within = (topic, input, deliver) => {
137
166
  if (topic === 'rooms') {
138
167
  return following(() => watch(topic, input, (rooms) => deliver(roomsWithin(reach, rooms))));
139
168
  }
169
+ if (topic === 'readiness') {
170
+ return following(() => runtime.watchReadiness(port, reach, deliver));
171
+ }
140
172
  if (topic === 'sync-status') {
141
- return following(() => watch(topic, input, (status) => deliver(statusWithin(reach, status))));
173
+ return following(() => watch(topic, input, (status) => {
174
+ const within = statusWithin(reach, status);
175
+ deliver({ ...within, attentionRequired: unlocked(within.attentionRequired) });
176
+ }), true);
142
177
  }
143
178
  if (topic === 'room-drafts') {
144
- return following(() => watch(topic, input, (drafts) => deliver(draftsWithin(reach, drafts))));
179
+ return following(() => watch(topic, input, (drafts) => deliver(unlocked(draftsWithin(reach, drafts)))), true);
145
180
  }
146
181
  if (topic === 'queue') {
147
182
  const room = input[0];
148
183
  return following(() => {
149
- if (!holds(reach, room)) {
184
+ if (!holds(reach, room) || runtime.locked(room)) {
150
185
  deliver([]);
151
186
  return () => { };
152
187
  }
153
188
  return watch(topic, input, (entries) => deliver(queueWithin(reach, room, entries)));
154
- });
189
+ }, true);
155
190
  }
156
191
  if (topic === 'query') {
157
192
  const plan = runtime.plan(input[0], reach);
158
193
  let held = null;
159
194
  return following(() => {
195
+ const locked = unlocking(plan.rooms);
196
+ if (locked !== null) {
197
+ const answer = { result: locked, keys: [] };
198
+ if (held === null || changeOf(held, answer) !== null)
199
+ deliver(answer);
200
+ held = digestOf(answer);
201
+ return () => { };
202
+ }
160
203
  let first = true;
161
- return runtime.watchPlan({ ...plan, reach: planReach(reach) }, (message) => {
204
+ let open = true;
205
+ const heard = (message) => {
162
206
  if (!first) {
163
- held = applied(held, message);
207
+ held = digestApplied(held, message);
164
208
  deliver(message);
165
209
  return;
166
210
  }
167
211
  first = false;
168
- if (held === null) {
169
- held = message;
170
- deliver(message);
171
- return;
172
- }
173
- const next = reconciled(held, message);
174
- if (next === null)
175
- return;
176
- held = next.keyed;
177
- deliver(next.change);
212
+ const change = held === null ? message : changeOf(held, message);
213
+ held = digestOf(message);
214
+ if (change !== null)
215
+ deliver(change);
216
+ };
217
+ const current = { ...plan, reach: planReach(reach), locked: runtime.lockedRooms() };
218
+ const stop = runtime.watchPlan(current, (message) => {
219
+ if (open)
220
+ heard(message);
178
221
  });
179
- });
222
+ return () => {
223
+ open = false;
224
+ stop();
225
+ };
226
+ }, true);
180
227
  }
181
228
  if (topic === 'conversation') {
182
229
  return following(() => {
@@ -186,7 +233,7 @@ export function narrowed(runtime, given) {
186
233
  return () => { };
187
234
  });
188
235
  }
189
- if (topic === 'conversations') {
236
+ if (topic === 'conversations' || topic === 'agents') {
190
237
  return following(() => {
191
238
  if (conversing(reach))
192
239
  return watch(topic, input, deliver);
@@ -196,14 +243,32 @@ export function narrowed(runtime, given) {
196
243
  }
197
244
  return watch(topic, input, deliver);
198
245
  };
246
+ const files = new Map();
247
+ let handed = 0;
248
+ const hand = async (reading) => {
249
+ const answer = await reading;
250
+ if (answer.kind !== 'binary')
251
+ return answer;
252
+ handed += 1;
253
+ const file = String(handed);
254
+ files.set(file, answer.file);
255
+ return { ...answer, file };
256
+ };
199
257
  const conversation = () => (conversing(reach) ? md.conversation : NO_CONVERSATION);
200
258
  const chatDraft = () => (conversing(reach) ? md.chatDraft : NO_CHAT_DRAFT);
201
259
  const view = {
202
260
  ...md,
203
261
  rooms: () => roomsWithin(reach, md.rooms()),
204
- query: ((input) => runtime.query(runtime.plan(input, reach))),
205
- search: (input) => runtime.search(input, reach),
262
+ query: ((input) => {
263
+ const plan = runtime.plan(input, reach);
264
+ return Promise.resolve(unlocking(plan.rooms) ?? runtime.query({ ...plan, locked: runtime.lockedRooms() }));
265
+ }),
266
+ search: (input) => port.search === 'required'
267
+ ? runtime.search(input, reach, runtime.lockedRooms())
268
+ : Promise.resolve(undeclaredSearch()),
206
269
  types(room) {
270
+ if (holds(reach, room) && runtime.locked(room))
271
+ throw lockedError(room);
207
272
  if (wholly(reach, room))
208
273
  return md.types(room);
209
274
  if (!holds(reach, room))
@@ -214,30 +279,98 @@ export function narrowed(runtime, given) {
214
279
  async save(room, roomDrafts, writtenBy) {
215
280
  if (!holds(reach, room))
216
281
  throw unreached(room);
217
- const outside = roomDrafts.find(({ path }) => !covers(reach, room, path) ||
218
- !moves(reach, room, md.roomDraft.read(room, path)?.parts.move));
219
- if (outside !== undefined)
220
- return { outcome: 'refused', rule: 'stale', file: outside.path };
282
+ if (runtime.locked(room))
283
+ return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
284
+ const held = (await Promise.all(roomDrafts.map(({ path }) => md.roomDraft.read(room, path)))).map((draft) => draft?.parts.move);
285
+ const outside = roomDrafts.find(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]));
286
+ if (outside !== undefined) {
287
+ return { outcome: 'refused', code: 'stale', retryable: false, file: outside.path };
288
+ }
289
+ if (intoLocked(held))
290
+ return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
221
291
  return savedWithin(reach, room, await md.save(room, roomDrafts, writtenBy));
222
292
  },
223
- history: (room, path, query) => covers(reach, room, path)
224
- ? md.history(room, path, query)
225
- : Promise.resolve({ kind: 'room-not-readable', locator: room }),
226
- reached: (room, roomVersion, path) => (path === undefined ? wholly(reach, room) : covers(reach, room, path)) &&
227
- md.reached(room, roomVersion, path),
293
+ async saveParts(room, parts, writtenBy) {
294
+ if (!holds(reach, room))
295
+ throw unreached(room);
296
+ if (runtime.locked(room))
297
+ return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
298
+ const held = parts.map(({ parts: one }) => readParts(one).move);
299
+ if (parts.some(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]))) {
300
+ throw unreached(room);
301
+ }
302
+ if (intoLocked(held))
303
+ return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
304
+ return savedWithin(reach, room, await md.saveParts(room, parts, writtenBy));
305
+ },
306
+ resolve(room, path, destination) {
307
+ const at = runtime.located(room, path, destination);
308
+ return at !== null && !covers(reach, at.room, at.path)
309
+ ? Promise.resolve(UNREADABLE)
310
+ : md.resolve(room, path, destination);
311
+ },
312
+ history: (room, path, query) => !covers(reach, room, path)
313
+ ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
314
+ : runtime.locked(room)
315
+ ? Promise.resolve(lockedRoom(room))
316
+ : md.history(room, path, query),
317
+ binaryFile: {
318
+ read: (room, path, revision) => !covers(reach, room, path)
319
+ ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
320
+ : runtime.locked(room)
321
+ ? Promise.resolve(lockedRoom(room))
322
+ : hand(md.binaryFile.read(room, path, revision)),
323
+ link: (room, path, revision) => !covers(reach, room, path)
324
+ ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
325
+ : runtime.locked(room)
326
+ ? Promise.resolve(lockedRoom(room))
327
+ : md.binaryFile.link(room, path, revision),
328
+ async part(file, part) {
329
+ const key = files.get(file);
330
+ if (key === undefined)
331
+ return null;
332
+ const bytes = await md.binaryFile.part(key, part);
333
+ if (bytes === null)
334
+ files.delete(file);
335
+ return bytes;
336
+ },
337
+ },
338
+ reached: async (room, roomVersion, path) => (path === undefined ? wholly(reach, room) : covers(reach, room, path)) &&
339
+ !runtime.locked(room) &&
340
+ (await md.reached(room, roomVersion, path)),
228
341
  log: () => (reach === null ? md.log() : ''),
342
+ cleanUp: () => (reach === null ? md.cleanUp() : Promise.reject(deviceUnreached())),
229
343
  roomDraft: {
230
- list: () => md.roomDraft.list().then((drafts) => draftsWithin(reach, drafts)),
231
- read: (room, path) => covers(reach, room, path) ? shownDraft(reach, md.roomDraft.read(room, path)) : null,
232
- async write(room, path, revision, parts) {
233
- if (!covers(reach, room, path) || !moves(reach, room, readParts(parts).move)) {
234
- throw unreached(room);
344
+ list: () => md.roomDraft.list().then((drafts) => unlocked(draftsWithin(reach, drafts))),
345
+ async read(room, path) {
346
+ if (!covers(reach, room, path))
347
+ return null;
348
+ if (runtime.locked(room))
349
+ throw lockedError(room);
350
+ return shownDraft(reach, await md.roomDraft.read(room, path));
351
+ },
352
+ write(room, path, revision, parts, next) {
353
+ try {
354
+ const move = readParts(parts).move;
355
+ if (!covers(reach, room, path) || !moves(reach, room, move))
356
+ throw unreached(room);
357
+ if (runtime.locked(room))
358
+ throw lockedError(room);
359
+ if (intoLocked([move]))
360
+ throw lockedError(move.room);
361
+ }
362
+ catch (error) {
363
+ return Promise.reject(error);
235
364
  }
236
- return writeWithin(reach, await md.roomDraft.write(room, path, revision, parts));
365
+ return md.roomDraft
366
+ .write(room, path, revision, parts, next)
367
+ .then((written) => writeWithin(reach, written));
237
368
  },
238
369
  async discard(room, path, revision) {
239
370
  if (!covers(reach, room, path))
240
- return { outcome: 'stale', current: null };
371
+ return staleWrite(null);
372
+ if (runtime.locked(room))
373
+ throw lockedError(room);
241
374
  return writeWithin(reach, await md.roomDraft.discard(room, path, revision));
242
375
  },
243
376
  },
@@ -245,7 +378,12 @@ export function narrowed(runtime, given) {
245
378
  list: () => conversation().list(),
246
379
  read: (id, options) => conversation().read(id, options),
247
380
  create: (input) => conversation().create(input),
248
- send: (id) => conversation().send(id),
381
+ send: (id, operation, draft) => conversation().send(id, operation, draft),
382
+ attach: (room, file) => !wholly(reach, room)
383
+ ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
384
+ : runtime.locked(room)
385
+ ? Promise.resolve(lockedRoom(room))
386
+ : conversation().attach(room, file),
249
387
  answer: (id, answer) => conversation().answer(id, answer),
250
388
  interrupt: (id) => conversation().interrupt(id),
251
389
  kill: (id) => conversation().kill(id),
@@ -253,7 +391,8 @@ export function narrowed(runtime, given) {
253
391
  delete: (id) => conversation().delete(id),
254
392
  },
255
393
  chatDraft: {
256
- write: (id, draft) => chatDraft().write(id, draft),
394
+ write: (id, draft, revision) => chatDraft().write(id, draft, revision),
395
+ prepend: (id, draft) => chatDraft().prepend(id, draft),
257
396
  discard: (id) => chatDraft().discard(id),
258
397
  },
259
398
  observe: observing(within),
@@ -266,5 +405,10 @@ export function narrowed(runtime, given) {
266
405
  for (const restart of [...open])
267
406
  restart();
268
407
  },
408
+ facts(next) {
409
+ port = next;
410
+ for (const restart of [...open])
411
+ restart();
412
+ },
269
413
  };
270
414
  }
package/dist/react.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import type { MdRuntimeClient } from './client.js';
2
- import type { AppRoom, ConnectionRefusal, SaveResult } from './connection.js';
2
+ import type { AppRoom, ConnectionRefusal, SavedRoomDraft, SaveResult } from './connection.js';
3
3
  import type { Member, ServiceMode } from './adapter.js';
4
- import type { ConversationEntry, ConversationOptions, ConversationView } from './conversation.js';
4
+ import type { ConversationAgent, ConversationEntry, ConversationOptions, ConversationView } from './conversation.js';
5
+ import { type RuntimeError } from './failure.js';
5
6
  import type { QueueEntry } from './outcome.js';
6
- import type { DocumentQuery, DocumentResult, GroupQuery, GroupResult } from './query.js';
7
+ import type { DocumentQuery, DocumentResult, GroupQuery, GroupResult, PendingResult } from './query.js';
8
+ import type { Readiness } from './readiness.js';
7
9
  import type { RoomDraft, RoomDraftParts } from './room-draft.js';
8
10
  import type { SyncStatus } from './status.js';
9
11
  type Client = MdRuntimeClient | null;
@@ -15,25 +17,27 @@ export type Observed<T> = {
15
17
  };
16
18
  export declare function useObserve(client: Client, topic: 'deployment-facts'): Observed<unknown>;
17
19
  export declare function useObserve(client: Client, topic: 'rooms'): Observed<readonly AppRoom[]>;
20
+ export declare function useObserve(client: Client, topic: 'readiness'): Observed<Readiness>;
18
21
  export declare function useObserve(client: Client, topic: 'connection-refusal'): Observed<ConnectionRefusal | null>;
19
22
  export declare function useObserve(client: Client, topic: 'storage-loss'): Observed<string | null>;
20
23
  export declare function useObserve(client: Client, topic: 'sync-status'): Observed<SyncStatus>;
21
24
  export declare function useObserve(client: Client, topic: 'service-mode'): Observed<ServiceMode>;
22
25
  export declare function useObserve(client: Client, topic: 'member'): Observed<Member | null>;
23
- export declare function useObserve(client: Client, topic: 'query', query: DocumentQuery): Observed<DocumentResult>;
24
- export declare function useObserve(client: Client, topic: 'query', query: GroupQuery): Observed<GroupResult>;
26
+ export declare function useObserve(client: Client, topic: 'query', query: DocumentQuery): Observed<DocumentResult | PendingResult>;
27
+ export declare function useObserve(client: Client, topic: 'query', query: GroupQuery): Observed<GroupResult | PendingResult>;
25
28
  export declare function useObserve(client: Client, topic: 'queue', locator: string): Observed<readonly QueueEntry[]>;
26
29
  export declare function useObserve(client: Client, topic: 'room-drafts'): Observed<readonly RoomDraft[]>;
27
30
  export declare function useObserve(client: Client, topic: 'presentation'): Observed<unknown>;
28
31
  export declare function useObserve(client: Client, topic: 'conversation', conversation: string, options: ConversationOptions): Observed<ConversationView>;
29
32
  export declare function useObserve(client: Client, topic: 'conversations'): Observed<readonly ConversationEntry[]>;
33
+ export declare function useObserve(client: Client, topic: 'agents'): Observed<readonly ConversationAgent[]>;
30
34
  export type Saving = {
31
35
  readonly busy: boolean;
32
36
  readonly outcome: SaveResult | null;
33
- readonly failure: Error | null;
34
- save(room: string, roomDrafts: ReadonlyMap<string, RoomDraftParts>): Promise<SaveResult>;
37
+ readonly failure: RuntimeError | null;
38
+ save(room: string, parts: ReadonlyMap<string, RoomDraftParts>): Promise<SaveResult>;
39
+ saveWritten(room: string, roomDrafts: readonly SavedRoomDraft[]): Promise<SaveResult>;
35
40
  };
36
- export declare function saveRoomDrafts(client: MdRuntimeClient, room: string, roomDrafts: ReadonlyMap<string, RoomDraftParts>): Promise<SaveResult>;
37
41
  export declare function useSave(client: MdRuntimeClient): Saving;
38
42
  export {};
39
43
  //# sourceMappingURL=react.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"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"}