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

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/dist/adapter.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import { DISCOVER_PREFIXES, capabilities, discoveredRoom, mapDiscovery, parseDiscovery, trackedFrom, } from './discovery.js';
2
- import { scopeModels, streamedModels, viewModels } from './model.js';
3
- import { gathered, selections } from './gather.js';
2
+ import { partModels, streamedModels, viewModels } from './model.js';
3
+ import { gathered, gatheredEach, selections } from './gather.js';
4
4
  import { createSiteAdapter } from './site.js';
5
5
  import { bootstrapOf, contentPrefixes, matchesScope, parseEnumeration, parseEnvelope, parseGrant, refreshFrom, viewOf, } from './read.js';
6
- import { acceptedLinks, enumeratedLinks, heldLinks, scopeLinks, streamedLinks, } from './links.js';
6
+ import { acceptedHanded, enumeratedHanded, heldHanded, scopeHanded, streamedHanded, } from './handed.js';
7
7
  import { houseAction } from './actions.js';
8
8
  import { classifyDoor, classifyRead, discoveryFailure, doorRefusal } from './refusal.js';
9
9
  import { houseNotifications } from './stream.js';
10
- import { DOOR_BATCH, DOOR_BATCH_UPLOAD, DOOR_BOOTSTRAP, DOOR_DISCOVER, DOOR_ENUMERATE, DOOR_REVISIONS, } from './transport.js';
10
+ import { DOOR_BATCH, DOOR_BATCH_UPLOAD, DOOR_BOOTSTRAP, DOOR_DISCOVER, DOOR_ENUMERATE, DOOR_FILES_GET, DOOR_REVISIONS, } from './transport.js';
11
11
  import { batchPaths, deltaBody, deltaBytes, deltaDigest, historyOutcome, houseChanges, mutationOutcome, operationHead, rejectedMapping, revisionBody, uploadable, } from './write.js';
12
+ import { houseReferrer } from './referrer.js';
12
13
  import { followsVersion, logPosition, presented, reachedVersion, roomVersion, } from './version.js';
13
14
  const UNCERTAIN = { kind: 'transport-uncertainty' };
14
15
  const UNCERTAIN_READ = { kind: 'transport-uncertainty' };
@@ -28,14 +29,26 @@ export function createAgentsHouseAdapter(options) {
28
29
  throw new Error('no Discovery declared the bounds');
29
30
  return bounds;
30
31
  }
31
- async function bootstrappedRoom(envelope, entry) {
32
- const scope = envelope.scopes.find((candidate) => matchesScope(candidate, entry));
32
+ async function bootstrappedRoom(envelope, scope, entry, continued) {
33
33
  if (scope === undefined)
34
34
  return { kind: 'room-not-readable', locator: entry.locator };
35
- handed.set(entry.locator, scopeLinks(scope));
35
+ const next = envelope.next?.room === entry.authority ? envelope.next.path : null;
36
+ if (continued === null && next === null)
37
+ handed.set(entry.locator, scopeHanded(scope));
38
+ else
39
+ handed.delete(entry.locator);
36
40
  notifications.reach(entry.authority, scope);
37
- const models = await scopeModels(scope, entry);
38
- return { ...bootstrapOf(scope), ...(models === undefined ? {} : { models }) };
41
+ const seen = [
42
+ ...(continued?.seen ?? []),
43
+ ...entry.schemas.filter((schema) => scope.files.some((file) => file.path === schema)),
44
+ ];
45
+ const models = await partModels(scope, entry, new Set(seen), next === null);
46
+ const continuation = next === null ? null : { after: next, seen };
47
+ return {
48
+ ...bootstrapOf(scope),
49
+ ...(models === undefined ? {} : { models }),
50
+ ...(continuation === null ? {} : { pageToken: JSON.stringify(continuation) }),
51
+ };
39
52
  }
40
53
  async function enumeratedRoom(enumeration, ask) {
41
54
  const view = viewOf(enumeration, ask.entry);
@@ -45,21 +58,18 @@ export function createAgentsHouseAdapter(options) {
45
58
  const answer = refreshFrom(view, ask.fromRoomVersion);
46
59
  if (answer.kind !== 'net-advancement')
47
60
  return answer;
48
- handed.set(ask.entry.locator, enumeratedLinks(view, handed.get(ask.entry.locator)));
61
+ handed.set(ask.entry.locator, enumeratedHanded(view, handed.get(ask.entry.locator)));
49
62
  const models = await viewModels(view, ask.entry);
50
63
  return models === undefined ? answer : { ...answer, models };
51
64
  }
52
65
  async function streamed(entry, request, from) {
53
- const links = handed.get(entry.locator);
54
- if (links?.roomVersion !== request.fromRoomVersion)
66
+ const held = handed.get(entry.locator);
67
+ if (held?.roomVersion !== request.fromRoomVersion)
55
68
  return null;
56
- const advanced = notifications.advance(entry, from, (path, revision) => links.revisions.get(path) === revision);
69
+ const advanced = notifications.advance(entry, from, (path, revision) => held.revisions.get(path) === revision);
57
70
  if (advanced === null)
58
71
  return null;
59
- const relinked = streamedLinks(links, advanced);
60
- if (relinked === null)
61
- return null;
62
- handed.set(entry.locator, relinked);
72
+ handed.set(entry.locator, streamedHanded(held, advanced));
63
73
  const models = await streamedModels(advanced.schemas, entry, 'credential');
64
74
  return models === undefined ? advanced.page : { ...advanced.page, models };
65
75
  }
@@ -69,7 +79,7 @@ export function createAgentsHouseAdapter(options) {
69
79
  const at = logPosition(room.roomVersion);
70
80
  if (entry === undefined || at === null)
71
81
  return [];
72
- handed.set(room.locator, heldLinks(room));
82
+ handed.set(room.locator, heldHanded(room));
73
83
  notifications.reach(entry.authority, at);
74
84
  return [presented(entry.authority, at)];
75
85
  });
@@ -78,19 +88,15 @@ export function createAgentsHouseAdapter(options) {
78
88
  function adopted(entry, outcome) {
79
89
  if (outcome.kind !== 'accepted')
80
90
  return outcome;
81
- const { originals, ...accepted } = outcome;
82
- const links = handed.get(entry.locator);
83
- if (links === undefined)
84
- return accepted;
85
- const follows = followsVersion(links.roomVersion, accepted.roomVersion);
86
- const relinked = acceptedLinks(links, accepted, follows ? accepted.roomVersion : links.roomVersion, originals);
87
- handed.set(entry.locator, relinked.links);
88
- const at = logPosition(accepted.roomVersion);
91
+ const held = handed.get(entry.locator);
92
+ if (held === undefined)
93
+ return outcome;
94
+ const follows = followsVersion(held.roomVersion, outcome.roomVersion);
95
+ handed.set(entry.locator, acceptedHanded(held, outcome, follows ? outcome.roomVersion : held.roomVersion));
96
+ const at = logPosition(outcome.roomVersion);
89
97
  if (follows && at !== null)
90
98
  notifications.reach(entry.authority, at);
91
- return relinked.attachments === undefined
92
- ? accepted
93
- : { ...accepted, attachments: relinked.attachments };
99
+ return outcome;
94
100
  }
95
101
  function authorityFor(locator) {
96
102
  return tracked.get(locator);
@@ -109,41 +115,54 @@ export function createAgentsHouseAdapter(options) {
109
115
  return result;
110
116
  return { ...result, at: { locator, roomVersion: roomVersion({ position, logEpoch }) } };
111
117
  }
112
- async function bundled(body) {
113
- const grant = parseGrant(body);
114
- if (grant === null)
115
- return body;
116
- if (grant.method !== 'GET')
117
- return null;
118
- const answer = await transport.transfer({
119
- act: 'local_copy_bundle',
120
- method: 'GET',
121
- url: grant.url,
122
- answer: 'json',
123
- });
124
- return answer.status === 200 ? answer.body : null;
125
- }
126
118
  function weight(entry) {
127
119
  return contentPrefixes(entry).length;
128
120
  }
129
- async function bootstrapped(entries) {
130
- const answers = [];
131
- for (const part of selections(entries, weight, declared().max_prefixes)) {
132
- const answer = await transport.door(DOOR_BOOTSTRAP, {
133
- prefixes: part.flatMap((entry) => contentPrefixes(entry)),
134
- });
135
- const classified = part.map((entry) => classifyDoor(answer.status, answer.body, entry.locator));
136
- const envelope = classified[0] === null ? parseEnvelope(await bundled(answer.body)) : null;
137
- for (const [index, entry] of part.entries()) {
138
- const failure = classified[index];
139
- if (failure === null || failure === undefined) {
140
- answers.push(envelope === null ? UNCERTAIN_READ : await bootstrappedRoom(envelope, entry));
141
- continue;
121
+ async function bootstrapped(entries, answer) {
122
+ let open = entries.map((entry, ask) => ({ entry, ask }));
123
+ while (open.length > 0) {
124
+ const unreached = [];
125
+ for (const part of selections(open, ({ entry }) => weight(entry), declared().max_prefixes)) {
126
+ const answered = await transport.door(DOOR_BOOTSTRAP, {
127
+ prefixes: part.flatMap(({ entry }) => contentPrefixes(entry)),
128
+ });
129
+ const classified = part.map(({ entry }) => classifyDoor(answered.status, answered.body, entry.locator));
130
+ const envelope = classified[0] === null ? parseEnvelope(answered.body) : null;
131
+ for (const [index, asked] of part.entries()) {
132
+ const failure = classified[index];
133
+ if (failure !== null && failure !== undefined) {
134
+ answer(asked.ask, failure);
135
+ continue;
136
+ }
137
+ if (envelope === null) {
138
+ answer(asked.ask, UNCERTAIN_READ);
139
+ continue;
140
+ }
141
+ const scope = envelope.scopes.find((candidate) => matchesScope(candidate, asked.entry));
142
+ if (scope === undefined && envelope.next !== undefined) {
143
+ unreached.push(asked);
144
+ continue;
145
+ }
146
+ answer(asked.ask, await bootstrappedRoom(envelope, scope, asked.entry, null));
142
147
  }
143
- answers.push(failure);
144
148
  }
149
+ open = unreached;
145
150
  }
146
- return answers;
151
+ }
152
+ async function continuedBootstrap(entry, continued) {
153
+ const after = { room: entry.authority, path: continued.after };
154
+ const answered = await transport.door(DOOR_BOOTSTRAP, {
155
+ prefixes: contentPrefixes(entry),
156
+ after,
157
+ });
158
+ const failure = classifyDoor(answered.status, answered.body, entry.locator);
159
+ if (failure !== null)
160
+ return failure;
161
+ const envelope = parseEnvelope(answered.body);
162
+ if (envelope === null)
163
+ return UNCERTAIN_READ;
164
+ const scope = envelope.scopes.find((candidate) => matchesScope(candidate, entry));
165
+ return bootstrappedRoom(envelope, scope, entry, continued);
147
166
  }
148
167
  function layered(asks) {
149
168
  const depths = new Map();
@@ -190,7 +209,7 @@ export function createAgentsHouseAdapter(options) {
190
209
  }
191
210
  return asks.map((ask) => answers.get(ask) ?? UNCERTAIN_READ);
192
211
  }
193
- const bootstrapTogether = gathered(bootstrapped);
212
+ const bootstrapTogether = gatheredEach(bootstrapped);
194
213
  const enumerateTogether = gathered(enumerated);
195
214
  async function uploaded(head, changes, delta, bytes, entry, handed, keep) {
196
215
  const paths = batchPaths(changes);
@@ -207,9 +226,7 @@ export function createAgentsHouseAdapter(options) {
207
226
  return { outcome: UNCERTAIN };
208
227
  const delivered = await transport.transfer({
209
228
  act: 'authored_batch_upload',
210
- method: 'POST',
211
229
  url: grant.url,
212
- answer: 'json',
213
230
  body: `${grant.operation}\n${delta}`,
214
231
  });
215
232
  if (delivered.status !== 200)
@@ -221,7 +238,30 @@ export function createAgentsHouseAdapter(options) {
221
238
  await keep(upload);
222
239
  return { body: { ...head, paths, upload, runtime: notifications.runtime } };
223
240
  }
224
- async function submit(head, changes, delta, bytes, entry, handed, keep) {
241
+ async function staged(answer, batch) {
242
+ const refusal = doorRefusal(answer.body);
243
+ if (refusal?.code !== 'files_unstaged')
244
+ return null;
245
+ const grants = refusal.fields.upload;
246
+ if (!Array.isArray(grants))
247
+ return false;
248
+ for (const grant of grants) {
249
+ const { url, operation, sha256 } = grant;
250
+ const change = batch.changes.find((held) => held.kind === 'binary' && held.sha256 === sha256);
251
+ if (typeof url !== 'string' || typeof operation !== 'string' || change === undefined)
252
+ return false;
253
+ const delivered = await transport.transfer({
254
+ act: 'binary_stage',
255
+ url,
256
+ body: change.blob,
257
+ operation,
258
+ });
259
+ if (delivered.status !== 200)
260
+ return false;
261
+ }
262
+ return true;
263
+ }
264
+ async function submit(batch, head, changes, delta, bytes, entry, handed, keep) {
225
265
  const inline = { ...head, changes, runtime: notifications.runtime };
226
266
  const prepared = uploadable(inline, bytes, declared())
227
267
  ? await uploaded(head, changes, delta, bytes, entry, handed, keep)
@@ -229,7 +269,33 @@ export function createAgentsHouseAdapter(options) {
229
269
  if ('outcome' in prepared)
230
270
  return prepared.outcome;
231
271
  const answer = await transport.door(DOOR_BATCH, prepared.body);
232
- return mutationOutcome(answer.status, answer.body, entry.locator, entry.handle);
272
+ const stagedFiles = await staged(answer, batch);
273
+ if (stagedFiles === false)
274
+ return UNCERTAIN;
275
+ const settled = stagedFiles === null ? answer : await transport.door(DOOR_BATCH, prepared.body);
276
+ if (stagedFiles === true && (await staged(settled, batch)) !== null)
277
+ return UNCERTAIN;
278
+ return mutationOutcome(settled.status, settled.body, entry.locator, entry.handle);
279
+ }
280
+ async function downloaded(answer, locator) {
281
+ const failure = classifyDoor(answer.status, answer.body, locator);
282
+ if (failure !== null) {
283
+ return failure.kind === 'scoped-refusal'
284
+ ? {
285
+ kind: 'rejected',
286
+ code: failure.code,
287
+ fields: failure.fields,
288
+ retryable: failure.retryable,
289
+ }
290
+ : failure;
291
+ }
292
+ const grant = parseGrant(answer.body);
293
+ if (grant === null || grant.method !== 'GET')
294
+ return UNCERTAIN_READ;
295
+ const read = await transport.download(grant.url);
296
+ if (read.status !== 200 || read.blob === null)
297
+ return UNCERTAIN_READ;
298
+ return { kind: 'binary', blob: read.blob };
233
299
  }
234
300
  return {
235
301
  async authorize() {
@@ -252,14 +318,18 @@ export function createAgentsHouseAdapter(options) {
252
318
  if (!tracked.has(locator))
253
319
  handed.delete(locator);
254
320
  notifications.track(entries);
255
- return mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document));
321
+ return {
322
+ ...mapDiscovery(document, document.authorities.map((authority) => discoveredRoom(authority)), capabilities(document)),
323
+ member: document.member,
324
+ };
256
325
  },
257
326
  async bootstrap(_authorization, request) {
258
327
  const entry = authorityFor(request.locator);
259
328
  if (entry === undefined)
260
329
  return { kind: 'room-not-readable', locator: request.locator };
261
- if (request.pageToken !== undefined)
262
- return { kind: 'transport-uncertainty' };
330
+ if (request.pageToken !== undefined) {
331
+ return continuedBootstrap(entry, JSON.parse(request.pageToken));
332
+ }
263
333
  return bootstrapTogether(entry);
264
334
  },
265
335
  async refresh(_authorization, request) {
@@ -287,10 +357,11 @@ export function createAgentsHouseAdapter(options) {
287
357
  const delta = deltaBody(mapped.changes);
288
358
  const bytes = deltaBytes(delta);
289
359
  const handed = request.upload;
290
- const outcome = await submit(head, mapped.changes, delta, bytes, entry, handed, keep);
360
+ const batch = request.changeBatch;
361
+ const outcome = await submit(batch, head, mapped.changes, delta, bytes, entry, handed, keep);
291
362
  if (handed === undefined || !lapsedGrant(outcome))
292
363
  return adopted(entry, outcome);
293
- return adopted(entry, await submit(head, mapped.changes, delta, bytes, entry, undefined, keep));
364
+ return adopted(entry, await submit(batch, head, mapped.changes, delta, bytes, entry, undefined, keep));
294
365
  },
295
366
  async history(_authorization, request) {
296
367
  const entry = authorityFor(request.locator);
@@ -307,6 +378,37 @@ export function createAgentsHouseAdapter(options) {
307
378
  ...(request.revision === undefined ? {} : { revision: request.revision }),
308
379
  });
309
380
  },
381
+ async binary(_authorization, request) {
382
+ if (request.kind === 'path') {
383
+ const entry = authorityFor(request.locator);
384
+ if (entry === undefined)
385
+ return { kind: 'room-not-readable', locator: request.locator };
386
+ const answer = await transport.door(DOOR_FILES_GET, {
387
+ room_ref: entry.authority,
388
+ path: request.path,
389
+ revision: request.revision,
390
+ });
391
+ return downloaded(answer, request.locator);
392
+ }
393
+ const referrer = houseReferrer(request.referrer, tracked);
394
+ if (referrer === null) {
395
+ return { kind: 'rejected', code: 'referrer_unknown', fields: {}, retryable: false };
396
+ }
397
+ const answer = await transport.door(DOOR_FILES_GET, {
398
+ file: request.fileRef,
399
+ referrer: referrer.referrer,
400
+ });
401
+ return downloaded(answer, referrer.locator);
402
+ },
403
+ referrerScope(referrer) {
404
+ const held = houseReferrer(referrer, tracked);
405
+ if (held === null)
406
+ return null;
407
+ if (held.locator === '')
408
+ return { kind: 'conversations' };
409
+ const { path } = held.referrer;
410
+ return { kind: 'room', locator: held.locator, ...(path === undefined ? {} : { path }) };
411
+ },
310
412
  reached(locator, version, target) {
311
413
  return reachedVersion(version, target, authorityFor(locator)?.logEpoch);
312
414
  },
@@ -1,4 +1,4 @@
1
- import type { Capability, DiscoveredRoom, Discovery, ProviderLimit, Retention } from '@agentshouse/mdruntime';
1
+ import type { Capability, DiscoveredRoom, Discovery, Member, ProviderLimit, Retention } from '@agentshouse/mdruntime';
2
2
  import { type LogPosition } from './version.js';
3
3
  export declare const PROVIDER_ACTIONS = "provider-actions";
4
4
  export declare const DISCOVER_PREFIXES: readonly string[];
@@ -37,6 +37,7 @@ export type HouseAuthority = LogPosition & {
37
37
  operations: HouseOperations;
38
38
  };
39
39
  export type HouseDiscoveryDocument = {
40
+ member: Member;
40
41
  bounds: HouseBounds;
41
42
  authorities: readonly HouseAuthority[];
42
43
  actions: readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
package/dist/discovery.js CHANGED
@@ -1,4 +1,4 @@
1
- import { declaredActions, houseConversationAgents } from './actions.js';
1
+ import { declaredActions, houseConversationAgents, SITE_SUBMIT } from './actions.js';
2
2
  import { readPosition, roomVersion } from './version.js';
3
3
  export const PROVIDER_ACTIONS = 'provider-actions';
4
4
  export const DISCOVER_PREFIXES = ['/'];
@@ -46,6 +46,14 @@ function parseHouseModel(value) {
46
46
  return undefined;
47
47
  return { root: held.root, paths };
48
48
  }
49
+ function parseMember(value) {
50
+ if (typeof value !== 'object' || value === null)
51
+ return null;
52
+ const { user, name } = value;
53
+ if (typeof user !== 'string' || typeof name !== 'string')
54
+ return null;
55
+ return { kind: 'user', id: user, name };
56
+ }
49
57
  function parseOperations(value) {
50
58
  if (typeof value !== 'object' || value === null)
51
59
  return null;
@@ -98,6 +106,9 @@ export function parseDiscovery(body) {
98
106
  if (typeof body !== 'object' || body === null)
99
107
  return null;
100
108
  const held = body;
109
+ const member = parseMember(held.member);
110
+ if (member === null)
111
+ return null;
101
112
  const bounds = parseBounds(held.bounds);
102
113
  if (bounds === null)
103
114
  return null;
@@ -115,7 +126,7 @@ export function parseDiscovery(body) {
115
126
  return null;
116
127
  authorities.push(authority);
117
128
  }
118
- return { bounds, authorities, actions };
129
+ return { member, bounds, authorities, actions };
119
130
  }
120
131
  function parseSiteAuthority(value) {
121
132
  if (typeof value !== 'object' || value === null)
@@ -218,7 +229,10 @@ export function capabilities(document) {
218
229
  }
219
230
  export function siteCapabilities() {
220
231
  return [
221
- { name: PROVIDER_ACTIONS, actions: [{ name: 'submit', inputShape: {}, resultKind: 'house' }] },
232
+ {
233
+ name: PROVIDER_ACTIONS,
234
+ actions: [{ name: SITE_SUBMIT, inputShape: {}, resultKind: 'house' }],
235
+ },
222
236
  ];
223
237
  }
224
238
  export function discoveredRoom(authority) {
package/dist/gather.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export declare function gatheredEach<A, R>(send: (asks: readonly A[], answer: (ask: number, result: R) => void) => Promise<void>): (ask: A) => Promise<R>;
1
2
  export declare function gathered<A, R>(send: (asks: readonly A[]) => Promise<readonly R[]>): (ask: A) => Promise<R>;
2
3
  export declare function selections<T>(items: readonly T[], weight: (item: T) => number, limit: number): readonly (readonly T[])[];
3
4
  //# sourceMappingURL=gather.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../src/gather.ts"],"names":[],"mappings":"AAMA,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAC3B,IAAI,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,KAAK,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,GAClD,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CA0BxB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAC1B,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAC3B,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAgB3B"}
1
+ {"version":3,"file":"gather.d.ts","sourceRoot":"","sources":["../src/gather.ts"],"names":[],"mappings":"AAMA,wBAAgB,YAAY,CAAC,CAAC,EAAE,CAAC,EAC/B,IAAI,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,GACpF,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAwBxB;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,EAC3B,IAAI,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,KAAK,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,GAClD,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAMxB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAC1B,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,EAC3B,KAAK,EAAE,MAAM,GACZ,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAgB3B"}
package/dist/gather.js CHANGED
@@ -1,13 +1,11 @@
1
- export function gathered(send) {
1
+ export function gatheredEach(send) {
2
2
  let held = [];
3
3
  function flush() {
4
4
  const taken = held;
5
5
  held = [];
6
- send(taken.map((entry) => entry.ask)).then((answers) => {
7
- taken.forEach((entry, index) => {
8
- entry.resolve(answers[index]);
9
- });
10
- }, (reason) => {
6
+ send(taken.map((entry) => entry.ask), (ask, result) => {
7
+ taken[ask]?.resolve(result);
8
+ }).catch((reason) => {
11
9
  for (const entry of taken)
12
10
  entry.reject(reason);
13
11
  });
@@ -20,6 +18,13 @@ export function gathered(send) {
20
18
  held.push({ ask, resolve, reject });
21
19
  });
22
20
  }
21
+ export function gathered(send) {
22
+ return gatheredEach(async (asks, answer) => {
23
+ (await send(asks)).forEach((result, ask) => {
24
+ answer(ask, result);
25
+ });
26
+ });
27
+ }
23
28
  export function selections(items, weight, limit) {
24
29
  const parts = [];
25
30
  let part = [];
@@ -0,0 +1,15 @@
1
+ import type { HeldRoom, MutationResult } from '@agentshouse/mdruntime';
2
+ import type { HouseScope, HouseView } from './read.js';
3
+ import type { StreamedAdvancement } from './stream.js';
4
+ export type HandedRoom = {
5
+ roomVersion: string;
6
+ revisions: ReadonlyMap<string, string>;
7
+ };
8
+ export declare function scopeHanded(scope: HouseScope): HandedRoom;
9
+ export declare function heldHanded(held: HeldRoom): HandedRoom;
10
+ export declare function acceptedHanded(held: HandedRoom, accepted: Extract<MutationResult, {
11
+ kind: 'accepted';
12
+ }>, roomVersion: string): HandedRoom;
13
+ export declare function enumeratedHanded(view: HouseView, earlier: HandedRoom | undefined): HandedRoom;
14
+ export declare function streamedHanded(held: HandedRoom, advanced: StreamedAdvancement): HandedRoom;
15
+ //# sourceMappingURL=handed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handed.d.ts","sourceRoot":"","sources":["../src/handed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CASzD;AAOD,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAErD;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,EACvD,WAAW,EAAE,MAAM,GAClB,UAAU,CAKZ;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,GAAG,SAAS,GAAG,UAAU,CAM7F;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,mBAAmB,GAAG,UAAU,CAM1F"}
package/dist/handed.js ADDED
@@ -0,0 +1,38 @@
1
+ import { roomVersion } from './version.js';
2
+ export function scopeHanded(scope) {
3
+ return {
4
+ roomVersion: roomVersion(scope),
5
+ revisions: new Map(scope.files.flatMap(({ path, revision }) => revision === undefined ? [] : [[path, revision]])),
6
+ };
7
+ }
8
+ function revised(revisions, path, revision) {
9
+ if (revision === undefined)
10
+ revisions.delete(path);
11
+ else
12
+ revisions.set(path, revision);
13
+ }
14
+ export function heldHanded(held) {
15
+ return { roomVersion: held.roomVersion, revisions: new Map(Object.entries(held.revisions)) };
16
+ }
17
+ export function acceptedHanded(held, accepted, roomVersion) {
18
+ const revisions = new Map(held.revisions);
19
+ for (const [path, revision] of Object.entries(accepted.revisions))
20
+ revisions.set(path, revision);
21
+ for (const path of accepted.removals)
22
+ revisions.delete(path);
23
+ return { roomVersion, revisions };
24
+ }
25
+ export function enumeratedHanded(view, earlier) {
26
+ const revisions = new Map(earlier?.revisions);
27
+ for (const change of view.changes) {
28
+ revised(revisions, change.path, 'removed' in change ? undefined : change.revision);
29
+ }
30
+ return { roomVersion: roomVersion(view), revisions };
31
+ }
32
+ export function streamedHanded(held, advanced) {
33
+ const revisions = new Map(held.revisions);
34
+ for (const entry of advanced.entries) {
35
+ revised(revisions, entry.path, entry.kind === 'removed' ? undefined : entry.revision);
36
+ }
37
+ return { roomVersion: advanced.page.roomVersion, revisions };
38
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { createAgentsHouseAdapter, type AgentsHouseAdapterOptions } from './adapter.js';
2
- export type { HouseByteAct, HouseByteAnswer, HouseByteTransfer, HouseDoorAnswer, HouseHeldRoom, HouseOpening, HouseStream, HouseStreamEntry, HouseStreamFrame, HouseSiteTransport, HouseTransport, } from './transport.js';
2
+ export { HOUSE_APP_ACTS, HOUSE_APP_BATCHES, HOUSE_SITE_ACTS } from './actions.js';
3
+ export type { HouseByteAct, HouseByteTransfer, HouseBytesAnswer, HouseDoorAnswer, HouseHeldRoom, HouseOpening, HouseStream, HouseStreamEntry, HouseStreamFrame, HouseSiteTransport, HouseTransport, } from './transport.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,KAAK,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACxF,YAAY,EACV,YAAY,EACZ,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,GACf,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,KAAK,yBAAyB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAClF,YAAY,EACV,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,GACf,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
1
  export { createAgentsHouseAdapter } from './adapter.js';
2
+ export { HOUSE_APP_ACTS, HOUSE_APP_BATCHES, HOUSE_SITE_ACTS } from './actions.js';
package/dist/model.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { RoomModels } from '@agentshouse/mdruntime';
2
2
  import type { TrackedAuthority } from './discovery.js';
3
3
  import { type HouseScope, type HouseView } from './read.js';
4
4
  import type { HouseMode, HouseStreamEntry } from './transport.js';
5
- export declare function scopeModels(scope: HouseScope, tracked: TrackedAuthority): Promise<RoomModels | undefined>;
5
+ export declare function partModels(scope: HouseScope, tracked: TrackedAuthority, seen: ReadonlySet<string>, final: boolean): Promise<RoomModels | undefined>;
6
6
  export declare function viewModels(view: HouseView, tracked: TrackedAuthority): Promise<RoomModels | undefined>;
7
7
  export declare function streamedModels(schemas: ReadonlyMap<string, HouseStreamEntry>, tracked: TrackedAuthority, mode: HouseMode): Promise<RoomModels | undefined>;
8
8
  //# sourceMappingURL=model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAA0C,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAoClE,wBAAgB,WAAW,CACzB,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAEjC;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAcjC;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAC9C,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAWjC"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAA0C,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACpG,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAoClE,wBAAgB,UAAU,CACxB,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EACzB,KAAK,EAAE,OAAO,GACb,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAKjC;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAcjC;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAC9C,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAWjC"}
package/dist/model.js CHANGED
@@ -26,8 +26,12 @@ async function modelsOf(tracked, read) {
26
26
  }
27
27
  return models.collection === undefined && models.selection === undefined ? undefined : models;
28
28
  }
29
- export function scopeModels(scope, tracked) {
30
- return modelsOf(tracked, (schema) => schemaOf(scope, schema));
29
+ export function partModels(scope, tracked, seen, final) {
30
+ return modelsOf(tracked, (schema) => {
31
+ if (scope.files.some((file) => file.path === schema))
32
+ return schemaOf(scope, schema);
33
+ return final && !seen.has(schema) ? ABSENT_SCHEMA : undefined;
34
+ });
31
35
  }
32
36
  export function viewModels(view, tracked) {
33
37
  return modelsOf(tracked, (schema) => {