@agentshouse/mdruntime-adapter 0.1.0-ca80960fd750d → 0.1.0-ca9b5ec924eff
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 +5 -59
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +11 -289
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +157 -358
- 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/chunks.d.ts +38 -0
- package/dist/chunks.d.ts.map +1 -0
- package/dist/chunks.js +247 -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 -15
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +75 -56
- 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 +682 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +394 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/model.d.ts +5 -8
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +32 -46
- package/dist/read.d.ts +21 -59
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +50 -330
- package/dist/refusal.d.ts +0 -3
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +0 -5
- package/dist/room-types.d.ts +2 -3
- package/dist/room-types.d.ts.map +1 -1
- package/dist/room-types.js +49 -12
- 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 -167
- 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 +16 -15
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +233 -423
- package/dist/transport.d.ts +47 -36
- 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 +18 -25
- package/package.json +7 -3
- package/AGENTS.md +0 -312
- package/dist/gather.d.ts +0 -4
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -35
- package/dist/part.d.ts +0 -15
- package/dist/part.d.ts.map +0 -1
- package/dist/part.js +0 -82
package/dist/stream.js
CHANGED
|
@@ -1,112 +1,114 @@
|
|
|
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 { keptSpaceSchemas, streamedModels } from './model.js';
|
|
4
|
+
import { answered, answering, binaryFileOf, createdOf, folded, forgotten, headChange, revised, } from './read.js';
|
|
5
|
+
import { houseDoorRoute, } from './transport.js';
|
|
6
|
+
import { DECIMAL, logPosition, presented, 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/list'), {});
|
|
13
|
+
const agents = answer.status === 200 ? answer.body?.agents : null;
|
|
14
|
+
if (!Array.isArray(agents))
|
|
15
|
+
return null;
|
|
16
|
+
return agents.flatMap((one) => {
|
|
17
|
+
const { id, name, retired_at: retired } = (one ?? {});
|
|
18
|
+
return typeof id === 'string' && typeof name === 'string'
|
|
19
|
+
? [{ agent: id, name, retired: retired !== null && retired !== undefined }]
|
|
20
|
+
: [];
|
|
21
|
+
});
|
|
22
|
+
}
|
|
11
23
|
function listedConversation(listed) {
|
|
12
24
|
return {
|
|
13
25
|
conversation: listed.conversation_id,
|
|
14
26
|
agent: listed.agent_id,
|
|
27
|
+
agentName: listed.agent_name,
|
|
28
|
+
agentRetired: listed.agent_retired,
|
|
15
29
|
name: listed.name,
|
|
16
30
|
created: listed.created_at,
|
|
17
31
|
finished: listed.finished_at,
|
|
18
32
|
outcome: listed.outcome,
|
|
19
33
|
waiting: listed.waiting,
|
|
34
|
+
newest: listed.newest === null ? null : cursorPosition(listed.newest),
|
|
35
|
+
processEnded: listed.process_ended_at,
|
|
20
36
|
};
|
|
21
37
|
}
|
|
22
38
|
function position(value) {
|
|
23
|
-
if (
|
|
39
|
+
if (!DECIMAL.test(value))
|
|
24
40
|
return null;
|
|
25
41
|
return BigInt(value);
|
|
26
42
|
}
|
|
27
|
-
function
|
|
28
|
-
const
|
|
29
|
-
let open = null;
|
|
43
|
+
function* changed(tracked, entries, version, schemas) {
|
|
44
|
+
const answer = answering();
|
|
30
45
|
for (const entry of entries) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
46
|
+
yield ROW_WEIGHT + (entry.text?.length ?? 0);
|
|
47
|
+
if (entry.kind === 'folder') {
|
|
48
|
+
folded(answer, entry.path, entry.removed === true);
|
|
49
|
+
continue;
|
|
35
50
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
if (entry.text === undefined)
|
|
44
|
-
return null;
|
|
45
|
-
open = { entry, texts: [entry.text] };
|
|
51
|
+
if (entry.path === tracked.schema)
|
|
52
|
+
schemas.set(entry.path, entry);
|
|
53
|
+
forgotten(answer, entry.path);
|
|
54
|
+
if (entry.space !== undefined) {
|
|
55
|
+
answer.removals.add(entry.path);
|
|
56
|
+
continue;
|
|
46
57
|
}
|
|
47
|
-
if (entry.
|
|
58
|
+
if (entry.kind === 'removed') {
|
|
59
|
+
answer.removals.add(entry.path);
|
|
48
60
|
continue;
|
|
49
|
-
const { continued: _continued, ...head } = open.entry;
|
|
50
|
-
whole.push({ ...head, text: open.texts.join('') });
|
|
51
|
-
open = null;
|
|
52
|
-
}
|
|
53
|
-
return open === null ? whole : null;
|
|
54
|
-
}
|
|
55
|
-
async function verified(entries) {
|
|
56
|
-
try {
|
|
57
|
-
for (const entry of entries) {
|
|
58
|
-
if (entry.text === undefined || entry.sha256 === undefined)
|
|
59
|
-
continue;
|
|
60
|
-
if ((await sha256Hex(entry.text)) !== entry.sha256)
|
|
61
|
-
return false;
|
|
62
61
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
const binary = binaryFileOf(entry);
|
|
63
|
+
if (binary === undefined)
|
|
64
|
+
answer.documents.set(entry.path, entry.text ?? '');
|
|
65
|
+
else if (binary !== null)
|
|
66
|
+
answer.binaryFiles.set(entry.path, binary);
|
|
67
|
+
if (binary === undefined && entry.facts !== undefined)
|
|
68
|
+
answer.facts.set(entry.path, entry.facts);
|
|
69
|
+
const revision = entry.revision ?? binary?.sha256;
|
|
70
|
+
if (revision !== undefined)
|
|
71
|
+
revised(answer, entry.path, revision);
|
|
72
|
+
const head = headChange(entry);
|
|
73
|
+
if (head)
|
|
74
|
+
answer.changes.set(entry.path, head);
|
|
75
|
+
const created = createdOf(entry);
|
|
76
|
+
if (created)
|
|
77
|
+
answer.created.set(entry.path, created);
|
|
67
78
|
}
|
|
79
|
+
return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
|
|
68
80
|
}
|
|
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
|
-
};
|
|
81
|
+
async function changePage(tracked, entries, version, mode, spaces, whole) {
|
|
82
|
+
const schemas = new Map();
|
|
83
|
+
const page = await stepped(changed(tracked, entries, version, schemas));
|
|
84
|
+
const models = await streamedModels(schemas, tracked, mode, spaces, whole);
|
|
85
|
+
return models === undefined ? page : { ...page, models };
|
|
89
86
|
}
|
|
90
|
-
export function houseNotifications(transport, mode) {
|
|
87
|
+
export function houseNotifications(transport, mode, discovering, spaces) {
|
|
91
88
|
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();
|
|
89
|
+
const staged = new Map();
|
|
90
|
+
let socket = null;
|
|
91
|
+
const tracking = new Map();
|
|
100
92
|
const observers = new Set();
|
|
93
|
+
const replaying = new Map();
|
|
101
94
|
const conversationObservers = new Set();
|
|
102
95
|
const modeObservers = new Set();
|
|
103
96
|
let replicated = [];
|
|
97
|
+
let listedCursor = null;
|
|
98
|
+
const unanswered = [];
|
|
99
|
+
const heldAtZero = new Set();
|
|
104
100
|
const live = new Set();
|
|
105
101
|
let opening = null;
|
|
102
|
+
let announced = null;
|
|
106
103
|
const runtime = crypto.randomUUID();
|
|
107
104
|
function emit(event) {
|
|
108
|
-
for (const observer of observers)
|
|
109
|
-
observer
|
|
105
|
+
for (const observer of observers) {
|
|
106
|
+
const held = replaying.get(observer);
|
|
107
|
+
if (held === undefined)
|
|
108
|
+
observer(event);
|
|
109
|
+
else
|
|
110
|
+
held.push(event);
|
|
111
|
+
}
|
|
110
112
|
}
|
|
111
113
|
function emitConversation(event) {
|
|
112
114
|
if (event.kind === 'turn' ||
|
|
@@ -115,6 +117,7 @@ export function houseNotifications(transport, mode) {
|
|
|
115
117
|
event.kind === 'commands' ||
|
|
116
118
|
event.kind === 'options' ||
|
|
117
119
|
event.kind === 'starting' ||
|
|
120
|
+
event.kind === 'subagents' ||
|
|
118
121
|
event.kind === 'link' ||
|
|
119
122
|
event.kind === 'deliveries') {
|
|
120
123
|
live.add(event.conversation);
|
|
@@ -124,12 +127,33 @@ export function houseNotifications(transport, mode) {
|
|
|
124
127
|
}
|
|
125
128
|
function reopened(next) {
|
|
126
129
|
opening = next;
|
|
127
|
-
|
|
130
|
+
announced = null;
|
|
131
|
+
socket = next;
|
|
132
|
+
staged.clear();
|
|
133
|
+
unanswered.length = 0;
|
|
134
|
+
heldAtZero.clear();
|
|
128
135
|
const gapped = new Set([...replicated, ...live]);
|
|
129
136
|
live.clear();
|
|
130
137
|
for (const conversation of gapped)
|
|
131
138
|
emitConversation({ kind: 'gap', conversation });
|
|
132
139
|
emit({ kind: 'opened' });
|
|
140
|
+
if (mode === 'site')
|
|
141
|
+
announce(next, null);
|
|
142
|
+
}
|
|
143
|
+
function announce(via, frame) {
|
|
144
|
+
void discovering.opened(frame).then((discovery) => {
|
|
145
|
+
if (socket !== via)
|
|
146
|
+
return;
|
|
147
|
+
if (discovery === null) {
|
|
148
|
+
via.close();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
announced = { kind: 'discovered', discovery };
|
|
152
|
+
emit(announced);
|
|
153
|
+
}, () => {
|
|
154
|
+
if (socket === via)
|
|
155
|
+
via.close();
|
|
156
|
+
});
|
|
133
157
|
}
|
|
134
158
|
function converse(frame) {
|
|
135
159
|
const conversation = frame.conversation_id;
|
|
@@ -148,6 +172,7 @@ export function houseNotifications(transport, mode) {
|
|
|
148
172
|
return;
|
|
149
173
|
emitConversation({ kind: 'commands', conversation, commands: [] });
|
|
150
174
|
emitConversation({ kind: 'options', conversation, options: [] });
|
|
175
|
+
emitConversation({ kind: 'subagents', conversation, subagents: [] });
|
|
151
176
|
return;
|
|
152
177
|
}
|
|
153
178
|
if (frame.type === 'commands') {
|
|
@@ -166,6 +191,14 @@ export function houseNotifications(transport, mode) {
|
|
|
166
191
|
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
167
192
|
return;
|
|
168
193
|
}
|
|
194
|
+
if (frame.type === 'subagents') {
|
|
195
|
+
emitConversation({
|
|
196
|
+
kind: 'subagents',
|
|
197
|
+
conversation,
|
|
198
|
+
subagents: structuredClone(frame.subagents),
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
169
202
|
if (frame.type === 'link') {
|
|
170
203
|
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
171
204
|
return;
|
|
@@ -187,171 +220,31 @@ export function houseNotifications(transport, mode) {
|
|
|
187
220
|
return;
|
|
188
221
|
emitConversation({ kind: 'accepted-message', conversation, message });
|
|
189
222
|
}
|
|
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);
|
|
223
|
+
function stage(frame, via) {
|
|
224
|
+
const held = staged.get(frame.carry);
|
|
225
|
+
if (frame.index !== (held?.parts ?? 0)) {
|
|
226
|
+
staged.delete(frame.carry);
|
|
223
227
|
return;
|
|
224
228
|
}
|
|
225
229
|
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;
|
|
230
|
+
for (const [carry, other] of staged) {
|
|
231
|
+
if (other.authority === frame.authority)
|
|
232
|
+
staged.delete(carry);
|
|
233
|
+
}
|
|
247
234
|
}
|
|
248
|
-
|
|
235
|
+
const next = held ?? { authority: frame.authority, parts: 0, entries: [] };
|
|
236
|
+
keptSpaceSchemas(frame.entries, spaces);
|
|
237
|
+
next.entries.push(...frame.entries);
|
|
238
|
+
next.parts += 1;
|
|
239
|
+
staged.set(frame.carry, next);
|
|
249
240
|
via?.received(frame.authority, frame.carry, frame.index);
|
|
250
241
|
}
|
|
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);
|
|
242
|
+
function carried(frame) {
|
|
243
|
+
const held = staged.get(frame.carry);
|
|
244
|
+
staged.delete(frame.carry);
|
|
245
|
+
if ((held?.parts ?? 0) !== frame.parts)
|
|
267
246
|
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);
|
|
291
|
-
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
|
-
};
|
|
247
|
+
publish(frame, held?.entries ?? []);
|
|
355
248
|
}
|
|
356
249
|
function handle(frame, via) {
|
|
357
250
|
if (frame.type === 'signal') {
|
|
@@ -363,18 +256,35 @@ export function houseNotifications(transport, mode) {
|
|
|
363
256
|
return;
|
|
364
257
|
}
|
|
365
258
|
if (frame.type === 'opening') {
|
|
259
|
+
if (via !== null && mode === 'credential')
|
|
260
|
+
announce(via, frame);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (frame.type === 'caught_up') {
|
|
264
|
+
discovering.expired?.(frame.expired);
|
|
366
265
|
emit({
|
|
367
|
-
kind: '
|
|
368
|
-
expired:
|
|
266
|
+
kind: 'caught-up',
|
|
267
|
+
expired: [
|
|
268
|
+
...frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
|
|
269
|
+
...(unanswered.shift() ?? []),
|
|
270
|
+
],
|
|
369
271
|
});
|
|
370
272
|
return;
|
|
371
273
|
}
|
|
372
274
|
if (frame.type === 'authority_changed') {
|
|
373
|
-
|
|
275
|
+
const change = discovering.changed(frame);
|
|
276
|
+
if (change !== null)
|
|
277
|
+
emit(change);
|
|
374
278
|
return;
|
|
375
279
|
}
|
|
376
280
|
if (frame.type === 'conversations') {
|
|
377
|
-
emitConversation({
|
|
281
|
+
emitConversation({
|
|
282
|
+
kind: 'list',
|
|
283
|
+
entries: frame.conversations.map(listedConversation),
|
|
284
|
+
whole: frame.whole,
|
|
285
|
+
more: frame.more,
|
|
286
|
+
cursor: frame.cursor,
|
|
287
|
+
});
|
|
378
288
|
return;
|
|
379
289
|
}
|
|
380
290
|
if (frame.type === 'conversation') {
|
|
@@ -390,6 +300,7 @@ export function houseNotifications(transport, mode) {
|
|
|
390
300
|
frame.type === 'commands' ||
|
|
391
301
|
frame.type === 'options' ||
|
|
392
302
|
frame.type === 'starting' ||
|
|
303
|
+
frame.type === 'subagents' ||
|
|
393
304
|
frame.type === 'link' ||
|
|
394
305
|
frame.type === 'deliveries' ||
|
|
395
306
|
frame.type === 'interactions' ||
|
|
@@ -398,57 +309,39 @@ export function houseNotifications(transport, mode) {
|
|
|
398
309
|
return;
|
|
399
310
|
}
|
|
400
311
|
if (frame.type === 'part')
|
|
401
|
-
|
|
402
|
-
if (frame.type === 'carried')
|
|
403
|
-
|
|
312
|
+
stage(frame, via);
|
|
313
|
+
else if (frame.type === 'carried')
|
|
314
|
+
carried(frame);
|
|
404
315
|
}
|
|
405
316
|
function publish(frame, entries) {
|
|
406
317
|
const at = position(frame.position);
|
|
407
318
|
const after = position(frame.after);
|
|
408
|
-
if (at === null || after === null || after >= at)
|
|
409
|
-
interrupt(frame.authority);
|
|
319
|
+
if (at === null || after === null || after >= at)
|
|
410
320
|
return;
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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;
|
|
321
|
+
const from = after === 0n && !heldAtZero.has(frame.authority)
|
|
322
|
+
? null
|
|
323
|
+
: roomVersion({ position: frame.after, logEpoch: frame.log_epoch });
|
|
324
|
+
const version = roomVersion({ position: frame.position, logEpoch: frame.log_epoch });
|
|
325
|
+
for (const tracked of tracking.get(frame.authority) ?? []) {
|
|
326
|
+
emit({
|
|
327
|
+
kind: 'room-change',
|
|
328
|
+
locator: tracked.locator,
|
|
329
|
+
from,
|
|
330
|
+
roomVersion: version,
|
|
331
|
+
read: () => changePage(tracked, entries, version, mode, spaces, from === null),
|
|
437
332
|
});
|
|
438
|
-
return;
|
|
439
333
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
.then(() => handle(frame, via))
|
|
443
|
-
.finally(() => {
|
|
444
|
-
verifying -= 1;
|
|
445
|
-
});
|
|
446
|
-
});
|
|
334
|
+
}
|
|
335
|
+
stream.observe((frame) => handle(frame, socket));
|
|
447
336
|
stream.opened(reopened);
|
|
448
|
-
stream.closed(({ revoked, lost }) => {
|
|
337
|
+
stream.closed(({ revoked, lost, authorityChanged }) => {
|
|
449
338
|
opening = null;
|
|
450
|
-
|
|
451
|
-
|
|
339
|
+
announced = null;
|
|
340
|
+
socket = null;
|
|
341
|
+
staged.clear();
|
|
342
|
+
unanswered.length = 0;
|
|
343
|
+
heldAtZero.clear();
|
|
344
|
+
emit({ kind: 'closed', revoked, lost, authorityChanged });
|
|
452
345
|
});
|
|
453
346
|
return {
|
|
454
347
|
runtime,
|
|
@@ -464,23 +357,34 @@ export function houseNotifications(transport, mode) {
|
|
|
464
357
|
replicate(next) {
|
|
465
358
|
replicated = [...next];
|
|
466
359
|
},
|
|
360
|
+
hold(cursor) {
|
|
361
|
+
listedCursor = cursor;
|
|
362
|
+
},
|
|
467
363
|
observe(notify) {
|
|
468
364
|
conversationObservers.add(notify);
|
|
469
365
|
return () => {
|
|
470
366
|
conversationObservers.delete(notify);
|
|
471
367
|
};
|
|
472
368
|
},
|
|
369
|
+
...(mode === 'credential'
|
|
370
|
+
? {
|
|
371
|
+
agents: () => houseAgents(transport),
|
|
372
|
+
history: (request) => houseHistory(transport, request),
|
|
373
|
+
}
|
|
374
|
+
: {}),
|
|
473
375
|
},
|
|
474
|
-
observe(notify
|
|
376
|
+
observe(notify) {
|
|
475
377
|
observers.add(notify);
|
|
476
|
-
if (receipts === null) {
|
|
477
|
-
receipts = port;
|
|
478
|
-
loaded = load(port);
|
|
479
|
-
}
|
|
480
378
|
if (opening !== null) {
|
|
379
|
+
const replayed = [{ kind: 'opened' }];
|
|
380
|
+
if (announced !== null)
|
|
381
|
+
replayed.push(announced);
|
|
382
|
+
replaying.set(notify, replayed);
|
|
481
383
|
queueMicrotask(() => {
|
|
482
|
-
|
|
483
|
-
|
|
384
|
+
replaying.delete(notify);
|
|
385
|
+
for (const event of replayed)
|
|
386
|
+
if (observers.has(notify))
|
|
387
|
+
notify(event);
|
|
484
388
|
});
|
|
485
389
|
}
|
|
486
390
|
return () => {
|
|
@@ -488,153 +392,59 @@ export function houseNotifications(transport, mode) {
|
|
|
488
392
|
};
|
|
489
393
|
},
|
|
490
394
|
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
395
|
opening = null;
|
|
500
|
-
|
|
396
|
+
announced = null;
|
|
397
|
+
if (socket === null)
|
|
501
398
|
return;
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
if (room.position === rooms[index].position)
|
|
508
|
-
continue;
|
|
509
|
-
announce(room.authority, { position: room.position, logEpoch: room.log_epoch });
|
|
510
|
-
}
|
|
399
|
+
const entries = new Map([...tracking.values()].flat().map((tracked) => [tracked.locator, tracked]));
|
|
400
|
+
const named = rooms.flatMap((room) => {
|
|
401
|
+
const entry = entries.get(room.locator);
|
|
402
|
+
const at = room.roomVersion === null ? null : logPosition(room.roomVersion);
|
|
403
|
+
return entry === undefined || at === null ? [] : [{ entry, at }];
|
|
511
404
|
});
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
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();
|
|
529
|
-
},
|
|
530
|
-
track(entries) {
|
|
531
|
-
locators.clear();
|
|
532
|
-
for (const entry of entries) {
|
|
533
|
-
locators.set(entry.authority, [...(locators.get(entry.authority) ?? []), entry.locator]);
|
|
534
|
-
if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
|
|
535
|
-
lines.set(entry.authority, { logEpoch: entry.logEpoch, frames: [], held: null });
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
for (const authority of lines.keys()) {
|
|
539
|
-
if (!locators.has(authority))
|
|
540
|
-
lines.delete(authority);
|
|
405
|
+
const unheld = rooms.flatMap((room) => {
|
|
406
|
+
const entry = entries.get(room.locator);
|
|
407
|
+
return entry === undefined || room.roomVersion !== null ? [] : [entry];
|
|
408
|
+
});
|
|
409
|
+
for (const { entry, at } of named) {
|
|
410
|
+
if (at.position === '0')
|
|
411
|
+
heldAtZero.add(entry.authority);
|
|
412
|
+
else
|
|
413
|
+
heldAtZero.delete(entry.authority);
|
|
541
414
|
}
|
|
542
|
-
|
|
543
|
-
.
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
415
|
+
for (const entry of unheld)
|
|
416
|
+
heldAtZero.delete(entry.authority);
|
|
417
|
+
const site = mode === 'site';
|
|
418
|
+
unanswered.push(site ? unheld.map((entry) => entry.locator) : []);
|
|
419
|
+
socket.hold([
|
|
420
|
+
...named.map(({ entry, at }) => presented(entry.authority, at)),
|
|
421
|
+
...(site ? [] : unheld).map((entry) => presented(entry.authority, { position: '0', logEpoch: entry.logEpoch })),
|
|
422
|
+
], runtime, listedCursor);
|
|
423
|
+
if (site)
|
|
550
424
|
return;
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
425
|
+
const made = unheld.filter((entry) => entry.position === '0');
|
|
426
|
+
queueMicrotask(() => {
|
|
427
|
+
for (const entry of made) {
|
|
428
|
+
const version = roomVersion(entry);
|
|
429
|
+
emit({
|
|
430
|
+
kind: 'room-change',
|
|
431
|
+
locator: entry.locator,
|
|
432
|
+
from: null,
|
|
433
|
+
roomVersion: version,
|
|
434
|
+
read: () => changePage(entry, [], version, mode, spaces, true),
|
|
435
|
+
});
|
|
436
|
+
}
|
|
557
437
|
});
|
|
558
438
|
},
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
const
|
|
562
|
-
|
|
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
|
-
}
|
|
439
|
+
track(entries) {
|
|
440
|
+
tracking.clear();
|
|
441
|
+
for (const entry of entries) {
|
|
442
|
+
tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
|
|
620
443
|
}
|
|
621
|
-
const
|
|
622
|
-
|
|
623
|
-
|
|
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
|
-
});
|
|
444
|
+
for (const [carry, held] of staged) {
|
|
445
|
+
if (!tracking.has(held.authority))
|
|
446
|
+
staged.delete(carry);
|
|
629
447
|
}
|
|
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
448
|
},
|
|
639
449
|
};
|
|
640
450
|
}
|