@agentshouse/mdruntime-adapter 0.1.0-cbc4863107a46 → 0.1.0-cc1bdabaf4e28
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 +14 -21
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +84 -133
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +212 -163
- 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 +6 -10
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +34 -29
- package/dist/gather.d.ts +1 -1
- package/dist/gather.d.ts.map +1 -1
- package/dist/gather.js +4 -14
- package/dist/house-model.d.ts +2 -0
- package/dist/house-model.d.ts.map +1 -0
- package/dist/house-model.js +442 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -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 +15 -0
- package/dist/part.d.ts.map +1 -0
- package/dist/part.js +82 -0
- package/dist/read.d.ts +57 -26
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +268 -152
- package/dist/room-types.d.ts +7 -0
- package/dist/room-types.d.ts.map +1 -0
- package/dist/room-types.js +124 -0
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +78 -104
- package/dist/stream.d.ts +3 -3
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +58 -36
- package/dist/transport.d.ts +23 -10
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +1 -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 +12 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +92 -55
- package/package.json +8 -4
- package/AGENTS.md +0 -299
- package/dist/handed.d.ts +0 -15
- package/dist/handed.d.ts.map +0 -1
- package/dist/handed.js +0 -38
- package/dist/referrer.d.ts +0 -7
- package/dist/referrer.d.ts.map +0 -1
- package/dist/referrer.js +0 -35
package/dist/adapter.js
CHANGED
|
@@ -1,46 +1,48 @@
|
|
|
1
|
+
import { stepped } from '@agentshouse/mdruntime';
|
|
1
2
|
import { DISCOVER_PREFIXES, capabilities, discoveredRoom, mapDiscovery, parseDiscovery, trackedFrom, } from './discovery.js';
|
|
2
|
-
import { partModels, streamedModels, viewModels } from './model.js';
|
|
3
|
+
import { manifestedModels, partModels, streamedModels, viewModels } from './model.js';
|
|
3
4
|
import { gathered, gatheredEach, selections } from './gather.js';
|
|
4
5
|
import { createSiteAdapter } from './site.js';
|
|
5
|
-
import {
|
|
6
|
+
import { authorityRoot, bootstrapping, emptyScope, housePart, manifested, parseEnumeration, parseFileAddress, parseGrant, parseParted, partInventory, refreshFrom, viewOf, wholeView, } from './read.js';
|
|
7
|
+
import { PART_ATTEMPTS, partArrival, partFrame, unverifiedPart } from './part.js';
|
|
6
8
|
import { sha256Hex } from './digest.js';
|
|
7
|
-
import {
|
|
9
|
+
import { finishedUpload, houseUpload } from './upload.js';
|
|
8
10
|
import { houseAction } from './actions.js';
|
|
9
11
|
import { classifyDoor, classifyRead, discoveryFailure, doorRefusal } from './refusal.js';
|
|
10
12
|
import { houseNotifications } from './stream.js';
|
|
11
13
|
import { DOOR_BATCH, DOOR_BATCH_UPLOAD, DOOR_BOOTSTRAP, DOOR_DISCOVER, DOOR_ENUMERATE, DOOR_FILES_GET, DOOR_REVISIONS, } from './transport.js';
|
|
12
|
-
import { batchPaths, deltaBody, deltaBytes, deltaDigest, historyOutcome, houseChanges, mutationOutcome, operationHead, rejectedMapping, revisionBody, uploadable, } from './write.js';
|
|
13
|
-
import {
|
|
14
|
+
import { batchPaths, deltaBody, deltaBytes, deltaDigest, historyOutcome, houseChanges, houseMove, mutationOutcome, operationHead, rejectedMapping, revisionBody, uploadable, } from './write.js';
|
|
15
|
+
import { HOUSE_NAMEABLE_ROOM_TYPES, HOUSE_ROOM_TYPES } from './room-types.js';
|
|
14
16
|
import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
|
|
15
17
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
16
18
|
const UNCERTAIN_READ = { kind: 'transport-uncertainty' };
|
|
19
|
+
const EXPIRED_ADDRESS = 403;
|
|
17
20
|
function lapsedGrant(outcome) {
|
|
18
21
|
return outcome.kind === 'rejected' && outcome.code === 'upload_unavailable';
|
|
19
22
|
}
|
|
20
|
-
function heldFiles(authority, held,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
.sort();
|
|
26
|
-
if (paths.length === 0)
|
|
27
|
-
return null;
|
|
28
|
-
const files = paths.slice(0, budget).map((path) => ({ path, revision: held.revisions[path] }));
|
|
29
|
-
return { room: authority, through: paths.length > budget ? files.at(-1).path : null, files };
|
|
23
|
+
async function heldFiles(authority, held, bound) {
|
|
24
|
+
const listed = await held.files(null, bound + 1);
|
|
25
|
+
const files = listed.slice(0, bound);
|
|
26
|
+
const through = listed.length > bound ? (files.at(-1)?.path ?? null) : null;
|
|
27
|
+
return files.length === 0 ? null : { room: authority, through, files };
|
|
30
28
|
}
|
|
31
29
|
async function reused(scope, held) {
|
|
32
30
|
const sent = new Set(scope.contents.map((entry) => entry.path));
|
|
33
31
|
const contents = [...scope.contents];
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
const asked = scope.files.filter((file) => file.binary === undefined && !sent.has(file.path));
|
|
33
|
+
if (asked.length === 0)
|
|
34
|
+
return scope;
|
|
35
|
+
if (held === undefined)
|
|
36
|
+
return null;
|
|
37
|
+
const kept = await held.contents(asked.map(({ path }) => path));
|
|
38
|
+
for (const file of asked) {
|
|
39
|
+
const found = kept.get(file.path);
|
|
40
|
+
if (found === undefined ||
|
|
41
|
+
found.revision !== file.revision ||
|
|
42
|
+
(await sha256Hex(found.content)) !== file.sha256) {
|
|
41
43
|
return null;
|
|
42
44
|
}
|
|
43
|
-
contents.push({ path: file.path, content });
|
|
45
|
+
contents.push({ path: file.path, content: found.content });
|
|
44
46
|
}
|
|
45
47
|
return { ...scope, contents };
|
|
46
48
|
}
|
|
@@ -51,48 +53,83 @@ export function createAgentsHouseAdapter(options) {
|
|
|
51
53
|
const notifications = houseNotifications(transport, 'credential');
|
|
52
54
|
const tracked = new Map();
|
|
53
55
|
const handed = new Map();
|
|
56
|
+
let heldRevisions;
|
|
54
57
|
let bounds;
|
|
55
58
|
function declared() {
|
|
56
59
|
if (bounds === undefined)
|
|
57
60
|
throw new Error('no Discovery declared the bounds');
|
|
58
61
|
return bounds;
|
|
59
62
|
}
|
|
60
|
-
async function
|
|
63
|
+
async function fetchedPart(entry, continued, listed, received, arriving) {
|
|
64
|
+
if (received !== undefined) {
|
|
65
|
+
const kept = new Uint8Array(received);
|
|
66
|
+
const held = await housePart(continued.room, kept, listed, 'credential');
|
|
67
|
+
if (held !== null)
|
|
68
|
+
return 'kind' in held ? held : { scope: held, frame: kept };
|
|
69
|
+
}
|
|
70
|
+
for (let attempt = 0; attempt < PART_ATTEMPTS; attempt += 1) {
|
|
71
|
+
const answered = await transport.door(DOOR_BOOTSTRAP, {
|
|
72
|
+
prefixes: [authorityRoot(entry.handle)],
|
|
73
|
+
part: listed.part,
|
|
74
|
+
...(continued.held === undefined ? {} : { held: [continued.held] }),
|
|
75
|
+
}, partArrival(listed, arriving));
|
|
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);
|
|
87
|
+
}
|
|
88
|
+
async function manifestPage(asked, continued) {
|
|
89
|
+
const inventory = partInventory(continued.room);
|
|
90
|
+
if (inventory.parts === 0) {
|
|
91
|
+
const page = await partPage(asked, continued, undefined, undefined);
|
|
92
|
+
return page.kind === 'bootstrap' ? { ...page, inventory } : page;
|
|
93
|
+
}
|
|
94
|
+
const { models, seen } = await manifestedModels(continued.room, asked.entry);
|
|
95
|
+
return manifested(continued.room, inventory, JSON.stringify({ ...continued, seen }), models);
|
|
96
|
+
}
|
|
97
|
+
async function partPage(asked, continued, received, arriving) {
|
|
61
98
|
const { entry } = asked;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
99
|
+
const listed = continued.room.parts[continued.next];
|
|
100
|
+
const sent = listed === undefined
|
|
101
|
+
? { scope: emptyScope(continued.room), frame: null }
|
|
102
|
+
: await fetchedPart(entry, continued, listed, received, arriving);
|
|
103
|
+
if ('kind' in sent)
|
|
104
|
+
return sent;
|
|
105
|
+
const scope = await reused(sent.scope, asked.held);
|
|
65
106
|
if (scope === null) {
|
|
66
107
|
return asked.held === undefined
|
|
67
108
|
? UNCERTAIN_READ
|
|
68
|
-
:
|
|
69
|
-
? bootstrapTogether({ entry, held: undefined })
|
|
70
|
-
: continuedBootstrap({ entry, held: undefined }, continued);
|
|
109
|
+
: bootstrapTogether({ entry, held: undefined });
|
|
71
110
|
}
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
if (continued ===
|
|
75
|
-
handed.set(entry.locator,
|
|
111
|
+
const next = continued.next + 1;
|
|
112
|
+
const more = next < continued.room.parts.length;
|
|
113
|
+
if (continued.next === 0 && !more)
|
|
114
|
+
handed.set(entry.locator, roomVersion(scope));
|
|
76
115
|
else
|
|
77
116
|
handed.delete(entry.locator);
|
|
78
117
|
notifications.reach(entry.authority, scope);
|
|
79
118
|
const seen = [
|
|
80
|
-
...
|
|
81
|
-
...
|
|
119
|
+
...continued.seen,
|
|
120
|
+
...(scope.files.some((file) => file.path === entry.schema) ? [entry.schema] : []),
|
|
82
121
|
];
|
|
83
|
-
const models = await partModels(scope, entry, new Set(seen),
|
|
84
|
-
const continuation = next === null
|
|
85
|
-
? null
|
|
86
|
-
: { after: next, seen, ...(cursor?.cut === undefined ? {} : { cut: cursor.cut }) };
|
|
122
|
+
const models = await partModels(scope, entry, new Set(seen), !more);
|
|
87
123
|
return {
|
|
88
|
-
...
|
|
124
|
+
...(await stepped(bootstrapping(scope))),
|
|
89
125
|
...(models === undefined ? {} : { models }),
|
|
90
|
-
...(
|
|
126
|
+
...(more ? { pageToken: JSON.stringify({ ...continued, next, seen }) } : {}),
|
|
127
|
+
...(sent.frame === null ? {} : { received: sent.frame }),
|
|
91
128
|
};
|
|
92
129
|
}
|
|
93
130
|
async function enumeratedPage(ask, page) {
|
|
94
131
|
const answer = await transport.door(DOOR_ENUMERATE, {
|
|
95
|
-
prefixes:
|
|
132
|
+
prefixes: [authorityRoot(ask.entry.handle)],
|
|
96
133
|
positions: [
|
|
97
134
|
{
|
|
98
135
|
...presented(ask.entry.authority, { position: page.after, logEpoch: ask.from.logEpoch }),
|
|
@@ -116,21 +153,24 @@ export function createAgentsHouseAdapter(options) {
|
|
|
116
153
|
if ('kind' in view)
|
|
117
154
|
return view;
|
|
118
155
|
notifications.reach(ask.entry.authority, view);
|
|
119
|
-
const answer = refreshFrom(view, ask.fromRoomVersion);
|
|
156
|
+
const answer = await refreshFrom(view, ask.fromRoomVersion);
|
|
120
157
|
if (answer.kind !== 'net-advancement')
|
|
121
158
|
return answer;
|
|
122
|
-
handed.set(ask.entry.locator,
|
|
159
|
+
handed.set(ask.entry.locator, roomVersion(view));
|
|
123
160
|
const models = await viewModels(view, ask.entry);
|
|
124
161
|
return models === undefined ? answer : { ...answer, models };
|
|
125
162
|
}
|
|
126
163
|
async function streamed(entry, request, from) {
|
|
127
|
-
|
|
128
|
-
if (held?.roomVersion !== request.fromRoomVersion)
|
|
164
|
+
if (handed.get(entry.locator) !== request.fromRoomVersion)
|
|
129
165
|
return null;
|
|
130
|
-
const
|
|
166
|
+
const asked = notifications.edited(entry, from);
|
|
167
|
+
const kept = asked.length === 0 || heldRevisions === undefined
|
|
168
|
+
? new Map()
|
|
169
|
+
: await heldRevisions(entry.locator, asked);
|
|
170
|
+
const advanced = await stepped(notifications.advance(entry, from, (path, revision) => kept.get(path) === revision));
|
|
131
171
|
if (advanced === null)
|
|
132
172
|
return null;
|
|
133
|
-
handed.set(entry.locator,
|
|
173
|
+
handed.set(entry.locator, advanced.page.roomVersion);
|
|
134
174
|
const models = await streamedModels(advanced.schemas, entry, 'credential');
|
|
135
175
|
return models === undefined ? advanced.page : { ...advanced.page, models };
|
|
136
176
|
}
|
|
@@ -140,20 +180,27 @@ export function createAgentsHouseAdapter(options) {
|
|
|
140
180
|
const at = logPosition(room.roomVersion);
|
|
141
181
|
if (entry === undefined || at === null)
|
|
142
182
|
return [];
|
|
143
|
-
handed.set(room.locator,
|
|
183
|
+
handed.set(room.locator, room.roomVersion);
|
|
144
184
|
notifications.reach(entry.authority, at);
|
|
145
185
|
return [presented(entry.authority, at)];
|
|
146
186
|
});
|
|
147
187
|
notifications.send(kept);
|
|
148
188
|
}
|
|
149
|
-
function
|
|
189
|
+
async function adoptedMove(entry, into, outcome) {
|
|
190
|
+
if (outcome.kind === 'accepted' && outcome.destination !== undefined) {
|
|
191
|
+
await adopted(into, { kind: 'accepted', ...outcome.destination });
|
|
192
|
+
}
|
|
193
|
+
return adopted(entry, outcome);
|
|
194
|
+
}
|
|
195
|
+
async function adopted(entry, outcome) {
|
|
150
196
|
if (outcome.kind !== 'accepted')
|
|
151
197
|
return outcome;
|
|
152
198
|
const held = handed.get(entry.locator);
|
|
153
199
|
if (held === undefined)
|
|
154
200
|
return outcome;
|
|
155
|
-
const follows = followsVersion(held
|
|
156
|
-
|
|
201
|
+
const follows = followsVersion(held, outcome.roomVersion);
|
|
202
|
+
if (follows)
|
|
203
|
+
handed.set(entry.locator, outcome.roomVersion);
|
|
157
204
|
const at = logPosition(outcome.roomVersion);
|
|
158
205
|
if (follows && at !== null)
|
|
159
206
|
notifications.reach(entry.authority, at);
|
|
@@ -176,68 +223,61 @@ export function createAgentsHouseAdapter(options) {
|
|
|
176
223
|
return result;
|
|
177
224
|
return { ...result, at: { locator, roomVersion: roomVersion({ position, logEpoch }) } };
|
|
178
225
|
}
|
|
179
|
-
function
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
226
|
+
async function holding(asks) {
|
|
227
|
+
const bound = Math.floor(declared().max_held_files / Math.max(1, asks.filter((ask) => ask.held !== undefined).length));
|
|
228
|
+
const held = [];
|
|
229
|
+
for (const ask of asks) {
|
|
230
|
+
if (ask.held === undefined || bound === 0)
|
|
231
|
+
continue;
|
|
232
|
+
const files = await heldFiles(ask.entry.authority, ask.held, bound);
|
|
233
|
+
if (files !== null)
|
|
234
|
+
held.push(files);
|
|
235
|
+
}
|
|
236
|
+
return held;
|
|
185
237
|
}
|
|
186
238
|
async function bootstrapped(asks, answer) {
|
|
187
239
|
let open = asks.map((asked, ask) => ({ entry: asked.entry, asked, ask }));
|
|
188
240
|
while (open.length > 0) {
|
|
189
241
|
const unreached = [];
|
|
190
|
-
for (const part of selections(open,
|
|
191
|
-
const held = holding(part.map(({ asked }) => asked)
|
|
242
|
+
for (const part of selections(open, declared().max_prefixes)) {
|
|
243
|
+
const held = await holding(part.map(({ asked }) => asked));
|
|
192
244
|
const answered = await transport.door(DOOR_BOOTSTRAP, {
|
|
193
|
-
prefixes: part.
|
|
245
|
+
prefixes: part.map(({ entry }) => authorityRoot(entry.handle)),
|
|
194
246
|
...(held.length === 0 ? {} : { held }),
|
|
195
247
|
});
|
|
196
248
|
const classified = part.map(({ entry }) => classifyDoor(answered.status, answered.body, entry.locator));
|
|
197
|
-
const
|
|
249
|
+
const parted = classified[0] === null ? parseParted(answered.body) : null;
|
|
198
250
|
for (const [index, asked] of part.entries()) {
|
|
199
251
|
const failure = classified[index];
|
|
200
252
|
if (failure !== null && failure !== undefined) {
|
|
201
253
|
answer(asked.ask, failure);
|
|
202
254
|
continue;
|
|
203
255
|
}
|
|
204
|
-
if (
|
|
256
|
+
if (parted === null) {
|
|
205
257
|
answer(asked.ask, UNCERTAIN_READ);
|
|
206
258
|
continue;
|
|
207
259
|
}
|
|
208
|
-
const
|
|
209
|
-
if (
|
|
260
|
+
const room = parted.rooms.find((candidate) => candidate.anchor === asked.entry.authority);
|
|
261
|
+
if (room === undefined && parted.next !== undefined) {
|
|
210
262
|
unreached.push(asked);
|
|
211
263
|
continue;
|
|
212
264
|
}
|
|
213
|
-
|
|
265
|
+
if (room === undefined) {
|
|
266
|
+
answer(asked.ask, { kind: 'room-not-readable', locator: asked.entry.locator });
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const kept = held.find((files) => files.room === asked.entry.authority);
|
|
270
|
+
answer(asked.ask, await manifestPage(asked.asked, {
|
|
271
|
+
room,
|
|
272
|
+
next: 0,
|
|
273
|
+
seen: [],
|
|
274
|
+
...(kept === undefined ? {} : { held: kept }),
|
|
275
|
+
}));
|
|
214
276
|
}
|
|
215
277
|
}
|
|
216
278
|
open = unreached;
|
|
217
279
|
}
|
|
218
280
|
}
|
|
219
|
-
async function continuedBootstrap(asked, continued) {
|
|
220
|
-
const { entry } = asked;
|
|
221
|
-
const after = {
|
|
222
|
-
room: entry.authority,
|
|
223
|
-
path: continued.after,
|
|
224
|
-
...(continued.cut === undefined ? {} : { cut: continued.cut }),
|
|
225
|
-
};
|
|
226
|
-
const held = holding([asked], continued.after);
|
|
227
|
-
const answered = await transport.door(DOOR_BOOTSTRAP, {
|
|
228
|
-
prefixes: contentPrefixes(entry),
|
|
229
|
-
after,
|
|
230
|
-
...(held.length === 0 ? {} : { held }),
|
|
231
|
-
});
|
|
232
|
-
const failure = classifyRead(answered.status, answered.body, entry.locator);
|
|
233
|
-
if (failure !== null)
|
|
234
|
-
return failure;
|
|
235
|
-
const envelope = parseEnvelope(answered.body);
|
|
236
|
-
if (envelope === null)
|
|
237
|
-
return UNCERTAIN_READ;
|
|
238
|
-
const scope = envelope.scopes.find((candidate) => matchesScope(candidate, entry));
|
|
239
|
-
return bootstrappedRoom(envelope, scope, asked, continued);
|
|
240
|
-
}
|
|
241
281
|
function layered(asks) {
|
|
242
282
|
const depths = new Map();
|
|
243
283
|
const layers = [];
|
|
@@ -250,12 +290,12 @@ export function createAgentsHouseAdapter(options) {
|
|
|
250
290
|
}
|
|
251
291
|
async function enumerated(asks) {
|
|
252
292
|
const answers = [];
|
|
253
|
-
const parts = layered(asks.map((ask, index) => ({ ask, index }))).flatMap((layer) => selections(layer,
|
|
293
|
+
const parts = layered(asks.map((ask, index) => ({ ask, index }))).flatMap((layer) => selections(layer, declared().max_prefixes));
|
|
254
294
|
for (const part of parts) {
|
|
255
295
|
let open = [...part];
|
|
256
296
|
while (open.length > 0) {
|
|
257
297
|
const answer = await transport.door(DOOR_ENUMERATE, {
|
|
258
|
-
prefixes: open.
|
|
298
|
+
prefixes: open.map(({ ask }) => authorityRoot(ask.entry.handle)),
|
|
259
299
|
positions: open.map(({ ask }) => presented(ask.entry.authority, ask.from)),
|
|
260
300
|
});
|
|
261
301
|
const classified = open.map(({ ask }) => classifyRead(answer.status, answer.body, ask.entry.locator));
|
|
@@ -294,10 +334,12 @@ export function createAgentsHouseAdapter(options) {
|
|
|
294
334
|
}
|
|
295
335
|
const minted = await transport.door(DOOR_BATCH_UPLOAD, { ...head, paths, bytes, sha256 });
|
|
296
336
|
if (minted.status !== 200) {
|
|
297
|
-
return {
|
|
337
|
+
return {
|
|
338
|
+
outcome: await stepped(mutationOutcome(minted.status, minted.body, entry.locator, entry.handle)),
|
|
339
|
+
};
|
|
298
340
|
}
|
|
299
341
|
const grant = parseGrant(minted.body);
|
|
300
|
-
if (grant === null
|
|
342
|
+
if (grant === null)
|
|
301
343
|
return { outcome: UNCERTAIN };
|
|
302
344
|
const delivered = await transport.transfer({
|
|
303
345
|
act: 'authored_batch_upload',
|
|
@@ -307,36 +349,31 @@ export function createAgentsHouseAdapter(options) {
|
|
|
307
349
|
if (delivered.status !== 200)
|
|
308
350
|
return { outcome: UNCERTAIN };
|
|
309
351
|
const holding = parseGrant(delivered.body);
|
|
310
|
-
if (holding === null
|
|
352
|
+
if (holding === null)
|
|
311
353
|
return { outcome: UNCERTAIN };
|
|
312
354
|
const upload = { url: holding.url, operation: holding.operation, bytes, sha256 };
|
|
313
355
|
await keep(upload);
|
|
314
356
|
return { body: { ...head, paths, upload, runtime: notifications.runtime } };
|
|
315
357
|
}
|
|
316
|
-
async function staged(answer, batch) {
|
|
358
|
+
async function staged(answer, { changeBatch: batch, file }) {
|
|
317
359
|
const refusal = doorRefusal(answer.body);
|
|
318
360
|
if (refusal?.code !== 'files_unstaged')
|
|
319
361
|
return null;
|
|
320
|
-
const
|
|
321
|
-
if (!Array.isArray(
|
|
362
|
+
const uploads = refusal.fields.upload;
|
|
363
|
+
if (!Array.isArray(uploads))
|
|
322
364
|
return false;
|
|
323
|
-
for (const
|
|
324
|
-
const
|
|
325
|
-
const change = batch.changes.find((held) => held.kind === 'binary' && held.sha256 === sha256);
|
|
326
|
-
if (
|
|
365
|
+
for (const named of uploads) {
|
|
366
|
+
const upload = houseUpload(named);
|
|
367
|
+
const change = batch.changes.find((held) => held.kind === 'binary' && held.sha256 === named.sha256);
|
|
368
|
+
if (upload === null || change === undefined)
|
|
327
369
|
return false;
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
url,
|
|
331
|
-
body: change.blob,
|
|
332
|
-
operation,
|
|
333
|
-
});
|
|
334
|
-
if (delivered.status !== 200)
|
|
370
|
+
const finished = await finishedUpload(transport, upload, await file(change.localId));
|
|
371
|
+
if (finished?.body?.staged !== true)
|
|
335
372
|
return false;
|
|
336
373
|
}
|
|
337
374
|
return true;
|
|
338
375
|
}
|
|
339
|
-
async function submit(
|
|
376
|
+
async function submit(request, head, changes, delta, bytes, entry, handed, keep, into) {
|
|
340
377
|
const inline = { ...head, changes, runtime: notifications.runtime };
|
|
341
378
|
const prepared = uploadable(inline, bytes, declared())
|
|
342
379
|
? await uploaded(head, changes, delta, bytes, entry, handed, keep)
|
|
@@ -344,15 +381,20 @@ export function createAgentsHouseAdapter(options) {
|
|
|
344
381
|
if ('outcome' in prepared)
|
|
345
382
|
return prepared.outcome;
|
|
346
383
|
const answer = await transport.door(DOOR_BATCH, prepared.body);
|
|
347
|
-
const stagedFiles = await staged(answer,
|
|
384
|
+
const stagedFiles = await staged(answer, request);
|
|
348
385
|
if (stagedFiles === false)
|
|
349
386
|
return UNCERTAIN;
|
|
350
387
|
const settled = stagedFiles === null ? answer : await transport.door(DOOR_BATCH, prepared.body);
|
|
351
|
-
if (stagedFiles === true && (await staged(settled,
|
|
388
|
+
if (stagedFiles === true && (await staged(settled, request)) !== null)
|
|
352
389
|
return UNCERTAIN;
|
|
353
|
-
return mutationOutcome(settled.status, settled.body, entry.locator, entry.handle
|
|
390
|
+
return stepped(mutationOutcome(settled.status, settled.body, entry.locator, entry.handle, into === undefined
|
|
391
|
+
? undefined
|
|
392
|
+
: {
|
|
393
|
+
source: { authority: entry.authority, handle: entry.handle },
|
|
394
|
+
destination: { authority: into.authority, handle: into.handle },
|
|
395
|
+
}));
|
|
354
396
|
}
|
|
355
|
-
function
|
|
397
|
+
function addressed(answer, locator) {
|
|
356
398
|
const failure = classifyDoor(answer.status, answer.body, locator);
|
|
357
399
|
if (failure !== null) {
|
|
358
400
|
return failure.kind === 'scoped-refusal'
|
|
@@ -364,33 +406,48 @@ export function createAgentsHouseAdapter(options) {
|
|
|
364
406
|
}
|
|
365
407
|
: failure;
|
|
366
408
|
}
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return
|
|
409
|
+
const address = parseFileAddress(answer.body);
|
|
410
|
+
return address === null ? UNCERTAIN_READ : { kind: 'address', ...address };
|
|
411
|
+
}
|
|
412
|
+
function linked(answer, locator) {
|
|
413
|
+
const address = addressed(answer, locator);
|
|
414
|
+
return address.kind === 'address'
|
|
415
|
+
? { kind: 'link', url: address.url, name: address.name }
|
|
416
|
+
: address;
|
|
373
417
|
}
|
|
374
|
-
async function downloaded(
|
|
375
|
-
|
|
376
|
-
if (
|
|
377
|
-
return
|
|
378
|
-
|
|
379
|
-
if (read.status
|
|
418
|
+
async function downloaded(ask, locator) {
|
|
419
|
+
let address = addressed(await ask(), locator);
|
|
420
|
+
if (address.kind !== 'address')
|
|
421
|
+
return address;
|
|
422
|
+
let read = await transport.download(address.url);
|
|
423
|
+
if (read.status === EXPIRED_ADDRESS) {
|
|
424
|
+
address = addressed(await ask(), locator);
|
|
425
|
+
if (address.kind !== 'address')
|
|
426
|
+
return address;
|
|
427
|
+
read = await transport.download(address.url);
|
|
428
|
+
}
|
|
429
|
+
if (read.status !== 200 || read.body === null)
|
|
380
430
|
return UNCERTAIN_READ;
|
|
381
|
-
return {
|
|
431
|
+
return {
|
|
432
|
+
kind: 'binary',
|
|
433
|
+
body: read.body,
|
|
434
|
+
mediaType: address.mediaType,
|
|
435
|
+
sha256: address.sha256,
|
|
436
|
+
};
|
|
382
437
|
}
|
|
383
|
-
function
|
|
438
|
+
function pathAddress(request) {
|
|
384
439
|
const entry = authorityFor(request.locator);
|
|
385
440
|
if (entry === undefined)
|
|
386
441
|
return null;
|
|
387
|
-
return transport.door(DOOR_FILES_GET, {
|
|
442
|
+
return () => transport.door(DOOR_FILES_GET, {
|
|
388
443
|
room_ref: entry.authority,
|
|
389
444
|
path: request.path,
|
|
390
445
|
revision: request.revision,
|
|
391
446
|
});
|
|
392
447
|
}
|
|
393
448
|
return {
|
|
449
|
+
roomTypes: HOUSE_ROOM_TYPES,
|
|
450
|
+
nameableRoomTypes: HOUSE_NAMEABLE_ROOM_TYPES,
|
|
394
451
|
async authorize() {
|
|
395
452
|
return options.authorize();
|
|
396
453
|
},
|
|
@@ -440,7 +497,7 @@ export function createAgentsHouseAdapter(options) {
|
|
|
440
497
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
441
498
|
const asked = { entry, held: request.held };
|
|
442
499
|
if (request.pageToken !== undefined) {
|
|
443
|
-
return
|
|
500
|
+
return partPage(asked, JSON.parse(request.pageToken), request.received, request.arriving);
|
|
444
501
|
}
|
|
445
502
|
return bootstrapTogether(asked);
|
|
446
503
|
},
|
|
@@ -462,18 +519,27 @@ export function createAgentsHouseAdapter(options) {
|
|
|
462
519
|
const entry = authorityFor(request.locator);
|
|
463
520
|
if (entry === undefined)
|
|
464
521
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
465
|
-
const
|
|
522
|
+
const batch = request.changeBatch;
|
|
523
|
+
const destination = batch.between?.destination.room;
|
|
524
|
+
const into = destination === undefined ? undefined : authorityFor(destination);
|
|
525
|
+
if (destination !== undefined && into === undefined) {
|
|
526
|
+
return { kind: 'room-not-readable', locator: destination };
|
|
527
|
+
}
|
|
528
|
+
const mapped = into === undefined
|
|
529
|
+
? houseChanges(batch, entry.handle)
|
|
530
|
+
: houseMove(batch, entry.handle, into.handle);
|
|
466
531
|
if (mapped.kind === 'unmapped')
|
|
467
532
|
return rejectedMapping(mapped);
|
|
468
|
-
const head = operationHead(
|
|
533
|
+
const head = operationHead(batch);
|
|
469
534
|
const delta = deltaBody(mapped.changes);
|
|
470
535
|
const bytes = deltaBytes(delta);
|
|
471
536
|
const handed = request.upload;
|
|
472
|
-
const
|
|
473
|
-
const
|
|
537
|
+
const answer = (upload) => submit(request, head, mapped.changes, delta, bytes, entry, upload, keep, into);
|
|
538
|
+
const settle = (outcome) => into === undefined ? adopted(entry, outcome) : adoptedMove(entry, into, outcome);
|
|
539
|
+
const outcome = await answer(handed);
|
|
474
540
|
if (handed === undefined || !lapsedGrant(outcome))
|
|
475
|
-
return
|
|
476
|
-
return
|
|
541
|
+
return settle(outcome);
|
|
542
|
+
return settle(await answer(undefined));
|
|
477
543
|
},
|
|
478
544
|
async history(_authorization, request) {
|
|
479
545
|
const entry = authorityFor(request.locator);
|
|
@@ -491,36 +557,16 @@ export function createAgentsHouseAdapter(options) {
|
|
|
491
557
|
});
|
|
492
558
|
},
|
|
493
559
|
async binary(_authorization, request) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
return downloaded(await asked, request.locator);
|
|
499
|
-
}
|
|
500
|
-
const referrer = houseReferrer(request.referrer, tracked);
|
|
501
|
-
if (referrer === null) {
|
|
502
|
-
return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
|
|
503
|
-
}
|
|
504
|
-
const answer = await transport.door(DOOR_FILES_GET, {
|
|
505
|
-
file: request.fileRef,
|
|
506
|
-
referrer: referrer.referrer,
|
|
507
|
-
});
|
|
508
|
-
return downloaded(answer, referrer.locator);
|
|
560
|
+
const ask = pathAddress(request);
|
|
561
|
+
if (ask === null)
|
|
562
|
+
return { kind: 'room-not-readable', locator: request.locator };
|
|
563
|
+
return downloaded(ask, request.locator);
|
|
509
564
|
},
|
|
510
565
|
async link(_authorization, request) {
|
|
511
|
-
const
|
|
512
|
-
if (
|
|
566
|
+
const ask = pathAddress(request);
|
|
567
|
+
if (ask === null)
|
|
513
568
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
514
|
-
return
|
|
515
|
-
},
|
|
516
|
-
referrerScope(referrer) {
|
|
517
|
-
const held = houseReferrer(referrer, tracked);
|
|
518
|
-
if (held === null)
|
|
519
|
-
return null;
|
|
520
|
-
if (held.locator === '')
|
|
521
|
-
return { kind: 'conversations' };
|
|
522
|
-
const { path } = held.referrer;
|
|
523
|
-
return { kind: 'room', locator: held.locator, ...(path === undefined ? {} : { path }) };
|
|
569
|
+
return linked(await ask(), request.locator);
|
|
524
570
|
},
|
|
525
571
|
reached(locator, version, target) {
|
|
526
572
|
return reachedVersion(version, target, authorityFor(locator)?.logEpoch);
|
|
@@ -534,7 +580,10 @@ export function createAgentsHouseAdapter(options) {
|
|
|
534
580
|
roomStream: {
|
|
535
581
|
hold: held,
|
|
536
582
|
reopen: notifications.reopen,
|
|
537
|
-
observe
|
|
583
|
+
observe(notify, receipts, revisions) {
|
|
584
|
+
heldRevisions = revisions;
|
|
585
|
+
return notifications.observe(notify, receipts);
|
|
586
|
+
},
|
|
538
587
|
published(locator, roomVersion) {
|
|
539
588
|
const at = logPosition(roomVersion);
|
|
540
589
|
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"}
|