@agentshouse/mdruntime 0.1.0-c09bf842921ff → 0.1.0-c0b4d0492dec3

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 (108) hide show
  1. package/README.md +1 -1
  2. package/dist/adapter.d.ts +15 -16
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/bootstrap.d.ts +8 -4
  5. package/dist/bootstrap.d.ts.map +1 -1
  6. package/dist/bootstrap.js +206 -76
  7. package/dist/change.d.ts +1 -0
  8. package/dist/change.d.ts.map +1 -1
  9. package/dist/chat-types.d.ts +3 -0
  10. package/dist/chat-types.d.ts.map +1 -0
  11. package/dist/chat-types.js +2 -0
  12. package/dist/client.d.ts +5 -0
  13. package/dist/client.d.ts.map +1 -1
  14. package/dist/client.js +1 -0
  15. package/dist/compile.d.ts +5 -0
  16. package/dist/compile.d.ts.map +1 -1
  17. package/dist/compile.js +186 -55
  18. package/dist/connection.d.ts +8 -2
  19. package/dist/connection.d.ts.map +1 -1
  20. package/dist/connection.js +1386 -1040
  21. package/dist/conversation-row.d.ts +33 -0
  22. package/dist/conversation-row.d.ts.map +1 -0
  23. package/dist/conversation-row.js +47 -0
  24. package/dist/conversation.d.ts +13 -5
  25. package/dist/conversation.d.ts.map +1 -1
  26. package/dist/conversation.js +354 -192
  27. package/dist/entry.d.ts.map +1 -1
  28. package/dist/entry.js +1 -0
  29. package/dist/figures.d.ts +48 -0
  30. package/dist/figures.d.ts.map +1 -0
  31. package/dist/figures.js +197 -0
  32. package/dist/host.d.ts.map +1 -1
  33. package/dist/host.js +3 -3
  34. package/dist/index.d.ts +9 -4
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -1
  37. package/dist/job.d.ts +20 -1
  38. package/dist/job.d.ts.map +1 -1
  39. package/dist/job.js +26 -0
  40. package/dist/live.d.ts +4 -4
  41. package/dist/live.d.ts.map +1 -1
  42. package/dist/live.js +53 -15
  43. package/dist/memory.d.ts +1 -0
  44. package/dist/memory.d.ts.map +1 -1
  45. package/dist/memory.js +11 -3
  46. package/dist/messages.d.ts +25 -1
  47. package/dist/messages.d.ts.map +1 -1
  48. package/dist/messages.js +82 -3
  49. package/dist/model.d.ts +0 -2
  50. package/dist/model.d.ts.map +1 -1
  51. package/dist/model.js +0 -6
  52. package/dist/outcome.d.ts +1 -0
  53. package/dist/outcome.d.ts.map +1 -1
  54. package/dist/outcome.js +3 -0
  55. package/dist/overlay.d.ts +1 -0
  56. package/dist/overlay.d.ts.map +1 -1
  57. package/dist/overlay.js +11 -0
  58. package/dist/parts.d.ts +59 -0
  59. package/dist/parts.d.ts.map +1 -0
  60. package/dist/parts.js +118 -0
  61. package/dist/query.d.ts +10 -0
  62. package/dist/query.d.ts.map +1 -1
  63. package/dist/questions.d.ts +32 -0
  64. package/dist/questions.d.ts.map +1 -0
  65. package/dist/questions.js +118 -0
  66. package/dist/reach.d.ts +5 -5
  67. package/dist/reach.d.ts.map +1 -1
  68. package/dist/reach.js +156 -99
  69. package/dist/read.d.ts +7 -0
  70. package/dist/read.d.ts.map +1 -0
  71. package/dist/read.js +17 -0
  72. package/dist/reads.d.ts +35 -0
  73. package/dist/reads.d.ts.map +1 -0
  74. package/dist/reads.js +128 -0
  75. package/dist/recovery.d.ts.map +1 -1
  76. package/dist/recovery.js +9 -1
  77. package/dist/refresh.d.ts +1 -1
  78. package/dist/refresh.d.ts.map +1 -1
  79. package/dist/refresh.js +4 -0
  80. package/dist/replica.d.ts.map +1 -1
  81. package/dist/replica.js +23 -6
  82. package/dist/save.d.ts.map +1 -1
  83. package/dist/save.js +10 -7
  84. package/dist/source.d.ts +61 -0
  85. package/dist/source.d.ts.map +1 -0
  86. package/dist/source.js +81 -0
  87. package/dist/status.d.ts +0 -2
  88. package/dist/status.d.ts.map +1 -1
  89. package/dist/status.js +0 -6
  90. package/dist/store.d.ts +85 -25
  91. package/dist/store.d.ts.map +1 -1
  92. package/dist/store.js +136 -98
  93. package/dist/stored.d.ts +55 -28
  94. package/dist/stored.d.ts.map +1 -1
  95. package/dist/stored.js +187 -74
  96. package/dist/tables.d.ts +99 -19
  97. package/dist/tables.d.ts.map +1 -1
  98. package/dist/tables.js +171 -34
  99. package/dist/tallies.d.ts +18 -0
  100. package/dist/tallies.d.ts.map +1 -0
  101. package/dist/tallies.js +129 -0
  102. package/dist/wire.d.ts +6 -0
  103. package/dist/wire.d.ts.map +1 -1
  104. package/dist/wire.js +3 -0
  105. package/package.json +2 -2
  106. package/dist/fence.d.ts +0 -6
  107. package/dist/fence.d.ts.map +0 -1
  108. package/dist/fence.js +0 -10
@@ -0,0 +1,118 @@
1
+ import { excerpt, list, record, text } from './read.js';
2
+ const OPTION = 'optionId';
3
+ function choicesOf(schema) {
4
+ const items = record(schema.items);
5
+ const listed = [schema.oneOf, schema.enum, items.anyOf, items.enum].find(Array.isArray) ?? [];
6
+ return listed.flatMap((one) => {
7
+ if (typeof one === 'string')
8
+ return [{ value: one, label: one, about: null }];
9
+ const value = text(record(one), 'const');
10
+ return value === null
11
+ ? []
12
+ : [
13
+ {
14
+ value,
15
+ label: text(record(one), 'title') ?? value,
16
+ about: text(record(one), 'description'),
17
+ },
18
+ ];
19
+ });
20
+ }
21
+ function fieldOf(name, schema) {
22
+ const type = text(schema, 'type');
23
+ const kind = type === 'boolean' || type === 'number' || type === 'integer'
24
+ ? type
25
+ : type === 'array'
26
+ ? 'multi-select'
27
+ : 'string';
28
+ return {
29
+ name,
30
+ kind,
31
+ prompt: text(schema, 'title') ?? name,
32
+ about: text(schema, 'description'),
33
+ choices: kind === 'boolean' ? [] : choicesOf(schema),
34
+ };
35
+ }
36
+ export function entered(field) {
37
+ return field.kind !== 'boolean' && field.choices.length === 0;
38
+ }
39
+ function valueOf(field, raw) {
40
+ return field.kind === 'number' || field.kind === 'integer' ? Number(raw) : raw;
41
+ }
42
+ function typed(fields, answer) {
43
+ return Object.fromEntries(Object.entries(answer).map(([name, value]) => {
44
+ const field = fields.find((one) => one.name === name);
45
+ return [
46
+ name,
47
+ field !== undefined && entered(field) && typeof value === 'string'
48
+ ? valueOf(field, value)
49
+ : value,
50
+ ];
51
+ }));
52
+ }
53
+ function askedOf(request) {
54
+ const params = record(request.params);
55
+ const method = text(request, 'method');
56
+ if (method === 'session/request_permission') {
57
+ return {
58
+ message: '',
59
+ fields: [
60
+ {
61
+ name: OPTION,
62
+ kind: 'string',
63
+ prompt: text(record(params.toolCall), 'title') ?? '',
64
+ about: null,
65
+ choices: list(params, 'options').flatMap((entry) => {
66
+ const one = record(entry);
67
+ const value = text(one, OPTION);
68
+ return value === null
69
+ ? []
70
+ : [{ value, label: text(one, 'name') ?? value, about: null }];
71
+ }),
72
+ },
73
+ ],
74
+ accept: (answer) => ({ outcome: { outcome: 'selected', optionId: answer[OPTION] } }),
75
+ decline: null,
76
+ };
77
+ }
78
+ if (method !== 'elicitation/create')
79
+ return null;
80
+ const fields = Object.entries(record(record(params.requestedSchema).properties)).map(([name, schema]) => fieldOf(name, record(schema)));
81
+ return {
82
+ message: text(params, 'message') ?? '',
83
+ fields,
84
+ accept: (answer) => ({ action: 'accept', content: typed(fields, answer) }),
85
+ decline: { action: 'decline' },
86
+ };
87
+ }
88
+ export function questionsOf(view) {
89
+ return (view?.questions ?? []).flatMap((entry) => {
90
+ const one = record(entry);
91
+ const interaction = text(one, 'interaction_id');
92
+ const asked = askedOf(record(one.request));
93
+ return asked === null || interaction === null
94
+ ? []
95
+ : [
96
+ {
97
+ interaction,
98
+ secret: one.secret === true,
99
+ undelivered: one.telegram_undelivered === true,
100
+ ...asked,
101
+ },
102
+ ];
103
+ });
104
+ }
105
+ export function openQuestion(questions) {
106
+ const [asked] = questionsOf({ questions });
107
+ if (asked === undefined)
108
+ return null;
109
+ const said = asked.message === '' ? asked.fields[0]?.prompt : asked.message;
110
+ return said === undefined || said === '' ? null : excerpt(said);
111
+ }
112
+ export function loneOf(questions) {
113
+ const asked = questions.length === 1 && !questions[0]?.secret ? questions[0] : undefined;
114
+ const only = asked?.fields.length === 1 ? asked.fields[0] : undefined;
115
+ return asked !== undefined && only !== undefined && entered(only)
116
+ ? { question: asked, field: only }
117
+ : null;
118
+ }
package/dist/reach.d.ts CHANGED
@@ -28,16 +28,16 @@ export type NarrowedView = RuntimeView & {
28
28
  narrow(reach: PortReach | null): void;
29
29
  };
30
30
  export type Reachable = RuntimeView & {
31
- plan(input: unknown, reach: PortReach | null): Plan;
31
+ plan(input: unknown, reach: PortReach | null): Promise<Plan>;
32
32
  query(plan: Plan): Promise<QueryResult>;
33
33
  watchPlan(plan: Plan, deliver: Deliver, fail: Fail): () => void;
34
34
  search(input: unknown, reach: PortReach | null): Promise<SearchResult>;
35
35
  watchReadiness(port: ReadinessPort, reach: PortReach | null, deliver: (readiness: Readiness) => void): () => void;
36
- locked(room: string): boolean;
37
- lockedRooms(): readonly string[];
36
+ locked(room: string): Promise<boolean>;
37
+ lockedRooms(): Promise<readonly string[]>;
38
38
  watchLocks(notify: () => void): () => void;
39
- located(room: string, path: string, destination: string): ReachedDocument | null;
40
- room(locator: string): AppRoom | undefined;
39
+ located(room: string, path: string, destination: string): Promise<ReachedDocument | null>;
40
+ room(locator: string): Promise<AppRoom | undefined>;
41
41
  };
42
42
  export declare function holds(reach: PortReach | null, room: string): boolean;
43
43
  export declare function governs(reach: PortReach | null, room: {
@@ -1 +1 @@
1
- {"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reach.d.ts","sourceRoot":"","sources":["../src/reach.ts"],"names":[],"mappings":"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"}
package/dist/reach.js CHANGED
@@ -170,15 +170,65 @@ export function narrowed(runtime, given, port) {
170
170
  stop();
171
171
  };
172
172
  }
173
- const unlocking = (rooms) => {
174
- const locked = (rooms ?? []).filter((room) => runtime.locked(room));
175
- return locked.length === 0
176
- ? null
177
- : { pending: locked.map((room) => ({ room, awaits: 'unlock' })) };
173
+ const unlocking = (rooms, locked) => {
174
+ const held = (rooms ?? []).filter((room) => locked.includes(room));
175
+ return held.length === 0 ? null : { pending: held.map((room) => ({ room, awaits: 'unlock' })) };
178
176
  };
179
- const unlocked = (entries) => entries.filter((entry) => !runtime.locked(entry.room));
180
- const intoLocked = (held) => held.some((move) => move?.room !== undefined && runtime.locked(move.room));
177
+ const unlocked = (entries, locked) => entries.filter((entry) => !locked.includes(entry.room));
178
+ const intoLocked = async (held) => {
179
+ for (const move of held) {
180
+ if (move?.room !== undefined && (await runtime.locked(move.room)))
181
+ return true;
182
+ }
183
+ return false;
184
+ };
185
+ function ordered(deliver) {
186
+ let open = true;
187
+ let shown = Promise.resolve();
188
+ return {
189
+ push(making) {
190
+ shown = shown.then(() => making.then((value) => {
191
+ if (open)
192
+ deliver(value);
193
+ }, () => { }), () => { });
194
+ },
195
+ stop() {
196
+ open = false;
197
+ },
198
+ };
199
+ }
200
+ function unlockedWatch(topic, input, deliver, fail, within) {
201
+ const shown = ordered(deliver);
202
+ const stop = watch(topic, input, (message) => {
203
+ shown.push(runtime.lockedRooms().then((locked) => within(message, locked)));
204
+ }, fail);
205
+ return () => {
206
+ shown.stop();
207
+ stop();
208
+ };
209
+ }
210
+ function lockedFirst(room, start, shut) {
211
+ let open = true;
212
+ let stop = () => { };
213
+ void (async () => {
214
+ const closed = !holds(reach, room) || (await runtime.locked(room));
215
+ if (!open)
216
+ return;
217
+ if (closed)
218
+ shut();
219
+ else
220
+ stop = start();
221
+ })();
222
+ return () => {
223
+ open = false;
224
+ stop();
225
+ };
226
+ }
181
227
  const within = (topic, input, deliver, fail) => {
228
+ if (topic === 'read' && reach !== null) {
229
+ fail(deviceUnreached());
230
+ return () => { };
231
+ }
182
232
  if (topic === 'rooms') {
183
233
  return following(() => watch(topic, input, (rooms) => deliver(roomsWithin(reach, rooms)), fail));
184
234
  }
@@ -186,55 +236,59 @@ export function narrowed(runtime, given, port) {
186
236
  return following(() => runtime.watchReadiness(port, reach, deliver));
187
237
  }
188
238
  if (topic === 'sync-status') {
189
- return following(() => watch(topic, input, (status) => {
190
- const within = statusWithin(reach, status);
191
- deliver({ ...within, attentionRequired: unlocked(within.attentionRequired) });
192
- }, fail), true);
239
+ return following(() => unlockedWatch(topic, input, deliver, fail, (status, locked) => {
240
+ const shown = statusWithin(reach, status);
241
+ return { ...shown, attentionRequired: unlocked(shown.attentionRequired, locked) };
242
+ }), true);
193
243
  }
194
244
  if (topic === 'room-drafts') {
195
- return following(() => watch(topic, input, (drafts) => deliver(unlocked(draftsWithin(reach, drafts))), fail), true);
245
+ return following(() => unlockedWatch(topic, input, deliver, fail, (drafts, locked) => unlocked(draftsWithin(reach, drafts), locked)), true);
196
246
  }
197
247
  if (topic === 'queue') {
198
248
  const room = input[0];
199
- return following(() => {
200
- if (!holds(reach, room) || runtime.locked(room)) {
201
- deliver([]);
202
- return () => { };
203
- }
204
- return watch(topic, input, (entries) => deliver(queueWithin(reach, room, entries)), fail);
205
- }, true);
249
+ return following(() => lockedFirst(room, () => watch(topic, input, (entries) => deliver(queueWithin(reach, room, entries)), fail), () => deliver([])), true);
206
250
  }
207
251
  if (topic === 'query') {
208
- const plan = runtime.plan(input[0], reach);
252
+ const planning = runtime.plan(input[0], reach);
209
253
  let held = null;
210
254
  return following(() => {
211
- const locked = unlocking(plan.rooms);
212
- if (locked !== null) {
213
- const answer = { result: locked, keys: [] };
214
- if (held === null || changeOf(held, answer) !== null)
215
- deliver(answer);
216
- held = digestOf(answer);
217
- return () => { };
218
- }
219
- let first = true;
220
255
  let open = true;
221
- const heard = (message) => {
222
- if (!first) {
223
- held = digestApplied(held, message);
224
- deliver(message);
256
+ let stop = () => { };
257
+ void (async () => {
258
+ const plan = await planning;
259
+ const locked = await runtime.lockedRooms();
260
+ if (!open)
261
+ return;
262
+ const pending = unlocking(plan.rooms, locked);
263
+ if (pending !== null) {
264
+ const answer = { result: pending, keys: [] };
265
+ if (held === null || changeOf(held, answer) !== null)
266
+ deliver(answer);
267
+ held = digestOf(answer);
225
268
  return;
226
269
  }
227
- first = false;
228
- const change = held === null ? message : changeOf(held, message);
229
- held = digestOf(message);
230
- if (change !== null)
231
- deliver(change);
232
- };
233
- const current = { ...plan, reach: planReach(reach), locked: runtime.lockedRooms() };
234
- const stop = runtime.watchPlan(current, (message) => {
235
- if (open)
236
- heard(message);
237
- }, (error) => {
270
+ let first = true;
271
+ const heard = (message) => {
272
+ if (!first) {
273
+ held = digestApplied(held, message);
274
+ deliver(message);
275
+ return;
276
+ }
277
+ first = false;
278
+ const change = held === null ? message : changeOf(held, message);
279
+ held = digestOf(message);
280
+ if (change !== null)
281
+ deliver(change);
282
+ };
283
+ const current = { ...plan, reach: planReach(reach), locked };
284
+ stop = runtime.watchPlan(current, (message) => {
285
+ if (open)
286
+ heard(message);
287
+ }, (error) => {
288
+ if (open)
289
+ fail(error);
290
+ });
291
+ })().catch((error) => {
238
292
  if (open)
239
293
  fail(error);
240
294
  });
@@ -260,6 +314,12 @@ export function narrowed(runtime, given, port) {
260
314
  return () => { };
261
315
  });
262
316
  }
317
+ if (topic === 'figures') {
318
+ if (reach === null)
319
+ return watch(topic, input, deliver, fail);
320
+ fail(deviceUnreached());
321
+ return () => { };
322
+ }
263
323
  return watch(topic, input, deliver, fail);
264
324
  };
265
325
  const files = new Map();
@@ -278,31 +338,33 @@ export function narrowed(runtime, given, port) {
278
338
  const view = {
279
339
  ...md,
280
340
  rooms: () => md.rooms().then((rooms) => roomsWithin(reach, rooms)),
281
- query: ((input) => {
282
- const plan = runtime.plan(input, reach);
283
- return Promise.resolve(unlocking(plan.rooms) ?? runtime.query({ ...plan, locked: runtime.lockedRooms() }));
341
+ query: (async (input) => {
342
+ const plan = await runtime.plan(input, reach);
343
+ const locked = await runtime.lockedRooms();
344
+ return unlocking(plan.rooms, locked) ?? runtime.query({ ...plan, locked });
284
345
  }),
285
346
  search: (input) => runtime.search(input, reach),
286
- types(room) {
287
- if (holds(reach, room) && runtime.locked(room))
347
+ async types(room) {
348
+ if (holds(reach, room) && (await runtime.locked(room)))
288
349
  throw lockedError(room);
289
350
  if (wholly(reach, room))
290
351
  return md.types(room);
291
352
  if (!holds(reach, room))
292
353
  return structuredClone(UNHELD_TYPES);
293
- return typesWithin(reach, runtime.room(room), md.types(room));
354
+ return typesWithin(reach, await runtime.room(room), await md.types(room));
294
355
  },
295
356
  async save(room, roomDrafts, writtenBy) {
296
357
  if (!holds(reach, room))
297
358
  throw unreached(room);
298
- if (runtime.locked(room))
359
+ if (await runtime.locked(room)) {
299
360
  return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
361
+ }
300
362
  const held = (await Promise.all(roomDrafts.map(({ path }) => md.roomDraft.read(room, path)))).map((draft) => draft?.parts.move);
301
363
  const outside = roomDrafts.find(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]));
302
364
  if (outside !== undefined) {
303
365
  return { outcome: 'refused', code: 'stale', retryable: false, file: outside.path };
304
366
  }
305
- if (intoLocked(held))
367
+ if (await intoLocked(held))
306
368
  return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
307
369
  return savedWithin(reach, room, await md.save(room, roomDrafts, writtenBy));
308
370
  },
@@ -313,47 +375,48 @@ export function narrowed(runtime, given, port) {
313
375
  if (filed !== undefined) {
314
376
  return { outcome: 'refused', code: ATTACH_REQUIRED, retryable: false, file: filed.path };
315
377
  }
316
- if (runtime.locked(room))
378
+ if (await runtime.locked(room)) {
317
379
  return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
380
+ }
318
381
  const held = parts.map(({ path, parts: one }) => readParts(one, path).move);
319
382
  if (parts.some(({ path }, at) => !covers(reach, room, path) || !moves(reach, room, held[at]))) {
320
383
  throw unreached(room);
321
384
  }
322
- if (intoLocked(held))
385
+ if (await intoLocked(held))
323
386
  return { outcome: 'refused', code: ROOM_LOCKED, retryable: true };
324
387
  return savedWithin(reach, room, await md.saveParts(room, parts, writtenBy));
325
388
  },
326
- resolve(room, path, destination) {
327
- const at = runtime.located(room, path, destination);
389
+ async resolve(room, path, destination) {
390
+ const at = await runtime.located(room, path, destination);
328
391
  return at !== null && !covers(reach, at.room, at.path)
329
- ? Promise.resolve(UNREADABLE)
392
+ ? UNREADABLE
330
393
  : md.resolve(room, path, destination);
331
394
  },
332
- history: (room, path, query) => !covers(reach, room, path)
333
- ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
334
- : runtime.locked(room)
335
- ? Promise.resolve(lockedRoom(room))
395
+ history: async (room, path, query) => !covers(reach, room, path)
396
+ ? failure({ kind: 'room-not-readable', locator: room })
397
+ : (await runtime.locked(room))
398
+ ? lockedRoom(room)
336
399
  : md.history(room, path, query),
337
400
  binaryFile: {
338
- read: (room, path, revision) => !covers(reach, room, path)
339
- ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
340
- : runtime.locked(room)
341
- ? Promise.resolve(lockedRoom(room))
401
+ read: async (room, path, revision) => !covers(reach, room, path)
402
+ ? failure({ kind: 'room-not-readable', locator: room })
403
+ : (await runtime.locked(room))
404
+ ? lockedRoom(room)
342
405
  : hand(md.binaryFile.read(room, path, revision)),
343
- link: (room, path, revision) => !covers(reach, room, path)
344
- ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
345
- : runtime.locked(room)
346
- ? Promise.resolve(lockedRoom(room))
406
+ link: async (room, path, revision) => !covers(reach, room, path)
407
+ ? failure({ kind: 'room-not-readable', locator: room })
408
+ : (await runtime.locked(room))
409
+ ? lockedRoom(room)
347
410
  : md.binaryFile.link(room, path, revision),
348
- show: (room, path, revision) => !covers(reach, room, path)
349
- ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
350
- : runtime.locked(room)
351
- ? Promise.resolve(lockedRoom(room))
411
+ show: async (room, path, revision) => !covers(reach, room, path)
412
+ ? failure({ kind: 'room-not-readable', locator: room })
413
+ : (await runtime.locked(room))
414
+ ? lockedRoom(room)
352
415
  : hand(md.binaryFile.show(room, path, revision)),
353
- attach: (room, file) => !wholly(reach, room)
354
- ? Promise.resolve(failure({ kind: 'room-not-readable', locator: room }))
355
- : runtime.locked(room)
356
- ? Promise.resolve(lockedRoom(room))
416
+ attach: async (room, file) => !wholly(reach, room)
417
+ ? failure({ kind: 'room-not-readable', locator: room })
418
+ : (await runtime.locked(room))
419
+ ? lockedRoom(room)
357
420
  : md.binaryFile.attach(room, file),
358
421
  async part(file, part) {
359
422
  const key = files.get(file);
@@ -366,44 +429,38 @@ export function narrowed(runtime, given, port) {
366
429
  },
367
430
  },
368
431
  reached: async (room, roomVersion, path) => (path === undefined ? wholly(reach, room) : covers(reach, room, path)) &&
369
- !runtime.locked(room) &&
432
+ !(await runtime.locked(room)) &&
370
433
  (await md.reached(room, roomVersion, path)),
371
434
  log: () => (reach === null ? md.log() : ''),
372
435
  cleanUp: () => (reach === null ? md.cleanUp() : Promise.reject(deviceUnreached())),
373
436
  unsent: () => (reach === null ? md.unsent() : Promise.reject(deviceUnreached())),
374
437
  reset: () => (reach === null ? md.reset() : Promise.reject(deviceUnreached())),
438
+ readAgain: () => (reach === null ? md.readAgain() : Promise.reject(deviceUnreached())),
375
439
  roomDraft: {
376
- list: () => md.roomDraft.list().then((drafts) => unlocked(draftsWithin(reach, drafts))),
440
+ list: async () => unlocked(draftsWithin(reach, await md.roomDraft.list()), await runtime.lockedRooms()),
377
441
  async read(room, path) {
378
442
  if (!covers(reach, room, path))
379
443
  return null;
380
- if (runtime.locked(room))
444
+ if (await runtime.locked(room))
381
445
  throw lockedError(room);
382
446
  return shownDraft(reach, await md.roomDraft.read(room, path));
383
447
  },
384
- write(room, path, revision, parts, next) {
385
- try {
386
- if (reach !== null && carriesFile(parts))
387
- throw attachRequired();
388
- const move = readParts(parts, path).move;
389
- if (!covers(reach, room, path) || !moves(reach, room, move))
390
- throw unreached(room);
391
- if (runtime.locked(room))
392
- throw lockedError(room);
393
- if (intoLocked([move]))
394
- throw lockedError(move.room);
395
- }
396
- catch (error) {
397
- return Promise.reject(error);
398
- }
399
- return md.roomDraft
400
- .write(room, path, revision, parts, next)
401
- .then((written) => writeWithin(reach, written));
448
+ async write(room, path, revision, parts, next) {
449
+ if (reach !== null && carriesFile(parts))
450
+ throw attachRequired();
451
+ const move = readParts(parts, path).move;
452
+ if (!covers(reach, room, path) || !moves(reach, room, move))
453
+ throw unreached(room);
454
+ if (await runtime.locked(room))
455
+ throw lockedError(room);
456
+ if (await intoLocked([move]))
457
+ throw lockedError(move.room);
458
+ return writeWithin(reach, await md.roomDraft.write(room, path, revision, parts, next));
402
459
  },
403
460
  async discard(room, path, revision) {
404
461
  if (!covers(reach, room, path))
405
462
  return staleWrite(null);
406
- if (runtime.locked(room))
463
+ if (await runtime.locked(room))
407
464
  throw lockedError(room);
408
465
  return writeWithin(reach, await md.roomDraft.discard(room, path, revision));
409
466
  },
package/dist/read.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export type Fields = Readonly<Record<string, unknown>>;
2
+ export declare const EXCERPT = 512;
3
+ export declare function excerpt(said: string): string;
4
+ export declare function record(entry: unknown): Fields;
5
+ export declare function text(fields: Fields, name: string): string | null;
6
+ export declare function list(fields: Fields, name: string): readonly unknown[];
7
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../src/read.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEvD,eAAO,MAAM,OAAO,MAAM,CAAC;AAE3B,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAI7C;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGhE;AAED,wBAAgB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,OAAO,EAAE,CAGrE"}
package/dist/read.js ADDED
@@ -0,0 +1,17 @@
1
+ export const EXCERPT = 512;
2
+ export function excerpt(said) {
3
+ return [...said.slice(0, EXCERPT * 2)].slice(0, EXCERPT).join('');
4
+ }
5
+ export function record(entry) {
6
+ return typeof entry === 'object' && entry !== null && !Array.isArray(entry)
7
+ ? entry
8
+ : {};
9
+ }
10
+ export function text(fields, name) {
11
+ const value = fields[name];
12
+ return typeof value === 'string' && value !== '' ? value : null;
13
+ }
14
+ export function list(fields, name) {
15
+ const value = fields[name];
16
+ return Array.isArray(value) ? value : [];
17
+ }
@@ -0,0 +1,35 @@
1
+ import { type CallResult } from './outcome.js';
2
+ import type { Recovery } from './recovery.js';
3
+ import type { Connection, RuntimeDatabase } from './tables.js';
4
+ export declare const READ_TABLES: readonly string[];
5
+ export type ReadAt = {
6
+ readonly name: string;
7
+ readonly input: string;
8
+ readonly build: string;
9
+ };
10
+ export type ObservedRead = {
11
+ readonly answer: unknown;
12
+ readonly failure: CallResult | null;
13
+ readonly kept: boolean;
14
+ };
15
+ export type ReadAnswers = {
16
+ watch(name: string, input: unknown, deliver: (read: ObservedRead) => void): () => void;
17
+ again(): void;
18
+ reopened(): void;
19
+ };
20
+ export type ReadAnswersOptions = {
21
+ readonly database: RuntimeDatabase;
22
+ readonly build: string;
23
+ readonly unkept: readonly string[];
24
+ readonly recovery: Recovery;
25
+ call(name: string, input: unknown): Promise<CallResult>;
26
+ online(): boolean;
27
+ closed(): boolean;
28
+ full(): boolean;
29
+ filled(): void;
30
+ };
31
+ export declare function storedRead(connection: Connection, { name, input, build }: ReadAt): string | null;
32
+ export declare function keptRead(connection: Connection, { name, input, build }: ReadAt, answer: string): null;
33
+ export declare function readsOfOtherBuildsForgotten(connection: Connection, build: string): null;
34
+ export declare function readAnswers(options: ReadAnswersOptions): ReadAnswers;
35
+ //# sourceMappingURL=reads.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reads.d.ts","sourceRoot":"","sources":["../src/reads.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE/D,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAExC,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACvF,KAAK,IAAI,IAAI,CAAC;IACd,QAAQ,IAAI,IAAI,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACxD,MAAM,IAAI,OAAO,CAAC;IAClB,MAAM,IAAI,OAAO,CAAC;IAClB,IAAI,IAAI,OAAO,CAAC;IAChB,MAAM,IAAI,IAAI,CAAC;CAChB,CAAC;AAaF,wBAAgB,UAAU,CAAC,UAAU,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhG;AAED,wBAAgB,QAAQ,CACtB,UAAU,EAAE,UAAU,EACtB,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,MAAM,EAC9B,MAAM,EAAE,MAAM,GACb,IAAI,CAMN;AAED,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGvF;AAMD,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAwGpE"}