@agentshouse/mdruntime 0.1.0-c5d3fa6fb67bc → 0.1.0-c5d81e5d5cb58

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 (233) hide show
  1. package/README.md +18 -15
  2. package/dist/adapter.d.ts +86 -34
  3. package/dist/adapter.d.ts.map +1 -1
  4. package/dist/attached-model.d.ts +5 -1
  5. package/dist/attached-model.d.ts.map +1 -1
  6. package/dist/attached-model.js +38 -4
  7. package/dist/binary.d.ts +0 -5
  8. package/dist/binary.d.ts.map +1 -1
  9. package/dist/binary.js +1 -1
  10. package/dist/bootstrap.d.ts +31 -8
  11. package/dist/bootstrap.d.ts.map +1 -1
  12. package/dist/bootstrap.js +187 -85
  13. package/dist/chain.d.ts +11 -0
  14. package/dist/chain.d.ts.map +1 -0
  15. package/dist/chain.js +64 -0
  16. package/dist/change-set.d.ts +9 -16
  17. package/dist/change-set.d.ts.map +1 -1
  18. package/dist/change-set.js +11 -89
  19. package/dist/change.d.ts +31 -1
  20. package/dist/change.d.ts.map +1 -1
  21. package/dist/change.js +10 -1
  22. package/dist/client.d.ts +13 -5
  23. package/dist/client.d.ts.map +1 -1
  24. package/dist/client.js +95 -10
  25. package/dist/collection.d.ts +11 -19
  26. package/dist/collection.d.ts.map +1 -1
  27. package/dist/collection.js +53 -289
  28. package/dist/compile.d.ts +16 -0
  29. package/dist/compile.d.ts.map +1 -0
  30. package/dist/compile.js +765 -0
  31. package/dist/connection.d.ts +28 -13
  32. package/dist/connection.d.ts.map +1 -1
  33. package/dist/connection.js +2937 -1064
  34. package/dist/conversation.d.ts +18 -3
  35. package/dist/conversation.d.ts.map +1 -1
  36. package/dist/conversation.js +340 -117
  37. package/dist/digest.d.ts +7 -0
  38. package/dist/digest.d.ts.map +1 -0
  39. package/dist/digest.js +113 -0
  40. package/dist/durability.d.ts +3 -5
  41. package/dist/durability.d.ts.map +1 -1
  42. package/dist/durability.js +5 -0
  43. package/dist/entry.d.ts +3 -1
  44. package/dist/entry.d.ts.map +1 -1
  45. package/dist/entry.js +18 -23
  46. package/dist/file.d.ts +2 -19
  47. package/dist/file.d.ts.map +1 -1
  48. package/dist/file.js +7 -122
  49. package/dist/fulltext.d.ts +27 -0
  50. package/dist/fulltext.d.ts.map +1 -0
  51. package/dist/fulltext.js +368 -0
  52. package/dist/host.d.ts +8 -7
  53. package/dist/host.d.ts.map +1 -1
  54. package/dist/host.js +84 -14
  55. package/dist/identity.d.ts +0 -1
  56. package/dist/identity.d.ts.map +1 -1
  57. package/dist/identity.js +0 -3
  58. package/dist/index.d.ts +14 -11
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +5 -1
  61. package/dist/live.d.ts +22 -0
  62. package/dist/live.d.ts.map +1 -0
  63. package/dist/live.js +124 -0
  64. package/dist/media.d.ts +8 -0
  65. package/dist/media.d.ts.map +1 -0
  66. package/dist/media.js +208 -0
  67. package/dist/memory.d.ts +8 -4
  68. package/dist/memory.d.ts.map +1 -1
  69. package/dist/memory.js +79 -32
  70. package/dist/messages.d.ts +28 -0
  71. package/dist/messages.d.ts.map +1 -0
  72. package/dist/messages.js +90 -0
  73. package/dist/model.d.ts +6 -0
  74. package/dist/model.d.ts.map +1 -1
  75. package/dist/model.js +7 -1
  76. package/dist/name.d.ts +4 -0
  77. package/dist/name.d.ts.map +1 -0
  78. package/dist/name.js +122 -0
  79. package/dist/observation.d.ts +15 -0
  80. package/dist/observation.d.ts.map +1 -1
  81. package/dist/observation.js +93 -3
  82. package/dist/opened.d.ts +22 -0
  83. package/dist/opened.d.ts.map +1 -0
  84. package/dist/opened.js +107 -0
  85. package/dist/outcome.d.ts +45 -4
  86. package/dist/outcome.d.ts.map +1 -1
  87. package/dist/outcome.js +39 -0
  88. package/dist/overlay.d.ts +2 -5
  89. package/dist/overlay.d.ts.map +1 -1
  90. package/dist/overlay.js +87 -172
  91. package/dist/paths.d.ts +1 -0
  92. package/dist/paths.d.ts.map +1 -1
  93. package/dist/paths.js +4 -0
  94. package/dist/query.d.ts +35 -2
  95. package/dist/query.d.ts.map +1 -1
  96. package/dist/query.js +46 -7
  97. package/dist/reach.d.ts +13 -4
  98. package/dist/reach.d.ts.map +1 -1
  99. package/dist/reach.js +210 -68
  100. package/dist/react.d.ts +3 -3
  101. package/dist/react.d.ts.map +1 -1
  102. package/dist/react.js +7 -17
  103. package/dist/readiness.d.ts +20 -9
  104. package/dist/readiness.d.ts.map +1 -1
  105. package/dist/readiness.js +6 -6
  106. package/dist/reads.d.ts +11 -0
  107. package/dist/reads.d.ts.map +1 -0
  108. package/dist/reads.js +100 -0
  109. package/dist/recovery.d.ts +2 -2
  110. package/dist/recovery.d.ts.map +1 -1
  111. package/dist/recovery.js +8 -7
  112. package/dist/refresh.d.ts +16 -15
  113. package/dist/refresh.d.ts.map +1 -1
  114. package/dist/refresh.js +113 -56
  115. package/dist/replica.d.ts +56 -33
  116. package/dist/replica.d.ts.map +1 -1
  117. package/dist/replica.js +298 -188
  118. package/dist/room-draft.d.ts +16 -1
  119. package/dist/room-draft.d.ts.map +1 -1
  120. package/dist/room-draft.js +65 -25
  121. package/dist/rows.d.ts +38 -30
  122. package/dist/rows.d.ts.map +1 -1
  123. package/dist/rows.js +173 -96
  124. package/dist/save.d.ts +53 -14
  125. package/dist/save.d.ts.map +1 -1
  126. package/dist/save.js +529 -185
  127. package/dist/search.d.ts +25 -42
  128. package/dist/search.d.ts.map +1 -1
  129. package/dist/search.js +30 -169
  130. package/dist/seed.d.ts +16 -0
  131. package/dist/seed.d.ts.map +1 -0
  132. package/dist/seed.js +75 -0
  133. package/dist/shared.d.ts +8 -3
  134. package/dist/shared.d.ts.map +1 -1
  135. package/dist/shared.js +129 -66
  136. package/dist/status.d.ts +5 -0
  137. package/dist/status.d.ts.map +1 -1
  138. package/dist/status.js +3 -1
  139. package/dist/store.d.ts +106 -90
  140. package/dist/store.d.ts.map +1 -1
  141. package/dist/store.js +355 -659
  142. package/dist/stored.d.ts +154 -0
  143. package/dist/stored.d.ts.map +1 -0
  144. package/dist/stored.js +624 -0
  145. package/dist/tables.d.ts +362 -0
  146. package/dist/tables.d.ts.map +1 -0
  147. package/dist/tables.js +627 -0
  148. package/dist/turn.d.ts +5 -3
  149. package/dist/turn.d.ts.map +1 -1
  150. package/dist/turn.js +51 -21
  151. package/dist/validation.d.ts +30 -0
  152. package/dist/validation.d.ts.map +1 -0
  153. package/dist/validation.js +162 -0
  154. package/dist/windows.d.ts +22 -0
  155. package/dist/windows.d.ts.map +1 -0
  156. package/dist/windows.js +89 -0
  157. package/dist/wire.d.ts +33 -1
  158. package/dist/wire.d.ts.map +1 -1
  159. package/dist/wire.js +9 -1
  160. package/dist/words.d.ts +19 -0
  161. package/dist/words.d.ts.map +1 -0
  162. package/dist/words.js +156 -0
  163. package/package.json +18 -19
  164. package/AGENTS.md +0 -299
  165. package/dist/acquisition.d.ts +0 -14
  166. package/dist/acquisition.d.ts.map +0 -1
  167. package/dist/acquisition.js +0 -24
  168. package/dist/chat/acts.d.ts +0 -33
  169. package/dist/chat/acts.d.ts.map +0 -1
  170. package/dist/chat/acts.js +0 -36
  171. package/dist/chat/context.d.ts +0 -3
  172. package/dist/chat/context.d.ts.map +0 -1
  173. package/dist/chat/context.js +0 -10
  174. package/dist/chat/input.d.ts +0 -9
  175. package/dist/chat/input.d.ts.map +0 -1
  176. package/dist/chat/input.js +0 -99
  177. package/dist/chat/kit.d.ts +0 -61
  178. package/dist/chat/kit.d.ts.map +0 -1
  179. package/dist/chat/kit.js +0 -123
  180. package/dist/chat/lasting.d.ts +0 -6
  181. package/dist/chat/lasting.d.ts.map +0 -1
  182. package/dist/chat/lasting.js +0 -19
  183. package/dist/chat/list.d.ts +0 -27
  184. package/dist/chat/list.d.ts.map +0 -1
  185. package/dist/chat/list.js +0 -63
  186. package/dist/chat/markdown.d.ts +0 -20
  187. package/dist/chat/markdown.d.ts.map +0 -1
  188. package/dist/chat/markdown.js +0 -188
  189. package/dist/chat/message.d.ts +0 -6
  190. package/dist/chat/message.d.ts.map +0 -1
  191. package/dist/chat/message.js +0 -192
  192. package/dist/chat/messages.d.ts +0 -22
  193. package/dist/chat/messages.d.ts.map +0 -1
  194. package/dist/chat/messages.js +0 -155
  195. package/dist/chat/name.d.ts +0 -6
  196. package/dist/chat/name.d.ts.map +0 -1
  197. package/dist/chat/name.js +0 -37
  198. package/dist/chat/opened.d.ts +0 -11
  199. package/dist/chat/opened.d.ts.map +0 -1
  200. package/dist/chat/opened.js +0 -17
  201. package/dist/chat/overlay.d.ts +0 -31
  202. package/dist/chat/overlay.d.ts.map +0 -1
  203. package/dist/chat/overlay.js +0 -97
  204. package/dist/chat/parts.d.ts +0 -57
  205. package/dist/chat/parts.d.ts.map +0 -1
  206. package/dist/chat/parts.js +0 -119
  207. package/dist/chat/process.d.ts +0 -20
  208. package/dist/chat/process.d.ts.map +0 -1
  209. package/dist/chat/process.js +0 -32
  210. package/dist/chat/provider.d.ts +0 -63
  211. package/dist/chat/provider.d.ts.map +0 -1
  212. package/dist/chat/provider.js +0 -629
  213. package/dist/chat/question.d.ts +0 -9
  214. package/dist/chat/question.d.ts.map +0 -1
  215. package/dist/chat/question.js +0 -80
  216. package/dist/chat/questions.d.ts +0 -31
  217. package/dist/chat/questions.d.ts.map +0 -1
  218. package/dist/chat/questions.js +0 -111
  219. package/dist/chat/read.d.ts +0 -5
  220. package/dist/chat/read.d.ts.map +0 -1
  221. package/dist/chat/read.js +0 -13
  222. package/dist/chat/ready.d.ts +0 -34
  223. package/dist/chat/ready.d.ts.map +0 -1
  224. package/dist/chat/ready.js +0 -91
  225. package/dist/chat/style.d.ts +0 -4
  226. package/dist/chat/style.d.ts.map +0 -1
  227. package/dist/chat/style.js +0 -302
  228. package/dist/chat.d.ts +0 -14
  229. package/dist/chat.d.ts.map +0 -1
  230. package/dist/chat.js +0 -8
  231. package/dist/read-side.d.ts +0 -25
  232. package/dist/read-side.d.ts.map +0 -1
  233. package/dist/read-side.js +0 -642
@@ -1,6 +1,6 @@
1
- import { apply, equalValue, frontmatterValue, parse, serialize } from '@agentshouse/mdmodel';
1
+ import { apply, equalValue, frontmatterValue, parse, serialize, } from '@agentshouse/mdmodel';
2
2
  import { runtimeError } from './failure.js';
3
- import { hexDigest } from './file.js';
3
+ import { sha256 } from './digest.js';
4
4
  import { binaryLocalId } from './identity.js';
5
5
  import { normalize } from './paths.js';
6
6
  export function returnedBy(kind) {
@@ -90,7 +90,12 @@ export function readParts(value) {
90
90
  if (!plain(value.move))
91
91
  malformed();
92
92
  const base = markdownBase(value.move.base);
93
- parts.move = { to: text(value.move.to), ...(base === undefined ? {} : { base }) };
93
+ const room = optionalText(value.move.room);
94
+ parts.move = {
95
+ to: text(value.move.to),
96
+ ...(room === undefined ? {} : { room }),
97
+ ...(base === undefined ? {} : { base }),
98
+ };
94
99
  }
95
100
  if (value.removal !== undefined) {
96
101
  if (!plain(value.removal))
@@ -120,11 +125,51 @@ function kept(prior, base) {
120
125
  throw runtimeError('room-draft-base-missing');
121
126
  return base;
122
127
  }
128
+ function movePart(current, move) {
129
+ return {
130
+ to: move.to,
131
+ ...(move.room === undefined ? {} : { room: move.room }),
132
+ base: kept(current, move.base),
133
+ };
134
+ }
123
135
  function editsText(parts) {
124
136
  return (parts.preamble !== undefined ||
125
137
  named(parts.fields).length > 0 ||
126
138
  named(parts.sections).length > 0);
127
139
  }
140
+ function partNames(parts) {
141
+ const names = [];
142
+ for (const [name, part] of Object.entries(parts)) {
143
+ if (name === 'preamble' || name === 'markdown')
144
+ names.push(name);
145
+ else if ((name === 'fields' || name === 'sections') && plain(part))
146
+ names.push(...Object.keys(part).map((one) => `${name}/${one}`));
147
+ else
148
+ return null;
149
+ }
150
+ return names.sort().join('\u0000');
151
+ }
152
+ function withBaseOf(prior, part) {
153
+ return plain(part) && plain(prior) && Object.hasOwn(prior, 'base')
154
+ ? { ...part, base: prior.base }
155
+ : part;
156
+ }
157
+ export function gatheredParts(earlier, later) {
158
+ if (!plain(earlier) || !plain(later))
159
+ return null;
160
+ const named = partNames(earlier);
161
+ if (named === null || named !== partNames(later))
162
+ return null;
163
+ return Object.fromEntries(Object.entries(later).map(([name, part]) => [
164
+ name,
165
+ name === 'fields' || name === 'sections'
166
+ ? Object.fromEntries(Object.entries(part).map(([one, value]) => [
167
+ one,
168
+ withBaseOf(earlier[name][one], value),
169
+ ]))
170
+ : withBaseOf(earlier[name], part),
171
+ ]));
172
+ }
128
173
  export function held(current, parts, file) {
129
174
  if (parts.markdown !== undefined && editsText(parts)) {
130
175
  throw runtimeError('room-draft-markdown-exclusive');
@@ -144,9 +189,7 @@ export function held(current, parts, file) {
144
189
  }
145
190
  return {
146
191
  file: current.file,
147
- ...(parts.move === undefined
148
- ? {}
149
- : { move: { to: parts.move.to, base: kept(current.move, parts.move.base) } }),
192
+ ...(parts.move === undefined ? {} : { move: movePart(current.move, parts.move) }),
150
193
  ...(parts.removal === undefined
151
194
  ? {}
152
195
  : { removal: { base: kept(current.removal, parts.removal.base) } }),
@@ -181,9 +224,8 @@ export function held(current, parts, file) {
181
224
  }
182
225
  if (parts.creation !== undefined)
183
226
  next.creation = parts.creation;
184
- if (parts.move !== undefined) {
185
- next.move = { to: parts.move.to, base: kept(current?.move, parts.move.base) };
186
- }
227
+ if (parts.move !== undefined)
228
+ next.move = movePart(current?.move, parts.move);
187
229
  if (parts.removal !== undefined) {
188
230
  next.removal = { base: kept(current?.removal, parts.removal.base) };
189
231
  }
@@ -240,13 +282,12 @@ export function underneath(parts, path, visible) {
240
282
  }
241
283
  const UNTYPED_MEDIA_TYPE = 'application/octet-stream';
242
284
  export async function heldFile(blob, base) {
243
- const bytes = await blob.arrayBuffer();
244
285
  return {
245
- blob,
246
286
  localId: binaryLocalId(),
247
- byteLength: bytes.byteLength,
287
+ ...(blob instanceof File ? { name: blob.name } : {}),
288
+ byteLength: blob.size,
248
289
  mediaType: blob.type === '' ? UNTYPED_MEDIA_TYPE : blob.type,
249
- sha256: hexDigest(await crypto.subtle.digest('SHA-256', bytes)),
290
+ sha256: await sha256(blob),
250
291
  base,
251
292
  };
252
293
  }
@@ -279,16 +320,15 @@ function frontmatterOf(fields) {
279
320
  const opened = parse('---\n---\n');
280
321
  if (!opened.ok)
281
322
  return malformed();
282
- let document = opened.document;
283
- for (const [name, part] of fields) {
284
- const next = apply(document, { kind: 'field', name, value: part.value, prior: undefined });
285
- if (next.outcome !== 'applied')
286
- return malformed();
287
- document = next.document;
288
- }
289
- return serialize(document);
290
- }
291
- function concatenated(markdown, parts) {
323
+ const next = apply(opened.document, fields.map(([name, part]) => ({
324
+ kind: 'field',
325
+ name,
326
+ value: part.value,
327
+ prior: undefined,
328
+ })));
329
+ return next.outcome === 'applied' ? serialize(next.document) : malformed();
330
+ }
331
+ export function partsAfter(markdown, parts) {
292
332
  const fields = named(parts.fields);
293
333
  const pieces = [
294
334
  ...(fields.length === 0 ? [] : [frontmatterOf(fields)]),
@@ -319,7 +359,7 @@ export function returnedInto(existing, returned) {
319
359
  delete next.fields;
320
360
  delete next.sections;
321
361
  delete next.preamble;
322
- const value = concatenated(whole.value, existing.markdown === undefined ? existing : returned);
362
+ const value = partsAfter(whole.value, existing.markdown === undefined ? existing : returned);
323
363
  next.markdown = { value, base: whole.base };
324
364
  }
325
365
  const creation = existing.creation ?? returned.creation;
@@ -370,7 +410,7 @@ export function changesOf(path, parts) {
370
410
  changes.push({ kind: 'replace', path, content: parts.markdown.value });
371
411
  }
372
412
  if (parts.file !== undefined && parts.removal === undefined) {
373
- const { base, ...file } = parts.file;
413
+ const { base, name: _name, ...file } = parts.file;
374
414
  const at = parts.move === undefined ? path : moveTarget(parts.move);
375
415
  if (base !== null && at !== path)
376
416
  changes.push({ kind: 'move', path, to: at });
package/dist/rows.d.ts CHANGED
@@ -1,38 +1,46 @@
1
- import { type Frontmatter } from '@agentshouse/mdmodel';
2
- import type { HeadChange } from './adapter.js';
3
- import type { BinaryFileRecord } from './binary.js';
4
1
  import { type Composition } from './collection.js';
5
- type Fields = Readonly<Record<string, unknown>>;
6
- export type DocumentRow = {
7
- key: string;
8
- kind: 'document';
9
- room: string;
10
- path: string;
11
- type: string | null;
12
- fields: Fields;
13
- values: Fields;
14
- reached: Readonly<Record<string, readonly unknown[]>>;
15
- directories: readonly string[];
16
- text: string | null;
17
- change: HeadChange | null;
18
- fileId: string | null;
19
- binary: BinaryFileRecord | null;
2
+ export type ValueKind = 'string' | 'number' | 'boolean' | 'null' | 'array' | 'object' | 'undefined';
3
+ type HeldValue = {
4
+ readonly keys: string;
5
+ readonly places: string;
6
+ readonly item: number;
7
+ readonly kind: ValueKind;
8
+ readonly value: string | number | null;
9
+ readonly size: number | null;
20
10
  };
21
- export type ReferenceRow = {
22
- key: string;
23
- kind: 'reference';
24
- room: string;
25
- source: string;
26
- target: string;
27
- field: string;
28
- forms: readonly string[];
29
- path: string;
30
- type: string;
11
+ type LinkKind = 'field' | 'section' | 'body';
12
+ type HeldLink = {
13
+ readonly kind: LinkKind;
14
+ readonly keys: string;
15
+ readonly places: string;
16
+ readonly target: string;
17
+ readonly field: string;
18
+ };
19
+ export type Described = {
20
+ readonly type: string | null;
21
+ readonly declared: string | null;
22
+ readonly queried: boolean;
23
+ readonly folder: string;
24
+ readonly fields: string | null;
25
+ };
26
+ export type Derived = Described & {
27
+ readonly values: readonly HeldValue[];
28
+ readonly links: readonly HeldLink[];
31
29
  };
32
- export type Row = DocumentRow | ReferenceRow;
33
30
  export declare function documentKey(room: string, path: string): string;
34
31
  export declare function roomOfKey(key: string): string;
32
+ export declare function pathOfKey(key: string): string;
35
33
  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[];
34
+ export declare function folderOf(path: string): string;
35
+ export type Reach = 'exact' | 'value' | 'link';
36
+ export type Placed = {
37
+ readonly keys: string;
38
+ readonly places: string;
39
+ readonly glob: boolean;
40
+ };
41
+ export declare function placedOf(pointer: string, reach: Reach): Placed;
42
+ export declare function kindOf(value: unknown): ValueKind;
43
+ export declare function described(path: string, content: string | null): Described;
44
+ export declare function derived(path: string, content: string | null, composition: Composition): Derived;
37
45
  export {};
38
46
  //# sourceMappingURL=rows.d.ts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"AAWA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9D,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEpG,KAAK,SAAS,GAAG;IACf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF,KAAK,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAE7C,KAAK,QAAQ,GAAG;IACd,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG;IAChC,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;CACrC,CAAC;AAMF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7C;AAWD,MAAM,MAAM,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;AAE/C,MAAM,MAAM,MAAM,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhG,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAuB9D;AAwBD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAMhD;AAiJD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAEzE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAO/F"}
package/dist/rows.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ARRAY_INDEX, escapePointer, references, target, } from '@agentshouse/mdmodel';
1
+ import { ARRAY_INDEX, bodyAfterFrontmatter, bodyLinks, escapePointer, parseFrontmatter, references, sectionReferences, target, } from '@agentshouse/mdmodel';
2
2
  import { governing } from './collection.js';
3
3
  import { definitionOf } from './model.js';
4
4
  function keyOf(...parts) {
@@ -10,6 +10,50 @@ export function documentKey(room, path) {
10
10
  export function roomOfKey(key) {
11
11
  return key.split('\u0000')[1];
12
12
  }
13
+ export function pathOfKey(key) {
14
+ return key.split('\u0000')[2];
15
+ }
16
+ export function markdownPath(path) {
17
+ return path.endsWith('.md');
18
+ }
19
+ export function folderOf(path) {
20
+ return path.slice(0, Math.max(path.lastIndexOf('/'), 0));
21
+ }
22
+ export function placedOf(pointer, reach) {
23
+ const [first = '', ...rest] = pointer.split('/').slice(1);
24
+ const keys = [first];
25
+ const gaps = [[]];
26
+ for (const segment of rest) {
27
+ if (ARRAY_INDEX.test(segment)) {
28
+ gaps.at(-1).push(segment);
29
+ continue;
30
+ }
31
+ keys.push(segment);
32
+ gaps.push([]);
33
+ }
34
+ const places = gaps
35
+ .map((gap, at) => {
36
+ const open = at < gaps.length - 1 ? reach !== 'exact' : reach === 'link';
37
+ return `/${gap.map((number) => `[.:]${number}`).join('')}.${open ? '*' : ''}`;
38
+ })
39
+ .join('');
40
+ return {
41
+ keys: keys.map((key) => `/${key}`).join(''),
42
+ places,
43
+ glob: /[[*]/u.test(places),
44
+ };
45
+ }
46
+ function placesOf({ done, head, tail }) {
47
+ return `${done}/${head}${tail}.`;
48
+ }
49
+ function throughOf(keys, places) {
50
+ const gaps = places.split('/').slice(1);
51
+ return keys
52
+ .split('/')
53
+ .slice(1)
54
+ .map((key, at) => `/${key}${gaps[at].replace(/\.\d*/gu, '').replaceAll(':', '/')}`)
55
+ .join('');
56
+ }
13
57
  function plainObject(value) {
14
58
  return typeof value === 'object' && value !== null && !Array.isArray(value);
15
59
  }
@@ -18,120 +62,153 @@ function compared(reading, exact, value) {
18
62
  return value;
19
63
  return (typeof value === 'string' ? target(reading.path, value) : null) ?? undefined;
20
64
  }
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))
65
+ export function kindOf(value) {
66
+ if (value === undefined)
67
+ return 'undefined';
68
+ if (value === null)
69
+ return 'null';
70
+ if (Array.isArray(value))
71
+ return 'array';
72
+ if (typeof value === 'object')
73
+ return 'object';
74
+ return typeof value;
75
+ }
76
+ function scalarOf(value) {
77
+ if (typeof value === 'string' || typeof value === 'number')
78
+ return value;
79
+ if (typeof value === 'boolean')
80
+ return value ? 1 : 0;
81
+ if (Array.isArray(value))
82
+ return JSON.stringify(value);
83
+ return null;
84
+ }
85
+ function held(reading, keys, places, value) {
86
+ reading.values.push({
87
+ keys,
88
+ places,
89
+ item: -1,
90
+ kind: kindOf(value),
91
+ value: scalarOf(value),
92
+ size: Array.isArray(value) ? value.length : null,
93
+ });
94
+ if (!Array.isArray(value))
34
95
  return;
35
- const found = compared(reading, exact, node);
36
- if (typeof found !== 'string')
96
+ value.forEach((item, index) => {
97
+ const itemKind = kindOf(item);
98
+ reading.values.push({
99
+ keys,
100
+ places,
101
+ item: index,
102
+ kind: itemKind,
103
+ value: itemKind === 'array' ? null : scalarOf(item),
104
+ size: null,
105
+ });
106
+ });
107
+ }
108
+ function record(reading, node, at) {
109
+ const value = Array.isArray(node)
110
+ ? node.map((item, index) => compared(reading, `${at.exact}/${index}`, item))
111
+ : compared(reading, at.exact, node);
112
+ const places = placesOf(at);
113
+ held(reading, at.keys, places, value);
114
+ if (typeof value !== 'string' || !reading.references.has(at.exact))
37
115
  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);
116
+ reading.links.push({
117
+ kind: 'field',
118
+ keys: at.keys,
119
+ places,
120
+ target: value,
121
+ field: throughOf(at.keys, places),
122
+ });
123
+ }
124
+ function walk(reading, node, at) {
125
+ record(reading, node, at);
49
126
  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}`));
127
+ node.forEach((item, index) => walk(reading, item, { ...at, tail: `${at.tail}.${index}`, exact: `${at.exact}/${index}` }));
56
128
  return;
57
129
  }
58
130
  if (!plainObject(node))
59
131
  return;
60
132
  for (const [key, value] of Object.entries(node)) {
61
133
  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}`);
134
+ const exact = `${at.exact}/${segment}`;
135
+ walk(reading, value, ARRAY_INDEX.test(segment)
136
+ ? { ...at, head: `${at.head}${at.tail.replaceAll('.', ':')}:${segment}`, tail: '', exact }
137
+ : { keys: `${at.keys}/${segment}`, done: placesOf(at), head: '', tail: '', exact });
65
138
  }
66
139
  }
67
- function directoriesOf(path) {
68
- const parts = path.split('/').slice(0, -1);
69
- return ['', ...parts.map((_, index) => parts.slice(0, index + 1).join('/'))];
70
- }
71
- export function markdownPath(path) {
72
- return path.endsWith('.md');
73
- }
74
- export function rowsOf(room, path, document, composition, change, fileId, binary) {
75
- const key = documentKey(room, path);
76
- if (document === null || !markdownPath(path)) {
77
- return [
78
- {
79
- key,
80
- kind: 'document',
81
- room,
82
- path,
83
- type: null,
84
- fields: {},
85
- values: {},
86
- reached: {},
87
- directories: directoriesOf(path),
88
- text: null,
89
- change,
90
- fileId,
91
- binary,
92
- },
93
- ];
140
+ function bodyTargets(path, content) {
141
+ const seen = new Set();
142
+ const found = [];
143
+ for (const { target: reached } of bodyLinks(bodyAfterFrontmatter(content), path)) {
144
+ if (seen.has(reached))
145
+ continue;
146
+ seen.add(reached);
147
+ found.push({ kind: 'body', keys: '', places: '', target: reached, field: '' });
94
148
  }
95
- const type = document.type ?? 'any';
149
+ return found;
150
+ }
151
+ function typedRows(path, content, document, composition) {
96
152
  const definition = definitionOf(governing(composition, path), document.type);
97
153
  const reading = {
98
154
  path,
99
155
  references: new Set(definition === undefined ? [] : references(document, definition).map((one) => one.pointer)),
100
- values: {},
101
- reached: {},
102
- targets: new Map(),
156
+ values: [],
157
+ links: [],
103
158
  };
104
159
  for (const [name, value] of Object.entries(document.fields)) {
105
160
  const segment = escapePointer(name);
106
- walk(reading, value, [{ text: `/${segment}`, through: false, pending: false }], `/${segment}`);
161
+ walk(reading, value, {
162
+ keys: `/${segment}`,
163
+ done: '',
164
+ head: '',
165
+ tail: '',
166
+ exact: `/${segment}`,
167
+ });
107
168
  }
108
- const { values, reached } = reading;
109
- return [
110
- {
111
- key,
112
- kind: 'document',
113
- room,
114
- path,
115
- type,
116
- fields: document.fields,
117
- values,
118
- reached,
119
- directories: directoriesOf(path),
120
- text: document.content,
121
- change,
122
- fileId,
123
- binary,
169
+ const links = reading.links;
170
+ if (definition !== undefined) {
171
+ const sectioned = new Set();
172
+ for (const { target: reached } of sectionReferences(path, content, definition)) {
173
+ if (reached === null || sectioned.has(reached))
174
+ continue;
175
+ sectioned.add(reached);
176
+ links.push({ kind: 'section', keys: '', places: '', target: reached, field: '' });
177
+ }
178
+ }
179
+ return { values: reading.values, links: [...links, ...bodyTargets(path, content)] };
180
+ }
181
+ function read(path, content) {
182
+ const folder = folderOf(path);
183
+ const unread = { fields: null, folder, type: null };
184
+ if (content === null) {
185
+ return { described: { ...unread, declared: null, queried: true }, document: null };
186
+ }
187
+ const parsed = parseFrontmatter(content, path);
188
+ const declared = parsed.ok ? (parsed.frontmatter.type ?? 'any') : null;
189
+ if (!markdownPath(path) || !parsed.ok) {
190
+ return { described: { ...unread, declared, queried: !markdownPath(path) }, document: null };
191
+ }
192
+ const document = parsed.frontmatter;
193
+ return {
194
+ described: {
195
+ type: document.type ?? 'any',
196
+ declared,
197
+ queried: true,
198
+ folder,
199
+ fields: JSON.stringify(document.fields),
124
200
  },
125
- ...[...reading.targets.values()].map(({ field, target: found, forms }) => ({
126
- key: keyOf('r', room, path, field, found),
127
- kind: 'reference',
128
- room,
129
- source: key,
130
- target: documentKey(room, found),
131
- field,
132
- forms: [...forms].sort(),
133
- path,
134
- type,
135
- })),
136
- ];
201
+ document,
202
+ };
203
+ }
204
+ export function described(path, content) {
205
+ return read(path, content).described;
206
+ }
207
+ export function derived(path, content, composition) {
208
+ const { described: columns, document } = read(path, content);
209
+ if (document !== null) {
210
+ return { ...columns, ...typedRows(path, content, document, composition) };
211
+ }
212
+ const links = content === null || markdownPath(path) ? [] : bodyTargets(path, content);
213
+ return { ...columns, values: [], links };
137
214
  }
package/dist/save.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- import type { ProviderLimit } from './adapter.js';
1
+ import { type Validation } from '@agentshouse/mdmodel';
2
+ import type { OperationScopes, ProviderLimit } from './adapter.js';
2
3
  import { type Change, type ChangeBatch, type Precondition, type WrittenBy } from './change.js';
3
4
  import { type Composition } from './collection.js';
5
+ import { type Layer } from './overlay.js';
4
6
  import type { VisibleLayer } from './replica.js';
5
7
  import type { ChangedPart } from './room-draft.js';
6
8
  export type SaveRefusal = {
@@ -19,25 +21,29 @@ export type SaveInput = {
19
21
  providerOwnedPaths: readonly string[];
20
22
  providerLimits: readonly ProviderLimit[];
21
23
  visible: VisibleLayer;
24
+ folders: ReadonlySet<string>;
22
25
  handle: string;
23
26
  changes: readonly Change[];
24
27
  bases: readonly Precondition[];
25
28
  queued?: ReadonlySet<string>;
26
29
  writtenBy?: WrittenBy;
27
- clean?: {
28
- text: Readonly<Record<string, string>>;
29
- binaries: Readonly<Record<string, unknown>>;
30
- composition: Composition;
31
- };
30
+ unmodeled: boolean;
31
+ validate: Validator;
32
32
  };
33
- export type BatchResult = {
34
- kind: 'batch';
35
- batch: ChangeBatch;
36
- } | {
33
+ export type Validator = (resulting: Layer, touched: readonly string[]) => Promise<Validation>;
34
+ type Refusing = {
37
35
  kind: 'refused';
38
36
  refusal: SaveRefusal;
39
37
  };
40
- export declare function providerRewritten(batch: ChangeBatch, visible: VisibleLayer): ChangeBatch;
38
+ export type BatchResult = {
39
+ kind: 'batch';
40
+ batch: ChangeBatch;
41
+ } | Refusing;
42
+ export declare function providerRewritten(batch: ChangeBatch, visible: VisibleLayer): Generator<number, ChangeBatch, void>;
43
+ export declare function leavingRewritten(batch: ChangeBatch, visible: VisibleLayer): Generator<number, ChangeBatch, void>;
44
+ export declare function rewriting(batch: ChangeBatch, locator: string): boolean;
45
+ export declare function effectiveIn(batch: ChangeBatch, locator: string, visible: VisibleLayer): Generator<number, ChangeBatch, void>;
46
+ export declare function queuedDocuments(queue: readonly ChangeBatch[]): ReadonlySet<string>;
41
47
  export type Requeued = {
42
48
  kind: 'requeued';
43
49
  queue: readonly ChangeBatch[];
@@ -57,8 +63,41 @@ export type Joining = {
57
63
  kind: 'refused';
58
64
  refusal: SaveRefusal;
59
65
  };
60
- export declare function requeued(queue: readonly ChangeBatch[], changes: readonly Change[], visible: VisibleLayer, changeable: (batch: ChangeBatch) => boolean, state: (queue: readonly ChangeBatch[]) => VisibleLayer): Requeued;
66
+ type VisibleOver = (queue: readonly ChangeBatch[]) => Generator<number, VisibleLayer, void>;
67
+ export declare function requeuing(queue: readonly ChangeBatch[], changes: readonly Change[], visible: VisibleLayer, changeable: (batch: ChangeBatch) => boolean, state: VisibleOver): Generator<number, Requeued, void>;
61
68
  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;
63
- export declare function buildBatch(input: SaveInput): BatchResult;
69
+ export declare function limiting(queue: readonly ChangeBatch[], batch: ChangeBatch, limits: readonly ProviderLimit[], state: VisibleOver): Generator<number, SaveRefusal | null, void>;
70
+ export declare const MOVE_DOCUMENTS = "move-documents";
71
+ export type MoveSide = {
72
+ room: string;
73
+ handle: string;
74
+ baseRoomVersion: string;
75
+ composition: Composition;
76
+ operations: OperationScopes;
77
+ providerOwnedPaths: readonly string[];
78
+ visible: VisibleLayer;
79
+ folders: ReadonlySet<string>;
80
+ queued: ReadonlySet<string>;
81
+ unmodeled: boolean;
82
+ validate: Validator;
83
+ };
84
+ export type MoveInput = {
85
+ source: MoveSide;
86
+ destination: MoveSide;
87
+ moves: readonly {
88
+ readonly path: string;
89
+ readonly to: string;
90
+ }[];
91
+ providerLimits: readonly ProviderLimit[];
92
+ local: boolean;
93
+ writtenBy?: WrittenBy;
94
+ };
95
+ export type MoveResult = {
96
+ kind: 'moved';
97
+ leaving: ChangeBatch;
98
+ arriving: ChangeBatch;
99
+ } | Refusing;
100
+ export declare function buildMove(input: MoveInput): Promise<MoveResult>;
101
+ export declare function buildBatch(input: SaveInput): Promise<BatchResult>;
102
+ export {};
64
103
  //# sourceMappingURL=save.d.ts.map