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