@agentshouse/mdruntime-adapter 0.1.0-ca764edcceec6 → 0.1.0-ca7fab027bb19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/actions.d.ts +4 -66
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +7 -338
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +228 -364
- 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 +23 -15
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +92 -55
- 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 +672 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +377 -0
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/model.d.ts +5 -4
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +34 -41
- package/dist/read.d.ts +57 -64
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +154 -318
- 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 +5 -0
- package/dist/room-types.d.ts.map +1 -0
- package/dist/room-types.js +120 -0
- package/dist/search.d.ts +5 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +47 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +81 -200
- 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 +254 -422
- package/dist/transport.d.ts +64 -43
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +54 -11
- package/dist/upload.d.ts +12 -0
- package/dist/upload.d.ts.map +1 -0
- package/dist/upload.js +63 -0
- package/dist/write.d.ts +18 -2
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +105 -75
- package/package.json +8 -4
- package/AGENTS.md +0 -299
- package/dist/gather.d.ts +0 -4
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -45
- package/dist/handed.d.ts +0 -15
- package/dist/handed.d.ts.map +0 -1
- package/dist/handed.js +0 -38
- package/dist/referrer.d.ts +0 -7
- package/dist/referrer.d.ts.map +0 -1
- package/dist/referrer.js +0 -35
package/dist/stream.js
CHANGED
|
@@ -1,117 +1,125 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
import { ROW_WEIGHT, stepped, } from '@agentshouse/mdruntime';
|
|
2
|
+
import { acceptedMessage, cursorPosition, houseHistory } from './history.js';
|
|
3
|
+
import { keptSpaceSchemas, streamedModels } from './model.js';
|
|
4
|
+
import { answered, answering, binaryFileOf, createdOf, folded, forgotten, headChange, revised, } from './read.js';
|
|
5
|
+
import { houseDoorRoute, } from './transport.js';
|
|
6
|
+
import { DECIMAL, logPosition, presented, 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/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
|
+
}
|
|
10
23
|
function listedConversation(listed) {
|
|
11
24
|
return {
|
|
12
25
|
conversation: listed.conversation_id,
|
|
13
26
|
agent: listed.agent_id,
|
|
27
|
+
agentName: listed.agent_name,
|
|
28
|
+
agentRetired: listed.agent_retired,
|
|
14
29
|
name: listed.name,
|
|
15
30
|
created: listed.created_at,
|
|
16
31
|
finished: listed.finished_at,
|
|
17
32
|
outcome: listed.outcome,
|
|
33
|
+
waiting: listed.waiting,
|
|
34
|
+
newest: listed.newest === null ? null : cursorPosition(listed.newest),
|
|
35
|
+
processEnded: listed.process_ended_at,
|
|
18
36
|
};
|
|
19
37
|
}
|
|
20
38
|
function position(value) {
|
|
21
|
-
if (
|
|
39
|
+
if (!DECIMAL.test(value))
|
|
22
40
|
return null;
|
|
23
41
|
return BigInt(value);
|
|
24
42
|
}
|
|
25
|
-
function
|
|
26
|
-
const
|
|
27
|
-
let open = null;
|
|
43
|
+
function* changed(tracked, entries, version, schemas) {
|
|
44
|
+
const answer = answering();
|
|
28
45
|
for (const entry of entries) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
yield ROW_WEIGHT + (entry.text?.length ?? 0);
|
|
47
|
+
if (entry.kind === 'folder') {
|
|
48
|
+
folded(answer, entry.path, entry.removed === true);
|
|
49
|
+
continue;
|
|
33
50
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
if (entry.text === undefined)
|
|
42
|
-
return null;
|
|
43
|
-
open = { entry, texts: [entry.text] };
|
|
51
|
+
if (entry.path === tracked.schema)
|
|
52
|
+
schemas.set(entry.path, entry);
|
|
53
|
+
forgotten(answer, entry.path);
|
|
54
|
+
if (entry.space !== undefined) {
|
|
55
|
+
answer.removals.add(entry.path);
|
|
56
|
+
continue;
|
|
44
57
|
}
|
|
45
|
-
if (entry.
|
|
58
|
+
if (entry.kind === 'removed') {
|
|
59
|
+
answer.removals.add(entry.path);
|
|
46
60
|
continue;
|
|
47
|
-
const { continued: _continued, ...head } = open.entry;
|
|
48
|
-
whole.push({ ...head, text: open.texts.join('') });
|
|
49
|
-
open = null;
|
|
50
|
-
}
|
|
51
|
-
return open === null ? whole : null;
|
|
52
|
-
}
|
|
53
|
-
async function verified(entries) {
|
|
54
|
-
try {
|
|
55
|
-
for (const entry of entries) {
|
|
56
|
-
if (entry.text === undefined || entry.sha256 === undefined)
|
|
57
|
-
continue;
|
|
58
|
-
if ((await sha256Hex(entry.text)) !== entry.sha256)
|
|
59
|
-
return false;
|
|
60
61
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
const binary = binaryFileOf(entry);
|
|
63
|
+
if (binary === undefined)
|
|
64
|
+
answer.documents.set(entry.path, entry.text ?? '');
|
|
65
|
+
else if (binary !== null)
|
|
66
|
+
answer.binaryFiles.set(entry.path, binary);
|
|
67
|
+
if (binary === undefined && entry.facts !== undefined)
|
|
68
|
+
answer.facts.set(entry.path, entry.facts);
|
|
69
|
+
const revision = entry.revision ?? binary?.sha256;
|
|
70
|
+
if (revision !== undefined)
|
|
71
|
+
revised(answer, entry.path, revision);
|
|
72
|
+
const head = headChange(entry);
|
|
73
|
+
if (head)
|
|
74
|
+
answer.changes.set(entry.path, head);
|
|
75
|
+
const created = createdOf(entry);
|
|
76
|
+
if (created)
|
|
77
|
+
answer.created.set(entry.path, created);
|
|
65
78
|
}
|
|
79
|
+
return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
|
|
66
80
|
}
|
|
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
|
-
};
|
|
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 };
|
|
87
86
|
}
|
|
88
|
-
export function houseNotifications(transport, mode) {
|
|
87
|
+
export function houseNotifications(transport, mode, discovering, spaces) {
|
|
89
88
|
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();
|
|
89
|
+
const staged = new Map();
|
|
90
|
+
let socket = null;
|
|
91
|
+
const tracking = new Map();
|
|
98
92
|
const observers = new Set();
|
|
93
|
+
const replaying = new Map();
|
|
99
94
|
const conversationObservers = new Set();
|
|
100
95
|
const modeObservers = new Set();
|
|
101
96
|
let replicated = [];
|
|
97
|
+
let listedCursor = null;
|
|
98
|
+
const unanswered = [];
|
|
99
|
+
const heldAtZero = new Set();
|
|
102
100
|
const live = new Set();
|
|
103
101
|
let opening = null;
|
|
102
|
+
let announced = null;
|
|
104
103
|
const runtime = crypto.randomUUID();
|
|
105
104
|
function emit(event) {
|
|
106
|
-
for (const observer of observers)
|
|
107
|
-
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
|
+
}
|
|
108
112
|
}
|
|
109
113
|
function emitConversation(event) {
|
|
110
114
|
if (event.kind === 'turn' ||
|
|
111
115
|
event.kind === 'questions' ||
|
|
112
116
|
event.kind === 'process' ||
|
|
113
117
|
event.kind === 'commands' ||
|
|
114
|
-
event.kind === 'options'
|
|
118
|
+
event.kind === 'options' ||
|
|
119
|
+
event.kind === 'starting' ||
|
|
120
|
+
event.kind === 'subagents' ||
|
|
121
|
+
event.kind === 'link' ||
|
|
122
|
+
event.kind === 'deliveries') {
|
|
115
123
|
live.add(event.conversation);
|
|
116
124
|
}
|
|
117
125
|
for (const observer of conversationObservers)
|
|
@@ -119,12 +127,33 @@ export function houseNotifications(transport, mode) {
|
|
|
119
127
|
}
|
|
120
128
|
function reopened(next) {
|
|
121
129
|
opening = next;
|
|
122
|
-
|
|
130
|
+
announced = null;
|
|
131
|
+
socket = next;
|
|
132
|
+
staged.clear();
|
|
133
|
+
unanswered.length = 0;
|
|
134
|
+
heldAtZero.clear();
|
|
123
135
|
const gapped = new Set([...replicated, ...live]);
|
|
124
136
|
live.clear();
|
|
125
137
|
for (const conversation of gapped)
|
|
126
138
|
emitConversation({ kind: 'gap', conversation });
|
|
127
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
|
+
});
|
|
128
157
|
}
|
|
129
158
|
function converse(frame) {
|
|
130
159
|
const conversation = frame.conversation_id;
|
|
@@ -143,6 +172,7 @@ export function houseNotifications(transport, mode) {
|
|
|
143
172
|
return;
|
|
144
173
|
emitConversation({ kind: 'commands', conversation, commands: [] });
|
|
145
174
|
emitConversation({ kind: 'options', conversation, options: [] });
|
|
175
|
+
emitConversation({ kind: 'subagents', conversation, subagents: [] });
|
|
146
176
|
return;
|
|
147
177
|
}
|
|
148
178
|
if (frame.type === 'commands') {
|
|
@@ -157,6 +187,26 @@ export function houseNotifications(transport, mode) {
|
|
|
157
187
|
emitConversation({ kind: 'options', conversation, options: structuredClone(frame.options) });
|
|
158
188
|
return;
|
|
159
189
|
}
|
|
190
|
+
if (frame.type === 'starting') {
|
|
191
|
+
emitConversation({ kind: 'starting', conversation, step: frame.step });
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (frame.type === 'subagents') {
|
|
195
|
+
emitConversation({
|
|
196
|
+
kind: 'subagents',
|
|
197
|
+
conversation,
|
|
198
|
+
subagents: structuredClone(frame.subagents),
|
|
199
|
+
});
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (frame.type === 'link') {
|
|
203
|
+
emitConversation({ kind: 'link', conversation, connected: frame.connected });
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (frame.type === 'deliveries') {
|
|
207
|
+
emitConversation({ kind: 'deliveries', conversation, unknown: [...frame.unknown] });
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
160
210
|
if (frame.type === 'interactions') {
|
|
161
211
|
emitConversation({
|
|
162
212
|
kind: 'questions',
|
|
@@ -170,171 +220,31 @@ export function houseNotifications(transport, mode) {
|
|
|
170
220
|
return;
|
|
171
221
|
emitConversation({ kind: 'accepted-message', conversation, message });
|
|
172
222
|
}
|
|
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);
|
|
223
|
+
function stage(frame, via) {
|
|
224
|
+
const held = staged.get(frame.carry);
|
|
225
|
+
if (frame.index !== (held?.parts ?? 0)) {
|
|
226
|
+
staged.delete(frame.carry);
|
|
206
227
|
return;
|
|
207
228
|
}
|
|
208
229
|
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;
|
|
230
|
+
for (const [carry, other] of staged) {
|
|
231
|
+
if (other.authority === frame.authority)
|
|
232
|
+
staged.delete(carry);
|
|
233
|
+
}
|
|
230
234
|
}
|
|
231
|
-
|
|
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);
|
|
232
240
|
via?.received(frame.authority, frame.carry, frame.index);
|
|
233
241
|
}
|
|
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);
|
|
242
|
+
function carried(frame) {
|
|
243
|
+
const held = staged.get(frame.carry);
|
|
244
|
+
staged.delete(frame.carry);
|
|
245
|
+
if ((held?.parts ?? 0) !== frame.parts)
|
|
255
246
|
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);
|
|
274
|
-
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
|
-
};
|
|
247
|
+
publish(frame, held?.entries ?? []);
|
|
338
248
|
}
|
|
339
249
|
function handle(frame, via) {
|
|
340
250
|
if (frame.type === 'signal') {
|
|
@@ -346,18 +256,35 @@ export function houseNotifications(transport, mode) {
|
|
|
346
256
|
return;
|
|
347
257
|
}
|
|
348
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);
|
|
349
265
|
emit({
|
|
350
|
-
kind: '
|
|
351
|
-
expired:
|
|
266
|
+
kind: 'caught-up',
|
|
267
|
+
expired: [
|
|
268
|
+
...frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
|
|
269
|
+
...(unanswered.shift() ?? []),
|
|
270
|
+
],
|
|
352
271
|
});
|
|
353
272
|
return;
|
|
354
273
|
}
|
|
355
274
|
if (frame.type === 'authority_changed') {
|
|
356
|
-
|
|
275
|
+
const change = discovering.changed(frame);
|
|
276
|
+
if (change !== null)
|
|
277
|
+
emit(change);
|
|
357
278
|
return;
|
|
358
279
|
}
|
|
359
280
|
if (frame.type === 'conversations') {
|
|
360
|
-
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
|
+
});
|
|
361
288
|
return;
|
|
362
289
|
}
|
|
363
290
|
if (frame.type === 'conversation') {
|
|
@@ -372,63 +299,49 @@ export function houseNotifications(transport, mode) {
|
|
|
372
299
|
frame.type === 'process' ||
|
|
373
300
|
frame.type === 'commands' ||
|
|
374
301
|
frame.type === 'options' ||
|
|
302
|
+
frame.type === 'starting' ||
|
|
303
|
+
frame.type === 'subagents' ||
|
|
304
|
+
frame.type === 'link' ||
|
|
305
|
+
frame.type === 'deliveries' ||
|
|
375
306
|
frame.type === 'interactions' ||
|
|
376
307
|
frame.type === 'message') {
|
|
377
308
|
converse(frame);
|
|
378
309
|
return;
|
|
379
310
|
}
|
|
380
311
|
if (frame.type === 'part')
|
|
381
|
-
|
|
382
|
-
if (frame.type === 'carried')
|
|
383
|
-
|
|
312
|
+
stage(frame, via);
|
|
313
|
+
else if (frame.type === 'carried')
|
|
314
|
+
carried(frame);
|
|
384
315
|
}
|
|
385
316
|
function publish(frame, entries) {
|
|
386
317
|
const at = position(frame.position);
|
|
387
318
|
const after = position(frame.after);
|
|
388
|
-
if (at === null || after === null || after >= at)
|
|
389
|
-
interrupt(frame.authority);
|
|
319
|
+
if (at === null || after === null || after >= at)
|
|
390
320
|
return;
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
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;
|
|
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),
|
|
417
332
|
});
|
|
418
|
-
return;
|
|
419
333
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
.then(() => handle(frame, via))
|
|
423
|
-
.finally(() => {
|
|
424
|
-
verifying -= 1;
|
|
425
|
-
});
|
|
426
|
-
});
|
|
334
|
+
}
|
|
335
|
+
stream.observe((frame) => handle(frame, socket));
|
|
427
336
|
stream.opened(reopened);
|
|
428
|
-
stream.closed(({ revoked, lost }) => {
|
|
337
|
+
stream.closed(({ revoked, lost, authorityChanged }) => {
|
|
429
338
|
opening = null;
|
|
430
|
-
|
|
431
|
-
|
|
339
|
+
announced = null;
|
|
340
|
+
socket = null;
|
|
341
|
+
staged.clear();
|
|
342
|
+
unanswered.length = 0;
|
|
343
|
+
heldAtZero.clear();
|
|
344
|
+
emit({ kind: 'closed', revoked, lost, authorityChanged });
|
|
432
345
|
});
|
|
433
346
|
return {
|
|
434
347
|
runtime,
|
|
@@ -444,175 +357,94 @@ export function houseNotifications(transport, mode) {
|
|
|
444
357
|
replicate(next) {
|
|
445
358
|
replicated = [...next];
|
|
446
359
|
},
|
|
360
|
+
hold(cursor) {
|
|
361
|
+
listedCursor = cursor;
|
|
362
|
+
},
|
|
447
363
|
observe(notify) {
|
|
448
364
|
conversationObservers.add(notify);
|
|
449
365
|
return () => {
|
|
450
366
|
conversationObservers.delete(notify);
|
|
451
367
|
};
|
|
452
368
|
},
|
|
369
|
+
...(mode === 'credential'
|
|
370
|
+
? {
|
|
371
|
+
agents: () => houseAgents(transport),
|
|
372
|
+
history: (request) => houseHistory(transport, request),
|
|
373
|
+
}
|
|
374
|
+
: {}),
|
|
453
375
|
},
|
|
454
|
-
observe(notify
|
|
376
|
+
observe(notify) {
|
|
455
377
|
observers.add(notify);
|
|
456
|
-
if (receipts === null) {
|
|
457
|
-
receipts = port;
|
|
458
|
-
loaded = load(port);
|
|
459
|
-
}
|
|
460
378
|
if (opening !== null) {
|
|
379
|
+
const replayed = [{ kind: 'opened' }];
|
|
380
|
+
if (announced !== null)
|
|
381
|
+
replayed.push(announced);
|
|
382
|
+
replaying.set(notify, replayed);
|
|
461
383
|
queueMicrotask(() => {
|
|
462
|
-
|
|
463
|
-
|
|
384
|
+
replaying.delete(notify);
|
|
385
|
+
for (const event of replayed)
|
|
386
|
+
if (observers.has(notify))
|
|
387
|
+
notify(event);
|
|
464
388
|
});
|
|
465
389
|
}
|
|
466
390
|
return () => {
|
|
467
391
|
observers.delete(notify);
|
|
468
392
|
};
|
|
469
393
|
},
|
|
470
|
-
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;
|
|
394
|
+
send(rooms) {
|
|
479
395
|
opening = null;
|
|
480
|
-
|
|
396
|
+
announced = null;
|
|
397
|
+
if (socket === null)
|
|
481
398
|
return;
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
.
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
if (room.position === rooms[index].position)
|
|
488
|
-
continue;
|
|
489
|
-
announce(room.authority, { position: room.position, logEpoch: room.log_epoch });
|
|
490
|
-
}
|
|
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 }];
|
|
491
404
|
});
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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);
|
|
414
|
+
}
|
|
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)
|
|
497
424
|
return;
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
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
|
+
}
|
|
437
|
+
});
|
|
509
438
|
},
|
|
510
439
|
track(entries) {
|
|
511
|
-
|
|
440
|
+
tracking.clear();
|
|
512
441
|
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
|
-
}
|
|
442
|
+
tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
|
|
517
443
|
}
|
|
518
|
-
for (const
|
|
519
|
-
if (!
|
|
520
|
-
|
|
444
|
+
for (const [carry, held] of staged) {
|
|
445
|
+
if (!tracking.has(held.authority))
|
|
446
|
+
staged.delete(carry);
|
|
521
447
|
}
|
|
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
448
|
},
|
|
617
449
|
};
|
|
618
450
|
}
|