@agentshouse/mdruntime-adapter 0.1.0-cd61dfca5d699 → 0.1.0-cd7e4bb187177
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/actions.d.ts +3 -65
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +1 -337
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +220 -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 +13 -12
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +62 -51
- package/dist/history.d.ts +12 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +91 -0
- package/dist/house-model.d.ts +2398 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +1321 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/model.d.ts +5 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +10 -29
- package/dist/part.d.ts +14 -0
- package/dist/part.d.ts.map +1 -0
- package/dist/part.js +90 -0
- package/dist/read.d.ts +46 -63
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +216 -283
- package/dist/refusal.d.ts +0 -3
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +0 -5
- package/dist/room-stream.d.ts +19 -0
- package/dist/room-stream.d.ts.map +1 -0
- package/dist/room-stream.js +57 -0
- package/dist/room-types.d.ts +7 -0
- package/dist/room-types.d.ts.map +1 -0
- package/dist/room-types.js +126 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +84 -195
- package/dist/stream.d.ts +13 -14
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +150 -420
- package/dist/transport.d.ts +45 -38
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +53 -11
- package/dist/upload.d.ts +12 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +63 -0
- package/dist/write.d.ts +16 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +100 -55
- 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,91 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { ROW_WEIGHT, stepped, } from '@agentshouse/mdruntime';
|
|
2
|
+
import { acceptedMessage, cursorPosition, houseHistory } from './history.js';
|
|
3
|
+
import { streamedModels } from './model.js';
|
|
4
|
+
import { answered, answering, binaryFileOf, folded, forgotten, headChange, revised, } from './read.js';
|
|
5
|
+
import { houseDoorRoute, } from './transport.js';
|
|
6
|
+
import { DECIMAL, roomVersion } from './version.js';
|
|
6
7
|
function turnOperation(frame) {
|
|
7
8
|
const { type: _type, conversation_id: _conversation, turn_id: _turn, ...operation } = frame;
|
|
8
9
|
return structuredClone(operation);
|
|
9
10
|
}
|
|
11
|
+
async function houseAgents(transport) {
|
|
12
|
+
const answer = await transport.door(houseDoorRoute('agents/read'), {});
|
|
13
|
+
const agents = answer.status === 200 ? answer.body?.agents : null;
|
|
14
|
+
if (!Array.isArray(agents))
|
|
15
|
+
return null;
|
|
16
|
+
return agents.flatMap((one) => {
|
|
17
|
+
const { id, name, retired_at: retired } = (one ?? {});
|
|
18
|
+
return typeof id === 'string' && typeof name === 'string'
|
|
19
|
+
? [{ agent: id, name, retired: retired !== null && retired !== undefined }]
|
|
20
|
+
: [];
|
|
21
|
+
});
|
|
22
|
+
}
|
|
10
23
|
function listedConversation(listed) {
|
|
11
24
|
return {
|
|
12
25
|
conversation: listed.conversation_id,
|
|
13
26
|
agent: listed.agent_id,
|
|
27
|
+
agentName: listed.agent_name,
|
|
28
|
+
agentRetired: listed.agent_retired,
|
|
14
29
|
name: listed.name,
|
|
15
30
|
created: listed.created_at,
|
|
16
31
|
finished: listed.finished_at,
|
|
17
32
|
outcome: listed.outcome,
|
|
18
33
|
waiting: listed.waiting,
|
|
34
|
+
newest: listed.newest === null ? null : cursorPosition(listed.newest),
|
|
19
35
|
};
|
|
20
36
|
}
|
|
21
37
|
function position(value) {
|
|
22
|
-
if (
|
|
38
|
+
if (!DECIMAL.test(value))
|
|
23
39
|
return null;
|
|
24
40
|
return BigInt(value);
|
|
25
41
|
}
|
|
26
|
-
function
|
|
27
|
-
const
|
|
28
|
-
let open = null;
|
|
42
|
+
function* changed(tracked, entries, version, schemas) {
|
|
43
|
+
const answer = answering();
|
|
29
44
|
for (const entry of entries) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
if (open !== null)
|
|
37
|
-
return null;
|
|
38
|
-
if (entry.continued !== true) {
|
|
39
|
-
whole.push(entry);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
if (entry.text === undefined)
|
|
43
|
-
return null;
|
|
44
|
-
open = { entry, texts: [entry.text] };
|
|
45
|
+
yield ROW_WEIGHT + (entry.text?.length ?? 0);
|
|
46
|
+
if (entry.kind === 'folder') {
|
|
47
|
+
folded(answer, entry.path, entry.removed === true);
|
|
48
|
+
continue;
|
|
45
49
|
}
|
|
46
|
-
if (entry.
|
|
50
|
+
if (entry.path === tracked.schema)
|
|
51
|
+
schemas.set(entry.path, entry);
|
|
52
|
+
forgotten(answer, entry.path);
|
|
53
|
+
if (entry.kind === 'removed') {
|
|
54
|
+
answer.removals.add(entry.path);
|
|
47
55
|
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
56
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
const binary = binaryFileOf(entry);
|
|
58
|
+
if (binary === undefined)
|
|
59
|
+
answer.documents.set(entry.path, entry.text ?? '');
|
|
60
|
+
else if (binary !== null)
|
|
61
|
+
answer.binaryFiles.set(entry.path, binary);
|
|
62
|
+
const revision = entry.revision ?? binary?.sha256;
|
|
63
|
+
if (revision !== undefined)
|
|
64
|
+
revised(answer, entry.path, revision);
|
|
65
|
+
const head = headChange(entry);
|
|
66
|
+
if (head)
|
|
67
|
+
answer.changes.set(entry.path, head);
|
|
66
68
|
}
|
|
69
|
+
return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
|
|
67
70
|
}
|
|
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
|
-
};
|
|
71
|
+
async function changePage(tracked, entries, version, mode) {
|
|
72
|
+
const schemas = new Map();
|
|
73
|
+
const page = await stepped(changed(tracked, entries, version, schemas));
|
|
74
|
+
const models = await streamedModels(schemas, tracked, mode);
|
|
75
|
+
return models === undefined ? page : { ...page, models };
|
|
88
76
|
}
|
|
89
|
-
export function houseNotifications(transport, mode) {
|
|
77
|
+
export function houseNotifications(transport, mode, discovering) {
|
|
90
78
|
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();
|
|
79
|
+
const staged = new Map();
|
|
80
|
+
let socket = null;
|
|
81
|
+
const tracking = new Map();
|
|
99
82
|
const observers = new Set();
|
|
100
83
|
const conversationObservers = new Set();
|
|
101
84
|
const modeObservers = new Set();
|
|
102
85
|
let replicated = [];
|
|
103
86
|
const live = new Set();
|
|
104
87
|
let opening = null;
|
|
88
|
+
let announced = null;
|
|
105
89
|
const runtime = crypto.randomUUID();
|
|
106
90
|
function emit(event) {
|
|
107
91
|
for (const observer of observers)
|
|
@@ -114,6 +98,7 @@ export function houseNotifications(transport, mode) {
|
|
|
114
98
|
event.kind === 'commands' ||
|
|
115
99
|
event.kind === 'options' ||
|
|
116
100
|
event.kind === 'starting' ||
|
|
101
|
+
event.kind === 'subagents' ||
|
|
117
102
|
event.kind === 'link' ||
|
|
118
103
|
event.kind === 'deliveries') {
|
|
119
104
|
live.add(event.conversation);
|
|
@@ -123,12 +108,31 @@ export function houseNotifications(transport, mode) {
|
|
|
123
108
|
}
|
|
124
109
|
function reopened(next) {
|
|
125
110
|
opening = next;
|
|
126
|
-
|
|
111
|
+
announced = null;
|
|
112
|
+
socket = next;
|
|
113
|
+
staged.clear();
|
|
127
114
|
const gapped = new Set([...replicated, ...live]);
|
|
128
115
|
live.clear();
|
|
129
116
|
for (const conversation of gapped)
|
|
130
117
|
emitConversation({ kind: 'gap', conversation });
|
|
131
118
|
emit({ kind: 'opened' });
|
|
119
|
+
if (mode === 'site')
|
|
120
|
+
announce(next, null);
|
|
121
|
+
}
|
|
122
|
+
function announce(via, frame) {
|
|
123
|
+
void discovering.opened(frame).then((discovery) => {
|
|
124
|
+
if (socket !== via)
|
|
125
|
+
return;
|
|
126
|
+
if (discovery === null) {
|
|
127
|
+
via.close();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
announced = { kind: 'discovered', discovery };
|
|
131
|
+
emit(announced);
|
|
132
|
+
}, () => {
|
|
133
|
+
if (socket === via)
|
|
134
|
+
via.close();
|
|
135
|
+
});
|
|
132
136
|
}
|
|
133
137
|
function converse(frame) {
|
|
134
138
|
const conversation = frame.conversation_id;
|
|
@@ -147,6 +151,7 @@ export function houseNotifications(transport, mode) {
|
|
|
147
151
|
return;
|
|
148
152
|
emitConversation({ kind: 'commands', conversation, commands: [] });
|
|
149
153
|
emitConversation({ kind: 'options', conversation, options: [] });
|
|
154
|
+
emitConversation({ kind: 'subagents', conversation, subagents: [] });
|
|
150
155
|
return;
|
|
151
156
|
}
|
|
152
157
|
if (frame.type === 'commands') {
|
|
@@ -165,6 +170,14 @@ export function houseNotifications(transport, mode) {
|
|
|
165
170
|
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
166
171
|
return;
|
|
167
172
|
}
|
|
173
|
+
if (frame.type === 'subagents') {
|
|
174
|
+
emitConversation({
|
|
175
|
+
kind: 'subagents',
|
|
176
|
+
conversation,
|
|
177
|
+
subagents: structuredClone(frame.subagents),
|
|
178
|
+
});
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
168
181
|
if (frame.type === 'link') {
|
|
169
182
|
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
170
183
|
return;
|
|
@@ -186,171 +199,30 @@ export function houseNotifications(transport, mode) {
|
|
|
186
199
|
return;
|
|
187
200
|
emitConversation({ kind: 'accepted-message', conversation, message });
|
|
188
201
|
}
|
|
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);
|
|
202
|
+
function stage(frame, via) {
|
|
203
|
+
const held = staged.get(frame.carry);
|
|
204
|
+
if (frame.index !== (held?.parts ?? 0)) {
|
|
205
|
+
staged.delete(frame.carry);
|
|
222
206
|
return;
|
|
223
207
|
}
|
|
224
208
|
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;
|
|
209
|
+
for (const [carry, other] of staged) {
|
|
210
|
+
if (other.authority === frame.authority)
|
|
211
|
+
staged.delete(carry);
|
|
212
|
+
}
|
|
246
213
|
}
|
|
247
|
-
|
|
214
|
+
const next = held ?? { authority: frame.authority, parts: 0, entries: [] };
|
|
215
|
+
next.entries.push(...frame.entries);
|
|
216
|
+
next.parts += 1;
|
|
217
|
+
staged.set(frame.carry, next);
|
|
248
218
|
via?.received(frame.authority, frame.carry, frame.index);
|
|
249
219
|
}
|
|
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);
|
|
220
|
+
function carried(frame) {
|
|
221
|
+
const held = staged.get(frame.carry);
|
|
222
|
+
staged.delete(frame.carry);
|
|
223
|
+
if ((held?.parts ?? 0) !== frame.parts)
|
|
271
224
|
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
|
-
};
|
|
225
|
+
publish(frame, held?.entries ?? []);
|
|
354
226
|
}
|
|
355
227
|
function handle(frame, via) {
|
|
356
228
|
if (frame.type === 'signal') {
|
|
@@ -362,14 +234,21 @@ export function houseNotifications(transport, mode) {
|
|
|
362
234
|
return;
|
|
363
235
|
}
|
|
364
236
|
if (frame.type === 'opening') {
|
|
237
|
+
if (via !== null && mode === 'credential')
|
|
238
|
+
announce(via, frame);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (frame.type === 'caught_up') {
|
|
365
242
|
emit({
|
|
366
|
-
kind: '
|
|
367
|
-
expired: frame.expired.flatMap((authority) =>
|
|
243
|
+
kind: 'caught-up',
|
|
244
|
+
expired: frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
|
|
368
245
|
});
|
|
369
246
|
return;
|
|
370
247
|
}
|
|
371
248
|
if (frame.type === 'authority_changed') {
|
|
372
|
-
|
|
249
|
+
const change = discovering.changed(frame);
|
|
250
|
+
if (change !== null)
|
|
251
|
+
emit(change);
|
|
373
252
|
return;
|
|
374
253
|
}
|
|
375
254
|
if (frame.type === 'conversations') {
|
|
@@ -389,6 +268,7 @@ export function houseNotifications(transport, mode) {
|
|
|
389
268
|
frame.type === 'commands' ||
|
|
390
269
|
frame.type === 'options' ||
|
|
391
270
|
frame.type === 'starting' ||
|
|
271
|
+
frame.type === 'subagents' ||
|
|
392
272
|
frame.type === 'link' ||
|
|
393
273
|
frame.type === 'deliveries' ||
|
|
394
274
|
frame.type === 'interactions' ||
|
|
@@ -397,56 +277,34 @@ export function houseNotifications(transport, mode) {
|
|
|
397
277
|
return;
|
|
398
278
|
}
|
|
399
279
|
if (frame.type === 'part')
|
|
400
|
-
|
|
401
|
-
if (frame.type === 'carried')
|
|
402
|
-
|
|
280
|
+
stage(frame, via);
|
|
281
|
+
else if (frame.type === 'carried')
|
|
282
|
+
carried(frame);
|
|
403
283
|
}
|
|
404
284
|
function publish(frame, entries) {
|
|
405
285
|
const at = position(frame.position);
|
|
406
286
|
const after = position(frame.after);
|
|
407
|
-
if (at === null || after === null || after >= at)
|
|
408
|
-
interrupt(frame.authority);
|
|
287
|
+
if (at === null || after === null || after >= at)
|
|
409
288
|
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;
|
|
289
|
+
const from = roomVersion({ position: frame.after, logEpoch: frame.log_epoch });
|
|
290
|
+
const version = roomVersion({ position: frame.position, logEpoch: frame.log_epoch });
|
|
291
|
+
for (const tracked of tracking.get(frame.authority) ?? []) {
|
|
292
|
+
emit({
|
|
293
|
+
kind: 'room-change',
|
|
294
|
+
locator: tracked.locator,
|
|
295
|
+
from,
|
|
296
|
+
roomVersion: version,
|
|
297
|
+
read: () => changePage(tracked, entries, version, mode),
|
|
436
298
|
});
|
|
437
|
-
return;
|
|
438
299
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
.then(() => handle(frame, via))
|
|
442
|
-
.finally(() => {
|
|
443
|
-
verifying -= 1;
|
|
444
|
-
});
|
|
445
|
-
});
|
|
300
|
+
}
|
|
301
|
+
stream.observe((frame) => handle(frame, socket));
|
|
446
302
|
stream.opened(reopened);
|
|
447
303
|
stream.closed(({ revoked, lost }) => {
|
|
448
304
|
opening = null;
|
|
449
|
-
|
|
305
|
+
announced = null;
|
|
306
|
+
socket = null;
|
|
307
|
+
staged.clear();
|
|
450
308
|
emit({ kind: 'closed', revoked, lost });
|
|
451
309
|
});
|
|
452
310
|
return {
|
|
@@ -469,17 +327,21 @@ export function houseNotifications(transport, mode) {
|
|
|
469
327
|
conversationObservers.delete(notify);
|
|
470
328
|
};
|
|
471
329
|
},
|
|
330
|
+
...(mode === 'credential'
|
|
331
|
+
? {
|
|
332
|
+
agents: () => houseAgents(transport),
|
|
333
|
+
history: (request) => houseHistory(transport, request),
|
|
334
|
+
}
|
|
335
|
+
: {}),
|
|
472
336
|
},
|
|
473
|
-
observe(notify
|
|
337
|
+
observe(notify) {
|
|
474
338
|
observers.add(notify);
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
loaded = load(port);
|
|
478
|
-
}
|
|
479
|
-
if (opening !== null) {
|
|
339
|
+
const replayed = opening === null ? [] : [{ kind: 'opened' }, announced];
|
|
340
|
+
if (replayed.length > 0) {
|
|
480
341
|
queueMicrotask(() => {
|
|
481
|
-
|
|
482
|
-
|
|
342
|
+
for (const event of replayed)
|
|
343
|
+
if (event !== null && observers.has(notify))
|
|
344
|
+
notify(event);
|
|
483
345
|
});
|
|
484
346
|
}
|
|
485
347
|
return () => {
|
|
@@ -487,151 +349,19 @@ export function houseNotifications(transport, mode) {
|
|
|
487
349
|
};
|
|
488
350
|
},
|
|
489
351
|
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
352
|
opening = null;
|
|
527
|
-
|
|
353
|
+
announced = null;
|
|
354
|
+
socket?.hold(rooms, runtime);
|
|
528
355
|
},
|
|
529
356
|
track(entries) {
|
|
530
|
-
|
|
357
|
+
tracking.clear();
|
|
531
358
|
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);
|
|
359
|
+
tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
|
|
540
360
|
}
|
|
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
|
-
}
|
|
361
|
+
for (const [carry, held] of staged) {
|
|
362
|
+
if (!tracking.has(held.authority))
|
|
363
|
+
staged.delete(carry);
|
|
618
364
|
}
|
|
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
365
|
},
|
|
636
366
|
};
|
|
637
367
|
}
|