@agentshouse/mdruntime-adapter 0.1.0-cc710a8825617 → 0.1.0-cc7da2d4669a3
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 +3 -65
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +3 -336
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +233 -355
- 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 +13 -12
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +62 -51
- package/dist/history.d.ts +12 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +91 -0
- package/dist/house-model.d.ts +2915 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +1603 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/model.d.ts +5 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +10 -29
- 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 +46 -63
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +216 -283
- package/dist/refusal.d.ts +0 -3
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +0 -5
- 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 +126 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +104 -198
- package/dist/stream.d.ts +14 -15
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +165 -423
- package/dist/transport.d.ts +62 -43
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +52 -11
- package/dist/upload.d.ts +12 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +63 -0
- package/dist/write.d.ts +16 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +101 -56
- package/package.json +8 -4
- package/AGENTS.md +0 -302
- package/dist/gather.d.ts +0 -4
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -45
- package/dist/handed.d.ts +0 -15
- package/dist/handed.d.ts.map +0 -1
- package/dist/handed.js +0 -38
- package/dist/referrer.d.ts +0 -7
- package/dist/referrer.d.ts.map +0 -1
- package/dist/referrer.js +0 -35
package/dist/stream.js
CHANGED
|
@@ -1,106 +1,91 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { ROW_WEIGHT, stepped, } from '@agentshouse/mdruntime';
|
|
2
|
+
import { acceptedMessage, cursorPosition, houseHistory } from './history.js';
|
|
3
|
+
import { streamedModels } from './model.js';
|
|
4
|
+
import { answered, answering, binaryFileOf, folded, forgotten, headChange, revised, } from './read.js';
|
|
5
|
+
import { houseDoorRoute, } from './transport.js';
|
|
6
|
+
import { DECIMAL, roomVersion } from './version.js';
|
|
6
7
|
function turnOperation(frame) {
|
|
7
8
|
const { type: _type, conversation_id: _conversation, turn_id: _turn, ...operation } = frame;
|
|
8
9
|
return structuredClone(operation);
|
|
9
10
|
}
|
|
11
|
+
async function houseAgents(transport) {
|
|
12
|
+
const answer = await transport.door(houseDoorRoute('agents/read'), {});
|
|
13
|
+
const agents = answer.status === 200 ? answer.body?.agents : null;
|
|
14
|
+
if (!Array.isArray(agents))
|
|
15
|
+
return null;
|
|
16
|
+
return agents.flatMap((one) => {
|
|
17
|
+
const { id, name, retired_at: retired } = (one ?? {});
|
|
18
|
+
return typeof id === 'string' && typeof name === 'string'
|
|
19
|
+
? [{ agent: id, name, retired: retired !== null && retired !== undefined }]
|
|
20
|
+
: [];
|
|
21
|
+
});
|
|
22
|
+
}
|
|
10
23
|
function listedConversation(listed) {
|
|
11
24
|
return {
|
|
12
25
|
conversation: listed.conversation_id,
|
|
13
26
|
agent: listed.agent_id,
|
|
27
|
+
agentName: listed.agent_name,
|
|
28
|
+
agentRetired: listed.agent_retired,
|
|
14
29
|
name: listed.name,
|
|
15
30
|
created: listed.created_at,
|
|
16
31
|
finished: listed.finished_at,
|
|
17
32
|
outcome: listed.outcome,
|
|
33
|
+
waiting: listed.waiting,
|
|
34
|
+
newest: listed.newest === null ? null : cursorPosition(listed.newest),
|
|
18
35
|
};
|
|
19
36
|
}
|
|
20
37
|
function position(value) {
|
|
21
|
-
if (
|
|
38
|
+
if (!DECIMAL.test(value))
|
|
22
39
|
return null;
|
|
23
40
|
return BigInt(value);
|
|
24
41
|
}
|
|
25
|
-
function
|
|
26
|
-
const
|
|
27
|
-
let open = null;
|
|
42
|
+
function* changed(tracked, entries, version, schemas) {
|
|
43
|
+
const answer = answering();
|
|
28
44
|
for (const entry of entries) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
if (open !== null)
|
|
36
|
-
return null;
|
|
37
|
-
if (entry.continued !== true) {
|
|
38
|
-
whole.push(entry);
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (entry.text === undefined)
|
|
42
|
-
return null;
|
|
43
|
-
open = { entry, texts: [entry.text] };
|
|
45
|
+
yield ROW_WEIGHT + (entry.text?.length ?? 0);
|
|
46
|
+
if (entry.kind === 'folder') {
|
|
47
|
+
folded(answer, entry.path, entry.removed === true);
|
|
48
|
+
continue;
|
|
44
49
|
}
|
|
45
|
-
if (entry.
|
|
50
|
+
if (entry.path === tracked.schema)
|
|
51
|
+
schemas.set(entry.path, entry);
|
|
52
|
+
forgotten(answer, entry.path);
|
|
53
|
+
if (entry.kind === 'removed') {
|
|
54
|
+
answer.removals.add(entry.path);
|
|
46
55
|
continue;
|
|
47
|
-
const { continued: _continued, ...head } = open.entry;
|
|
48
|
-
whole.push({ ...head, text: open.texts.join('') });
|
|
49
|
-
open = null;
|
|
50
|
-
}
|
|
51
|
-
return open === null ? whole : null;
|
|
52
|
-
}
|
|
53
|
-
async function verified(entries) {
|
|
54
|
-
try {
|
|
55
|
-
for (const entry of entries) {
|
|
56
|
-
if (entry.text === undefined || entry.sha256 === undefined)
|
|
57
|
-
continue;
|
|
58
|
-
if ((await sha256Hex(entry.text)) !== entry.sha256)
|
|
59
|
-
return false;
|
|
60
56
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
const binary = binaryFileOf(entry);
|
|
58
|
+
if (binary === undefined)
|
|
59
|
+
answer.documents.set(entry.path, entry.text ?? '');
|
|
60
|
+
else if (binary !== null)
|
|
61
|
+
answer.binaryFiles.set(entry.path, binary);
|
|
62
|
+
const revision = entry.revision ?? binary?.sha256;
|
|
63
|
+
if (revision !== undefined)
|
|
64
|
+
revised(answer, entry.path, revision);
|
|
65
|
+
const head = headChange(entry);
|
|
66
|
+
if (head)
|
|
67
|
+
answer.changes.set(entry.path, head);
|
|
65
68
|
}
|
|
69
|
+
return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
|
|
66
70
|
}
|
|
67
|
-
function
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const text = last.text?.length ?? 0;
|
|
73
|
-
if (last.kind !== 'piece') {
|
|
74
|
-
return last.sha256 === undefined
|
|
75
|
-
? kept.resume
|
|
76
|
-
: { ...point, handled: frame.handled, piece: { sha256: last.sha256, offset: text } };
|
|
77
|
-
}
|
|
78
|
-
const piece = kept.resume?.piece ?? null;
|
|
79
|
-
if (piece === null)
|
|
80
|
-
return kept.resume;
|
|
81
|
-
const pieces = frame.entries.reduce((sum, entry) => sum + (entry.kind === 'piece' ? (entry.text?.length ?? 0) : 0), 0);
|
|
82
|
-
return {
|
|
83
|
-
...point,
|
|
84
|
-
handled: frame.handled,
|
|
85
|
-
piece: { sha256: piece.sha256, offset: piece.offset + pieces },
|
|
86
|
-
};
|
|
71
|
+
async function changePage(tracked, entries, version, mode) {
|
|
72
|
+
const schemas = new Map();
|
|
73
|
+
const page = await stepped(changed(tracked, entries, version, schemas));
|
|
74
|
+
const models = await streamedModels(schemas, tracked, mode);
|
|
75
|
+
return models === undefined ? page : { ...page, models };
|
|
87
76
|
}
|
|
88
|
-
export function houseNotifications(transport, mode) {
|
|
77
|
+
export function houseNotifications(transport, mode, discovering) {
|
|
89
78
|
const stream = transport.stream;
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
let loaded = Promise.resolve();
|
|
94
|
-
let acknowledging = null;
|
|
95
|
-
let receiving = Promise.resolve();
|
|
96
|
-
let verifying = 0;
|
|
97
|
-
const locators = new Map();
|
|
79
|
+
const staged = new Map();
|
|
80
|
+
let socket = null;
|
|
81
|
+
const tracking = new Map();
|
|
98
82
|
const observers = new Set();
|
|
99
83
|
const conversationObservers = new Set();
|
|
100
84
|
const modeObservers = new Set();
|
|
101
85
|
let replicated = [];
|
|
102
86
|
const live = new Set();
|
|
103
87
|
let opening = null;
|
|
88
|
+
let announced = null;
|
|
104
89
|
const runtime = crypto.randomUUID();
|
|
105
90
|
function emit(event) {
|
|
106
91
|
for (const observer of observers)
|
|
@@ -111,7 +96,10 @@ export function houseNotifications(transport, mode) {
|
|
|
111
96
|
event.kind === 'questions' ||
|
|
112
97
|
event.kind === 'process' ||
|
|
113
98
|
event.kind === 'commands' ||
|
|
114
|
-
event.kind === 'options'
|
|
99
|
+
event.kind === 'options' ||
|
|
100
|
+
event.kind === 'starting' ||
|
|
101
|
+
event.kind === 'link' ||
|
|
102
|
+
event.kind === 'deliveries') {
|
|
115
103
|
live.add(event.conversation);
|
|
116
104
|
}
|
|
117
105
|
for (const observer of conversationObservers)
|
|
@@ -119,12 +107,31 @@ export function houseNotifications(transport, mode) {
|
|
|
119
107
|
}
|
|
120
108
|
function reopened(next) {
|
|
121
109
|
opening = next;
|
|
122
|
-
|
|
110
|
+
announced = null;
|
|
111
|
+
socket = next;
|
|
112
|
+
staged.clear();
|
|
123
113
|
const gapped = new Set([...replicated, ...live]);
|
|
124
114
|
live.clear();
|
|
125
115
|
for (const conversation of gapped)
|
|
126
116
|
emitConversation({ kind: 'gap', conversation });
|
|
127
117
|
emit({ kind: 'opened' });
|
|
118
|
+
if (mode === 'site')
|
|
119
|
+
announce(next, null);
|
|
120
|
+
}
|
|
121
|
+
function announce(via, frame) {
|
|
122
|
+
void discovering.opened(frame).then((discovery) => {
|
|
123
|
+
if (socket !== via)
|
|
124
|
+
return;
|
|
125
|
+
if (discovery === null) {
|
|
126
|
+
via.close();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
announced = { kind: 'discovered', discovery };
|
|
130
|
+
emit(announced);
|
|
131
|
+
}, () => {
|
|
132
|
+
if (socket === via)
|
|
133
|
+
via.close();
|
|
134
|
+
});
|
|
128
135
|
}
|
|
129
136
|
function converse(frame) {
|
|
130
137
|
const conversation = frame.conversation_id;
|
|
@@ -157,6 +164,18 @@ export function houseNotifications(transport, mode) {
|
|
|
157
164
|
emitConversation({ kind: 'options', conversation, options: structuredClone(frame.options) });
|
|
158
165
|
return;
|
|
159
166
|
}
|
|
167
|
+
if (frame.type === 'starting') {
|
|
168
|
+
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (frame.type === 'link') {
|
|
172
|
+
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (frame.type === 'deliveries') {
|
|
176
|
+
emitConversation({ kind: 'deliveries', conversation, unknown: [...frame.unknown] });
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
160
179
|
if (frame.type === 'interactions') {
|
|
161
180
|
emitConversation({
|
|
162
181
|
kind: 'questions',
|
|
@@ -170,171 +189,30 @@ export function houseNotifications(transport, mode) {
|
|
|
170
189
|
return;
|
|
171
190
|
emitConversation({ kind: 'accepted-message', conversation, message });
|
|
172
191
|
}
|
|
173
|
-
function
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
function interrupt(authority) {
|
|
180
|
-
const line = lines.get(authority);
|
|
181
|
-
if (line !== undefined)
|
|
182
|
-
lines.set(authority, { ...line, frames: [] });
|
|
183
|
-
}
|
|
184
|
-
async function forget(carries) {
|
|
185
|
-
const held = carries.filter((carry) => kept.delete(carry));
|
|
186
|
-
if (held.length > 0)
|
|
187
|
-
await receipts?.drop(held).catch(() => { });
|
|
188
|
-
}
|
|
189
|
-
async function lost(authority, carry) {
|
|
190
|
-
interrupt(authority);
|
|
191
|
-
await forget([carry]);
|
|
192
|
-
}
|
|
193
|
-
async function stage(frame, via) {
|
|
194
|
-
await loaded;
|
|
195
|
-
const port = receipts;
|
|
196
|
-
if (port === null)
|
|
197
|
-
return;
|
|
198
|
-
const held = kept.get(frame.carry);
|
|
199
|
-
if (held === undefined && frame.index !== 0) {
|
|
200
|
-
interrupt(frame.authority);
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
if (held !== undefined &&
|
|
204
|
-
(held.fenced !== null || frame.index > held.parts || frame.index < (held.resume?.parts ?? 0))) {
|
|
205
|
-
await lost(frame.authority, frame.carry);
|
|
192
|
+
function stage(frame, via) {
|
|
193
|
+
const held = staged.get(frame.carry);
|
|
194
|
+
if (frame.index !== (held?.parts ?? 0)) {
|
|
195
|
+
staged.delete(frame.carry);
|
|
206
196
|
return;
|
|
207
197
|
}
|
|
208
198
|
if (held === undefined) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const start = held ?? {
|
|
214
|
-
authority: frame.authority,
|
|
215
|
-
carry: frame.carry,
|
|
216
|
-
logEpoch: lines.get(frame.authority)?.logEpoch ?? null,
|
|
217
|
-
after: frame.after,
|
|
218
|
-
parts: 0,
|
|
219
|
-
resume: null,
|
|
220
|
-
fenced: null,
|
|
221
|
-
};
|
|
222
|
-
const next = { ...start, parts: frame.index + 1, resume: resumed(start, frame) };
|
|
223
|
-
const part = { entries: frame.entries };
|
|
224
|
-
try {
|
|
225
|
-
await port.keep(frame.carry, next, { index: frame.index, value: part });
|
|
226
|
-
}
|
|
227
|
-
catch {
|
|
228
|
-
await lost(frame.authority, frame.carry);
|
|
229
|
-
return;
|
|
199
|
+
for (const [carry, other] of staged) {
|
|
200
|
+
if (other.authority === frame.authority)
|
|
201
|
+
staged.delete(carry);
|
|
202
|
+
}
|
|
230
203
|
}
|
|
231
|
-
|
|
204
|
+
const next = held ?? { authority: frame.authority, parts: 0, entries: [] };
|
|
205
|
+
next.entries.push(...frame.entries);
|
|
206
|
+
next.parts += 1;
|
|
207
|
+
staged.set(frame.carry, next);
|
|
232
208
|
via?.received(frame.authority, frame.carry, frame.index);
|
|
233
209
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (
|
|
238
|
-
return null;
|
|
239
|
-
const read = (await receipts.parts(carry, parts));
|
|
240
|
-
if (read.length !== parts)
|
|
241
|
-
return null;
|
|
242
|
-
const entries = assembled(read.flatMap((part) => part.entries));
|
|
243
|
-
return entries !== null && (await verified(entries)) ? entries : null;
|
|
244
|
-
}
|
|
245
|
-
async function carried(frame) {
|
|
246
|
-
await loaded;
|
|
247
|
-
const held = kept.get(frame.carry);
|
|
248
|
-
if (frame.parts > 0 && held?.parts !== frame.parts) {
|
|
249
|
-
await lost(frame.authority, frame.carry);
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
const entries = await keptEntries(frame.carry, frame.parts).catch(() => null);
|
|
253
|
-
if (entries === null) {
|
|
254
|
-
await lost(frame.authority, frame.carry);
|
|
210
|
+
function carried(frame) {
|
|
211
|
+
const held = staged.get(frame.carry);
|
|
212
|
+
staged.delete(frame.carry);
|
|
213
|
+
if ((held?.parts ?? 0) !== frame.parts)
|
|
255
214
|
return;
|
|
256
|
-
|
|
257
|
-
const fenced = {
|
|
258
|
-
...(held ?? {
|
|
259
|
-
authority: frame.authority,
|
|
260
|
-
carry: frame.carry,
|
|
261
|
-
logEpoch: frame.log_epoch,
|
|
262
|
-
after: frame.after,
|
|
263
|
-
parts: 0,
|
|
264
|
-
resume: null,
|
|
265
|
-
}),
|
|
266
|
-
after: frame.after,
|
|
267
|
-
fenced: { position: frame.position, logEpoch: frame.log_epoch },
|
|
268
|
-
};
|
|
269
|
-
try {
|
|
270
|
-
await receipts?.keep(frame.carry, fenced);
|
|
271
|
-
}
|
|
272
|
-
catch {
|
|
273
|
-
await lost(frame.authority, frame.carry);
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
kept.set(frame.carry, fenced);
|
|
277
|
-
publish(frame, entries);
|
|
278
|
-
}
|
|
279
|
-
async function load(port) {
|
|
280
|
-
try {
|
|
281
|
-
for (const { key, head } of await port.heads())
|
|
282
|
-
kept.set(key, head);
|
|
283
|
-
}
|
|
284
|
-
catch {
|
|
285
|
-
kept.clear();
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
async function restored(room) {
|
|
289
|
-
const line = lines.get(room.authority);
|
|
290
|
-
let at = room.position;
|
|
291
|
-
const chain = [];
|
|
292
|
-
for (;;) {
|
|
293
|
-
const next = [...kept.values()].find((carry) => carry.authority === room.authority &&
|
|
294
|
-
carry.after === at &&
|
|
295
|
-
carry.fenced?.logEpoch === room.log_epoch);
|
|
296
|
-
if (next?.fenced == null)
|
|
297
|
-
break;
|
|
298
|
-
const entries = await keptEntries(next.carry, next.parts).catch(() => null);
|
|
299
|
-
if (entries === null)
|
|
300
|
-
break;
|
|
301
|
-
chain.push({ carry: next, entries });
|
|
302
|
-
at = next.fenced.position;
|
|
303
|
-
}
|
|
304
|
-
const partial = [...kept.values()].find((carry) => carry.authority === room.authority &&
|
|
305
|
-
carry.fenced === null &&
|
|
306
|
-
carry.logEpoch === room.log_epoch &&
|
|
307
|
-
carry.after === at &&
|
|
308
|
-
carry.resume !== null &&
|
|
309
|
-
carry.resume.parts > 0);
|
|
310
|
-
const stale = [...kept.values()].filter((carry) => carry.authority === room.authority &&
|
|
311
|
-
carry !== partial &&
|
|
312
|
-
!chain.some((link) => link.carry === carry));
|
|
313
|
-
await forget(stale.map((carry) => carry.carry));
|
|
314
|
-
if (line !== undefined && line.logEpoch === room.log_epoch && chain.length > 0) {
|
|
315
|
-
const frames = chain.map(({ carry, entries }) => ({
|
|
316
|
-
after: BigInt(carry.after),
|
|
317
|
-
position: BigInt(carry.fenced.position),
|
|
318
|
-
entries,
|
|
319
|
-
}));
|
|
320
|
-
lines.set(room.authority, { ...line, frames: [...line.frames, ...frames] });
|
|
321
|
-
}
|
|
322
|
-
return {
|
|
323
|
-
...room,
|
|
324
|
-
position: at,
|
|
325
|
-
...(partial?.resume == null
|
|
326
|
-
? {}
|
|
327
|
-
: {
|
|
328
|
-
carry: {
|
|
329
|
-
id: partial.carry,
|
|
330
|
-
parts: partial.resume.parts,
|
|
331
|
-
from: partial.resume.from,
|
|
332
|
-
target: partial.resume.target,
|
|
333
|
-
handled: partial.resume.handled,
|
|
334
|
-
...(partial.resume.piece === null ? {} : { piece: partial.resume.piece }),
|
|
335
|
-
},
|
|
336
|
-
}),
|
|
337
|
-
};
|
|
215
|
+
publish(frame, held?.entries ?? []);
|
|
338
216
|
}
|
|
339
217
|
function handle(frame, via) {
|
|
340
218
|
if (frame.type === 'signal') {
|
|
@@ -346,12 +224,23 @@ export function houseNotifications(transport, mode) {
|
|
|
346
224
|
return;
|
|
347
225
|
}
|
|
348
226
|
if (frame.type === 'opening') {
|
|
227
|
+
if (via !== null && mode === 'credential')
|
|
228
|
+
announce(via, frame);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (frame.type === 'caught_up') {
|
|
349
232
|
emit({
|
|
350
|
-
kind: '
|
|
351
|
-
expired: frame.expired.flatMap((authority) =>
|
|
233
|
+
kind: 'caught-up',
|
|
234
|
+
expired: frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
|
|
352
235
|
});
|
|
353
236
|
return;
|
|
354
237
|
}
|
|
238
|
+
if (frame.type === 'authority_changed') {
|
|
239
|
+
const change = discovering.changed(frame);
|
|
240
|
+
if (change !== null)
|
|
241
|
+
emit(change);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
355
244
|
if (frame.type === 'conversations') {
|
|
356
245
|
emitConversation({ kind: 'list', entries: frame.conversations.map(listedConversation) });
|
|
357
246
|
return;
|
|
@@ -368,63 +257,44 @@ export function houseNotifications(transport, mode) {
|
|
|
368
257
|
frame.type === 'process' ||
|
|
369
258
|
frame.type === 'commands' ||
|
|
370
259
|
frame.type === 'options' ||
|
|
260
|
+
frame.type === 'starting' ||
|
|
261
|
+
frame.type === 'link' ||
|
|
262
|
+
frame.type === 'deliveries' ||
|
|
371
263
|
frame.type === 'interactions' ||
|
|
372
264
|
frame.type === 'message') {
|
|
373
265
|
converse(frame);
|
|
374
266
|
return;
|
|
375
267
|
}
|
|
376
268
|
if (frame.type === 'part')
|
|
377
|
-
|
|
378
|
-
if (frame.type === 'carried')
|
|
379
|
-
|
|
269
|
+
stage(frame, via);
|
|
270
|
+
else if (frame.type === 'carried')
|
|
271
|
+
carried(frame);
|
|
380
272
|
}
|
|
381
273
|
function publish(frame, entries) {
|
|
382
274
|
const at = position(frame.position);
|
|
383
275
|
const after = position(frame.after);
|
|
384
|
-
if (at === null || after === null || after >= at)
|
|
385
|
-
interrupt(frame.authority);
|
|
276
|
+
if (at === null || after === null || after >= at)
|
|
386
277
|
return;
|
|
387
|
-
}
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const next = last !== undefined && after <= last.position ? [...line.frames, held] : [held];
|
|
397
|
-
lines.set(frame.authority, { ...line, frames: next.length > HELD_FRAMES_MAX ? [] : next });
|
|
398
|
-
}
|
|
399
|
-
else {
|
|
400
|
-
interrupt(frame.authority);
|
|
401
|
-
}
|
|
402
|
-
announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });
|
|
403
|
-
}
|
|
404
|
-
stream.observe((frame) => {
|
|
405
|
-
const via = acknowledging;
|
|
406
|
-
if (verifying === 0) {
|
|
407
|
-
const handled = handle(frame, via);
|
|
408
|
-
if (handled === undefined)
|
|
409
|
-
return;
|
|
410
|
-
verifying += 1;
|
|
411
|
-
receiving = handled.finally(() => {
|
|
412
|
-
verifying -= 1;
|
|
278
|
+
const from = roomVersion({ position: frame.after, logEpoch: frame.log_epoch });
|
|
279
|
+
const version = roomVersion({ position: frame.position, logEpoch: frame.log_epoch });
|
|
280
|
+
for (const tracked of tracking.get(frame.authority) ?? []) {
|
|
281
|
+
emit({
|
|
282
|
+
kind: 'room-change',
|
|
283
|
+
locator: tracked.locator,
|
|
284
|
+
from,
|
|
285
|
+
roomVersion: version,
|
|
286
|
+
read: () => changePage(tracked, entries, version, mode),
|
|
413
287
|
});
|
|
414
|
-
return;
|
|
415
288
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
.then(() => handle(frame, via))
|
|
419
|
-
.finally(() => {
|
|
420
|
-
verifying -= 1;
|
|
421
|
-
});
|
|
422
|
-
});
|
|
289
|
+
}
|
|
290
|
+
stream.observe((frame) => handle(frame, socket));
|
|
423
291
|
stream.opened(reopened);
|
|
424
|
-
stream.closed((revoked) => {
|
|
292
|
+
stream.closed(({ revoked, lost }) => {
|
|
425
293
|
opening = null;
|
|
426
|
-
|
|
427
|
-
|
|
294
|
+
announced = null;
|
|
295
|
+
socket = null;
|
|
296
|
+
staged.clear();
|
|
297
|
+
emit({ kind: 'closed', revoked, lost });
|
|
428
298
|
});
|
|
429
299
|
return {
|
|
430
300
|
runtime,
|
|
@@ -446,169 +316,41 @@ export function houseNotifications(transport, mode) {
|
|
|
446
316
|
conversationObservers.delete(notify);
|
|
447
317
|
};
|
|
448
318
|
},
|
|
319
|
+
...(mode === 'credential'
|
|
320
|
+
? {
|
|
321
|
+
agents: () => houseAgents(transport),
|
|
322
|
+
history: (request) => houseHistory(transport, request),
|
|
323
|
+
}
|
|
324
|
+
: {}),
|
|
449
325
|
},
|
|
450
|
-
observe(notify
|
|
326
|
+
observe(notify) {
|
|
451
327
|
observers.add(notify);
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
loaded = load(port);
|
|
455
|
-
}
|
|
456
|
-
if (opening !== null) {
|
|
328
|
+
const replayed = opening === null ? [] : [{ kind: 'opened' }, announced];
|
|
329
|
+
if (replayed.length > 0) {
|
|
457
330
|
queueMicrotask(() => {
|
|
458
|
-
|
|
459
|
-
|
|
331
|
+
for (const event of replayed)
|
|
332
|
+
if (event !== null && observers.has(notify))
|
|
333
|
+
notify(event);
|
|
460
334
|
});
|
|
461
335
|
}
|
|
462
336
|
return () => {
|
|
463
337
|
observers.delete(notify);
|
|
464
338
|
};
|
|
465
339
|
},
|
|
466
|
-
send(rooms
|
|
467
|
-
for (const room of rooms) {
|
|
468
|
-
const line = lines.get(room.authority);
|
|
469
|
-
const held = position(room.position);
|
|
470
|
-
if (line === undefined || held === null || line.logEpoch !== room.log_epoch)
|
|
471
|
-
continue;
|
|
472
|
-
lines.set(room.authority, { ...line, frames: [], held });
|
|
473
|
-
}
|
|
474
|
-
const current = opening;
|
|
475
|
-
opening = null;
|
|
476
|
-
if (current === null)
|
|
477
|
-
return;
|
|
478
|
-
void loaded
|
|
479
|
-
.then(() => Promise.all(rooms.map(restored)))
|
|
480
|
-
.then((presented) => {
|
|
481
|
-
current.hold(presented, runtime, demand);
|
|
482
|
-
for (const [index, room] of presented.entries()) {
|
|
483
|
-
if (room.position === rooms[index].position)
|
|
484
|
-
continue;
|
|
485
|
-
announce(room.authority, { position: room.position, logEpoch: room.log_epoch });
|
|
486
|
-
}
|
|
487
|
-
});
|
|
488
|
-
},
|
|
489
|
-
published(locator, at) {
|
|
490
|
-
const authority = [...locators].find(([, held]) => held.includes(locator))?.[0];
|
|
491
|
-
const reached = position(at.position);
|
|
492
|
-
if (authority === undefined || reached === null)
|
|
493
|
-
return;
|
|
494
|
-
void forget([...kept.values()]
|
|
495
|
-
.filter((carry) => carry.authority === authority &&
|
|
496
|
-
carry.fenced !== null &&
|
|
497
|
-
carry.fenced.logEpoch === at.logEpoch &&
|
|
498
|
-
BigInt(carry.fenced.position) <= reached)
|
|
499
|
-
.map((carry) => carry.carry));
|
|
500
|
-
},
|
|
501
|
-
reopen() {
|
|
502
|
-
const current = opening;
|
|
340
|
+
send(rooms) {
|
|
503
341
|
opening = null;
|
|
504
|
-
|
|
342
|
+
announced = null;
|
|
343
|
+
socket?.hold(rooms, runtime);
|
|
505
344
|
},
|
|
506
345
|
track(entries) {
|
|
507
|
-
|
|
346
|
+
tracking.clear();
|
|
508
347
|
for (const entry of entries) {
|
|
509
|
-
|
|
510
|
-
if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
|
|
511
|
-
lines.set(entry.authority, { logEpoch: entry.logEpoch, frames: [], held: null });
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
for (const authority of lines.keys()) {
|
|
515
|
-
if (!locators.has(authority))
|
|
516
|
-
lines.delete(authority);
|
|
348
|
+
tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
|
|
517
349
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
},
|
|
522
|
-
reach(authority, at) {
|
|
523
|
-
const line = lines.get(authority);
|
|
524
|
-
const held = position(at.position);
|
|
525
|
-
if (line === undefined || held === null || line.logEpoch !== at.logEpoch)
|
|
526
|
-
return;
|
|
527
|
-
if (line.held !== null && held <= line.held)
|
|
528
|
-
return;
|
|
529
|
-
lines.set(authority, {
|
|
530
|
-
...line,
|
|
531
|
-
frames: line.frames.filter((frame) => frame.position > held),
|
|
532
|
-
held,
|
|
533
|
-
});
|
|
534
|
-
},
|
|
535
|
-
advance(tracked, from, holds) {
|
|
536
|
-
const line = lines.get(tracked.authority);
|
|
537
|
-
const start = position(from.position);
|
|
538
|
-
if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
|
|
539
|
-
return null;
|
|
540
|
-
const pending = line.frames.filter((frame) => frame.position > start);
|
|
541
|
-
const first = pending[0];
|
|
542
|
-
if (first === undefined || first.after > start)
|
|
543
|
-
return null;
|
|
544
|
-
const documents = {};
|
|
545
|
-
const revisions = {};
|
|
546
|
-
const changes = {};
|
|
547
|
-
const binaryFiles = {};
|
|
548
|
-
const removals = [];
|
|
549
|
-
const applied = [];
|
|
550
|
-
const schemas = new Map();
|
|
551
|
-
const forget = (path) => {
|
|
552
|
-
delete documents[path];
|
|
553
|
-
delete revisions[path];
|
|
554
|
-
delete changes[path];
|
|
555
|
-
delete binaryFiles[path];
|
|
556
|
-
const removed = removals.indexOf(path);
|
|
557
|
-
if (removed !== -1)
|
|
558
|
-
removals.splice(removed, 1);
|
|
559
|
-
};
|
|
560
|
-
for (const frame of pending) {
|
|
561
|
-
for (const entry of frame.entries) {
|
|
562
|
-
if (entry.kind === 'edited' &&
|
|
563
|
-
entry.revision !== undefined &&
|
|
564
|
-
holds?.(entry.path, entry.revision) === true) {
|
|
565
|
-
forget(entry.path);
|
|
566
|
-
continue;
|
|
567
|
-
}
|
|
568
|
-
applied.push(entry);
|
|
569
|
-
if (tracked.schemas.includes(entry.path))
|
|
570
|
-
schemas.set(entry.path, entry);
|
|
571
|
-
if (entry.kind === 'removed') {
|
|
572
|
-
forget(entry.path);
|
|
573
|
-
removals.push(entry.path);
|
|
574
|
-
continue;
|
|
575
|
-
}
|
|
576
|
-
const binary = binaryFileOf(entry);
|
|
577
|
-
if (binary === null || (binary === undefined && entry.text === undefined))
|
|
578
|
-
return null;
|
|
579
|
-
if (mode === 'credential' && entry.revision === undefined)
|
|
580
|
-
return null;
|
|
581
|
-
const head = headChange(entry);
|
|
582
|
-
if (head === null)
|
|
583
|
-
return null;
|
|
584
|
-
forget(entry.path);
|
|
585
|
-
if (binary === undefined)
|
|
586
|
-
documents[entry.path] = entry.text;
|
|
587
|
-
else
|
|
588
|
-
binaryFiles[entry.path] = binary;
|
|
589
|
-
const revision = entry.revision ?? binary?.sha256;
|
|
590
|
-
if (revision !== undefined)
|
|
591
|
-
revisions[entry.path] = revision;
|
|
592
|
-
if (head !== undefined)
|
|
593
|
-
changes[entry.path] = head;
|
|
594
|
-
}
|
|
350
|
+
for (const [carry, held] of staged) {
|
|
351
|
+
if (!tracking.has(held.authority))
|
|
352
|
+
staged.delete(carry);
|
|
595
353
|
}
|
|
596
|
-
const last = pending.at(-1);
|
|
597
|
-
lines.set(tracked.authority, { ...line, frames: pending, held: last.position });
|
|
598
|
-
return {
|
|
599
|
-
page: {
|
|
600
|
-
kind: 'net-advancement',
|
|
601
|
-
roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),
|
|
602
|
-
documents,
|
|
603
|
-
revisions,
|
|
604
|
-
...identities(revisions),
|
|
605
|
-
changes,
|
|
606
|
-
binaryFiles,
|
|
607
|
-
removals: removals.sort(),
|
|
608
|
-
},
|
|
609
|
-
entries: applied,
|
|
610
|
-
schemas,
|
|
611
|
-
};
|
|
612
354
|
},
|
|
613
355
|
};
|
|
614
356
|
}
|