@agentshouse/mdruntime 0.1.0-c16fc8caac7ff → 0.1.0-c1c2b722d3dcd

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 (152) hide show
  1. package/AGENTS.md +275 -275
  2. package/README.md +8 -8
  3. package/dist/adapter.d.ts +51 -9
  4. package/dist/adapter.d.ts.map +1 -1
  5. package/dist/attempt.d.ts.map +1 -1
  6. package/dist/attempt.js +14 -1
  7. package/dist/bootstrap.d.ts +3 -2
  8. package/dist/bootstrap.d.ts.map +1 -1
  9. package/dist/bootstrap.js +33 -7
  10. package/dist/change-set.d.ts +2 -0
  11. package/dist/change-set.d.ts.map +1 -1
  12. package/dist/change-set.js +36 -10
  13. package/dist/chat/acts.d.ts +3 -4
  14. package/dist/chat/acts.d.ts.map +1 -1
  15. package/dist/chat/acts.js +10 -10
  16. package/dist/chat/earlier.d.ts +10 -0
  17. package/dist/chat/earlier.d.ts.map +1 -0
  18. package/dist/chat/earlier.js +54 -0
  19. package/dist/chat/kit.d.ts +2 -1
  20. package/dist/chat/kit.d.ts.map +1 -1
  21. package/dist/chat/kit.js +3 -3
  22. package/dist/chat/list.d.ts +2 -1
  23. package/dist/chat/list.d.ts.map +1 -1
  24. package/dist/chat/list.js +42 -5
  25. package/dist/chat/markdown.d.ts +1 -0
  26. package/dist/chat/markdown.d.ts.map +1 -1
  27. package/dist/chat/markdown.js +78 -20
  28. package/dist/chat/message.d.ts.map +1 -1
  29. package/dist/chat/message.js +2 -2
  30. package/dist/chat/messages.d.ts +1 -0
  31. package/dist/chat/messages.d.ts.map +1 -1
  32. package/dist/chat/messages.js +4 -0
  33. package/dist/chat/pieces.d.ts +62 -0
  34. package/dist/chat/pieces.d.ts.map +1 -0
  35. package/dist/chat/pieces.js +1110 -0
  36. package/dist/chat/provider.d.ts +1 -1
  37. package/dist/chat/provider.d.ts.map +1 -1
  38. package/dist/chat/provider.js +62 -79
  39. package/dist/chat/question.d.ts +1 -1
  40. package/dist/chat/question.d.ts.map +1 -1
  41. package/dist/chat/question.js +7 -18
  42. package/dist/chat/ready.d.ts +1 -0
  43. package/dist/chat/ready.d.ts.map +1 -1
  44. package/dist/chat/ready.js +2 -2
  45. package/dist/chat/style.js +4 -4
  46. package/dist/chat.d.ts +1 -1
  47. package/dist/chat.d.ts.map +1 -1
  48. package/dist/chat.js +1 -1
  49. package/dist/client.d.ts +17 -9
  50. package/dist/client.d.ts.map +1 -1
  51. package/dist/client.js +19 -6
  52. package/dist/collection.d.ts +20 -5
  53. package/dist/collection.d.ts.map +1 -1
  54. package/dist/collection.js +309 -33
  55. package/dist/connection.d.ts +31 -9
  56. package/dist/connection.d.ts.map +1 -1
  57. package/dist/connection.js +1573 -372
  58. package/dist/conversation.d.ts +20 -7
  59. package/dist/conversation.d.ts.map +1 -1
  60. package/dist/conversation.js +474 -163
  61. package/dist/durability.d.ts +7 -1
  62. package/dist/durability.d.ts.map +1 -1
  63. package/dist/entry.d.ts +17 -0
  64. package/dist/entry.d.ts.map +1 -0
  65. package/dist/entry.js +157 -0
  66. package/dist/fence.d.ts +6 -0
  67. package/dist/fence.d.ts.map +1 -0
  68. package/dist/fence.js +10 -0
  69. package/dist/host.d.ts +14 -2
  70. package/dist/host.d.ts.map +1 -1
  71. package/dist/host.js +91 -9
  72. package/dist/identity.d.ts +2 -0
  73. package/dist/identity.d.ts.map +1 -1
  74. package/dist/identity.js +6 -0
  75. package/dist/index.d.ts +10 -7
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +2 -0
  78. package/dist/memory.d.ts +8 -2
  79. package/dist/memory.d.ts.map +1 -1
  80. package/dist/memory.js +33 -6
  81. package/dist/model.d.ts +4 -2
  82. package/dist/model.d.ts.map +1 -1
  83. package/dist/model.js +10 -1
  84. package/dist/observation.d.ts +7 -2
  85. package/dist/observation.d.ts.map +1 -1
  86. package/dist/observation.js +29 -12
  87. package/dist/outcome.d.ts +12 -2
  88. package/dist/outcome.d.ts.map +1 -1
  89. package/dist/outcome.js +4 -0
  90. package/dist/overlay.d.ts +3 -0
  91. package/dist/overlay.d.ts.map +1 -1
  92. package/dist/overlay.js +114 -95
  93. package/dist/query.d.ts +56 -4
  94. package/dist/query.d.ts.map +1 -1
  95. package/dist/query.js +36 -7
  96. package/dist/reach.d.ts +6 -3
  97. package/dist/reach.d.ts.map +1 -1
  98. package/dist/reach.js +30 -5
  99. package/dist/react.d.ts +8 -6
  100. package/dist/react.d.ts.map +1 -1
  101. package/dist/react.js +7 -17
  102. package/dist/read-side.d.ts +16 -7
  103. package/dist/read-side.d.ts.map +1 -1
  104. package/dist/read-side.js +484 -100
  105. package/dist/readiness.d.ts +53 -0
  106. package/dist/readiness.d.ts.map +1 -0
  107. package/dist/readiness.js +33 -0
  108. package/dist/reads.d.ts +11 -0
  109. package/dist/reads.d.ts.map +1 -0
  110. package/dist/reads.js +98 -0
  111. package/dist/recovery.d.ts +25 -0
  112. package/dist/recovery.d.ts.map +1 -0
  113. package/dist/recovery.js +197 -0
  114. package/dist/refresh.d.ts +4 -4
  115. package/dist/refresh.d.ts.map +1 -1
  116. package/dist/refresh.js +18 -11
  117. package/dist/replica.d.ts +10 -5
  118. package/dist/replica.d.ts.map +1 -1
  119. package/dist/replica.js +95 -32
  120. package/dist/room-draft.d.ts +13 -1
  121. package/dist/room-draft.d.ts.map +1 -1
  122. package/dist/room-draft.js +11 -12
  123. package/dist/rows.d.ts +6 -13
  124. package/dist/rows.d.ts.map +1 -1
  125. package/dist/rows.js +10 -13
  126. package/dist/save.d.ts +9 -3
  127. package/dist/save.d.ts.map +1 -1
  128. package/dist/save.js +187 -92
  129. package/dist/search.d.ts +49 -6
  130. package/dist/search.d.ts.map +1 -1
  131. package/dist/search.js +192 -47
  132. package/dist/seed.d.ts +16 -0
  133. package/dist/seed.d.ts.map +1 -0
  134. package/dist/seed.js +75 -0
  135. package/dist/shared.d.ts +14 -0
  136. package/dist/shared.d.ts.map +1 -0
  137. package/dist/shared.js +394 -0
  138. package/dist/status.d.ts +4 -0
  139. package/dist/status.d.ts.map +1 -1
  140. package/dist/store.d.ts +56 -11
  141. package/dist/store.d.ts.map +1 -1
  142. package/dist/store.js +311 -84
  143. package/dist/turn.d.ts +9 -0
  144. package/dist/turn.d.ts.map +1 -0
  145. package/dist/turn.js +64 -0
  146. package/dist/windows.d.ts +26 -0
  147. package/dist/windows.d.ts.map +1 -0
  148. package/dist/windows.js +93 -0
  149. package/dist/wire.d.ts +152 -32
  150. package/dist/wire.d.ts.map +1 -1
  151. package/dist/wire.js +52 -31
  152. package/package.json +6 -2
package/dist/save.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import { definitionOf } from './model.js';
2
2
  import { apply, ATTACHMENT, links, parse, pointerSegments, references, relative, relativize, retarget, serialize, target, } from '@agentshouse/mdmodel';
3
3
  import { immutable, queuedFile, departure, } from './change.js';
4
- import { collectionOf, documentsOf, governing, validateCollection, } from './collection.js';
4
+ import { available, changedCleanly, collectionOf, documentsOf, governing, referring, validateCollection, } from './collection.js';
5
5
  import { changeBatchIdentity } from './identity.js';
6
6
  import { overlay } from './overlay.js';
7
7
  import { covered, normalize } from './paths.js';
8
+ import { differences } from './shared.js';
9
+ import { ROW_WEIGHT, stepped } from './turn.js';
8
10
  function refuse(code, file, location) {
9
11
  return {
10
12
  kind: 'refused',
@@ -20,7 +22,7 @@ function repointed(document, definition, from, to, moves, settled) {
20
22
  const parsed = parse(document.content, from);
21
23
  if (!parsed.ok)
22
24
  return [];
23
- let next = parsed.document;
25
+ const changes = [];
24
26
  const names = new Set();
25
27
  for (const { pointer, value } of definition === undefined
26
28
  ? []
@@ -32,38 +34,39 @@ function repointed(document, definition, from, to, moves, settled) {
32
34
  const destination = moves.get(named) ?? named;
33
35
  if (target(to, value) === destination)
34
36
  continue;
35
- const applied = apply(next, {
37
+ changes.push({
36
38
  kind: 'reference',
37
39
  pointer,
38
40
  value: retarget(value, relative(to, destination)),
39
41
  prior: value,
40
42
  });
41
- if (applied.outcome !== 'applied')
42
- continue;
43
- next = applied.document;
44
43
  names.add(name);
45
44
  }
45
+ if (changes.length === 0)
46
+ return [];
47
+ const applied = apply(parsed.document, changes);
48
+ if (applied.outcome !== 'applied')
49
+ return [];
50
+ const next = applied.document;
46
51
  return [...names].map((name) => ({ kind: 'field', path: from, name, value: next.fields[name] }));
47
52
  }
48
- function edited(document, path, changes) {
49
- let next = document;
53
+ function edited(document, changes) {
54
+ const parts = new Map();
50
55
  for (const change of changes) {
51
- if (change.path !== path)
52
- continue;
53
- if (change.kind !== 'section' && change.kind !== 'preamble')
54
- continue;
55
- const applied = apply(next, change.kind === 'preamble'
56
- ? { kind: 'preamble', value: change.value, prior: next.preamble }
57
- : {
56
+ if (change.kind === 'preamble')
57
+ parts.set('preamble', { kind: 'preamble', value: change.value, prior: document.preamble });
58
+ if (change.kind === 'section')
59
+ parts.set(`section ${change.name}`, {
58
60
  kind: 'section',
59
61
  name: change.name,
60
62
  value: change.value,
61
- prior: next.sections[change.name],
63
+ prior: document.sections[change.name] ?? '',
62
64
  });
63
- if (applied.outcome === 'applied')
64
- next = applied.document;
65
65
  }
66
- return next;
66
+ if (parts.size === 0)
67
+ return document;
68
+ const applied = apply(document, [...parts.values()]);
69
+ return applied.outcome === 'applied' ? applied.document : document;
67
70
  }
68
71
  function bodies(path, before, after) {
69
72
  const changes = [];
@@ -78,7 +81,7 @@ function bodies(path, before, after) {
78
81
  return changes;
79
82
  }
80
83
  function relinks(path, moved, before, moves) {
81
- let after = before;
84
+ const changes = [];
82
85
  for (const link of links(before, path)) {
83
86
  const destination = moves.get(link.target) ?? link.target;
84
87
  if (destination === link.target && moved === path)
@@ -86,20 +89,23 @@ function relinks(path, moved, before, moves) {
86
89
  const to = relative(moved, destination);
87
90
  if (to === relative(path, link.target))
88
91
  continue;
89
- const applied = apply(after, { kind: 'link', href: link.href, to });
90
- if (applied.outcome === 'refuse') {
91
- return {
92
- kind: 'refused',
93
- refusal: {
94
- code: applied.refusal.rule,
95
- retryable: false,
96
- file: path,
97
- ...(applied.refusal.location === undefined ? {} : { location: applied.refusal.location }),
98
- },
99
- };
100
- }
101
- after = applied.document;
92
+ changes.push({ kind: 'link', href: link.href, to });
102
93
  }
94
+ if (changes.length === 0)
95
+ return { kind: 'changes', changes: [] };
96
+ const applied = apply(before, changes);
97
+ if (applied.outcome === 'refuse') {
98
+ return {
99
+ kind: 'refused',
100
+ refusal: {
101
+ code: applied.refusal.rule,
102
+ retryable: false,
103
+ file: path,
104
+ ...(applied.refusal.location === undefined ? {} : { location: applied.refusal.location }),
105
+ },
106
+ };
107
+ }
108
+ const after = applied.document;
103
109
  if (after === before)
104
110
  return { kind: 'changes', changes: [] };
105
111
  if (before.type === undefined) {
@@ -107,19 +113,14 @@ function relinks(path, moved, before, moves) {
107
113
  }
108
114
  return { kind: 'changes', changes: bodies(path, before, after) };
109
115
  }
110
- function subsumed(merged, path) {
111
- for (let index = merged.length - 1; index >= 0; index -= 1) {
112
- const item = merged[index];
113
- if (item.path !== path)
114
- continue;
115
- if (item.kind === 'section' || item.kind === 'preamble')
116
- merged.splice(index, 1);
117
- }
116
+ function partKey(change) {
117
+ return change.kind === 'section' ? `section ${change.name}` : change.kind;
118
118
  }
119
119
  function rewrites(changes, visible) {
120
120
  const moves = new Map();
121
121
  const settled = new Set();
122
- for (const change of changes) {
122
+ const parts = new Map();
123
+ for (const [index, change] of changes.entries()) {
123
124
  if (change.kind === 'move')
124
125
  moves.set(change.path, change.to);
125
126
  if (change.kind === 'remove' ||
@@ -130,6 +131,13 @@ function rewrites(changes, visible) {
130
131
  }
131
132
  if (change.kind === 'field')
132
133
  settled.add(`${change.path} ${change.name}`);
134
+ if (isPart(change)) {
135
+ const held = parts.get(change.path);
136
+ if (held === undefined)
137
+ parts.set(change.path, [index]);
138
+ else
139
+ held.push(index);
140
+ }
133
141
  }
134
142
  if (moves.size === 0)
135
143
  return { kind: 'changes', changes };
@@ -141,28 +149,41 @@ function rewrites(changes, visible) {
141
149
  const moved = moves.get(path) ?? path;
142
150
  const definition = definitionOf(governing(visible.collection.composition, path), document.type);
143
151
  added.push(...repointed(document, definition, path, moved, moves, settled));
144
- const relinked = relinks(path, moved, edited(document, path, merged), moves);
152
+ const own = parts.get(path) ?? [];
153
+ const relinked = relinks(path, moved, edited(document, own.map((index) => merged[index])), moves);
145
154
  if (relinked.kind === 'refused')
146
155
  return relinked;
156
+ const keyed = new Map();
157
+ for (const index of own) {
158
+ const key = partKey(merged[index]);
159
+ if (!keyed.has(key))
160
+ keyed.set(key, index);
161
+ }
147
162
  for (const change of relinked.changes) {
148
163
  if (change.kind === 'replace') {
149
- subsumed(merged, path);
164
+ for (const index of own) {
165
+ const kind = merged[index]?.kind;
166
+ if (kind === 'section' || kind === 'preamble')
167
+ merged[index] = null;
168
+ }
150
169
  added.push(change);
151
170
  continue;
152
171
  }
153
- const index = merged.findIndex((item) => item.kind === change.kind &&
154
- item.path === path &&
155
- (change.kind !== 'section' || (item.kind === 'section' && item.name === change.name)));
156
- if (index === -1)
172
+ const index = keyed.get(partKey(change));
173
+ if (index === undefined)
157
174
  added.push(change);
158
175
  else
159
176
  merged[index] = change;
160
177
  }
161
178
  }
162
- return { kind: 'changes', changes: [...added, ...merged] };
179
+ return {
180
+ kind: 'changes',
181
+ changes: [...added, ...merged.filter((change) => change !== null)],
182
+ };
163
183
  }
164
184
  function anticipated(changes, preconditions, rewritten, visible) {
165
- const derived = rewritten.filter((change) => !changes.includes(change));
185
+ const given = new Set(changes);
186
+ const derived = rewritten.filter((change) => !given.has(change));
166
187
  return {
167
188
  changes: rewritten,
168
189
  preconditions: [...preconditionsOf(derived, visible, []), ...preconditions],
@@ -177,7 +198,7 @@ export function providerRewritten(batch, visible) {
177
198
  ...anticipated(batch.changes, batch.preconditions, rewritten.changes, visible),
178
199
  };
179
200
  }
180
- function incoming(collection, removed) {
201
+ function* incoming(collection, removed, candidates) {
181
202
  const found = new Map();
182
203
  const note = (target, file) => {
183
204
  if (!removed.has(target))
@@ -186,7 +207,14 @@ function incoming(collection, removed) {
186
207
  referrers.add(file);
187
208
  found.set(target, referrers);
188
209
  };
189
- for (const [path, document] of documentsOf(collection)) {
210
+ const read = function* (paths) {
211
+ for (const path of [...new Set(paths)].sort()) {
212
+ const document = collection.document(path);
213
+ if (document !== undefined)
214
+ yield [path, document];
215
+ }
216
+ };
217
+ for (const [path, document] of candidates === null ? documentsOf(collection) : read(candidates)) {
190
218
  const definition = definitionOf(governing(collection.composition, path), document.type);
191
219
  for (const { value, to } of definition === undefined ? [] : references(document, definition)) {
192
220
  if (to.includes(ATTACHMENT))
@@ -195,6 +223,7 @@ function incoming(collection, removed) {
195
223
  if (named !== null)
196
224
  note(named, path);
197
225
  }
226
+ yield ROW_WEIGHT + collection.text[path].length;
198
227
  }
199
228
  const [first] = [...found.keys()].sort();
200
229
  if (first === undefined)
@@ -217,10 +246,13 @@ function affected(change) {
217
246
  return change.kind === 'move' ? [change.path, change.to] : [change.path];
218
247
  }
219
248
  function guard(changes, input) {
220
- const existing = new Set([
221
- ...Object.keys(input.visible.documents),
222
- ...Object.keys(input.visible.binaries),
223
- ]);
249
+ const overridden = new Map();
250
+ const existing = {
251
+ has: (path) => overridden.get(path) ??
252
+ (Object.hasOwn(input.visible.documents, path) || Object.hasOwn(input.visible.binaries, path)),
253
+ add: (path) => void overridden.set(path, true),
254
+ delete: (path) => void overridden.set(path, false),
255
+ };
224
256
  for (const [index, change] of changes.entries()) {
225
257
  for (const path of affected(change)) {
226
258
  const normalized = normalize(path);
@@ -275,7 +307,7 @@ function guard(changes, input) {
275
307
  continue;
276
308
  }
277
309
  if (change.kind === 'replace') {
278
- if (!input.local && input.visible.revisions[change.path] === undefined) {
310
+ if (unrevised(input, change.path)) {
279
311
  return refuse('unknown-revision', change.path);
280
312
  }
281
313
  continue;
@@ -289,6 +321,22 @@ function guard(changes, input) {
289
321
  function unrevised(input, path) {
290
322
  return (!input.local && input.queued?.has(path) !== true && input.visible.revisions[path] === undefined);
291
323
  }
324
+ export function queuedDocuments(queue) {
325
+ const paths = new Set();
326
+ for (const batch of queue) {
327
+ for (const change of batch.changes) {
328
+ if (change.kind === 'binary')
329
+ continue;
330
+ if (change.kind === 'remove')
331
+ paths.delete(change.path);
332
+ else if (change.kind !== 'move')
333
+ paths.add(change.path);
334
+ else if (paths.delete(change.path))
335
+ paths.add(change.to);
336
+ }
337
+ }
338
+ return paths;
339
+ }
292
340
  function identity(precondition) {
293
341
  const part = precondition.kind === 'field' || precondition.kind === 'section' ? precondition.name : '';
294
342
  return `${precondition.kind} ${precondition.path} ${part}`;
@@ -364,8 +412,8 @@ function preconditionsOf(changes, visible, bases) {
364
412
  function depth(path) {
365
413
  return path.split('/').length;
366
414
  }
367
- function exceeded(limits, changes, resulting) {
368
- const written = changes.map((change) => (change.kind === 'move' ? change.to : change.path));
415
+ function exceeded(limits, changes, effective, resulting) {
416
+ const written = effective.map((change) => (change.kind === 'move' ? change.to : change.path));
369
417
  const created = changes
370
418
  .filter((change) => change.kind === 'create' || change.kind === 'move' || change.kind === 'binary')
371
419
  .map((change) => (change.kind === 'move' ? change.to : change.path));
@@ -381,7 +429,7 @@ function exceeded(limits, changes, resulting) {
381
429
  return refuse('provider-limit', undefined, limit.name);
382
430
  }
383
431
  if (limit.name === 'document-size') {
384
- const large = written.find((path) => (resulting.documents[path] ?? '').length > value);
432
+ const large = written.find((path) => new TextEncoder().encode(resulting.documents[path] ?? '').byteLength > value);
385
433
  if (large !== undefined)
386
434
  return refuse('provider-limit', large, limit.name);
387
435
  }
@@ -413,7 +461,7 @@ function relativeField(path, name, value, handle, definition) {
413
461
  !opened.ok ||
414
462
  !JSON.stringify(value ?? null).includes(`/rooms/${handle}/`))
415
463
  return value;
416
- const held = apply(opened.document, { kind: 'field', name, value, prior: undefined });
464
+ const held = apply(opened.document, [{ kind: 'field', name, value, prior: undefined }]);
417
465
  if (held.outcome !== 'applied')
418
466
  return value;
419
467
  const result = relativize(held.document, path, handle, definition);
@@ -449,12 +497,15 @@ function relativeChanges(input) {
449
497
  return { ...change, fields, sections };
450
498
  });
451
499
  }
452
- function unmodeledType(collection, composition) {
500
+ function* unmodeledType(collection, composition) {
501
+ if (available(composition))
502
+ return false;
453
503
  for (const [path, document] of documentsOf(collection)) {
454
504
  if (document.type !== undefined &&
455
505
  document.type !== 'any' &&
456
506
  governing(composition, path).status === 'unavailable')
457
507
  return true;
508
+ yield ROW_WEIGHT + collection.text[path].length;
458
509
  }
459
510
  return false;
460
511
  }
@@ -467,29 +518,44 @@ function isPart(change) {
467
518
  function touched(change) {
468
519
  return change.kind === 'move' ? [change.path, change.to] : [change.path];
469
520
  }
470
- function partApplied(content, path, change) {
521
+ function partsApplied(content, path, changes) {
471
522
  const parsed = parse(content, path);
472
523
  if (!parsed.ok)
473
524
  return null;
474
525
  const document = parsed.document;
475
- const applied = apply(document, change.kind === 'field'
476
- ? {
477
- kind: 'field',
478
- name: change.name,
479
- value: change.value,
480
- prior: document.fields[change.name],
481
- }
482
- : change.kind === 'section'
483
- ? {
526
+ const parts = new Map();
527
+ for (const change of changes) {
528
+ if (change.kind === 'field')
529
+ parts.set(`field ${change.name}`, {
530
+ kind: 'field',
531
+ name: change.name,
532
+ value: change.value,
533
+ prior: document.fields[change.name],
534
+ });
535
+ else if (change.kind === 'section')
536
+ parts.set(`section ${change.name}`, {
484
537
  kind: 'section',
485
538
  name: change.name,
486
539
  value: change.value,
487
- prior: document.sections[change.name],
488
- }
489
- : { kind: 'preamble', value: change.value, prior: document.preamble });
540
+ prior: document.sections[change.name] ?? '',
541
+ });
542
+ else
543
+ parts.set('preamble', { kind: 'preamble', value: change.value, prior: document.preamble });
544
+ }
545
+ const applied = apply(document, [...parts.values()]);
490
546
  return applied.outcome === 'applied' ? serialize(applied.document) : null;
491
547
  }
492
- function folded(changes, change, appending) {
548
+ function settledParts(changes, deferred) {
549
+ for (const [held, parts] of deferred) {
550
+ const content = partsApplied(held.content, held.path, parts);
551
+ if (content === null)
552
+ return held.path;
553
+ changes[changes.indexOf(held)] = { ...held, content };
554
+ }
555
+ deferred.clear();
556
+ return null;
557
+ }
558
+ function folded(changes, change, appending, deferred) {
493
559
  const held = changes.find((item) => item.path === change.path && (item.kind === 'create' || item.kind === 'replace'));
494
560
  const whole = held === undefined ? -1 : changes.indexOf(held);
495
561
  const occupied = changes.some((item) => !isPart(item) && item !== held && touched(item).includes(change.path));
@@ -510,10 +576,11 @@ function folded(changes, change, appending) {
510
576
  return 'appended';
511
577
  }
512
578
  if ('content' in held) {
513
- const content = partApplied(held.content, held.path, change);
514
- if (content === null)
515
- return 'refused';
516
- changes[whole] = { ...held, content };
579
+ const parts = deferred.get(held);
580
+ if (parts === undefined)
581
+ deferred.set(held, [change]);
582
+ else
583
+ parts.push(change);
517
584
  return 'folded';
518
585
  }
519
586
  if (change.kind === 'preamble')
@@ -551,10 +618,14 @@ function relinked(batch, move, before, after, appending) {
551
618
  const changes = [...batch.changes];
552
619
  const appended = [];
553
620
  let changed = false;
621
+ const deferred = new Map();
554
622
  for (const change of derived.changes) {
555
623
  if (change === move)
556
624
  continue;
557
- const outcome = folded(changes, change, appending);
625
+ const unsettled = isPart(change) ? null : settledParts(changes, deferred);
626
+ if (unsettled !== null)
627
+ return unqueueable(unsettled);
628
+ const outcome = folded(changes, change, appending, deferred);
558
629
  if (outcome === 'refused')
559
630
  return unqueueable(change.path);
560
631
  if (outcome === 'appended')
@@ -562,6 +633,9 @@ function relinked(batch, move, before, after, appending) {
562
633
  if (outcome !== 'skipped')
563
634
  changed = true;
564
635
  }
636
+ const unsettled = settledParts(changes, deferred);
637
+ if (unsettled !== null)
638
+ return unqueueable(unsettled);
565
639
  if (!changed)
566
640
  return { kind: 'relinked', batch };
567
641
  const held = new Set(batch.preconditions.map(identity));
@@ -695,10 +769,17 @@ export function joined(queue, owner, extra) {
695
769
  if (clash !== undefined)
696
770
  return unqueueable(clash);
697
771
  const changes = [...owner.changes];
772
+ const deferred = new Map();
698
773
  for (const change of extra.changes) {
699
- if (folded(changes, change, true) === 'refused')
774
+ const unsettled = isPart(change) ? null : settledParts(changes, deferred);
775
+ if (unsettled !== null)
776
+ return unqueueable(unsettled);
777
+ if (folded(changes, change, true, deferred) === 'refused')
700
778
  return unqueueable(change.path);
701
779
  }
780
+ const unsettled = settledParts(changes, deferred);
781
+ if (unsettled !== null)
782
+ return unqueueable(unsettled);
702
783
  const held = new Set(owner.preconditions.map(covering));
703
784
  const written = new Set(owner.changes.flatMap((change) => change.kind === 'create' || change.kind === 'replace' ? [change.path] : []));
704
785
  const preconditions = [
@@ -718,13 +799,15 @@ export function joined(queue, owner, extra) {
718
799
  return { kind: 'joined', batch, queue: queue.map((item) => (item === owner ? batch : item)) };
719
800
  }
720
801
  export function limitedIn(queue, batch, limits, state) {
721
- const limited = exceeded(limits, batch.changes, state(queue.slice(0, queue.indexOf(batch) + 1)));
802
+ const at = queue.indexOf(batch);
803
+ const limited = exceeded(limits, batch.changes, providerRewritten(batch, state(queue.slice(0, at))).changes, state(queue.slice(0, at + 1)));
722
804
  return limited?.kind === 'refused' ? limited.refusal : null;
723
805
  }
724
- export function buildBatch(input) {
806
+ function* batching(input) {
725
807
  const changes = relativeChanges(input);
726
808
  const structural = changes.find((change) => change.kind === 'move' || change.kind === 'remove');
727
- if (structural !== undefined && unmodeledType(input.visible.collection, input.composition))
809
+ if (structural !== undefined &&
810
+ (yield* unmodeledType(input.visible.collection, input.composition)))
728
811
  return refuse('model-unavailable', structural.path);
729
812
  if (changes.length === 0)
730
813
  return refuse('no-change');
@@ -739,9 +822,13 @@ export function buildBatch(input) {
739
822
  const resulting = overlay(input.visible, [
740
823
  { id: '', baseRoomVersion: input.baseRoomVersion, ...predicted },
741
824
  ]);
825
+ const clean = input.clean !== undefined && available(input.composition) ? input.clean : null;
742
826
  const removed = new Set(changes.filter((change) => change.kind === 'remove').map((change) => change.path));
743
827
  if (removed.size > 0) {
744
- const referenced = incoming(collectionOf(resulting.documents, input.composition), removed);
828
+ const referrers = clean === null ? null : referring(clean, input.composition, removed);
829
+ const referenced = yield* incoming(collectionOf(resulting.documents, input.composition), removed, clean === null || referrers === null
830
+ ? null
831
+ : [...referrers, ...(yield* differences(clean.text, resulting.documents))]);
745
832
  if (referenced !== null)
746
833
  return referenced;
747
834
  }
@@ -751,15 +838,20 @@ export function buildBatch(input) {
751
838
  const parsed = parse(content);
752
839
  return parsed.ok && parsed.document.type !== undefined && parsed.document.type !== 'any';
753
840
  };
754
- const typedPaths = [...new Set(predicted.changes.flatMap(affected))].filter((path) => typed(input.visible.documents[path]) || typed(resulting.documents[path]));
841
+ const touched = [...new Set(predicted.changes.flatMap(affected))];
842
+ const typedPaths = touched.filter((path) => typed(input.visible.documents[path]) || typed(resulting.documents[path]));
755
843
  const needsModel = typedPaths.length > 0;
756
844
  const withoutModel = typedPaths.find((path) => governing(input.composition, path).status === 'unavailable');
757
845
  if (withoutModel !== undefined)
758
846
  return refuse('model-unavailable', withoutModel);
759
- const validationText = needsModel
760
- ? resulting.documents
761
- : Object.fromEntries(Object.entries(resulting.documents).filter(([path]) => predicted.changes.some((change) => affected(change).includes(path))));
762
- const verdict = validateCollection(validationText, Object.keys(resulting.binaries), input.composition);
847
+ const verdict = clean !== null &&
848
+ (yield* changedCleanly({ text: resulting.documents, binaries: resulting.binaries }, clean, input.composition))
849
+ ? { verdict: 'accept' }
850
+ : yield* validateCollection(needsModel
851
+ ? resulting.documents
852
+ : Object.fromEntries(touched.flatMap((path) => resulting.documents[path] === undefined
853
+ ? []
854
+ : [[path, resulting.documents[path]]])), Object.keys(resulting.binaries), input.composition);
763
855
  if (verdict.verdict === 'refuse') {
764
856
  return {
765
857
  kind: 'refused',
@@ -772,7 +864,7 @@ export function buildBatch(input) {
772
864
  },
773
865
  };
774
866
  }
775
- const limited = exceeded(input.providerLimits, changes, resulting);
867
+ const limited = exceeded(input.providerLimits, changes, predicted.changes, resulting);
776
868
  if (limited !== null)
777
869
  return limited;
778
870
  const validated = typedPaths
@@ -798,3 +890,6 @@ export function buildBatch(input) {
798
890
  }),
799
891
  };
800
892
  }
893
+ export function buildBatch(input) {
894
+ return stepped(batching(input));
895
+ }
package/dist/search.d.ts CHANGED
@@ -1,12 +1,16 @@
1
+ import type { ProviderRefusal } from './adapter.js';
1
2
  import type { ChangeSet } from './change-set.js';
2
- import { type Filter } from './query.js';
3
+ import { type CoveredRoom, type Filter, type PendingRoom } from './query.js';
3
4
  import type { Open } from './open.js';
4
5
  export type DocumentPart = Open<'fields' | 'sections' | 'preamble' | 'path'>;
5
6
  export type SearchRequest = {
6
7
  text: string;
7
8
  documents?: Filter;
9
+ collection?: true;
8
10
  conversations?: readonly string[];
9
11
  limit?: number;
12
+ after?: string;
13
+ total?: true;
10
14
  };
11
15
  export type DocumentHit = {
12
16
  room: string;
@@ -21,10 +25,38 @@ export type MessageHit = {
21
25
  score: number;
22
26
  matches: Readonly<Record<string, readonly Open<'text'>[]>>;
23
27
  };
24
- export type SearchResult = {
28
+ export type SearchCoverage = {
29
+ rooms: readonly CoveredRoom[];
30
+ conversations: readonly string[];
31
+ index: string;
32
+ overlay: readonly string[];
33
+ };
34
+ export type PendingConversation = {
35
+ conversation: string;
36
+ awaits: Open<'index'>;
37
+ };
38
+ export type SearchHits = {
25
39
  documents: readonly DocumentHit[];
26
40
  messages: readonly MessageHit[];
27
41
  };
42
+ export type SearchWindow = SearchHits & {
43
+ next?: string;
44
+ total?: {
45
+ documents: number;
46
+ messages: number;
47
+ };
48
+ };
49
+ export type SearchPending = SearchHits & {
50
+ pending: readonly (PendingRoom | PendingConversation)[];
51
+ coverage: SearchCoverage;
52
+ };
53
+ export type SearchUndeclared = ProviderRefusal & {
54
+ kind: 'undeclared';
55
+ };
56
+ export type SearchResult = (SearchWindow & {
57
+ coverage: SearchCoverage;
58
+ }) | SearchPending | SearchUndeclared;
59
+ export declare function undeclaredSearch(): SearchUndeclared;
28
60
  export type SearchedDocument = {
29
61
  room: string;
30
62
  path: string;
@@ -39,24 +71,35 @@ export type SearchedMessage = {
39
71
  text: string;
40
72
  };
41
73
  export type SearchSource = {
42
- documents(): readonly SearchedDocument[];
74
+ room(room: string): readonly string[];
43
75
  document(room: string, path: string): SearchedDocument | null;
44
- messages(): readonly SearchedMessage[];
45
- message(conversation: string, identity: string): SearchedMessage | null;
46
76
  };
77
+ type HitCursor = readonly [number, string, string] | readonly [] | null;
47
78
  export type SearchPlan = {
48
79
  text: string;
49
80
  documents: unknown;
81
+ collection: boolean;
50
82
  conversations: readonly string[] | null;
51
83
  limit: number | null;
84
+ after: readonly [HitCursor, HitCursor] | null;
85
+ total: boolean;
52
86
  };
53
87
  export type SearchIndex = {
88
+ generation(): string;
89
+ rooms(): ReadonlySet<string>;
90
+ conversations(): ReadonlySet<string>;
91
+ indexRoom(room: string): Promise<void>;
92
+ indexMessages(conversation: string, messages: readonly SearchedMessage[], whole: boolean): void;
93
+ forget(rooms: readonly string[]): void;
54
94
  changed(set: ChangeSet): void;
95
+ changes(): number;
96
+ caughtUp(): Promise<void>;
55
97
  search(plan: SearchPlan, documents: readonly {
56
98
  room: string;
57
99
  path: string;
58
- }[] | null): SearchResult;
100
+ }[] | null, conversations: readonly string[], rooms: ReadonlySet<string> | null, selections: ReadonlyMap<string, readonly string[]> | null): SearchWindow;
59
101
  };
60
102
  export declare function searchPlanOf(input: unknown): SearchPlan;
61
103
  export declare function createSearchIndex(source: SearchSource): SearchIndex;
104
+ export {};
62
105
  //# sourceMappingURL=search.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}