@agentshouse/mdruntime-adapter 0.1.0-cf22c8563f9f4 → 0.1.0-cf41d9210cb6b

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 (66) hide show
  1. package/README.md +2 -2
  2. package/dist/actions.d.ts +51 -2
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +123 -214
  5. package/dist/adapter.d.ts +1 -0
  6. package/dist/adapter.d.ts.map +1 -1
  7. package/dist/adapter.js +336 -109
  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/crockford.d.ts +4 -0
  12. package/dist/crockford.d.ts.map +1 -0
  13. package/dist/crockford.js +3 -0
  14. package/dist/discovery.d.ts +9 -11
  15. package/dist/discovery.d.ts.map +1 -1
  16. package/dist/discovery.js +55 -36
  17. package/dist/gather.d.ts +1 -1
  18. package/dist/gather.d.ts.map +1 -1
  19. package/dist/gather.js +15 -20
  20. package/dist/house-model.d.ts +2 -0
  21. package/dist/house-model.d.ts.map +1 -0
  22. package/dist/house-model.js +489 -0
  23. package/dist/index.d.ts +8 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +7 -0
  26. package/dist/model.d.ts +6 -2
  27. package/dist/model.d.ts.map +1 -1
  28. package/dist/model.js +32 -20
  29. package/dist/part.d.ts +14 -0
  30. package/dist/part.d.ts.map +1 -0
  31. package/dist/part.js +90 -0
  32. package/dist/read.d.ts +74 -20
  33. package/dist/read.d.ts.map +1 -1
  34. package/dist/read.js +353 -168
  35. package/dist/refusal.d.ts +2 -5
  36. package/dist/refusal.d.ts.map +1 -1
  37. package/dist/refusal.js +6 -9
  38. package/dist/room-stream.d.ts +19 -0
  39. package/dist/room-stream.d.ts.map +1 -0
  40. package/dist/room-stream.js +57 -0
  41. package/dist/room-types.d.ts +7 -0
  42. package/dist/room-types.d.ts.map +1 -0
  43. package/dist/room-types.js +125 -0
  44. package/dist/site.d.ts +1 -1
  45. package/dist/site.d.ts.map +1 -1
  46. package/dist/site.js +131 -62
  47. package/dist/stream.d.ts +6 -4
  48. package/dist/stream.d.ts.map +1 -1
  49. package/dist/stream.js +366 -44
  50. package/dist/transport.d.ts +76 -11
  51. package/dist/transport.d.ts.map +1 -1
  52. package/dist/transport.js +4 -0
  53. package/dist/upload.d.ts +12 -0
  54. package/dist/upload.d.ts.map +1 -0
  55. package/dist/upload.js +63 -0
  56. package/dist/version.d.ts +1 -0
  57. package/dist/version.d.ts.map +1 -1
  58. package/dist/version.js +1 -1
  59. package/dist/write.d.ts +18 -9
  60. package/dist/write.d.ts.map +1 -1
  61. package/dist/write.js +164 -41
  62. package/package.json +9 -6
  63. package/AGENTS.md +0 -244
  64. package/dist/links.d.ts +0 -20
  65. package/dist/links.d.ts.map +0 -1
  66. package/dist/links.js +0 -104
package/dist/stream.js CHANGED
@@ -1,5 +1,7 @@
1
- import { acceptedMessage } from './actions.js';
2
- import { headChange } from './read.js';
1
+ import { ROW_WEIGHT, } from '@agentshouse/mdruntime';
2
+ import { acceptedMessage, cursorPosition } from './actions.js';
3
+ import { sha256Hex } from './digest.js';
4
+ import { answered, answering, binaryFileOf, folded, forgotten, headChange, revised, } from './read.js';
3
5
  import { roomVersion } from './version.js';
4
6
  const HELD_FRAMES_MAX = 256;
5
7
  function turnOperation(frame) {
@@ -14,6 +16,8 @@ function listedConversation(listed) {
14
16
  created: listed.created_at,
15
17
  finished: listed.finished_at,
16
18
  outcome: listed.outcome,
19
+ waiting: listed.waiting,
20
+ newest: listed.newest === null ? null : cursorPosition(listed.newest),
17
21
  };
18
22
  }
19
23
  function position(value) {
@@ -21,9 +25,78 @@ function position(value) {
21
25
  return null;
22
26
  return BigInt(value);
23
27
  }
28
+ function assembled(entries) {
29
+ const whole = [];
30
+ let open = null;
31
+ for (const entry of entries) {
32
+ if (entry.kind === 'piece') {
33
+ if (open === null || open.entry.path !== entry.path || entry.text === undefined)
34
+ return null;
35
+ open.texts.push(entry.text);
36
+ }
37
+ else {
38
+ if (open !== null)
39
+ return null;
40
+ if (entry.continued !== true) {
41
+ whole.push(entry);
42
+ continue;
43
+ }
44
+ if (entry.text === undefined)
45
+ return null;
46
+ open = { entry, texts: [entry.text] };
47
+ }
48
+ if (entry.continued === true)
49
+ continue;
50
+ const { continued: _continued, ...head } = open.entry;
51
+ whole.push({ ...head, text: open.texts.join('') });
52
+ open = null;
53
+ }
54
+ return open === null ? whole : null;
55
+ }
56
+ async function verified(entries) {
57
+ try {
58
+ for (const entry of entries) {
59
+ if (entry.text === undefined || entry.sha256 === undefined)
60
+ continue;
61
+ if ((await sha256Hex(entry.text)) !== entry.sha256)
62
+ return false;
63
+ }
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }
70
+ function resumed(kept, frame) {
71
+ const last = frame.entries.at(-1);
72
+ const point = { parts: frame.index + 1, from: frame.from, target: frame.target };
73
+ if (last?.continued !== true)
74
+ return { ...point, handled: frame.handled, piece: null };
75
+ const text = last.text?.length ?? 0;
76
+ if (last.kind !== 'piece') {
77
+ return last.sha256 === undefined
78
+ ? kept.resume
79
+ : { ...point, handled: frame.handled, piece: { sha256: last.sha256, offset: text } };
80
+ }
81
+ const piece = kept.resume?.piece ?? null;
82
+ if (piece === null)
83
+ return kept.resume;
84
+ const pieces = frame.entries.reduce((sum, entry) => sum + (entry.kind === 'piece' ? (entry.text?.length ?? 0) : 0), 0);
85
+ return {
86
+ ...point,
87
+ handled: frame.handled,
88
+ piece: { sha256: piece.sha256, offset: piece.offset + pieces },
89
+ };
90
+ }
24
91
  export function houseNotifications(transport, mode) {
25
92
  const stream = transport.stream;
26
93
  const lines = new Map();
94
+ const kept = new Map();
95
+ let receipts = null;
96
+ let loaded = Promise.resolve();
97
+ let acknowledging = null;
98
+ let receiving = Promise.resolve();
99
+ let verifying = 0;
27
100
  const locators = new Map();
28
101
  const observers = new Set();
29
102
  const conversationObservers = new Set();
@@ -41,7 +114,10 @@ export function houseNotifications(transport, mode) {
41
114
  event.kind === 'questions' ||
42
115
  event.kind === 'process' ||
43
116
  event.kind === 'commands' ||
44
- event.kind === 'options') {
117
+ event.kind === 'options' ||
118
+ event.kind === 'starting' ||
119
+ event.kind === 'link' ||
120
+ event.kind === 'deliveries') {
45
121
  live.add(event.conversation);
46
122
  }
47
123
  for (const observer of conversationObservers)
@@ -49,6 +125,7 @@ export function houseNotifications(transport, mode) {
49
125
  }
50
126
  function reopened(next) {
51
127
  opening = next;
128
+ acknowledging = next;
52
129
  const gapped = new Set([...replicated, ...live]);
53
130
  live.clear();
54
131
  for (const conversation of gapped)
@@ -86,6 +163,18 @@ export function houseNotifications(transport, mode) {
86
163
  emitConversation({ kind: 'options', conversation, options: structuredClone(frame.options) });
87
164
  return;
88
165
  }
166
+ if (frame.type === 'starting') {
167
+ emitConversation({ kind: 'starting', conversation, step: frame.step });
168
+ return;
169
+ }
170
+ if (frame.type === 'link') {
171
+ emitConversation({ kind: 'link', conversation, connected: frame.connected });
172
+ return;
173
+ }
174
+ if (frame.type === 'deliveries') {
175
+ emitConversation({ kind: 'deliveries', conversation, unknown: [...frame.unknown] });
176
+ return;
177
+ }
89
178
  if (frame.type === 'interactions') {
90
179
  emitConversation({
91
180
  kind: 'questions',
@@ -110,7 +199,162 @@ export function houseNotifications(transport, mode) {
110
199
  if (line !== undefined)
111
200
  lines.set(authority, { ...line, frames: [] });
112
201
  }
113
- function receive(frame) {
202
+ async function forget(carries) {
203
+ const held = carries.filter((carry) => kept.delete(carry));
204
+ if (held.length > 0)
205
+ await receipts?.drop(held).catch(() => { });
206
+ }
207
+ async function lost(authority, carry) {
208
+ interrupt(authority);
209
+ await forget([carry]);
210
+ }
211
+ async function stage(frame, via) {
212
+ await loaded;
213
+ const port = receipts;
214
+ if (port === null)
215
+ return;
216
+ const held = kept.get(frame.carry);
217
+ if (held === undefined && frame.index !== 0) {
218
+ interrupt(frame.authority);
219
+ return;
220
+ }
221
+ if (held !== undefined &&
222
+ (held.fenced !== null || frame.index > held.parts || frame.index < (held.resume?.parts ?? 0))) {
223
+ await lost(frame.authority, frame.carry);
224
+ return;
225
+ }
226
+ if (held === undefined) {
227
+ await forget([...kept.values()]
228
+ .filter((other) => other.authority === frame.authority && other.fenced === null)
229
+ .map((other) => other.carry));
230
+ }
231
+ const start = held ?? {
232
+ authority: frame.authority,
233
+ carry: frame.carry,
234
+ logEpoch: lines.get(frame.authority)?.logEpoch ?? null,
235
+ after: frame.after,
236
+ parts: 0,
237
+ resume: null,
238
+ fenced: null,
239
+ };
240
+ const next = { ...start, parts: frame.index + 1, resume: resumed(start, frame) };
241
+ const part = { entries: frame.entries };
242
+ try {
243
+ await port.keep(frame.carry, next, { index: frame.index, value: part });
244
+ }
245
+ catch {
246
+ await lost(frame.authority, frame.carry);
247
+ return;
248
+ }
249
+ kept.set(frame.carry, next);
250
+ via?.received(frame.authority, frame.carry, frame.index);
251
+ }
252
+ async function keptEntries(carry, parts) {
253
+ if (parts === 0)
254
+ return [];
255
+ if (receipts === null)
256
+ return null;
257
+ const read = (await receipts.parts(carry, parts));
258
+ if (read.length !== parts)
259
+ return null;
260
+ const entries = assembled(read.flatMap((part) => part.entries));
261
+ return entries !== null && (await verified(entries)) ? entries : null;
262
+ }
263
+ async function carried(frame) {
264
+ await loaded;
265
+ const held = kept.get(frame.carry);
266
+ if (frame.parts > 0 && held?.parts !== frame.parts) {
267
+ await lost(frame.authority, frame.carry);
268
+ return;
269
+ }
270
+ const entries = await keptEntries(frame.carry, frame.parts).catch(() => null);
271
+ if (entries === null) {
272
+ await lost(frame.authority, frame.carry);
273
+ return;
274
+ }
275
+ const fenced = {
276
+ ...(held ?? {
277
+ authority: frame.authority,
278
+ carry: frame.carry,
279
+ logEpoch: frame.log_epoch,
280
+ after: frame.after,
281
+ parts: 0,
282
+ resume: null,
283
+ }),
284
+ after: frame.after,
285
+ fenced: { position: frame.position, logEpoch: frame.log_epoch },
286
+ };
287
+ try {
288
+ await receipts?.keep(frame.carry, fenced);
289
+ }
290
+ catch {
291
+ await lost(frame.authority, frame.carry);
292
+ return;
293
+ }
294
+ kept.set(frame.carry, fenced);
295
+ publish(frame, entries);
296
+ }
297
+ async function load(port) {
298
+ try {
299
+ for (const { key, head } of await port.heads())
300
+ kept.set(key, head);
301
+ }
302
+ catch {
303
+ kept.clear();
304
+ }
305
+ }
306
+ async function restored(room) {
307
+ const line = lines.get(room.authority);
308
+ let at = room.position;
309
+ const chain = [];
310
+ for (;;) {
311
+ const next = [...kept.values()].find((carry) => carry.authority === room.authority &&
312
+ carry.after === at &&
313
+ carry.fenced?.logEpoch === room.log_epoch);
314
+ if (next?.fenced == null)
315
+ break;
316
+ const entries = await keptEntries(next.carry, next.parts).catch(() => null);
317
+ if (entries === null)
318
+ break;
319
+ chain.push({ carry: next, entries });
320
+ at = next.fenced.position;
321
+ }
322
+ const partial = [...kept.values()].find((carry) => carry.authority === room.authority &&
323
+ carry.fenced === null &&
324
+ carry.logEpoch === room.log_epoch &&
325
+ carry.after === at &&
326
+ carry.resume !== null &&
327
+ carry.resume.parts > 0);
328
+ const stale = [...kept.values()].filter((carry) => carry.authority === room.authority &&
329
+ carry !== partial &&
330
+ !chain.some((link) => link.carry === carry));
331
+ await forget(stale.map((carry) => carry.carry));
332
+ if (line !== undefined && line.logEpoch === room.log_epoch && chain.length > 0) {
333
+ const frames = chain.map(({ carry, entries }) => ({
334
+ after: BigInt(carry.after),
335
+ position: BigInt(carry.fenced.position),
336
+ entries,
337
+ }));
338
+ lines.set(room.authority, { ...line, frames: [...line.frames, ...frames] });
339
+ }
340
+ return {
341
+ ...room,
342
+ position: at,
343
+ ...(partial?.resume == null
344
+ ? {}
345
+ : {
346
+ carry: {
347
+ id: partial.carry,
348
+ parts: partial.resume.parts,
349
+ from: partial.resume.from,
350
+ target: partial.resume.target,
351
+ handled: partial.resume.handled,
352
+ ...(partial.resume.piece === null ? {} : { piece: partial.resume.piece }),
353
+ },
354
+ }),
355
+ };
356
+ }
357
+ function handle(frame, via) {
114
358
  if (frame.type === 'signal') {
115
359
  const mode = frame.service_mode;
116
360
  if (mode !== 'open' && mode !== 'write-halted')
@@ -126,6 +370,10 @@ export function houseNotifications(transport, mode) {
126
370
  });
127
371
  return;
128
372
  }
373
+ if (frame.type === 'authority_changed') {
374
+ emit({ kind: 'authority-changed', scope: { authorities: frame.rooms } });
375
+ return;
376
+ }
129
377
  if (frame.type === 'conversations') {
130
378
  emitConversation({ kind: 'list', entries: frame.conversations.map(listedConversation) });
131
379
  return;
@@ -142,13 +390,23 @@ export function houseNotifications(transport, mode) {
142
390
  frame.type === 'process' ||
143
391
  frame.type === 'commands' ||
144
392
  frame.type === 'options' ||
393
+ frame.type === 'starting' ||
394
+ frame.type === 'link' ||
395
+ frame.type === 'deliveries' ||
145
396
  frame.type === 'interactions' ||
146
397
  frame.type === 'message') {
147
398
  converse(frame);
148
399
  return;
149
400
  }
150
- if (frame.type !== 'entries')
151
- return;
401
+ if (frame.type === 'part')
402
+ return ahead(() => stage(frame, via));
403
+ if (frame.type === 'carried')
404
+ return ahead(() => carried(frame));
405
+ }
406
+ function ahead(work) {
407
+ return receipts === null ? work() : receipts.ahead(work);
408
+ }
409
+ function publish(frame, entries) {
152
410
  const at = position(frame.position);
153
411
  const after = position(frame.after);
154
412
  if (at === null || after === null || after >= at) {
@@ -162,7 +420,7 @@ export function houseNotifications(transport, mode) {
162
420
  const last = line.frames.at(-1);
163
421
  if (last !== undefined && at <= last.position)
164
422
  return;
165
- const held = { after, position: at, entries: frame.entries };
423
+ const held = { after, position: at, entries };
166
424
  const next = last !== undefined && after <= last.position ? [...line.frames, held] : [held];
167
425
  lines.set(frame.authority, { ...line, frames: next.length > HELD_FRAMES_MAX ? [] : next });
168
426
  }
@@ -171,11 +429,30 @@ export function houseNotifications(transport, mode) {
171
429
  }
172
430
  announce(frame.authority, { position: frame.position, logEpoch: frame.log_epoch });
173
431
  }
174
- stream.observe(receive);
432
+ stream.observe((frame) => {
433
+ const via = acknowledging;
434
+ if (verifying === 0) {
435
+ const handled = handle(frame, via);
436
+ if (handled === undefined)
437
+ return;
438
+ verifying += 1;
439
+ receiving = handled.finally(() => {
440
+ verifying -= 1;
441
+ });
442
+ return;
443
+ }
444
+ verifying += 1;
445
+ receiving = receiving
446
+ .then(() => handle(frame, via))
447
+ .finally(() => {
448
+ verifying -= 1;
449
+ });
450
+ });
175
451
  stream.opened(reopened);
176
- stream.closed((revoked) => {
452
+ stream.closed(({ revoked, lost }) => {
177
453
  opening = null;
178
- emit({ kind: 'closed', revoked });
454
+ acknowledging = null;
455
+ emit({ kind: 'closed', revoked, lost });
179
456
  });
180
457
  return {
181
458
  runtime,
@@ -198,8 +475,12 @@ export function houseNotifications(transport, mode) {
198
475
  };
199
476
  },
200
477
  },
201
- observe(notify) {
478
+ observe(notify, port) {
202
479
  observers.add(notify);
480
+ if (receipts === null) {
481
+ receipts = port;
482
+ loaded = load(port);
483
+ }
203
484
  if (opening !== null) {
204
485
  queueMicrotask(() => {
205
486
  if (observers.has(notify))
@@ -220,7 +501,35 @@ export function houseNotifications(transport, mode) {
220
501
  }
221
502
  const current = opening;
222
503
  opening = null;
223
- current?.hold(rooms, runtime);
504
+ if (current === null)
505
+ return;
506
+ void loaded
507
+ .then(() => Promise.all(rooms.map(restored)))
508
+ .then((presented) => {
509
+ current.hold(presented, runtime);
510
+ for (const [index, room] of presented.entries()) {
511
+ if (room.position === rooms[index].position)
512
+ continue;
513
+ announce(room.authority, { position: room.position, logEpoch: room.log_epoch });
514
+ }
515
+ });
516
+ },
517
+ published(locator, at) {
518
+ const authority = [...locators].find(([, held]) => held.includes(locator))?.[0];
519
+ const reached = position(at.position);
520
+ if (authority === undefined || reached === null)
521
+ return;
522
+ void forget([...kept.values()]
523
+ .filter((carry) => carry.authority === authority &&
524
+ carry.fenced !== null &&
525
+ carry.fenced.logEpoch === at.logEpoch &&
526
+ BigInt(carry.fenced.position) <= reached)
527
+ .map((carry) => carry.carry));
528
+ },
529
+ reopen() {
530
+ const current = opening;
531
+ opening = null;
532
+ current?.close();
224
533
  },
225
534
  track(entries) {
226
535
  locators.clear();
@@ -234,6 +543,9 @@ export function houseNotifications(transport, mode) {
234
543
  if (!locators.has(authority))
235
544
  lines.delete(authority);
236
545
  }
546
+ void loaded.then(() => forget([...kept.values()]
547
+ .filter((carry) => !locators.has(carry.authority))
548
+ .map((carry) => carry.carry)));
237
549
  },
238
550
  reach(authority, at) {
239
551
  const line = lines.get(authority);
@@ -248,7 +560,18 @@ export function houseNotifications(transport, mode) {
248
560
  held,
249
561
  });
250
562
  },
251
- advance(tracked, from, holds) {
563
+ edited(tracked, from) {
564
+ const line = lines.get(tracked.authority);
565
+ const start = position(from.position);
566
+ if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
567
+ return [];
568
+ return [
569
+ ...new Set(line.frames
570
+ .filter((frame) => frame.position > start)
571
+ .flatMap((frame) => frame.entries.flatMap((entry) => entry.kind === 'edited' && entry.revision !== undefined ? [entry.path] : []))),
572
+ ];
573
+ },
574
+ *advance(tracked, from, holds) {
252
575
  const line = lines.get(tracked.authority);
253
576
  const start = position(from.position);
254
577
  if (line === undefined || start === null || line.logEpoch !== from.logEpoch)
@@ -257,64 +580,63 @@ export function houseNotifications(transport, mode) {
257
580
  const first = pending[0];
258
581
  if (first === undefined || first.after > start)
259
582
  return null;
260
- const documents = {};
261
- const revisions = {};
262
- const changes = {};
263
- const removals = [];
264
- const applied = [];
583
+ const answer = answering();
265
584
  const schemas = new Map();
266
- const forget = (path) => {
267
- delete documents[path];
268
- delete revisions[path];
269
- delete changes[path];
270
- const removed = removals.indexOf(path);
271
- if (removed !== -1)
272
- removals.splice(removed, 1);
273
- };
274
585
  for (const frame of pending) {
275
586
  for (const entry of frame.entries) {
587
+ yield ROW_WEIGHT + (entry.text?.length ?? 0);
588
+ if (entry.kind === 'folder') {
589
+ folded(answer, entry.path, entry.removed === true);
590
+ continue;
591
+ }
276
592
  if (entry.kind === 'edited' &&
277
593
  entry.revision !== undefined &&
278
594
  holds?.(entry.path, entry.revision) === true) {
279
- forget(entry.path);
595
+ forgotten(answer, entry.path);
280
596
  continue;
281
597
  }
282
- applied.push(entry);
283
- if (tracked.schemas.includes(entry.path))
598
+ if (entry.path === tracked.schema)
284
599
  schemas.set(entry.path, entry);
285
600
  if (entry.kind === 'removed') {
286
- forget(entry.path);
287
- removals.push(entry.path);
601
+ forgotten(answer, entry.path);
602
+ answer.removals.add(entry.path);
288
603
  continue;
289
604
  }
290
- if (entry.text === undefined)
605
+ const binary = binaryFileOf(entry);
606
+ if (binary === null || (binary === undefined && entry.text === undefined))
291
607
  return null;
292
608
  if (mode === 'credential' && entry.revision === undefined)
293
609
  return null;
294
610
  const head = headChange(entry);
295
611
  if (head === null)
296
612
  return null;
297
- forget(entry.path);
298
- documents[entry.path] = entry.text;
299
- if (entry.revision !== undefined)
300
- revisions[entry.path] = entry.revision;
613
+ forgotten(answer, entry.path);
614
+ if (binary === undefined)
615
+ answer.documents.set(entry.path, entry.text);
616
+ else
617
+ answer.binaryFiles.set(entry.path, binary);
618
+ const revision = entry.revision ?? binary?.sha256;
619
+ if (revision !== undefined)
620
+ revised(answer, entry.path, revision);
301
621
  if (head !== undefined)
302
- changes[entry.path] = head;
622
+ answer.changes.set(entry.path, head);
303
623
  }
304
624
  }
305
625
  const last = pending.at(-1);
306
- lines.set(tracked.authority, { ...line, frames: pending, held: last.position });
626
+ const current = lines.get(tracked.authority);
627
+ if (current?.logEpoch === line.logEpoch) {
628
+ lines.set(tracked.authority, {
629
+ ...current,
630
+ frames: current.frames.filter((frame) => frame.position > start),
631
+ held: current.held !== null && current.held > last.position ? current.held : last.position,
632
+ });
633
+ }
307
634
  return {
308
635
  page: {
309
636
  kind: 'net-advancement',
310
637
  roomVersion: roomVersion({ position: last.position.toString(), logEpoch: line.logEpoch }),
311
- documents,
312
- revisions,
313
- changes,
314
- binaryTargets: [],
315
- removals: removals.sort(),
638
+ ...(yield* answered(answer)),
316
639
  },
317
- entries: applied,
318
640
  schemas,
319
641
  };
320
642
  },