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