@agentshouse/mdruntime-adapter 0.1.0-cd59fd8945dcb → 0.1.0-cdfc733e397ee
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/AGENTS.md +138 -129
- package/dist/actions.d.ts +23 -0
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +65 -31
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +203 -44
- package/dist/discovery.d.ts +1 -0
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +6 -2
- package/dist/handed.d.ts +15 -0
- package/dist/handed.d.ts.map +1 -0
- package/dist/handed.js +38 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/model.d.ts +0 -1
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +0 -3
- package/dist/read.d.ts +26 -6
- package/dist/read.d.ts.map +1 -1
- package/dist/read.js +140 -52
- package/dist/referrer.d.ts +7 -0
- package/dist/referrer.d.ts.map +1 -0
- package/dist/referrer.js +35 -0
- package/dist/refusal.d.ts.map +1 -1
- package/dist/refusal.js +2 -1
- package/dist/site.d.ts.map +1 -1
- package/dist/site.js +136 -33
- package/dist/stream.d.ts +3 -2
- package/dist/stream.d.ts.map +1 -1
- package/dist/stream.js +299 -13
- package/dist/transport.d.ts +42 -5
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +3 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/write.d.ts +2 -9
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +54 -5
- package/package.json +2 -3
- package/dist/links.d.ts +0 -20
- package/dist/links.d.ts.map +0 -1
- package/dist/links.js +0 -104
package/dist/read.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readPosition, roomVersion } from './version.js';
|
|
1
|
+
import { DECIMAL, readPosition, roomVersion } from './version.js';
|
|
2
2
|
export function authorityRoot(handle) {
|
|
3
3
|
return `/rooms/${handle}`;
|
|
4
4
|
}
|
|
@@ -51,8 +51,19 @@ export function headChange(held) {
|
|
|
51
51
|
function headed(head) {
|
|
52
52
|
return head === undefined ? {} : { head };
|
|
53
53
|
}
|
|
54
|
-
function
|
|
55
|
-
|
|
54
|
+
export function binaryFileOf(held) {
|
|
55
|
+
if (held.file === undefined)
|
|
56
|
+
return undefined;
|
|
57
|
+
const { file, bytes, media_type: mediaType, sha256 } = held;
|
|
58
|
+
if (typeof file !== 'string' ||
|
|
59
|
+
typeof bytes !== 'number' ||
|
|
60
|
+
typeof mediaType !== 'string' ||
|
|
61
|
+
typeof sha256 !== 'string')
|
|
62
|
+
return null;
|
|
63
|
+
return { fileRef: file, byteLength: bytes, mediaType, sha256 };
|
|
64
|
+
}
|
|
65
|
+
function binaried(binary) {
|
|
66
|
+
return binary === undefined ? {} : { binary };
|
|
56
67
|
}
|
|
57
68
|
function parseFile(value, mode) {
|
|
58
69
|
if (typeof value !== 'object' || value === null)
|
|
@@ -61,16 +72,30 @@ function parseFile(value, mode) {
|
|
|
61
72
|
if (typeof file.path !== 'string')
|
|
62
73
|
return null;
|
|
63
74
|
const head = headChange(file);
|
|
64
|
-
|
|
75
|
+
const binary = binaryFileOf(file);
|
|
76
|
+
if (head === null || binary === null)
|
|
65
77
|
return null;
|
|
66
78
|
if (mode === 'site') {
|
|
67
79
|
if (typeof file.sha256 !== 'string')
|
|
68
80
|
return null;
|
|
69
|
-
return {
|
|
81
|
+
return {
|
|
82
|
+
path: file.path,
|
|
83
|
+
revision: binary?.sha256,
|
|
84
|
+
version: file.sha256,
|
|
85
|
+
...headed(head),
|
|
86
|
+
...binaried(binary),
|
|
87
|
+
};
|
|
70
88
|
}
|
|
71
89
|
if (typeof file.revision !== 'string')
|
|
72
90
|
return null;
|
|
73
|
-
return {
|
|
91
|
+
return {
|
|
92
|
+
path: file.path,
|
|
93
|
+
revision: file.revision,
|
|
94
|
+
version: file.revision,
|
|
95
|
+
...(typeof file.sha256 === 'string' ? { sha256: file.sha256 } : {}),
|
|
96
|
+
...headed(head),
|
|
97
|
+
...binaried(binary),
|
|
98
|
+
};
|
|
74
99
|
}
|
|
75
100
|
function parseScope(value, mode) {
|
|
76
101
|
if (typeof value !== 'object' || value === null)
|
|
@@ -106,17 +131,28 @@ function parseScope(value, mode) {
|
|
|
106
131
|
return null;
|
|
107
132
|
contents.push({ path: content.path, content: content.content });
|
|
108
133
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
134
|
+
return { anchor: manifest.anchor, ...at, files, contents };
|
|
135
|
+
}
|
|
136
|
+
function parseCut(value) {
|
|
137
|
+
if (value === undefined)
|
|
138
|
+
return undefined;
|
|
139
|
+
if (typeof value !== 'object' || value === null)
|
|
140
|
+
return null;
|
|
141
|
+
const { position, log_epoch: logEpoch } = value;
|
|
142
|
+
if (typeof position !== 'string' || typeof logEpoch !== 'string')
|
|
143
|
+
return null;
|
|
144
|
+
return { position, log_epoch: logEpoch };
|
|
112
145
|
}
|
|
113
146
|
function parseCursor(value) {
|
|
114
147
|
if (typeof value !== 'object' || value === null)
|
|
115
148
|
return null;
|
|
116
|
-
const { room, path } = value;
|
|
149
|
+
const { room, path, cut } = value;
|
|
117
150
|
if (typeof room !== 'string' || (path !== null && typeof path !== 'string'))
|
|
118
151
|
return null;
|
|
119
|
-
|
|
152
|
+
const parsed = parseCut(cut);
|
|
153
|
+
if (parsed === null)
|
|
154
|
+
return null;
|
|
155
|
+
return { room, path, ...(parsed === undefined ? {} : { cut: parsed }) };
|
|
120
156
|
}
|
|
121
157
|
export function parseEnvelope(body) {
|
|
122
158
|
if (typeof body !== 'object' || body === null)
|
|
@@ -138,6 +174,18 @@ export function parseEnvelope(body) {
|
|
|
138
174
|
export function parseSiteBootstrap(body) {
|
|
139
175
|
return parseScope(body, 'site');
|
|
140
176
|
}
|
|
177
|
+
export function siteBootstrapNext(body) {
|
|
178
|
+
if (typeof body !== 'object' || body === null || !('next' in body))
|
|
179
|
+
return null;
|
|
180
|
+
return typeof body.next === 'string' && body.next.length > 0 ? body.next : null;
|
|
181
|
+
}
|
|
182
|
+
export function siteBootstrapOffset(body) {
|
|
183
|
+
if (typeof body !== 'object' || body === null || !('offset' in body))
|
|
184
|
+
return null;
|
|
185
|
+
return Number.isSafeInteger(body.offset) && body.offset > 0
|
|
186
|
+
? body.offset
|
|
187
|
+
: null;
|
|
188
|
+
}
|
|
141
189
|
function parseChange(value, mode) {
|
|
142
190
|
if (typeof value !== 'object' || value === null)
|
|
143
191
|
return null;
|
|
@@ -147,8 +195,15 @@ function parseChange(value, mode) {
|
|
|
147
195
|
if (held.removed === true)
|
|
148
196
|
return { path: held.path, removed: true };
|
|
149
197
|
const head = headChange(held);
|
|
150
|
-
|
|
198
|
+
const binary = binaryFileOf(held);
|
|
199
|
+
if (head === null || binary === null)
|
|
151
200
|
return null;
|
|
201
|
+
if (binary !== undefined) {
|
|
202
|
+
if (mode === 'credential' && typeof held.revision !== 'string')
|
|
203
|
+
return null;
|
|
204
|
+
const revision = typeof held.revision === 'string' ? held.revision : binary.sha256;
|
|
205
|
+
return { path: held.path, binary, revision, version: revision, ...headed(head) };
|
|
206
|
+
}
|
|
152
207
|
if (mode === 'site') {
|
|
153
208
|
if (typeof held.content !== 'string' || typeof held.sha256 !== 'string')
|
|
154
209
|
return null;
|
|
@@ -169,12 +224,6 @@ function parseChange(value, mode) {
|
|
|
169
224
|
...headed(head),
|
|
170
225
|
};
|
|
171
226
|
}
|
|
172
|
-
if (typeof held.reference === 'object' && held.reference !== null) {
|
|
173
|
-
const reference = held.reference;
|
|
174
|
-
if (typeof reference.revision !== 'string')
|
|
175
|
-
return null;
|
|
176
|
-
return { path: held.path, reference: { revision: reference.revision } };
|
|
177
|
-
}
|
|
178
227
|
return null;
|
|
179
228
|
}
|
|
180
229
|
export function parseEnumeration(body, mode) {
|
|
@@ -199,14 +248,60 @@ export function parseEnumeration(body, mode) {
|
|
|
199
248
|
return null;
|
|
200
249
|
changes.push(mapped);
|
|
201
250
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
251
|
+
const next = held.next === undefined ? undefined : readPage(held.next);
|
|
252
|
+
if (next === null)
|
|
253
|
+
return null;
|
|
254
|
+
authorities.push({
|
|
255
|
+
authority: held.authority,
|
|
256
|
+
...at,
|
|
257
|
+
changes,
|
|
258
|
+
...(next === undefined ? {} : { next }),
|
|
259
|
+
});
|
|
207
260
|
}
|
|
208
261
|
return { authorities };
|
|
209
262
|
}
|
|
263
|
+
function readPage(held) {
|
|
264
|
+
if (typeof held !== 'object' || held === null)
|
|
265
|
+
return null;
|
|
266
|
+
const { after, through, read } = held;
|
|
267
|
+
if (typeof after !== 'string' || !DECIMAL.test(after))
|
|
268
|
+
return null;
|
|
269
|
+
if (typeof through !== 'string' || !DECIMAL.test(through))
|
|
270
|
+
return null;
|
|
271
|
+
if (typeof read !== 'number' || !Number.isSafeInteger(read) || read < 0)
|
|
272
|
+
return null;
|
|
273
|
+
return { after, through, read };
|
|
274
|
+
}
|
|
275
|
+
function advances(asked, next) {
|
|
276
|
+
const moved = BigInt(next.through) - BigInt(asked.through);
|
|
277
|
+
return moved > 0n || (moved === 0n && next.after === asked.after && next.read > asked.read);
|
|
278
|
+
}
|
|
279
|
+
export async function wholeView(first, more) {
|
|
280
|
+
const changes = new Map(first.changes.map((change) => [change.path, change]));
|
|
281
|
+
let view = first;
|
|
282
|
+
while (view.next !== undefined) {
|
|
283
|
+
const asked = view.next;
|
|
284
|
+
const page = await more(asked);
|
|
285
|
+
if ('kind' in page)
|
|
286
|
+
return page;
|
|
287
|
+
if (page.position !== asked.through ||
|
|
288
|
+
page.logEpoch !== first.logEpoch ||
|
|
289
|
+
(page.next !== undefined && !advances(asked, page.next))) {
|
|
290
|
+
return { kind: 'transport-uncertainty' };
|
|
291
|
+
}
|
|
292
|
+
for (const change of page.changes) {
|
|
293
|
+
changes.delete(change.path);
|
|
294
|
+
changes.set(change.path, change);
|
|
295
|
+
}
|
|
296
|
+
view = page;
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
authority: first.authority,
|
|
300
|
+
position: view.position,
|
|
301
|
+
logEpoch: first.logEpoch,
|
|
302
|
+
changes: [...changes.values()],
|
|
303
|
+
};
|
|
304
|
+
}
|
|
210
305
|
export function advancedScope(scope, view) {
|
|
211
306
|
const files = new Map(scope.files.map((file) => [file.path, file]));
|
|
212
307
|
const contents = new Map(scope.contents.map((entry) => [entry.path, entry.content]));
|
|
@@ -215,18 +310,15 @@ export function advancedScope(scope, view) {
|
|
|
215
310
|
contents.delete(change.path);
|
|
216
311
|
if ('removed' in change)
|
|
217
312
|
continue;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
313
|
+
files.set(change.path, {
|
|
314
|
+
path: change.path,
|
|
315
|
+
revision: change.revision,
|
|
316
|
+
version: change.version,
|
|
317
|
+
...headed(change.head),
|
|
318
|
+
...('binary' in change ? { binary: change.binary } : {}),
|
|
319
|
+
});
|
|
320
|
+
if ('content' in change)
|
|
225
321
|
contents.set(change.path, change.content);
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
const { revision } = change.reference;
|
|
229
|
-
files.set(change.path, { path: change.path, revision, version: revision });
|
|
230
322
|
}
|
|
231
323
|
return {
|
|
232
324
|
...scope,
|
|
@@ -244,16 +336,16 @@ export function bootstrapOf(scope) {
|
|
|
244
336
|
const documents = {};
|
|
245
337
|
const revisions = {};
|
|
246
338
|
const changes = {};
|
|
247
|
-
const
|
|
339
|
+
const binaryFiles = {};
|
|
248
340
|
for (const file of scope.files) {
|
|
249
341
|
if (file.revision !== undefined)
|
|
250
342
|
revisions[file.path] = file.revision;
|
|
251
343
|
if (file.head !== undefined)
|
|
252
344
|
changes[file.path] = file.head;
|
|
253
345
|
const content = contents.get(file.path);
|
|
254
|
-
if (
|
|
255
|
-
|
|
256
|
-
else
|
|
346
|
+
if (file.binary !== undefined)
|
|
347
|
+
binaryFiles[file.path] = file.binary;
|
|
348
|
+
else if (content !== undefined)
|
|
257
349
|
documents[file.path] = content;
|
|
258
350
|
}
|
|
259
351
|
return {
|
|
@@ -262,8 +354,7 @@ export function bootstrapOf(scope) {
|
|
|
262
354
|
documents,
|
|
263
355
|
revisions,
|
|
264
356
|
changes,
|
|
265
|
-
|
|
266
|
-
...declared(scope.attachments),
|
|
357
|
+
binaryFiles,
|
|
267
358
|
};
|
|
268
359
|
}
|
|
269
360
|
export function schemaOf(scope, schema) {
|
|
@@ -284,23 +375,21 @@ export function refreshFrom(view, fromRoomVersion) {
|
|
|
284
375
|
const documents = {};
|
|
285
376
|
const revisions = {};
|
|
286
377
|
const changes = {};
|
|
287
|
-
const
|
|
378
|
+
const binaryFiles = {};
|
|
288
379
|
const removals = [];
|
|
289
380
|
for (const change of view.changes) {
|
|
290
381
|
if ('removed' in change) {
|
|
291
382
|
removals.push(change.path);
|
|
292
383
|
continue;
|
|
293
384
|
}
|
|
294
|
-
if ('content' in change)
|
|
385
|
+
if ('content' in change)
|
|
295
386
|
documents[change.path] = change.content;
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
binaryTargets.push(change.path);
|
|
303
|
-
revisions[change.path] = change.reference.revision;
|
|
387
|
+
else
|
|
388
|
+
binaryFiles[change.path] = change.binary;
|
|
389
|
+
if (change.revision !== undefined)
|
|
390
|
+
revisions[change.path] = change.revision;
|
|
391
|
+
if (change.head !== undefined)
|
|
392
|
+
changes[change.path] = change.head;
|
|
304
393
|
}
|
|
305
394
|
return {
|
|
306
395
|
kind: 'net-advancement',
|
|
@@ -308,8 +397,7 @@ export function refreshFrom(view, fromRoomVersion) {
|
|
|
308
397
|
documents,
|
|
309
398
|
revisions,
|
|
310
399
|
changes,
|
|
311
|
-
|
|
400
|
+
binaryFiles,
|
|
312
401
|
removals: removals.sort(),
|
|
313
|
-
...declared(view.attachments),
|
|
314
402
|
};
|
|
315
403
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TrackedAuthority } from './discovery.js';
|
|
2
|
+
export type HouseReferrer = {
|
|
3
|
+
locator: string;
|
|
4
|
+
referrer: Readonly<Record<string, string>>;
|
|
5
|
+
};
|
|
6
|
+
export declare function houseReferrer(referrer: unknown, tracked: ReadonlyMap<string, TrackedAuthority>): HouseReferrer | null;
|
|
7
|
+
//# sourceMappingURL=referrer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referrer.d.ts","sourceRoot":"","sources":["../src/referrer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC;AAgB5F,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAC7C,aAAa,GAAG,IAAI,CAqBtB"}
|
package/dist/referrer.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function fields(value) {
|
|
2
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
3
|
+
? value
|
|
4
|
+
: null;
|
|
5
|
+
}
|
|
6
|
+
function named(held, ...keys) {
|
|
7
|
+
const present = Object.keys(held);
|
|
8
|
+
return (present.length === keys.length &&
|
|
9
|
+
keys.every((key) => typeof held[key] === 'string' && held[key] !== ''));
|
|
10
|
+
}
|
|
11
|
+
export function houseReferrer(referrer, tracked) {
|
|
12
|
+
const held = fields(referrer);
|
|
13
|
+
if (held === null)
|
|
14
|
+
return null;
|
|
15
|
+
if (named(held, 'room', 'path')) {
|
|
16
|
+
const entry = tracked.get(held.room);
|
|
17
|
+
if (entry === undefined)
|
|
18
|
+
return null;
|
|
19
|
+
return {
|
|
20
|
+
locator: entry.locator,
|
|
21
|
+
referrer: { room_ref: entry.authority, path: held.path },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (named(held, 'room_ref', 'record')) {
|
|
25
|
+
const roomRef = held.room_ref;
|
|
26
|
+
const entry = [...tracked.values()].find((candidate) => candidate.authority === roomRef);
|
|
27
|
+
return {
|
|
28
|
+
locator: entry?.locator ?? roomRef,
|
|
29
|
+
referrer: { room_ref: roomRef, record: held.record },
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
if (named(held, 'message'))
|
|
33
|
+
return { locator: '', referrer: { message: held.message } };
|
|
34
|
+
return null;
|
|
35
|
+
}
|
package/dist/refusal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refusal.d.ts","sourceRoot":"","sources":["../src/refusal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,aAAa,EACd,MAAM,wBAAwB,CAAC;AAEhC,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAOjE;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAC7B,OAAO,EAAE,eAAe,GACvB,aAAa,CAEf;
|
|
1
|
+
{"version":3,"file":"refusal.d.ts","sourceRoot":"","sources":["../src/refusal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,eAAe,EACf,aAAa,EACd,MAAM,wBAAwB,CAAC;AAEhC,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAOjE;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAC7B,OAAO,EAAE,eAAe,GACvB,aAAa,CAEf;AAqBD,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,GACd,cAAc,GAAG,IAAI,CAMvB;AAED,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,GACd,cAAc,GAAG;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAAG,IAAI,CAGpD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,cAAc,GAAG,IAAI,CAQrF"}
|
package/dist/refusal.js
CHANGED
|
@@ -18,8 +18,9 @@ function doorFailure(status, body) {
|
|
|
18
18
|
const refusal = doorRefusal(body);
|
|
19
19
|
if (status === 401)
|
|
20
20
|
return { kind: 'revoked-authorization' };
|
|
21
|
-
if (refusal?.retryable === true)
|
|
21
|
+
if (refusal?.retryable === true || refusal?.code === 'update_required') {
|
|
22
22
|
return { kind: 'transport-uncertainty' };
|
|
23
|
+
}
|
|
23
24
|
if (status === 404 || refusal?.code === 'room_not_found')
|
|
24
25
|
return { kind: 'room-not-readable' };
|
|
25
26
|
if (status < 400)
|
package/dist/site.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,
|
|
1
|
+
{"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAOR,MAAM,wBAAwB,CAAC;AA2BhC,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAC;AAmCxB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,kBAAkB,GAAG,OAAO,CAuQxE"}
|
package/dist/site.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { actionOutcome } from './actions.js';
|
|
1
|
+
import { actionOutcome, SITE_SUBMIT } from './actions.js';
|
|
2
2
|
import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteTracked, } from './discovery.js';
|
|
3
|
-
import {
|
|
4
|
-
import { advancedScope, bootstrapOf, parseEnumeration, parseSiteBootstrap, refreshFrom, viewOf, } from './read.js';
|
|
3
|
+
import { partModels, streamedModels, viewModels } from './model.js';
|
|
4
|
+
import { advancedScope, bootstrapOf, parseEnumeration, parseSiteBootstrap, refreshFrom, siteBootstrapNext, siteBootstrapOffset, viewOf, wholeView, } from './read.js';
|
|
5
|
+
import { sha256Hex } from './digest.js';
|
|
5
6
|
import { classifyDoor, classifyRead, discoveryFailure } from './refusal.js';
|
|
6
7
|
import { houseNotifications } from './stream.js';
|
|
7
|
-
import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT, } from './transport.js';
|
|
8
|
+
import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT, SITE_FILE_RECORD, SITE_FILES, } from './transport.js';
|
|
9
|
+
import { houseReferrer } from './referrer.js';
|
|
8
10
|
import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
|
|
9
11
|
const UNCERTAIN = { kind: 'transport-uncertainty' };
|
|
10
12
|
function siteRoom(tracked) {
|
|
@@ -24,32 +26,94 @@ function settled(refused) {
|
|
|
24
26
|
export function createSiteAdapter(transport) {
|
|
25
27
|
const notifications = houseNotifications(transport, 'site');
|
|
26
28
|
const tracked = new Map();
|
|
27
|
-
|
|
29
|
+
function published(referrer) {
|
|
30
|
+
const named = houseReferrer(referrer, tracked);
|
|
31
|
+
return named === null || !tracked.has(named.locator) ? null : named;
|
|
32
|
+
}
|
|
33
|
+
async function enumerated(entry, from, page) {
|
|
28
34
|
const answer = await transport.door(SITE_DOOR_ENUMERATE, {
|
|
29
|
-
positions: [
|
|
35
|
+
positions: [
|
|
36
|
+
page === undefined
|
|
37
|
+
? presented(entry.authority, from)
|
|
38
|
+
: {
|
|
39
|
+
...presented(entry.authority, { position: page.after, logEpoch: from.logEpoch }),
|
|
40
|
+
page: { through: page.through, read: page.read },
|
|
41
|
+
},
|
|
42
|
+
],
|
|
30
43
|
});
|
|
31
44
|
const classified = classifyRead(answer.status, answer.body, entry.locator);
|
|
32
45
|
if (classified !== null)
|
|
33
46
|
return classified;
|
|
34
|
-
|
|
47
|
+
const found = parseEnumeration(answer.body, 'site');
|
|
48
|
+
if (found === null)
|
|
49
|
+
return UNCERTAIN;
|
|
50
|
+
return viewOf(found, entry) ?? { kind: 'room-not-readable', locator: entry.locator };
|
|
51
|
+
}
|
|
52
|
+
async function enumeration(entry, from) {
|
|
53
|
+
const first = await enumerated(entry, from);
|
|
54
|
+
return 'kind' in first ? first : wholeView(first, (page) => enumerated(entry, from, page));
|
|
35
55
|
}
|
|
36
|
-
async function
|
|
37
|
-
const
|
|
56
|
+
async function bootstrapPart(entry, after, offset) {
|
|
57
|
+
const query = [
|
|
58
|
+
...(after === null ? [] : [`after=${encodeURIComponent(after)}`]),
|
|
59
|
+
...(offset === null ? [] : [`offset=${offset}`]),
|
|
60
|
+
];
|
|
61
|
+
const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}${query.length === 0 ? '' : `?${query.join('&')}`}`);
|
|
38
62
|
const classified = classifyDoor(answer.status, answer.body, entry.locator);
|
|
39
63
|
if (classified !== null)
|
|
40
64
|
return { failure: classified };
|
|
41
65
|
const scope = parseSiteBootstrap(answer.body);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
66
|
+
return scope === null ? { failure: UNCERTAIN } : { body: answer.body, scope };
|
|
67
|
+
}
|
|
68
|
+
async function assembled(entry, scope, path, offset) {
|
|
69
|
+
const opened = scope.contents.at(-1);
|
|
70
|
+
if (opened === undefined || opened.path !== path || opened.content.length !== offset) {
|
|
71
|
+
return UNCERTAIN;
|
|
72
|
+
}
|
|
73
|
+
let text = opened.content;
|
|
74
|
+
for (;;) {
|
|
75
|
+
const part = await bootstrapPart(entry, path, text.length);
|
|
76
|
+
if ('failure' in part)
|
|
77
|
+
return part.failure;
|
|
78
|
+
const [piece] = part.scope.contents;
|
|
79
|
+
if (piece === undefined ||
|
|
80
|
+
part.scope.contents.length !== 1 ||
|
|
81
|
+
piece.path !== path ||
|
|
82
|
+
piece.content.length === 0) {
|
|
83
|
+
return UNCERTAIN;
|
|
84
|
+
}
|
|
85
|
+
text += piece.content;
|
|
86
|
+
const more = siteBootstrapOffset(part.body);
|
|
87
|
+
if (more === null)
|
|
88
|
+
break;
|
|
89
|
+
if (more !== text.length)
|
|
90
|
+
return UNCERTAIN;
|
|
91
|
+
}
|
|
92
|
+
const file = scope.files.find((held) => held.path === path);
|
|
93
|
+
if (file === undefined || (await sha256Hex(text)) !== file.version)
|
|
94
|
+
return UNCERTAIN;
|
|
95
|
+
return { ...scope, contents: [...scope.contents.slice(0, -1), { path, content: text }] };
|
|
96
|
+
}
|
|
97
|
+
async function caughtUp(entry, after) {
|
|
98
|
+
const part = await bootstrapPart(entry, after, null);
|
|
99
|
+
if ('failure' in part)
|
|
100
|
+
return part;
|
|
101
|
+
const next = siteBootstrapNext(part.body);
|
|
102
|
+
const offset = siteBootstrapOffset(part.body);
|
|
103
|
+
if (offset !== null) {
|
|
104
|
+
if (next === null)
|
|
105
|
+
return { failure: UNCERTAIN };
|
|
106
|
+
const scope = await assembled(entry, part.scope, next, offset);
|
|
107
|
+
return 'kind' in scope ? { failure: scope } : { scope, next };
|
|
108
|
+
}
|
|
109
|
+
const { scope } = part;
|
|
110
|
+
if (after !== null || next !== null || roomVersion(scope) === roomVersion(entry)) {
|
|
111
|
+
return { scope, next };
|
|
112
|
+
}
|
|
113
|
+
const view = await enumeration(entry, scope);
|
|
114
|
+
if ('kind' in view)
|
|
115
|
+
return { failure: settled(view) };
|
|
116
|
+
return { scope: advancedScope(scope, view), next: null };
|
|
53
117
|
}
|
|
54
118
|
async function refreshed(entry, fromRoomVersion) {
|
|
55
119
|
const from = logPosition(fromRoomVersion);
|
|
@@ -60,12 +124,9 @@ export function createSiteAdapter(transport) {
|
|
|
60
124
|
const models = await streamedModels(streamed.schemas, entry, 'site');
|
|
61
125
|
return models === undefined ? streamed.page : { ...streamed.page, models };
|
|
62
126
|
}
|
|
63
|
-
const
|
|
64
|
-
if ('kind' in
|
|
65
|
-
return
|
|
66
|
-
const view = viewOf(found, entry);
|
|
67
|
-
if (view === undefined)
|
|
68
|
-
return { kind: 'room-not-readable', locator: entry.locator };
|
|
127
|
+
const view = await enumeration(entry, from);
|
|
128
|
+
if ('kind' in view)
|
|
129
|
+
return view;
|
|
69
130
|
notifications.reach(entry.authority, view);
|
|
70
131
|
const answer = refreshFrom(view, fromRoomVersion);
|
|
71
132
|
if (answer.kind !== 'net-advancement')
|
|
@@ -75,6 +136,7 @@ export function createSiteAdapter(transport) {
|
|
|
75
136
|
}
|
|
76
137
|
return {
|
|
77
138
|
localSaves: true,
|
|
139
|
+
exhaustiveDiscovery: true,
|
|
78
140
|
async authorize() {
|
|
79
141
|
return {};
|
|
80
142
|
},
|
|
@@ -97,14 +159,24 @@ export function createSiteAdapter(transport) {
|
|
|
97
159
|
const entry = tracked.get(request.locator);
|
|
98
160
|
if (entry === undefined)
|
|
99
161
|
return { kind: 'room-not-readable', locator: request.locator };
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
162
|
+
const continued = request.pageToken === undefined
|
|
163
|
+
? null
|
|
164
|
+
: JSON.parse(request.pageToken);
|
|
165
|
+
const held = await caughtUp(entry, continued?.after ?? null);
|
|
103
166
|
if ('failure' in held)
|
|
104
167
|
return held.failure;
|
|
105
168
|
notifications.reach(entry.authority, held.scope);
|
|
106
|
-
const
|
|
107
|
-
|
|
169
|
+
const seen = [
|
|
170
|
+
...(continued?.seen ?? []),
|
|
171
|
+
...entry.schemas.filter((schema) => held.scope.files.some((file) => file.path === schema)),
|
|
172
|
+
];
|
|
173
|
+
const models = await partModels(held.scope, entry, new Set(seen), held.next === null);
|
|
174
|
+
const continuation = held.next === null ? null : { after: held.next, seen };
|
|
175
|
+
return {
|
|
176
|
+
...bootstrapOf(held.scope),
|
|
177
|
+
...(models === undefined ? {} : { models }),
|
|
178
|
+
...(continuation === null ? {} : { pageToken: JSON.stringify(continuation) }),
|
|
179
|
+
};
|
|
108
180
|
},
|
|
109
181
|
async refresh(_authorization, request) {
|
|
110
182
|
const entry = tracked.get(request.locator);
|
|
@@ -120,6 +192,32 @@ export function createSiteAdapter(transport) {
|
|
|
120
192
|
async history() {
|
|
121
193
|
return { kind: 'no-history' };
|
|
122
194
|
},
|
|
195
|
+
async binary(_authorization, request) {
|
|
196
|
+
const named = published(request.kind === 'path' ? { room: request.locator, path: request.path } : request.referrer);
|
|
197
|
+
if (named === null) {
|
|
198
|
+
return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
|
|
199
|
+
}
|
|
200
|
+
if (request.fileRef === undefined) {
|
|
201
|
+
return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
|
|
202
|
+
}
|
|
203
|
+
const { room_ref, path, record } = named.referrer;
|
|
204
|
+
const read = await transport.download(`${SITE_FILES}${room_ref}/${encodeURIComponent(request.fileRef)}/${path === undefined
|
|
205
|
+
? `${SITE_FILE_RECORD}/${encodeURIComponent(record)}`
|
|
206
|
+
: encodeURIComponent(path)}`);
|
|
207
|
+
if (read.status === 404) {
|
|
208
|
+
return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
|
|
209
|
+
}
|
|
210
|
+
return read.status === 200 && read.blob !== null
|
|
211
|
+
? { kind: 'binary', blob: read.blob }
|
|
212
|
+
: UNCERTAIN;
|
|
213
|
+
},
|
|
214
|
+
referrerScope(referrer) {
|
|
215
|
+
const named = published(referrer);
|
|
216
|
+
if (named === null)
|
|
217
|
+
return null;
|
|
218
|
+
const { path } = named.referrer;
|
|
219
|
+
return { kind: 'room', locator: named.locator, ...(path === undefined ? {} : { path }) };
|
|
220
|
+
},
|
|
123
221
|
reached(locator, version, target) {
|
|
124
222
|
return reachedVersion(version, target, tracked.get(locator)?.logEpoch);
|
|
125
223
|
},
|
|
@@ -127,7 +225,7 @@ export function createSiteAdapter(transport) {
|
|
|
127
225
|
return followsVersion(version, next);
|
|
128
226
|
},
|
|
129
227
|
async action(_authorization, request) {
|
|
130
|
-
if (request.name !==
|
|
228
|
+
if (request.name !== SITE_SUBMIT) {
|
|
131
229
|
return {
|
|
132
230
|
kind: 'rejected',
|
|
133
231
|
code: 'action-unimplemented',
|
|
@@ -137,7 +235,7 @@ export function createSiteAdapter(transport) {
|
|
|
137
235
|
}
|
|
138
236
|
if (!transport.online())
|
|
139
237
|
return UNCERTAIN;
|
|
140
|
-
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input),
|
|
238
|
+
return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input), SITE_SUBMIT);
|
|
141
239
|
},
|
|
142
240
|
roomStream: {
|
|
143
241
|
hold(rooms) {
|
|
@@ -152,6 +250,11 @@ export function createSiteAdapter(transport) {
|
|
|
152
250
|
},
|
|
153
251
|
reopen: notifications.reopen,
|
|
154
252
|
observe: notifications.observe,
|
|
253
|
+
published(locator, roomVersion) {
|
|
254
|
+
const at = logPosition(roomVersion);
|
|
255
|
+
if (at !== null)
|
|
256
|
+
notifications.published(locator, at);
|
|
257
|
+
},
|
|
155
258
|
},
|
|
156
259
|
serviceMode: notifications.serviceMode,
|
|
157
260
|
};
|
package/dist/stream.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConversationStream, RefreshPage, RoomStreamEvent, ServiceModeSignal } from '@agentshouse/mdruntime';
|
|
1
|
+
import type { ConversationStream, RefreshPage, RoomStreamEvent, ServiceModeSignal, StreamReceipts } from '@agentshouse/mdruntime';
|
|
2
2
|
import type { TrackedAuthority } from './discovery.js';
|
|
3
3
|
import type { HouseDoor, HouseHeldRoom, HouseMode, HouseStreamEntry } from './transport.js';
|
|
4
4
|
import { type LogPosition } from './version.js';
|
|
@@ -10,8 +10,9 @@ export type StreamedAdvancement = {
|
|
|
10
10
|
};
|
|
11
11
|
export type HouseNotifications = {
|
|
12
12
|
runtime: string;
|
|
13
|
-
observe(notify: (event: RoomStreamEvent) => void): () => void;
|
|
13
|
+
observe(notify: (event: RoomStreamEvent) => void, receipts: StreamReceipts): () => void;
|
|
14
14
|
send(rooms: readonly HouseHeldRoom[]): void;
|
|
15
|
+
published(locator: string, at: LogPosition): void;
|
|
15
16
|
reopen(): void;
|
|
16
17
|
track(authorities: readonly TrackedAuthority[]): void;
|
|
17
18
|
reach(authority: string, at: LogPosition): void;
|
package/dist/stream.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,kBAAkB,EAElB,WAAW,EACX,eAAe,EAEf,iBAAiB,EACjB,cAAc,EAEf,MAAM,wBAAwB,CAAC;AAGhC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EACV,SAAS,EACT,aAAa,EAEb,SAAS,EAET,gBAAgB,EAEjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AA0C7D,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;AAEvE,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;IACrC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,EAAE,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI,CAAC;IACxF,IAAI,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAAC;IAC5C,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAClD,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,GAAG,IAAI,CAAC;IACtD,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,OAAO,CACL,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,EACjB,KAAK,CAAC,EAAE,YAAY,GACnB,mBAAmB,GAAG,IAAI,CAAC;IAC9B,aAAa,EAAE,kBAAkB,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAkFF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CAmhB5F"}
|