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