@agentshouse/mdruntime-adapter 0.1.0-cd028205a5103 → 0.1.0-cd36fe2bc9d48

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.
Files changed (53) hide show
  1. package/AGENTS.md +298 -225
  2. package/dist/actions.d.ts +53 -1
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +178 -204
  5. package/dist/adapter.d.ts +1 -0
  6. package/dist/adapter.d.ts.map +1 -1
  7. package/dist/adapter.js +376 -105
  8. package/dist/discovery.d.ts +7 -4
  9. package/dist/discovery.d.ts.map +1 -1
  10. package/dist/discovery.js +46 -13
  11. package/dist/gather.d.ts +2 -1
  12. package/dist/gather.d.ts.map +1 -1
  13. package/dist/gather.js +15 -20
  14. package/dist/index.d.ts +4 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -0
  17. package/dist/model.d.ts +1 -1
  18. package/dist/model.d.ts.map +1 -1
  19. package/dist/model.js +6 -2
  20. package/dist/part.d.ts +15 -0
  21. package/dist/part.d.ts.map +1 -0
  22. package/dist/part.js +85 -0
  23. package/dist/read.d.ts +72 -20
  24. package/dist/read.d.ts.map +1 -1
  25. package/dist/read.js +323 -161
  26. package/dist/refusal.d.ts +2 -5
  27. package/dist/refusal.d.ts.map +1 -1
  28. package/dist/refusal.js +6 -9
  29. package/dist/room-types.d.ts +6 -0
  30. package/dist/room-types.d.ts.map +1 -0
  31. package/dist/room-types.js +66 -0
  32. package/dist/site.d.ts +1 -1
  33. package/dist/site.d.ts.map +1 -1
  34. package/dist/site.js +165 -61
  35. package/dist/stream.d.ts +5 -4
  36. package/dist/stream.d.ts.map +1 -1
  37. package/dist/stream.js +355 -42
  38. package/dist/transport.d.ts +67 -13
  39. package/dist/transport.d.ts.map +1 -1
  40. package/dist/transport.js +3 -0
  41. package/dist/upload.d.ts +12 -0
  42. package/dist/upload.d.ts.map +1 -0
  43. package/dist/upload.js +52 -0
  44. package/dist/version.d.ts +1 -0
  45. package/dist/version.d.ts.map +1 -1
  46. package/dist/version.js +1 -1
  47. package/dist/write.d.ts +14 -9
  48. package/dist/write.d.ts.map +1 -1
  49. package/dist/write.js +156 -41
  50. package/package.json +3 -4
  51. package/dist/links.d.ts +0 -20
  52. package/dist/links.d.ts.map +0 -1
  53. package/dist/links.js +0 -104
package/dist/read.js CHANGED
@@ -1,13 +1,72 @@
1
- import { readPosition, roomVersion } from './version.js';
1
+ import { patching, ROW_WEIGHT, stepped, } from '@agentshouse/mdruntime';
2
+ import { checkedPayload, gunzipped, parsePart } from './part.js';
3
+ import { DECIMAL, readPosition, roomVersion } from './version.js';
4
+ const REVISION_FILE = /^fr_([0-9a-z]+)\.[0-9a-z]+\.[0-9a-z]$/u;
5
+ function fileOf(revision) {
6
+ return REVISION_FILE.exec(revision)?.[1];
7
+ }
8
+ export function answering() {
9
+ return {
10
+ documents: new Map(),
11
+ revisions: new Map(),
12
+ fileIds: new Map(),
13
+ changes: new Map(),
14
+ binaryFiles: new Map(),
15
+ removals: new Set(),
16
+ folders: new Set(),
17
+ folderRemovals: new Set(),
18
+ };
19
+ }
20
+ export function revised(answer, path, revision) {
21
+ answer.revisions.set(path, revision);
22
+ const file = fileOf(revision);
23
+ if (file !== undefined)
24
+ answer.fileIds.set(path, file);
25
+ }
26
+ export function forgotten(answer, path) {
27
+ answer.documents.delete(path);
28
+ answer.revisions.delete(path);
29
+ answer.fileIds.delete(path);
30
+ answer.changes.delete(path);
31
+ answer.binaryFiles.delete(path);
32
+ answer.removals.delete(path);
33
+ }
34
+ export function folded(answer, path, removed) {
35
+ if (removed) {
36
+ answer.folders.delete(path);
37
+ answer.folderRemovals.add(path);
38
+ }
39
+ else {
40
+ answer.folderRemovals.delete(path);
41
+ answer.folders.add(path);
42
+ }
43
+ }
44
+ function* pathsOf(paths) {
45
+ const list = [];
46
+ for (const path of paths) {
47
+ list.push(path);
48
+ yield ROW_WEIGHT;
49
+ }
50
+ return list;
51
+ }
52
+ export function* answered(answer) {
53
+ const removals = yield* pathsOf(answer.removals);
54
+ return {
55
+ documents: yield* patching({}, answer.documents),
56
+ revisions: yield* patching({}, answer.revisions),
57
+ ...(answer.fileIds.size === 0 ? {} : { fileIds: yield* patching({}, answer.fileIds) }),
58
+ changes: yield* patching({}, answer.changes),
59
+ binaryFiles: yield* patching({}, answer.binaryFiles),
60
+ removals,
61
+ ...(answer.folders.size === 0 ? {} : { folders: yield* pathsOf(answer.folders) }),
62
+ ...(answer.folderRemovals.size === 0
63
+ ? {}
64
+ : { folderRemovals: yield* pathsOf(answer.folderRemovals) }),
65
+ };
66
+ }
2
67
  export function authorityRoot(handle) {
3
68
  return `/rooms/${handle}`;
4
69
  }
5
- export function contentPrefixes(tracked) {
6
- return [
7
- authorityRoot(tracked.handle),
8
- ...tracked.schemas.map((schema) => schemaPath(tracked.handle, schema)),
9
- ];
10
- }
11
70
  export function schemaPath(handle, schema) {
12
71
  return `${authorityRoot(handle)}/${schema}`;
13
72
  }
@@ -20,22 +79,37 @@ export function parseGrant(body) {
20
79
  const transfer = body.transfer;
21
80
  if (typeof transfer.url !== 'string')
22
81
  return null;
23
- if (transfer.method === 'GET')
24
- return { method: 'GET', url: transfer.url };
25
82
  if (transfer.method !== 'POST' || typeof transfer.operation !== 'string')
26
83
  return null;
27
- return { method: 'POST', operation: transfer.operation, url: transfer.url };
84
+ return { operation: transfer.operation, url: transfer.url };
85
+ }
86
+ export function parseFileAddress(body) {
87
+ if (typeof body !== 'object' || body === null)
88
+ return null;
89
+ const { download, name, sha256, media_type: mediaType } = body;
90
+ if (typeof download !== 'string' ||
91
+ typeof name !== 'string' ||
92
+ typeof sha256 !== 'string' ||
93
+ typeof mediaType !== 'string') {
94
+ return null;
95
+ }
96
+ return { url: download, name, sha256, mediaType };
28
97
  }
29
98
  function changeAuthor(value) {
30
99
  if (typeof value !== 'object' || value === null)
31
100
  return null;
32
- const { user, site, name } = value;
101
+ const { user, site, inbox, name } = value;
33
102
  if (typeof name !== 'string')
34
103
  return null;
35
- if (typeof user === 'string' && site === undefined)
104
+ const named = [user, site, inbox].filter((id) => id !== undefined);
105
+ if (named.length !== 1)
106
+ return null;
107
+ if (typeof user === 'string')
36
108
  return { kind: 'user', id: user, name };
37
- if (typeof site === 'string' && user === undefined)
109
+ if (typeof site === 'string')
38
110
  return { kind: 'site', id: site, name };
111
+ if (typeof inbox === 'string')
112
+ return { kind: 'inbox', id: inbox, name };
39
113
  return null;
40
114
  }
41
115
  export function headChange(held) {
@@ -51,32 +125,16 @@ export function headChange(held) {
51
125
  function headed(head) {
52
126
  return head === undefined ? {} : { head };
53
127
  }
54
- function parseOriginal(value) {
55
- if (typeof value !== 'object' || value === null)
56
- return null;
57
- const { attachment, name, bytes, media_type: mediaType } = value;
58
- if (typeof attachment !== 'string' || typeof name !== 'string')
59
- return null;
60
- if (typeof bytes !== 'number' || !Number.isSafeInteger(bytes) || bytes < 0)
61
- return null;
62
- if (mediaType !== null && typeof mediaType !== 'string')
128
+ export function binaryFileOf(held) {
129
+ if (held.media_type === undefined)
130
+ return undefined;
131
+ const { bytes, media_type: mediaType, sha256 } = held;
132
+ if (typeof bytes !== 'number' || typeof mediaType !== 'string' || typeof sha256 !== 'string')
63
133
  return null;
64
- return { reference: attachment, name, byteLength: bytes, mediaType, entry: value };
134
+ return { byteLength: bytes, mediaType, sha256 };
65
135
  }
66
- export function parseOriginals(value) {
67
- if (!Array.isArray(value))
68
- return null;
69
- const attachments = [];
70
- for (const entry of value) {
71
- const attachment = parseOriginal(entry);
72
- if (attachment === null)
73
- return null;
74
- attachments.push(attachment);
75
- }
76
- return attachments;
77
- }
78
- function declared(attachments) {
79
- return attachments === undefined ? {} : { attachments };
136
+ function binaried(binary) {
137
+ return binary === undefined ? {} : { binary };
80
138
  }
81
139
  function parseFile(value, mode) {
82
140
  if (typeof value !== 'object' || value === null)
@@ -85,24 +143,38 @@ function parseFile(value, mode) {
85
143
  if (typeof file.path !== 'string')
86
144
  return null;
87
145
  const head = headChange(file);
88
- if (head === null)
146
+ const binary = binaryFileOf(file);
147
+ if (head === null || binary === null)
89
148
  return null;
90
149
  if (mode === 'site') {
91
150
  if (typeof file.sha256 !== 'string')
92
151
  return null;
93
- return { path: file.path, revision: undefined, version: file.sha256, ...headed(head) };
152
+ return {
153
+ path: file.path,
154
+ revision: binary?.sha256,
155
+ version: file.sha256,
156
+ ...headed(head),
157
+ ...binaried(binary),
158
+ };
94
159
  }
95
160
  if (typeof file.revision !== 'string')
96
161
  return null;
97
- return { path: file.path, revision: file.revision, version: file.revision, ...headed(head) };
162
+ return {
163
+ path: file.path,
164
+ revision: file.revision,
165
+ version: file.revision,
166
+ ...(typeof file.sha256 === 'string' ? { sha256: file.sha256 } : {}),
167
+ ...headed(head),
168
+ ...binaried(binary),
169
+ };
98
170
  }
99
- function parseScope(value, mode) {
171
+ function parseRoomParts(value) {
100
172
  if (typeof value !== 'object' || value === null)
101
173
  return null;
102
174
  const held = value;
103
175
  if (typeof held.manifest !== 'object' || held.manifest === null)
104
176
  return null;
105
- if (!Array.isArray(held.contents))
177
+ if (!Array.isArray(held.parts))
106
178
  return null;
107
179
  const manifest = held.manifest;
108
180
  if (manifest.scope !== 'room')
@@ -112,47 +184,122 @@ function parseScope(value, mode) {
112
184
  return null;
113
185
  if (typeof manifest.room_handle !== 'string' || manifest.room_handle.length === 0)
114
186
  return null;
115
- if (!Array.isArray(manifest.files))
116
- return null;
117
- const files = [];
118
- for (const entry of manifest.files) {
119
- const file = parseFile(entry, mode);
120
- if (file === null)
187
+ const parts = [];
188
+ for (const entry of held.parts) {
189
+ const part = parsePart(entry);
190
+ if (part === null)
121
191
  return null;
122
- files.push(file);
192
+ parts.push(part);
123
193
  }
124
- const contents = [];
125
- for (const entry of held.contents) {
126
- if (typeof entry !== 'object' || entry === null)
127
- return null;
128
- const content = entry;
129
- if (typeof content.path !== 'string' || typeof content.content !== 'string')
130
- return null;
131
- contents.push({ path: content.path, content: content.content });
132
- }
133
- if (mode === 'site')
134
- return { anchor: manifest.anchor, ...at, files, contents };
135
- const attachments = parseOriginals(held.originals);
136
- if (attachments === null)
137
- return null;
138
- return { anchor: manifest.anchor, ...at, files, contents, attachments };
194
+ return { anchor: manifest.anchor, ...at, parts };
139
195
  }
140
- export function parseEnvelope(body) {
196
+ export function parseParted(body) {
141
197
  if (typeof body !== 'object' || body === null)
142
198
  return null;
143
199
  if (!('scopes' in body) || !Array.isArray(body.scopes))
144
200
  return null;
145
- const scopes = [];
201
+ const rooms = [];
146
202
  for (const entry of body.scopes) {
147
- const scope = parseScope(entry, 'credential');
148
- if (scope === null)
203
+ const room = parseRoomParts(entry);
204
+ if (room === null)
205
+ return null;
206
+ rooms.push(room);
207
+ }
208
+ if (!('next' in body) || body.next === undefined)
209
+ return { rooms };
210
+ const next = body.next;
211
+ if (typeof next !== 'object' || next === null || typeof next.room !== 'string')
212
+ return null;
213
+ return { rooms, next: next.room };
214
+ }
215
+ export function parseSiteParted(body) {
216
+ return parseRoomParts(body);
217
+ }
218
+ export function partInventory(room) {
219
+ return {
220
+ parts: room.parts.length,
221
+ bytes: room.parts.reduce((sum, part) => sum + part.bytes, 0),
222
+ };
223
+ }
224
+ export function manifested(room, inventory, pageToken) {
225
+ return {
226
+ kind: 'bootstrap',
227
+ roomVersion: roomVersion(room),
228
+ documents: {},
229
+ revisions: {},
230
+ changes: {},
231
+ binaryFiles: {},
232
+ inventory,
233
+ pageToken,
234
+ };
235
+ }
236
+ export function emptyScope(room) {
237
+ return {
238
+ anchor: room.anchor,
239
+ position: room.position,
240
+ logEpoch: room.logEpoch,
241
+ files: [],
242
+ contents: [],
243
+ };
244
+ }
245
+ function* partLines(text, mode) {
246
+ const files = [];
247
+ const contents = [];
248
+ const folders = [];
249
+ let start = 0;
250
+ while (start < text.length) {
251
+ const end = text.indexOf('\n', start);
252
+ if (end === -1)
253
+ return null;
254
+ let entry;
255
+ try {
256
+ entry = JSON.parse(text.slice(start, end));
257
+ }
258
+ catch {
259
+ return null;
260
+ }
261
+ start = end + 1;
262
+ if (folderLine(entry)) {
263
+ folders.push(entry.folder);
264
+ yield ROW_WEIGHT;
265
+ continue;
266
+ }
267
+ const file = parseFile(entry, mode);
268
+ if (file === null)
269
+ return null;
270
+ files.push(file);
271
+ const { content } = entry;
272
+ if (typeof content === 'string')
273
+ contents.push({ path: file.path, content });
274
+ else if (content !== undefined)
149
275
  return null;
150
- scopes.push(scope);
276
+ yield ROW_WEIGHT;
151
277
  }
152
- return { scopes };
278
+ return { files, contents, folders };
279
+ }
280
+ function folderLine(entry) {
281
+ if (typeof entry !== 'object' || entry === null || !('folder' in entry))
282
+ return false;
283
+ return typeof entry.folder === 'string' && Object.keys(entry).length === 1;
284
+ }
285
+ export async function housePart(room, frame, listed, mode) {
286
+ const payload = await checkedPayload(frame, listed);
287
+ if (payload === null)
288
+ return null;
289
+ const text = await gunzipped(payload);
290
+ const read = text === null ? null : await stepped(partLines(text, mode));
291
+ return read === null ? { kind: 'transport-uncertainty' } : { ...emptyScope(room), ...read };
153
292
  }
154
- export function parseSiteBootstrap(body) {
155
- return parseScope(body, 'site');
293
+ function folderChange(value) {
294
+ if (typeof value !== 'object' || value === null)
295
+ return null;
296
+ const { path, folder, removed, ...rest } = value;
297
+ return typeof path === 'string' &&
298
+ folder === true &&
299
+ (removed === undefined || removed === true) &&
300
+ Object.keys(rest).length === 0
301
+ ? { path, removed: removed === true }
302
+ : null;
156
303
  }
157
304
  function parseChange(value, mode) {
158
305
  if (typeof value !== 'object' || value === null)
@@ -163,8 +310,15 @@ function parseChange(value, mode) {
163
310
  if (held.removed === true)
164
311
  return { path: held.path, removed: true };
165
312
  const head = headChange(held);
166
- if (head === null)
313
+ const binary = binaryFileOf(held);
314
+ if (head === null || binary === null)
167
315
  return null;
316
+ if (binary !== undefined) {
317
+ if (mode === 'credential' && typeof held.revision !== 'string')
318
+ return null;
319
+ const revision = typeof held.revision === 'string' ? held.revision : binary.sha256;
320
+ return { path: held.path, binary, revision, version: revision, ...headed(head) };
321
+ }
168
322
  if (mode === 'site') {
169
323
  if (typeof held.content !== 'string' || typeof held.sha256 !== 'string')
170
324
  return null;
@@ -185,12 +339,6 @@ function parseChange(value, mode) {
185
339
  ...headed(head),
186
340
  };
187
341
  }
188
- if (typeof held.reference === 'object' && held.reference !== null) {
189
- const reference = held.reference;
190
- if (typeof reference.revision !== 'string')
191
- return null;
192
- return { path: held.path, reference: { revision: reference.revision } };
193
- }
194
342
  return null;
195
343
  }
196
344
  export function parseEnumeration(body, mode) {
@@ -209,81 +357,102 @@ export function parseEnumeration(body, mode) {
209
357
  if (!Array.isArray(held.changes))
210
358
  return null;
211
359
  const changes = [];
360
+ const folders = [];
212
361
  for (const change of held.changes) {
362
+ const folder = folderChange(change);
363
+ if (folder !== null) {
364
+ folders.push(folder);
365
+ continue;
366
+ }
213
367
  const mapped = parseChange(change, mode);
214
368
  if (mapped === null)
215
369
  return null;
216
370
  changes.push(mapped);
217
371
  }
218
- if (mode === 'site') {
219
- authorities.push({ authority: held.authority, ...at, changes });
220
- continue;
221
- }
222
- const attachments = parseOriginals(held.originals);
223
- if (attachments === null)
372
+ const next = held.next === undefined ? undefined : readPage(held.next);
373
+ if (next === null)
224
374
  return null;
225
- authorities.push({ authority: held.authority, ...at, changes, attachments });
375
+ authorities.push({
376
+ authority: held.authority,
377
+ ...at,
378
+ changes,
379
+ ...(folders.length === 0 ? {} : { folders }),
380
+ ...(next === undefined ? {} : { next }),
381
+ });
226
382
  }
227
383
  return { authorities };
228
384
  }
229
- export function advancedScope(scope, view) {
230
- const files = new Map(scope.files.map((file) => [file.path, file]));
231
- const contents = new Map(scope.contents.map((entry) => [entry.path, entry.content]));
232
- for (const change of view.changes) {
233
- files.delete(change.path);
234
- contents.delete(change.path);
235
- if ('removed' in change)
236
- continue;
237
- if ('content' in change) {
238
- files.set(change.path, {
239
- path: change.path,
240
- revision: change.revision,
241
- version: change.version,
242
- ...headed(change.head),
243
- });
244
- contents.set(change.path, change.content);
245
- continue;
385
+ function readPage(held) {
386
+ if (typeof held !== 'object' || held === null)
387
+ return null;
388
+ const { after, through, read } = held;
389
+ if (typeof after !== 'string' || !DECIMAL.test(after))
390
+ return null;
391
+ if (typeof through !== 'string' || !DECIMAL.test(through))
392
+ return null;
393
+ if (typeof read !== 'number' || !Number.isSafeInteger(read) || read < 0)
394
+ return null;
395
+ return { after, through, read };
396
+ }
397
+ function advances(asked, next) {
398
+ const moved = BigInt(next.through) - BigInt(asked.through);
399
+ return moved > 0n || (moved === 0n && next.after === asked.after && next.read > asked.read);
400
+ }
401
+ export async function wholeView(first, more) {
402
+ const changes = new Map(first.changes.map((change) => [change.path, change]));
403
+ const folders = new Map((first.folders ?? []).map((folder) => [folder.path, folder]));
404
+ let view = first;
405
+ while (view.next !== undefined) {
406
+ const asked = view.next;
407
+ const page = await more(asked);
408
+ if ('kind' in page)
409
+ return page;
410
+ if (page.position !== asked.through ||
411
+ page.logEpoch !== first.logEpoch ||
412
+ (page.next !== undefined && !advances(asked, page.next))) {
413
+ return { kind: 'transport-uncertainty' };
414
+ }
415
+ for (const change of page.changes) {
416
+ changes.delete(change.path);
417
+ changes.set(change.path, change);
246
418
  }
247
- const { revision } = change.reference;
248
- files.set(change.path, { path: change.path, revision, version: revision });
419
+ for (const folder of page.folders ?? []) {
420
+ folders.delete(folder.path);
421
+ folders.set(folder.path, folder);
422
+ }
423
+ view = page;
249
424
  }
250
425
  return {
251
- ...scope,
426
+ authority: first.authority,
252
427
  position: view.position,
253
- logEpoch: view.logEpoch,
254
- files: [...files.values()],
255
- contents: [...contents].map(([path, content]) => ({ path, content })),
428
+ logEpoch: first.logEpoch,
429
+ changes: [...changes.values()],
430
+ ...(folders.size === 0 ? {} : { folders: [...folders.values()] }),
256
431
  };
257
432
  }
258
- export function matchesScope(scope, tracked) {
259
- return scope.anchor === tracked.authority;
260
- }
261
- export function bootstrapOf(scope) {
262
- const contents = new Map(scope.contents.map((entry) => [entry.path, entry.content]));
263
- const documents = {};
264
- const revisions = {};
265
- const changes = {};
266
- const binaryTargets = [];
433
+ export function* bootstrapping(scope) {
434
+ const contents = new Map();
435
+ for (const entry of scope.contents) {
436
+ contents.set(entry.path, entry.content);
437
+ yield ROW_WEIGHT;
438
+ }
439
+ const answer = answering();
267
440
  for (const file of scope.files) {
268
- if (file.revision !== undefined)
269
- revisions[file.path] = file.revision;
441
+ yield ROW_WEIGHT;
270
442
  if (file.head !== undefined)
271
- changes[file.path] = file.head;
443
+ answer.changes.set(file.path, file.head);
272
444
  const content = contents.get(file.path);
273
- if (content === undefined)
274
- binaryTargets.push(file.path);
275
- else
276
- documents[file.path] = content;
445
+ if (file.binary !== undefined)
446
+ answer.binaryFiles.set(file.path, file.binary);
447
+ else if (content !== undefined)
448
+ answer.documents.set(file.path, content);
449
+ if (file.revision !== undefined)
450
+ revised(answer, file.path, file.revision);
277
451
  }
278
- return {
279
- kind: 'bootstrap',
280
- roomVersion: roomVersion(scope),
281
- documents,
282
- revisions,
283
- changes,
284
- binaryTargets: binaryTargets.sort(),
285
- ...declared(scope.attachments),
286
- };
452
+ for (const folder of scope.folders ?? [])
453
+ folded(answer, folder, false);
454
+ const { removals: _removals, folderRemovals: _folderRemovals, ...page } = yield* answered(answer);
455
+ return { kind: 'bootstrap', roomVersion: roomVersion(scope), ...page };
287
456
  }
288
457
  export function schemaOf(scope, schema) {
289
458
  const file = scope.files.find((entry) => entry.path === schema);
@@ -297,38 +466,31 @@ export function schemaOf(scope, schema) {
297
466
  export function viewOf(enumeration, tracked) {
298
467
  return enumeration.authorities.find((entry) => entry.authority === tracked.authority);
299
468
  }
300
- export function refreshFrom(view, fromRoomVersion) {
469
+ function* refreshing(view, fromRoomVersion) {
301
470
  if (roomVersion(view) === fromRoomVersion)
302
471
  return { kind: 'still-current' };
303
- const documents = {};
304
- const revisions = {};
305
- const changes = {};
306
- const binaryTargets = [];
307
- const removals = [];
472
+ const answer = answering();
308
473
  for (const change of view.changes) {
474
+ yield ROW_WEIGHT;
309
475
  if ('removed' in change) {
310
- removals.push(change.path);
476
+ answer.removals.add(change.path);
311
477
  continue;
312
478
  }
313
- if ('content' in change) {
314
- documents[change.path] = change.content;
315
- if (change.revision !== undefined)
316
- revisions[change.path] = change.revision;
317
- if (change.head !== undefined)
318
- changes[change.path] = change.head;
319
- continue;
320
- }
321
- binaryTargets.push(change.path);
322
- revisions[change.path] = change.reference.revision;
479
+ if ('content' in change)
480
+ answer.documents.set(change.path, change.content);
481
+ else
482
+ answer.binaryFiles.set(change.path, change.binary);
483
+ if (change.head !== undefined)
484
+ answer.changes.set(change.path, change.head);
485
+ if (change.revision !== undefined)
486
+ revised(answer, change.path, change.revision);
323
487
  }
324
- return {
325
- kind: 'net-advancement',
326
- roomVersion: roomVersion(view),
327
- documents,
328
- revisions,
329
- changes,
330
- binaryTargets: binaryTargets.sort(),
331
- removals: removals.sort(),
332
- ...declared(view.attachments),
333
- };
488
+ for (const folder of view.folders ?? []) {
489
+ yield ROW_WEIGHT;
490
+ folded(answer, folder.path, folder.removed);
491
+ }
492
+ return { kind: 'net-advancement', roomVersion: roomVersion(view), ...(yield* answered(answer)) };
493
+ }
494
+ export async function refreshFrom(view, fromRoomVersion) {
495
+ return stepped(refreshing(view, fromRoomVersion));
334
496
  }
package/dist/refusal.d.ts CHANGED
@@ -1,9 +1,6 @@
1
1
  import type { AdapterFailure, DiscoverResult, ProviderRefusal, ScopedRefusal } from '@agentshouse/mdruntime';
2
- export type DoorRefusal = ProviderRefusal & {
3
- retryable: boolean;
4
- };
5
- export declare function doorRefusal(body: unknown): DoorRefusal | null;
6
- export declare function scopedRefusal(locator: string, scope: ScopedRefusal['scope'], refusal: DoorRefusal): ScopedRefusal;
2
+ export declare function doorRefusal(body: unknown): ProviderRefusal | null;
3
+ export declare function scopedRefusal(locator: string, scope: ScopedRefusal['scope'], refusal: ProviderRefusal): ScopedRefusal;
7
4
  export declare function classifyDoor(status: number, body: unknown, locator: string): AdapterFailure | null;
8
5
  export declare function classifyRead(status: number, body: unknown, locator: string): AdapterFailure | {
9
6
  kind: 'beyond-horizon';
@@ -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,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnE,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CAO7D;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,EAC7B,OAAO,EAAE,WAAW,GACnB,aAAa,CAEf;AAmBD,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,CAYrF"}
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
@@ -6,11 +6,11 @@ export function doorRefusal(body) {
6
6
  const error = body.error;
7
7
  if (typeof error.code !== 'string')
8
8
  return null;
9
- const { code, ...fields } = error;
10
- return { code, fields, retryable: error.retryable === true };
9
+ const { code, retryable, ...fields } = error;
10
+ return { code, fields, retryable: retryable === true };
11
11
  }
12
12
  export function scopedRefusal(locator, scope, refusal) {
13
- return { kind: 'scoped-refusal', locator, scope, code: refusal.code, fields: refusal.fields };
13
+ return { kind: 'scoped-refusal', locator, scope, ...refusal };
14
14
  }
15
15
  function doorFailure(status, body) {
16
16
  if (status === 0)
@@ -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)
@@ -50,11 +51,7 @@ export function discoveryFailure(status, body) {
50
51
  if (failure.kind === 'revoked-authorization')
51
52
  return failure;
52
53
  if (failure.kind === 'refused') {
53
- return {
54
- kind: 'contract-unavailable',
55
- code: failure.refusal.code,
56
- fields: failure.refusal.fields,
57
- };
54
+ return { kind: 'contract-unavailable', ...failure.refusal };
58
55
  }
59
56
  return { kind: 'transport-uncertainty' };
60
57
  }
@@ -0,0 +1,6 @@
1
+ export declare const INBOX_CHANNEL_KINDS: readonly ['telegram-bot', 'whatsapp', 'messenger', 'instagram'];
2
+ export type InboxChannelKind = (typeof INBOX_CHANNEL_KINDS)[number];
3
+ export declare const INBOX_CHAT_TYPE = "inbox-chat";
4
+ export declare const INBOX_MESSAGE_TYPE = "inbox-message";
5
+ export declare const HOUSE_ROOM_TYPES: string;
6
+ //# sourceMappingURL=room-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"room-types.d.ts","sourceRoot":"","sources":["../src/room-types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,YAAI,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,CAAU,CAAC;AAEnG,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,eAAe,eAAe,CAAC;AAE5C,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAalD,eAAO,MAAM,gBAAgB,QAsDjB,CAAC"}