@agentshouse/mdruntime 0.1.0-c99e5271060cd → 0.1.0-ca10e63188fc5

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 (176) hide show
  1. package/README.md +21 -8
  2. package/dist/adapter.d.ts +134 -30
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/attached-model.d.ts +5 -1
  5. package/dist/attached-model.d.ts.map +1 -1
  6. package/dist/attached-model.js +21 -4
  7. package/dist/attempt.d.ts +16 -0
  8. package/dist/attempt.d.ts.map +1 -0
  9. package/dist/attempt.js +70 -0
  10. package/dist/binary.d.ts +18 -0
  11. package/dist/binary.d.ts.map +1 -0
  12. package/dist/binary.js +8 -0
  13. package/dist/bootstrap.d.ts +32 -9
  14. package/dist/bootstrap.d.ts.map +1 -1
  15. package/dist/bootstrap.js +192 -67
  16. package/dist/chain.d.ts +11 -0
  17. package/dist/chain.d.ts.map +1 -0
  18. package/dist/chain.js +64 -0
  19. package/dist/change-set.d.ts +9 -14
  20. package/dist/change-set.d.ts.map +1 -1
  21. package/dist/change-set.js +11 -62
  22. package/dist/change.d.ts +41 -0
  23. package/dist/change.d.ts.map +1 -1
  24. package/dist/change.js +34 -0
  25. package/dist/client.d.ts +31 -12
  26. package/dist/client.d.ts.map +1 -1
  27. package/dist/client.js +104 -7
  28. package/dist/collection.d.ts +12 -6
  29. package/dist/collection.d.ts.map +1 -1
  30. package/dist/collection.js +51 -76
  31. package/dist/compile.d.ts +16 -0
  32. package/dist/compile.d.ts.map +1 -0
  33. package/dist/compile.js +765 -0
  34. package/dist/connection.d.ts +52 -16
  35. package/dist/connection.d.ts.map +1 -1
  36. package/dist/connection.js +3656 -766
  37. package/dist/conversation.d.ts +37 -11
  38. package/dist/conversation.d.ts.map +1 -1
  39. package/dist/conversation.js +576 -179
  40. package/dist/digest.d.ts +7 -0
  41. package/dist/digest.d.ts.map +1 -0
  42. package/dist/digest.js +113 -0
  43. package/dist/durability.d.ts +5 -1
  44. package/dist/durability.d.ts.map +1 -1
  45. package/dist/durability.js +5 -0
  46. package/dist/entry.d.ts +19 -0
  47. package/dist/entry.d.ts.map +1 -0
  48. package/dist/entry.js +151 -0
  49. package/dist/expectation.d.ts +21 -0
  50. package/dist/expectation.d.ts.map +1 -0
  51. package/dist/expectation.js +70 -0
  52. package/dist/fence.d.ts +6 -0
  53. package/dist/fence.d.ts.map +1 -0
  54. package/dist/fence.js +10 -0
  55. package/dist/file.d.ts +2 -19
  56. package/dist/file.d.ts.map +1 -1
  57. package/dist/file.js +7 -122
  58. package/dist/fulltext.d.ts +27 -0
  59. package/dist/fulltext.d.ts.map +1 -0
  60. package/dist/fulltext.js +368 -0
  61. package/dist/host.d.ts +15 -3
  62. package/dist/host.d.ts.map +1 -1
  63. package/dist/host.js +131 -15
  64. package/dist/identity.d.ts +3 -0
  65. package/dist/identity.d.ts.map +1 -1
  66. package/dist/identity.js +9 -0
  67. package/dist/index.d.ts +18 -9
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +8 -0
  70. package/dist/live.d.ts +22 -0
  71. package/dist/live.d.ts.map +1 -0
  72. package/dist/live.js +124 -0
  73. package/dist/media.d.ts +8 -0
  74. package/dist/media.d.ts.map +1 -0
  75. package/dist/media.js +205 -0
  76. package/dist/memory.d.ts +12 -5
  77. package/dist/memory.d.ts.map +1 -1
  78. package/dist/memory.js +112 -24
  79. package/dist/messages.d.ts +28 -0
  80. package/dist/messages.d.ts.map +1 -0
  81. package/dist/messages.js +90 -0
  82. package/dist/model.d.ts +10 -2
  83. package/dist/model.d.ts.map +1 -1
  84. package/dist/model.js +17 -2
  85. package/dist/name.d.ts +4 -0
  86. package/dist/name.d.ts.map +1 -0
  87. package/dist/name.js +122 -0
  88. package/dist/observation.d.ts +20 -2
  89. package/dist/observation.d.ts.map +1 -1
  90. package/dist/observation.js +113 -12
  91. package/dist/opened.d.ts +22 -0
  92. package/dist/opened.d.ts.map +1 -0
  93. package/dist/opened.js +107 -0
  94. package/dist/outcome.d.ts +52 -1
  95. package/dist/outcome.d.ts.map +1 -1
  96. package/dist/outcome.js +46 -0
  97. package/dist/overlay.d.ts +15 -5
  98. package/dist/overlay.d.ts.map +1 -1
  99. package/dist/overlay.js +129 -177
  100. package/dist/query.d.ts +68 -4
  101. package/dist/query.d.ts.map +1 -1
  102. package/dist/query.js +48 -7
  103. package/dist/reach.d.ts +17 -4
  104. package/dist/reach.d.ts.map +1 -1
  105. package/dist/reach.js +226 -50
  106. package/dist/react.d.ts +10 -7
  107. package/dist/react.d.ts.map +1 -1
  108. package/dist/react.js +7 -17
  109. package/dist/readiness.d.ts +64 -0
  110. package/dist/readiness.d.ts.map +1 -0
  111. package/dist/readiness.js +33 -0
  112. package/dist/reads.d.ts +11 -0
  113. package/dist/reads.d.ts.map +1 -0
  114. package/dist/reads.js +100 -0
  115. package/dist/recovery.d.ts +25 -0
  116. package/dist/recovery.d.ts.map +1 -0
  117. package/dist/recovery.js +198 -0
  118. package/dist/refresh.d.ts +16 -15
  119. package/dist/refresh.d.ts.map +1 -1
  120. package/dist/refresh.js +113 -54
  121. package/dist/replica.d.ts +59 -33
  122. package/dist/replica.d.ts.map +1 -1
  123. package/dist/replica.js +309 -157
  124. package/dist/room-draft.d.ts +35 -3
  125. package/dist/room-draft.d.ts.map +1 -1
  126. package/dist/room-draft.js +174 -16
  127. package/dist/rows.d.ts +37 -35
  128. package/dist/rows.d.ts.map +1 -1
  129. package/dist/rows.js +173 -102
  130. package/dist/save.d.ts +68 -3
  131. package/dist/save.d.ts.map +1 -1
  132. package/dist/save.js +795 -143
  133. package/dist/search.d.ts +39 -28
  134. package/dist/search.d.ts.map +1 -1
  135. package/dist/search.js +37 -105
  136. package/dist/seed.d.ts +16 -0
  137. package/dist/seed.d.ts.map +1 -0
  138. package/dist/seed.js +75 -0
  139. package/dist/shared.d.ts +16 -0
  140. package/dist/shared.d.ts.map +1 -0
  141. package/dist/shared.js +431 -0
  142. package/dist/status.d.ts +4 -1
  143. package/dist/status.d.ts.map +1 -1
  144. package/dist/status.js +0 -8
  145. package/dist/store.d.ts +126 -80
  146. package/dist/store.d.ts.map +1 -1
  147. package/dist/store.js +371 -457
  148. package/dist/stored.d.ts +152 -0
  149. package/dist/stored.d.ts.map +1 -0
  150. package/dist/stored.js +571 -0
  151. package/dist/tables.d.ts +354 -0
  152. package/dist/tables.d.ts.map +1 -0
  153. package/dist/tables.js +624 -0
  154. package/dist/turn.d.ts +9 -0
  155. package/dist/turn.d.ts.map +1 -0
  156. package/dist/turn.js +75 -0
  157. package/dist/validation.d.ts +30 -0
  158. package/dist/validation.d.ts.map +1 -0
  159. package/dist/validation.js +162 -0
  160. package/dist/windows.d.ts +22 -0
  161. package/dist/windows.d.ts.map +1 -0
  162. package/dist/windows.js +89 -0
  163. package/dist/wire.d.ts +169 -30
  164. package/dist/wire.d.ts.map +1 -1
  165. package/dist/wire.js +57 -29
  166. package/dist/words.d.ts +19 -0
  167. package/dist/words.d.ts.map +1 -0
  168. package/dist/words.js +150 -0
  169. package/package.json +26 -15
  170. package/AGENTS.md +0 -269
  171. package/dist/attachment.d.ts +0 -3
  172. package/dist/attachment.d.ts.map +0 -1
  173. package/dist/attachment.js +0 -8
  174. package/dist/read-side.d.ts +0 -18
  175. package/dist/read-side.d.ts.map +0 -1
  176. package/dist/read-side.js +0 -433
package/dist/memory.js CHANGED
@@ -1,7 +1,11 @@
1
1
  import { sameChange } from './overlay.js';
2
+ const ATTACHMENTS = 'attachments';
3
+ function lastName(path) {
4
+ return path.slice(path.lastIndexOf('/') + 1);
5
+ }
2
6
  const FIXTURE_RETENTION = {
3
7
  history: { kind: 'duration', seconds: 1 },
4
- outcome: 1,
8
+ outcome: 604_800,
5
9
  refreshHorizon: 1,
6
10
  };
7
11
  function declaredRetention(value) {
@@ -15,12 +19,7 @@ function declaredRetention(value) {
15
19
  }
16
20
  const MODEL_ABSENT = { kind: 'model-unavailable', reason: 'not-readable' };
17
21
  function modelsOf(room) {
18
- return {
19
- collection: room.model ?? MODEL_ABSENT,
20
- ...(room.typedSelection === undefined
21
- ? {}
22
- : { selection: room.selectionModel ?? MODEL_ABSENT }),
23
- };
22
+ return { collection: room.model ?? MODEL_ABSENT };
24
23
  }
25
24
  function changedModels(room, from) {
26
25
  const now = modelsOf(room);
@@ -55,7 +54,10 @@ export function createMemoryAdapter(options = {}) {
55
54
  const scripted = new Map();
56
55
  const unsealed = new Map();
57
56
  const sealed = new Set();
57
+ const sentTurns = new Map();
58
58
  const historyPageSize = options.historyPageSize;
59
+ const attached = new Map();
60
+ const linked = new WeakMap();
59
61
  let held = [];
60
62
  let expiring = [];
61
63
  let replicated = [];
@@ -86,6 +88,19 @@ export function createMemoryAdapter(options = {}) {
86
88
  const wanted = ordinals.get(`${locator}\u0000${target}`);
87
89
  return held !== undefined && wanted !== undefined && held >= wanted;
88
90
  }
91
+ function heldBlob(room, path) {
92
+ return attached.get(`${room.locator}\u0000${path}`) ?? room.blobs?.[path];
93
+ }
94
+ function freePath(room, name) {
95
+ const dot = name.lastIndexOf('.');
96
+ const stem = dot > 0 ? name.slice(0, dot) : name;
97
+ const extension = dot > 0 ? name.slice(dot) : '';
98
+ for (let count = 1;; count += 1) {
99
+ const path = `${ATTACHMENTS}/${count === 1 ? stem : `${stem}-${count}`}${extension}`;
100
+ if (heldBlob(room, path) === undefined && room.documents?.[path] === undefined)
101
+ return path;
102
+ }
103
+ }
89
104
  function retain(entries) {
90
105
  for (const room of entries) {
91
106
  note(room.locator, room);
@@ -114,25 +129,39 @@ export function createMemoryAdapter(options = {}) {
114
129
  const size = pageSize ?? paths.length;
115
130
  const taken = paths.slice(from, from + size);
116
131
  const next = from + taken.length;
117
- const targets = opening ? (room.binaryTargets ?? []) : [];
132
+ const targets = opening ? Object.keys(room.binaryFiles ?? {}) : [];
118
133
  return {
119
134
  kind: 'bootstrap',
120
135
  roomVersion: room.roomVersion,
121
136
  ...(opening ? { models: modelsOf(room) } : {}),
122
137
  documents: named(room.documents ?? {}, taken),
123
- revisions: named(room.revisions ?? {}, taken),
138
+ revisions: named(room.revisions ?? {}, [...taken, ...targets]),
139
+ ...(room.fileIds === undefined
140
+ ? {}
141
+ : { fileIds: named(room.fileIds, [...taken, ...targets]) }),
124
142
  changes: named(room.changes ?? {}, [...taken, ...targets]),
125
- binaryTargets: targets,
126
- ...(opening && room.attachments !== undefined ? { attachments: room.attachments } : {}),
143
+ binaryFiles: named(room.binaryFiles ?? {}, targets),
144
+ ...(opening && room.folders !== undefined ? { folders: room.folders } : {}),
127
145
  ...(next < paths.length ? { pageToken: taken.at(-1) } : {}),
128
146
  };
129
147
  }
148
+ function foldersMoved(room, from) {
149
+ const now = new Set(room.folders ?? []);
150
+ const before = new Set(from.folders ?? []);
151
+ const folders = [...now].filter((folder) => !before.has(folder)).sort();
152
+ const folderRemovals = [...before].filter((folder) => !now.has(folder)).sort();
153
+ return {
154
+ ...(folders.length === 0 ? {} : { folders }),
155
+ ...(folderRemovals.length === 0 ? {} : { folderRemovals }),
156
+ };
157
+ }
130
158
  function advancement(room, from, at) {
131
159
  const current = room.documents ?? {};
132
160
  const previous = from.documents ?? {};
133
- const currentTargets = new Set(room.binaryTargets ?? []);
134
- const previousTargets = new Set(from.binaryTargets ?? []);
161
+ const currentTargets = new Set(Object.keys(room.binaryFiles ?? {}));
162
+ const previousTargets = new Set(Object.keys(from.binaryFiles ?? {}));
135
163
  const headMoved = (path) => room.revisions?.[path] !== from.revisions?.[path] ||
164
+ room.fileIds?.[path] !== from.fileIds?.[path] ||
136
165
  !sameChange(room.changes?.[path], from.changes?.[path]);
137
166
  const changed = Object.keys(current)
138
167
  .filter((path) => current[path] !== previous[path] || headMoved(path))
@@ -147,24 +176,25 @@ export function createMemoryAdapter(options = {}) {
147
176
  const targets = opening
148
177
  ? [...currentTargets].filter((target) => !previousTargets.has(target) || headMoved(target))
149
178
  : [];
150
- const attachments = room.attachments ?? [];
151
- const declared = opening && JSON.stringify(attachments) !== JSON.stringify(from.attachments ?? []);
152
179
  const models = opening ? changedModels(room, from) : undefined;
153
180
  return {
154
181
  kind: 'net-advancement',
155
182
  roomVersion: room.roomVersion,
156
183
  ...(models === undefined ? {} : { models }),
157
184
  documents: named(current, taken),
158
- revisions: named(room.revisions ?? {}, taken),
185
+ revisions: named(room.revisions ?? {}, [...taken, ...targets]),
186
+ ...(room.fileIds === undefined
187
+ ? {}
188
+ : { fileIds: named(room.fileIds, [...taken, ...targets]) }),
159
189
  changes: named(room.changes ?? {}, [...taken, ...targets]),
160
- binaryTargets: targets,
190
+ binaryFiles: named(room.binaryFiles ?? {}, targets),
191
+ ...(opening ? foldersMoved(room, from) : {}),
161
192
  removals: opening
162
193
  ? [
163
194
  ...Object.keys(previous).filter((path) => !(path in current) && !currentTargets.has(path)),
164
195
  ...[...previousTargets].filter((target) => !currentTargets.has(target) && !(target in current)),
165
196
  ].sort()
166
197
  : [],
167
- ...(declared ? { attachments } : {}),
168
198
  ...(pageToken === undefined ? {} : { pageToken }),
169
199
  };
170
200
  }
@@ -224,9 +254,15 @@ export function createMemoryAdapter(options = {}) {
224
254
  if (outcome !== undefined)
225
255
  return outcome;
226
256
  if (name === 'conversation.send') {
257
+ const operation = typeof input.operation_id === 'string' ? input.operation_id : null;
258
+ const answered = operation === null ? undefined : sentTurns.get(operation);
259
+ if (answered !== undefined)
260
+ return { kind: 'action', result: { turn: answered } };
227
261
  issued += 1;
228
262
  const turn = `turn-${issued}`;
229
263
  unsealed.set(turn, named);
264
+ if (operation !== null)
265
+ sentTurns.set(operation, turn);
230
266
  return { kind: 'action', result: { turn } };
231
267
  }
232
268
  if (name === 'conversation.cancel') {
@@ -257,6 +293,8 @@ export function createMemoryAdapter(options = {}) {
257
293
  };
258
294
  }
259
295
  return {
296
+ ...(options.exhaustiveDiscovery === undefined ? {} : { exhaustiveDiscovery: true }),
297
+ ...(options.roomTypes === undefined ? {} : { roomTypes: options.roomTypes }),
260
298
  setRooms(next) {
261
299
  rooms = [...next];
262
300
  retain(rooms);
@@ -269,9 +307,9 @@ export function createMemoryAdapter(options = {}) {
269
307
  for (const observer of observers)
270
308
  observer({ kind: 'opened' });
271
309
  },
272
- close(revoked = false) {
310
+ close({ revoked = false, lost = !revoked } = {}) {
273
311
  for (const observer of observers)
274
- observer({ kind: 'closed', revoked });
312
+ observer({ kind: 'closed', revoked, lost });
275
313
  },
276
314
  expire(locators) {
277
315
  expiring = [...locators];
@@ -280,6 +318,13 @@ export function createMemoryAdapter(options = {}) {
280
318
  for (const observer of observers)
281
319
  observer({ kind: 'room-version', locator, roomVersion });
282
320
  },
321
+ notifyAuthorityChanged(scope) {
322
+ for (const observer of observers) {
323
+ observer(scope === undefined
324
+ ? { kind: 'authority-changed' }
325
+ : { kind: 'authority-changed', scope });
326
+ }
327
+ },
283
328
  notifyConversation(event) {
284
329
  if (event.kind === 'accepted-message') {
285
330
  sealed.add(event.message.turn);
@@ -340,17 +385,19 @@ export function createMemoryAdapter(options = {}) {
340
385
  },
341
386
  reopen() {
342
387
  queueMicrotask(() => {
343
- for (const observer of observers)
344
- observer({ kind: 'closed', revoked: false });
388
+ for (const observer of observers) {
389
+ observer({ kind: 'closed', revoked: false, lost: false });
390
+ }
345
391
  });
346
392
  },
393
+ published() { },
347
394
  observe(notify) {
348
395
  observers.add(notify);
349
396
  queueMicrotask(() => {
350
397
  if (!observers.has(notify))
351
398
  return;
352
399
  if (options.unopened === true) {
353
- notify({ kind: 'closed', revoked: false });
400
+ notify({ kind: 'closed', revoked: false, lost: true });
354
401
  return;
355
402
  }
356
403
  announceList();
@@ -433,7 +480,13 @@ export function createMemoryAdapter(options = {}) {
433
480
  retryable: false,
434
481
  affected: {},
435
482
  };
436
- }, request).then((answer) => note(request.locator, answer));
483
+ }, request).then((answer) => {
484
+ const destination = request.changeBatch.between?.destination.room;
485
+ if (answer.kind === 'accepted' && answer.destination !== undefined && destination) {
486
+ note(destination, answer.destination);
487
+ }
488
+ return note(request.locator, answer);
489
+ });
437
490
  },
438
491
  async history(_authorization, request) {
439
492
  return resolveScript(scripts.history, () => {
@@ -447,6 +500,41 @@ export function createMemoryAdapter(options = {}) {
447
500
  };
448
501
  }, request);
449
502
  },
503
+ async binary(_authorization, request) {
504
+ return resolveScript(scripts.binary, () => {
505
+ const room = rooms.find((entry) => entry.locator === request.locator);
506
+ if (room === undefined)
507
+ return { kind: 'room-not-readable', locator: request.locator };
508
+ const blob = heldBlob(room, request.path);
509
+ return blob === undefined
510
+ ? { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false }
511
+ : { kind: 'binary', body: blob.stream(), mediaType: blob.type };
512
+ }, request);
513
+ },
514
+ async link(_authorization, request) {
515
+ return resolveScript(scripts.link, () => {
516
+ const room = rooms.find((entry) => entry.locator === request.locator);
517
+ if (room === undefined)
518
+ return { kind: 'room-not-readable', locator: request.locator };
519
+ const blob = heldBlob(room, request.path);
520
+ if (blob === undefined) {
521
+ return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
522
+ }
523
+ const url = linked.get(blob) ?? URL.createObjectURL(blob);
524
+ linked.set(blob, url);
525
+ return { kind: 'link', url, name: lastName(request.path), mediaType: blob.type };
526
+ }, request);
527
+ },
528
+ async attach(_authorization, request) {
529
+ return resolveScript(scripts.attach, () => {
530
+ const room = rooms.find((entry) => entry.locator === request.locator);
531
+ if (room === undefined)
532
+ return { kind: 'room-not-readable', locator: request.locator };
533
+ const path = freePath(room, request.name);
534
+ attached.set(`${room.locator}\u0000${path}`, request.blob);
535
+ return { kind: 'attached', path, revision: `attached-${attached.size}` };
536
+ }, request);
537
+ },
450
538
  async action(_authorization, request) {
451
539
  return resolveScript(scripts.action, () => {
452
540
  if (request.name.startsWith('conversation.'))
@@ -0,0 +1,28 @@
1
+ import type { AcceptedMessage } from './adapter.js';
2
+ import type { Connection } from './tables.js';
3
+ export declare const MESSAGE_TABLES: readonly string[];
4
+ export type HeldConversation = {
5
+ readonly conversation: string;
6
+ readonly read: string | null | undefined;
7
+ readonly partial: boolean;
8
+ };
9
+ export type MessageWindow = {
10
+ readonly messages: AcceptedMessage[];
11
+ readonly more: boolean;
12
+ };
13
+ export type ConversationWrite = {
14
+ readonly conversation: string;
15
+ readonly messages: readonly AcceptedMessage[];
16
+ readonly read?: {
17
+ readonly at: string | null;
18
+ readonly partial: boolean;
19
+ };
20
+ };
21
+ export declare function heldConversations(connection: Connection): HeldConversation[];
22
+ export declare function keptMessages(connection: Connection, { conversation, messages, read }: ConversationWrite): null;
23
+ export declare function messageWindow(connection: Connection, conversation: string, limit: number, before: readonly [string, string] | null): MessageWindow;
24
+ export declare function messageCount(connection: Connection, conversation: string): number;
25
+ export declare function turnArrived(connection: Connection, conversation: string, turn: string): boolean;
26
+ export declare function droppedMessages(connection: Connection, conversations: readonly string[]): void;
27
+ export declare function forgottenMessages(connection: Connection): void;
28
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,aAAa,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAM3C,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7F,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAC3E,CAAC;AAMF,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAmB5E;AAED,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,EAAE,YAAY,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,iBAAiB,GAClD,IAAI,CAoCN;AAYD,wBAAgB,aAAa,CAC3B,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GACvC,aAAa,CAUf;AAED,wBAAgB,YAAY,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAMjF;AAED,wBAAgB,WAAW,CAAC,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAO/F;AAED,wBAAgB,eAAe,CAAC,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAW9F;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAG9D"}
@@ -0,0 +1,90 @@
1
+ import { indexMessage, unindexMessages } from './fulltext.js';
2
+ export const MESSAGE_TABLES = [
3
+ 'CREATE TABLE conversation_reads (conversation TEXT PRIMARY KEY, read TEXT, partial INTEGER NOT NULL) WITHOUT ROWID',
4
+ 'CREATE TABLE conversation_messages (id INTEGER PRIMARY KEY, conversation TEXT NOT NULL, identity TEXT NOT NULL, turn TEXT NOT NULL, position TEXT NOT NULL, message TEXT NOT NULL, text TEXT NOT NULL)',
5
+ 'CREATE UNIQUE INDEX conversation_messages_identity ON conversation_messages (conversation, identity)',
6
+ 'CREATE INDEX conversation_messages_position ON conversation_messages (conversation, position, identity)',
7
+ 'CREATE INDEX conversation_messages_turn ON conversation_messages (conversation, turn)',
8
+ ];
9
+ function text(value) {
10
+ return typeof value === 'string' ? value : String(value);
11
+ }
12
+ export function heldConversations(connection) {
13
+ const held = new Map();
14
+ for (const row of connection.rows('SELECT conversation, read, partial FROM conversation_reads')) {
15
+ held.set(text(row.conversation), {
16
+ conversation: text(row.conversation),
17
+ read: row.read === null ? null : text(row.read),
18
+ partial: Number(row.partial) === 1,
19
+ });
20
+ }
21
+ for (const row of connection.rows('SELECT DISTINCT conversation FROM conversation_messages WHERE conversation NOT IN (SELECT conversation FROM conversation_reads)')) {
22
+ held.set(text(row.conversation), {
23
+ conversation: text(row.conversation),
24
+ read: undefined,
25
+ partial: true,
26
+ });
27
+ }
28
+ return [...held.values()];
29
+ }
30
+ export function keptMessages(connection, { conversation, messages, read }) {
31
+ for (const message of messages) {
32
+ const [held] = connection.rows('SELECT id FROM conversation_messages WHERE conversation = ? AND identity = ?', [conversation, message.identity]);
33
+ const record = [
34
+ message.turn,
35
+ message.position,
36
+ JSON.stringify(message.message ?? null),
37
+ message.text,
38
+ ];
39
+ let id;
40
+ if (held === undefined) {
41
+ connection.run('INSERT INTO conversation_messages (conversation, identity, turn, position, message, text) VALUES (?, ?, ?, ?, ?, ?)', [conversation, message.identity, ...record]);
42
+ id = Number(connection.rows('SELECT last_insert_rowid() AS id')[0].id);
43
+ }
44
+ else {
45
+ id = Number(held.id);
46
+ unindexMessages(connection, [id]);
47
+ connection.run('UPDATE conversation_messages SET turn = ?, position = ?, message = ?, text = ? WHERE id = ?', [...record, id]);
48
+ }
49
+ indexMessage(connection, id, message.text);
50
+ }
51
+ if (read !== undefined) {
52
+ connection.run('INSERT OR REPLACE INTO conversation_reads (conversation, read, partial) VALUES (?, ?, ?)', [conversation, read.at, read.partial ? 1 : 0]);
53
+ }
54
+ return null;
55
+ }
56
+ function accepted(row) {
57
+ return {
58
+ identity: text(row.identity),
59
+ turn: text(row.turn),
60
+ position: text(row.position),
61
+ text: text(row.text),
62
+ message: JSON.parse(text(row.message)),
63
+ };
64
+ }
65
+ export function messageWindow(connection, conversation, limit, before) {
66
+ const rows = connection.rows(`SELECT identity, turn, position, message, text FROM conversation_messages WHERE conversation = ?${before === null ? '' : ' AND (position < ? OR (position = ? AND identity < ?))'} ORDER BY position DESC, identity DESC LIMIT ?`, before === null
67
+ ? [conversation, limit + 1]
68
+ : [conversation, before[0], before[0], before[1], limit + 1]);
69
+ return { messages: rows.slice(0, limit).map(accepted).reverse(), more: rows.length > limit };
70
+ }
71
+ export function messageCount(connection, conversation) {
72
+ const [counted] = connection.rows('SELECT count(*) AS held FROM conversation_messages WHERE conversation = ?', [conversation]);
73
+ return Number(counted?.held ?? 0);
74
+ }
75
+ export function turnArrived(connection, conversation, turn) {
76
+ return (connection.rows('SELECT 1 FROM conversation_messages WHERE conversation = ? AND turn = ? LIMIT 1', [conversation, turn]).length > 0);
77
+ }
78
+ export function droppedMessages(connection, conversations) {
79
+ for (const conversation of conversations) {
80
+ unindexMessages(connection, connection
81
+ .rows('SELECT id FROM conversation_messages WHERE conversation = ?', [conversation])
82
+ .map((row) => Number(row.id)));
83
+ connection.run('DELETE FROM conversation_messages WHERE conversation = ?', [conversation]);
84
+ connection.run('DELETE FROM conversation_reads WHERE conversation = ?', [conversation]);
85
+ }
86
+ }
87
+ export function forgottenMessages(connection) {
88
+ connection.run('DELETE FROM conversation_messages');
89
+ connection.run('DELETE FROM conversation_reads');
90
+ }
package/dist/model.d.ts CHANGED
@@ -28,13 +28,19 @@ export type ModelState = {
28
28
  verifiedWith: ModelIdentity;
29
29
  types: VerifiedModel['types'];
30
30
  };
31
- export type TypesResult = {
31
+ export type StoredModel = Extract<ModelState, {
32
32
  status: 'unavailable';
33
+ }> | Omit<Extract<ModelState, {
34
+ status: 'current' | 'cached';
35
+ }>, 'types'>;
36
+ export type TypesResult = {
37
+ status: Open<'unavailable'>;
33
38
  reason: ModelUnavailableReason;
39
+ types: null;
34
40
  schema?: string | null;
35
41
  revision?: string | null;
36
42
  } | {
37
- status: 'current' | 'cached';
43
+ status: Open<'current' | 'cached'>;
38
44
  identity: string;
39
45
  version: string;
40
46
  verifiedWith: ModelIdentity;
@@ -50,7 +56,9 @@ export type ValidationReceipt = {
50
56
  export declare const NO_MODEL: ModelState;
51
57
  export declare function definitionOf(state: ModelState, type: string | undefined): Definition | undefined;
52
58
  export declare function modelTypes(state: ModelState): TypesResult;
59
+ export declare function storedModel(state: ModelState): StoredModel;
53
60
  export declare function cached(state: ModelState): ModelState;
54
61
  export declare function sameModel(left: ModelIdentity, right: ModelIdentity): boolean;
62
+ export declare function sameTyping(left: ModelState, right: ModelState): boolean;
55
63
  export declare function referenceField(facts: ValueFacts | undefined): boolean;
56
64
  //# sourceMappingURL=model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAC/F,MAAM,MAAM,sBAAsB,GAAG,IAAI,CAAC,cAAc,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC,CAAC;AACnG,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,MAAM,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,MAAM,GAAG,UAAU,CAAC;AAChC,MAAM,MAAM,UAAU,GAClB;IACE,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IACE,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,EAAE,aAAa,CAAC;IAC5B,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CAC/B,CAAC;AACN,MAAM,MAAM,WAAW,GACnB;IACE,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IACE,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,aAAa,CAAC;IAC5B,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AACN,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,CAAC;CACpC,CAAC;AACF,eAAO,MAAM,QAAQ,EAAE,UAA8D,CAAC;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAGhG;AACD,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAgBzD;AACD,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAEpD;AACD,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAE5E;AACD,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAErE"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
package/dist/model.js CHANGED
@@ -6,7 +6,7 @@ export function definitionOf(state, type) {
6
6
  }
7
7
  export function modelTypes(state) {
8
8
  return state.status === 'unavailable'
9
- ? { ...state }
9
+ ? { ...state, types: null }
10
10
  : {
11
11
  status: state.status,
12
12
  identity: state.snapshot.identity,
@@ -14,15 +14,30 @@ export function modelTypes(state) {
14
14
  verifiedWith: { ...state.verifiedWith },
15
15
  schema: state.snapshot.schema,
16
16
  revision: state.snapshot.revision,
17
- types: structuredClone(Object.values(state.types).sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0)),
17
+ types: Object.values(state.types).sort((left, right) => left.name < right.name ? -1 : left.name > right.name ? 1 : 0),
18
18
  };
19
19
  }
20
+ export function storedModel(state) {
21
+ if (state.status === 'unavailable')
22
+ return state;
23
+ const { types: _types, ...stored } = state;
24
+ return stored;
25
+ }
20
26
  export function cached(state) {
21
27
  return state.status === 'unavailable' ? state : { ...state, status: 'cached' };
22
28
  }
23
29
  export function sameModel(left, right) {
24
30
  return left.identity === right.identity && left.version === right.version;
25
31
  }
32
+ export function sameTyping(left, right) {
33
+ if (left === right)
34
+ return true;
35
+ if (left.status === 'unavailable' || right.status === 'unavailable') {
36
+ return left.status === right.status;
37
+ }
38
+ return (left.snapshot.schema === right.snapshot.schema &&
39
+ sameModel(left.verifiedWith, right.verifiedWith));
40
+ }
26
41
  export function referenceField(facts) {
27
42
  return facts?.reference !== undefined || facts?.items?.reference !== undefined;
28
43
  }
package/dist/name.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare function transliterated(text: string): string;
2
+ export declare function nameFrom(title: string): string;
3
+ export declare function cutName(name: string, most: number): string;
4
+ //# sourceMappingURL=name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"name.d.ts","sourceRoot":"","sources":["../src/name.ts"],"names":[],"mappings":"AAgHA,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK9C;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D"}
package/dist/name.js ADDED
@@ -0,0 +1,122 @@
1
+ const LETTERS = {
2
+ а: 'a',
3
+ б: 'b',
4
+ в: 'v',
5
+ г: 'g',
6
+ ґ: 'g',
7
+ д: 'd',
8
+ ђ: 'dj',
9
+ ѓ: 'gj',
10
+ е: 'e',
11
+ ё: 'yo',
12
+ є: 'ye',
13
+ ж: 'zh',
14
+ з: 'z',
15
+ ѕ: 'dz',
16
+ и: 'i',
17
+ і: 'i',
18
+ ї: 'yi',
19
+ й: 'y',
20
+ ј: 'j',
21
+ к: 'k',
22
+ ќ: 'kj',
23
+ л: 'l',
24
+ љ: 'lj',
25
+ м: 'm',
26
+ н: 'n',
27
+ њ: 'nj',
28
+ о: 'o',
29
+ п: 'p',
30
+ р: 'r',
31
+ с: 's',
32
+ т: 't',
33
+ ћ: 'c',
34
+ у: 'u',
35
+ ў: 'u',
36
+ ф: 'f',
37
+ х: 'kh',
38
+ ц: 'ts',
39
+ ч: 'ch',
40
+ џ: 'dz',
41
+ ш: 'sh',
42
+ щ: 'shch',
43
+ ъ: '',
44
+ ы: 'y',
45
+ ь: '',
46
+ э: 'e',
47
+ ю: 'yu',
48
+ я: 'ya',
49
+ α: 'a',
50
+ β: 'v',
51
+ γ: 'g',
52
+ δ: 'd',
53
+ ε: 'e',
54
+ ζ: 'z',
55
+ η: 'i',
56
+ θ: 'th',
57
+ ι: 'i',
58
+ κ: 'k',
59
+ λ: 'l',
60
+ μ: 'm',
61
+ ν: 'n',
62
+ ξ: 'x',
63
+ ο: 'o',
64
+ π: 'p',
65
+ ρ: 'r',
66
+ σ: 's',
67
+ ς: 's',
68
+ τ: 't',
69
+ υ: 'y',
70
+ φ: 'f',
71
+ χ: 'ch',
72
+ ψ: 'ps',
73
+ ω: 'o',
74
+ ß: 'ss',
75
+ æ: 'ae',
76
+ œ: 'oe',
77
+ ø: 'o',
78
+ đ: 'd',
79
+ ð: 'd',
80
+ þ: 'th',
81
+ ł: 'l',
82
+ ı: 'i',
83
+ };
84
+ const MARKS = /\p{M}/gu;
85
+ const ADMITTED = /^[a-z0-9]$/;
86
+ const WORDLIKE = /^[\p{L}\p{N}]$/u;
87
+ function lowerLetterOf(character) {
88
+ const known = LETTERS[character];
89
+ if (known !== undefined)
90
+ return known;
91
+ const bare = character.normalize('NFKD').replace(MARKS, '');
92
+ const mapped = LETTERS[bare];
93
+ if (mapped !== undefined)
94
+ return mapped;
95
+ return [...bare].every((one) => ADMITTED.test(one)) ? bare : null;
96
+ }
97
+ function codePoint(character) {
98
+ return WORDLIKE.test(character) ? `-u${character.codePointAt(0)?.toString(16) ?? ''}-` : '-';
99
+ }
100
+ function latin(text, unknown) {
101
+ return [...text]
102
+ .map((character) => {
103
+ if ((character.codePointAt(0) ?? 0) < 0x80)
104
+ return character;
105
+ const lower = character.toLowerCase();
106
+ const letter = lowerLetterOf(lower) ?? unknown(lower);
107
+ return lower === character ? letter : `${letter.charAt(0).toUpperCase()}${letter.slice(1)}`;
108
+ })
109
+ .join('');
110
+ }
111
+ export function transliterated(text) {
112
+ return latin(text, () => '-');
113
+ }
114
+ export function nameFrom(title) {
115
+ return latin(title, codePoint)
116
+ .toLowerCase()
117
+ .replace(/[^a-z0-9]+/g, '-')
118
+ .replace(/^-+|-+$/g, '');
119
+ }
120
+ export function cutName(name, most) {
121
+ return name.slice(0, most).replace(/-+$/, '');
122
+ }
@@ -1,4 +1,4 @@
1
- import type { QueryDocument, QueryGroup, QueryResult } from './query.js';
1
+ import type { QueryCoverage, QueryDocument, QueryGroup, QueryResult } from './query.js';
2
2
  export type Observation<T> = {
3
3
  current(): T;
4
4
  subscribe(listener: (value: T) => void): () => void;
@@ -13,15 +13,33 @@ export type QueryChange = {
13
13
  changed: readonly (readonly [RowKey, QueryDocument | QueryGroup])[];
14
14
  removed: readonly RowKey[];
15
15
  order: readonly RowKey[] | null;
16
+ coverage?: QueryCoverage;
17
+ next?: string | null;
18
+ total?: number;
16
19
  };
20
+ export type QueryMessage = KeyedResult | QueryChange;
17
21
  export type Observed = {
18
22
  observation: Observation<unknown>;
19
23
  receive(message: unknown): void;
20
24
  end(): void;
21
25
  };
22
26
  export declare function rowsOf(result: QueryResult): readonly (QueryDocument | QueryGroup)[];
23
- export declare function applied(keyed: KeyedResult, change: QueryChange): KeyedResult;
27
+ export declare function whole(message: QueryMessage): message is KeyedResult;
28
+ export declare function applied(keyed: KeyedResult, message: QueryMessage): KeyedResult;
24
29
  export declare function observed(first: unknown, stop: () => void, keyed: boolean): Observed;
25
30
  export declare function opened(watch: (deliver: (message: unknown) => void) => () => void, keyed: boolean): Promise<Observation<unknown>>;
26
31
  export declare function observing<Topic extends string>(watch: (topic: Topic, input: readonly unknown[], deliver: (message: unknown) => void) => () => void): (topic: Topic, ...input: unknown[]) => Promise<Observation<unknown>>;
32
+ export type Digest = {
33
+ readonly pending: string;
34
+ } | {
35
+ readonly keys: readonly RowKey[];
36
+ readonly rows: ReadonlyMap<RowKey, number>;
37
+ readonly coverage: string;
38
+ readonly next: string | undefined;
39
+ readonly total: number | undefined;
40
+ };
41
+ export declare function hashed(text: string): number;
42
+ export declare function digestOf({ result, keys }: KeyedResult): Digest;
43
+ export declare function digestApplied(digest: Digest, message: QueryMessage): Digest;
44
+ export declare function changeOf(previous: Digest, next: KeyedResult): QueryMessage | null;
27
45
  //# sourceMappingURL=observation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,OAAO,IAAI,CAAC,CAAC;IACb,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACpD,KAAK,IAAI,IAAI,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE3E,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC;IACpE,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,WAAW,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IAChC,GAAG,IAAI,IAAI,CAAC;CACb,CAAC;AAEF,wBAAgB,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC,aAAa,GAAG,UAAU,CAAC,EAAE,CAEnF;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,GAAG,WAAW,CAc5E;AAiBD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,QAAQ,CAkCnF;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAAK,MAAM,IAAI,EAC1D,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAiB/B;AAED,wBAAgB,SAAS,CAAC,KAAK,SAAS,MAAM,EAC5C,KAAK,EAAE,CACL,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAChC,MAAM,IAAI,WAEA,KAAK,YAAY,OAAO,EAAE,KAAG,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAQ1E"}
1
+ {"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"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"}