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

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 (75) hide show
  1. package/README.md +2 -2
  2. package/dist/actions.d.ts +4 -65
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +8 -347
  5. package/dist/adapter.d.ts +1 -0
  6. package/dist/adapter.d.ts.map +1 -1
  7. package/dist/adapter.js +245 -277
  8. package/dist/app-reference.d.ts +2 -0
  9. package/dist/app-reference.d.ts.map +1 -0
  10. package/dist/app-reference.js +2 -0
  11. package/dist/chunks.d.ts +38 -0
  12. package/dist/chunks.d.ts.map +1 -0
  13. package/dist/chunks.js +247 -0
  14. package/dist/crockford.d.ts +4 -0
  15. package/dist/crockford.d.ts.map +1 -0
  16. package/dist/crockford.js +3 -0
  17. package/dist/discovery.d.ts +23 -14
  18. package/dist/discovery.d.ts.map +1 -1
  19. package/dist/discovery.js +92 -54
  20. package/dist/history.d.ts +12 -0
  21. package/dist/history.d.ts.map +1 -0
  22. package/dist/history.js +92 -0
  23. package/dist/house-model.d.ts +672 -0
  24. package/dist/house-model.d.ts.map +1 -0
  25. package/dist/house-model.js +377 -0
  26. package/dist/index.d.ts +11 -2
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +10 -1
  29. package/dist/model.d.ts +5 -5
  30. package/dist/model.d.ts.map +1 -1
  31. package/dist/model.js +33 -43
  32. package/dist/read.d.ts +59 -44
  33. package/dist/read.d.ts.map +1 -1
  34. package/dist/read.js +158 -236
  35. package/dist/refusal.d.ts +0 -3
  36. package/dist/refusal.d.ts.map +1 -1
  37. package/dist/refusal.js +2 -6
  38. package/dist/room-types.d.ts +7 -0
  39. package/dist/room-types.d.ts.map +1 -0
  40. package/dist/room-types.js +123 -0
  41. package/dist/search.d.ts +5 -0
  42. package/dist/search.d.ts.map +1 -0
  43. package/dist/search.js +47 -0
  44. package/dist/site.d.ts +1 -1
  45. package/dist/site.d.ts.map +1 -1
  46. package/dist/site.js +108 -131
  47. package/dist/space-schema.d.ts +7 -0
  48. package/dist/space-schema.d.ts.map +1 -0
  49. package/dist/space-schema.js +18 -0
  50. package/dist/stream.d.ts +15 -13
  51. package/dist/stream.d.ts.map +1 -1
  52. package/dist/stream.js +275 -159
  53. package/dist/transport.d.ts +81 -25
  54. package/dist/transport.d.ts.map +1 -1
  55. package/dist/transport.js +54 -11
  56. package/dist/upload.d.ts +12 -0
  57. package/dist/upload.d.ts.map +1 -0
  58. package/dist/upload.js +63 -0
  59. package/dist/version.d.ts +1 -0
  60. package/dist/version.d.ts.map +1 -1
  61. package/dist/version.js +1 -1
  62. package/dist/write.d.ts +18 -2
  63. package/dist/write.d.ts.map +1 -1
  64. package/dist/write.js +105 -71
  65. package/package.json +8 -4
  66. package/AGENTS.md +0 -302
  67. package/dist/gather.d.ts +0 -4
  68. package/dist/gather.d.ts.map +0 -1
  69. package/dist/gather.js +0 -45
  70. package/dist/handed.d.ts +0 -15
  71. package/dist/handed.d.ts.map +0 -1
  72. package/dist/handed.js +0 -38
  73. package/dist/referrer.d.ts +0 -7
  74. package/dist/referrer.d.ts.map +0 -1
  75. package/dist/referrer.js +0 -35
package/dist/stream.js CHANGED
@@ -1,47 +1,125 @@
1
- import { acceptedMessage } from './actions.js';
2
- import { binaryFileOf, headChange } from './read.js';
3
- import { roomVersion } from './version.js';
4
- const HELD_FRAMES_MAX = 256;
1
+ import { ROW_WEIGHT, stepped, } from '@agentshouse/mdruntime';
2
+ import { acceptedMessage, cursorPosition, houseHistory } from './history.js';
3
+ import { keptSpaceSchemas, streamedModels } from './model.js';
4
+ import { answered, answering, binaryFileOf, createdOf, folded, forgotten, headChange, revised, } from './read.js';
5
+ import { houseDoorRoute, } from './transport.js';
6
+ import { DECIMAL, logPosition, presented, roomVersion } from './version.js';
5
7
  function turnOperation(frame) {
6
8
  const { type: _type, conversation_id: _conversation, turn_id: _turn, ...operation } = frame;
7
9
  return structuredClone(operation);
8
10
  }
11
+ async function houseAgents(transport) {
12
+ const answer = await transport.door(houseDoorRoute('agents/list'), {});
13
+ const agents = answer.status === 200 ? answer.body?.agents : null;
14
+ if (!Array.isArray(agents))
15
+ return null;
16
+ return agents.flatMap((one) => {
17
+ const { id, name, retired_at: retired } = (one ?? {});
18
+ return typeof id === 'string' && typeof name === 'string'
19
+ ? [{ agent: id, name, retired: retired !== null && retired !== undefined }]
20
+ : [];
21
+ });
22
+ }
9
23
  function listedConversation(listed) {
10
24
  return {
11
25
  conversation: listed.conversation_id,
12
26
  agent: listed.agent_id,
27
+ agentName: listed.agent_name,
28
+ agentRetired: listed.agent_retired,
13
29
  name: listed.name,
14
30
  created: listed.created_at,
15
31
  finished: listed.finished_at,
16
32
  outcome: listed.outcome,
33
+ waiting: listed.waiting,
34
+ newest: listed.newest === null ? null : cursorPosition(listed.newest),
35
+ processEnded: listed.process_ended_at,
17
36
  };
18
37
  }
19
38
  function position(value) {
20
- if (!/^(?:0|[1-9][0-9]*)$/.test(value))
39
+ if (!DECIMAL.test(value))
21
40
  return null;
22
41
  return BigInt(value);
23
42
  }
24
- export function houseNotifications(transport, mode) {
43
+ function* changed(tracked, entries, version, schemas) {
44
+ const answer = answering();
45
+ for (const entry of entries) {
46
+ yield ROW_WEIGHT + (entry.text?.length ?? 0);
47
+ if (entry.kind === 'folder') {
48
+ folded(answer, entry.path, entry.removed === true);
49
+ continue;
50
+ }
51
+ if (entry.path === tracked.schema)
52
+ schemas.set(entry.path, entry);
53
+ forgotten(answer, entry.path);
54
+ if (entry.space !== undefined) {
55
+ answer.removals.add(entry.path);
56
+ continue;
57
+ }
58
+ if (entry.kind === 'removed') {
59
+ answer.removals.add(entry.path);
60
+ continue;
61
+ }
62
+ const binary = binaryFileOf(entry);
63
+ if (binary === undefined)
64
+ answer.documents.set(entry.path, entry.text ?? '');
65
+ else if (binary !== null)
66
+ answer.binaryFiles.set(entry.path, binary);
67
+ if (binary === undefined && entry.facts !== undefined)
68
+ answer.facts.set(entry.path, entry.facts);
69
+ const revision = entry.revision ?? binary?.sha256;
70
+ if (revision !== undefined)
71
+ revised(answer, entry.path, revision);
72
+ const head = headChange(entry);
73
+ if (head)
74
+ answer.changes.set(entry.path, head);
75
+ const created = createdOf(entry);
76
+ if (created)
77
+ answer.created.set(entry.path, created);
78
+ }
79
+ return { kind: 'net-advancement', roomVersion: version, ...(yield* answered(answer)) };
80
+ }
81
+ async function changePage(tracked, entries, version, mode, spaces, whole) {
82
+ const schemas = new Map();
83
+ const page = await stepped(changed(tracked, entries, version, schemas));
84
+ const models = await streamedModels(schemas, tracked, mode, spaces, whole);
85
+ return models === undefined ? page : { ...page, models };
86
+ }
87
+ export function houseNotifications(transport, mode, discovering, spaces) {
25
88
  const stream = transport.stream;
26
- const lines = new Map();
27
- const locators = new Map();
89
+ const staged = new Map();
90
+ let socket = null;
91
+ const tracking = new Map();
28
92
  const observers = new Set();
93
+ const replaying = new Map();
29
94
  const conversationObservers = new Set();
30
95
  const modeObservers = new Set();
31
96
  let replicated = [];
97
+ let listedCursor = null;
98
+ const unanswered = [];
99
+ const heldAtZero = new Set();
32
100
  const live = new Set();
33
101
  let opening = null;
102
+ let announced = null;
34
103
  const runtime = crypto.randomUUID();
35
104
  function emit(event) {
36
- for (const observer of observers)
37
- observer(event);
105
+ for (const observer of observers) {
106
+ const held = replaying.get(observer);
107
+ if (held === undefined)
108
+ observer(event);
109
+ else
110
+ held.push(event);
111
+ }
38
112
  }
39
113
  function emitConversation(event) {
40
114
  if (event.kind === 'turn' ||
41
115
  event.kind === 'questions' ||
42
116
  event.kind === 'process' ||
43
117
  event.kind === 'commands' ||
44
- event.kind === 'options') {
118
+ event.kind === 'options' ||
119
+ event.kind === 'starting' ||
120
+ event.kind === 'subagents' ||
121
+ event.kind === 'link' ||
122
+ event.kind === 'deliveries') {
45
123
  live.add(event.conversation);
46
124
  }
47
125
  for (const observer of conversationObservers)
@@ -49,11 +127,33 @@ export function houseNotifications(transport, mode) {
49
127
  }
50
128
  function reopened(next) {
51
129
  opening = next;
130
+ announced = null;
131
+ socket = next;
132
+ staged.clear();
133
+ unanswered.length = 0;
134
+ heldAtZero.clear();
52
135
  const gapped = new Set([...replicated, ...live]);
53
136
  live.clear();
54
137
  for (const conversation of gapped)
55
138
  emitConversation({ kind: 'gap', conversation });
56
139
  emit({ kind: 'opened' });
140
+ if (mode === 'site')
141
+ announce(next, null);
142
+ }
143
+ function announce(via, frame) {
144
+ void discovering.opened(frame).then((discovery) => {
145
+ if (socket !== via)
146
+ return;
147
+ if (discovery === null) {
148
+ via.close();
149
+ return;
150
+ }
151
+ announced = { kind: 'discovered', discovery };
152
+ emit(announced);
153
+ }, () => {
154
+ if (socket === via)
155
+ via.close();
156
+ });
57
157
  }
58
158
  function converse(frame) {
59
159
  const conversation = frame.conversation_id;
@@ -72,6 +172,7 @@ export function houseNotifications(transport, mode) {
72
172
  return;
73
173
  emitConversation({ kind: 'commands', conversation, commands: [] });
74
174
  emitConversation({ kind: 'options', conversation, options: [] });
175
+ emitConversation({ kind: 'subagents', conversation, subagents: [] });
75
176
  return;
76
177
  }
77
178
  if (frame.type === 'commands') {
@@ -86,6 +187,26 @@ export function houseNotifications(transport, mode) {
86
187
  emitConversation({ kind: 'options', conversation, options: structuredClone(frame.options) });
87
188
  return;
88
189
  }
190
+ if (frame.type === 'starting') {
191
+ emitConversation({ kind: 'starting', conversation, step: frame.step });
192
+ return;
193
+ }
194
+ if (frame.type === 'subagents') {
195
+ emitConversation({
196
+ kind: 'subagents',
197
+ conversation,
198
+ subagents: structuredClone(frame.subagents),
199
+ });
200
+ return;
201
+ }
202
+ if (frame.type === 'link') {
203
+ emitConversation({ kind: 'link', conversation, connected: frame.connected });
204
+ return;
205
+ }
206
+ if (frame.type === 'deliveries') {
207
+ emitConversation({ kind: 'deliveries', conversation, unknown: [...frame.unknown] });
208
+ return;
209
+ }
89
210
  if (frame.type === 'interactions') {
90
211
  emitConversation({
91
212
  kind: 'questions',
@@ -99,18 +220,33 @@ export function houseNotifications(transport, mode) {
99
220
  return;
100
221
  emitConversation({ kind: 'accepted-message', conversation, message });
101
222
  }
102
- function announce(authority, at) {
103
- const version = roomVersion(at);
104
- for (const locator of locators.get(authority) ?? []) {
105
- emit({ kind: 'room-version', locator, roomVersion: version });
223
+ function stage(frame, via) {
224
+ const held = staged.get(frame.carry);
225
+ if (frame.index !== (held?.parts ?? 0)) {
226
+ staged.delete(frame.carry);
227
+ return;
228
+ }
229
+ if (held === undefined) {
230
+ for (const [carry, other] of staged) {
231
+ if (other.authority === frame.authority)
232
+ staged.delete(carry);
233
+ }
106
234
  }
235
+ const next = held ?? { authority: frame.authority, parts: 0, entries: [] };
236
+ keptSpaceSchemas(frame.entries, spaces);
237
+ next.entries.push(...frame.entries);
238
+ next.parts += 1;
239
+ staged.set(frame.carry, next);
240
+ via?.received(frame.authority, frame.carry, frame.index);
107
241
  }
108
- function interrupt(authority) {
109
- const line = lines.get(authority);
110
- if (line !== undefined)
111
- lines.set(authority, { ...line, frames: [] });
242
+ function carried(frame) {
243
+ const held = staged.get(frame.carry);
244
+ staged.delete(frame.carry);
245
+ if ((held?.parts ?? 0) !== frame.parts)
246
+ return;
247
+ publish(frame, held?.entries ?? []);
112
248
  }
113
- function receive(frame) {
249
+ function handle(frame, via) {
114
250
  if (frame.type === 'signal') {
115
251
  const mode = frame.service_mode;
116
252
  if (mode !== 'open' && mode !== 'write-halted')
@@ -120,14 +256,35 @@ export function houseNotifications(transport, mode) {
120
256
  return;
121
257
  }
122
258
  if (frame.type === 'opening') {
259
+ if (via !== null && mode === 'credential')
260
+ announce(via, frame);
261
+ return;
262
+ }
263
+ if (frame.type === 'caught_up') {
264
+ discovering.expired?.(frame.expired);
123
265
  emit({
124
- kind: 'opening',
125
- expired: frame.expired.flatMap((authority) => locators.get(authority) ?? []),
266
+ kind: 'caught-up',
267
+ expired: [
268
+ ...frame.expired.flatMap((authority) => (tracking.get(authority) ?? []).map((tracked) => tracked.locator)),
269
+ ...(unanswered.shift() ?? []),
270
+ ],
126
271
  });
127
272
  return;
128
273
  }
274
+ if (frame.type === 'authority_changed') {
275
+ const change = discovering.changed(frame);
276
+ if (change !== null)
277
+ emit(change);
278
+ return;
279
+ }
129
280
  if (frame.type === 'conversations') {
130
- emitConversation({ kind: 'list', entries: frame.conversations.map(listedConversation) });
281
+ emitConversation({
282
+ kind: 'list',
283
+ entries: frame.conversations.map(listedConversation),
284
+ whole: frame.whole,
285
+ more: frame.more,
286
+ cursor: frame.cursor,
287
+ });
131
288
  return;
132
289
  }
133
290
  if (frame.type === 'conversation') {
@@ -142,40 +299,49 @@ export function houseNotifications(transport, mode) {
142
299
  frame.type === 'process' ||
143
300
  frame.type === 'commands' ||
144
301
  frame.type === 'options' ||
302
+ frame.type === 'starting' ||
303
+ frame.type === 'subagents' ||
304
+ frame.type === 'link' ||
305
+ frame.type === 'deliveries' ||
145
306
  frame.type === 'interactions' ||
146
307
  frame.type === 'message') {
147
308
  converse(frame);
148
309
  return;
149
310
  }
150
- if (frame.type !== 'entries')
151
- return;
311
+ if (frame.type === 'part')
312
+ stage(frame, via);
313
+ else if (frame.type === 'carried')
314
+ carried(frame);
315
+ }
316
+ function publish(frame, entries) {
152
317
  const at = position(frame.position);
153
318
  const after = position(frame.after);
154
- if (at === null || after === null || after >= at) {
155
- interrupt(frame.authority);
319
+ if (at === null || after === null || after >= at)
156
320
  return;
321
+ const from = after === 0n && !heldAtZero.has(frame.authority)
322
+ ? null
323
+ : roomVersion({ position: frame.after, logEpoch: frame.log_epoch });
324
+ const version = roomVersion({ position: frame.position, logEpoch: frame.log_epoch });
325
+ for (const tracked of tracking.get(frame.authority) ?? []) {
326
+ emit({
327
+ kind: 'room-change',
328
+ locator: tracked.locator,
329
+ from,
330
+ roomVersion: version,
331
+ read: () => changePage(tracked, entries, version, mode, spaces, from === null),
332
+ });
157
333
  }
158
- const line = lines.get(frame.authority);
159
- if (line?.logEpoch === frame.log_epoch) {
160
- if (line.held !== null && at <= line.held)
161
- return;
162
- const last = line.frames.at(-1);
163
- if (last !== undefined && at <= last.position)
164
- return;
165
- const held = { after, position: at, entries: frame.entries };
166
- const next = last !== undefined && after <= last.position ? [...line.frames, held] : [held];
167
- lines.set(frame.authority, { ...line, frames: next.length > HELD_FRAMES_MAX ? [] : next });
168
- }
169
- else {
170
- interrupt(frame.authority);
171
- }
172
- announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });
173
334
  }
174
- stream.observe(receive);
335
+ stream.observe((frame) => handle(frame, socket));
175
336
  stream.opened(reopened);
176
- stream.closed((revoked) => {
337
+ stream.closed(({ revoked, lost, authorityChanged }) => {
177
338
  opening = null;
178
- emit({ kind: 'closed', revoked });
339
+ announced = null;
340
+ socket = null;
341
+ staged.clear();
342
+ unanswered.length = 0;
343
+ heldAtZero.clear();
344
+ emit({ kind: 'closed', revoked, lost, authorityChanged });
179
345
  });
180
346
  return {
181
347
  runtime,
@@ -191,19 +357,34 @@ export function houseNotifications(transport, mode) {
191
357
  replicate(next) {
192
358
  replicated = [...next];
193
359
  },
360
+ hold(cursor) {
361
+ listedCursor = cursor;
362
+ },
194
363
  observe(notify) {
195
364
  conversationObservers.add(notify);
196
365
  return () => {
197
366
  conversationObservers.delete(notify);
198
367
  };
199
368
  },
369
+ ...(mode === 'credential'
370
+ ? {
371
+ agents: () => houseAgents(transport),
372
+ history: (request) => houseHistory(transport, request),
373
+ }
374
+ : {}),
200
375
  },
201
376
  observe(notify) {
202
377
  observers.add(notify);
203
378
  if (opening !== null) {
379
+ const replayed = [{ kind: 'opened' }];
380
+ if (announced !== null)
381
+ replayed.push(announced);
382
+ replaying.set(notify, replayed);
204
383
  queueMicrotask(() => {
205
- if (observers.has(notify))
206
- notify({ kind: 'opened' });
384
+ replaying.delete(notify);
385
+ for (const event of replayed)
386
+ if (observers.has(notify))
387
+ notify(event);
207
388
  });
208
389
  }
209
390
  return () => {
@@ -211,124 +392,59 @@ export function houseNotifications(transport, mode) {
211
392
  };
212
393
  },
213
394
  send(rooms) {
214
- for (const room of rooms) {
215
- const line = lines.get(room.authority);
216
- const held = position(room.position);
217
- if (line === undefined || held === null || line.logEpoch !== room.log_epoch)
218
- continue;
219
- lines.set(room.authority, { ...line, frames: [], held });
220
- }
221
- const current = opening;
222
- opening = null;
223
- current?.hold(rooms, runtime);
224
- },
225
- reopen() {
226
- const current = opening;
227
395
  opening = null;
228
- current?.close();
229
- },
230
- track(entries) {
231
- locators.clear();
232
- for (const entry of entries) {
233
- locators.set(entry.authority, [...(locators.get(entry.authority) ?? []), entry.locator]);
234
- if (lines.get(entry.authority)?.logEpoch !== entry.logEpoch) {
235
- lines.set(entry.authority, { logEpoch: entry.logEpoch, frames: [], held: null });
236
- }
237
- }
238
- for (const authority of lines.keys()) {
239
- if (!locators.has(authority))
240
- lines.delete(authority);
241
- }
242
- },
243
- reach(authority, at) {
244
- const line = lines.get(authority);
245
- const held = position(at.position);
246
- if (line === undefined || held === null || line.logEpoch !== at.logEpoch)
396
+ announced = null;
397
+ if (socket === null)
247
398
  return;
248
- if (line.held !== null && held <= line.held)
399
+ const entries = new Map([...tracking.values()].flat().map((tracked) => [tracked.locator, tracked]));
400
+ const named = rooms.flatMap((room) => {
401
+ const entry = entries.get(room.locator);
402
+ const at = room.roomVersion === null ? null : logPosition(room.roomVersion);
403
+ return entry === undefined || at === null ? [] : [{ entry, at }];
404
+ });
405
+ const unheld = rooms.flatMap((room) => {
406
+ const entry = entries.get(room.locator);
407
+ return entry === undefined || room.roomVersion !== null ? [] : [entry];
408
+ });
409
+ for (const { entry, at } of named) {
410
+ if (at.position === '0')
411
+ heldAtZero.add(entry.authority);
412
+ else
413
+ heldAtZero.delete(entry.authority);
414
+ }
415
+ for (const entry of unheld)
416
+ heldAtZero.delete(entry.authority);
417
+ const site = mode === 'site';
418
+ unanswered.push(site ? unheld.map((entry) => entry.locator) : []);
419
+ socket.hold([
420
+ ...named.map(({ entry, at }) => presented(entry.authority, at)),
421
+ ...(site ? [] : unheld).map((entry) => presented(entry.authority, { position: '0', logEpoch: entry.logEpoch })),
422
+ ], runtime, listedCursor);
423
+ if (site)
249
424
  return;
250
- lines.set(authority, {
251
- ...line,
252
- frames: line.frames.filter((frame) => frame.position > held),
253
- held,
425
+ const made = unheld.filter((entry) => entry.position === '0');
426
+ queueMicrotask(() => {
427
+ for (const entry of made) {
428
+ const version = roomVersion(entry);
429
+ emit({
430
+ kind: 'room-change',
431
+ locator: entry.locator,
432
+ from: null,
433
+ roomVersion: version,
434
+ read: () => changePage(entry, [], version, mode, spaces, true),
435
+ });
436
+ }
254
437
  });
255
438
  },
256
- advance(tracked, from, holds) {
257
- const line = lines.get(tracked.authority);
258
- const start = position(from.position);
259
- if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
260
- return null;
261
- const pending = line.frames.filter((frame) => frame.position > start);
262
- const first = pending[0];
263
- if (first === undefined || first.after > start)
264
- return null;
265
- const documents = {};
266
- const revisions = {};
267
- const changes = {};
268
- const binaryFiles = {};
269
- const removals = [];
270
- const applied = [];
271
- const schemas = new Map();
272
- const forget = (path) => {
273
- delete documents[path];
274
- delete revisions[path];
275
- delete changes[path];
276
- delete binaryFiles[path];
277
- const removed = removals.indexOf(path);
278
- if (removed !== -1)
279
- removals.splice(removed, 1);
280
- };
281
- for (const frame of pending) {
282
- for (const entry of frame.entries) {
283
- if (entry.kind === 'edited' &&
284
- entry.revision !== undefined &&
285
- holds?.(entry.path, entry.revision) === true) {
286
- forget(entry.path);
287
- continue;
288
- }
289
- applied.push(entry);
290
- if (tracked.schemas.includes(entry.path))
291
- schemas.set(entry.path, entry);
292
- if (entry.kind === 'removed') {
293
- forget(entry.path);
294
- removals.push(entry.path);
295
- continue;
296
- }
297
- const binary = binaryFileOf(entry);
298
- if (binary === null || (binary === undefined && entry.text === undefined))
299
- return null;
300
- if (mode === 'credential' && entry.revision === undefined)
301
- return null;
302
- const head = headChange(entry);
303
- if (head === null)
304
- return null;
305
- forget(entry.path);
306
- if (binary === undefined)
307
- documents[entry.path] = entry.text;
308
- else
309
- binaryFiles[entry.path] = binary;
310
- const revision = entry.revision ?? binary?.sha256;
311
- if (revision !== undefined)
312
- revisions[entry.path] = revision;
313
- if (head !== undefined)
314
- changes[entry.path] = head;
315
- }
439
+ track(entries) {
440
+ tracking.clear();
441
+ for (const entry of entries) {
442
+ tracking.set(entry.authority, [...(tracking.get(entry.authority) ?? []), entry]);
443
+ }
444
+ for (const [carry, held] of staged) {
445
+ if (!tracking.has(held.authority))
446
+ staged.delete(carry);
316
447
  }
317
- const last = pending.at(-1);
318
- lines.set(tracked.authority, { ...line, frames: pending, held: last.position });
319
- return {
320
- page: {
321
- kind: 'net-advancement',
322
- roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),
323
- documents,
324
- revisions,
325
- changes,
326
- binaryFiles,
327
- removals: removals.sort(),
328
- },
329
- entries: applied,
330
- schemas,
331
- };
332
448
  },
333
449
  };
334
450
  }