@agentshouse/mdruntime 0.1.0-cfbf80d8d4644 → 0.1.0-cfcbb238a5fa0

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 (201) hide show
  1. package/AGENTS.md +270 -203
  2. package/README.md +20 -10
  3. package/dist/acquisition.d.ts +14 -0
  4. package/dist/acquisition.d.ts.map +1 -0
  5. package/dist/acquisition.js +24 -0
  6. package/dist/adapter.d.ts +83 -20
  7. package/dist/adapter.d.ts.map +1 -1
  8. package/dist/attached-model.d.ts.map +1 -1
  9. package/dist/attached-model.js +15 -2
  10. package/dist/attempt.d.ts +16 -0
  11. package/dist/attempt.d.ts.map +1 -0
  12. package/dist/attempt.js +70 -0
  13. package/dist/binary.d.ts +23 -0
  14. package/dist/binary.d.ts.map +1 -0
  15. package/dist/binary.js +8 -0
  16. package/dist/bootstrap.d.ts +18 -5
  17. package/dist/bootstrap.d.ts.map +1 -1
  18. package/dist/bootstrap.js +113 -37
  19. package/dist/change-set.d.ts +2 -0
  20. package/dist/change-set.d.ts.map +1 -1
  21. package/dist/change-set.js +49 -16
  22. package/dist/change.d.ts +15 -0
  23. package/dist/change.d.ts.map +1 -1
  24. package/dist/change.js +26 -1
  25. package/dist/chat/acts.d.ts +33 -0
  26. package/dist/chat/acts.d.ts.map +1 -0
  27. package/dist/chat/acts.js +36 -0
  28. package/dist/chat/context.d.ts +3 -0
  29. package/dist/chat/context.d.ts.map +1 -0
  30. package/dist/chat/context.js +10 -0
  31. package/dist/chat/input.d.ts +9 -0
  32. package/dist/chat/input.d.ts.map +1 -0
  33. package/dist/chat/input.js +99 -0
  34. package/dist/chat/kit.d.ts +61 -0
  35. package/dist/chat/kit.d.ts.map +1 -0
  36. package/dist/chat/kit.js +123 -0
  37. package/dist/chat/lasting.d.ts +6 -0
  38. package/dist/chat/lasting.d.ts.map +1 -0
  39. package/dist/chat/lasting.js +19 -0
  40. package/dist/chat/list.d.ts +27 -0
  41. package/dist/chat/list.d.ts.map +1 -0
  42. package/dist/chat/list.js +63 -0
  43. package/dist/chat/markdown.d.ts +20 -0
  44. package/dist/chat/markdown.d.ts.map +1 -0
  45. package/dist/chat/markdown.js +188 -0
  46. package/dist/chat/message.d.ts +6 -0
  47. package/dist/chat/message.d.ts.map +1 -0
  48. package/dist/chat/message.js +192 -0
  49. package/dist/chat/messages.d.ts +22 -0
  50. package/dist/chat/messages.d.ts.map +1 -0
  51. package/dist/chat/messages.js +155 -0
  52. package/dist/chat/name.d.ts +6 -0
  53. package/dist/chat/name.d.ts.map +1 -0
  54. package/dist/chat/name.js +37 -0
  55. package/dist/chat/opened.d.ts +11 -0
  56. package/dist/chat/opened.d.ts.map +1 -0
  57. package/dist/chat/opened.js +17 -0
  58. package/dist/chat/overlay.d.ts +31 -0
  59. package/dist/chat/overlay.d.ts.map +1 -0
  60. package/dist/chat/overlay.js +97 -0
  61. package/dist/chat/parts.d.ts +57 -0
  62. package/dist/chat/parts.d.ts.map +1 -0
  63. package/dist/chat/parts.js +119 -0
  64. package/dist/chat/process.d.ts +20 -0
  65. package/dist/chat/process.d.ts.map +1 -0
  66. package/dist/chat/process.js +32 -0
  67. package/dist/chat/provider.d.ts +63 -0
  68. package/dist/chat/provider.d.ts.map +1 -0
  69. package/dist/chat/provider.js +629 -0
  70. package/dist/chat/question.d.ts +9 -0
  71. package/dist/chat/question.d.ts.map +1 -0
  72. package/dist/chat/question.js +80 -0
  73. package/dist/chat/questions.d.ts +31 -0
  74. package/dist/chat/questions.d.ts.map +1 -0
  75. package/dist/chat/questions.js +111 -0
  76. package/dist/chat/read.d.ts +5 -0
  77. package/dist/chat/read.d.ts.map +1 -0
  78. package/dist/chat/read.js +13 -0
  79. package/dist/chat/ready.d.ts +34 -0
  80. package/dist/chat/ready.d.ts.map +1 -0
  81. package/dist/chat/ready.js +91 -0
  82. package/dist/chat/style.d.ts +4 -0
  83. package/dist/chat/style.d.ts.map +1 -0
  84. package/dist/chat/style.js +302 -0
  85. package/dist/chat.d.ts +14 -0
  86. package/dist/chat.d.ts.map +1 -0
  87. package/dist/chat.js +8 -0
  88. package/dist/client.d.ts +25 -12
  89. package/dist/client.d.ts.map +1 -1
  90. package/dist/client.js +75 -16
  91. package/dist/collection.d.ts +21 -12
  92. package/dist/collection.d.ts.map +1 -1
  93. package/dist/collection.js +271 -23
  94. package/dist/connection.d.ts +44 -15
  95. package/dist/connection.d.ts.map +1 -1
  96. package/dist/connection.js +1788 -400
  97. package/dist/conversation.d.ts +26 -10
  98. package/dist/conversation.d.ts.map +1 -1
  99. package/dist/conversation.js +414 -148
  100. package/dist/durability.d.ts +7 -1
  101. package/dist/durability.d.ts.map +1 -1
  102. package/dist/entry.d.ts +17 -0
  103. package/dist/entry.d.ts.map +1 -0
  104. package/dist/entry.js +156 -0
  105. package/dist/expectation.d.ts +21 -0
  106. package/dist/expectation.d.ts.map +1 -0
  107. package/dist/expectation.js +70 -0
  108. package/dist/failure.d.ts +13 -0
  109. package/dist/failure.d.ts.map +1 -0
  110. package/dist/failure.js +19 -0
  111. package/dist/fence.d.ts +6 -0
  112. package/dist/fence.d.ts.map +1 -0
  113. package/dist/fence.js +10 -0
  114. package/dist/host.d.ts +18 -2
  115. package/dist/host.d.ts.map +1 -1
  116. package/dist/host.js +97 -19
  117. package/dist/identity.d.ts +5 -0
  118. package/dist/identity.d.ts.map +1 -1
  119. package/dist/identity.js +19 -1
  120. package/dist/index.d.ts +16 -8
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js +5 -0
  123. package/dist/memory.d.ts +11 -4
  124. package/dist/memory.d.ts.map +1 -1
  125. package/dist/memory.js +87 -25
  126. package/dist/model.d.ts +14 -4
  127. package/dist/model.d.ts.map +1 -1
  128. package/dist/model.js +12 -1
  129. package/dist/observation.d.ts +5 -2
  130. package/dist/observation.d.ts.map +1 -1
  131. package/dist/observation.js +22 -11
  132. package/dist/open.d.ts +2 -0
  133. package/dist/open.d.ts.map +1 -0
  134. package/dist/open.js +1 -0
  135. package/dist/outcome.d.ts +32 -3
  136. package/dist/outcome.d.ts.map +1 -1
  137. package/dist/outcome.js +42 -1
  138. package/dist/overlay.d.ts +16 -3
  139. package/dist/overlay.d.ts.map +1 -1
  140. package/dist/overlay.js +118 -77
  141. package/dist/query.d.ts +40 -4
  142. package/dist/query.d.ts.map +1 -1
  143. package/dist/query.js +60 -21
  144. package/dist/reach.d.ts +8 -3
  145. package/dist/reach.d.ts.map +1 -1
  146. package/dist/reach.js +60 -24
  147. package/dist/react.d.ts +31 -18
  148. package/dist/react.d.ts.map +1 -1
  149. package/dist/react.js +15 -11
  150. package/dist/read-side.d.ts +13 -6
  151. package/dist/read-side.d.ts.map +1 -1
  152. package/dist/read-side.js +394 -129
  153. package/dist/readiness.d.ts +53 -0
  154. package/dist/readiness.d.ts.map +1 -0
  155. package/dist/readiness.js +33 -0
  156. package/dist/reads.d.ts +11 -0
  157. package/dist/reads.d.ts.map +1 -0
  158. package/dist/reads.js +98 -0
  159. package/dist/recovery.d.ts +25 -0
  160. package/dist/recovery.d.ts.map +1 -0
  161. package/dist/recovery.js +197 -0
  162. package/dist/refresh.d.ts +13 -3
  163. package/dist/refresh.d.ts.map +1 -1
  164. package/dist/refresh.js +49 -38
  165. package/dist/replica.d.ts +9 -6
  166. package/dist/replica.d.ts.map +1 -1
  167. package/dist/replica.js +125 -68
  168. package/dist/room-draft.d.ts +38 -9
  169. package/dist/room-draft.d.ts.map +1 -1
  170. package/dist/room-draft.js +134 -25
  171. package/dist/rows.d.ts +11 -14
  172. package/dist/rows.d.ts.map +1 -1
  173. package/dist/rows.js +89 -49
  174. package/dist/save.d.ts +31 -1
  175. package/dist/save.d.ts.map +1 -1
  176. package/dist/save.js +376 -47
  177. package/dist/search.d.ts +39 -8
  178. package/dist/search.d.ts.map +1 -1
  179. package/dist/search.js +132 -46
  180. package/dist/seed.d.ts +16 -0
  181. package/dist/seed.d.ts.map +1 -0
  182. package/dist/seed.js +61 -0
  183. package/dist/shared.d.ts +11 -0
  184. package/dist/shared.d.ts.map +1 -0
  185. package/dist/shared.js +368 -0
  186. package/dist/status.d.ts +6 -2
  187. package/dist/status.d.ts.map +1 -1
  188. package/dist/status.js +0 -8
  189. package/dist/store.d.ts +75 -18
  190. package/dist/store.d.ts.map +1 -1
  191. package/dist/store.js +539 -200
  192. package/dist/turn.d.ts +7 -0
  193. package/dist/turn.d.ts.map +1 -0
  194. package/dist/turn.js +45 -0
  195. package/dist/wire.d.ts +141 -33
  196. package/dist/wire.d.ts.map +1 -1
  197. package/dist/wire.js +61 -31
  198. package/package.json +26 -14
  199. package/dist/attachment.d.ts +0 -3
  200. package/dist/attachment.d.ts.map +0 -1
  201. package/dist/attachment.js +0 -8
@@ -1,19 +1,20 @@
1
- import { apply, parse, serialize } from '@agentshouse/mdmodel';
1
+ import { apply, equalValue, frontmatterValue, parse, serialize } from '@agentshouse/mdmodel';
2
+ import { runtimeError } from './failure.js';
3
+ import { hexDigest } from './file.js';
4
+ import { binaryLocalId } from './identity.js';
2
5
  import { normalize } from './paths.js';
6
+ export function returnedBy(kind) {
7
+ return { kind, code: kind, fields: {}, retryable: false };
8
+ }
9
+ export function staleWrite(current) {
10
+ return { outcome: 'stale', code: 'stale', retryable: false, current };
11
+ }
3
12
  function malformed() {
4
- throw new Error('room-draft-malformed');
13
+ throw runtimeError('room-draft-malformed');
5
14
  }
6
15
  function plain(value) {
7
16
  return typeof value === 'object' && value !== null && !Array.isArray(value);
8
17
  }
9
- function frontmatterValue(value) {
10
- if (Array.isArray(value))
11
- return value.every(frontmatterValue);
12
- return (value === null ||
13
- typeof value === 'string' ||
14
- typeof value === 'boolean' ||
15
- (typeof value === 'number' && Number.isFinite(value)));
16
- }
17
18
  function text(value) {
18
19
  return typeof value === 'string' ? value : malformed();
19
20
  }
@@ -61,6 +62,7 @@ const PART_NAMES = new Set([
61
62
  'creation',
62
63
  'move',
63
64
  'removal',
65
+ 'file',
64
66
  ]);
65
67
  export function readParts(value) {
66
68
  if (!plain(value) || Object.keys(value).some((name) => !PART_NAMES.has(name)))
@@ -96,6 +98,13 @@ export function readParts(value) {
96
98
  const base = markdownBase(value.removal.base);
97
99
  parts.removal = base === undefined ? {} : { base };
98
100
  }
101
+ if (value.file !== undefined) {
102
+ if (!plain(value.file) || !(value.file.blob instanceof Blob))
103
+ malformed();
104
+ if (Object.keys(value).length > 1)
105
+ throw runtimeError('room-draft-file-exclusive');
106
+ parts.file = { blob: value.file.blob };
107
+ }
99
108
  return parts;
100
109
  }
101
110
  function named(record) {
@@ -108,7 +117,7 @@ function kept(prior, base) {
108
117
  if (prior !== undefined)
109
118
  return prior.base;
110
119
  if (base === undefined)
111
- throw new Error('room-draft-base-missing');
120
+ throw runtimeError('room-draft-base-missing');
112
121
  return base;
113
122
  }
114
123
  function editsText(parts) {
@@ -116,9 +125,32 @@ function editsText(parts) {
116
125
  named(parts.fields).length > 0 ||
117
126
  named(parts.sections).length > 0);
118
127
  }
119
- export function held(current, parts) {
128
+ export function held(current, parts, file) {
120
129
  if (parts.markdown !== undefined && editsText(parts)) {
121
- throw new Error('room-draft-markdown-exclusive');
130
+ throw runtimeError('room-draft-markdown-exclusive');
131
+ }
132
+ if (file !== undefined) {
133
+ if (current !== undefined && current.file === undefined) {
134
+ throw runtimeError('room-draft-file-exclusive');
135
+ }
136
+ return { file: { ...file, base: current?.file === undefined ? file.base : current.file.base } };
137
+ }
138
+ if (current?.file !== undefined) {
139
+ if (editsText(parts) ||
140
+ parts.markdown !== undefined ||
141
+ parts.creation !== undefined ||
142
+ (parts.move === undefined && parts.removal === undefined)) {
143
+ throw runtimeError('room-draft-file-exclusive');
144
+ }
145
+ return {
146
+ file: current.file,
147
+ ...(parts.move === undefined
148
+ ? {}
149
+ : { move: { to: parts.move.to, base: kept(current.move, parts.move.base) } }),
150
+ ...(parts.removal === undefined
151
+ ? {}
152
+ : { removal: { base: kept(current.removal, parts.removal.base) } }),
153
+ };
122
154
  }
123
155
  const next = {};
124
156
  const fields = named(parts.fields);
@@ -156,17 +188,9 @@ export function held(current, parts) {
156
188
  next.removal = { base: kept(current?.removal, parts.removal.base) };
157
189
  }
158
190
  if (Object.keys(next).length === 0)
159
- throw new Error('room-draft-empty');
191
+ throw runtimeError('room-draft-empty');
160
192
  return next;
161
193
  }
162
- export function equalValue(left, right) {
163
- if (left === right)
164
- return true;
165
- return (Array.isArray(left) &&
166
- Array.isArray(right) &&
167
- left.length === right.length &&
168
- left.every((item, index) => equalValue(item, right[index])));
169
- }
170
194
  function sameField(left, right) {
171
195
  if (left === null || right === null)
172
196
  return left === right;
@@ -174,7 +198,7 @@ function sameField(left, right) {
174
198
  }
175
199
  export function underneath(parts, path, visible) {
176
200
  const markdown = visible?.documents[path] ?? null;
177
- const document = visible?.collection.documents[path];
201
+ const document = visible?.collection.document(path);
178
202
  const report = {};
179
203
  const fields = {};
180
204
  for (const [name, part] of named(parts.fields)) {
@@ -207,8 +231,28 @@ export function underneath(parts, path, visible) {
207
231
  report.move = markdown;
208
232
  if (parts.removal !== undefined && markdown !== parts.removal.base)
209
233
  report.removal = markdown;
234
+ if (parts.file !== undefined) {
235
+ const file = binaryBase(visible, path);
236
+ if (file !== parts.file.base || markdown !== null)
237
+ report.file = file;
238
+ }
210
239
  return report;
211
240
  }
241
+ const UNTYPED_MEDIA_TYPE = 'application/octet-stream';
242
+ export async function heldFile(blob, base) {
243
+ const bytes = await blob.arrayBuffer();
244
+ return {
245
+ blob,
246
+ localId: binaryLocalId(),
247
+ byteLength: bytes.byteLength,
248
+ mediaType: blob.type === '' ? UNTYPED_MEDIA_TYPE : blob.type,
249
+ sha256: hexDigest(await crypto.subtle.digest('SHA-256', bytes)),
250
+ base,
251
+ };
252
+ }
253
+ export function binaryBase(visible, path) {
254
+ return visible?.binaries[path] === undefined ? null : (visible.revisions[path] ?? null);
255
+ }
212
256
  export function changedParts(path, report) {
213
257
  return [
214
258
  ...(report.creation === undefined ? [] : [{ path, part: 'creation' }]),
@@ -218,6 +262,7 @@ export function changedParts(path, report) {
218
262
  ...(report.markdown === undefined ? [] : [{ path, part: 'markdown' }]),
219
263
  ...(report.move === undefined ? [] : [{ path, part: 'move' }]),
220
264
  ...(report.removal === undefined ? [] : [{ path, part: 'removal' }]),
265
+ ...(report.file === undefined ? [] : [{ path, part: 'file' }]),
221
266
  ];
222
267
  }
223
268
  function joined(existing, returned) {
@@ -243,7 +288,7 @@ function frontmatterOf(fields) {
243
288
  }
244
289
  return serialize(document);
245
290
  }
246
- function concatenated(markdown, parts) {
291
+ export function partsAfter(markdown, parts) {
247
292
  const fields = named(parts.fields);
248
293
  const pieces = [
249
294
  ...(fields.length === 0 ? [] : [frontmatterOf(fields)]),
@@ -274,18 +319,21 @@ export function returnedInto(existing, returned) {
274
319
  delete next.fields;
275
320
  delete next.sections;
276
321
  delete next.preamble;
277
- const value = concatenated(whole.value, existing.markdown === undefined ? existing : returned);
322
+ const value = partsAfter(whole.value, existing.markdown === undefined ? existing : returned);
278
323
  next.markdown = { value, base: whole.base };
279
324
  }
280
325
  const creation = existing.creation ?? returned.creation;
281
326
  const move = existing.move ?? returned.move;
282
327
  const removal = existing.removal ?? returned.removal;
328
+ const file = existing.file ?? returned.file;
283
329
  if (creation !== undefined)
284
330
  next.creation = creation;
285
331
  if (move !== undefined)
286
332
  next.move = move;
287
333
  if (removal !== undefined)
288
334
  next.removal = removal;
335
+ if (file !== undefined)
336
+ next.file = file;
289
337
  return next;
290
338
  }
291
339
  export function moveTarget(move) {
@@ -321,9 +369,70 @@ export function changesOf(path, parts) {
321
369
  if (parts.markdown !== undefined) {
322
370
  changes.push({ kind: 'replace', path, content: parts.markdown.value });
323
371
  }
372
+ if (parts.file !== undefined && parts.removal === undefined) {
373
+ const { base, ...file } = parts.file;
374
+ const at = parts.move === undefined ? path : moveTarget(parts.move);
375
+ if (base !== null && at !== path)
376
+ changes.push({ kind: 'move', path, to: at });
377
+ changes.push({ kind: 'binary', path: at, ...file });
378
+ if (base === null && at !== path)
379
+ bases.push({ kind: 'absent', path: at });
380
+ return { changes, bases };
381
+ }
382
+ if (parts.file?.base === null)
383
+ return { changes, bases };
324
384
  if (parts.move !== undefined)
325
385
  changes.push({ kind: 'move', path, to: moveTarget(parts.move) });
326
386
  if (parts.removal !== undefined)
327
387
  changes.push({ kind: 'remove', path });
328
388
  return { changes, bases };
329
389
  }
390
+ function rebased(before, after) {
391
+ return before === undefined ? after : { ...after, base: before.base };
392
+ }
393
+ function rebasedAll(before, after) {
394
+ return {
395
+ ...before,
396
+ ...Object.fromEntries(Object.entries(after).map(([name, part]) => [name, rebased(before?.[name], part)])),
397
+ };
398
+ }
399
+ export function joinedDraft(carried, saved) {
400
+ const draft = saved.find((item) => item.path === carried.path);
401
+ if (draft === undefined)
402
+ return carried;
403
+ const held = carried.parts;
404
+ const next = draft.parts;
405
+ return {
406
+ path: carried.path,
407
+ parts: {
408
+ ...held,
409
+ ...next,
410
+ ...(next.fields === undefined ? {} : { fields: rebasedAll(held.fields, next.fields) }),
411
+ ...(next.sections === undefined
412
+ ? {}
413
+ : { sections: rebasedAll(held.sections, next.sections) }),
414
+ ...(next.preamble === undefined ? {} : { preamble: rebased(held.preamble, next.preamble) }),
415
+ ...(next.markdown === undefined ? {} : { markdown: rebased(held.markdown, next.markdown) }),
416
+ },
417
+ };
418
+ }
419
+ export function withdrawnDrafts(drafts, changes) {
420
+ return drafts.flatMap((draft) => {
421
+ const file = draft.parts.file;
422
+ const at = draft.parts.move?.to ?? draft.path;
423
+ const change = changes.find((item) => (item.kind === 'move' || item.kind === 'remove') && item.path === at);
424
+ if (file === undefined || change === undefined)
425
+ return [draft];
426
+ if (change.kind === 'move') {
427
+ return [
428
+ {
429
+ path: draft.path,
430
+ parts: change.to === draft.path ? { file } : { file, move: { to: change.to, base: null } },
431
+ },
432
+ ];
433
+ }
434
+ return file.base === null
435
+ ? []
436
+ : [{ path: draft.path, parts: { file, removal: { base: null } } }];
437
+ });
438
+ }
package/dist/rows.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { type Document } from '@agentshouse/mdmodel';
1
+ import { type Frontmatter } from '@agentshouse/mdmodel';
2
2
  import type { HeadChange } from './adapter.js';
3
+ import type { BinaryFileRecord } from './binary.js';
3
4
  import { type Composition } from './collection.js';
4
5
  type Fields = Readonly<Record<string, unknown>>;
5
6
  export type DocumentRow = {
@@ -10,19 +11,12 @@ export type DocumentRow = {
10
11
  type: string | null;
11
12
  fields: Fields;
12
13
  values: Fields;
13
- sizes: Readonly<Record<string, number>>;
14
+ reached: Readonly<Record<string, readonly unknown[]>>;
14
15
  directories: readonly string[];
15
- body: string;
16
+ text: string | null;
16
17
  change: HeadChange | null;
17
- };
18
- export type BodyRow = {
19
- key: string;
20
- kind: 'body';
21
- room: string;
22
- path: string;
23
- preamble: string;
24
- sections: Readonly<Record<string, string>>;
25
- markdown: string;
18
+ fileId: string | null;
19
+ binary: BinaryFileRecord | null;
26
20
  };
27
21
  export type ReferenceRow = {
28
22
  key: string;
@@ -31,11 +25,14 @@ export type ReferenceRow = {
31
25
  source: string;
32
26
  target: string;
33
27
  field: string;
28
+ forms: readonly string[];
34
29
  path: string;
35
30
  type: string;
36
31
  };
37
- export type Row = DocumentRow | BodyRow | ReferenceRow;
32
+ export type Row = DocumentRow | ReferenceRow;
38
33
  export declare function documentKey(room: string, path: string): string;
39
- export declare function rowsOf(room: string, path: string, document: Document | null, composition: Composition, change: HeadChange | null): readonly Row[];
34
+ export declare function roomOfKey(key: string): string;
35
+ export declare function markdownPath(path: string): boolean;
36
+ export declare function rowsOf(room: string, path: string, document: Frontmatter | null, composition: Composition, change: HeadChange | null, fileId: string | null, binary: BinaryFileRecord | null): readonly Row[];
40
37
  export {};
41
38
  //# sourceMappingURL=rows.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9D,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEhD,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,CAAC;AAMvD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAiBD,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GAAG,IAAI,EACzB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,UAAU,GAAG,IAAI,GACxB,SAAS,GAAG,EAAE,CAsEhB"}
1
+ {"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9D,KAAK,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAEhD,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,CAAC;IACtD,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,GAAG,GAAG,WAAW,GAAG,YAAY,CAAC;AAM7C,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAmFD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,WAAW,GAAG,IAAI,EAC5B,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,MAAM,EAAE,gBAAgB,GAAG,IAAI,GAC9B,SAAS,GAAG,EAAE,CAiEhB"}
package/dist/rows.js CHANGED
@@ -1,30 +1,79 @@
1
- import { target } from '@agentshouse/mdmodel';
1
+ import { ARRAY_INDEX, escapePointer, references, target, } from '@agentshouse/mdmodel';
2
2
  import { governing } from './collection.js';
3
- import { definitionOf, referenceField } from './model.js';
3
+ import { definitionOf } from './model.js';
4
4
  function keyOf(...parts) {
5
5
  return `${parts.join('\u0000')}\u0000`;
6
6
  }
7
7
  export function documentKey(room, path) {
8
8
  return keyOf('d', room, path);
9
9
  }
10
- function targetOf(path, value) {
11
- return typeof value === 'string' ? target(path, value) : null;
10
+ export function roomOfKey(key) {
11
+ return key.split('\u0000')[1];
12
12
  }
13
- function resolved(path, value) {
14
- if (value === null)
15
- return null;
16
- if (!Array.isArray(value))
17
- return targetOf(path, value) ?? undefined;
18
- return value.map((item) => targetOf(path, item)).filter((item) => item !== null);
13
+ function plainObject(value) {
14
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
15
+ }
16
+ function compared(reading, exact, value) {
17
+ if (!reading.references.has(exact))
18
+ return value;
19
+ return (typeof value === 'string' ? target(reading.path, value) : null) ?? undefined;
20
+ }
21
+ function record(reading, node, forms, exact) {
22
+ const value = Array.isArray(node)
23
+ ? node.map((item, index) => compared(reading, `${exact}/${index}`, item))
24
+ : compared(reading, exact, node);
25
+ for (const form of forms) {
26
+ if (form.pending)
27
+ continue;
28
+ (reading.reached[form.text] ??= []).push(value);
29
+ if (!form.through && value !== undefined && !plainObject(value)) {
30
+ reading.values[form.text] = value;
31
+ }
32
+ }
33
+ if (Array.isArray(node) || plainObject(node) || !reading.references.has(exact))
34
+ return;
35
+ const found = compared(reading, exact, node);
36
+ if (typeof found !== 'string')
37
+ return;
38
+ const field = forms
39
+ .map((form) => form.text)
40
+ .reduce((left, right) => (right.length < left.length ? right : left));
41
+ const known = reading.targets.get(`${field}\u0000${found}`);
42
+ const kept = known ?? { field, target: found, forms: new Set() };
43
+ for (const form of forms)
44
+ kept.forms.add(form.text);
45
+ reading.targets.set(`${field}\u0000${found}`, kept);
46
+ }
47
+ function walk(reading, node, forms, exact) {
48
+ record(reading, node, forms, exact);
49
+ if (Array.isArray(node)) {
50
+ node.forEach((item, index) => walk(reading, item, forms.flatMap((form) => [
51
+ ...(form.pending
52
+ ? []
53
+ : [{ text: `${form.text}/${index}`, through: form.through, pending: false }]),
54
+ { text: form.text, through: true, pending: true },
55
+ ]), `${exact}/${index}`));
56
+ return;
57
+ }
58
+ if (!plainObject(node))
59
+ return;
60
+ for (const [key, value] of Object.entries(node)) {
61
+ const segment = escapePointer(key);
62
+ walk(reading, value, forms.flatMap((form) => form.pending && ARRAY_INDEX.test(key)
63
+ ? []
64
+ : [{ text: `${form.text}/${segment}`, through: form.through, pending: false }]), `${exact}/${segment}`);
65
+ }
19
66
  }
20
67
  function directoriesOf(path) {
21
68
  const parts = path.split('/').slice(0, -1);
22
69
  return ['', ...parts.map((_, index) => parts.slice(0, index + 1).join('/'))];
23
70
  }
24
- export function rowsOf(room, path, document, composition, change) {
71
+ export function markdownPath(path) {
72
+ return path.endsWith('.md');
73
+ }
74
+ export function rowsOf(room, path, document, composition, change, fileId, binary) {
25
75
  const key = documentKey(room, path);
26
- const body = keyOf('b', room, path);
27
- if (document === null || !path.endsWith('.md')) {
76
+ if (document === null || !markdownPath(path)) {
28
77
  return [
29
78
  {
30
79
  key,
@@ -34,41 +83,29 @@ export function rowsOf(room, path, document, composition, change) {
34
83
  type: null,
35
84
  fields: {},
36
85
  values: {},
37
- sizes: {},
86
+ reached: {},
38
87
  directories: directoriesOf(path),
39
- body,
88
+ text: null,
40
89
  change,
90
+ fileId,
91
+ binary,
41
92
  },
42
93
  ];
43
94
  }
44
95
  const type = document.type ?? 'any';
45
96
  const definition = definitionOf(governing(composition, path), document.type);
46
- const values = {};
47
- const sizes = {};
48
- const references = [];
97
+ const reading = {
98
+ path,
99
+ references: new Set(definition === undefined ? [] : references(document, definition).map((one) => one.pointer)),
100
+ values: {},
101
+ reached: {},
102
+ targets: new Map(),
103
+ };
49
104
  for (const [name, value] of Object.entries(document.fields)) {
50
- const reference = referenceField(definition?.fields[name]);
51
- const compared = reference ? resolved(path, value) : value;
52
- if (compared !== undefined)
53
- values[name] = compared;
54
- if (Array.isArray(value))
55
- sizes[name] = value.length;
56
- if (!reference)
57
- continue;
58
- const targets = [compared].flat().filter((found) => typeof found === 'string');
59
- for (const found of new Set(targets)) {
60
- references.push({
61
- key: keyOf('r', room, path, name, found),
62
- kind: 'reference',
63
- room,
64
- source: key,
65
- target: documentKey(room, found),
66
- field: name,
67
- path,
68
- type,
69
- });
70
- }
105
+ const segment = escapePointer(name);
106
+ walk(reading, value, [{ text: `/${segment}`, through: false, pending: false }], `/${segment}`);
71
107
  }
108
+ const { values, reached } = reading;
72
109
  return [
73
110
  {
74
111
  key,
@@ -78,20 +115,23 @@ export function rowsOf(room, path, document, composition, change) {
78
115
  type,
79
116
  fields: document.fields,
80
117
  values,
81
- sizes,
118
+ reached,
82
119
  directories: directoriesOf(path),
83
- body,
120
+ text: document.content,
84
121
  change,
122
+ fileId,
123
+ binary,
85
124
  },
86
- {
87
- key: body,
88
- kind: 'body',
125
+ ...[...reading.targets.values()].map(({ field, target: found, forms }) => ({
126
+ key: keyOf('r', room, path, field, found),
127
+ kind: 'reference',
89
128
  room,
129
+ source: key,
130
+ target: documentKey(room, found),
131
+ field,
132
+ forms: [...forms].sort(),
90
133
  path,
91
- preamble: document.preamble,
92
- sections: document.sections,
93
- markdown: document.content,
94
- },
95
- ...references,
134
+ type,
135
+ })),
96
136
  ];
97
137
  }
package/dist/save.d.ts CHANGED
@@ -4,13 +4,15 @@ import { type Composition } from './collection.js';
4
4
  import type { VisibleLayer } from './replica.js';
5
5
  import type { ChangedPart } from './room-draft.js';
6
6
  export type SaveRefusal = {
7
- rule: string;
7
+ code: string;
8
+ retryable: boolean;
8
9
  file?: string;
9
10
  location?: string;
10
11
  referrers?: readonly string[];
11
12
  parts?: readonly ChangedPart[];
12
13
  };
13
14
  export type SaveInput = {
15
+ local: boolean;
14
16
  composition: Composition;
15
17
  baseRoomVersion: string;
16
18
  operations: import('./adapter.js').OperationScopes;
@@ -20,7 +22,13 @@ export type SaveInput = {
20
22
  handle: string;
21
23
  changes: readonly Change[];
22
24
  bases: readonly Precondition[];
25
+ queued?: ReadonlySet<string>;
23
26
  writtenBy?: WrittenBy;
27
+ clean?: {
28
+ text: Readonly<Record<string, string>>;
29
+ binaries: Readonly<Record<string, unknown>>;
30
+ composition: Composition;
31
+ };
24
32
  };
25
33
  export type BatchResult = {
26
34
  kind: 'batch';
@@ -30,5 +38,27 @@ export type BatchResult = {
30
38
  refusal: SaveRefusal;
31
39
  };
32
40
  export declare function providerRewritten(batch: ChangeBatch, visible: VisibleLayer): ChangeBatch;
41
+ export type Requeued = {
42
+ kind: 'requeued';
43
+ queue: readonly ChangeBatch[];
44
+ changes: readonly Change[];
45
+ queued: ReadonlySet<string>;
46
+ withdrawn: ReadonlyMap<string, ChangeBatch | null>;
47
+ owners: ReadonlySet<string>;
48
+ } | {
49
+ kind: 'refused';
50
+ refusal: SaveRefusal;
51
+ };
52
+ export type Joining = {
53
+ kind: 'joined';
54
+ batch: ChangeBatch;
55
+ queue: readonly ChangeBatch[];
56
+ } | {
57
+ kind: 'refused';
58
+ refusal: SaveRefusal;
59
+ };
60
+ export declare function requeued(queue: readonly ChangeBatch[], changes: readonly Change[], visible: VisibleLayer, changeable: (batch: ChangeBatch) => boolean, state: (queue: readonly ChangeBatch[]) => VisibleLayer): Requeued;
61
+ export declare function joined(queue: readonly ChangeBatch[], owner: ChangeBatch, extra: ChangeBatch): Joining;
62
+ export declare function limitedIn(queue: readonly ChangeBatch[], batch: ChangeBatch, limits: readonly ProviderLimit[], state: (queue: readonly ChangeBatch[]) => VisibleLayer): SaveRefusal | null;
33
63
  export declare function buildBatch(input: SaveInput): BatchResult;
34
64
  //# sourceMappingURL=save.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"save.d.ts","sourceRoot":"","sources":["../src/save.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,OAAO,cAAc,EAAE,eAAe,CAAC;IACnD,kBAAkB,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,cAAc,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC;AA+K9C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAOxF;AAuQD,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,WAAW,CAyFxD"}
1
+ {"version":3,"file":"save.d.ts","sourceRoot":"","sources":["../src/save.ts"],"names":[],"mappings":"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"}