@agentshouse/mdruntime-adapter 0.1.0-cdc1a38081f09 → 0.1.0-cdcec0737ac0e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/actions.d.ts +4 -59
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +7 -289
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +138 -328
- 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 +21 -13
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +73 -53
- package/dist/history.d.ts +12 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +92 -0
- package/dist/house-model.d.ts +719 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +393 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/model.d.ts +5 -4
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +31 -35
- package/dist/part.d.ts +11 -12
- package/dist/part.d.ts.map +1 -1
- package/dist/part.js +63 -55
- package/dist/read.d.ts +20 -58
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +60 -221
- package/dist/refusal.d.ts +0 -3
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +0 -5
- package/dist/room-stream.d.ts +20 -0
- package/dist/room-stream.d.ts.map +1 -0
- package/dist/room-stream.js +57 -0
- package/dist/room-types.d.ts +4 -3
- package/dist/room-types.d.ts.map +1 -1
- package/dist/room-types.js +49 -9
- 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 +79 -159
- package/dist/space-schema.d.ts +7 -0
- package/dist/space-schema.d.ts.map +1 -0
- package/dist/space-schema.js +18 -0
- package/dist/stream.d.ts +14 -14
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +169 -424
- package/dist/transport.d.ts +51 -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 -317
- package/dist/gather.d.ts +0 -4
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -35
package/dist/adapter.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { stepped } from '@agentshouse/mdruntime';
|
|
2
|
-
import {
|
|
3
|
-
import { manifestedModels, partModels, streamedModels, viewModels } from './model.js';
|
|
4
|
-
import { gathered, gatheredEach, selections } from './gather.js';
|
|
2
|
+
import { capabilities, discoveredRoom, mapDiscovery, parseAuthorityChange, parseDiscovery, trackedFrom, } from './discovery.js';
|
|
5
3
|
import { createSiteAdapter } from './site.js';
|
|
6
|
-
import { authorityRoot, bootstrapping,
|
|
7
|
-
import {
|
|
4
|
+
import { authorityRoot, bootstrapping, parseFileAddress, parseGrant, } from './read.js';
|
|
5
|
+
import { roomStreams } from './room-stream.js';
|
|
6
|
+
import { spaceSchemas } from './space-schema.js';
|
|
8
7
|
import { sha256Hex } from './digest.js';
|
|
9
8
|
import { finishedUpload, houseUpload } from './upload.js';
|
|
10
9
|
import { houseAction } from './actions.js';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
10
|
+
import { houseSearch } from './search.js';
|
|
11
|
+
import { classifyDoor, doorRefusal } from './refusal.js';
|
|
12
|
+
import { houseNotifications, } from './stream.js';
|
|
13
|
+
import { houseDoorRoute, } from './transport.js';
|
|
14
14
|
import { batchPaths, deltaBody, deltaBytes, deltaDigest, historyOutcome, houseChanges, houseMove, mutationOutcome, operationHead, rejectedMapping, revisionBody, uploadable, } from './write.js';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { HOUSE_TYPED_PATHS } from './house-model.js';
|
|
16
|
+
import { HOUSE_NAMEABLE_ROOM_TYPES, HOUSE_ROOM_TYPES } from './room-types.js';
|
|
17
|
+
import { followsVersion, logPosition, presented, reachedVersion, roomVersion } from './version.js';
|
|
17
18
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
18
19
|
const UNCERTAIN_READ = { kind: 'transport-uncertainty' };
|
|
20
|
+
const OCTET_STREAM = 'application/octet-stream';
|
|
19
21
|
const EXPIRED_ADDRESS = 403;
|
|
20
22
|
function lapsedGrant(outcome) {
|
|
21
23
|
return outcome.kind === 'rejected' && outcome.code === 'upload_unavailable';
|
|
@@ -50,161 +52,86 @@ export function createAgentsHouseAdapter(options) {
|
|
|
50
52
|
if ('site' in options)
|
|
51
53
|
return createSiteAdapter(options.site, options.snapshot === true);
|
|
52
54
|
const transport = options.transport;
|
|
53
|
-
const
|
|
55
|
+
const spaces = spaceSchemas();
|
|
56
|
+
const notifications = houseNotifications(transport, 'credential', {
|
|
57
|
+
opened: async (frame) => (frame === null ? null : opened(frame)),
|
|
58
|
+
changed,
|
|
59
|
+
}, spaces);
|
|
54
60
|
const tracked = new Map();
|
|
55
|
-
const
|
|
56
|
-
|
|
61
|
+
const rooms = roomStreams('credential', spaces);
|
|
62
|
+
const unreused = new Set();
|
|
57
63
|
let bounds;
|
|
58
64
|
function declared() {
|
|
59
65
|
if (bounds === undefined)
|
|
60
66
|
throw new Error('no Discovery declared the bounds');
|
|
61
67
|
return bounds;
|
|
62
68
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const failure = classifyRead(answered.status, answered.body, entry.locator);
|
|
77
|
-
if (failure !== null)
|
|
78
|
-
return failure;
|
|
79
|
-
const frame = partFrame(answered.body);
|
|
80
|
-
if (frame === null)
|
|
81
|
-
continue;
|
|
82
|
-
const scope = await housePart(continued.room, frame, listed, 'credential');
|
|
83
|
-
if (scope !== null)
|
|
84
|
-
return 'kind' in scope ? scope : { scope, frame };
|
|
85
|
-
}
|
|
86
|
-
return unverifiedPart(entry.locator);
|
|
69
|
+
function opened(frame) {
|
|
70
|
+
const document = parseDiscovery(frame);
|
|
71
|
+
if (document === null)
|
|
72
|
+
return null;
|
|
73
|
+
bounds = document.bounds;
|
|
74
|
+
tracked.clear();
|
|
75
|
+
for (const entry of trackedFrom(document))
|
|
76
|
+
tracked.set(entry.locator, entry);
|
|
77
|
+
notifications.track([...tracked.values()]);
|
|
78
|
+
return {
|
|
79
|
+
...mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document.actions)),
|
|
80
|
+
member: document.member,
|
|
81
|
+
};
|
|
87
82
|
}
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const
|
|
95
|
-
|
|
83
|
+
function changed(frame) {
|
|
84
|
+
const change = parseAuthorityChange(frame);
|
|
85
|
+
if (change === null)
|
|
86
|
+
return null;
|
|
87
|
+
for (const locator of change.left)
|
|
88
|
+
tracked.delete(locator);
|
|
89
|
+
for (const entry of trackedFrom(change))
|
|
90
|
+
tracked.set(entry.locator, entry);
|
|
91
|
+
notifications.track([...tracked.values()]);
|
|
92
|
+
return {
|
|
93
|
+
kind: 'authority-changed',
|
|
94
|
+
rooms: change.authorities.map((authority) => discoveredRoom(authority)),
|
|
95
|
+
left: change.left,
|
|
96
|
+
member: change.member,
|
|
97
|
+
};
|
|
96
98
|
}
|
|
97
|
-
async function
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
: await fetchedPart(entry, continued, listed, received, arriving);
|
|
103
|
-
if ('kind' in sent)
|
|
104
|
-
return sent;
|
|
105
|
-
const scope = await reused(sent.scope, asked.held);
|
|
99
|
+
async function streamedPage(entry, token, held) {
|
|
100
|
+
const part = await rooms.part(entry, token);
|
|
101
|
+
if ('kind' in part)
|
|
102
|
+
return part;
|
|
103
|
+
const scope = await reused(part.scope, held);
|
|
106
104
|
if (scope === null) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
: bootstrapTogether({ entry, held: undefined });
|
|
105
|
+
unreused.add(entry.locator);
|
|
106
|
+
return UNCERTAIN_READ;
|
|
110
107
|
}
|
|
111
|
-
const next = continued.next + 1;
|
|
112
|
-
const more = next < continued.room.parts.length;
|
|
113
|
-
if (continued.next === 0 && !more)
|
|
114
|
-
handed.set(entry.locator, roomVersion(scope));
|
|
115
|
-
else
|
|
116
|
-
handed.delete(entry.locator);
|
|
117
|
-
notifications.reach(entry.authority, scope);
|
|
118
|
-
const seen = [
|
|
119
|
-
...continued.seen,
|
|
120
|
-
...entry.schemas.filter((schema) => scope.files.some((file) => file.path === schema)),
|
|
121
|
-
];
|
|
122
|
-
const models = await partModels(scope, entry, new Set(seen), !more);
|
|
123
108
|
return {
|
|
124
109
|
...(await stepped(bootstrapping(scope))),
|
|
125
|
-
...(models === undefined ? {} : { models }),
|
|
126
|
-
...(
|
|
127
|
-
|
|
110
|
+
...(part.models === undefined ? {} : { models: part.models }),
|
|
111
|
+
...(part.pageToken === undefined ? {} : { pageToken: part.pageToken }),
|
|
112
|
+
bytes: part.bytes,
|
|
128
113
|
};
|
|
129
114
|
}
|
|
130
|
-
async function
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
],
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const enumeration = parseEnumeration(answer.body, 'credential');
|
|
144
|
-
if (enumeration === null)
|
|
145
|
-
return UNCERTAIN_READ;
|
|
146
|
-
return (viewOf(enumeration, ask.entry) ?? { kind: 'room-not-readable', locator: ask.entry.locator });
|
|
147
|
-
}
|
|
148
|
-
async function enumeratedRoom(enumeration, ask) {
|
|
149
|
-
const first = viewOf(enumeration, ask.entry);
|
|
150
|
-
if (first === undefined)
|
|
151
|
-
return { kind: 'room-not-readable', locator: ask.entry.locator };
|
|
152
|
-
const view = await wholeView(first, (page) => enumeratedPage(ask, page));
|
|
153
|
-
if ('kind' in view)
|
|
154
|
-
return view;
|
|
155
|
-
notifications.reach(ask.entry.authority, view);
|
|
156
|
-
const answer = await refreshFrom(view, ask.fromRoomVersion);
|
|
157
|
-
if (answer.kind !== 'net-advancement')
|
|
158
|
-
return answer;
|
|
159
|
-
handed.set(ask.entry.locator, roomVersion(view));
|
|
160
|
-
const models = await viewModels(view, ask.entry);
|
|
161
|
-
return models === undefined ? answer : { ...answer, models };
|
|
162
|
-
}
|
|
163
|
-
async function streamed(entry, request, from) {
|
|
164
|
-
if (handed.get(entry.locator) !== request.fromRoomVersion)
|
|
165
|
-
return null;
|
|
166
|
-
const asked = notifications.edited(entry, from);
|
|
167
|
-
const kept = asked.length === 0 || heldRevisions === undefined
|
|
168
|
-
? new Map()
|
|
169
|
-
: await heldRevisions(entry.locator, asked);
|
|
170
|
-
const advanced = await stepped(notifications.advance(entry, from, (path, revision) => kept.get(path) === revision));
|
|
171
|
-
if (advanced === null)
|
|
172
|
-
return null;
|
|
173
|
-
handed.set(entry.locator, advanced.page.roomVersion);
|
|
174
|
-
const models = await streamedModels(advanced.schemas, entry, 'credential');
|
|
175
|
-
return models === undefined ? advanced.page : { ...advanced.page, models };
|
|
115
|
+
async function openedRoom(entry, request) {
|
|
116
|
+
const reusing = unreused.delete(entry.locator) ? undefined : request.held;
|
|
117
|
+
const files = reusing === undefined
|
|
118
|
+
? null
|
|
119
|
+
: await heldFiles(entry.authority, reusing, declared().max_held_files);
|
|
120
|
+
const answered = await transport.streamed(houseDoorRoute('bootstrap'), {
|
|
121
|
+
room_ref: entry.authority,
|
|
122
|
+
prefixes: [authorityRoot(entry.handle)],
|
|
123
|
+
...(files === null ? {} : { held: [files] }),
|
|
124
|
+
}, request.signal ?? new AbortController().signal);
|
|
125
|
+
if (answered.room === null)
|
|
126
|
+
return classifyDoor(answered.status, answered.body, entry.locator) ?? UNCERTAIN_READ;
|
|
127
|
+
return rooms.head(entry, answered.room, request.arriving, request.signal);
|
|
176
128
|
}
|
|
177
129
|
function held(rooms) {
|
|
178
|
-
|
|
130
|
+
notifications.send(rooms.flatMap((room) => {
|
|
179
131
|
const entry = tracked.get(room.locator);
|
|
180
132
|
const at = logPosition(room.roomVersion);
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
handed.set(room.locator, room.roomVersion);
|
|
184
|
-
notifications.reach(entry.authority, at);
|
|
185
|
-
return [presented(entry.authority, at)];
|
|
186
|
-
});
|
|
187
|
-
notifications.send(kept);
|
|
188
|
-
}
|
|
189
|
-
async function adoptedMove(entry, into, outcome) {
|
|
190
|
-
if (outcome.kind === 'accepted' && outcome.destination !== undefined) {
|
|
191
|
-
await adopted(into, { kind: 'accepted', ...outcome.destination });
|
|
192
|
-
}
|
|
193
|
-
return adopted(entry, outcome);
|
|
194
|
-
}
|
|
195
|
-
async function adopted(entry, outcome) {
|
|
196
|
-
if (outcome.kind !== 'accepted')
|
|
197
|
-
return outcome;
|
|
198
|
-
const held = handed.get(entry.locator);
|
|
199
|
-
if (held === undefined)
|
|
200
|
-
return outcome;
|
|
201
|
-
const follows = followsVersion(held, outcome.roomVersion);
|
|
202
|
-
if (follows)
|
|
203
|
-
handed.set(entry.locator, outcome.roomVersion);
|
|
204
|
-
const at = logPosition(outcome.roomVersion);
|
|
205
|
-
if (follows && at !== null)
|
|
206
|
-
notifications.reach(entry.authority, at);
|
|
207
|
-
return outcome;
|
|
133
|
+
return entry === undefined || at === null ? [] : [presented(entry.authority, at)];
|
|
134
|
+
}));
|
|
208
135
|
}
|
|
209
136
|
function authorityFor(locator) {
|
|
210
137
|
return tracked.get(locator);
|
|
@@ -223,116 +150,18 @@ export function createAgentsHouseAdapter(options) {
|
|
|
223
150
|
return result;
|
|
224
151
|
return { ...result, at: { locator, roomVersion: roomVersion({ position, logEpoch }) } };
|
|
225
152
|
}
|
|
226
|
-
async function holding(asks) {
|
|
227
|
-
const bound = Math.floor(declared().max_held_files / Math.max(1, asks.filter((ask) => ask.held !== undefined).length));
|
|
228
|
-
const held = [];
|
|
229
|
-
for (const ask of asks) {
|
|
230
|
-
if (ask.held === undefined || bound === 0)
|
|
231
|
-
continue;
|
|
232
|
-
const files = await heldFiles(ask.entry.authority, ask.held, bound);
|
|
233
|
-
if (files !== null)
|
|
234
|
-
held.push(files);
|
|
235
|
-
}
|
|
236
|
-
return held;
|
|
237
|
-
}
|
|
238
|
-
async function bootstrapped(asks, answer) {
|
|
239
|
-
let open = asks.map((asked, ask) => ({ entry: asked.entry, asked, ask }));
|
|
240
|
-
while (open.length > 0) {
|
|
241
|
-
const unreached = [];
|
|
242
|
-
for (const part of selections(open, declared().max_prefixes)) {
|
|
243
|
-
const held = await holding(part.map(({ asked }) => asked));
|
|
244
|
-
const answered = await transport.door(DOOR_BOOTSTRAP, {
|
|
245
|
-
prefixes: part.map(({ entry }) => authorityRoot(entry.handle)),
|
|
246
|
-
...(held.length === 0 ? {} : { held }),
|
|
247
|
-
});
|
|
248
|
-
const classified = part.map(({ entry }) => classifyDoor(answered.status, answered.body, entry.locator));
|
|
249
|
-
const parted = classified[0] === null ? parseParted(answered.body) : null;
|
|
250
|
-
for (const [index, asked] of part.entries()) {
|
|
251
|
-
const failure = classified[index];
|
|
252
|
-
if (failure !== null && failure !== undefined) {
|
|
253
|
-
answer(asked.ask, failure);
|
|
254
|
-
continue;
|
|
255
|
-
}
|
|
256
|
-
if (parted === null) {
|
|
257
|
-
answer(asked.ask, UNCERTAIN_READ);
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
const room = parted.rooms.find((candidate) => candidate.anchor === asked.entry.authority);
|
|
261
|
-
if (room === undefined && parted.next !== undefined) {
|
|
262
|
-
unreached.push(asked);
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
if (room === undefined) {
|
|
266
|
-
answer(asked.ask, { kind: 'room-not-readable', locator: asked.entry.locator });
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
const kept = held.find((files) => files.room === asked.entry.authority);
|
|
270
|
-
answer(asked.ask, await manifestPage(asked.asked, {
|
|
271
|
-
room,
|
|
272
|
-
next: 0,
|
|
273
|
-
seen: [],
|
|
274
|
-
...(kept === undefined ? {} : { held: kept }),
|
|
275
|
-
}));
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
open = unreached;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
function layered(asks) {
|
|
282
|
-
const depths = new Map();
|
|
283
|
-
const layers = [];
|
|
284
|
-
for (const ask of asks) {
|
|
285
|
-
const depth = depths.get(ask.ask.entry.authority) ?? 0;
|
|
286
|
-
depths.set(ask.ask.entry.authority, depth + 1);
|
|
287
|
-
(layers[depth] ??= []).push(ask);
|
|
288
|
-
}
|
|
289
|
-
return layers;
|
|
290
|
-
}
|
|
291
|
-
async function enumerated(asks) {
|
|
292
|
-
const answers = [];
|
|
293
|
-
const parts = layered(asks.map((ask, index) => ({ ask, index }))).flatMap((layer) => selections(layer, declared().max_prefixes));
|
|
294
|
-
for (const part of parts) {
|
|
295
|
-
let open = [...part];
|
|
296
|
-
while (open.length > 0) {
|
|
297
|
-
const answer = await transport.door(DOOR_ENUMERATE, {
|
|
298
|
-
prefixes: open.map(({ ask }) => authorityRoot(ask.entry.handle)),
|
|
299
|
-
positions: open.map(({ ask }) => presented(ask.entry.authority, ask.from)),
|
|
300
|
-
});
|
|
301
|
-
const classified = open.map(({ ask }) => classifyRead(answer.status, answer.body, ask.entry.locator));
|
|
302
|
-
if (classified[0]?.kind === 'beyond-horizon') {
|
|
303
|
-
const named = doorRefusal(answer.body)?.fields.authority;
|
|
304
|
-
const expired = open.filter(({ ask }) => ask.entry.authority === named);
|
|
305
|
-
const answered = expired.length === 0 ? UNCERTAIN_READ : { kind: 'beyond-horizon' };
|
|
306
|
-
const gone = expired.length === 0 ? open : expired;
|
|
307
|
-
for (const ask of gone)
|
|
308
|
-
answers[ask.index] = answered;
|
|
309
|
-
open = open.filter((ask) => !gone.includes(ask));
|
|
310
|
-
continue;
|
|
311
|
-
}
|
|
312
|
-
const enumeration = classified[0] === null ? parseEnumeration(answer.body, 'credential') : null;
|
|
313
|
-
for (const [answerIndex, { ask, index }] of open.entries()) {
|
|
314
|
-
const failure = classified[answerIndex];
|
|
315
|
-
if (failure !== null && failure !== undefined) {
|
|
316
|
-
answers[index] = failure;
|
|
317
|
-
continue;
|
|
318
|
-
}
|
|
319
|
-
answers[index] =
|
|
320
|
-
enumeration === null ? UNCERTAIN_READ : await enumeratedRoom(enumeration, ask);
|
|
321
|
-
}
|
|
322
|
-
open = [];
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return answers;
|
|
326
|
-
}
|
|
327
|
-
const bootstrapTogether = gatheredEach(bootstrapped);
|
|
328
|
-
const enumerateTogether = gathered(enumerated);
|
|
329
153
|
async function uploaded(head, changes, delta, bytes, entry, handed, keep) {
|
|
330
154
|
const paths = batchPaths(changes);
|
|
331
155
|
const sha256 = await deltaDigest(delta);
|
|
332
156
|
if (handed !== undefined && handed.sha256 === sha256) {
|
|
333
157
|
return { body: { ...head, paths, upload: handed, runtime: notifications.runtime } };
|
|
334
158
|
}
|
|
335
|
-
const minted = await transport.door(
|
|
159
|
+
const minted = await transport.door(houseDoorRoute('batch-upload'), {
|
|
160
|
+
...head,
|
|
161
|
+
paths,
|
|
162
|
+
bytes,
|
|
163
|
+
sha256,
|
|
164
|
+
});
|
|
336
165
|
if (minted.status !== 200) {
|
|
337
166
|
return {
|
|
338
167
|
outcome: await stepped(mutationOutcome(minted.status, minted.body, entry.locator, entry.handle)),
|
|
@@ -380,11 +209,11 @@ export function createAgentsHouseAdapter(options) {
|
|
|
380
209
|
: { body: inline };
|
|
381
210
|
if ('outcome' in prepared)
|
|
382
211
|
return prepared.outcome;
|
|
383
|
-
const answer = await transport.door(
|
|
212
|
+
const answer = await transport.door(houseDoorRoute('batch'), prepared.body);
|
|
384
213
|
const stagedFiles = await staged(answer, request);
|
|
385
214
|
if (stagedFiles === false)
|
|
386
215
|
return UNCERTAIN;
|
|
387
|
-
const settled = stagedFiles === null ? answer : await transport.door(
|
|
216
|
+
const settled = stagedFiles === null ? answer : await transport.door(houseDoorRoute('batch'), prepared.body);
|
|
388
217
|
if (stagedFiles === true && (await staged(settled, request)) !== null)
|
|
389
218
|
return UNCERTAIN;
|
|
390
219
|
return stepped(mutationOutcome(settled.status, settled.body, entry.locator, entry.handle, into === undefined
|
|
@@ -412,9 +241,22 @@ export function createAgentsHouseAdapter(options) {
|
|
|
412
241
|
function linked(answer, locator) {
|
|
413
242
|
const address = addressed(answer, locator);
|
|
414
243
|
return address.kind === 'address'
|
|
415
|
-
? { kind: 'link', url: address.url, name: address.name }
|
|
244
|
+
? { kind: 'link', url: address.url, name: address.name, mediaType: address.mediaType }
|
|
416
245
|
: address;
|
|
417
246
|
}
|
|
247
|
+
function refusedAttach(answer, locator) {
|
|
248
|
+
const failure = classifyDoor(answer.status, answer.body, locator);
|
|
249
|
+
if (failure === null)
|
|
250
|
+
return null;
|
|
251
|
+
return failure.kind === 'scoped-refusal'
|
|
252
|
+
? {
|
|
253
|
+
kind: 'rejected',
|
|
254
|
+
code: failure.code,
|
|
255
|
+
fields: failure.fields,
|
|
256
|
+
retryable: failure.retryable,
|
|
257
|
+
}
|
|
258
|
+
: failure;
|
|
259
|
+
}
|
|
418
260
|
async function downloaded(ask, locator) {
|
|
419
261
|
let address = addressed(await ask(), locator);
|
|
420
262
|
if (address.kind !== 'address')
|
|
@@ -439,7 +281,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
439
281
|
const entry = authorityFor(request.locator);
|
|
440
282
|
if (entry === undefined)
|
|
441
283
|
return null;
|
|
442
|
-
return () => transport.door(
|
|
284
|
+
return () => transport.door(houseDoorRoute('files/get'), {
|
|
443
285
|
room_ref: entry.authority,
|
|
444
286
|
path: request.path,
|
|
445
287
|
revision: request.revision,
|
|
@@ -447,72 +289,18 @@ export function createAgentsHouseAdapter(options) {
|
|
|
447
289
|
}
|
|
448
290
|
return {
|
|
449
291
|
roomTypes: HOUSE_ROOM_TYPES,
|
|
292
|
+
nameableRoomTypes: HOUSE_NAMEABLE_ROOM_TYPES,
|
|
293
|
+
typedPaths: HOUSE_TYPED_PATHS,
|
|
450
294
|
async authorize() {
|
|
451
295
|
return options.authorize();
|
|
452
296
|
},
|
|
453
|
-
async discover(_authorization, scope) {
|
|
454
|
-
const answer = await transport.door(DOOR_DISCOVER, {
|
|
455
|
-
prefixes: [...DISCOVER_PREFIXES],
|
|
456
|
-
...(scope === undefined ? {} : { rooms: scope.authorities }),
|
|
457
|
-
});
|
|
458
|
-
const failed = discoveryFailure(answer.status, answer.body);
|
|
459
|
-
if (failed !== null)
|
|
460
|
-
return failed;
|
|
461
|
-
const document = parseDiscovery(answer.body);
|
|
462
|
-
if (document === null)
|
|
463
|
-
return { kind: 'transport-uncertainty' };
|
|
464
|
-
bounds = document.bounds;
|
|
465
|
-
const entries = trackedFrom(document);
|
|
466
|
-
const covered = scope === undefined
|
|
467
|
-
? null
|
|
468
|
-
: [
|
|
469
|
-
...new Set([
|
|
470
|
-
...[...tracked.values()]
|
|
471
|
-
.filter((entry) => scope.authorities.includes(entry.authority))
|
|
472
|
-
.map((entry) => entry.locator),
|
|
473
|
-
...entries.map((entry) => entry.locator),
|
|
474
|
-
]),
|
|
475
|
-
];
|
|
476
|
-
if (covered === null)
|
|
477
|
-
tracked.clear();
|
|
478
|
-
else
|
|
479
|
-
for (const locator of covered)
|
|
480
|
-
tracked.delete(locator);
|
|
481
|
-
for (const entry of entries)
|
|
482
|
-
tracked.set(entry.locator, entry);
|
|
483
|
-
for (const locator of handed.keys())
|
|
484
|
-
if (!tracked.has(locator))
|
|
485
|
-
handed.delete(locator);
|
|
486
|
-
notifications.track([...tracked.values()]);
|
|
487
|
-
return {
|
|
488
|
-
...mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document.actions, [...tracked.values()])),
|
|
489
|
-
member: document.member,
|
|
490
|
-
...(covered === null ? {} : { covered }),
|
|
491
|
-
};
|
|
492
|
-
},
|
|
493
297
|
async bootstrap(_authorization, request) {
|
|
494
298
|
const entry = authorityFor(request.locator);
|
|
495
299
|
if (entry === undefined)
|
|
496
300
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
}
|
|
501
|
-
return bootstrapTogether(asked);
|
|
502
|
-
},
|
|
503
|
-
async refresh(_authorization, request) {
|
|
504
|
-
const entry = authorityFor(request.locator);
|
|
505
|
-
if (entry === undefined)
|
|
506
|
-
return { kind: 'room-not-readable', locator: request.locator };
|
|
507
|
-
if (request.pageToken !== undefined)
|
|
508
|
-
return { kind: 'transport-uncertainty' };
|
|
509
|
-
const from = logPosition(request.fromRoomVersion);
|
|
510
|
-
if (from === null)
|
|
511
|
-
return { kind: 'beyond-horizon' };
|
|
512
|
-
const answered = await streamed(entry, request, from);
|
|
513
|
-
if (answered !== null)
|
|
514
|
-
return answered;
|
|
515
|
-
return enumerateTogether({ entry, from, fromRoomVersion: request.fromRoomVersion });
|
|
301
|
+
return request.pageToken === undefined
|
|
302
|
+
? openedRoom(entry, request)
|
|
303
|
+
: streamedPage(entry, request.pageToken, request.held);
|
|
516
304
|
},
|
|
517
305
|
async mutate(_authorization, request, keep) {
|
|
518
306
|
const entry = authorityFor(request.locator);
|
|
@@ -529,22 +317,21 @@ export function createAgentsHouseAdapter(options) {
|
|
|
529
317
|
: houseMove(batch, entry.handle, into.handle);
|
|
530
318
|
if (mapped.kind === 'unmapped')
|
|
531
319
|
return rejectedMapping(mapped);
|
|
532
|
-
const head = operationHead(batch);
|
|
320
|
+
const head = operationHead(batch, entry.authority);
|
|
533
321
|
const delta = deltaBody(mapped.changes);
|
|
534
322
|
const bytes = deltaBytes(delta);
|
|
535
323
|
const handed = request.upload;
|
|
536
324
|
const answer = (upload) => submit(request, head, mapped.changes, delta, bytes, entry, upload, keep, into);
|
|
537
|
-
const settle = (outcome) => into === undefined ? adopted(entry, outcome) : adoptedMove(entry, into, outcome);
|
|
538
325
|
const outcome = await answer(handed);
|
|
539
326
|
if (handed === undefined || !lapsedGrant(outcome))
|
|
540
|
-
return
|
|
541
|
-
return
|
|
327
|
+
return outcome;
|
|
328
|
+
return answer(undefined);
|
|
542
329
|
},
|
|
543
330
|
async history(_authorization, request) {
|
|
544
331
|
const entry = authorityFor(request.locator);
|
|
545
332
|
if (entry === undefined)
|
|
546
333
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
547
|
-
const answer = await transport.door(
|
|
334
|
+
const answer = await transport.door(houseDoorRoute('revisions'), revisionBody({
|
|
548
335
|
path: request.path,
|
|
549
336
|
handle: entry.handle,
|
|
550
337
|
...(request.revision === undefined ? {} : { revision: request.revision }),
|
|
@@ -567,6 +354,35 @@ export function createAgentsHouseAdapter(options) {
|
|
|
567
354
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
568
355
|
return linked(await ask(), request.locator);
|
|
569
356
|
},
|
|
357
|
+
async attach(_authorization, request) {
|
|
358
|
+
const entry = authorityFor(request.locator);
|
|
359
|
+
if (entry === undefined)
|
|
360
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
361
|
+
const declared = await transport.door(houseDoorRoute('files/attach'), {
|
|
362
|
+
room_ref: entry.authority,
|
|
363
|
+
name: request.name,
|
|
364
|
+
bytes: request.byteLength,
|
|
365
|
+
sha256: request.sha256,
|
|
366
|
+
media_type: request.mediaType.length > 0 ? request.mediaType : OCTET_STREAM,
|
|
367
|
+
});
|
|
368
|
+
const refused = refusedAttach(declared, request.locator);
|
|
369
|
+
if (refused !== null)
|
|
370
|
+
return refused;
|
|
371
|
+
const upload = houseUpload(declared.body?.upload);
|
|
372
|
+
if (upload === null)
|
|
373
|
+
return UNCERTAIN_READ;
|
|
374
|
+
const finished = await finishedUpload(transport, upload, request.blob);
|
|
375
|
+
if (finished === null)
|
|
376
|
+
return UNCERTAIN_READ;
|
|
377
|
+
const unfinished = refusedAttach(finished, request.locator);
|
|
378
|
+
if (unfinished !== null)
|
|
379
|
+
return unfinished;
|
|
380
|
+
const { path, revision } = (finished.body ?? {});
|
|
381
|
+
const root = `/rooms/${entry.handle}/`;
|
|
382
|
+
return typeof path === 'string' && path.startsWith(root) && typeof revision === 'string'
|
|
383
|
+
? { kind: 'attached', path: path.slice(root.length), revision }
|
|
384
|
+
: UNCERTAIN_READ;
|
|
385
|
+
},
|
|
570
386
|
reached(locator, version, target) {
|
|
571
387
|
return reachedVersion(version, target, authorityFor(locator)?.logEpoch);
|
|
572
388
|
},
|
|
@@ -576,18 +392,12 @@ export function createAgentsHouseAdapter(options) {
|
|
|
576
392
|
async action(_authorization, request) {
|
|
577
393
|
return withAt(await houseAction(transport, request));
|
|
578
394
|
},
|
|
395
|
+
search(_authorization, request) {
|
|
396
|
+
return houseSearch(transport, [...tracked.values()], request);
|
|
397
|
+
},
|
|
579
398
|
roomStream: {
|
|
580
399
|
hold: held,
|
|
581
|
-
|
|
582
|
-
observe(notify, receipts, revisions) {
|
|
583
|
-
heldRevisions = revisions;
|
|
584
|
-
return notifications.observe(notify, receipts);
|
|
585
|
-
},
|
|
586
|
-
published(locator, roomVersion) {
|
|
587
|
-
const at = logPosition(roomVersion);
|
|
588
|
-
if (at !== null)
|
|
589
|
-
notifications.published(locator, at);
|
|
590
|
-
},
|
|
400
|
+
observe: notifications.observe,
|
|
591
401
|
},
|
|
592
402
|
conversations: notifications.conversations,
|
|
593
403
|
serviceMode: notifications.serviceMode,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-reference.d.ts","sourceRoot":"","sources":["../src/app-reference.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,qBAAqB,QAEjC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crockford.d.ts","sourceRoot":"","sources":["../src/crockford.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAErE,eAAO,MAAM,mBAAmB,uCAA4B,CAAC;AAE7D,eAAO,MAAM,2BAA2B,QAAqC,CAAC"}
|