@agentshouse/mdruntime-adapter 0.1.0-cae3b43168023 → 0.1.0-cb0bbc4ccacd0
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 -72
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +7 -322
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +151 -337
- 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 +22 -14
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +75 -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 +641 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +361 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -2
- package/dist/model.d.ts +8 -3
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +37 -34
- package/dist/part.d.ts +12 -11
- package/dist/part.d.ts.map +1 -1
- package/dist/part.js +66 -56
- package/dist/read.d.ts +25 -56
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +136 -298
- 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 +67 -10
- 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 +84 -178
- 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 +52 -39
- 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 +6 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +20 -38
- package/package.json +8 -4
- package/AGENTS.md +0 -309
- package/dist/gather.d.ts +0 -4
- package/dist/gather.d.ts.map +0 -1
- package/dist/gather.js +0 -35
- package/dist/referrer.d.ts +0 -9
- package/dist/referrer.d.ts.map +0 -1
- package/dist/referrer.js +0 -41
package/dist/adapter.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
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';
|
|
6
|
+
import { spaceSchemas } from './space-schema.js';
|
|
8
7
|
import { sha256Hex } from './digest.js';
|
|
8
|
+
import { finishedUpload, houseUpload } from './upload.js';
|
|
9
9
|
import { houseAction } from './actions.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
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';
|
|
13
14
|
import { batchPaths, deltaBody, deltaBytes, deltaDigest, historyOutcome, houseChanges, houseMove, mutationOutcome, operationHead, rejectedMapping, revisionBody, uploadable, } from './write.js';
|
|
14
|
-
import {
|
|
15
|
-
import { HOUSE_ROOM_TYPES } from './room-types.js';
|
|
16
|
-
import { followsVersion, logPosition, presented, reachedVersion, roomVersion
|
|
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,142 +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
|
-
}
|
|
77
|
-
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
|
+
};
|
|
78
82
|
}
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
+
};
|
|
98
|
+
}
|
|
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);
|
|
88
104
|
if (scope === null) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
: bootstrapTogether({ entry, held: undefined });
|
|
105
|
+
unreused.add(entry.locator);
|
|
106
|
+
return UNCERTAIN_READ;
|
|
92
107
|
}
|
|
93
|
-
const next = continued.next + 1;
|
|
94
|
-
const more = next < continued.room.parts.length;
|
|
95
|
-
if (continued.next === 0 && !more)
|
|
96
|
-
handed.set(entry.locator, roomVersion(scope));
|
|
97
|
-
else
|
|
98
|
-
handed.delete(entry.locator);
|
|
99
|
-
notifications.reach(entry.authority, scope);
|
|
100
|
-
const seen = [
|
|
101
|
-
...continued.seen,
|
|
102
|
-
...entry.schemas.filter((schema) => scope.files.some((file) => file.path === schema)),
|
|
103
|
-
];
|
|
104
|
-
const models = await partModels(scope, entry, new Set(seen), !more);
|
|
105
108
|
return {
|
|
106
109
|
...(await stepped(bootstrapping(scope))),
|
|
107
|
-
...(models === undefined ? {} : { models }),
|
|
108
|
-
...(
|
|
110
|
+
...(part.models === undefined ? {} : { models: part.models }),
|
|
111
|
+
...(part.pageToken === undefined ? {} : { pageToken: part.pageToken }),
|
|
112
|
+
bytes: part.bytes,
|
|
109
113
|
};
|
|
110
114
|
}
|
|
111
|
-
async function
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
],
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const enumeration = parseEnumeration(answer.body, 'credential');
|
|
125
|
-
if (enumeration === null)
|
|
126
|
-
return UNCERTAIN_READ;
|
|
127
|
-
return (viewOf(enumeration, ask.entry) ?? { kind: 'room-not-readable', locator: ask.entry.locator });
|
|
128
|
-
}
|
|
129
|
-
async function enumeratedRoom(enumeration, ask) {
|
|
130
|
-
const first = viewOf(enumeration, ask.entry);
|
|
131
|
-
if (first === undefined)
|
|
132
|
-
return { kind: 'room-not-readable', locator: ask.entry.locator };
|
|
133
|
-
const view = await wholeView(first, (page) => enumeratedPage(ask, page));
|
|
134
|
-
if ('kind' in view)
|
|
135
|
-
return view;
|
|
136
|
-
notifications.reach(ask.entry.authority, view);
|
|
137
|
-
const answer = await refreshFrom(view, ask.fromRoomVersion);
|
|
138
|
-
if (answer.kind !== 'net-advancement')
|
|
139
|
-
return answer;
|
|
140
|
-
handed.set(ask.entry.locator, roomVersion(view));
|
|
141
|
-
const models = await viewModels(view, ask.entry);
|
|
142
|
-
return models === undefined ? answer : { ...answer, models };
|
|
143
|
-
}
|
|
144
|
-
async function streamed(entry, request, from) {
|
|
145
|
-
if (handed.get(entry.locator) !== request.fromRoomVersion)
|
|
146
|
-
return null;
|
|
147
|
-
const asked = notifications.edited(entry, from);
|
|
148
|
-
const kept = asked.length === 0 || heldRevisions === undefined
|
|
149
|
-
? new Map()
|
|
150
|
-
: await heldRevisions(entry.locator, asked);
|
|
151
|
-
const advanced = await stepped(notifications.advance(entry, from, (path, revision) => kept.get(path) === revision));
|
|
152
|
-
if (advanced === null)
|
|
153
|
-
return null;
|
|
154
|
-
handed.set(entry.locator, advanced.page.roomVersion);
|
|
155
|
-
const models = await streamedModels(advanced.schemas, entry, 'credential');
|
|
156
|
-
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);
|
|
157
128
|
}
|
|
158
129
|
function held(rooms) {
|
|
159
|
-
|
|
130
|
+
notifications.send(rooms.flatMap((room) => {
|
|
160
131
|
const entry = tracked.get(room.locator);
|
|
161
132
|
const at = logPosition(room.roomVersion);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
handed.set(room.locator, room.roomVersion);
|
|
165
|
-
notifications.reach(entry.authority, at);
|
|
166
|
-
return [presented(entry.authority, at)];
|
|
167
|
-
});
|
|
168
|
-
notifications.send(kept);
|
|
169
|
-
}
|
|
170
|
-
async function adoptedMove(entry, into, outcome) {
|
|
171
|
-
if (outcome.kind === 'accepted' && outcome.destination !== undefined) {
|
|
172
|
-
await adopted(into, { kind: 'accepted', ...outcome.destination });
|
|
173
|
-
}
|
|
174
|
-
return adopted(entry, outcome);
|
|
175
|
-
}
|
|
176
|
-
async function adopted(entry, outcome) {
|
|
177
|
-
if (outcome.kind !== 'accepted')
|
|
178
|
-
return outcome;
|
|
179
|
-
const held = handed.get(entry.locator);
|
|
180
|
-
if (held === undefined)
|
|
181
|
-
return outcome;
|
|
182
|
-
const follows = followsVersion(held, outcome.roomVersion);
|
|
183
|
-
if (follows)
|
|
184
|
-
handed.set(entry.locator, outcome.roomVersion);
|
|
185
|
-
const at = logPosition(outcome.roomVersion);
|
|
186
|
-
if (follows && at !== null)
|
|
187
|
-
notifications.reach(entry.authority, at);
|
|
188
|
-
return outcome;
|
|
133
|
+
return entry === undefined || at === null ? [] : [presented(entry.authority, at)];
|
|
134
|
+
}));
|
|
189
135
|
}
|
|
190
136
|
function authorityFor(locator) {
|
|
191
137
|
return tracked.get(locator);
|
|
@@ -204,116 +150,18 @@ export function createAgentsHouseAdapter(options) {
|
|
|
204
150
|
return result;
|
|
205
151
|
return { ...result, at: { locator, roomVersion: roomVersion({ position, logEpoch }) } };
|
|
206
152
|
}
|
|
207
|
-
async function holding(asks) {
|
|
208
|
-
const bound = Math.floor(declared().max_held_files / Math.max(1, asks.filter((ask) => ask.held !== undefined).length));
|
|
209
|
-
const held = [];
|
|
210
|
-
for (const ask of asks) {
|
|
211
|
-
if (ask.held === undefined || bound === 0)
|
|
212
|
-
continue;
|
|
213
|
-
const files = await heldFiles(ask.entry.authority, ask.held, bound);
|
|
214
|
-
if (files !== null)
|
|
215
|
-
held.push(files);
|
|
216
|
-
}
|
|
217
|
-
return held;
|
|
218
|
-
}
|
|
219
|
-
async function bootstrapped(asks, answer) {
|
|
220
|
-
let open = asks.map((asked, ask) => ({ entry: asked.entry, asked, ask }));
|
|
221
|
-
while (open.length > 0) {
|
|
222
|
-
const unreached = [];
|
|
223
|
-
for (const part of selections(open, declared().max_prefixes)) {
|
|
224
|
-
const held = await holding(part.map(({ asked }) => asked));
|
|
225
|
-
const answered = await transport.door(DOOR_BOOTSTRAP, {
|
|
226
|
-
prefixes: part.map(({ entry }) => authorityRoot(entry.handle)),
|
|
227
|
-
...(held.length === 0 ? {} : { held }),
|
|
228
|
-
});
|
|
229
|
-
const classified = part.map(({ entry }) => classifyDoor(answered.status, answered.body, entry.locator));
|
|
230
|
-
const parted = classified[0] === null ? parseParted(answered.body) : null;
|
|
231
|
-
for (const [index, asked] of part.entries()) {
|
|
232
|
-
const failure = classified[index];
|
|
233
|
-
if (failure !== null && failure !== undefined) {
|
|
234
|
-
answer(asked.ask, failure);
|
|
235
|
-
continue;
|
|
236
|
-
}
|
|
237
|
-
if (parted === null) {
|
|
238
|
-
answer(asked.ask, UNCERTAIN_READ);
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
const room = parted.rooms.find((candidate) => candidate.anchor === asked.entry.authority);
|
|
242
|
-
if (room === undefined && parted.next !== undefined) {
|
|
243
|
-
unreached.push(asked);
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
if (room === undefined) {
|
|
247
|
-
answer(asked.ask, { kind: 'room-not-readable', locator: asked.entry.locator });
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
const kept = held.find((files) => files.room === asked.entry.authority);
|
|
251
|
-
answer(asked.ask, await partPage(asked.asked, {
|
|
252
|
-
room,
|
|
253
|
-
next: 0,
|
|
254
|
-
seen: [],
|
|
255
|
-
...(kept === undefined ? {} : { held: kept }),
|
|
256
|
-
}));
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
open = unreached;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
function layered(asks) {
|
|
263
|
-
const depths = new Map();
|
|
264
|
-
const layers = [];
|
|
265
|
-
for (const ask of asks) {
|
|
266
|
-
const depth = depths.get(ask.ask.entry.authority) ?? 0;
|
|
267
|
-
depths.set(ask.ask.entry.authority, depth + 1);
|
|
268
|
-
(layers[depth] ??= []).push(ask);
|
|
269
|
-
}
|
|
270
|
-
return layers;
|
|
271
|
-
}
|
|
272
|
-
async function enumerated(asks) {
|
|
273
|
-
const answers = [];
|
|
274
|
-
const parts = layered(asks.map((ask, index) => ({ ask, index }))).flatMap((layer) => selections(layer, declared().max_prefixes));
|
|
275
|
-
for (const part of parts) {
|
|
276
|
-
let open = [...part];
|
|
277
|
-
while (open.length > 0) {
|
|
278
|
-
const answer = await transport.door(DOOR_ENUMERATE, {
|
|
279
|
-
prefixes: open.map(({ ask }) => authorityRoot(ask.entry.handle)),
|
|
280
|
-
positions: open.map(({ ask }) => presented(ask.entry.authority, ask.from)),
|
|
281
|
-
});
|
|
282
|
-
const classified = open.map(({ ask }) => classifyRead(answer.status, answer.body, ask.entry.locator));
|
|
283
|
-
if (classified[0]?.kind === 'beyond-horizon') {
|
|
284
|
-
const named = doorRefusal(answer.body)?.fields.authority;
|
|
285
|
-
const expired = open.filter(({ ask }) => ask.entry.authority === named);
|
|
286
|
-
const answered = expired.length === 0 ? UNCERTAIN_READ : { kind: 'beyond-horizon' };
|
|
287
|
-
const gone = expired.length === 0 ? open : expired;
|
|
288
|
-
for (const ask of gone)
|
|
289
|
-
answers[ask.index] = answered;
|
|
290
|
-
open = open.filter((ask) => !gone.includes(ask));
|
|
291
|
-
continue;
|
|
292
|
-
}
|
|
293
|
-
const enumeration = classified[0] === null ? parseEnumeration(answer.body, 'credential') : null;
|
|
294
|
-
for (const [answerIndex, { ask, index }] of open.entries()) {
|
|
295
|
-
const failure = classified[answerIndex];
|
|
296
|
-
if (failure !== null && failure !== undefined) {
|
|
297
|
-
answers[index] = failure;
|
|
298
|
-
continue;
|
|
299
|
-
}
|
|
300
|
-
answers[index] =
|
|
301
|
-
enumeration === null ? UNCERTAIN_READ : await enumeratedRoom(enumeration, ask);
|
|
302
|
-
}
|
|
303
|
-
open = [];
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
return answers;
|
|
307
|
-
}
|
|
308
|
-
const bootstrapTogether = gatheredEach(bootstrapped);
|
|
309
|
-
const enumerateTogether = gathered(enumerated);
|
|
310
153
|
async function uploaded(head, changes, delta, bytes, entry, handed, keep) {
|
|
311
154
|
const paths = batchPaths(changes);
|
|
312
155
|
const sha256 = await deltaDigest(delta);
|
|
313
156
|
if (handed !== undefined && handed.sha256 === sha256) {
|
|
314
157
|
return { body: { ...head, paths, upload: handed, runtime: notifications.runtime } };
|
|
315
158
|
}
|
|
316
|
-
const minted = await transport.door(
|
|
159
|
+
const minted = await transport.door(houseDoorRoute('batch-upload'), {
|
|
160
|
+
...head,
|
|
161
|
+
paths,
|
|
162
|
+
bytes,
|
|
163
|
+
sha256,
|
|
164
|
+
});
|
|
317
165
|
if (minted.status !== 200) {
|
|
318
166
|
return {
|
|
319
167
|
outcome: await stepped(mutationOutcome(minted.status, minted.body, entry.locator, entry.handle)),
|
|
@@ -340,21 +188,16 @@ export function createAgentsHouseAdapter(options) {
|
|
|
340
188
|
const refusal = doorRefusal(answer.body);
|
|
341
189
|
if (refusal?.code !== 'files_unstaged')
|
|
342
190
|
return null;
|
|
343
|
-
const
|
|
344
|
-
if (!Array.isArray(
|
|
191
|
+
const uploads = refusal.fields.upload;
|
|
192
|
+
if (!Array.isArray(uploads))
|
|
345
193
|
return false;
|
|
346
|
-
for (const
|
|
347
|
-
const
|
|
348
|
-
const change = batch.changes.find((held) => held.kind === 'binary' && held.sha256 === sha256);
|
|
349
|
-
if (
|
|
194
|
+
for (const named of uploads) {
|
|
195
|
+
const upload = houseUpload(named);
|
|
196
|
+
const change = batch.changes.find((held) => held.kind === 'binary' && held.sha256 === named.sha256);
|
|
197
|
+
if (upload === null || change === undefined)
|
|
350
198
|
return false;
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
url,
|
|
354
|
-
body: await file(change.localId),
|
|
355
|
-
operation,
|
|
356
|
-
});
|
|
357
|
-
if (delivered.status !== 200)
|
|
199
|
+
const finished = await finishedUpload(transport, upload, await file(change.localId));
|
|
200
|
+
if (finished?.body?.staged !== true)
|
|
358
201
|
return false;
|
|
359
202
|
}
|
|
360
203
|
return true;
|
|
@@ -366,11 +209,11 @@ export function createAgentsHouseAdapter(options) {
|
|
|
366
209
|
: { body: inline };
|
|
367
210
|
if ('outcome' in prepared)
|
|
368
211
|
return prepared.outcome;
|
|
369
|
-
const answer = await transport.door(
|
|
212
|
+
const answer = await transport.door(houseDoorRoute('batch'), prepared.body);
|
|
370
213
|
const stagedFiles = await staged(answer, request);
|
|
371
214
|
if (stagedFiles === false)
|
|
372
215
|
return UNCERTAIN;
|
|
373
|
-
const settled = stagedFiles === null ? answer : await transport.door(
|
|
216
|
+
const settled = stagedFiles === null ? answer : await transport.door(houseDoorRoute('batch'), prepared.body);
|
|
374
217
|
if (stagedFiles === true && (await staged(settled, request)) !== null)
|
|
375
218
|
return UNCERTAIN;
|
|
376
219
|
return stepped(mutationOutcome(settled.status, settled.body, entry.locator, entry.handle, into === undefined
|
|
@@ -398,9 +241,22 @@ export function createAgentsHouseAdapter(options) {
|
|
|
398
241
|
function linked(answer, locator) {
|
|
399
242
|
const address = addressed(answer, locator);
|
|
400
243
|
return address.kind === 'address'
|
|
401
|
-
? { kind: 'link', url: address.url, name: address.name }
|
|
244
|
+
? { kind: 'link', url: address.url, name: address.name, mediaType: address.mediaType }
|
|
402
245
|
: address;
|
|
403
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
|
+
}
|
|
404
260
|
async function downloaded(ask, locator) {
|
|
405
261
|
let address = addressed(await ask(), locator);
|
|
406
262
|
if (address.kind !== 'address')
|
|
@@ -425,7 +281,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
425
281
|
const entry = authorityFor(request.locator);
|
|
426
282
|
if (entry === undefined)
|
|
427
283
|
return null;
|
|
428
|
-
return () => transport.door(
|
|
284
|
+
return () => transport.door(houseDoorRoute('files/get'), {
|
|
429
285
|
room_ref: entry.authority,
|
|
430
286
|
path: request.path,
|
|
431
287
|
revision: request.revision,
|
|
@@ -433,72 +289,18 @@ export function createAgentsHouseAdapter(options) {
|
|
|
433
289
|
}
|
|
434
290
|
return {
|
|
435
291
|
roomTypes: HOUSE_ROOM_TYPES,
|
|
292
|
+
nameableRoomTypes: HOUSE_NAMEABLE_ROOM_TYPES,
|
|
293
|
+
typedPaths: HOUSE_TYPED_PATHS,
|
|
436
294
|
async authorize() {
|
|
437
295
|
return options.authorize();
|
|
438
296
|
},
|
|
439
|
-
async discover(_authorization, scope) {
|
|
440
|
-
const answer = await transport.door(DOOR_DISCOVER, {
|
|
441
|
-
prefixes: [...DISCOVER_PREFIXES],
|
|
442
|
-
...(scope === undefined ? {} : { rooms: scope.authorities }),
|
|
443
|
-
});
|
|
444
|
-
const failed = discoveryFailure(answer.status, answer.body);
|
|
445
|
-
if (failed !== null)
|
|
446
|
-
return failed;
|
|
447
|
-
const document = parseDiscovery(answer.body);
|
|
448
|
-
if (document === null)
|
|
449
|
-
return { kind: 'transport-uncertainty' };
|
|
450
|
-
bounds = document.bounds;
|
|
451
|
-
const entries = trackedFrom(document);
|
|
452
|
-
const covered = scope === undefined
|
|
453
|
-
? null
|
|
454
|
-
: [
|
|
455
|
-
...new Set([
|
|
456
|
-
...[...tracked.values()]
|
|
457
|
-
.filter((entry) => scope.authorities.includes(entry.authority))
|
|
458
|
-
.map((entry) => entry.locator),
|
|
459
|
-
...entries.map((entry) => entry.locator),
|
|
460
|
-
]),
|
|
461
|
-
];
|
|
462
|
-
if (covered === null)
|
|
463
|
-
tracked.clear();
|
|
464
|
-
else
|
|
465
|
-
for (const locator of covered)
|
|
466
|
-
tracked.delete(locator);
|
|
467
|
-
for (const entry of entries)
|
|
468
|
-
tracked.set(entry.locator, entry);
|
|
469
|
-
for (const locator of handed.keys())
|
|
470
|
-
if (!tracked.has(locator))
|
|
471
|
-
handed.delete(locator);
|
|
472
|
-
notifications.track([...tracked.values()]);
|
|
473
|
-
return {
|
|
474
|
-
...mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document.actions, [...tracked.values()])),
|
|
475
|
-
member: document.member,
|
|
476
|
-
...(covered === null ? {} : { covered }),
|
|
477
|
-
};
|
|
478
|
-
},
|
|
479
297
|
async bootstrap(_authorization, request) {
|
|
480
298
|
const entry = authorityFor(request.locator);
|
|
481
299
|
if (entry === undefined)
|
|
482
300
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
}
|
|
487
|
-
return bootstrapTogether(asked);
|
|
488
|
-
},
|
|
489
|
-
async refresh(_authorization, request) {
|
|
490
|
-
const entry = authorityFor(request.locator);
|
|
491
|
-
if (entry === undefined)
|
|
492
|
-
return { kind: 'room-not-readable', locator: request.locator };
|
|
493
|
-
if (request.pageToken !== undefined)
|
|
494
|
-
return { kind: 'transport-uncertainty' };
|
|
495
|
-
const from = logPosition(request.fromRoomVersion);
|
|
496
|
-
if (from === null)
|
|
497
|
-
return { kind: 'beyond-horizon' };
|
|
498
|
-
const answered = await streamed(entry, request, from);
|
|
499
|
-
if (answered !== null)
|
|
500
|
-
return answered;
|
|
501
|
-
return enumerateTogether({ entry, from, fromRoomVersion: request.fromRoomVersion });
|
|
301
|
+
return request.pageToken === undefined
|
|
302
|
+
? openedRoom(entry, request)
|
|
303
|
+
: streamedPage(entry, request.pageToken, request.held);
|
|
502
304
|
},
|
|
503
305
|
async mutate(_authorization, request, keep) {
|
|
504
306
|
const entry = authorityFor(request.locator);
|
|
@@ -515,22 +317,21 @@ export function createAgentsHouseAdapter(options) {
|
|
|
515
317
|
: houseMove(batch, entry.handle, into.handle);
|
|
516
318
|
if (mapped.kind === 'unmapped')
|
|
517
319
|
return rejectedMapping(mapped);
|
|
518
|
-
const head = operationHead(batch);
|
|
320
|
+
const head = operationHead(batch, entry.authority);
|
|
519
321
|
const delta = deltaBody(mapped.changes);
|
|
520
322
|
const bytes = deltaBytes(delta);
|
|
521
323
|
const handed = request.upload;
|
|
522
324
|
const answer = (upload) => submit(request, head, mapped.changes, delta, bytes, entry, upload, keep, into);
|
|
523
|
-
const settle = (outcome) => into === undefined ? adopted(entry, outcome) : adoptedMove(entry, into, outcome);
|
|
524
325
|
const outcome = await answer(handed);
|
|
525
326
|
if (handed === undefined || !lapsedGrant(outcome))
|
|
526
|
-
return
|
|
527
|
-
return
|
|
327
|
+
return outcome;
|
|
328
|
+
return answer(undefined);
|
|
528
329
|
},
|
|
529
330
|
async history(_authorization, request) {
|
|
530
331
|
const entry = authorityFor(request.locator);
|
|
531
332
|
if (entry === undefined)
|
|
532
333
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
533
|
-
const answer = await transport.door(
|
|
334
|
+
const answer = await transport.door(houseDoorRoute('revisions'), revisionBody({
|
|
534
335
|
path: request.path,
|
|
535
336
|
handle: entry.handle,
|
|
536
337
|
...(request.revision === undefined ? {} : { revision: request.revision }),
|
|
@@ -542,17 +343,10 @@ export function createAgentsHouseAdapter(options) {
|
|
|
542
343
|
});
|
|
543
344
|
},
|
|
544
345
|
async binary(_authorization, request) {
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
return downloaded(ask, request.locator);
|
|
550
|
-
}
|
|
551
|
-
const referrer = houseReferrer(request.referrer, tracked);
|
|
552
|
-
if (referrer === null) {
|
|
553
|
-
return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
|
|
554
|
-
}
|
|
555
|
-
return downloaded(() => transport.door(DOOR_FILES_GET, { file: request.fileRef, referrer: referrer.referrer }), referrer.locator);
|
|
346
|
+
const ask = pathAddress(request);
|
|
347
|
+
if (ask === null)
|
|
348
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
349
|
+
return downloaded(ask, request.locator);
|
|
556
350
|
},
|
|
557
351
|
async link(_authorization, request) {
|
|
558
352
|
const ask = pathAddress(request);
|
|
@@ -560,8 +354,34 @@ export function createAgentsHouseAdapter(options) {
|
|
|
560
354
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
561
355
|
return linked(await ask(), request.locator);
|
|
562
356
|
},
|
|
563
|
-
|
|
564
|
-
|
|
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;
|
|
565
385
|
},
|
|
566
386
|
reached(locator, version, target) {
|
|
567
387
|
return reachedVersion(version, target, authorityFor(locator)?.logEpoch);
|
|
@@ -572,18 +392,12 @@ export function createAgentsHouseAdapter(options) {
|
|
|
572
392
|
async action(_authorization, request) {
|
|
573
393
|
return withAt(await houseAction(transport, request));
|
|
574
394
|
},
|
|
395
|
+
search(_authorization, request) {
|
|
396
|
+
return houseSearch(transport, [...tracked.values()], request);
|
|
397
|
+
},
|
|
575
398
|
roomStream: {
|
|
576
399
|
hold: held,
|
|
577
|
-
|
|
578
|
-
observe(notify, receipts, revisions) {
|
|
579
|
-
heldRevisions = revisions;
|
|
580
|
-
return notifications.observe(notify, receipts);
|
|
581
|
-
},
|
|
582
|
-
published(locator, roomVersion) {
|
|
583
|
-
const at = logPosition(roomVersion);
|
|
584
|
-
if (at !== null)
|
|
585
|
-
notifications.published(locator, at);
|
|
586
|
-
},
|
|
400
|
+
observe: notifications.observe,
|
|
587
401
|
},
|
|
588
402
|
conversations: notifications.conversations,
|
|
589
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"}
|