@agentshouse/mdruntime-adapter 0.1.0-cd673d02b6e50 → 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/dist/actions.d.ts +2 -47
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +7 -225
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +69 -214
- package/dist/discovery.d.ts +18 -5
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +60 -26
- 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 +718 -1
- package/dist/house-model.d.ts.map +1 -1
- package/dist/house-model.js +393 -486
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/model.d.ts +5 -4
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +27 -22
- package/dist/read.d.ts +11 -44
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +25 -174
- 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 +2 -1
- package/dist/room-stream.d.ts.map +1 -1
- package/dist/room-stream.js +2 -2
- package/dist/room-types.d.ts +2 -2
- package/dist/room-types.d.ts.map +1 -1
- package/dist/room-types.js +7 -9
- 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 +50 -92
- 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 +169 -424
- package/dist/transport.d.ts +44 -35
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +54 -12
- package/dist/upload.d.ts.map +1 -1
- package/dist/upload.js +2 -2
- package/dist/write.d.ts +2 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +8 -23
- package/package.json +2 -2
- package/dist/gather.d.ts +0 -3
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -35
package/dist/stream.js
CHANGED
|
@@ -1,108 +1,99 @@
|
|
|
1
|
-
import { ROW_WEIGHT, } from '@agentshouse/mdruntime';
|
|
2
|
-
import { acceptedMessage } from './
|
|
3
|
-
import {
|
|
1
|
+
import { ROW_WEIGHT, stepped, } from '@agentshouse/mdruntime';
|
|
2
|
+
import { acceptedMessage, cursorPosition, houseHistory } from './history.js';
|
|
3
|
+
import { keptSpaceSchemas, streamedModels } from './model.js';
|
|
4
4
|
import { answered, answering, binaryFileOf, folded, forgotten, headChange, revised, } from './read.js';
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { houseDoorRoute, } from './transport.js';
|
|
6
|
+
import { DECIMAL, roomVersion } from './version.js';
|
|
7
7
|
function turnOperation(frame) {
|
|
8
8
|
const { type: _type, conversation_id: _conversation, turn_id: _turn, ...operation } = frame;
|
|
9
9
|
return structuredClone(operation);
|
|
10
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
|
+
}
|
|
11
23
|
function listedConversation(listed) {
|
|
12
24
|
return {
|
|
13
25
|
conversation: listed.conversation_id,
|
|
14
26
|
agent: listed.agent_id,
|
|
27
|
+
agentName: listed.agent_name,
|
|
28
|
+
agentRetired: listed.agent_retired,
|
|
15
29
|
name: listed.name,
|
|
16
30
|
created: listed.created_at,
|
|
17
31
|
finished: listed.finished_at,
|
|
18
32
|
outcome: listed.outcome,
|
|
19
33
|
waiting: listed.waiting,
|
|
34
|
+
newest: listed.newest === null ? null : cursorPosition(listed.newest),
|
|
35
|
+
processEnded: listed.process_ended_at,
|
|
20
36
|
};
|
|
21
37
|
}
|
|
22
38
|
function position(value) {
|
|
23
|
-
if (
|
|
39
|
+
if (!DECIMAL.test(value))
|
|
24
40
|
return null;
|
|
25
41
|
return BigInt(value);
|
|
26
42
|
}
|
|
27
|
-
function
|
|
28
|
-
const
|
|
29
|
-
let open = null;
|
|
43
|
+
function* changed(tracked, entries, version, schemas) {
|
|
44
|
+
const answer = answering();
|
|
30
45
|
for (const entry of entries) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
yield ROW_WEIGHT + (entry.text?.length ?? 0);
|
|
47
|
+
if (entry.kind === 'folder') {
|
|
48
|
+
folded(answer, entry.path, entry.removed === true);
|
|
49
|
+
continue;
|
|
35
50
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
if (entry.text === undefined)
|
|
44
|
-
return null;
|
|
45
|
-
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;
|
|
46
57
|
}
|
|
47
|
-
if (entry.
|
|
58
|
+
if (entry.kind === 'removed') {
|
|
59
|
+
answer.removals.add(entry.path);
|
|
48
60
|
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
61
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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);
|
|
67
75
|
}
|
|
76
|
+
return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
|
|
68
77
|
}
|
|
69
|
-
function
|
|
70
|
-
const
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
};
|
|
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 };
|
|
89
83
|
}
|
|
90
|
-
export function houseNotifications(transport, mode) {
|
|
84
|
+
export function houseNotifications(transport, mode, discovering, spaces) {
|
|
91
85
|
const stream = transport.stream;
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
let loaded = Promise.resolve();
|
|
96
|
-
let acknowledging = null;
|
|
97
|
-
let receiving = Promise.resolve();
|
|
98
|
-
let verifying = 0;
|
|
99
|
-
const locators = new Map();
|
|
86
|
+
const staged = new Map();
|
|
87
|
+
let socket = null;
|
|
88
|
+
const tracking = new Map();
|
|
100
89
|
const observers = new Set();
|
|
101
90
|
const conversationObservers = new Set();
|
|
102
91
|
const modeObservers = new Set();
|
|
103
92
|
let replicated = [];
|
|
93
|
+
let listedCursor = null;
|
|
104
94
|
const live = new Set();
|
|
105
95
|
let opening = null;
|
|
96
|
+
let announced = null;
|
|
106
97
|
const runtime = crypto.randomUUID();
|
|
107
98
|
function emit(event) {
|
|
108
99
|
for (const observer of observers)
|
|
@@ -115,6 +106,7 @@ export function houseNotifications(transport, mode) {
|
|
|
115
106
|
event.kind === 'commands' ||
|
|
116
107
|
event.kind === 'options' ||
|
|
117
108
|
event.kind === 'starting' ||
|
|
109
|
+
event.kind === 'subagents' ||
|
|
118
110
|
event.kind === 'link' ||
|
|
119
111
|
event.kind === 'deliveries') {
|
|
120
112
|
live.add(event.conversation);
|
|
@@ -124,12 +116,31 @@ export function houseNotifications(transport, mode) {
|
|
|
124
116
|
}
|
|
125
117
|
function reopened(next) {
|
|
126
118
|
opening = next;
|
|
127
|
-
|
|
119
|
+
announced = null;
|
|
120
|
+
socket = next;
|
|
121
|
+
staged.clear();
|
|
128
122
|
const gapped = new Set([...replicated, ...live]);
|
|
129
123
|
live.clear();
|
|
130
124
|
for (const conversation of gapped)
|
|
131
125
|
emitConversation({ kind: 'gap', conversation });
|
|
132
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
|
+
});
|
|
133
144
|
}
|
|
134
145
|
function converse(frame) {
|
|
135
146
|
const conversation = frame.conversation_id;
|
|
@@ -148,6 +159,7 @@ export function houseNotifications(transport, mode) {
|
|
|
148
159
|
return;
|
|
149
160
|
emitConversation({ kind: 'commands', conversation, commands: [] });
|
|
150
161
|
emitConversation({ kind: 'options', conversation, options: [] });
|
|
162
|
+
emitConversation({ kind: 'subagents', conversation, subagents: [] });
|
|
151
163
|
return;
|
|
152
164
|
}
|
|
153
165
|
if (frame.type === 'commands') {
|
|
@@ -166,6 +178,14 @@ export function houseNotifications(transport, mode) {
|
|
|
166
178
|
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
167
179
|
return;
|
|
168
180
|
}
|
|
181
|
+
if (frame.type === 'subagents') {
|
|
182
|
+
emitConversation({
|
|
183
|
+
kind: 'subagents',
|
|
184
|
+
conversation,
|
|
185
|
+
subagents: structuredClone(frame.subagents),
|
|
186
|
+
});
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
169
189
|
if (frame.type === 'link') {
|
|
170
190
|
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
171
191
|
return;
|
|
@@ -187,171 +207,31 @@ export function houseNotifications(transport, mode) {
|
|
|
187
207
|
return;
|
|
188
208
|
emitConversation({ kind: 'accepted-message', conversation, message });
|
|
189
209
|
}
|
|
190
|
-
function
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
function interrupt(authority) {
|
|
197
|
-
const line = lines.get(authority);
|
|
198
|
-
if (line !== undefined)
|
|
199
|
-
lines.set(authority, { ...line, frames: [] });
|
|
200
|
-
}
|
|
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);
|
|
210
|
+
function stage(frame, via) {
|
|
211
|
+
const held = staged.get(frame.carry);
|
|
212
|
+
if (frame.index !== (held?.parts ?? 0)) {
|
|
213
|
+
staged.delete(frame.carry);
|
|
223
214
|
return;
|
|
224
215
|
}
|
|
225
216
|
if (held === undefined) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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;
|
|
217
|
+
for (const [carry, other] of staged) {
|
|
218
|
+
if (other.authority === frame.authority)
|
|
219
|
+
staged.delete(carry);
|
|
220
|
+
}
|
|
247
221
|
}
|
|
248
|
-
|
|
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);
|
|
249
227
|
via?.received(frame.authority, frame.carry, frame.index);
|
|
250
228
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (
|
|
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);
|
|
229
|
+
function carried(frame) {
|
|
230
|
+
const held = staged.get(frame.carry);
|
|
231
|
+
staged.delete(frame.carry);
|
|
232
|
+
if ((held?.parts ?? 0) !== frame.parts)
|
|
291
233
|
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
|
-
};
|
|
234
|
+
publish(frame, held?.entries ?? []);
|
|
355
235
|
}
|
|
356
236
|
function handle(frame, via) {
|
|
357
237
|
if (frame.type === 'signal') {
|
|
@@ -363,18 +243,31 @@ export function houseNotifications(transport, mode) {
|
|
|
363
243
|
return;
|
|
364
244
|
}
|
|
365
245
|
if (frame.type === 'opening') {
|
|
246
|
+
if (via !== null && mode === 'credential')
|
|
247
|
+
announce(via, frame);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (frame.type === 'caught_up') {
|
|
366
251
|
emit({
|
|
367
|
-
kind: '
|
|
368
|
-
expired: frame.expired.flatMap((authority) =>
|
|
252
|
+
kind: 'caught-up',
|
|
253
|
+
expired: frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
|
|
369
254
|
});
|
|
370
255
|
return;
|
|
371
256
|
}
|
|
372
257
|
if (frame.type === 'authority_changed') {
|
|
373
|
-
|
|
258
|
+
const change = discovering.changed(frame);
|
|
259
|
+
if (change !== null)
|
|
260
|
+
emit(change);
|
|
374
261
|
return;
|
|
375
262
|
}
|
|
376
263
|
if (frame.type === 'conversations') {
|
|
377
|
-
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
|
+
});
|
|
378
271
|
return;
|
|
379
272
|
}
|
|
380
273
|
if (frame.type === 'conversation') {
|
|
@@ -390,6 +283,7 @@ export function houseNotifications(transport, mode) {
|
|
|
390
283
|
frame.type === 'commands' ||
|
|
391
284
|
frame.type === 'options' ||
|
|
392
285
|
frame.type === 'starting' ||
|
|
286
|
+
frame.type === 'subagents' ||
|
|
393
287
|
frame.type === 'link' ||
|
|
394
288
|
frame.type === 'deliveries' ||
|
|
395
289
|
frame.type === 'interactions' ||
|
|
@@ -398,57 +292,35 @@ export function houseNotifications(transport, mode) {
|
|
|
398
292
|
return;
|
|
399
293
|
}
|
|
400
294
|
if (frame.type === 'part')
|
|
401
|
-
|
|
402
|
-
if (frame.type === 'carried')
|
|
403
|
-
|
|
295
|
+
stage(frame, via);
|
|
296
|
+
else if (frame.type === 'carried')
|
|
297
|
+
carried(frame);
|
|
404
298
|
}
|
|
405
299
|
function publish(frame, entries) {
|
|
406
300
|
const at = position(frame.position);
|
|
407
301
|
const after = position(frame.after);
|
|
408
|
-
if (at === null || after === null || after >= at)
|
|
409
|
-
interrupt(frame.authority);
|
|
302
|
+
if (at === null || after === null || after >= at)
|
|
410
303
|
return;
|
|
411
|
-
}
|
|
412
|
-
const
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
const next = last !== undefined && after <= last.position ? [...line.frames, held] : [held];
|
|
421
|
-
lines.set(frame.authority, { ...line, frames: next.length > HELD_FRAMES_MAX ? [] : next });
|
|
422
|
-
}
|
|
423
|
-
else {
|
|
424
|
-
interrupt(frame.authority);
|
|
425
|
-
}
|
|
426
|
-
announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });
|
|
427
|
-
}
|
|
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;
|
|
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),
|
|
437
313
|
});
|
|
438
|
-
return;
|
|
439
314
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
.then(() => handle(frame, via))
|
|
443
|
-
.finally(() => {
|
|
444
|
-
verifying -= 1;
|
|
445
|
-
});
|
|
446
|
-
});
|
|
315
|
+
}
|
|
316
|
+
stream.observe((frame) => handle(frame, socket));
|
|
447
317
|
stream.opened(reopened);
|
|
448
|
-
stream.closed(({ revoked, lost }) => {
|
|
318
|
+
stream.closed(({ revoked, lost, authorityChanged }) => {
|
|
449
319
|
opening = null;
|
|
450
|
-
|
|
451
|
-
|
|
320
|
+
announced = null;
|
|
321
|
+
socket = null;
|
|
322
|
+
staged.clear();
|
|
323
|
+
emit({ kind: 'closed', revoked, lost, authorityChanged });
|
|
452
324
|
});
|
|
453
325
|
return {
|
|
454
326
|
runtime,
|
|
@@ -464,23 +336,30 @@ export function houseNotifications(transport, mode) {
|
|
|
464
336
|
replicate(next) {
|
|
465
337
|
replicated = [...next];
|
|
466
338
|
},
|
|
339
|
+
hold(cursor) {
|
|
340
|
+
listedCursor = cursor;
|
|
341
|
+
},
|
|
467
342
|
observe(notify) {
|
|
468
343
|
conversationObservers.add(notify);
|
|
469
344
|
return () => {
|
|
470
345
|
conversationObservers.delete(notify);
|
|
471
346
|
};
|
|
472
347
|
},
|
|
348
|
+
...(mode === 'credential'
|
|
349
|
+
? {
|
|
350
|
+
agents: () => houseAgents(transport),
|
|
351
|
+
history: (request) => houseHistory(transport, request),
|
|
352
|
+
}
|
|
353
|
+
: {}),
|
|
473
354
|
},
|
|
474
|
-
observe(notify
|
|
355
|
+
observe(notify) {
|
|
475
356
|
observers.add(notify);
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
loaded = load(port);
|
|
479
|
-
}
|
|
480
|
-
if (opening !== null) {
|
|
357
|
+
const replayed = opening === null ? [] : [{ kind: 'opened' }, announced];
|
|
358
|
+
if (replayed.length > 0) {
|
|
481
359
|
queueMicrotask(() => {
|
|
482
|
-
|
|
483
|
-
|
|
360
|
+
for (const event of replayed)
|
|
361
|
+
if (event !== null && observers.has(notify))
|
|
362
|
+
notify(event);
|
|
484
363
|
});
|
|
485
364
|
}
|
|
486
365
|
return () => {
|
|
@@ -488,153 +367,19 @@ export function houseNotifications(transport, mode) {
|
|
|
488
367
|
};
|
|
489
368
|
},
|
|
490
369
|
send(rooms) {
|
|
491
|
-
for (const room of rooms) {
|
|
492
|
-
const line = lines.get(room.authority);
|
|
493
|
-
const held = position(room.position);
|
|
494
|
-
if (line === undefined || held === null || line.logEpoch !== room.log_epoch)
|
|
495
|
-
continue;
|
|
496
|
-
lines.set(room.authority, { ...line, frames: [], held });
|
|
497
|
-
}
|
|
498
|
-
const current = opening;
|
|
499
370
|
opening = null;
|
|
500
|
-
|
|
501
|
-
|
|
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));
|
|
524
|
-
},
|
|
525
|
-
reopen() {
|
|
526
|
-
const current = opening;
|
|
527
|
-
opening = null;
|
|
528
|
-
current?.close();
|
|
371
|
+
announced = null;
|
|
372
|
+
socket?.hold(rooms, runtime, listedCursor);
|
|
529
373
|
},
|
|
530
374
|
track(entries) {
|
|
531
|
-
|
|
375
|
+
tracking.clear();
|
|
532
376
|
for (const entry of entries) {
|
|
533
|
-
|
|
534
|
-
if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
|
|
535
|
-
lines.set(entry.authority, { logEpoch: entry.logEpoch, frames: [], held: null });
|
|
536
|
-
}
|
|
377
|
+
tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
|
|
537
378
|
}
|
|
538
|
-
for (const
|
|
539
|
-
if (!
|
|
540
|
-
|
|
379
|
+
for (const [carry, held] of staged) {
|
|
380
|
+
if (!tracking.has(held.authority))
|
|
381
|
+
staged.delete(carry);
|
|
541
382
|
}
|
|
542
|
-
void loaded.then(() => forget([...kept.values()]
|
|
543
|
-
.filter((carry) => !locators.has(carry.authority))
|
|
544
|
-
.map((carry) => carry.carry)));
|
|
545
|
-
},
|
|
546
|
-
reach(authority, at) {
|
|
547
|
-
const line = lines.get(authority);
|
|
548
|
-
const held = position(at.position);
|
|
549
|
-
if (line === undefined || held === null || line.logEpoch !== at.logEpoch)
|
|
550
|
-
return;
|
|
551
|
-
if (line.held !== null && held <= line.held)
|
|
552
|
-
return;
|
|
553
|
-
lines.set(authority, {
|
|
554
|
-
...line,
|
|
555
|
-
frames: line.frames.filter((frame) => frame.position > held),
|
|
556
|
-
held,
|
|
557
|
-
});
|
|
558
|
-
},
|
|
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) {
|
|
571
|
-
const line = lines.get(tracked.authority);
|
|
572
|
-
const start = position(from.position);
|
|
573
|
-
if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
|
|
574
|
-
return null;
|
|
575
|
-
const pending = line.frames.filter((frame) => frame.position > start);
|
|
576
|
-
const first = pending[0];
|
|
577
|
-
if (first === undefined || first.after > start)
|
|
578
|
-
return null;
|
|
579
|
-
const answer = answering();
|
|
580
|
-
const schemas = new Map();
|
|
581
|
-
for (const frame of pending) {
|
|
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
|
-
}
|
|
588
|
-
if (entry.kind === 'edited' &&
|
|
589
|
-
entry.revision !== undefined &&
|
|
590
|
-
holds?.(entry.path, entry.revision) === true) {
|
|
591
|
-
forgotten(answer, entry.path);
|
|
592
|
-
continue;
|
|
593
|
-
}
|
|
594
|
-
if (entry.path === tracked.schema)
|
|
595
|
-
schemas.set(entry.path, entry);
|
|
596
|
-
if (entry.kind === 'removed') {
|
|
597
|
-
forgotten(answer, entry.path);
|
|
598
|
-
answer.removals.add(entry.path);
|
|
599
|
-
continue;
|
|
600
|
-
}
|
|
601
|
-
const binary = binaryFileOf(entry);
|
|
602
|
-
if (binary === null || (binary === undefined && entry.text === undefined))
|
|
603
|
-
return null;
|
|
604
|
-
if (mode === 'credential' && entry.revision === undefined)
|
|
605
|
-
return null;
|
|
606
|
-
const head = headChange(entry);
|
|
607
|
-
if (head === null)
|
|
608
|
-
return null;
|
|
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);
|
|
617
|
-
if (head !== undefined)
|
|
618
|
-
answer.changes.set(entry.path, head);
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
const last = pending.at(-1);
|
|
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
|
-
}
|
|
630
|
-
return {
|
|
631
|
-
page: {
|
|
632
|
-
kind: 'net-advancement',
|
|
633
|
-
roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),
|
|
634
|
-
...(yield* answered(answer)),
|
|
635
|
-
},
|
|
636
|
-
schemas,
|
|
637
|
-
};
|
|
638
383
|
},
|
|
639
384
|
};
|
|
640
385
|
}
|