@agentshouse/mdruntime-adapter 0.1.0-cafd7caa7ae65 → 0.1.0-cb4013fc9f680

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.
@@ -1 +1 @@
1
- {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../src/read.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../src/read.ts"],"names":[],"mappings":"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"}
package/dist/read.js CHANGED
@@ -1,4 +1,12 @@
1
- import { readPosition, roomVersion } from './version.js';
1
+ import { DECIMAL, readPosition, roomVersion } from './version.js';
2
+ const REVISION_FILE = /^fr_([0-9a-z]+)\.[0-9a-z]+\.[0-9a-z]$/u;
3
+ export function identities(revisions) {
4
+ const fileIds = Object.fromEntries(Object.entries(revisions).flatMap(([path, revision]) => {
5
+ const file = REVISION_FILE.exec(revision)?.[1];
6
+ return file === undefined ? [] : [[path, file]];
7
+ }));
8
+ return Object.keys(fileIds).length === 0 ? {} : { fileIds };
9
+ }
2
10
  export function authorityRoot(handle) {
3
11
  return `/rooms/${handle}`;
4
12
  }
@@ -92,6 +100,7 @@ function parseFile(value, mode) {
92
100
  path: file.path,
93
101
  revision: file.revision,
94
102
  version: file.revision,
103
+ ...(typeof file.sha256 === 'string' ? { sha256: file.sha256 } : {}),
95
104
  ...headed(head),
96
105
  ...binaried(binary),
97
106
  };
@@ -132,13 +141,26 @@ function parseScope(value, mode) {
132
141
  }
133
142
  return { anchor: manifest.anchor, ...at, files, contents };
134
143
  }
144
+ function parseCut(value) {
145
+ if (value === undefined)
146
+ return undefined;
147
+ if (typeof value !== 'object' || value === null)
148
+ return null;
149
+ const { position, log_epoch: logEpoch } = value;
150
+ if (typeof position !== 'string' || typeof logEpoch !== 'string')
151
+ return null;
152
+ return { position, log_epoch: logEpoch };
153
+ }
135
154
  function parseCursor(value) {
136
155
  if (typeof value !== 'object' || value === null)
137
156
  return null;
138
- const { room, path } = value;
157
+ const { room, path, cut } = value;
139
158
  if (typeof room !== 'string' || (path !== null && typeof path !== 'string'))
140
159
  return null;
141
- return { room, path };
160
+ const parsed = parseCut(cut);
161
+ if (parsed === null)
162
+ return null;
163
+ return { room, path, ...(parsed === undefined ? {} : { cut: parsed }) };
142
164
  }
143
165
  export function parseEnvelope(body) {
144
166
  if (typeof body !== 'object' || body === null)
@@ -160,6 +182,18 @@ export function parseEnvelope(body) {
160
182
  export function parseSiteBootstrap(body) {
161
183
  return parseScope(body, 'site');
162
184
  }
185
+ export function siteBootstrapNext(body) {
186
+ if (typeof body !== 'object' || body === null || !('next' in body))
187
+ return null;
188
+ return typeof body.next === 'string' && body.next.length > 0 ? body.next : null;
189
+ }
190
+ export function siteBootstrapOffset(body) {
191
+ if (typeof body !== 'object' || body === null || !('offset' in body))
192
+ return null;
193
+ return Number.isSafeInteger(body.offset) && body.offset > 0
194
+ ? body.offset
195
+ : null;
196
+ }
163
197
  function parseChange(value, mode) {
164
198
  if (typeof value !== 'object' || value === null)
165
199
  return null;
@@ -222,10 +256,60 @@ export function parseEnumeration(body, mode) {
222
256
  return null;
223
257
  changes.push(mapped);
224
258
  }
225
- authorities.push({ authority: held.authority, ...at, changes });
259
+ const next = held.next === undefined ? undefined : readPage(held.next);
260
+ if (next === null)
261
+ return null;
262
+ authorities.push({
263
+ authority: held.authority,
264
+ ...at,
265
+ changes,
266
+ ...(next === undefined ? {} : { next }),
267
+ });
226
268
  }
227
269
  return { authorities };
228
270
  }
271
+ function readPage(held) {
272
+ if (typeof held !== 'object' || held === null)
273
+ return null;
274
+ const { after, through, read } = held;
275
+ if (typeof after !== 'string' || !DECIMAL.test(after))
276
+ return null;
277
+ if (typeof through !== 'string' || !DECIMAL.test(through))
278
+ return null;
279
+ if (typeof read !== 'number' || !Number.isSafeInteger(read) || read < 0)
280
+ return null;
281
+ return { after, through, read };
282
+ }
283
+ function advances(asked, next) {
284
+ const moved = BigInt(next.through) - BigInt(asked.through);
285
+ return moved > 0n || (moved === 0n && next.after === asked.after && next.read > asked.read);
286
+ }
287
+ export async function wholeView(first, more) {
288
+ const changes = new Map(first.changes.map((change) => [change.path, change]));
289
+ let view = first;
290
+ while (view.next !== undefined) {
291
+ const asked = view.next;
292
+ const page = await more(asked);
293
+ if ('kind' in page)
294
+ return page;
295
+ if (page.position !== asked.through ||
296
+ page.logEpoch !== first.logEpoch ||
297
+ (page.next !== undefined && !advances(asked, page.next))) {
298
+ return { kind: 'transport-uncertainty' };
299
+ }
300
+ for (const change of page.changes) {
301
+ changes.delete(change.path);
302
+ changes.set(change.path, change);
303
+ }
304
+ view = page;
305
+ }
306
+ return {
307
+ authority: first.authority,
308
+ position: view.position,
309
+ logEpoch: first.logEpoch,
310
+ changes: [...changes.values()],
311
+ };
312
+ }
229
313
  export function advancedScope(scope, view) {
230
314
  const files = new Map(scope.files.map((file) => [file.path, file]));
231
315
  const contents = new Map(scope.contents.map((entry) => [entry.path, entry.content]));
@@ -277,6 +361,7 @@ export function bootstrapOf(scope) {
277
361
  roomVersion: roomVersion(scope),
278
362
  documents,
279
363
  revisions,
364
+ ...identities(revisions),
280
365
  changes,
281
366
  binaryFiles,
282
367
  };
@@ -320,6 +405,7 @@ export function refreshFrom(view, fromRoomVersion) {
320
405
  roomVersion: roomVersion(view),
321
406
  documents,
322
407
  revisions,
408
+ ...identities(revisions),
323
409
  changes,
324
410
  binaryFiles,
325
411
  removals: removals.sort(),
@@ -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;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,CAQrF"}
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 CHANGED
@@ -1,4 +1,4 @@
1
1
  import type { Adapter } from '@agentshouse/mdruntime';
2
2
  import { type HouseSiteTransport } from './transport.js';
3
- export declare function createSiteAdapter(transport: HouseSiteTransport): Adapter;
3
+ export declare function createSiteAdapter(transport: HouseSiteTransport, snapshot?: boolean): Adapter;
4
4
  //# sourceMappingURL=site.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAOR,MAAM,wBAAwB,CAAC;AAsBhC,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAC;AAiCxB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,kBAAkB,GAAG,OAAO,CA8KxE"}
1
+ {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../src/site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EAUR,MAAM,wBAAwB,CAAC;AA2BhC,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,gBAAgB,CAAC;AAyCxB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,kBAAkB,EAAE,QAAQ,UAAQ,GAAG,OAAO,CAyR1F"}
package/dist/site.js CHANGED
@@ -1,13 +1,17 @@
1
1
  import { actionOutcome, SITE_SUBMIT } from './actions.js';
2
2
  import { mapDiscovery, parseSiteDiscovery, siteCapabilities, siteTracked, } from './discovery.js';
3
- import { scopeModels, streamedModels, viewModels } from './model.js';
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
8
  import { SITE_DOOR_BOOTSTRAP, SITE_DOOR_DISCOVER, SITE_DOOR_ENUMERATE, SITE_DOOR_SUBMIT, SITE_FILE_RECORD, SITE_FILES, } from './transport.js';
8
9
  import { houseReferrer } from './referrer.js';
9
10
  import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
10
11
  const UNCERTAIN = { kind: 'transport-uncertainty' };
12
+ function unfound() {
13
+ return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
14
+ }
11
15
  function siteRoom(tracked) {
12
16
  return {
13
17
  name: tracked.handle,
@@ -22,39 +26,109 @@ function siteRoom(tracked) {
22
26
  function settled(refused) {
23
27
  return refused.kind === 'beyond-horizon' ? UNCERTAIN : refused;
24
28
  }
25
- export function createSiteAdapter(transport) {
29
+ export function createSiteAdapter(transport, snapshot = false) {
26
30
  const notifications = houseNotifications(transport, 'site');
27
31
  const tracked = new Map();
28
32
  function published(referrer) {
29
33
  const named = houseReferrer(referrer, tracked);
30
34
  return named === null || !tracked.has(named.locator) ? null : named;
31
35
  }
32
- async function enumeration(entry, from) {
36
+ function fileRoute(request) {
37
+ const named = published(request.kind === 'path' ? { room: request.locator, path: request.path } : request.referrer);
38
+ if (named === null) {
39
+ return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
40
+ }
41
+ if (request.fileRef === undefined)
42
+ return unfound();
43
+ const { room_ref, path, record } = named.referrer;
44
+ return `${SITE_FILES}${room_ref}/${encodeURIComponent(request.fileRef)}/${path === undefined
45
+ ? `${SITE_FILE_RECORD}/${encodeURIComponent(record)}`
46
+ : encodeURIComponent(path)}`;
47
+ }
48
+ async function enumerated(entry, from, page) {
33
49
  const answer = await transport.door(SITE_DOOR_ENUMERATE, {
34
- positions: [presented(entry.authority, from)],
50
+ positions: [
51
+ page === undefined
52
+ ? presented(entry.authority, from)
53
+ : {
54
+ ...presented(entry.authority, { position: page.after, logEpoch: from.logEpoch }),
55
+ page: { through: page.through, read: page.read },
56
+ },
57
+ ],
35
58
  });
36
59
  const classified = classifyRead(answer.status, answer.body, entry.locator);
37
60
  if (classified !== null)
38
61
  return classified;
39
- return parseEnumeration(answer.body, 'site') ?? UNCERTAIN;
62
+ const found = parseEnumeration(answer.body, 'site');
63
+ if (found === null)
64
+ return UNCERTAIN;
65
+ return viewOf(found, entry) ?? { kind: 'room-not-readable', locator: entry.locator };
66
+ }
67
+ async function enumeration(entry, from) {
68
+ const first = await enumerated(entry, from);
69
+ return 'kind' in first ? first : wholeView(first, (page) => enumerated(entry, from, page));
40
70
  }
41
- async function caughtUp(entry) {
42
- const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}`);
71
+ async function bootstrapPart(entry, after, offset) {
72
+ const query = [
73
+ ...(after === null ? [] : [`after=${encodeURIComponent(after)}`]),
74
+ ...(offset === null ? [] : [`offset=${offset}`]),
75
+ ];
76
+ const answer = await transport.read(`${SITE_DOOR_BOOTSTRAP}${entry.authority}${query.length === 0 ? '' : `?${query.join('&')}`}`);
43
77
  const classified = classifyDoor(answer.status, answer.body, entry.locator);
44
78
  if (classified !== null)
45
79
  return { failure: classified };
46
80
  const scope = parseSiteBootstrap(answer.body);
47
- if (scope === null)
48
- return { failure: UNCERTAIN };
49
- if (roomVersion(scope) === roomVersion(entry))
50
- return { scope };
51
- const found = await enumeration(entry, scope);
52
- if ('kind' in found)
53
- return { failure: settled(found) };
54
- const view = viewOf(found, entry);
55
- if (view === undefined)
56
- return { failure: { kind: 'room-not-readable', locator: entry.locator } };
57
- return { scope: advancedScope(scope, view) };
81
+ return scope === null ? { failure: UNCERTAIN } : { body: answer.body, scope };
82
+ }
83
+ async function assembled(entry, scope, path, offset) {
84
+ const opened = scope.contents.at(-1);
85
+ if (opened === undefined || opened.path !== path || opened.content.length !== offset) {
86
+ return UNCERTAIN;
87
+ }
88
+ let text = opened.content;
89
+ for (;;) {
90
+ const part = await bootstrapPart(entry, path, text.length);
91
+ if ('failure' in part)
92
+ return part.failure;
93
+ const [piece] = part.scope.contents;
94
+ if (piece === undefined ||
95
+ part.scope.contents.length !== 1 ||
96
+ piece.path !== path ||
97
+ piece.content.length === 0) {
98
+ return UNCERTAIN;
99
+ }
100
+ text += piece.content;
101
+ const more = siteBootstrapOffset(part.body);
102
+ if (more === null)
103
+ break;
104
+ if (more !== text.length)
105
+ return UNCERTAIN;
106
+ }
107
+ const file = scope.files.find((held) => held.path === path);
108
+ if (file === undefined || (await sha256Hex(text)) !== file.version)
109
+ return UNCERTAIN;
110
+ return { ...scope, contents: [...scope.contents.slice(0, -1), { path, content: text }] };
111
+ }
112
+ async function caughtUp(entry, after) {
113
+ const part = await bootstrapPart(entry, after, null);
114
+ if ('failure' in part)
115
+ return part;
116
+ const next = siteBootstrapNext(part.body);
117
+ const offset = siteBootstrapOffset(part.body);
118
+ if (offset !== null) {
119
+ if (next === null)
120
+ return { failure: UNCERTAIN };
121
+ const scope = await assembled(entry, part.scope, next, offset);
122
+ return 'kind' in scope ? { failure: scope } : { scope, next };
123
+ }
124
+ const { scope } = part;
125
+ if (after !== null || next !== null || roomVersion(scope) === roomVersion(entry)) {
126
+ return { scope, next };
127
+ }
128
+ const view = await enumeration(entry, scope);
129
+ if ('kind' in view)
130
+ return { failure: settled(view) };
131
+ return { scope: advancedScope(scope, view), next: null };
58
132
  }
59
133
  async function refreshed(entry, fromRoomVersion) {
60
134
  const from = logPosition(fromRoomVersion);
@@ -65,12 +139,9 @@ export function createSiteAdapter(transport) {
65
139
  const models = await streamedModels(streamed.schemas, entry, 'site');
66
140
  return models === undefined ? streamed.page : { ...streamed.page, models };
67
141
  }
68
- const found = await enumeration(entry, from);
69
- if ('kind' in found)
70
- return found;
71
- const view = viewOf(found, entry);
72
- if (view === undefined)
73
- return { kind: 'room-not-readable', locator: entry.locator };
142
+ const view = await enumeration(entry, from);
143
+ if ('kind' in view)
144
+ return view;
74
145
  notifications.reach(entry.authority, view);
75
146
  const answer = refreshFrom(view, fromRoomVersion);
76
147
  if (answer.kind !== 'net-advancement')
@@ -80,6 +151,7 @@ export function createSiteAdapter(transport) {
80
151
  }
81
152
  return {
82
153
  localSaves: true,
154
+ exhaustiveDiscovery: true,
83
155
  async authorize() {
84
156
  return {};
85
157
  },
@@ -102,14 +174,24 @@ export function createSiteAdapter(transport) {
102
174
  const entry = tracked.get(request.locator);
103
175
  if (entry === undefined)
104
176
  return { kind: 'room-not-readable', locator: request.locator };
105
- if (request.pageToken !== undefined)
106
- return UNCERTAIN;
107
- const held = await caughtUp(entry);
177
+ const continued = request.pageToken === undefined
178
+ ? null
179
+ : JSON.parse(request.pageToken);
180
+ const held = await caughtUp(entry, continued?.after ?? null);
108
181
  if ('failure' in held)
109
182
  return held.failure;
110
183
  notifications.reach(entry.authority, held.scope);
111
- const models = await scopeModels(held.scope, entry);
112
- return { ...bootstrapOf(held.scope), ...(models === undefined ? {} : { models }) };
184
+ const seen = [
185
+ ...(continued?.seen ?? []),
186
+ ...entry.schemas.filter((schema) => held.scope.files.some((file) => file.path === schema)),
187
+ ];
188
+ const models = await partModels(held.scope, entry, new Set(seen), held.next === null);
189
+ const continuation = held.next === null ? null : { after: held.next, seen };
190
+ return {
191
+ ...bootstrapOf(held.scope),
192
+ ...(models === undefined ? {} : { models }),
193
+ ...(continuation === null ? {} : { pageToken: JSON.stringify(continuation) }),
194
+ };
113
195
  },
114
196
  async refresh(_authorization, request) {
115
197
  const entry = tracked.get(request.locator);
@@ -117,6 +199,11 @@ export function createSiteAdapter(transport) {
117
199
  return { kind: 'room-not-readable', locator: request.locator };
118
200
  if (request.pageToken !== undefined)
119
201
  return UNCERTAIN;
202
+ if (snapshot) {
203
+ return request.fromRoomVersion === roomVersion(entry)
204
+ ? { kind: 'still-current' }
205
+ : { kind: 'beyond-horizon' };
206
+ }
120
207
  return refreshed(entry, request.fromRoomVersion);
121
208
  },
122
209
  async mutate() {
@@ -126,24 +213,26 @@ export function createSiteAdapter(transport) {
126
213
  return { kind: 'no-history' };
127
214
  },
128
215
  async binary(_authorization, request) {
129
- const named = published(request.kind === 'path' ? { room: request.locator, path: request.path } : request.referrer);
130
- if (named === null) {
131
- return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
132
- }
133
- if (request.fileRef === undefined) {
134
- return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
135
- }
136
- const { room_ref, path, record } = named.referrer;
137
- const read = await transport.download(`${SITE_FILES}${room_ref}/${encodeURIComponent(request.fileRef)}/${path === undefined
138
- ? `${SITE_FILE_RECORD}/${encodeURIComponent(record)}`
139
- : encodeURIComponent(path)}`);
140
- if (read.status === 404) {
141
- return { kind: 'rejected', code: 'file_not_found', fields: {}, retryable: false };
142
- }
216
+ const route = fileRoute(request);
217
+ if (typeof route !== 'string')
218
+ return route;
219
+ const read = await transport.download(route);
220
+ if (read.status === 404)
221
+ return unfound();
143
222
  return read.status === 200 && read.blob !== null
144
223
  ? { kind: 'binary', blob: read.blob }
145
224
  : UNCERTAIN;
146
225
  },
226
+ async link(_authorization, request) {
227
+ const route = fileRoute(request);
228
+ if (typeof route !== 'string')
229
+ return route;
230
+ return {
231
+ kind: 'link',
232
+ url: route,
233
+ name: request.path.slice(request.path.lastIndexOf('/') + 1),
234
+ };
235
+ },
147
236
  referrerScope(referrer) {
148
237
  const named = published(referrer);
149
238
  if (named === null)
@@ -170,20 +259,27 @@ export function createSiteAdapter(transport) {
170
259
  return UNCERTAIN;
171
260
  return actionOutcome(await transport.door(SITE_DOOR_SUBMIT, request.input), SITE_SUBMIT);
172
261
  },
173
- roomStream: {
174
- hold(rooms) {
175
- notifications.send(rooms.flatMap((room) => {
176
- const entry = tracked.get(room.locator);
177
- const at = logPosition(room.roomVersion);
178
- if (entry === undefined || at === null)
179
- return [];
180
- notifications.reach(entry.authority, at);
181
- return [presented(entry.authority, at)];
182
- }));
262
+ roomStream: snapshot
263
+ ? undefined
264
+ : {
265
+ hold(rooms) {
266
+ notifications.send(rooms.flatMap((room) => {
267
+ const entry = tracked.get(room.locator);
268
+ const at = logPosition(room.roomVersion);
269
+ if (entry === undefined || at === null)
270
+ return [];
271
+ notifications.reach(entry.authority, at);
272
+ return [presented(entry.authority, at)];
273
+ }), null);
274
+ },
275
+ reopen: notifications.reopen,
276
+ observe: notifications.observe,
277
+ published(locator, roomVersion) {
278
+ const at = logPosition(roomVersion);
279
+ if (at !== null)
280
+ notifications.published(locator, at);
281
+ },
183
282
  },
184
- reopen: notifications.reopen,
185
- observe: notifications.observe,
186
- },
187
283
  serviceMode: notifications.serviceMode,
188
284
  };
189
285
  }
package/dist/stream.d.ts CHANGED
@@ -1,6 +1,6 @@
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
- import type { HouseDoor, HouseHeldRoom, HouseMode, HouseStreamEntry } from './transport.js';
3
+ import type { HouseDemand, HouseDoor, HouseHeldRoom, HouseMode, HouseStreamEntry } from './transport.js';
4
4
  import { type LogPosition } from './version.js';
5
5
  export type HeldRevision = (path: string, revision: string) => boolean;
6
6
  export type StreamedAdvancement = {
@@ -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;
14
- send(rooms: readonly HouseHeldRoom[]): void;
13
+ observe(notify: (event: RoomStreamEvent) => void, receipts: StreamReceipts): () => void;
14
+ send(rooms: readonly HouseHeldRoom[], demand: HouseDemand | null): 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;
@@ -1 +1 @@
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,EAElB,MAAM,wBAAwB,CAAC;AAEhC,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;AAgB7D,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,GAAG,MAAM,IAAI,CAAC;IAC9D,IAAI,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI,CAAC;IAC5C,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;AAuBF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,kBAAkB,CA8S5F"}
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,WAAW,EACX,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,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;IACxE,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,CAwhB5F"}