@agentshouse/mdruntime-adapter 0.1.0-cedab65f24a09 → 0.1.0-cf059d0c8e9c0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/actions.d.ts +3 -65
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +1 -336
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +220 -371
- package/dist/app-reference.d.ts +2 -0
- package/dist/app-reference.d.ts.map +1 -0
- package/dist/app-reference.js +2 -0
- package/dist/crockford.d.ts +4 -0
- package/dist/crockford.d.ts.map +1 -0
- package/dist/crockford.js +3 -0
- package/dist/discovery.d.ts +13 -12
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +62 -51
- package/dist/history.d.ts +12 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +91 -0
- package/dist/house-model.d.ts +2249 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +1237 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/model.d.ts +5 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +10 -29
- package/dist/part.d.ts +14 -0
- package/dist/part.d.ts.map +1 -0
- package/dist/part.js +90 -0
- package/dist/read.d.ts +46 -63
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +216 -283
- package/dist/refusal.d.ts +0 -3
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +0 -5
- package/dist/room-stream.d.ts +19 -0
- package/dist/room-stream.d.ts.map +1 -0
- package/dist/room-stream.js +57 -0
- package/dist/room-types.d.ts +7 -0
- package/dist/room-types.d.ts.map +1 -0
- package/dist/room-types.js +126 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +84 -195
- package/dist/stream.d.ts +13 -14
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +181 -422
- package/dist/transport.d.ts +62 -39
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +53 -11
- package/dist/upload.d.ts +12 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +63 -0
- package/dist/write.d.ts +16 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +100 -55
- package/package.json +8 -4
- package/AGENTS.md +0 -299
- package/dist/gather.d.ts +0 -4
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -45
- package/dist/handed.d.ts +0 -15
- package/dist/handed.d.ts.map +0 -1
- package/dist/handed.js +0 -38
- package/dist/referrer.d.ts +0 -7
- package/dist/referrer.d.ts.map +0 -1
- package/dist/referrer.js +0 -35
package/dist/stream.js
CHANGED
|
@@ -1,106 +1,92 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { ROW_WEIGHT, stepped, } from '@agentshouse/mdruntime';
|
|
2
|
+
import { acceptedMessage, cursorPosition, houseHistory } from './history.js';
|
|
3
|
+
import { streamedModels } from './model.js';
|
|
4
|
+
import { answered, answering, binaryFileOf, folded, forgotten, headChange, revised, } from './read.js';
|
|
5
|
+
import { houseDoorRoute, } from './transport.js';
|
|
6
|
+
import { DECIMAL, roomVersion } from './version.js';
|
|
6
7
|
function turnOperation(frame) {
|
|
7
8
|
const { type: _type, conversation_id: _conversation, turn_id: _turn, ...operation } = frame;
|
|
8
9
|
return structuredClone(operation);
|
|
9
10
|
}
|
|
11
|
+
async function houseAgents(transport) {
|
|
12
|
+
const answer = await transport.door(houseDoorRoute('agents/read'), {});
|
|
13
|
+
const agents = answer.status === 200 ? answer.body?.agents : null;
|
|
14
|
+
if (!Array.isArray(agents))
|
|
15
|
+
return null;
|
|
16
|
+
return agents.flatMap((one) => {
|
|
17
|
+
const { id, name, retired_at: retired } = (one ?? {});
|
|
18
|
+
return typeof id === 'string' && typeof name === 'string'
|
|
19
|
+
? [{ agent: id, name, retired: retired !== null && retired !== undefined }]
|
|
20
|
+
: [];
|
|
21
|
+
});
|
|
22
|
+
}
|
|
10
23
|
function listedConversation(listed) {
|
|
11
24
|
return {
|
|
12
25
|
conversation: listed.conversation_id,
|
|
13
26
|
agent: listed.agent_id,
|
|
27
|
+
agentName: listed.agent_name,
|
|
28
|
+
agentRetired: listed.agent_retired,
|
|
14
29
|
name: listed.name,
|
|
15
30
|
created: listed.created_at,
|
|
16
31
|
finished: listed.finished_at,
|
|
17
32
|
outcome: listed.outcome,
|
|
33
|
+
waiting: listed.waiting,
|
|
34
|
+
newest: listed.newest === null ? null : cursorPosition(listed.newest),
|
|
18
35
|
};
|
|
19
36
|
}
|
|
20
37
|
function position(value) {
|
|
21
|
-
if (
|
|
38
|
+
if (!DECIMAL.test(value))
|
|
22
39
|
return null;
|
|
23
40
|
return BigInt(value);
|
|
24
41
|
}
|
|
25
|
-
function
|
|
26
|
-
const
|
|
27
|
-
let open = null;
|
|
42
|
+
function* changed(tracked, entries, version, schemas) {
|
|
43
|
+
const answer = answering();
|
|
28
44
|
for (const entry of entries) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
if (open !== null)
|
|
36
|
-
return null;
|
|
37
|
-
if (entry.continued !== true) {
|
|
38
|
-
whole.push(entry);
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (entry.text === undefined)
|
|
42
|
-
return null;
|
|
43
|
-
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;
|
|
44
49
|
}
|
|
45
|
-
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);
|
|
46
55
|
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
56
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
const binary = binaryFileOf(entry);
|
|
58
|
+
if (binary === undefined)
|
|
59
|
+
answer.documents.set(entry.path, entry.text ?? '');
|
|
60
|
+
else if (binary !== null)
|
|
61
|
+
answer.binaryFiles.set(entry.path, binary);
|
|
62
|
+
const revision = entry.revision ?? binary?.sha256;
|
|
63
|
+
if (revision !== undefined)
|
|
64
|
+
revised(answer, entry.path, revision);
|
|
65
|
+
const head = headChange(entry);
|
|
66
|
+
if (head)
|
|
67
|
+
answer.changes.set(entry.path, head);
|
|
65
68
|
}
|
|
69
|
+
return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
|
|
66
70
|
}
|
|
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
|
-
};
|
|
71
|
+
async function changePage(tracked, entries, version, mode) {
|
|
72
|
+
const schemas = new Map();
|
|
73
|
+
const page = await stepped(changed(tracked, entries, version, schemas));
|
|
74
|
+
const models = await streamedModels(schemas, tracked, mode);
|
|
75
|
+
return models === undefined ? page : { ...page, models };
|
|
87
76
|
}
|
|
88
|
-
export function houseNotifications(transport, mode) {
|
|
77
|
+
export function houseNotifications(transport, mode, discovering) {
|
|
89
78
|
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();
|
|
79
|
+
const staged = new Map();
|
|
80
|
+
let socket = null;
|
|
81
|
+
const tracking = new Map();
|
|
98
82
|
const observers = new Set();
|
|
99
83
|
const conversationObservers = new Set();
|
|
100
84
|
const modeObservers = new Set();
|
|
101
85
|
let replicated = [];
|
|
86
|
+
let listedCursor = null;
|
|
102
87
|
const live = new Set();
|
|
103
88
|
let opening = null;
|
|
89
|
+
let announced = null;
|
|
104
90
|
const runtime = crypto.randomUUID();
|
|
105
91
|
function emit(event) {
|
|
106
92
|
for (const observer of observers)
|
|
@@ -111,7 +97,11 @@ export function houseNotifications(transport, mode) {
|
|
|
111
97
|
event.kind === 'questions' ||
|
|
112
98
|
event.kind === 'process' ||
|
|
113
99
|
event.kind === 'commands' ||
|
|
114
|
-
event.kind === 'options'
|
|
100
|
+
event.kind === 'options' ||
|
|
101
|
+
event.kind === 'starting' ||
|
|
102
|
+
event.kind === 'subagents' ||
|
|
103
|
+
event.kind === 'link' ||
|
|
104
|
+
event.kind === 'deliveries') {
|
|
115
105
|
live.add(event.conversation);
|
|
116
106
|
}
|
|
117
107
|
for (const observer of conversationObservers)
|
|
@@ -119,12 +109,31 @@ export function houseNotifications(transport, mode) {
|
|
|
119
109
|
}
|
|
120
110
|
function reopened(next) {
|
|
121
111
|
opening = next;
|
|
122
|
-
|
|
112
|
+
announced = null;
|
|
113
|
+
socket = next;
|
|
114
|
+
staged.clear();
|
|
123
115
|
const gapped = new Set([...replicated, ...live]);
|
|
124
116
|
live.clear();
|
|
125
117
|
for (const conversation of gapped)
|
|
126
118
|
emitConversation({ kind: 'gap', conversation });
|
|
127
119
|
emit({ kind: 'opened' });
|
|
120
|
+
if (mode === 'site')
|
|
121
|
+
announce(next, null);
|
|
122
|
+
}
|
|
123
|
+
function announce(via, frame) {
|
|
124
|
+
void discovering.opened(frame).then((discovery) => {
|
|
125
|
+
if (socket !== via)
|
|
126
|
+
return;
|
|
127
|
+
if (discovery === null) {
|
|
128
|
+
via.close();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
announced = { kind: 'discovered', discovery };
|
|
132
|
+
emit(announced);
|
|
133
|
+
}, () => {
|
|
134
|
+
if (socket === via)
|
|
135
|
+
via.close();
|
|
136
|
+
});
|
|
128
137
|
}
|
|
129
138
|
function converse(frame) {
|
|
130
139
|
const conversation = frame.conversation_id;
|
|
@@ -143,6 +152,7 @@ export function houseNotifications(transport, mode) {
|
|
|
143
152
|
return;
|
|
144
153
|
emitConversation({ kind: 'commands', conversation, commands: [] });
|
|
145
154
|
emitConversation({ kind: 'options', conversation, options: [] });
|
|
155
|
+
emitConversation({ kind: 'subagents', conversation, subagents: [] });
|
|
146
156
|
return;
|
|
147
157
|
}
|
|
148
158
|
if (frame.type === 'commands') {
|
|
@@ -157,6 +167,26 @@ export function houseNotifications(transport, mode) {
|
|
|
157
167
|
emitConversation({ kind: 'options', conversation, options: structuredClone(frame.options) });
|
|
158
168
|
return;
|
|
159
169
|
}
|
|
170
|
+
if (frame.type === 'starting') {
|
|
171
|
+
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
if (frame.type === 'subagents') {
|
|
175
|
+
emitConversation({
|
|
176
|
+
kind: 'subagents',
|
|
177
|
+
conversation,
|
|
178
|
+
subagents: structuredClone(frame.subagents),
|
|
179
|
+
});
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (frame.type === 'link') {
|
|
183
|
+
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (frame.type === 'deliveries') {
|
|
187
|
+
emitConversation({ kind: 'deliveries', conversation, unknown: [...frame.unknown] });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
160
190
|
if (frame.type === 'interactions') {
|
|
161
191
|
emitConversation({
|
|
162
192
|
kind: 'questions',
|
|
@@ -170,171 +200,30 @@ export function houseNotifications(transport, mode) {
|
|
|
170
200
|
return;
|
|
171
201
|
emitConversation({ kind: 'accepted-message', conversation, message });
|
|
172
202
|
}
|
|
173
|
-
function
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
function interrupt(authority) {
|
|
180
|
-
const line = lines.get(authority);
|
|
181
|
-
if (line !== undefined)
|
|
182
|
-
lines.set(authority, { ...line, frames: [] });
|
|
183
|
-
}
|
|
184
|
-
async function forget(carries) {
|
|
185
|
-
const held = carries.filter((carry) => kept.delete(carry));
|
|
186
|
-
if (held.length > 0)
|
|
187
|
-
await receipts?.drop(held).catch(() => { });
|
|
188
|
-
}
|
|
189
|
-
async function lost(authority, carry) {
|
|
190
|
-
interrupt(authority);
|
|
191
|
-
await forget([carry]);
|
|
192
|
-
}
|
|
193
|
-
async function stage(frame, via) {
|
|
194
|
-
await loaded;
|
|
195
|
-
const port = receipts;
|
|
196
|
-
if (port === null)
|
|
197
|
-
return;
|
|
198
|
-
const held = kept.get(frame.carry);
|
|
199
|
-
if (held === undefined && frame.index !== 0) {
|
|
200
|
-
interrupt(frame.authority);
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
if (held !== undefined &&
|
|
204
|
-
(held.fenced !== null || frame.index > held.parts || frame.index < (held.resume?.parts ?? 0))) {
|
|
205
|
-
await lost(frame.authority, frame.carry);
|
|
203
|
+
function stage(frame, via) {
|
|
204
|
+
const held = staged.get(frame.carry);
|
|
205
|
+
if (frame.index !== (held?.parts ?? 0)) {
|
|
206
|
+
staged.delete(frame.carry);
|
|
206
207
|
return;
|
|
207
208
|
}
|
|
208
209
|
if (held === undefined) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const start = held ?? {
|
|
214
|
-
authority: frame.authority,
|
|
215
|
-
carry: frame.carry,
|
|
216
|
-
logEpoch: lines.get(frame.authority)?.logEpoch ?? null,
|
|
217
|
-
after: frame.after,
|
|
218
|
-
parts: 0,
|
|
219
|
-
resume: null,
|
|
220
|
-
fenced: null,
|
|
221
|
-
};
|
|
222
|
-
const next = { ...start, parts: frame.index + 1, resume: resumed(start, frame) };
|
|
223
|
-
const part = { entries: frame.entries };
|
|
224
|
-
try {
|
|
225
|
-
await port.keep(frame.carry, next, { index: frame.index, value: part });
|
|
226
|
-
}
|
|
227
|
-
catch {
|
|
228
|
-
await lost(frame.authority, frame.carry);
|
|
229
|
-
return;
|
|
210
|
+
for (const [carry, other] of staged) {
|
|
211
|
+
if (other.authority === frame.authority)
|
|
212
|
+
staged.delete(carry);
|
|
213
|
+
}
|
|
230
214
|
}
|
|
231
|
-
|
|
215
|
+
const next = held ?? { authority: frame.authority, parts: 0, entries: [] };
|
|
216
|
+
next.entries.push(...frame.entries);
|
|
217
|
+
next.parts += 1;
|
|
218
|
+
staged.set(frame.carry, next);
|
|
232
219
|
via?.received(frame.authority, frame.carry, frame.index);
|
|
233
220
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (
|
|
238
|
-
return null;
|
|
239
|
-
const read = (await receipts.parts(carry, parts));
|
|
240
|
-
if (read.length !== parts)
|
|
241
|
-
return null;
|
|
242
|
-
const entries = assembled(read.flatMap((part) => part.entries));
|
|
243
|
-
return entries !== null && (await verified(entries)) ? entries : null;
|
|
244
|
-
}
|
|
245
|
-
async function carried(frame) {
|
|
246
|
-
await loaded;
|
|
247
|
-
const held = kept.get(frame.carry);
|
|
248
|
-
if (frame.parts > 0 && held?.parts !== frame.parts) {
|
|
249
|
-
await lost(frame.authority, frame.carry);
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
const entries = await keptEntries(frame.carry, frame.parts).catch(() => null);
|
|
253
|
-
if (entries === null) {
|
|
254
|
-
await lost(frame.authority, frame.carry);
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
const fenced = {
|
|
258
|
-
...(held ?? {
|
|
259
|
-
authority: frame.authority,
|
|
260
|
-
carry: frame.carry,
|
|
261
|
-
logEpoch: frame.log_epoch,
|
|
262
|
-
after: frame.after,
|
|
263
|
-
parts: 0,
|
|
264
|
-
resume: null,
|
|
265
|
-
}),
|
|
266
|
-
after: frame.after,
|
|
267
|
-
fenced: { position: frame.position, logEpoch: frame.log_epoch },
|
|
268
|
-
};
|
|
269
|
-
try {
|
|
270
|
-
await receipts?.keep(frame.carry, fenced);
|
|
271
|
-
}
|
|
272
|
-
catch {
|
|
273
|
-
await lost(frame.authority, frame.carry);
|
|
221
|
+
function carried(frame) {
|
|
222
|
+
const held = staged.get(frame.carry);
|
|
223
|
+
staged.delete(frame.carry);
|
|
224
|
+
if ((held?.parts ?? 0) !== frame.parts)
|
|
274
225
|
return;
|
|
275
|
-
|
|
276
|
-
kept.set(frame.carry, fenced);
|
|
277
|
-
publish(frame, entries);
|
|
278
|
-
}
|
|
279
|
-
async function load(port) {
|
|
280
|
-
try {
|
|
281
|
-
for (const { key, head } of await port.heads())
|
|
282
|
-
kept.set(key, head);
|
|
283
|
-
}
|
|
284
|
-
catch {
|
|
285
|
-
kept.clear();
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
async function restored(room) {
|
|
289
|
-
const line = lines.get(room.authority);
|
|
290
|
-
let at = room.position;
|
|
291
|
-
const chain = [];
|
|
292
|
-
for (;;) {
|
|
293
|
-
const next = [...kept.values()].find((carry) => carry.authority === room.authority &&
|
|
294
|
-
carry.after === at &&
|
|
295
|
-
carry.fenced?.logEpoch === room.log_epoch);
|
|
296
|
-
if (next?.fenced == null)
|
|
297
|
-
break;
|
|
298
|
-
const entries = await keptEntries(next.carry, next.parts).catch(() => null);
|
|
299
|
-
if (entries === null)
|
|
300
|
-
break;
|
|
301
|
-
chain.push({ carry: next, entries });
|
|
302
|
-
at = next.fenced.position;
|
|
303
|
-
}
|
|
304
|
-
const partial = [...kept.values()].find((carry) => carry.authority === room.authority &&
|
|
305
|
-
carry.fenced === null &&
|
|
306
|
-
carry.logEpoch === room.log_epoch &&
|
|
307
|
-
carry.after === at &&
|
|
308
|
-
carry.resume !== null &&
|
|
309
|
-
carry.resume.parts > 0);
|
|
310
|
-
const stale = [...kept.values()].filter((carry) => carry.authority === room.authority &&
|
|
311
|
-
carry !== partial &&
|
|
312
|
-
!chain.some((link) => link.carry === carry));
|
|
313
|
-
await forget(stale.map((carry) => carry.carry));
|
|
314
|
-
if (line !== undefined && line.logEpoch === room.log_epoch && chain.length > 0) {
|
|
315
|
-
const frames = chain.map(({ carry, entries }) => ({
|
|
316
|
-
after: BigInt(carry.after),
|
|
317
|
-
position: BigInt(carry.fenced.position),
|
|
318
|
-
entries,
|
|
319
|
-
}));
|
|
320
|
-
lines.set(room.authority, { ...line, frames: [...line.frames, ...frames] });
|
|
321
|
-
}
|
|
322
|
-
return {
|
|
323
|
-
...room,
|
|
324
|
-
position: at,
|
|
325
|
-
...(partial?.resume == null
|
|
326
|
-
? {}
|
|
327
|
-
: {
|
|
328
|
-
carry: {
|
|
329
|
-
id: partial.carry,
|
|
330
|
-
parts: partial.resume.parts,
|
|
331
|
-
from: partial.resume.from,
|
|
332
|
-
target: partial.resume.target,
|
|
333
|
-
handled: partial.resume.handled,
|
|
334
|
-
...(partial.resume.piece === null ? {} : { piece: partial.resume.piece }),
|
|
335
|
-
},
|
|
336
|
-
}),
|
|
337
|
-
};
|
|
226
|
+
publish(frame, held?.entries ?? []);
|
|
338
227
|
}
|
|
339
228
|
function handle(frame, via) {
|
|
340
229
|
if (frame.type === 'signal') {
|
|
@@ -346,18 +235,31 @@ export function houseNotifications(transport, mode) {
|
|
|
346
235
|
return;
|
|
347
236
|
}
|
|
348
237
|
if (frame.type === 'opening') {
|
|
238
|
+
if (via !== null && mode === 'credential')
|
|
239
|
+
announce(via, frame);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (frame.type === 'caught_up') {
|
|
349
243
|
emit({
|
|
350
|
-
kind: '
|
|
351
|
-
expired: frame.expired.flatMap((authority) =>
|
|
244
|
+
kind: 'caught-up',
|
|
245
|
+
expired: frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
|
|
352
246
|
});
|
|
353
247
|
return;
|
|
354
248
|
}
|
|
355
249
|
if (frame.type === 'authority_changed') {
|
|
356
|
-
|
|
250
|
+
const change = discovering.changed(frame);
|
|
251
|
+
if (change !== null)
|
|
252
|
+
emit(change);
|
|
357
253
|
return;
|
|
358
254
|
}
|
|
359
255
|
if (frame.type === 'conversations') {
|
|
360
|
-
emitConversation({
|
|
256
|
+
emitConversation({
|
|
257
|
+
kind: 'list',
|
|
258
|
+
entries: frame.conversations.map(listedConversation),
|
|
259
|
+
whole: frame.whole,
|
|
260
|
+
more: frame.more,
|
|
261
|
+
cursor: frame.cursor,
|
|
262
|
+
});
|
|
361
263
|
return;
|
|
362
264
|
}
|
|
363
265
|
if (frame.type === 'conversation') {
|
|
@@ -372,62 +274,44 @@ export function houseNotifications(transport, mode) {
|
|
|
372
274
|
frame.type === 'process' ||
|
|
373
275
|
frame.type === 'commands' ||
|
|
374
276
|
frame.type === 'options' ||
|
|
277
|
+
frame.type === 'starting' ||
|
|
278
|
+
frame.type === 'subagents' ||
|
|
279
|
+
frame.type === 'link' ||
|
|
280
|
+
frame.type === 'deliveries' ||
|
|
375
281
|
frame.type === 'interactions' ||
|
|
376
282
|
frame.type === 'message') {
|
|
377
283
|
converse(frame);
|
|
378
284
|
return;
|
|
379
285
|
}
|
|
380
286
|
if (frame.type === 'part')
|
|
381
|
-
|
|
382
|
-
if (frame.type === 'carried')
|
|
383
|
-
|
|
287
|
+
stage(frame, via);
|
|
288
|
+
else if (frame.type === 'carried')
|
|
289
|
+
carried(frame);
|
|
384
290
|
}
|
|
385
291
|
function publish(frame, entries) {
|
|
386
292
|
const at = position(frame.position);
|
|
387
293
|
const after = position(frame.after);
|
|
388
|
-
if (at === null || after === null || after >= at)
|
|
389
|
-
interrupt(frame.authority);
|
|
294
|
+
if (at === null || after === null || after >= at)
|
|
390
295
|
return;
|
|
391
|
-
}
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
const next = last !== undefined && after <= last.position ? [...line.frames, held] : [held];
|
|
401
|
-
lines.set(frame.authority, { ...line, frames: next.length > HELD_FRAMES_MAX ? [] : next });
|
|
402
|
-
}
|
|
403
|
-
else {
|
|
404
|
-
interrupt(frame.authority);
|
|
405
|
-
}
|
|
406
|
-
announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });
|
|
407
|
-
}
|
|
408
|
-
stream.observe((frame) => {
|
|
409
|
-
const via = acknowledging;
|
|
410
|
-
if (verifying === 0) {
|
|
411
|
-
const handled = handle(frame, via);
|
|
412
|
-
if (handled === undefined)
|
|
413
|
-
return;
|
|
414
|
-
verifying += 1;
|
|
415
|
-
receiving = handled.finally(() => {
|
|
416
|
-
verifying -= 1;
|
|
296
|
+
const from = roomVersion({ position: frame.after, logEpoch: frame.log_epoch });
|
|
297
|
+
const version = roomVersion({ position: frame.position, logEpoch: frame.log_epoch });
|
|
298
|
+
for (const tracked of tracking.get(frame.authority) ?? []) {
|
|
299
|
+
emit({
|
|
300
|
+
kind: 'room-change',
|
|
301
|
+
locator: tracked.locator,
|
|
302
|
+
from,
|
|
303
|
+
roomVersion: version,
|
|
304
|
+
read: () => changePage(tracked, entries, version, mode),
|
|
417
305
|
});
|
|
418
|
-
return;
|
|
419
306
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
.then(() => handle(frame, via))
|
|
423
|
-
.finally(() => {
|
|
424
|
-
verifying -= 1;
|
|
425
|
-
});
|
|
426
|
-
});
|
|
307
|
+
}
|
|
308
|
+
stream.observe((frame) => handle(frame, socket));
|
|
427
309
|
stream.opened(reopened);
|
|
428
310
|
stream.closed(({ revoked, lost }) => {
|
|
429
311
|
opening = null;
|
|
430
|
-
|
|
312
|
+
announced = null;
|
|
313
|
+
socket = null;
|
|
314
|
+
staged.clear();
|
|
431
315
|
emit({ kind: 'closed', revoked, lost });
|
|
432
316
|
});
|
|
433
317
|
return {
|
|
@@ -444,23 +328,30 @@ export function houseNotifications(transport, mode) {
|
|
|
444
328
|
replicate(next) {
|
|
445
329
|
replicated = [...next];
|
|
446
330
|
},
|
|
331
|
+
hold(cursor) {
|
|
332
|
+
listedCursor = cursor;
|
|
333
|
+
},
|
|
447
334
|
observe(notify) {
|
|
448
335
|
conversationObservers.add(notify);
|
|
449
336
|
return () => {
|
|
450
337
|
conversationObservers.delete(notify);
|
|
451
338
|
};
|
|
452
339
|
},
|
|
340
|
+
...(mode === 'credential'
|
|
341
|
+
? {
|
|
342
|
+
agents: () => houseAgents(transport),
|
|
343
|
+
history: (request) => houseHistory(transport, request),
|
|
344
|
+
}
|
|
345
|
+
: {}),
|
|
453
346
|
},
|
|
454
|
-
observe(notify
|
|
347
|
+
observe(notify) {
|
|
455
348
|
observers.add(notify);
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
loaded = load(port);
|
|
459
|
-
}
|
|
460
|
-
if (opening !== null) {
|
|
349
|
+
const replayed = opening === null ? [] : [{ kind: 'opened' }, announced];
|
|
350
|
+
if (replayed.length > 0) {
|
|
461
351
|
queueMicrotask(() => {
|
|
462
|
-
|
|
463
|
-
|
|
352
|
+
for (const event of replayed)
|
|
353
|
+
if (event !== null && observers.has(notify))
|
|
354
|
+
notify(event);
|
|
464
355
|
});
|
|
465
356
|
}
|
|
466
357
|
return () => {
|
|
@@ -468,151 +359,19 @@ export function houseNotifications(transport, mode) {
|
|
|
468
359
|
};
|
|
469
360
|
},
|
|
470
361
|
send(rooms) {
|
|
471
|
-
for (const room of rooms) {
|
|
472
|
-
const line = lines.get(room.authority);
|
|
473
|
-
const held = position(room.position);
|
|
474
|
-
if (line === undefined || held === null || line.logEpoch !== room.log_epoch)
|
|
475
|
-
continue;
|
|
476
|
-
lines.set(room.authority, { ...line, frames: [], held });
|
|
477
|
-
}
|
|
478
|
-
const current = opening;
|
|
479
|
-
opening = null;
|
|
480
|
-
if (current === null)
|
|
481
|
-
return;
|
|
482
|
-
void loaded
|
|
483
|
-
.then(() => Promise.all(rooms.map(restored)))
|
|
484
|
-
.then((presented) => {
|
|
485
|
-
current.hold(presented, runtime);
|
|
486
|
-
for (const [index, room] of presented.entries()) {
|
|
487
|
-
if (room.position === rooms[index].position)
|
|
488
|
-
continue;
|
|
489
|
-
announce(room.authority, { position: room.position, logEpoch: room.log_epoch });
|
|
490
|
-
}
|
|
491
|
-
});
|
|
492
|
-
},
|
|
493
|
-
published(locator, at) {
|
|
494
|
-
const authority = [...locators].find(([, held]) => held.includes(locator))?.[0];
|
|
495
|
-
const reached = position(at.position);
|
|
496
|
-
if (authority === undefined || reached === null)
|
|
497
|
-
return;
|
|
498
|
-
void forget([...kept.values()]
|
|
499
|
-
.filter((carry) => carry.authority === authority &&
|
|
500
|
-
carry.fenced !== null &&
|
|
501
|
-
carry.fenced.logEpoch === at.logEpoch &&
|
|
502
|
-
BigInt(carry.fenced.position) <= reached)
|
|
503
|
-
.map((carry) => carry.carry));
|
|
504
|
-
},
|
|
505
|
-
reopen() {
|
|
506
|
-
const current = opening;
|
|
507
362
|
opening = null;
|
|
508
|
-
|
|
363
|
+
announced = null;
|
|
364
|
+
socket?.hold(rooms, runtime, listedCursor);
|
|
509
365
|
},
|
|
510
366
|
track(entries) {
|
|
511
|
-
|
|
367
|
+
tracking.clear();
|
|
512
368
|
for (const entry of entries) {
|
|
513
|
-
|
|
514
|
-
if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
|
|
515
|
-
lines.set(entry.authority, { logEpoch: entry.logEpoch, frames: [], held: null });
|
|
516
|
-
}
|
|
369
|
+
tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
|
|
517
370
|
}
|
|
518
|
-
for (const
|
|
519
|
-
if (!
|
|
520
|
-
|
|
371
|
+
for (const [carry, held] of staged) {
|
|
372
|
+
if (!tracking.has(held.authority))
|
|
373
|
+
staged.delete(carry);
|
|
521
374
|
}
|
|
522
|
-
void loaded.then(() => forget([...kept.values()]
|
|
523
|
-
.filter((carry) => !locators.has(carry.authority))
|
|
524
|
-
.map((carry) => carry.carry)));
|
|
525
|
-
},
|
|
526
|
-
reach(authority, at) {
|
|
527
|
-
const line = lines.get(authority);
|
|
528
|
-
const held = position(at.position);
|
|
529
|
-
if (line === undefined || held === null || line.logEpoch !== at.logEpoch)
|
|
530
|
-
return;
|
|
531
|
-
if (line.held !== null && held <= line.held)
|
|
532
|
-
return;
|
|
533
|
-
lines.set(authority, {
|
|
534
|
-
...line,
|
|
535
|
-
frames: line.frames.filter((frame) => frame.position > held),
|
|
536
|
-
held,
|
|
537
|
-
});
|
|
538
|
-
},
|
|
539
|
-
advance(tracked, from, holds) {
|
|
540
|
-
const line = lines.get(tracked.authority);
|
|
541
|
-
const start = position(from.position);
|
|
542
|
-
if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
|
|
543
|
-
return null;
|
|
544
|
-
const pending = line.frames.filter((frame) => frame.position > start);
|
|
545
|
-
const first = pending[0];
|
|
546
|
-
if (first === undefined || first.after > start)
|
|
547
|
-
return null;
|
|
548
|
-
const documents = {};
|
|
549
|
-
const revisions = {};
|
|
550
|
-
const changes = {};
|
|
551
|
-
const binaryFiles = {};
|
|
552
|
-
const removals = [];
|
|
553
|
-
const applied = [];
|
|
554
|
-
const schemas = new Map();
|
|
555
|
-
const forget = (path) => {
|
|
556
|
-
delete documents[path];
|
|
557
|
-
delete revisions[path];
|
|
558
|
-
delete changes[path];
|
|
559
|
-
delete binaryFiles[path];
|
|
560
|
-
const removed = removals.indexOf(path);
|
|
561
|
-
if (removed !== -1)
|
|
562
|
-
removals.splice(removed, 1);
|
|
563
|
-
};
|
|
564
|
-
for (const frame of pending) {
|
|
565
|
-
for (const entry of frame.entries) {
|
|
566
|
-
if (entry.kind === 'edited' &&
|
|
567
|
-
entry.revision !== undefined &&
|
|
568
|
-
holds?.(entry.path, entry.revision) === true) {
|
|
569
|
-
forget(entry.path);
|
|
570
|
-
continue;
|
|
571
|
-
}
|
|
572
|
-
applied.push(entry);
|
|
573
|
-
if (tracked.schemas.includes(entry.path))
|
|
574
|
-
schemas.set(entry.path, entry);
|
|
575
|
-
if (entry.kind === 'removed') {
|
|
576
|
-
forget(entry.path);
|
|
577
|
-
removals.push(entry.path);
|
|
578
|
-
continue;
|
|
579
|
-
}
|
|
580
|
-
const binary = binaryFileOf(entry);
|
|
581
|
-
if (binary === null || (binary === undefined && entry.text === undefined))
|
|
582
|
-
return null;
|
|
583
|
-
if (mode === 'credential' && entry.revision === undefined)
|
|
584
|
-
return null;
|
|
585
|
-
const head = headChange(entry);
|
|
586
|
-
if (head === null)
|
|
587
|
-
return null;
|
|
588
|
-
forget(entry.path);
|
|
589
|
-
if (binary === undefined)
|
|
590
|
-
documents[entry.path] = entry.text;
|
|
591
|
-
else
|
|
592
|
-
binaryFiles[entry.path] = binary;
|
|
593
|
-
const revision = entry.revision ?? binary?.sha256;
|
|
594
|
-
if (revision !== undefined)
|
|
595
|
-
revisions[entry.path] = revision;
|
|
596
|
-
if (head !== undefined)
|
|
597
|
-
changes[entry.path] = head;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
const last = pending.at(-1);
|
|
601
|
-
lines.set(tracked.authority, { ...line, frames: pending, held: last.position });
|
|
602
|
-
return {
|
|
603
|
-
page: {
|
|
604
|
-
kind: 'net-advancement',
|
|
605
|
-
roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),
|
|
606
|
-
documents,
|
|
607
|
-
revisions,
|
|
608
|
-
...identities(revisions),
|
|
609
|
-
changes,
|
|
610
|
-
binaryFiles,
|
|
611
|
-
removals: removals.sort(),
|
|
612
|
-
},
|
|
613
|
-
entries: applied,
|
|
614
|
-
schemas,
|
|
615
|
-
};
|
|
616
375
|
},
|
|
617
376
|
};
|
|
618
377
|
}
|