@agentshouse/mdruntime-adapter 0.1.0-cd59fd8945dcb → 0.1.0-cd673d02b6e50
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/README.md +2 -2
- package/dist/actions.d.ts +13 -7
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +37 -114
- package/dist/adapter.d.ts +1 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +330 -130
- package/dist/app-reference.d.ts +2 -0
- package/dist/app-reference.d.ts.map +1 -0
- package/dist/app-reference.js +2 -0
- package/dist/crockford.d.ts +4 -0
- package/dist/crockford.d.ts.map +1 -0
- package/dist/crockford.js +3 -0
- package/dist/discovery.d.ts +7 -10
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +44 -36
- package/dist/gather.d.ts +1 -2
- package/dist/gather.d.ts.map +1 -1
- package/dist/gather.js +5 -15
- package/dist/house-model.d.ts +2 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +486 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/model.d.ts +5 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +10 -15
- package/dist/part.d.ts +14 -0
- package/dist/part.d.ts.map +1 -0
- package/dist/part.js +90 -0
- package/dist/read.d.ts +72 -23
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +352 -150
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +2 -1
- package/dist/room-stream.d.ts +19 -0
- package/dist/room-stream.d.ts.map +1 -0
- package/dist/room-stream.js +57 -0
- package/dist/room-types.d.ts +7 -0
- package/dist/room-types.d.ts.map +1 -0
- package/dist/room-types.js +125 -0
- package/dist/site.d.ts +1 -1
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +123 -61
- package/dist/stream.d.ts +5 -4
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +356 -43
- package/dist/transport.d.ts +71 -8
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +4 -0
- package/dist/upload.d.ts +12 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +63 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/write.d.ts +17 -9
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +138 -40
- package/package.json +8 -5
- package/AGENTS.md +0 -290
- package/dist/links.d.ts +0 -20
- package/dist/links.d.ts.map +0 -1
- package/dist/links.js +0 -104
package/dist/stream.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { ROW_WEIGHT, } from '@agentshouse/mdruntime';
|
|
1
2
|
import { acceptedMessage } from './actions.js';
|
|
2
|
-
import {
|
|
3
|
+
import { sha256Hex } from './digest.js';
|
|
4
|
+
import { answered, answering, binaryFileOf, folded, forgotten, headChange, revised, } from './read.js';
|
|
3
5
|
import { roomVersion } from './version.js';
|
|
4
6
|
const HELD_FRAMES_MAX = 256;
|
|
5
7
|
function turnOperation(frame) {
|
|
@@ -14,6 +16,7 @@ function listedConversation(listed) {
|
|
|
14
16
|
created: listed.created_at,
|
|
15
17
|
finished: listed.finished_at,
|
|
16
18
|
outcome: listed.outcome,
|
|
19
|
+
waiting: listed.waiting,
|
|
17
20
|
};
|
|
18
21
|
}
|
|
19
22
|
function position(value) {
|
|
@@ -21,9 +24,78 @@ function position(value) {
|
|
|
21
24
|
return null;
|
|
22
25
|
return BigInt(value);
|
|
23
26
|
}
|
|
27
|
+
function assembled(entries) {
|
|
28
|
+
const whole = [];
|
|
29
|
+
let open = null;
|
|
30
|
+
for (const entry of entries) {
|
|
31
|
+
if (entry.kind === 'piece') {
|
|
32
|
+
if (open === null || open.entry.path !== entry.path || entry.text === undefined)
|
|
33
|
+
return null;
|
|
34
|
+
open.texts.push(entry.text);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (open !== null)
|
|
38
|
+
return null;
|
|
39
|
+
if (entry.continued !== true) {
|
|
40
|
+
whole.push(entry);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (entry.text === undefined)
|
|
44
|
+
return null;
|
|
45
|
+
open = { entry, texts: [entry.text] };
|
|
46
|
+
}
|
|
47
|
+
if (entry.continued === true)
|
|
48
|
+
continue;
|
|
49
|
+
const { continued: _continued, ...head } = open.entry;
|
|
50
|
+
whole.push({ ...head, text: open.texts.join('') });
|
|
51
|
+
open = null;
|
|
52
|
+
}
|
|
53
|
+
return open === null ? whole : null;
|
|
54
|
+
}
|
|
55
|
+
async function verified(entries) {
|
|
56
|
+
try {
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
if (entry.text === undefined || entry.sha256 === undefined)
|
|
59
|
+
continue;
|
|
60
|
+
if ((await sha256Hex(entry.text)) !== entry.sha256)
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function resumed(kept, frame) {
|
|
70
|
+
const last = frame.entries.at(-1);
|
|
71
|
+
const point = { parts: frame.index + 1, from: frame.from, target: frame.target };
|
|
72
|
+
if (last?.continued !== true)
|
|
73
|
+
return { ...point, handled: frame.handled, piece: null };
|
|
74
|
+
const text = last.text?.length ?? 0;
|
|
75
|
+
if (last.kind !== 'piece') {
|
|
76
|
+
return last.sha256 === undefined
|
|
77
|
+
? kept.resume
|
|
78
|
+
: { ...point, handled: frame.handled, piece: { sha256: last.sha256, offset: text } };
|
|
79
|
+
}
|
|
80
|
+
const piece = kept.resume?.piece ?? null;
|
|
81
|
+
if (piece === null)
|
|
82
|
+
return kept.resume;
|
|
83
|
+
const pieces = frame.entries.reduce((sum, entry) => sum + (entry.kind === 'piece' ? (entry.text?.length ?? 0) : 0), 0);
|
|
84
|
+
return {
|
|
85
|
+
...point,
|
|
86
|
+
handled: frame.handled,
|
|
87
|
+
piece: { sha256: piece.sha256, offset: piece.offset + pieces },
|
|
88
|
+
};
|
|
89
|
+
}
|
|
24
90
|
export function houseNotifications(transport, mode) {
|
|
25
91
|
const stream = transport.stream;
|
|
26
92
|
const lines = new Map();
|
|
93
|
+
const kept = new Map();
|
|
94
|
+
let receipts = null;
|
|
95
|
+
let loaded = Promise.resolve();
|
|
96
|
+
let acknowledging = null;
|
|
97
|
+
let receiving = Promise.resolve();
|
|
98
|
+
let verifying = 0;
|
|
27
99
|
const locators = new Map();
|
|
28
100
|
const observers = new Set();
|
|
29
101
|
const conversationObservers = new Set();
|
|
@@ -41,7 +113,10 @@ export function houseNotifications(transport, mode) {
|
|
|
41
113
|
event.kind === 'questions' ||
|
|
42
114
|
event.kind === 'process' ||
|
|
43
115
|
event.kind === 'commands' ||
|
|
44
|
-
event.kind === 'options'
|
|
116
|
+
event.kind === 'options' ||
|
|
117
|
+
event.kind === 'starting' ||
|
|
118
|
+
event.kind === 'link' ||
|
|
119
|
+
event.kind === 'deliveries') {
|
|
45
120
|
live.add(event.conversation);
|
|
46
121
|
}
|
|
47
122
|
for (const observer of conversationObservers)
|
|
@@ -49,6 +124,7 @@ export function houseNotifications(transport, mode) {
|
|
|
49
124
|
}
|
|
50
125
|
function reopened(next) {
|
|
51
126
|
opening = next;
|
|
127
|
+
acknowledging = next;
|
|
52
128
|
const gapped = new Set([...replicated, ...live]);
|
|
53
129
|
live.clear();
|
|
54
130
|
for (const conversation of gapped)
|
|
@@ -86,6 +162,18 @@ export function houseNotifications(transport, mode) {
|
|
|
86
162
|
emitConversation({ kind: 'options', conversation, options: structuredClone(frame.options) });
|
|
87
163
|
return;
|
|
88
164
|
}
|
|
165
|
+
if (frame.type === 'starting') {
|
|
166
|
+
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (frame.type === 'link') {
|
|
170
|
+
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (frame.type === 'deliveries') {
|
|
174
|
+
emitConversation({ kind: 'deliveries', conversation, unknown: [...frame.unknown] });
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
89
177
|
if (frame.type === 'interactions') {
|
|
90
178
|
emitConversation({
|
|
91
179
|
kind: 'questions',
|
|
@@ -110,7 +198,162 @@ export function houseNotifications(transport, mode) {
|
|
|
110
198
|
if (line !== undefined)
|
|
111
199
|
lines.set(authority, { ...line, frames: [] });
|
|
112
200
|
}
|
|
113
|
-
function
|
|
201
|
+
async function forget(carries) {
|
|
202
|
+
const held = carries.filter((carry) => kept.delete(carry));
|
|
203
|
+
if (held.length > 0)
|
|
204
|
+
await receipts?.drop(held).catch(() => { });
|
|
205
|
+
}
|
|
206
|
+
async function lost(authority, carry) {
|
|
207
|
+
interrupt(authority);
|
|
208
|
+
await forget([carry]);
|
|
209
|
+
}
|
|
210
|
+
async function stage(frame, via) {
|
|
211
|
+
await loaded;
|
|
212
|
+
const port = receipts;
|
|
213
|
+
if (port === null)
|
|
214
|
+
return;
|
|
215
|
+
const held = kept.get(frame.carry);
|
|
216
|
+
if (held === undefined && frame.index !== 0) {
|
|
217
|
+
interrupt(frame.authority);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (held !== undefined &&
|
|
221
|
+
(held.fenced !== null || frame.index > held.parts || frame.index < (held.resume?.parts ?? 0))) {
|
|
222
|
+
await lost(frame.authority, frame.carry);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (held === undefined) {
|
|
226
|
+
await forget([...kept.values()]
|
|
227
|
+
.filter((other) => other.authority === frame.authority && other.fenced === null)
|
|
228
|
+
.map((other) => other.carry));
|
|
229
|
+
}
|
|
230
|
+
const start = held ?? {
|
|
231
|
+
authority: frame.authority,
|
|
232
|
+
carry: frame.carry,
|
|
233
|
+
logEpoch: lines.get(frame.authority)?.logEpoch ?? null,
|
|
234
|
+
after: frame.after,
|
|
235
|
+
parts: 0,
|
|
236
|
+
resume: null,
|
|
237
|
+
fenced: null,
|
|
238
|
+
};
|
|
239
|
+
const next = { ...start, parts: frame.index + 1, resume: resumed(start, frame) };
|
|
240
|
+
const part = { entries: frame.entries };
|
|
241
|
+
try {
|
|
242
|
+
await port.keep(frame.carry, next, { index: frame.index, value: part });
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
await lost(frame.authority, frame.carry);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
kept.set(frame.carry, next);
|
|
249
|
+
via?.received(frame.authority, frame.carry, frame.index);
|
|
250
|
+
}
|
|
251
|
+
async function keptEntries(carry, parts) {
|
|
252
|
+
if (parts === 0)
|
|
253
|
+
return [];
|
|
254
|
+
if (receipts === null)
|
|
255
|
+
return null;
|
|
256
|
+
const read = (await receipts.parts(carry, parts));
|
|
257
|
+
if (read.length !== parts)
|
|
258
|
+
return null;
|
|
259
|
+
const entries = assembled(read.flatMap((part) => part.entries));
|
|
260
|
+
return entries !== null && (await verified(entries)) ? entries : null;
|
|
261
|
+
}
|
|
262
|
+
async function carried(frame) {
|
|
263
|
+
await loaded;
|
|
264
|
+
const held = kept.get(frame.carry);
|
|
265
|
+
if (frame.parts > 0 && held?.parts !== frame.parts) {
|
|
266
|
+
await lost(frame.authority, frame.carry);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const entries = await keptEntries(frame.carry, frame.parts).catch(() => null);
|
|
270
|
+
if (entries === null) {
|
|
271
|
+
await lost(frame.authority, frame.carry);
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const fenced = {
|
|
275
|
+
...(held ?? {
|
|
276
|
+
authority: frame.authority,
|
|
277
|
+
carry: frame.carry,
|
|
278
|
+
logEpoch: frame.log_epoch,
|
|
279
|
+
after: frame.after,
|
|
280
|
+
parts: 0,
|
|
281
|
+
resume: null,
|
|
282
|
+
}),
|
|
283
|
+
after: frame.after,
|
|
284
|
+
fenced: { position: frame.position, logEpoch: frame.log_epoch },
|
|
285
|
+
};
|
|
286
|
+
try {
|
|
287
|
+
await receipts?.keep(frame.carry, fenced);
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
await lost(frame.authority, frame.carry);
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
kept.set(frame.carry, fenced);
|
|
294
|
+
publish(frame, entries);
|
|
295
|
+
}
|
|
296
|
+
async function load(port) {
|
|
297
|
+
try {
|
|
298
|
+
for (const { key, head } of await port.heads())
|
|
299
|
+
kept.set(key, head);
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
kept.clear();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
async function restored(room) {
|
|
306
|
+
const line = lines.get(room.authority);
|
|
307
|
+
let at = room.position;
|
|
308
|
+
const chain = [];
|
|
309
|
+
for (;;) {
|
|
310
|
+
const next = [...kept.values()].find((carry) => carry.authority === room.authority &&
|
|
311
|
+
carry.after === at &&
|
|
312
|
+
carry.fenced?.logEpoch === room.log_epoch);
|
|
313
|
+
if (next?.fenced == null)
|
|
314
|
+
break;
|
|
315
|
+
const entries = await keptEntries(next.carry, next.parts).catch(() => null);
|
|
316
|
+
if (entries === null)
|
|
317
|
+
break;
|
|
318
|
+
chain.push({ carry: next, entries });
|
|
319
|
+
at = next.fenced.position;
|
|
320
|
+
}
|
|
321
|
+
const partial = [...kept.values()].find((carry) => carry.authority === room.authority &&
|
|
322
|
+
carry.fenced === null &&
|
|
323
|
+
carry.logEpoch === room.log_epoch &&
|
|
324
|
+
carry.after === at &&
|
|
325
|
+
carry.resume !== null &&
|
|
326
|
+
carry.resume.parts > 0);
|
|
327
|
+
const stale = [...kept.values()].filter((carry) => carry.authority === room.authority &&
|
|
328
|
+
carry !== partial &&
|
|
329
|
+
!chain.some((link) => link.carry === carry));
|
|
330
|
+
await forget(stale.map((carry) => carry.carry));
|
|
331
|
+
if (line !== undefined && line.logEpoch === room.log_epoch && chain.length > 0) {
|
|
332
|
+
const frames = chain.map(({ carry, entries }) => ({
|
|
333
|
+
after: BigInt(carry.after),
|
|
334
|
+
position: BigInt(carry.fenced.position),
|
|
335
|
+
entries,
|
|
336
|
+
}));
|
|
337
|
+
lines.set(room.authority, { ...line, frames: [...line.frames, ...frames] });
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
...room,
|
|
341
|
+
position: at,
|
|
342
|
+
...(partial?.resume == null
|
|
343
|
+
? {}
|
|
344
|
+
: {
|
|
345
|
+
carry: {
|
|
346
|
+
id: partial.carry,
|
|
347
|
+
parts: partial.resume.parts,
|
|
348
|
+
from: partial.resume.from,
|
|
349
|
+
target: partial.resume.target,
|
|
350
|
+
handled: partial.resume.handled,
|
|
351
|
+
...(partial.resume.piece === null ? {} : { piece: partial.resume.piece }),
|
|
352
|
+
},
|
|
353
|
+
}),
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function handle(frame, via) {
|
|
114
357
|
if (frame.type === 'signal') {
|
|
115
358
|
const mode = frame.service_mode;
|
|
116
359
|
if (mode !== 'open' && mode !== 'write-halted')
|
|
@@ -126,6 +369,10 @@ export function houseNotifications(transport, mode) {
|
|
|
126
369
|
});
|
|
127
370
|
return;
|
|
128
371
|
}
|
|
372
|
+
if (frame.type === 'authority_changed') {
|
|
373
|
+
emit({ kind: 'authority-changed', scope: { authorities: frame.rooms } });
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
129
376
|
if (frame.type === 'conversations') {
|
|
130
377
|
emitConversation({ kind: 'list', entries: frame.conversations.map(listedConversation) });
|
|
131
378
|
return;
|
|
@@ -142,13 +389,20 @@ export function houseNotifications(transport, mode) {
|
|
|
142
389
|
frame.type === 'process' ||
|
|
143
390
|
frame.type === 'commands' ||
|
|
144
391
|
frame.type === 'options' ||
|
|
392
|
+
frame.type === 'starting' ||
|
|
393
|
+
frame.type === 'link' ||
|
|
394
|
+
frame.type === 'deliveries' ||
|
|
145
395
|
frame.type === 'interactions' ||
|
|
146
396
|
frame.type === 'message') {
|
|
147
397
|
converse(frame);
|
|
148
398
|
return;
|
|
149
399
|
}
|
|
150
|
-
if (frame.type
|
|
151
|
-
return;
|
|
400
|
+
if (frame.type === 'part')
|
|
401
|
+
return stage(frame, via);
|
|
402
|
+
if (frame.type === 'carried')
|
|
403
|
+
return carried(frame);
|
|
404
|
+
}
|
|
405
|
+
function publish(frame, entries) {
|
|
152
406
|
const at = position(frame.position);
|
|
153
407
|
const after = position(frame.after);
|
|
154
408
|
if (at === null || after === null || after >= at) {
|
|
@@ -162,7 +416,7 @@ export function houseNotifications(transport, mode) {
|
|
|
162
416
|
const last = line.frames.at(-1);
|
|
163
417
|
if (last !== undefined && at <= last.position)
|
|
164
418
|
return;
|
|
165
|
-
const held = { after, position: at, entries
|
|
419
|
+
const held = { after, position: at, entries };
|
|
166
420
|
const next = last !== undefined && after <= last.position ? [...line.frames, held] : [held];
|
|
167
421
|
lines.set(frame.authority, { ...line, frames: next.length > HELD_FRAMES_MAX ? [] : next });
|
|
168
422
|
}
|
|
@@ -171,11 +425,30 @@ export function houseNotifications(transport, mode) {
|
|
|
171
425
|
}
|
|
172
426
|
announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });
|
|
173
427
|
}
|
|
174
|
-
stream.observe(
|
|
428
|
+
stream.observe((frame) => {
|
|
429
|
+
const via = acknowledging;
|
|
430
|
+
if (verifying === 0) {
|
|
431
|
+
const handled = handle(frame, via);
|
|
432
|
+
if (handled === undefined)
|
|
433
|
+
return;
|
|
434
|
+
verifying += 1;
|
|
435
|
+
receiving = handled.finally(() => {
|
|
436
|
+
verifying -= 1;
|
|
437
|
+
});
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
verifying += 1;
|
|
441
|
+
receiving = receiving
|
|
442
|
+
.then(() => handle(frame, via))
|
|
443
|
+
.finally(() => {
|
|
444
|
+
verifying -= 1;
|
|
445
|
+
});
|
|
446
|
+
});
|
|
175
447
|
stream.opened(reopened);
|
|
176
|
-
stream.closed((revoked) => {
|
|
448
|
+
stream.closed(({ revoked, lost }) => {
|
|
177
449
|
opening = null;
|
|
178
|
-
|
|
450
|
+
acknowledging = null;
|
|
451
|
+
emit({ kind: 'closed', revoked, lost });
|
|
179
452
|
});
|
|
180
453
|
return {
|
|
181
454
|
runtime,
|
|
@@ -198,8 +471,12 @@ export function houseNotifications(transport, mode) {
|
|
|
198
471
|
};
|
|
199
472
|
},
|
|
200
473
|
},
|
|
201
|
-
observe(notify) {
|
|
474
|
+
observe(notify, port) {
|
|
202
475
|
observers.add(notify);
|
|
476
|
+
if (receipts === null) {
|
|
477
|
+
receipts = port;
|
|
478
|
+
loaded = load(port);
|
|
479
|
+
}
|
|
203
480
|
if (opening !== null) {
|
|
204
481
|
queueMicrotask(() => {
|
|
205
482
|
if (observers.has(notify))
|
|
@@ -220,7 +497,30 @@ export function houseNotifications(transport, mode) {
|
|
|
220
497
|
}
|
|
221
498
|
const current = opening;
|
|
222
499
|
opening = null;
|
|
223
|
-
current
|
|
500
|
+
if (current === null)
|
|
501
|
+
return;
|
|
502
|
+
void loaded
|
|
503
|
+
.then(() => Promise.all(rooms.map(restored)))
|
|
504
|
+
.then((presented) => {
|
|
505
|
+
current.hold(presented, runtime);
|
|
506
|
+
for (const [index, room] of presented.entries()) {
|
|
507
|
+
if (room.position === rooms[index].position)
|
|
508
|
+
continue;
|
|
509
|
+
announce(room.authority, { position: room.position, logEpoch: room.log_epoch });
|
|
510
|
+
}
|
|
511
|
+
});
|
|
512
|
+
},
|
|
513
|
+
published(locator, at) {
|
|
514
|
+
const authority = [...locators].find(([, held]) => held.includes(locator))?.[0];
|
|
515
|
+
const reached = position(at.position);
|
|
516
|
+
if (authority === undefined || reached === null)
|
|
517
|
+
return;
|
|
518
|
+
void forget([...kept.values()]
|
|
519
|
+
.filter((carry) => carry.authority === authority &&
|
|
520
|
+
carry.fenced !== null &&
|
|
521
|
+
carry.fenced.logEpoch === at.logEpoch &&
|
|
522
|
+
BigInt(carry.fenced.position) <= reached)
|
|
523
|
+
.map((carry) => carry.carry));
|
|
224
524
|
},
|
|
225
525
|
reopen() {
|
|
226
526
|
const current = opening;
|
|
@@ -239,6 +539,9 @@ export function houseNotifications(transport, mode) {
|
|
|
239
539
|
if (!locators.has(authority))
|
|
240
540
|
lines.delete(authority);
|
|
241
541
|
}
|
|
542
|
+
void loaded.then(() => forget([...kept.values()]
|
|
543
|
+
.filter((carry) => !locators.has(carry.authority))
|
|
544
|
+
.map((carry) => carry.carry)));
|
|
242
545
|
},
|
|
243
546
|
reach(authority, at) {
|
|
244
547
|
const line = lines.get(authority);
|
|
@@ -253,7 +556,18 @@ export function houseNotifications(transport, mode) {
|
|
|
253
556
|
held,
|
|
254
557
|
});
|
|
255
558
|
},
|
|
256
|
-
|
|
559
|
+
edited(tracked, from) {
|
|
560
|
+
const line = lines.get(tracked.authority);
|
|
561
|
+
const start = position(from.position);
|
|
562
|
+
if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
|
|
563
|
+
return [];
|
|
564
|
+
return [
|
|
565
|
+
...new Set(line.frames
|
|
566
|
+
.filter((frame) => frame.position > start)
|
|
567
|
+
.flatMap((frame) => frame.entries.flatMap((entry) => entry.kind === 'edited' && entry.revision !== undefined ? [entry.path] : []))),
|
|
568
|
+
];
|
|
569
|
+
},
|
|
570
|
+
*advance(tracked, from, holds) {
|
|
257
571
|
const line = lines.get(tracked.authority);
|
|
258
572
|
const start = position(from.position);
|
|
259
573
|
if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
|
|
@@ -262,64 +576,63 @@ export function houseNotifications(transport, mode) {
|
|
|
262
576
|
const first = pending[0];
|
|
263
577
|
if (first === undefined || first.after > start)
|
|
264
578
|
return null;
|
|
265
|
-
const
|
|
266
|
-
const revisions = {};
|
|
267
|
-
const changes = {};
|
|
268
|
-
const removals = [];
|
|
269
|
-
const applied = [];
|
|
579
|
+
const answer = answering();
|
|
270
580
|
const schemas = new Map();
|
|
271
|
-
const forget = (path) => {
|
|
272
|
-
delete documents[path];
|
|
273
|
-
delete revisions[path];
|
|
274
|
-
delete changes[path];
|
|
275
|
-
const removed = removals.indexOf(path);
|
|
276
|
-
if (removed !== -1)
|
|
277
|
-
removals.splice(removed, 1);
|
|
278
|
-
};
|
|
279
581
|
for (const frame of pending) {
|
|
280
582
|
for (const entry of frame.entries) {
|
|
583
|
+
yield ROW_WEIGHT + (entry.text?.length ?? 0);
|
|
584
|
+
if (entry.kind === 'folder') {
|
|
585
|
+
folded(answer, entry.path, entry.removed === true);
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
281
588
|
if (entry.kind === 'edited' &&
|
|
282
589
|
entry.revision !== undefined &&
|
|
283
590
|
holds?.(entry.path, entry.revision) === true) {
|
|
284
|
-
|
|
591
|
+
forgotten(answer, entry.path);
|
|
285
592
|
continue;
|
|
286
593
|
}
|
|
287
|
-
|
|
288
|
-
if (tracked.schemas.includes(entry.path))
|
|
594
|
+
if (entry.path === tracked.schema)
|
|
289
595
|
schemas.set(entry.path, entry);
|
|
290
596
|
if (entry.kind === 'removed') {
|
|
291
|
-
|
|
292
|
-
removals.
|
|
597
|
+
forgotten(answer, entry.path);
|
|
598
|
+
answer.removals.add(entry.path);
|
|
293
599
|
continue;
|
|
294
600
|
}
|
|
295
|
-
|
|
601
|
+
const binary = binaryFileOf(entry);
|
|
602
|
+
if (binary === null || (binary === undefined && entry.text === undefined))
|
|
296
603
|
return null;
|
|
297
604
|
if (mode === 'credential' && entry.revision === undefined)
|
|
298
605
|
return null;
|
|
299
606
|
const head = headChange(entry);
|
|
300
607
|
if (head === null)
|
|
301
608
|
return null;
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
609
|
+
forgotten(answer, entry.path);
|
|
610
|
+
if (binary === undefined)
|
|
611
|
+
answer.documents.set(entry.path, entry.text);
|
|
612
|
+
else
|
|
613
|
+
answer.binaryFiles.set(entry.path, binary);
|
|
614
|
+
const revision = entry.revision ?? binary?.sha256;
|
|
615
|
+
if (revision !== undefined)
|
|
616
|
+
revised(answer, entry.path, revision);
|
|
306
617
|
if (head !== undefined)
|
|
307
|
-
changes
|
|
618
|
+
answer.changes.set(entry.path, head);
|
|
308
619
|
}
|
|
309
620
|
}
|
|
310
621
|
const last = pending.at(-1);
|
|
311
|
-
lines.
|
|
622
|
+
const current = lines.get(tracked.authority);
|
|
623
|
+
if (current?.logEpoch === line.logEpoch) {
|
|
624
|
+
lines.set(tracked.authority, {
|
|
625
|
+
...current,
|
|
626
|
+
frames: current.frames.filter((frame) => frame.position > start),
|
|
627
|
+
held: current.held !== null && current.held > last.position ? current.held : last.position,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
312
630
|
return {
|
|
313
631
|
page: {
|
|
314
632
|
kind: 'net-advancement',
|
|
315
633
|
roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),
|
|
316
|
-
|
|
317
|
-
revisions,
|
|
318
|
-
changes,
|
|
319
|
-
binaryTargets: [],
|
|
320
|
-
removals: removals.sort(),
|
|
634
|
+
...(yield* answered(answer)),
|
|
321
635
|
},
|
|
322
|
-
entries: applied,
|
|
323
636
|
schemas,
|
|
324
637
|
};
|
|
325
638
|
},
|
package/dist/transport.d.ts
CHANGED
|
@@ -14,20 +14,30 @@ export type HouseDoorAnswer = {
|
|
|
14
14
|
status: number;
|
|
15
15
|
body: unknown;
|
|
16
16
|
};
|
|
17
|
-
export
|
|
18
|
-
export
|
|
17
|
+
export declare const DOOR_FILES_GET = "/door/files/get";
|
|
18
|
+
export declare const DOOR_FILES_ATTACH = "/door/files/attach";
|
|
19
|
+
export declare const DOOR_FILES_FINISH = "/door/files/finish";
|
|
20
|
+
export declare const SITE_FILES = "/_house/files/";
|
|
21
|
+
export type HouseByteAct = 'authored_batch_upload';
|
|
22
|
+
export type HouseBytesAnswer = {
|
|
23
|
+
status: number;
|
|
24
|
+
body: ReadableStream<Uint8Array> | null;
|
|
25
|
+
mediaType: string;
|
|
26
|
+
};
|
|
19
27
|
export type HouseByteTransfer = {
|
|
20
28
|
act: HouseByteAct;
|
|
21
29
|
url: string;
|
|
22
|
-
body:
|
|
23
|
-
operation?: string;
|
|
30
|
+
body: string;
|
|
24
31
|
};
|
|
25
32
|
export type HouseStreamEntry = {
|
|
26
33
|
path: string;
|
|
27
|
-
kind: 'edited' | 'removed';
|
|
34
|
+
kind: 'edited' | 'removed' | 'piece' | 'folder';
|
|
35
|
+
removed?: true;
|
|
28
36
|
revision?: string;
|
|
29
37
|
sha256?: string;
|
|
30
38
|
text?: string;
|
|
39
|
+
bytes?: number;
|
|
40
|
+
media_type?: string;
|
|
31
41
|
author?: {
|
|
32
42
|
user: string;
|
|
33
43
|
name: string;
|
|
@@ -36,6 +46,7 @@ export type HouseStreamEntry = {
|
|
|
36
46
|
name: string;
|
|
37
47
|
};
|
|
38
48
|
created_at?: string;
|
|
49
|
+
continued?: true;
|
|
39
50
|
};
|
|
40
51
|
type LiveFact<K extends ConversationEvent['kind']> = Extract<ConversationEvent, {
|
|
41
52
|
kind: K;
|
|
@@ -47,17 +58,32 @@ export type HouseListedConversation = {
|
|
|
47
58
|
created_at: string;
|
|
48
59
|
finished_at: string | null;
|
|
49
60
|
outcome: string | null;
|
|
61
|
+
waiting: boolean;
|
|
50
62
|
};
|
|
51
63
|
export type HouseStreamFrame = {
|
|
52
|
-
type: '
|
|
64
|
+
type: 'part';
|
|
53
65
|
authority: string;
|
|
66
|
+
carry: string;
|
|
67
|
+
index: number;
|
|
68
|
+
after: string;
|
|
69
|
+
from: string;
|
|
70
|
+
target: string;
|
|
71
|
+
handled: number;
|
|
72
|
+
entries: readonly HouseStreamEntry[];
|
|
73
|
+
} | {
|
|
74
|
+
type: 'carried';
|
|
75
|
+
authority: string;
|
|
76
|
+
carry: string;
|
|
77
|
+
parts: number;
|
|
54
78
|
after: string;
|
|
55
79
|
position: string;
|
|
56
80
|
log_epoch: string;
|
|
57
|
-
entries: readonly HouseStreamEntry[];
|
|
58
81
|
} | {
|
|
59
82
|
type: 'opening';
|
|
60
83
|
expired: readonly string[];
|
|
84
|
+
} | {
|
|
85
|
+
type: 'authority_changed';
|
|
86
|
+
rooms: readonly string[];
|
|
61
87
|
} | ({
|
|
62
88
|
type: 'turn';
|
|
63
89
|
conversation_id: string;
|
|
@@ -70,6 +96,10 @@ export type HouseStreamFrame = {
|
|
|
70
96
|
type: 'interactions';
|
|
71
97
|
conversation_id: string;
|
|
72
98
|
interactions: readonly unknown[];
|
|
99
|
+
} | {
|
|
100
|
+
type: 'deliveries';
|
|
101
|
+
conversation_id: string;
|
|
102
|
+
unknown: readonly string[];
|
|
73
103
|
} | {
|
|
74
104
|
type: 'process';
|
|
75
105
|
conversation_id: string;
|
|
@@ -82,6 +112,14 @@ export type HouseStreamFrame = {
|
|
|
82
112
|
type: 'options';
|
|
83
113
|
conversation_id: string;
|
|
84
114
|
options: LiveFact<'options'>['options'];
|
|
115
|
+
} | {
|
|
116
|
+
type: 'starting';
|
|
117
|
+
conversation_id: string;
|
|
118
|
+
step: string | null;
|
|
119
|
+
} | {
|
|
120
|
+
type: 'link';
|
|
121
|
+
conversation_id: string;
|
|
122
|
+
connected: boolean;
|
|
85
123
|
} | {
|
|
86
124
|
type: 'conversations';
|
|
87
125
|
conversations: readonly HouseListedConversation[];
|
|
@@ -95,30 +133,55 @@ export type HouseStreamFrame = {
|
|
|
95
133
|
type: 'signal';
|
|
96
134
|
service_mode: string;
|
|
97
135
|
};
|
|
136
|
+
export type HouseHeldCarry = {
|
|
137
|
+
id: string;
|
|
138
|
+
parts: number;
|
|
139
|
+
from: string;
|
|
140
|
+
target: string;
|
|
141
|
+
handled: number;
|
|
142
|
+
piece?: {
|
|
143
|
+
sha256: string;
|
|
144
|
+
offset: number;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
98
147
|
export type HouseHeldRoom = {
|
|
99
148
|
authority: string;
|
|
100
149
|
position: string;
|
|
101
150
|
log_epoch: string;
|
|
151
|
+
carry?: HouseHeldCarry;
|
|
102
152
|
};
|
|
103
153
|
export type HouseOpening = {
|
|
104
154
|
hold(rooms: readonly HouseHeldRoom[], runtime: string): void;
|
|
155
|
+
received(authority: string, carry: string, index: number): void;
|
|
105
156
|
close(): void;
|
|
106
157
|
};
|
|
158
|
+
export type HouseClosing = {
|
|
159
|
+
revoked: boolean;
|
|
160
|
+
lost: boolean;
|
|
161
|
+
};
|
|
107
162
|
export type HouseStream = {
|
|
108
163
|
observe(receive: (frame: HouseStreamFrame) => void): () => void;
|
|
109
164
|
opened(notify: (opening: HouseOpening) => void): () => void;
|
|
110
|
-
closed(notify: (
|
|
165
|
+
closed(notify: (closing: HouseClosing) => void): () => void;
|
|
166
|
+
};
|
|
167
|
+
export type HouseStreamed = HouseDoorAnswer & {
|
|
168
|
+
room: ReadableStream<Uint8Array> | null;
|
|
111
169
|
};
|
|
112
170
|
export type HouseDoor = {
|
|
113
171
|
door(route: string, body: unknown): Promise<HouseDoorAnswer>;
|
|
114
172
|
stream: HouseStream;
|
|
115
173
|
};
|
|
116
174
|
export type HouseTransport = HouseDoor & {
|
|
175
|
+
streamed(route: string, body: unknown, signal: AbortSignal): Promise<HouseStreamed>;
|
|
117
176
|
transfer(request: HouseByteTransfer): Promise<HouseDoorAnswer>;
|
|
177
|
+
put(url: string, body: Blob, headers: Readonly<Record<string, string>>): Promise<number>;
|
|
178
|
+
download(url: string): Promise<HouseBytesAnswer>;
|
|
118
179
|
};
|
|
119
180
|
export type HouseSiteTransport = HouseDoor & {
|
|
120
181
|
online(): boolean;
|
|
121
182
|
read(route: string): Promise<HouseDoorAnswer>;
|
|
183
|
+
streamed(route: string, signal: AbortSignal): Promise<HouseStreamed>;
|
|
184
|
+
download(route: string): Promise<HouseBytesAnswer>;
|
|
122
185
|
};
|
|
123
186
|
export {};
|
|
124
187
|
//# sourceMappingURL=transport.d.ts.map
|