@agentshouse/mdruntime 0.1.0-c97456d63baba → 0.1.0-c9b1e59e5baeb
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.
- package/AGENTS.md +221 -221
- package/README.md +8 -8
- package/dist/adapter.d.ts +35 -6
- package/dist/adapter.d.ts.map +1 -1
- package/dist/bootstrap.d.ts +2 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +5 -1
- package/dist/change-set.d.ts +5 -2
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +8 -2
- package/dist/chat/earlier.d.ts +10 -0
- package/dist/chat/earlier.d.ts.map +1 -0
- package/dist/chat/earlier.js +54 -0
- package/dist/chat/kit.js +1 -1
- package/dist/chat/list.d.ts +2 -1
- package/dist/chat/list.d.ts.map +1 -1
- package/dist/chat/list.js +40 -4
- package/dist/chat/markdown.d.ts +1 -0
- package/dist/chat/markdown.d.ts.map +1 -1
- package/dist/chat/markdown.js +78 -20
- package/dist/chat/message.d.ts.map +1 -1
- package/dist/chat/message.js +9 -2
- package/dist/chat/messages.d.ts.map +1 -1
- package/dist/chat/messages.js +36 -16
- package/dist/chat/overlay.d.ts +1 -0
- package/dist/chat/overlay.d.ts.map +1 -1
- package/dist/chat/overlay.js +10 -0
- package/dist/chat/pieces.d.ts +62 -0
- package/dist/chat/pieces.d.ts.map +1 -0
- package/dist/chat/pieces.js +1110 -0
- package/dist/chat/provider.d.ts +1 -0
- package/dist/chat/provider.d.ts.map +1 -1
- package/dist/chat/provider.js +22 -14
- package/dist/chat/question.d.ts +1 -1
- package/dist/chat/question.d.ts.map +1 -1
- package/dist/chat/question.js +7 -18
- package/dist/chat/ready.d.ts +1 -1
- package/dist/chat/ready.d.ts.map +1 -1
- package/dist/chat/ready.js +1 -1
- package/dist/chat/steady.d.ts +3 -0
- package/dist/chat/steady.d.ts.map +1 -0
- package/dist/chat/steady.js +26 -0
- package/dist/chat/style.js +1 -1
- package/dist/chat.d.ts +2 -2
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/client.d.ts +6 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +16 -5
- package/dist/collection.d.ts +4 -3
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +128 -63
- package/dist/connection.d.ts +13 -5
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +506 -228
- package/dist/conversation.d.ts +11 -0
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +195 -41
- package/dist/entry.d.ts.map +1 -1
- package/dist/entry.js +3 -2
- package/dist/host.d.ts +9 -7
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +58 -9
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/memory.d.ts +7 -3
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +24 -11
- package/dist/observation.d.ts +2 -0
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +9 -3
- package/dist/outcome.d.ts +8 -2
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +3 -0
- package/dist/overlay.d.ts +5 -4
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +197 -132
- package/dist/query.d.ts +27 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +36 -7
- package/dist/reach.d.ts +1 -2
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +17 -4
- package/dist/react.d.ts +3 -3
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +7 -17
- package/dist/read-side.d.ts +3 -1
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +256 -69
- package/dist/reads.d.ts +11 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +98 -0
- package/dist/refresh.d.ts +4 -4
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +39 -14
- package/dist/replica.d.ts +11 -5
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +79 -41
- package/dist/room-draft.d.ts +12 -0
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +11 -12
- package/dist/rows.d.ts +3 -1
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +8 -1
- package/dist/save.d.ts +4 -2
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +195 -111
- package/dist/search.d.ts +27 -6
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +89 -7
- package/dist/seed.d.ts +16 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +75 -0
- package/dist/shared.d.ts +4 -0
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +63 -33
- package/dist/store.d.ts +20 -4
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +404 -317
- package/dist/turn.d.ts +5 -3
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +26 -7
- package/dist/windows.d.ts +26 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +93 -0
- package/dist/wire.d.ts +16 -0
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +4 -0
- package/package.json +2 -2
- package/dist/acquisition.d.ts +0 -14
- package/dist/acquisition.d.ts.map +0 -1
- package/dist/acquisition.js +0 -24
package/dist/save.js
CHANGED
|
@@ -3,8 +3,10 @@ import { apply, ATTACHMENT, links, parse, pointerSegments, references, relative,
|
|
|
3
3
|
import { immutable, queuedFile, departure, } from './change.js';
|
|
4
4
|
import { available, changedCleanly, collectionOf, documentsOf, governing, referring, validateCollection, } from './collection.js';
|
|
5
5
|
import { changeBatchIdentity } from './identity.js';
|
|
6
|
-
import {
|
|
6
|
+
import { overlaying } from './overlay.js';
|
|
7
7
|
import { covered, normalize } from './paths.js';
|
|
8
|
+
import { differences } from './shared.js';
|
|
9
|
+
import { finished, 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
|
-
|
|
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
|
-
|
|
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,
|
|
49
|
-
|
|
53
|
+
function edited(document, changes) {
|
|
54
|
+
const parts = new Map();
|
|
50
55
|
for (const change of changes) {
|
|
51
|
-
if (change.
|
|
52
|
-
|
|
53
|
-
if (change.kind
|
|
54
|
-
|
|
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:
|
|
63
|
+
prior: document.sections[change.name] ?? '',
|
|
62
64
|
});
|
|
63
|
-
if (applied.outcome === 'applied')
|
|
64
|
-
next = applied.document;
|
|
65
65
|
}
|
|
66
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
111
|
-
|
|
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
|
-
function rewrites(changes, visible) {
|
|
119
|
+
function* rewrites(changes, visible) {
|
|
120
120
|
const moves = new Map();
|
|
121
121
|
const settled = new Set();
|
|
122
|
-
|
|
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,43 +149,57 @@ 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
|
|
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
|
-
|
|
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 =
|
|
154
|
-
|
|
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
|
}
|
|
178
|
+
yield ROW_WEIGHT + visible.collection.text[path].length;
|
|
161
179
|
}
|
|
162
|
-
return {
|
|
180
|
+
return {
|
|
181
|
+
kind: 'changes',
|
|
182
|
+
changes: [...added, ...merged.filter((change) => change !== null)],
|
|
183
|
+
};
|
|
163
184
|
}
|
|
164
|
-
function anticipated(changes, preconditions, rewritten, visible) {
|
|
165
|
-
const
|
|
185
|
+
function* anticipated(changes, preconditions, rewritten, visible) {
|
|
186
|
+
const given = new Set(changes);
|
|
187
|
+
const derived = rewritten.filter((change) => !given.has(change));
|
|
166
188
|
return {
|
|
167
189
|
changes: rewritten,
|
|
168
|
-
preconditions: [...preconditionsOf(derived, visible, []), ...preconditions],
|
|
190
|
+
preconditions: [...(yield* preconditionsOf(derived, visible, [])), ...preconditions],
|
|
169
191
|
};
|
|
170
192
|
}
|
|
171
|
-
export function providerRewritten(batch, visible) {
|
|
172
|
-
const rewritten = rewrites(batch.changes, visible);
|
|
193
|
+
export function* providerRewritten(batch, visible) {
|
|
194
|
+
const rewritten = yield* rewrites(batch.changes, visible);
|
|
173
195
|
if (rewritten.kind === 'refused')
|
|
174
196
|
return batch;
|
|
175
197
|
return {
|
|
176
198
|
...batch,
|
|
177
|
-
...anticipated(batch.changes, batch.preconditions, rewritten.changes, visible),
|
|
199
|
+
...(yield* anticipated(batch.changes, batch.preconditions, rewritten.changes, visible)),
|
|
178
200
|
};
|
|
179
201
|
}
|
|
180
|
-
function incoming(collection, removed, candidates) {
|
|
202
|
+
function* incoming(collection, removed, candidates) {
|
|
181
203
|
const found = new Map();
|
|
182
204
|
const note = (target, file) => {
|
|
183
205
|
if (!removed.has(target))
|
|
@@ -186,13 +208,14 @@ function incoming(collection, removed, candidates) {
|
|
|
186
208
|
referrers.add(file);
|
|
187
209
|
found.set(target, referrers);
|
|
188
210
|
};
|
|
189
|
-
const read =
|
|
190
|
-
|
|
191
|
-
: [...new Set(candidates)].sort().flatMap((path) => {
|
|
211
|
+
const read = function* (paths) {
|
|
212
|
+
for (const path of [...new Set(paths)].sort()) {
|
|
192
213
|
const document = collection.document(path);
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
214
|
+
if (document !== undefined)
|
|
215
|
+
yield [path, document];
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
for (const [path, document] of candidates === null ? documentsOf(collection) : read(candidates)) {
|
|
196
219
|
const definition = definitionOf(governing(collection.composition, path), document.type);
|
|
197
220
|
for (const { value, to } of definition === undefined ? [] : references(document, definition)) {
|
|
198
221
|
if (to.includes(ATTACHMENT))
|
|
@@ -201,6 +224,7 @@ function incoming(collection, removed, candidates) {
|
|
|
201
224
|
if (named !== null)
|
|
202
225
|
note(named, path);
|
|
203
226
|
}
|
|
227
|
+
yield ROW_WEIGHT + collection.text[path].length;
|
|
204
228
|
}
|
|
205
229
|
const [first] = [...found.keys()].sort();
|
|
206
230
|
if (first === undefined)
|
|
@@ -284,7 +308,7 @@ function guard(changes, input) {
|
|
|
284
308
|
continue;
|
|
285
309
|
}
|
|
286
310
|
if (change.kind === 'replace') {
|
|
287
|
-
if (
|
|
311
|
+
if (unrevised(input, change.path)) {
|
|
288
312
|
return refuse('unknown-revision', change.path);
|
|
289
313
|
}
|
|
290
314
|
continue;
|
|
@@ -298,6 +322,22 @@ function guard(changes, input) {
|
|
|
298
322
|
function unrevised(input, path) {
|
|
299
323
|
return (!input.local && input.queued?.has(path) !== true && input.visible.revisions[path] === undefined);
|
|
300
324
|
}
|
|
325
|
+
export function queuedDocuments(queue) {
|
|
326
|
+
const paths = new Set();
|
|
327
|
+
for (const batch of queue) {
|
|
328
|
+
for (const change of batch.changes) {
|
|
329
|
+
if (change.kind === 'binary')
|
|
330
|
+
continue;
|
|
331
|
+
if (change.kind === 'remove')
|
|
332
|
+
paths.delete(change.path);
|
|
333
|
+
else if (change.kind !== 'move')
|
|
334
|
+
paths.add(change.path);
|
|
335
|
+
else if (paths.delete(change.path))
|
|
336
|
+
paths.add(change.to);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return paths;
|
|
340
|
+
}
|
|
301
341
|
function identity(precondition) {
|
|
302
342
|
const part = precondition.kind === 'field' || precondition.kind === 'section' ? precondition.name : '';
|
|
303
343
|
return `${precondition.kind} ${precondition.path} ${part}`;
|
|
@@ -315,7 +355,7 @@ function sameTarget(precondition, change) {
|
|
|
315
355
|
return ((precondition.kind !== 'field' && precondition.kind !== 'section') ||
|
|
316
356
|
((change.kind === 'field' || change.kind === 'section') && precondition.name === change.name));
|
|
317
357
|
}
|
|
318
|
-
function preconditionsOf(changes, visible, bases) {
|
|
358
|
+
function* preconditionsOf(changes, visible, bases) {
|
|
319
359
|
const preconditions = [];
|
|
320
360
|
const seen = new Set();
|
|
321
361
|
const add = (precondition) => {
|
|
@@ -326,6 +366,7 @@ function preconditionsOf(changes, visible, bases) {
|
|
|
326
366
|
preconditions.push(precondition);
|
|
327
367
|
};
|
|
328
368
|
for (const change of changes) {
|
|
369
|
+
yield ROW_WEIGHT;
|
|
329
370
|
if (change.kind === 'field' || change.kind === 'section' || change.kind === 'preamble') {
|
|
330
371
|
const based = bases.find((base) => sameTarget(base, change));
|
|
331
372
|
if (based !== undefined) {
|
|
@@ -373,7 +414,7 @@ function preconditionsOf(changes, visible, bases) {
|
|
|
373
414
|
function depth(path) {
|
|
374
415
|
return path.split('/').length;
|
|
375
416
|
}
|
|
376
|
-
function
|
|
417
|
+
function* exceeding(limits, changes, effective, resulting) {
|
|
377
418
|
const written = effective.map((change) => (change.kind === 'move' ? change.to : change.path));
|
|
378
419
|
const created = changes
|
|
379
420
|
.filter((change) => change.kind === 'create' || change.kind === 'move' || change.kind === 'binary')
|
|
@@ -390,9 +431,13 @@ function exceeded(limits, changes, effective, resulting) {
|
|
|
390
431
|
return refuse('provider-limit', undefined, limit.name);
|
|
391
432
|
}
|
|
392
433
|
if (limit.name === 'document-size') {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
434
|
+
for (const path of written) {
|
|
435
|
+
const text = resulting.documents[path] ?? '';
|
|
436
|
+
if (new TextEncoder().encode(text).byteLength > value) {
|
|
437
|
+
return refuse('provider-limit', path, limit.name);
|
|
438
|
+
}
|
|
439
|
+
yield ROW_WEIGHT + text.length;
|
|
440
|
+
}
|
|
396
441
|
}
|
|
397
442
|
if (limit.name === 'path-length') {
|
|
398
443
|
const long = created.find((path) => path.length > value);
|
|
@@ -422,7 +467,7 @@ function relativeField(path, name, value, handle, definition) {
|
|
|
422
467
|
!opened.ok ||
|
|
423
468
|
!JSON.stringify(value ?? null).includes(`/rooms/${handle}/`))
|
|
424
469
|
return value;
|
|
425
|
-
const held = apply(opened.document, { kind: 'field', name, value, prior: undefined });
|
|
470
|
+
const held = apply(opened.document, [{ kind: 'field', name, value, prior: undefined }]);
|
|
426
471
|
if (held.outcome !== 'applied')
|
|
427
472
|
return value;
|
|
428
473
|
const result = relativize(held.document, path, handle, definition);
|
|
@@ -458,7 +503,7 @@ function relativeChanges(input) {
|
|
|
458
503
|
return { ...change, fields, sections };
|
|
459
504
|
});
|
|
460
505
|
}
|
|
461
|
-
function unmodeledType(collection, composition) {
|
|
506
|
+
function* unmodeledType(collection, composition) {
|
|
462
507
|
if (available(composition))
|
|
463
508
|
return false;
|
|
464
509
|
for (const [path, document] of documentsOf(collection)) {
|
|
@@ -466,6 +511,7 @@ function unmodeledType(collection, composition) {
|
|
|
466
511
|
document.type !== 'any' &&
|
|
467
512
|
governing(composition, path).status === 'unavailable')
|
|
468
513
|
return true;
|
|
514
|
+
yield ROW_WEIGHT + collection.text[path].length;
|
|
469
515
|
}
|
|
470
516
|
return false;
|
|
471
517
|
}
|
|
@@ -478,29 +524,44 @@ function isPart(change) {
|
|
|
478
524
|
function touched(change) {
|
|
479
525
|
return change.kind === 'move' ? [change.path, change.to] : [change.path];
|
|
480
526
|
}
|
|
481
|
-
function
|
|
527
|
+
function partsApplied(content, path, changes) {
|
|
482
528
|
const parsed = parse(content, path);
|
|
483
529
|
if (!parsed.ok)
|
|
484
530
|
return null;
|
|
485
531
|
const document = parsed.document;
|
|
486
|
-
const
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
532
|
+
const parts = new Map();
|
|
533
|
+
for (const change of changes) {
|
|
534
|
+
if (change.kind === 'field')
|
|
535
|
+
parts.set(`field ${change.name}`, {
|
|
536
|
+
kind: 'field',
|
|
537
|
+
name: change.name,
|
|
538
|
+
value: change.value,
|
|
539
|
+
prior: document.fields[change.name],
|
|
540
|
+
});
|
|
541
|
+
else if (change.kind === 'section')
|
|
542
|
+
parts.set(`section ${change.name}`, {
|
|
495
543
|
kind: 'section',
|
|
496
544
|
name: change.name,
|
|
497
545
|
value: change.value,
|
|
498
|
-
prior: document.sections[change.name],
|
|
499
|
-
}
|
|
500
|
-
|
|
546
|
+
prior: document.sections[change.name] ?? '',
|
|
547
|
+
});
|
|
548
|
+
else
|
|
549
|
+
parts.set('preamble', { kind: 'preamble', value: change.value, prior: document.preamble });
|
|
550
|
+
}
|
|
551
|
+
const applied = apply(document, [...parts.values()]);
|
|
501
552
|
return applied.outcome === 'applied' ? serialize(applied.document) : null;
|
|
502
553
|
}
|
|
503
|
-
function
|
|
554
|
+
function settledParts(changes, deferred) {
|
|
555
|
+
for (const [held, parts] of deferred) {
|
|
556
|
+
const content = partsApplied(held.content, held.path, parts);
|
|
557
|
+
if (content === null)
|
|
558
|
+
return held.path;
|
|
559
|
+
changes[changes.indexOf(held)] = { ...held, content };
|
|
560
|
+
}
|
|
561
|
+
deferred.clear();
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
function folded(changes, change, appending, deferred) {
|
|
504
565
|
const held = changes.find((item) => item.path === change.path && (item.kind === 'create' || item.kind === 'replace'));
|
|
505
566
|
const whole = held === undefined ? -1 : changes.indexOf(held);
|
|
506
567
|
const occupied = changes.some((item) => !isPart(item) && item !== held && touched(item).includes(change.path));
|
|
@@ -521,10 +582,11 @@ function folded(changes, change, appending) {
|
|
|
521
582
|
return 'appended';
|
|
522
583
|
}
|
|
523
584
|
if ('content' in held) {
|
|
524
|
-
const
|
|
525
|
-
if (
|
|
526
|
-
|
|
527
|
-
|
|
585
|
+
const parts = deferred.get(held);
|
|
586
|
+
if (parts === undefined)
|
|
587
|
+
deferred.set(held, [change]);
|
|
588
|
+
else
|
|
589
|
+
parts.push(change);
|
|
528
590
|
return 'folded';
|
|
529
591
|
}
|
|
530
592
|
if (change.kind === 'preamble')
|
|
@@ -556,16 +618,20 @@ function folded(changes, change, appending) {
|
|
|
556
618
|
return 'appended';
|
|
557
619
|
}
|
|
558
620
|
function relinked(batch, move, before, after, appending) {
|
|
559
|
-
const derived = rewrites([move], after);
|
|
621
|
+
const derived = finished(rewrites([move], after));
|
|
560
622
|
if (derived.kind === 'refused')
|
|
561
623
|
return derived;
|
|
562
624
|
const changes = [...batch.changes];
|
|
563
625
|
const appended = [];
|
|
564
626
|
let changed = false;
|
|
627
|
+
const deferred = new Map();
|
|
565
628
|
for (const change of derived.changes) {
|
|
566
629
|
if (change === move)
|
|
567
630
|
continue;
|
|
568
|
-
const
|
|
631
|
+
const unsettled = isPart(change) ? null : settledParts(changes, deferred);
|
|
632
|
+
if (unsettled !== null)
|
|
633
|
+
return unqueueable(unsettled);
|
|
634
|
+
const outcome = folded(changes, change, appending, deferred);
|
|
569
635
|
if (outcome === 'refused')
|
|
570
636
|
return unqueueable(change.path);
|
|
571
637
|
if (outcome === 'appended')
|
|
@@ -573,6 +639,9 @@ function relinked(batch, move, before, after, appending) {
|
|
|
573
639
|
if (outcome !== 'skipped')
|
|
574
640
|
changed = true;
|
|
575
641
|
}
|
|
642
|
+
const unsettled = settledParts(changes, deferred);
|
|
643
|
+
if (unsettled !== null)
|
|
644
|
+
return unqueueable(unsettled);
|
|
576
645
|
if (!changed)
|
|
577
646
|
return { kind: 'relinked', batch };
|
|
578
647
|
const held = new Set(batch.preconditions.map(identity));
|
|
@@ -584,7 +653,7 @@ function relinked(batch, move, before, after, appending) {
|
|
|
584
653
|
changes,
|
|
585
654
|
preconditions: [
|
|
586
655
|
...batch.preconditions,
|
|
587
|
-
...preconditionsOf(appended, before, []).filter((precondition) => !held.has(identity(precondition))),
|
|
656
|
+
...finished(preconditionsOf(appended, before, [])).filter((precondition) => !held.has(identity(precondition))),
|
|
588
657
|
],
|
|
589
658
|
}),
|
|
590
659
|
};
|
|
@@ -706,10 +775,17 @@ export function joined(queue, owner, extra) {
|
|
|
706
775
|
if (clash !== undefined)
|
|
707
776
|
return unqueueable(clash);
|
|
708
777
|
const changes = [...owner.changes];
|
|
778
|
+
const deferred = new Map();
|
|
709
779
|
for (const change of extra.changes) {
|
|
710
|
-
|
|
780
|
+
const unsettled = isPart(change) ? null : settledParts(changes, deferred);
|
|
781
|
+
if (unsettled !== null)
|
|
782
|
+
return unqueueable(unsettled);
|
|
783
|
+
if (folded(changes, change, true, deferred) === 'refused')
|
|
711
784
|
return unqueueable(change.path);
|
|
712
785
|
}
|
|
786
|
+
const unsettled = settledParts(changes, deferred);
|
|
787
|
+
if (unsettled !== null)
|
|
788
|
+
return unqueueable(unsettled);
|
|
713
789
|
const held = new Set(owner.preconditions.map(covering));
|
|
714
790
|
const written = new Set(owner.changes.flatMap((change) => change.kind === 'create' || change.kind === 'replace' ? [change.path] : []));
|
|
715
791
|
const preconditions = [
|
|
@@ -730,37 +806,35 @@ export function joined(queue, owner, extra) {
|
|
|
730
806
|
}
|
|
731
807
|
export function limitedIn(queue, batch, limits, state) {
|
|
732
808
|
const at = queue.indexOf(batch);
|
|
733
|
-
const limited =
|
|
809
|
+
const limited = finished(exceeding(limits, batch.changes, finished(providerRewritten(batch, state(queue.slice(0, at)))).changes, state(queue.slice(0, at + 1))));
|
|
734
810
|
return limited?.kind === 'refused' ? limited.refusal : null;
|
|
735
811
|
}
|
|
736
|
-
|
|
812
|
+
function* batching(input) {
|
|
737
813
|
const changes = relativeChanges(input);
|
|
738
814
|
const structural = changes.find((change) => change.kind === 'move' || change.kind === 'remove');
|
|
739
|
-
if (structural !== undefined &&
|
|
815
|
+
if (structural !== undefined &&
|
|
816
|
+
(yield* unmodeledType(input.visible.collection, input.composition)))
|
|
740
817
|
return refuse('model-unavailable', structural.path);
|
|
741
818
|
if (changes.length === 0)
|
|
742
819
|
return refuse('no-change');
|
|
743
|
-
const rewritten = rewrites(changes, input.visible);
|
|
820
|
+
const rewritten = yield* rewrites(changes, input.visible);
|
|
744
821
|
if (rewritten.kind === 'refused')
|
|
745
822
|
return rewritten;
|
|
746
823
|
const refusal = guard(changes, input);
|
|
747
824
|
if (refusal !== null)
|
|
748
825
|
return refusal;
|
|
749
|
-
const preconditions = preconditionsOf(changes, input.visible, input.bases);
|
|
750
|
-
const predicted = anticipated(changes, preconditions, rewritten.changes, input.visible);
|
|
751
|
-
const resulting =
|
|
826
|
+
const preconditions = yield* preconditionsOf(changes, input.visible, input.bases);
|
|
827
|
+
const predicted = yield* anticipated(changes, preconditions, rewritten.changes, input.visible);
|
|
828
|
+
const resulting = yield* overlaying(input.visible, [
|
|
752
829
|
{ id: '', baseRoomVersion: input.baseRoomVersion, ...predicted },
|
|
753
830
|
]);
|
|
754
|
-
const clean = input.clean !== undefined &&
|
|
755
|
-
input.clean.text === input.visible.documents &&
|
|
756
|
-
input.clean.binaries === input.visible.binaries &&
|
|
757
|
-
available(input.composition)
|
|
758
|
-
? input.clean
|
|
759
|
-
: null;
|
|
831
|
+
const clean = input.clean !== undefined && available(input.composition) ? input.clean : null;
|
|
760
832
|
const removed = new Set(changes.filter((change) => change.kind === 'remove').map((change) => change.path));
|
|
761
833
|
if (removed.size > 0) {
|
|
762
834
|
const referrers = clean === null ? null : referring(clean, input.composition, removed);
|
|
763
|
-
const referenced = incoming(collectionOf(resulting.documents, input.composition), removed,
|
|
835
|
+
const referenced = yield* incoming(collectionOf(resulting.documents, input.composition), removed, clean === null || referrers === null
|
|
836
|
+
? null
|
|
837
|
+
: [...referrers, ...(yield* differences(clean.text, resulting.documents))]);
|
|
764
838
|
if (referenced !== null)
|
|
765
839
|
return referenced;
|
|
766
840
|
}
|
|
@@ -771,15 +845,22 @@ export function buildBatch(input) {
|
|
|
771
845
|
return parsed.ok && parsed.document.type !== undefined && parsed.document.type !== 'any';
|
|
772
846
|
};
|
|
773
847
|
const touched = [...new Set(predicted.changes.flatMap(affected))];
|
|
774
|
-
const typedPaths =
|
|
848
|
+
const typedPaths = [];
|
|
849
|
+
for (const path of touched) {
|
|
850
|
+
const before = input.visible.documents[path];
|
|
851
|
+
const after = resulting.documents[path];
|
|
852
|
+
if (typed(before) || typed(after))
|
|
853
|
+
typedPaths.push(path);
|
|
854
|
+
yield ROW_WEIGHT + (before?.length ?? 0) + (after?.length ?? 0);
|
|
855
|
+
}
|
|
775
856
|
const needsModel = typedPaths.length > 0;
|
|
776
857
|
const withoutModel = typedPaths.find((path) => governing(input.composition, path).status === 'unavailable');
|
|
777
858
|
if (withoutModel !== undefined)
|
|
778
859
|
return refuse('model-unavailable', withoutModel);
|
|
779
860
|
const verdict = clean !== null &&
|
|
780
|
-
changedCleanly({ text: resulting.documents, binaries: resulting.binaries }, clean, input.composition)
|
|
861
|
+
(yield* changedCleanly({ text: resulting.documents, binaries: resulting.binaries }, clean, input.composition))
|
|
781
862
|
? { verdict: 'accept' }
|
|
782
|
-
: validateCollection(needsModel
|
|
863
|
+
: yield* validateCollection(needsModel
|
|
783
864
|
? resulting.documents
|
|
784
865
|
: Object.fromEntries(touched.flatMap((path) => resulting.documents[path] === undefined
|
|
785
866
|
? []
|
|
@@ -796,7 +877,7 @@ export function buildBatch(input) {
|
|
|
796
877
|
},
|
|
797
878
|
};
|
|
798
879
|
}
|
|
799
|
-
const limited =
|
|
880
|
+
const limited = yield* exceeding(input.providerLimits, changes, predicted.changes, resulting);
|
|
800
881
|
if (limited !== null)
|
|
801
882
|
return limited;
|
|
802
883
|
const validated = typedPaths
|
|
@@ -822,3 +903,6 @@ export function buildBatch(input) {
|
|
|
822
903
|
}),
|
|
823
904
|
};
|
|
824
905
|
}
|
|
906
|
+
export function buildBatch(input) {
|
|
907
|
+
return stepped(batching(input));
|
|
908
|
+
}
|
package/dist/search.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ProviderRefusal } from './adapter.js';
|
|
1
2
|
import type { ChangeSet } from './change-set.js';
|
|
2
3
|
import { type CoveredRoom, type Filter, type PendingRoom } from './query.js';
|
|
3
4
|
import type { Open } from './open.js';
|
|
@@ -5,8 +6,11 @@ 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;
|
|
@@ -31,16 +35,28 @@ export type PendingConversation = {
|
|
|
31
35
|
conversation: string;
|
|
32
36
|
awaits: Open<'index'>;
|
|
33
37
|
};
|
|
34
|
-
export type SearchPending = {
|
|
35
|
-
pending: readonly (PendingRoom | PendingConversation)[];
|
|
36
|
-
};
|
|
37
38
|
export type SearchHits = {
|
|
38
39
|
documents: readonly DocumentHit[];
|
|
39
40
|
messages: readonly MessageHit[];
|
|
40
41
|
};
|
|
41
|
-
export type
|
|
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 & {
|
|
42
57
|
coverage: SearchCoverage;
|
|
43
|
-
}) | SearchPending;
|
|
58
|
+
}) | SearchPending | SearchUndeclared;
|
|
59
|
+
export declare function undeclaredSearch(): SearchUndeclared;
|
|
44
60
|
export type SearchedDocument = {
|
|
45
61
|
room: string;
|
|
46
62
|
path: string;
|
|
@@ -58,11 +74,15 @@ export type SearchSource = {
|
|
|
58
74
|
room(room: string): readonly string[];
|
|
59
75
|
document(room: string, path: string): SearchedDocument | null;
|
|
60
76
|
};
|
|
77
|
+
type HitCursor = readonly [number, string, string] | readonly [] | null;
|
|
61
78
|
export type SearchPlan = {
|
|
62
79
|
text: string;
|
|
63
80
|
documents: unknown;
|
|
81
|
+
collection: boolean;
|
|
64
82
|
conversations: readonly string[] | null;
|
|
65
83
|
limit: number | null;
|
|
84
|
+
after: readonly [HitCursor, HitCursor] | null;
|
|
85
|
+
total: boolean;
|
|
66
86
|
};
|
|
67
87
|
export type SearchIndex = {
|
|
68
88
|
generation(): string;
|
|
@@ -77,8 +97,9 @@ export type SearchIndex = {
|
|
|
77
97
|
search(plan: SearchPlan, documents: readonly {
|
|
78
98
|
room: string;
|
|
79
99
|
path: string;
|
|
80
|
-
}[] | null, conversations: readonly string[]):
|
|
100
|
+
}[] | null, conversations: readonly string[], rooms: ReadonlySet<string> | null, selections: ReadonlyMap<string, readonly string[]> | null): SearchWindow;
|
|
81
101
|
};
|
|
82
102
|
export declare function searchPlanOf(input: unknown): SearchPlan;
|
|
83
103
|
export declare function createSearchIndex(source: SearchSource): SearchIndex;
|
|
104
|
+
export {};
|
|
84
105
|
//# sourceMappingURL=search.d.ts.map
|