@agentshouse/mdruntime-adapter 0.1.0-cc1bdabaf4e28 → 0.1.0-cc34762b70bb0
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 +4 -59
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +7 -289
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +134 -327
- package/dist/discovery.d.ts +19 -6
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +63 -30
- 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 -442
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/model.d.ts +2 -3
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -17
- package/dist/part.d.ts +11 -12
- package/dist/part.d.ts.map +1 -1
- package/dist/part.js +63 -55
- package/dist/read.d.ts +10 -58
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +37 -220
- 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 +3 -3
- package/dist/room-types.d.ts.map +1 -1
- package/dist/room-types.js +8 -7
- 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 +75 -158
- package/dist/stream.d.ts +13 -14
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +163 -425
- package/dist/transport.d.ts +48 -35
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +54 -11
- package/dist/upload.d.ts.map +1 -1
- package/dist/upload.js +2 -2
- package/dist/write.d.ts +6 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +17 -24
- package/package.json +2 -2
- package/dist/gather.d.ts +0 -4
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -35
package/dist/stream.js
CHANGED
|
@@ -1,108 +1,93 @@
|
|
|
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 { 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
|
-
|
|
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
|
+
yield ROW_WEIGHT + (entry.text?.length ?? 0);
|
|
47
|
+
if (entry.kind === 'folder') {
|
|
48
|
+
folded(answer, entry.path, entry.removed === true);
|
|
49
|
+
continue;
|
|
46
50
|
}
|
|
47
|
-
if (entry.
|
|
51
|
+
if (entry.path === tracked.schema)
|
|
52
|
+
schemas.set(entry.path, entry);
|
|
53
|
+
forgotten(answer, entry.path);
|
|
54
|
+
if (entry.kind === 'removed') {
|
|
55
|
+
answer.removals.add(entry.path);
|
|
48
56
|
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
57
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
const binary = binaryFileOf(entry);
|
|
59
|
+
if (binary === undefined)
|
|
60
|
+
answer.documents.set(entry.path, entry.text ?? '');
|
|
61
|
+
else if (binary !== null)
|
|
62
|
+
answer.binaryFiles.set(entry.path, binary);
|
|
63
|
+
const revision = entry.revision ?? binary?.sha256;
|
|
64
|
+
if (revision !== undefined)
|
|
65
|
+
revised(answer, entry.path, revision);
|
|
66
|
+
const head = headChange(entry);
|
|
67
|
+
if (head)
|
|
68
|
+
answer.changes.set(entry.path, head);
|
|
67
69
|
}
|
|
70
|
+
return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
|
|
68
71
|
}
|
|
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
|
-
};
|
|
72
|
+
async function changePage(tracked, entries, version, mode) {
|
|
73
|
+
const schemas = new Map();
|
|
74
|
+
const page = await stepped(changed(tracked, entries, version, schemas));
|
|
75
|
+
const models = await streamedModels(schemas, tracked, mode);
|
|
76
|
+
return models === undefined ? page : { ...page, models };
|
|
89
77
|
}
|
|
90
|
-
export function houseNotifications(transport, mode) {
|
|
78
|
+
export function houseNotifications(transport, mode, discovering) {
|
|
91
79
|
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();
|
|
80
|
+
const staged = new Map();
|
|
81
|
+
let socket = null;
|
|
82
|
+
const tracking = new Map();
|
|
100
83
|
const observers = new Set();
|
|
101
84
|
const conversationObservers = new Set();
|
|
102
85
|
const modeObservers = new Set();
|
|
103
86
|
let replicated = [];
|
|
87
|
+
let listedCursor = null;
|
|
104
88
|
const live = new Set();
|
|
105
89
|
let opening = null;
|
|
90
|
+
let announced = null;
|
|
106
91
|
const runtime = crypto.randomUUID();
|
|
107
92
|
function emit(event) {
|
|
108
93
|
for (const observer of observers)
|
|
@@ -115,6 +100,7 @@ export function houseNotifications(transport, mode) {
|
|
|
115
100
|
event.kind === 'commands' ||
|
|
116
101
|
event.kind === 'options' ||
|
|
117
102
|
event.kind === 'starting' ||
|
|
103
|
+
event.kind === 'subagents' ||
|
|
118
104
|
event.kind === 'link' ||
|
|
119
105
|
event.kind === 'deliveries') {
|
|
120
106
|
live.add(event.conversation);
|
|
@@ -124,12 +110,31 @@ export function houseNotifications(transport, mode) {
|
|
|
124
110
|
}
|
|
125
111
|
function reopened(next) {
|
|
126
112
|
opening = next;
|
|
127
|
-
|
|
113
|
+
announced = null;
|
|
114
|
+
socket = next;
|
|
115
|
+
staged.clear();
|
|
128
116
|
const gapped = new Set([...replicated, ...live]);
|
|
129
117
|
live.clear();
|
|
130
118
|
for (const conversation of gapped)
|
|
131
119
|
emitConversation({ kind: 'gap', conversation });
|
|
132
120
|
emit({ kind: 'opened' });
|
|
121
|
+
if (mode === 'site')
|
|
122
|
+
announce(next, null);
|
|
123
|
+
}
|
|
124
|
+
function announce(via, frame) {
|
|
125
|
+
void discovering.opened(frame).then((discovery) => {
|
|
126
|
+
if (socket !== via)
|
|
127
|
+
return;
|
|
128
|
+
if (discovery === null) {
|
|
129
|
+
via.close();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
announced = { kind: 'discovered', discovery };
|
|
133
|
+
emit(announced);
|
|
134
|
+
}, () => {
|
|
135
|
+
if (socket === via)
|
|
136
|
+
via.close();
|
|
137
|
+
});
|
|
133
138
|
}
|
|
134
139
|
function converse(frame) {
|
|
135
140
|
const conversation = frame.conversation_id;
|
|
@@ -148,6 +153,7 @@ export function houseNotifications(transport, mode) {
|
|
|
148
153
|
return;
|
|
149
154
|
emitConversation({ kind: 'commands', conversation, commands: [] });
|
|
150
155
|
emitConversation({ kind: 'options', conversation, options: [] });
|
|
156
|
+
emitConversation({ kind: 'subagents', conversation, subagents: [] });
|
|
151
157
|
return;
|
|
152
158
|
}
|
|
153
159
|
if (frame.type === 'commands') {
|
|
@@ -166,6 +172,14 @@ export function houseNotifications(transport, mode) {
|
|
|
166
172
|
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
167
173
|
return;
|
|
168
174
|
}
|
|
175
|
+
if (frame.type === 'subagents') {
|
|
176
|
+
emitConversation({
|
|
177
|
+
kind: 'subagents',
|
|
178
|
+
conversation,
|
|
179
|
+
subagents: structuredClone(frame.subagents),
|
|
180
|
+
});
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
169
183
|
if (frame.type === 'link') {
|
|
170
184
|
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
171
185
|
return;
|
|
@@ -187,171 +201,30 @@ export function houseNotifications(transport, mode) {
|
|
|
187
201
|
return;
|
|
188
202
|
emitConversation({ kind: 'accepted-message', conversation, message });
|
|
189
203
|
}
|
|
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);
|
|
204
|
+
function stage(frame, via) {
|
|
205
|
+
const held = staged.get(frame.carry);
|
|
206
|
+
if (frame.index !== (held?.parts ?? 0)) {
|
|
207
|
+
staged.delete(frame.carry);
|
|
223
208
|
return;
|
|
224
209
|
}
|
|
225
210
|
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;
|
|
211
|
+
for (const [carry, other] of staged) {
|
|
212
|
+
if (other.authority === frame.authority)
|
|
213
|
+
staged.delete(carry);
|
|
214
|
+
}
|
|
247
215
|
}
|
|
248
|
-
|
|
216
|
+
const next = held ?? { authority: frame.authority, parts: 0, entries: [] };
|
|
217
|
+
next.entries.push(...frame.entries);
|
|
218
|
+
next.parts += 1;
|
|
219
|
+
staged.set(frame.carry, next);
|
|
249
220
|
via?.received(frame.authority, frame.carry, frame.index);
|
|
250
221
|
}
|
|
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);
|
|
222
|
+
function carried(frame) {
|
|
223
|
+
const held = staged.get(frame.carry);
|
|
224
|
+
staged.delete(frame.carry);
|
|
225
|
+
if ((held?.parts ?? 0) !== frame.parts)
|
|
291
226
|
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
|
-
};
|
|
227
|
+
publish(frame, held?.entries ?? []);
|
|
355
228
|
}
|
|
356
229
|
function handle(frame, via) {
|
|
357
230
|
if (frame.type === 'signal') {
|
|
@@ -363,18 +236,31 @@ export function houseNotifications(transport, mode) {
|
|
|
363
236
|
return;
|
|
364
237
|
}
|
|
365
238
|
if (frame.type === 'opening') {
|
|
239
|
+
if (via !== null && mode === 'credential')
|
|
240
|
+
announce(via, frame);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (frame.type === 'caught_up') {
|
|
366
244
|
emit({
|
|
367
|
-
kind: '
|
|
368
|
-
expired: frame.expired.flatMap((authority) =>
|
|
245
|
+
kind: 'caught-up',
|
|
246
|
+
expired: frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
|
|
369
247
|
});
|
|
370
248
|
return;
|
|
371
249
|
}
|
|
372
250
|
if (frame.type === 'authority_changed') {
|
|
373
|
-
|
|
251
|
+
const change = discovering.changed(frame);
|
|
252
|
+
if (change !== null)
|
|
253
|
+
emit(change);
|
|
374
254
|
return;
|
|
375
255
|
}
|
|
376
256
|
if (frame.type === 'conversations') {
|
|
377
|
-
emitConversation({
|
|
257
|
+
emitConversation({
|
|
258
|
+
kind: 'list',
|
|
259
|
+
entries: frame.conversations.map(listedConversation),
|
|
260
|
+
whole: frame.whole,
|
|
261
|
+
more: frame.more,
|
|
262
|
+
cursor: frame.cursor,
|
|
263
|
+
});
|
|
378
264
|
return;
|
|
379
265
|
}
|
|
380
266
|
if (frame.type === 'conversation') {
|
|
@@ -390,6 +276,7 @@ export function houseNotifications(transport, mode) {
|
|
|
390
276
|
frame.type === 'commands' ||
|
|
391
277
|
frame.type === 'options' ||
|
|
392
278
|
frame.type === 'starting' ||
|
|
279
|
+
frame.type === 'subagents' ||
|
|
393
280
|
frame.type === 'link' ||
|
|
394
281
|
frame.type === 'deliveries' ||
|
|
395
282
|
frame.type === 'interactions' ||
|
|
@@ -398,57 +285,35 @@ export function houseNotifications(transport, mode) {
|
|
|
398
285
|
return;
|
|
399
286
|
}
|
|
400
287
|
if (frame.type === 'part')
|
|
401
|
-
|
|
402
|
-
if (frame.type === 'carried')
|
|
403
|
-
|
|
288
|
+
stage(frame, via);
|
|
289
|
+
else if (frame.type === 'carried')
|
|
290
|
+
carried(frame);
|
|
404
291
|
}
|
|
405
292
|
function publish(frame, entries) {
|
|
406
293
|
const at = position(frame.position);
|
|
407
294
|
const after = position(frame.after);
|
|
408
|
-
if (at === null || after === null || after >= at)
|
|
409
|
-
interrupt(frame.authority);
|
|
295
|
+
if (at === null || after === null || after >= at)
|
|
410
296
|
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;
|
|
297
|
+
const from = roomVersion({ position: frame.after, logEpoch: frame.log_epoch });
|
|
298
|
+
const version = roomVersion({ position: frame.position, logEpoch: frame.log_epoch });
|
|
299
|
+
for (const tracked of tracking.get(frame.authority) ?? []) {
|
|
300
|
+
emit({
|
|
301
|
+
kind: 'room-change',
|
|
302
|
+
locator: tracked.locator,
|
|
303
|
+
from,
|
|
304
|
+
roomVersion: version,
|
|
305
|
+
read: () => changePage(tracked, entries, version, mode),
|
|
437
306
|
});
|
|
438
|
-
return;
|
|
439
307
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
.then(() => handle(frame, via))
|
|
443
|
-
.finally(() => {
|
|
444
|
-
verifying -= 1;
|
|
445
|
-
});
|
|
446
|
-
});
|
|
308
|
+
}
|
|
309
|
+
stream.observe((frame) => handle(frame, socket));
|
|
447
310
|
stream.opened(reopened);
|
|
448
|
-
stream.closed(({ revoked, lost }) => {
|
|
311
|
+
stream.closed(({ revoked, lost, authorityChanged }) => {
|
|
449
312
|
opening = null;
|
|
450
|
-
|
|
451
|
-
|
|
313
|
+
announced = null;
|
|
314
|
+
socket = null;
|
|
315
|
+
staged.clear();
|
|
316
|
+
emit({ kind: 'closed', revoked, lost, authorityChanged });
|
|
452
317
|
});
|
|
453
318
|
return {
|
|
454
319
|
runtime,
|
|
@@ -464,23 +329,30 @@ export function houseNotifications(transport, mode) {
|
|
|
464
329
|
replicate(next) {
|
|
465
330
|
replicated = [...next];
|
|
466
331
|
},
|
|
332
|
+
hold(cursor) {
|
|
333
|
+
listedCursor = cursor;
|
|
334
|
+
},
|
|
467
335
|
observe(notify) {
|
|
468
336
|
conversationObservers.add(notify);
|
|
469
337
|
return () => {
|
|
470
338
|
conversationObservers.delete(notify);
|
|
471
339
|
};
|
|
472
340
|
},
|
|
341
|
+
...(mode === 'credential'
|
|
342
|
+
? {
|
|
343
|
+
agents: () => houseAgents(transport),
|
|
344
|
+
history: (request) => houseHistory(transport, request),
|
|
345
|
+
}
|
|
346
|
+
: {}),
|
|
473
347
|
},
|
|
474
|
-
observe(notify
|
|
348
|
+
observe(notify) {
|
|
475
349
|
observers.add(notify);
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
loaded = load(port);
|
|
479
|
-
}
|
|
480
|
-
if (opening !== null) {
|
|
350
|
+
const replayed = opening === null ? [] : [{ kind: 'opened' }, announced];
|
|
351
|
+
if (replayed.length > 0) {
|
|
481
352
|
queueMicrotask(() => {
|
|
482
|
-
|
|
483
|
-
|
|
353
|
+
for (const event of replayed)
|
|
354
|
+
if (event !== null && observers.has(notify))
|
|
355
|
+
notify(event);
|
|
484
356
|
});
|
|
485
357
|
}
|
|
486
358
|
return () => {
|
|
@@ -488,153 +360,19 @@ export function houseNotifications(transport, mode) {
|
|
|
488
360
|
};
|
|
489
361
|
},
|
|
490
362
|
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
363
|
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();
|
|
364
|
+
announced = null;
|
|
365
|
+
socket?.hold(rooms, runtime, listedCursor);
|
|
529
366
|
},
|
|
530
367
|
track(entries) {
|
|
531
|
-
|
|
368
|
+
tracking.clear();
|
|
532
369
|
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
|
-
}
|
|
370
|
+
tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
|
|
537
371
|
}
|
|
538
|
-
for (const
|
|
539
|
-
if (!
|
|
540
|
-
|
|
372
|
+
for (const [carry, held] of staged) {
|
|
373
|
+
if (!tracking.has(held.authority))
|
|
374
|
+
staged.delete(carry);
|
|
541
375
|
}
|
|
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
376
|
},
|
|
639
377
|
};
|
|
640
378
|
}
|