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