@agentshouse/mdruntime-adapter 0.1.0-ce1149641691d → 0.1.0-ce3ced044cab5
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 +6 -26
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +18 -150
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +167 -223
- 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 +5 -10
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +18 -32
- package/dist/gather.d.ts +0 -1
- package/dist/gather.d.ts.map +1 -1
- package/dist/gather.js +1 -1
- package/dist/house-model.d.ts +2 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +486 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/model.d.ts +5 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +11 -13
- 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 +33 -17
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +187 -122
- package/dist/room-stream.d.ts +19 -0
- package/dist/room-stream.d.ts.map +1 -0
- package/dist/room-stream.js +57 -0
- package/dist/room-types.d.ts +7 -0
- package/dist/room-types.d.ts.map +1 -0
- package/dist/room-types.js +125 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +43 -92
- package/dist/stream.d.ts +1 -0
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +17 -2
- package/dist/transport.d.ts +14 -8
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +2 -1
- 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 +4 -0
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +22 -18
- package/package.json +8 -4
- package/AGENTS.md +0 -304
- package/dist/handed.d.ts +0 -15
- package/dist/handed.d.ts.map +0 -1
- package/dist/handed.js +0 -45
- package/dist/referrer.d.ts +0 -7
- package/dist/referrer.d.ts.map +0 -1
- package/dist/referrer.js +0 -35
package/dist/adapter.js
CHANGED
|
@@ -1,60 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { stepped } from '@agentshouse/mdruntime';
|
|
2
2
|
import { DISCOVER_PREFIXES, capabilities, discoveredRoom, mapDiscovery, parseDiscovery, trackedFrom, } from './discovery.js';
|
|
3
|
-
import {
|
|
4
|
-
import { gathered,
|
|
3
|
+
import { streamedModels, viewModels } from './model.js';
|
|
4
|
+
import { gathered, selections } from './gather.js';
|
|
5
5
|
import { createSiteAdapter } from './site.js';
|
|
6
|
-
import { authorityRoot, bootstrapping,
|
|
7
|
-
import {
|
|
6
|
+
import { authorityRoot, bootstrapping, parseEnumeration, parseFileAddress, parseGrant, refreshFrom, viewOf, wholeView, } from './read.js';
|
|
7
|
+
import { roomStreams } from './room-stream.js';
|
|
8
8
|
import { sha256Hex } from './digest.js';
|
|
9
|
-
import {
|
|
9
|
+
import { finishedUpload, houseUpload } from './upload.js';
|
|
10
10
|
import { houseAction } from './actions.js';
|
|
11
11
|
import { classifyDoor, classifyRead, discoveryFailure, doorRefusal } from './refusal.js';
|
|
12
12
|
import { houseNotifications } from './stream.js';
|
|
13
|
-
import { DOOR_BATCH, DOOR_BATCH_UPLOAD, DOOR_BOOTSTRAP, DOOR_DISCOVER, DOOR_ENUMERATE, DOOR_FILES_GET, DOOR_REVISIONS, } from './transport.js';
|
|
13
|
+
import { DOOR_BATCH, DOOR_BATCH_UPLOAD, DOOR_BOOTSTRAP, DOOR_DISCOVER, DOOR_ENUMERATE, DOOR_FILES_ATTACH, DOOR_FILES_GET, DOOR_REVISIONS, } from './transport.js';
|
|
14
14
|
import { batchPaths, deltaBody, deltaBytes, deltaDigest, historyOutcome, houseChanges, houseMove, mutationOutcome, operationHead, rejectedMapping, revisionBody, uploadable, } from './write.js';
|
|
15
|
-
import {
|
|
15
|
+
import { HOUSE_NAMEABLE_ROOM_TYPES, HOUSE_ROOM_TYPES } from './room-types.js';
|
|
16
16
|
import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
|
|
17
17
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
18
18
|
const UNCERTAIN_READ = { kind: 'transport-uncertainty' };
|
|
19
|
+
const OCTET_STREAM = 'application/octet-stream';
|
|
20
|
+
const EXPIRED_ADDRESS = 403;
|
|
19
21
|
function lapsedGrant(outcome) {
|
|
20
22
|
return outcome.kind === 'rejected' && outcome.code === 'upload_unavailable';
|
|
21
23
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
return known;
|
|
27
|
-
const sorted = await stepped(sortedKeys(held.documents));
|
|
28
|
-
heldPaths.set(held.documents, sorted);
|
|
29
|
-
return sorted;
|
|
30
|
-
}
|
|
31
|
-
function heldFiles(authority, held, paths, bound) {
|
|
32
|
-
const files = [];
|
|
33
|
-
let through = null;
|
|
34
|
-
for (let at = 0; at < paths.length && through === null; at += 1) {
|
|
35
|
-
const revision = held.revisions[paths[at]];
|
|
36
|
-
if (revision === undefined)
|
|
37
|
-
continue;
|
|
38
|
-
if (files.length === bound)
|
|
39
|
-
through = files.at(-1).path;
|
|
40
|
-
else
|
|
41
|
-
files.push({ path: paths[at], revision });
|
|
42
|
-
}
|
|
24
|
+
async function heldFiles(authority, held, bound) {
|
|
25
|
+
const listed = await held.files(null, bound + 1);
|
|
26
|
+
const files = listed.slice(0, bound);
|
|
27
|
+
const through = listed.length > bound ? (files.at(-1)?.path ?? null) : null;
|
|
43
28
|
return files.length === 0 ? null : { room: authority, through, files };
|
|
44
29
|
}
|
|
45
30
|
async function reused(scope, held) {
|
|
46
31
|
const sent = new Set(scope.contents.map((entry) => entry.path));
|
|
47
32
|
const contents = [...scope.contents];
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
33
|
+
const asked = scope.files.filter((file) => file.binary === undefined && !sent.has(file.path));
|
|
34
|
+
if (asked.length === 0)
|
|
35
|
+
return scope;
|
|
36
|
+
if (held === undefined)
|
|
37
|
+
return null;
|
|
38
|
+
const kept = await held.contents(asked.map(({ path }) => path));
|
|
39
|
+
for (const file of asked) {
|
|
40
|
+
const found = kept.get(file.path);
|
|
41
|
+
if (found === undefined ||
|
|
42
|
+
found.revision !== file.revision ||
|
|
43
|
+
(await sha256Hex(found.content)) !== file.sha256) {
|
|
55
44
|
return null;
|
|
56
45
|
}
|
|
57
|
-
contents.push({ path: file.path, content });
|
|
46
|
+
contents.push({ path: file.path, content: found.content });
|
|
58
47
|
}
|
|
59
48
|
return { ...scope, contents };
|
|
60
49
|
}
|
|
@@ -65,74 +54,49 @@ export function createAgentsHouseAdapter(options) {
|
|
|
65
54
|
const notifications = houseNotifications(transport, 'credential');
|
|
66
55
|
const tracked = new Map();
|
|
67
56
|
const handed = new Map();
|
|
57
|
+
const rooms = roomStreams('credential');
|
|
58
|
+
const unreused = new Set();
|
|
59
|
+
let heldRevisions;
|
|
68
60
|
let bounds;
|
|
69
61
|
function declared() {
|
|
70
62
|
if (bounds === undefined)
|
|
71
63
|
throw new Error('no Discovery declared the bounds');
|
|
72
64
|
return bounds;
|
|
73
65
|
}
|
|
74
|
-
function
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
return next.then((room) => {
|
|
82
|
-
if (handed.get(locator) === held)
|
|
83
|
-
handed.set(locator, room);
|
|
84
|
-
else
|
|
85
|
-
handed.delete(locator);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
async function fetchedPart(entry, continued, listed) {
|
|
89
|
-
for (let attempt = 0; attempt < PART_ATTEMPTS; attempt += 1) {
|
|
90
|
-
const answered = await transport.door(DOOR_BOOTSTRAP, {
|
|
91
|
-
prefixes: [authorityRoot(entry.handle)],
|
|
92
|
-
part: listed.part,
|
|
93
|
-
...(continued.held === undefined ? {} : { held: [continued.held] }),
|
|
94
|
-
});
|
|
95
|
-
const failure = classifyRead(answered.status, answered.body, entry.locator);
|
|
96
|
-
if (failure !== null)
|
|
97
|
-
return failure;
|
|
98
|
-
const scope = await housePart(continued.room, answered.body, listed, 'credential');
|
|
99
|
-
if (scope !== null)
|
|
100
|
-
return scope;
|
|
101
|
-
}
|
|
102
|
-
return unverifiedPart(entry.locator);
|
|
103
|
-
}
|
|
104
|
-
async function partPage(asked, continued) {
|
|
105
|
-
const { entry } = asked;
|
|
106
|
-
const listed = continued.room.parts[continued.next];
|
|
107
|
-
const sent = listed === undefined
|
|
108
|
-
? emptyScope(continued.room)
|
|
109
|
-
: await fetchedPart(entry, continued, listed);
|
|
110
|
-
if ('kind' in sent)
|
|
111
|
-
return sent;
|
|
112
|
-
const scope = await reused(sent, asked.held);
|
|
66
|
+
async function streamedPage(entry, token, held) {
|
|
67
|
+
const part = await rooms.part(entry, token);
|
|
68
|
+
if ('kind' in part)
|
|
69
|
+
return part;
|
|
70
|
+
const scope = await reused(part.scope, held);
|
|
113
71
|
if (scope === null) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
: bootstrapTogether({ entry, held: undefined });
|
|
72
|
+
unreused.add(entry.locator);
|
|
73
|
+
return UNCERTAIN_READ;
|
|
117
74
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (continued.next === 0 && !more)
|
|
121
|
-
await hand(entry.locator, scopeHanded(scope));
|
|
75
|
+
if (part.first && part.ended)
|
|
76
|
+
handed.set(entry.locator, roomVersion(scope));
|
|
122
77
|
else
|
|
123
78
|
handed.delete(entry.locator);
|
|
124
79
|
notifications.reach(entry.authority, scope);
|
|
125
|
-
const seen = [
|
|
126
|
-
...continued.seen,
|
|
127
|
-
...entry.schemas.filter((schema) => scope.files.some((file) => file.path === schema)),
|
|
128
|
-
];
|
|
129
|
-
const models = await partModels(scope, entry, new Set(seen), !more);
|
|
130
80
|
return {
|
|
131
81
|
...(await stepped(bootstrapping(scope))),
|
|
132
|
-
...(models === undefined ? {} : { models }),
|
|
133
|
-
...(
|
|
82
|
+
...(part.models === undefined ? {} : { models: part.models }),
|
|
83
|
+
...(part.pageToken === undefined ? {} : { pageToken: part.pageToken }),
|
|
84
|
+
bytes: part.bytes,
|
|
134
85
|
};
|
|
135
86
|
}
|
|
87
|
+
async function openedRoom(entry, request) {
|
|
88
|
+
const reusing = unreused.delete(entry.locator) ? undefined : request.held;
|
|
89
|
+
const files = reusing === undefined
|
|
90
|
+
? null
|
|
91
|
+
: await heldFiles(entry.authority, reusing, declared().max_held_files);
|
|
92
|
+
const answered = await transport.streamed(DOOR_BOOTSTRAP, {
|
|
93
|
+
prefixes: [authorityRoot(entry.handle)],
|
|
94
|
+
...(files === null ? {} : { held: [files] }),
|
|
95
|
+
}, request.signal ?? new AbortController().signal);
|
|
96
|
+
if (answered.room === null)
|
|
97
|
+
return classifyDoor(answered.status, answered.body, entry.locator) ?? UNCERTAIN_READ;
|
|
98
|
+
return rooms.head(entry, answered.room, request.arriving, request.signal);
|
|
99
|
+
}
|
|
136
100
|
async function enumeratedPage(ask, page) {
|
|
137
101
|
const answer = await transport.door(DOOR_ENUMERATE, {
|
|
138
102
|
prefixes: [authorityRoot(ask.entry.handle)],
|
|
@@ -162,18 +126,21 @@ export function createAgentsHouseAdapter(options) {
|
|
|
162
126
|
const answer = await refreshFrom(view, ask.fromRoomVersion);
|
|
163
127
|
if (answer.kind !== 'net-advancement')
|
|
164
128
|
return answer;
|
|
165
|
-
|
|
129
|
+
handed.set(ask.entry.locator, roomVersion(view));
|
|
166
130
|
const models = await viewModels(view, ask.entry);
|
|
167
131
|
return models === undefined ? answer : { ...answer, models };
|
|
168
132
|
}
|
|
169
133
|
async function streamed(entry, request, from) {
|
|
170
|
-
|
|
171
|
-
if (held?.roomVersion !== request.fromRoomVersion)
|
|
134
|
+
if (handed.get(entry.locator) !== request.fromRoomVersion)
|
|
172
135
|
return null;
|
|
173
|
-
const
|
|
136
|
+
const asked = notifications.edited(entry, from);
|
|
137
|
+
const kept = asked.length === 0 || heldRevisions === undefined
|
|
138
|
+
? new Map()
|
|
139
|
+
: await heldRevisions(entry.locator, asked);
|
|
140
|
+
const advanced = await stepped(notifications.advance(entry, from, (path, revision) => kept.get(path) === revision));
|
|
174
141
|
if (advanced === null)
|
|
175
142
|
return null;
|
|
176
|
-
|
|
143
|
+
handed.set(entry.locator, advanced.page.roomVersion);
|
|
177
144
|
const models = await streamedModels(advanced.schemas, entry, 'credential');
|
|
178
145
|
return models === undefined ? advanced.page : { ...advanced.page, models };
|
|
179
146
|
}
|
|
@@ -183,7 +150,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
183
150
|
const at = logPosition(room.roomVersion);
|
|
184
151
|
if (entry === undefined || at === null)
|
|
185
152
|
return [];
|
|
186
|
-
handed.set(room.locator,
|
|
153
|
+
handed.set(room.locator, room.roomVersion);
|
|
187
154
|
notifications.reach(entry.authority, at);
|
|
188
155
|
return [presented(entry.authority, at)];
|
|
189
156
|
});
|
|
@@ -201,8 +168,9 @@ export function createAgentsHouseAdapter(options) {
|
|
|
201
168
|
const held = handed.get(entry.locator);
|
|
202
169
|
if (held === undefined)
|
|
203
170
|
return outcome;
|
|
204
|
-
const follows = followsVersion(held
|
|
205
|
-
|
|
171
|
+
const follows = followsVersion(held, outcome.roomVersion);
|
|
172
|
+
if (follows)
|
|
173
|
+
handed.set(entry.locator, outcome.roomVersion);
|
|
206
174
|
const at = logPosition(outcome.roomVersion);
|
|
207
175
|
if (follows && at !== null)
|
|
208
176
|
notifications.reach(entry.authority, at);
|
|
@@ -225,62 +193,6 @@ export function createAgentsHouseAdapter(options) {
|
|
|
225
193
|
return result;
|
|
226
194
|
return { ...result, at: { locator, roomVersion: roomVersion({ position, logEpoch }) } };
|
|
227
195
|
}
|
|
228
|
-
async function holding(asks) {
|
|
229
|
-
const bound = Math.floor(declared().max_held_files / Math.max(1, asks.filter((ask) => ask.held !== undefined).length));
|
|
230
|
-
const held = [];
|
|
231
|
-
for (const ask of asks) {
|
|
232
|
-
if (ask.held === undefined || bound === 0)
|
|
233
|
-
continue;
|
|
234
|
-
const paths = await sortedHeld(ask.held);
|
|
235
|
-
const files = heldFiles(ask.entry.authority, ask.held, paths, bound);
|
|
236
|
-
if (files !== null)
|
|
237
|
-
held.push(files);
|
|
238
|
-
}
|
|
239
|
-
return held;
|
|
240
|
-
}
|
|
241
|
-
async function bootstrapped(asks, answer) {
|
|
242
|
-
let open = asks.map((asked, ask) => ({ entry: asked.entry, asked, ask }));
|
|
243
|
-
while (open.length > 0) {
|
|
244
|
-
const unreached = [];
|
|
245
|
-
for (const part of selections(open, declared().max_prefixes)) {
|
|
246
|
-
const held = await holding(part.map(({ asked }) => asked));
|
|
247
|
-
const answered = await transport.door(DOOR_BOOTSTRAP, {
|
|
248
|
-
prefixes: part.map(({ entry }) => authorityRoot(entry.handle)),
|
|
249
|
-
...(held.length === 0 ? {} : { held }),
|
|
250
|
-
});
|
|
251
|
-
const classified = part.map(({ entry }) => classifyDoor(answered.status, answered.body, entry.locator));
|
|
252
|
-
const parted = classified[0] === null ? parseParted(answered.body) : null;
|
|
253
|
-
for (const [index, asked] of part.entries()) {
|
|
254
|
-
const failure = classified[index];
|
|
255
|
-
if (failure !== null && failure !== undefined) {
|
|
256
|
-
answer(asked.ask, failure);
|
|
257
|
-
continue;
|
|
258
|
-
}
|
|
259
|
-
if (parted === null) {
|
|
260
|
-
answer(asked.ask, UNCERTAIN_READ);
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
const room = parted.rooms.find((candidate) => candidate.anchor === asked.entry.authority);
|
|
264
|
-
if (room === undefined && parted.next !== undefined) {
|
|
265
|
-
unreached.push(asked);
|
|
266
|
-
continue;
|
|
267
|
-
}
|
|
268
|
-
if (room === undefined) {
|
|
269
|
-
answer(asked.ask, { kind: 'room-not-readable', locator: asked.entry.locator });
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
const kept = held.find((files) => files.room === asked.entry.authority);
|
|
273
|
-
answer(asked.ask, await partPage(asked.asked, {
|
|
274
|
-
room,
|
|
275
|
-
next: 0,
|
|
276
|
-
seen: [],
|
|
277
|
-
...(kept === undefined ? {} : { held: kept }),
|
|
278
|
-
}));
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
open = unreached;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
196
|
function layered(asks) {
|
|
285
197
|
const depths = new Map();
|
|
286
198
|
const layers = [];
|
|
@@ -327,7 +239,6 @@ export function createAgentsHouseAdapter(options) {
|
|
|
327
239
|
}
|
|
328
240
|
return answers;
|
|
329
241
|
}
|
|
330
|
-
const bootstrapTogether = gatheredEach(bootstrapped);
|
|
331
242
|
const enumerateTogether = gathered(enumerated);
|
|
332
243
|
async function uploaded(head, changes, delta, bytes, entry, handed, keep) {
|
|
333
244
|
const paths = batchPaths(changes);
|
|
@@ -342,7 +253,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
342
253
|
};
|
|
343
254
|
}
|
|
344
255
|
const grant = parseGrant(minted.body);
|
|
345
|
-
if (grant === null
|
|
256
|
+
if (grant === null)
|
|
346
257
|
return { outcome: UNCERTAIN };
|
|
347
258
|
const delivered = await transport.transfer({
|
|
348
259
|
act: 'authored_batch_upload',
|
|
@@ -352,36 +263,31 @@ export function createAgentsHouseAdapter(options) {
|
|
|
352
263
|
if (delivered.status !== 200)
|
|
353
264
|
return { outcome: UNCERTAIN };
|
|
354
265
|
const holding = parseGrant(delivered.body);
|
|
355
|
-
if (holding === null
|
|
266
|
+
if (holding === null)
|
|
356
267
|
return { outcome: UNCERTAIN };
|
|
357
268
|
const upload = { url: holding.url, operation: holding.operation, bytes, sha256 };
|
|
358
269
|
await keep(upload);
|
|
359
270
|
return { body: { ...head, paths, upload, runtime: notifications.runtime } };
|
|
360
271
|
}
|
|
361
|
-
async function staged(answer, batch) {
|
|
272
|
+
async function staged(answer, { changeBatch: batch, file }) {
|
|
362
273
|
const refusal = doorRefusal(answer.body);
|
|
363
274
|
if (refusal?.code !== 'files_unstaged')
|
|
364
275
|
return null;
|
|
365
|
-
const
|
|
366
|
-
if (!Array.isArray(
|
|
276
|
+
const uploads = refusal.fields.upload;
|
|
277
|
+
if (!Array.isArray(uploads))
|
|
367
278
|
return false;
|
|
368
|
-
for (const
|
|
369
|
-
const
|
|
370
|
-
const change = batch.changes.find((held) => held.kind === 'binary' && held.sha256 === sha256);
|
|
371
|
-
if (
|
|
279
|
+
for (const named of uploads) {
|
|
280
|
+
const upload = houseUpload(named);
|
|
281
|
+
const change = batch.changes.find((held) => held.kind === 'binary' && held.sha256 === named.sha256);
|
|
282
|
+
if (upload === null || change === undefined)
|
|
372
283
|
return false;
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
url,
|
|
376
|
-
body: change.blob,
|
|
377
|
-
operation,
|
|
378
|
-
});
|
|
379
|
-
if (delivered.status !== 200)
|
|
284
|
+
const finished = await finishedUpload(transport, upload, await file(change.localId));
|
|
285
|
+
if (finished?.body?.staged !== true)
|
|
380
286
|
return false;
|
|
381
287
|
}
|
|
382
288
|
return true;
|
|
383
289
|
}
|
|
384
|
-
async function submit(
|
|
290
|
+
async function submit(request, head, changes, delta, bytes, entry, handed, keep, into) {
|
|
385
291
|
const inline = { ...head, changes, runtime: notifications.runtime };
|
|
386
292
|
const prepared = uploadable(inline, bytes, declared())
|
|
387
293
|
? await uploaded(head, changes, delta, bytes, entry, handed, keep)
|
|
@@ -389,11 +295,11 @@ export function createAgentsHouseAdapter(options) {
|
|
|
389
295
|
if ('outcome' in prepared)
|
|
390
296
|
return prepared.outcome;
|
|
391
297
|
const answer = await transport.door(DOOR_BATCH, prepared.body);
|
|
392
|
-
const stagedFiles = await staged(answer,
|
|
298
|
+
const stagedFiles = await staged(answer, request);
|
|
393
299
|
if (stagedFiles === false)
|
|
394
300
|
return UNCERTAIN;
|
|
395
301
|
const settled = stagedFiles === null ? answer : await transport.door(DOOR_BATCH, prepared.body);
|
|
396
|
-
if (stagedFiles === true && (await staged(settled,
|
|
302
|
+
if (stagedFiles === true && (await staged(settled, request)) !== null)
|
|
397
303
|
return UNCERTAIN;
|
|
398
304
|
return stepped(mutationOutcome(settled.status, settled.body, entry.locator, entry.handle, into === undefined
|
|
399
305
|
? undefined
|
|
@@ -402,7 +308,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
402
308
|
destination: { authority: into.authority, handle: into.handle },
|
|
403
309
|
}));
|
|
404
310
|
}
|
|
405
|
-
function
|
|
311
|
+
function addressed(answer, locator) {
|
|
406
312
|
const failure = classifyDoor(answer.status, answer.body, locator);
|
|
407
313
|
if (failure !== null) {
|
|
408
314
|
return failure.kind === 'scoped-refusal'
|
|
@@ -414,33 +320,61 @@ export function createAgentsHouseAdapter(options) {
|
|
|
414
320
|
}
|
|
415
321
|
: failure;
|
|
416
322
|
}
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
if (grant === null || grant.method !== 'GET' || typeof name !== 'string') {
|
|
420
|
-
return UNCERTAIN_READ;
|
|
421
|
-
}
|
|
422
|
-
return { kind: 'link', url: grant.url, name };
|
|
323
|
+
const address = parseFileAddress(answer.body);
|
|
324
|
+
return address === null ? UNCERTAIN_READ : { kind: 'address', ...address };
|
|
423
325
|
}
|
|
424
|
-
|
|
425
|
-
const
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
326
|
+
function linked(answer, locator) {
|
|
327
|
+
const address = addressed(answer, locator);
|
|
328
|
+
return address.kind === 'address'
|
|
329
|
+
? { kind: 'link', url: address.url, name: address.name, mediaType: address.mediaType }
|
|
330
|
+
: address;
|
|
331
|
+
}
|
|
332
|
+
function refusedAttach(answer, locator) {
|
|
333
|
+
const failure = classifyDoor(answer.status, answer.body, locator);
|
|
334
|
+
if (failure === null)
|
|
335
|
+
return null;
|
|
336
|
+
return failure.kind === 'scoped-refusal'
|
|
337
|
+
? {
|
|
338
|
+
kind: 'rejected',
|
|
339
|
+
code: failure.code,
|
|
340
|
+
fields: failure.fields,
|
|
341
|
+
retryable: failure.retryable,
|
|
342
|
+
}
|
|
343
|
+
: failure;
|
|
344
|
+
}
|
|
345
|
+
async function downloaded(ask, locator) {
|
|
346
|
+
let address = addressed(await ask(), locator);
|
|
347
|
+
if (address.kind !== 'address')
|
|
348
|
+
return address;
|
|
349
|
+
let read = await transport.download(address.url);
|
|
350
|
+
if (read.status === EXPIRED_ADDRESS) {
|
|
351
|
+
address = addressed(await ask(), locator);
|
|
352
|
+
if (address.kind !== 'address')
|
|
353
|
+
return address;
|
|
354
|
+
read = await transport.download(address.url);
|
|
355
|
+
}
|
|
356
|
+
if (read.status !== 200 || read.body === null)
|
|
430
357
|
return UNCERTAIN_READ;
|
|
431
|
-
return {
|
|
358
|
+
return {
|
|
359
|
+
kind: 'binary',
|
|
360
|
+
body: read.body,
|
|
361
|
+
mediaType: address.mediaType,
|
|
362
|
+
sha256: address.sha256,
|
|
363
|
+
};
|
|
432
364
|
}
|
|
433
|
-
function
|
|
365
|
+
function pathAddress(request) {
|
|
434
366
|
const entry = authorityFor(request.locator);
|
|
435
367
|
if (entry === undefined)
|
|
436
368
|
return null;
|
|
437
|
-
return transport.door(DOOR_FILES_GET, {
|
|
369
|
+
return () => transport.door(DOOR_FILES_GET, {
|
|
438
370
|
room_ref: entry.authority,
|
|
439
371
|
path: request.path,
|
|
440
372
|
revision: request.revision,
|
|
441
373
|
});
|
|
442
374
|
}
|
|
443
375
|
return {
|
|
376
|
+
roomTypes: HOUSE_ROOM_TYPES,
|
|
377
|
+
nameableRoomTypes: HOUSE_NAMEABLE_ROOM_TYPES,
|
|
444
378
|
async authorize() {
|
|
445
379
|
return options.authorize();
|
|
446
380
|
},
|
|
@@ -488,11 +422,9 @@ export function createAgentsHouseAdapter(options) {
|
|
|
488
422
|
const entry = authorityFor(request.locator);
|
|
489
423
|
if (entry === undefined)
|
|
490
424
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
return bootstrapTogether(asked);
|
|
425
|
+
return request.pageToken === undefined
|
|
426
|
+
? openedRoom(entry, request)
|
|
427
|
+
: streamedPage(entry, request.pageToken, request.held);
|
|
496
428
|
},
|
|
497
429
|
async refresh(_authorization, request) {
|
|
498
430
|
const entry = authorityFor(request.locator);
|
|
@@ -527,7 +459,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
527
459
|
const delta = deltaBody(mapped.changes);
|
|
528
460
|
const bytes = deltaBytes(delta);
|
|
529
461
|
const handed = request.upload;
|
|
530
|
-
const answer = (upload) => submit(
|
|
462
|
+
const answer = (upload) => submit(request, head, mapped.changes, delta, bytes, entry, upload, keep, into);
|
|
531
463
|
const settle = (outcome) => into === undefined ? adopted(entry, outcome) : adoptedMove(entry, into, outcome);
|
|
532
464
|
const outcome = await answer(handed);
|
|
533
465
|
if (handed === undefined || !lapsedGrant(outcome))
|
|
@@ -550,36 +482,45 @@ export function createAgentsHouseAdapter(options) {
|
|
|
550
482
|
});
|
|
551
483
|
},
|
|
552
484
|
async binary(_authorization, request) {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
return downloaded(await asked, request.locator);
|
|
558
|
-
}
|
|
559
|
-
const referrer = houseReferrer(request.referrer, tracked);
|
|
560
|
-
if (referrer === null) {
|
|
561
|
-
return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
|
|
562
|
-
}
|
|
563
|
-
const answer = await transport.door(DOOR_FILES_GET, {
|
|
564
|
-
file: request.fileRef,
|
|
565
|
-
referrer: referrer.referrer,
|
|
566
|
-
});
|
|
567
|
-
return downloaded(answer, referrer.locator);
|
|
485
|
+
const ask = pathAddress(request);
|
|
486
|
+
if (ask === null)
|
|
487
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
488
|
+
return downloaded(ask, request.locator);
|
|
568
489
|
},
|
|
569
490
|
async link(_authorization, request) {
|
|
570
|
-
const
|
|
571
|
-
if (
|
|
491
|
+
const ask = pathAddress(request);
|
|
492
|
+
if (ask === null)
|
|
572
493
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
573
|
-
return
|
|
494
|
+
return linked(await ask(), request.locator);
|
|
574
495
|
},
|
|
575
|
-
|
|
576
|
-
const
|
|
577
|
-
if (
|
|
578
|
-
return
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
496
|
+
async attach(_authorization, request) {
|
|
497
|
+
const entry = authorityFor(request.locator);
|
|
498
|
+
if (entry === undefined)
|
|
499
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
500
|
+
const declared = await transport.door(DOOR_FILES_ATTACH, {
|
|
501
|
+
room_ref: entry.authority,
|
|
502
|
+
name: request.name,
|
|
503
|
+
bytes: request.byteLength,
|
|
504
|
+
sha256: request.sha256,
|
|
505
|
+
media_type: request.mediaType.length > 0 ? request.mediaType : OCTET_STREAM,
|
|
506
|
+
});
|
|
507
|
+
const refused = refusedAttach(declared, request.locator);
|
|
508
|
+
if (refused !== null)
|
|
509
|
+
return refused;
|
|
510
|
+
const upload = houseUpload(declared.body?.upload);
|
|
511
|
+
if (upload === null)
|
|
512
|
+
return UNCERTAIN_READ;
|
|
513
|
+
const finished = await finishedUpload(transport, upload, request.blob);
|
|
514
|
+
if (finished === null)
|
|
515
|
+
return UNCERTAIN_READ;
|
|
516
|
+
const unfinished = refusedAttach(finished, request.locator);
|
|
517
|
+
if (unfinished !== null)
|
|
518
|
+
return unfinished;
|
|
519
|
+
const { path, revision } = (finished.body ?? {});
|
|
520
|
+
const root = `/rooms/${entry.handle}/`;
|
|
521
|
+
return typeof path === 'string' && path.startsWith(root) && typeof revision === 'string'
|
|
522
|
+
? { kind: 'attached', path: path.slice(root.length), revision }
|
|
523
|
+
: UNCERTAIN_READ;
|
|
583
524
|
},
|
|
584
525
|
reached(locator, version, target) {
|
|
585
526
|
return reachedVersion(version, target, authorityFor(locator)?.logEpoch);
|
|
@@ -593,7 +534,10 @@ export function createAgentsHouseAdapter(options) {
|
|
|
593
534
|
roomStream: {
|
|
594
535
|
hold: held,
|
|
595
536
|
reopen: notifications.reopen,
|
|
596
|
-
observe
|
|
537
|
+
observe(notify, receipts, revisions) {
|
|
538
|
+
heldRevisions = revisions;
|
|
539
|
+
return notifications.observe(notify, receipts);
|
|
540
|
+
},
|
|
597
541
|
published(locator, roomVersion) {
|
|
598
542
|
const at = logPosition(roomVersion);
|
|
599
543
|
if (at !== null)
|
|
@@ -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"}
|
package/dist/discovery.d.ts
CHANGED
|
@@ -22,20 +22,16 @@ export type HouseOperations = {
|
|
|
22
22
|
write: readonly string[];
|
|
23
23
|
delete: readonly string[];
|
|
24
24
|
};
|
|
25
|
-
export type
|
|
26
|
-
export type HouseModel = {
|
|
27
|
-
root: string;
|
|
28
|
-
paths: readonly string[];
|
|
29
|
-
};
|
|
25
|
+
export type HouseAccessLevel = 'search' | 'open' | 'keep';
|
|
30
26
|
export type HouseAuthority = LogPosition & {
|
|
31
27
|
roomRef: string;
|
|
32
28
|
roomHandle: string;
|
|
33
29
|
name: string;
|
|
34
30
|
schema: string;
|
|
35
|
-
|
|
31
|
+
typedSelection: readonly string[] | null;
|
|
36
32
|
managedReplication: 'admitted' | 'unavailable';
|
|
37
33
|
protectedPaths: readonly string[];
|
|
38
|
-
|
|
34
|
+
level: HouseAccessLevel;
|
|
39
35
|
operations: HouseOperations;
|
|
40
36
|
};
|
|
41
37
|
export type HouseDiscoveryDocument = {
|
|
@@ -49,8 +45,7 @@ export type TrackedAuthority = LogPosition & {
|
|
|
49
45
|
authority: string;
|
|
50
46
|
handle: string;
|
|
51
47
|
schema: string;
|
|
52
|
-
|
|
53
|
-
schemas: readonly string[];
|
|
48
|
+
typedSelection: readonly string[] | null;
|
|
54
49
|
};
|
|
55
50
|
export type HouseSiteAuthority = LogPosition & {
|
|
56
51
|
roomRef: string;
|
|
@@ -67,7 +62,7 @@ export declare function siteTracked(document: HouseSiteDiscovery): TrackedAuthor
|
|
|
67
62
|
export declare function trackedFrom(document: HouseDiscoveryDocument): TrackedAuthority[];
|
|
68
63
|
export declare function providerLimits(bounds: HouseBounds): readonly ProviderLimit[];
|
|
69
64
|
export declare function declaredRetention(bounds: HouseBounds): Retention;
|
|
70
|
-
export declare function capabilities(actions: HouseDiscoveryDocument['actions'], rooms: readonly Pick<TrackedAuthority, 'authority' | '
|
|
65
|
+
export declare function capabilities(actions: HouseDiscoveryDocument['actions'], rooms: readonly Pick<TrackedAuthority, 'authority' | 'handle'>[]): readonly Capability[];
|
|
71
66
|
export declare function siteCapabilities(): readonly Capability[];
|
|
72
67
|
export declare function discoveredRoom(authority: HouseAuthority): DiscoveredRoom;
|
|
73
68
|
export declare function mapDiscovery(document: Pick<HouseDiscoveryDocument, 'bounds'>, rooms: readonly DiscoveredRoom[], declared: readonly Capability[]): Discovery;
|
package/dist/discovery.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,SAAS,EACT,MAAM,EACN,aAAa,EACb,SAAS,EACV,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAA6B,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3E,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AAEnD,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
|