@agentshouse/mdruntime 0.1.0-cedb03eaa48b6 → 0.1.0-cedd665dffa4c

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 (395) hide show
  1. package/README.md +24 -19
  2. package/dist/acceptance.d.ts +3 -0
  3. package/dist/acceptance.d.ts.map +1 -0
  4. package/dist/acceptance.js +299 -0
  5. package/dist/act-lanes.d.ts +30 -0
  6. package/dist/act-lanes.d.ts.map +1 -0
  7. package/dist/act-lanes.js +225 -0
  8. package/dist/actions.d.ts +26 -0
  9. package/dist/actions.d.ts.map +1 -0
  10. package/dist/actions.js +302 -0
  11. package/dist/adapter.d.ts +173 -125
  12. package/dist/adapter.d.ts.map +1 -1
  13. package/dist/attached-model.d.ts +6 -10
  14. package/dist/attached-model.d.ts.map +1 -1
  15. package/dist/attached-model.js +35 -41
  16. package/dist/binary.d.ts +0 -5
  17. package/dist/binary.d.ts.map +1 -1
  18. package/dist/binary.js +1 -1
  19. package/dist/bootstrap.d.ts +30 -11
  20. package/dist/bootstrap.d.ts.map +1 -1
  21. package/dist/bootstrap.js +309 -113
  22. package/dist/cell.d.ts +6 -0
  23. package/dist/cell.d.ts.map +1 -0
  24. package/dist/cell.js +9 -0
  25. package/dist/chain.d.ts +12 -0
  26. package/dist/chain.d.ts.map +1 -0
  27. package/dist/chain.js +64 -0
  28. package/dist/change-set.d.ts +13 -16
  29. package/dist/change-set.d.ts.map +1 -1
  30. package/dist/change-set.js +17 -89
  31. package/dist/change.d.ts +36 -1
  32. package/dist/change.d.ts.map +1 -1
  33. package/dist/change.js +17 -3
  34. package/dist/chat-types.d.ts +3 -0
  35. package/dist/chat-types.d.ts.map +1 -0
  36. package/dist/chat-types.js +11 -0
  37. package/dist/client.d.ts +37 -26
  38. package/dist/client.d.ts.map +1 -1
  39. package/dist/client.js +113 -23
  40. package/dist/collection.d.ts +32 -21
  41. package/dist/collection.d.ts.map +1 -1
  42. package/dist/collection.js +53 -318
  43. package/dist/compile.d.ts +18 -0
  44. package/dist/compile.d.ts.map +1 -0
  45. package/dist/compile.js +723 -0
  46. package/dist/connection.d.ts +7 -137
  47. package/dist/connection.d.ts.map +1 -1
  48. package/dist/connection.js +110 -3602
  49. package/dist/context.d.ts +2 -0
  50. package/dist/context.d.ts.map +1 -0
  51. package/dist/{chat/context.js → context.js} +2 -5
  52. package/dist/conversation-live.d.ts +150 -0
  53. package/dist/conversation-live.d.ts.map +1 -0
  54. package/dist/conversation-live.js +259 -0
  55. package/dist/conversation-row.d.ts +40 -0
  56. package/dist/conversation-row.d.ts.map +1 -0
  57. package/dist/conversation-row.js +66 -0
  58. package/dist/conversation.d.ts +75 -49
  59. package/dist/conversation.d.ts.map +1 -1
  60. package/dist/conversation.js +1029 -806
  61. package/dist/declaration.d.ts +10 -0
  62. package/dist/declaration.d.ts.map +1 -0
  63. package/dist/declaration.js +24 -0
  64. package/dist/digest.d.ts +7 -0
  65. package/dist/digest.d.ts.map +1 -0
  66. package/dist/digest.js +113 -0
  67. package/dist/discovery.d.ts +10 -0
  68. package/dist/discovery.d.ts.map +1 -0
  69. package/dist/discovery.js +150 -0
  70. package/dist/durability.d.ts +20 -4
  71. package/dist/durability.d.ts.map +1 -1
  72. package/dist/durability.js +9 -0
  73. package/dist/entry.d.ts +5 -2
  74. package/dist/entry.d.ts.map +1 -1
  75. package/dist/entry.js +33 -29
  76. package/dist/expectation.d.ts +26 -13
  77. package/dist/expectation.d.ts.map +1 -1
  78. package/dist/expectation.js +72 -19
  79. package/dist/failure.d.ts +3 -0
  80. package/dist/failure.d.ts.map +1 -1
  81. package/dist/failure.js +6 -0
  82. package/dist/figures.d.ts +49 -0
  83. package/dist/figures.d.ts.map +1 -0
  84. package/dist/figures.js +199 -0
  85. package/dist/file.d.ts +2 -19
  86. package/dist/file.d.ts.map +1 -1
  87. package/dist/file.js +8 -122
  88. package/dist/holdings.d.ts +29 -0
  89. package/dist/holdings.d.ts.map +1 -0
  90. package/dist/holdings.js +95 -0
  91. package/dist/host.d.ts +21 -8
  92. package/dist/host.d.ts.map +1 -1
  93. package/dist/host.js +119 -51
  94. package/dist/identity.d.ts +0 -2
  95. package/dist/identity.d.ts.map +1 -1
  96. package/dist/identity.js +0 -6
  97. package/dist/index.d.ts +41 -16
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +19 -4
  100. package/dist/install.d.ts +60 -0
  101. package/dist/install.d.ts.map +1 -0
  102. package/dist/install.js +537 -0
  103. package/dist/lifecycle.d.ts +7 -0
  104. package/dist/lifecycle.d.ts.map +1 -0
  105. package/dist/lifecycle.js +278 -0
  106. package/dist/listing.d.ts +52 -0
  107. package/dist/listing.d.ts.map +1 -0
  108. package/dist/listing.js +152 -0
  109. package/dist/live.d.ts +25 -0
  110. package/dist/live.d.ts.map +1 -0
  111. package/dist/live.js +206 -0
  112. package/dist/loaded.d.ts +5 -0
  113. package/dist/loaded.d.ts.map +1 -0
  114. package/dist/loaded.js +40 -0
  115. package/dist/locks.d.ts +7 -0
  116. package/dist/locks.d.ts.map +1 -0
  117. package/dist/locks.js +32 -0
  118. package/dist/lost.d.ts +5 -0
  119. package/dist/lost.d.ts.map +1 -0
  120. package/dist/lost.js +49 -0
  121. package/dist/media.d.ts +13 -0
  122. package/dist/media.d.ts.map +1 -0
  123. package/dist/media.js +269 -0
  124. package/dist/memory.d.ts +19 -7
  125. package/dist/memory.d.ts.map +1 -1
  126. package/dist/memory.js +281 -118
  127. package/dist/messages.d.ts +58 -0
  128. package/dist/messages.d.ts.map +1 -0
  129. package/dist/messages.js +162 -0
  130. package/dist/model.d.ts +8 -11
  131. package/dist/model.d.ts.map +1 -1
  132. package/dist/model.js +6 -23
  133. package/dist/models.d.ts +10 -0
  134. package/dist/models.d.ts.map +1 -0
  135. package/dist/models.js +153 -0
  136. package/dist/name.d.ts +4 -0
  137. package/dist/name.d.ts.map +1 -0
  138. package/dist/name.js +122 -0
  139. package/dist/observation.d.ts +38 -10
  140. package/dist/observation.d.ts.map +1 -1
  141. package/dist/observation.js +232 -44
  142. package/dist/opened.d.ts +22 -0
  143. package/dist/opened.d.ts.map +1 -0
  144. package/dist/opened.js +107 -0
  145. package/dist/opening.d.ts +4 -0
  146. package/dist/opening.d.ts.map +1 -0
  147. package/dist/opening.js +53 -0
  148. package/dist/outcome.d.ts +51 -9
  149. package/dist/outcome.d.ts.map +1 -1
  150. package/dist/outcome.js +62 -2
  151. package/dist/overlay.d.ts +8 -6
  152. package/dist/overlay.d.ts.map +1 -1
  153. package/dist/overlay.js +121 -182
  154. package/dist/page-metadata.d.ts +8 -0
  155. package/dist/page-metadata.d.ts.map +1 -0
  156. package/dist/page-metadata.js +19 -0
  157. package/dist/parts.d.ts +4 -0
  158. package/dist/parts.d.ts.map +1 -0
  159. package/dist/parts.js +13 -0
  160. package/dist/paths.d.ts +2 -0
  161. package/dist/paths.d.ts.map +1 -1
  162. package/dist/paths.js +26 -0
  163. package/dist/preparation.d.ts +41 -0
  164. package/dist/preparation.d.ts.map +1 -0
  165. package/dist/preparation.js +314 -0
  166. package/dist/presence.d.ts +58 -0
  167. package/dist/presence.d.ts.map +1 -0
  168. package/dist/presence.js +231 -0
  169. package/dist/queries.d.ts +16 -0
  170. package/dist/queries.d.ts.map +1 -0
  171. package/dist/queries.js +308 -0
  172. package/dist/query.d.ts +21 -207
  173. package/dist/query.d.ts.map +1 -1
  174. package/dist/query.js +3 -493
  175. package/dist/{chat/questions.d.ts → questions.d.ts} +5 -7
  176. package/dist/questions.d.ts.map +1 -0
  177. package/dist/{chat/questions.js → questions.js} +11 -7
  178. package/dist/queue.d.ts +40 -0
  179. package/dist/queue.d.ts.map +1 -0
  180. package/dist/queue.js +480 -0
  181. package/dist/reach.d.ts +21 -11
  182. package/dist/reach.d.ts.map +1 -1
  183. package/dist/reach.js +342 -112
  184. package/dist/react.d.ts +17 -3
  185. package/dist/react.d.ts.map +1 -1
  186. package/dist/react.js +33 -1
  187. package/dist/{chat/read.d.ts → read.d.ts} +2 -0
  188. package/dist/read.d.ts.map +1 -0
  189. package/dist/{chat/read.js → read.js} +4 -0
  190. package/dist/readiness.d.ts +22 -20
  191. package/dist/readiness.d.ts.map +1 -1
  192. package/dist/readiness.js +5 -13
  193. package/dist/reads.d.ts +38 -10
  194. package/dist/reads.d.ts.map +1 -1
  195. package/dist/reads.js +163 -83
  196. package/dist/recovery.d.ts +5 -2
  197. package/dist/recovery.d.ts.map +1 -1
  198. package/dist/recovery.js +65 -8
  199. package/dist/refresh.d.ts +18 -15
  200. package/dist/refresh.d.ts.map +1 -1
  201. package/dist/refresh.js +145 -60
  202. package/dist/refusal.d.ts +5 -0
  203. package/dist/refusal.d.ts.map +1 -0
  204. package/dist/refusal.js +55 -0
  205. package/dist/replica.d.ts +49 -36
  206. package/dist/replica.d.ts.map +1 -1
  207. package/dist/replica.js +322 -198
  208. package/dist/retried.d.ts +30 -0
  209. package/dist/retried.d.ts.map +1 -0
  210. package/dist/retried.js +72 -0
  211. package/dist/room-draft.d.ts +55 -13
  212. package/dist/room-draft.d.ts.map +1 -1
  213. package/dist/room-draft.js +416 -122
  214. package/dist/room-drafts.d.ts +24 -0
  215. package/dist/room-drafts.d.ts.map +1 -0
  216. package/dist/room-drafts.js +220 -0
  217. package/dist/rows.d.ts +32 -31
  218. package/dist/rows.d.ts.map +1 -1
  219. package/dist/rows.js +59 -124
  220. package/dist/runtime.d.ts +34 -0
  221. package/dist/runtime.d.ts.map +1 -0
  222. package/dist/runtime.js +1 -0
  223. package/dist/save.d.ts +43 -49
  224. package/dist/save.d.ts.map +1 -1
  225. package/dist/save.js +736 -302
  226. package/dist/saves.d.ts +32 -0
  227. package/dist/saves.d.ts.map +1 -0
  228. package/dist/saves.js +426 -0
  229. package/dist/search.d.ts +12 -95
  230. package/dist/search.d.ts.map +1 -1
  231. package/dist/search.js +10 -266
  232. package/dist/seed.d.ts +11 -2
  233. package/dist/seed.d.ts.map +1 -1
  234. package/dist/seed.js +71 -1
  235. package/dist/shared.d.ts +6 -7
  236. package/dist/shared.d.ts.map +1 -1
  237. package/dist/shared.js +75 -104
  238. package/dist/shown.d.ts +33 -0
  239. package/dist/shown.d.ts.map +1 -0
  240. package/dist/shown.js +309 -0
  241. package/dist/socket/admission.d.ts +7 -0
  242. package/dist/socket/admission.d.ts.map +1 -0
  243. package/dist/socket/admission.js +39 -0
  244. package/dist/socket/answers.d.ts +6 -0
  245. package/dist/socket/answers.d.ts.map +1 -0
  246. package/dist/socket/answers.js +20 -0
  247. package/dist/socket/lanes.d.ts +28 -0
  248. package/dist/socket/lanes.d.ts.map +1 -0
  249. package/dist/socket/lanes.js +103 -0
  250. package/dist/socket/reads.d.ts +10 -0
  251. package/dist/socket/reads.d.ts.map +1 -0
  252. package/dist/socket/reads.js +31 -0
  253. package/dist/socket/session.d.ts +38 -0
  254. package/dist/socket/session.d.ts.map +1 -0
  255. package/dist/socket/session.js +23 -0
  256. package/dist/socket.d.ts +67 -0
  257. package/dist/socket.d.ts.map +1 -0
  258. package/dist/socket.js +164 -0
  259. package/dist/source.d.ts +59 -0
  260. package/dist/source.d.ts.map +1 -0
  261. package/dist/source.js +93 -0
  262. package/dist/status.d.ts +4 -5
  263. package/dist/status.d.ts.map +1 -1
  264. package/dist/status.js +3 -7
  265. package/dist/store/installs.d.ts +30 -0
  266. package/dist/store/installs.d.ts.map +1 -0
  267. package/dist/store/installs.js +40 -0
  268. package/dist/store/readiness.d.ts +11 -0
  269. package/dist/store/readiness.d.ts.map +1 -0
  270. package/dist/store/readiness.js +68 -0
  271. package/dist/store/records.d.ts +217 -0
  272. package/dist/store/records.d.ts.map +1 -0
  273. package/dist/store/records.js +464 -0
  274. package/dist/store/room-held.d.ts +8 -0
  275. package/dist/store/room-held.d.ts.map +1 -0
  276. package/dist/store/room-held.js +17 -0
  277. package/dist/store/rooms-shown.d.ts +8 -0
  278. package/dist/store/rooms-shown.d.ts.map +1 -0
  279. package/dist/store/rooms-shown.js +13 -0
  280. package/dist/store/space.d.ts +11 -0
  281. package/dist/store/space.d.ts.map +1 -0
  282. package/dist/store/space.js +41 -0
  283. package/dist/store/watchers.d.ts +17 -0
  284. package/dist/store/watchers.d.ts.map +1 -0
  285. package/dist/store/watchers.js +56 -0
  286. package/dist/store/writes.d.ts +24 -0
  287. package/dist/store/writes.d.ts.map +1 -0
  288. package/dist/store/writes.js +125 -0
  289. package/dist/store.d.ts +114 -163
  290. package/dist/store.d.ts.map +1 -1
  291. package/dist/store.js +163 -750
  292. package/dist/stored.d.ts +167 -0
  293. package/dist/stored.d.ts.map +1 -0
  294. package/dist/stored.js +703 -0
  295. package/dist/surface.d.ts +89 -0
  296. package/dist/surface.d.ts.map +1 -0
  297. package/dist/surface.js +222 -0
  298. package/dist/sync.d.ts +19 -0
  299. package/dist/sync.d.ts.map +1 -0
  300. package/dist/sync.js +535 -0
  301. package/dist/tables.d.ts +419 -0
  302. package/dist/tables.d.ts.map +1 -0
  303. package/dist/tables.js +758 -0
  304. package/dist/tallies.d.ts +18 -0
  305. package/dist/tallies.d.ts.map +1 -0
  306. package/dist/tallies.js +128 -0
  307. package/dist/transfer.d.ts +0 -5
  308. package/dist/transfer.d.ts.map +1 -1
  309. package/dist/turn.d.ts +4 -2
  310. package/dist/turn.d.ts.map +1 -1
  311. package/dist/turn.js +46 -22
  312. package/dist/validation.d.ts +29 -0
  313. package/dist/validation.d.ts.map +1 -0
  314. package/dist/validation.js +98 -0
  315. package/dist/windows.d.ts +1 -16
  316. package/dist/windows.d.ts.map +1 -1
  317. package/dist/windows.js +2 -79
  318. package/dist/wire.d.ts +74 -9
  319. package/dist/wire.d.ts.map +1 -1
  320. package/dist/wire.js +26 -6
  321. package/package.json +19 -19
  322. package/AGENTS.md +0 -305
  323. package/dist/attempt.d.ts +0 -16
  324. package/dist/attempt.d.ts.map +0 -1
  325. package/dist/attempt.js +0 -70
  326. package/dist/chat/acts.d.ts +0 -33
  327. package/dist/chat/acts.d.ts.map +0 -1
  328. package/dist/chat/acts.js +0 -36
  329. package/dist/chat/context.d.ts +0 -3
  330. package/dist/chat/context.d.ts.map +0 -1
  331. package/dist/chat/earlier.d.ts +0 -10
  332. package/dist/chat/earlier.d.ts.map +0 -1
  333. package/dist/chat/earlier.js +0 -54
  334. package/dist/chat/input.d.ts +0 -9
  335. package/dist/chat/input.d.ts.map +0 -1
  336. package/dist/chat/input.js +0 -99
  337. package/dist/chat/kit.d.ts +0 -61
  338. package/dist/chat/kit.d.ts.map +0 -1
  339. package/dist/chat/kit.js +0 -123
  340. package/dist/chat/lasting.d.ts +0 -6
  341. package/dist/chat/lasting.d.ts.map +0 -1
  342. package/dist/chat/lasting.js +0 -19
  343. package/dist/chat/list.d.ts +0 -27
  344. package/dist/chat/list.d.ts.map +0 -1
  345. package/dist/chat/list.js +0 -99
  346. package/dist/chat/markdown.d.ts +0 -20
  347. package/dist/chat/markdown.d.ts.map +0 -1
  348. package/dist/chat/markdown.js +0 -188
  349. package/dist/chat/message.d.ts +0 -6
  350. package/dist/chat/message.d.ts.map +0 -1
  351. package/dist/chat/message.js +0 -192
  352. package/dist/chat/messages.d.ts +0 -22
  353. package/dist/chat/messages.d.ts.map +0 -1
  354. package/dist/chat/messages.js +0 -155
  355. package/dist/chat/name.d.ts +0 -6
  356. package/dist/chat/name.d.ts.map +0 -1
  357. package/dist/chat/name.js +0 -37
  358. package/dist/chat/opened.d.ts +0 -11
  359. package/dist/chat/opened.d.ts.map +0 -1
  360. package/dist/chat/opened.js +0 -17
  361. package/dist/chat/overlay.d.ts +0 -31
  362. package/dist/chat/overlay.d.ts.map +0 -1
  363. package/dist/chat/overlay.js +0 -97
  364. package/dist/chat/parts.d.ts +0 -57
  365. package/dist/chat/parts.d.ts.map +0 -1
  366. package/dist/chat/parts.js +0 -119
  367. package/dist/chat/process.d.ts +0 -20
  368. package/dist/chat/process.d.ts.map +0 -1
  369. package/dist/chat/process.js +0 -32
  370. package/dist/chat/provider.d.ts +0 -63
  371. package/dist/chat/provider.d.ts.map +0 -1
  372. package/dist/chat/provider.js +0 -628
  373. package/dist/chat/question.d.ts +0 -9
  374. package/dist/chat/question.d.ts.map +0 -1
  375. package/dist/chat/question.js +0 -69
  376. package/dist/chat/questions.d.ts.map +0 -1
  377. package/dist/chat/read.d.ts.map +0 -1
  378. package/dist/chat/ready.d.ts +0 -34
  379. package/dist/chat/ready.d.ts.map +0 -1
  380. package/dist/chat/ready.js +0 -91
  381. package/dist/chat/style.d.ts +0 -4
  382. package/dist/chat/style.d.ts.map +0 -1
  383. package/dist/chat/style.js +0 -302
  384. package/dist/chat.d.ts +0 -14
  385. package/dist/chat.d.ts.map +0 -1
  386. package/dist/chat.js +0 -8
  387. package/dist/fence.d.ts +0 -6
  388. package/dist/fence.d.ts.map +0 -1
  389. package/dist/fence.js +0 -10
  390. package/dist/log.d.ts +0 -5
  391. package/dist/log.d.ts.map +0 -1
  392. package/dist/log.js +0 -14
  393. package/dist/read-side.d.ts +0 -27
  394. package/dist/read-side.d.ts.map +0 -1
  395. package/dist/read-side.js +0 -824
package/dist/search.js CHANGED
@@ -1,270 +1,14 @@
1
- import MiniSearch from 'minisearch';
2
- import { indexGeneration } from './identity.js';
3
- import { flag, invalid, known, limitOf, plain, } from './query.js';
4
- import { beneath } from './paths.js';
5
- import { inUnits, ROW_WEIGHT } from './turn.js';
6
- import { decodedCursor } from './windows.js';
7
- export function undeclaredSearch() {
8
- return {
9
- kind: 'undeclared',
10
- code: 'search-undeclared',
11
- fields: { name: 'local_search' },
12
- retryable: false,
13
- };
14
- }
15
- const FIELDS = ['fields', 'sections', 'preamble', 'path', 'text'];
16
- function documentId(room, path) {
17
- return JSON.stringify(['document', room, path]);
18
- }
19
- function messageId(conversation, identity) {
20
- return JSON.stringify(['message', conversation, identity]);
21
- }
22
- function scalars(value) {
23
- if (value === null || value === undefined)
24
- return [];
25
- if (Array.isArray(value))
26
- return value.flatMap(scalars);
27
- if (typeof value === 'object')
28
- return Object.values(value).flatMap(scalars);
29
- return [String(value)];
30
- }
31
- function hitCursor(input) {
32
- if (input === null)
33
- return null;
34
- if (!Array.isArray(input))
35
- return undefined;
36
- if (input.length === 0)
37
- return [];
38
- const [score, first, second] = input;
39
- return input.length === 3 &&
40
- typeof score === 'number' &&
41
- typeof first === 'string' &&
42
- typeof second === 'string'
43
- ? [score, first, second]
44
- : undefined;
45
- }
46
- function searchAfter(input) {
47
- if (input === undefined)
48
- return null;
49
- const decoded = typeof input === 'string' ? decodedCursor(input) : null;
50
- const documents = decoded?.length === 2 ? hitCursor(decoded[0]) : undefined;
51
- const messages = decoded?.length === 2 ? hitCursor(decoded[1]) : undefined;
52
- if (documents === undefined || messages === undefined) {
53
- invalid('after', 'expects the next an earlier search returned');
54
- }
55
- return [documents, messages];
56
- }
1
+ import { invalid, known, plain } from '@agentshouse/mdmodel';
57
2
  export function searchPlanOf(input) {
58
3
  if (!plain(input))
59
4
  invalid('search', 'expects a search object');
60
- known(input, ['text', 'documents', 'collection', 'conversations', 'limit', 'after', 'total'], '');
61
- if (typeof input.text !== 'string')
62
- invalid('text', 'expects text');
63
- const conversations = input.conversations;
64
- if (conversations !== undefined &&
65
- (!Array.isArray(conversations) || conversations.some((named) => typeof named !== 'string'))) {
66
- invalid('conversations', 'expects a list of conversations');
67
- }
68
- return {
69
- text: input.text,
70
- documents: input.documents,
71
- collection: flag(input.collection, 'collection'),
72
- conversations: conversations ?? null,
73
- limit: limitOf(input.limit),
74
- after: searchAfter(input.after),
75
- total: flag(input.total, 'total'),
76
- };
77
- }
78
- function pair(left, right) {
79
- if (left[0] !== right[0])
80
- return left[0] < right[0] ? -1 : 1;
81
- if (left[1] !== right[1])
82
- return left[1] < right[1] ? -1 : 1;
83
- return 0;
84
- }
85
- function hitWindow(found, cursor, limit, tie) {
86
- if (cursor === null)
87
- return { kept: [], cursor: null };
88
- const start = cursor.length === 0
89
- ? 0
90
- : found.findIndex((hit) => hit.score < cursor[0] ||
91
- (hit.score === cursor[0] && pair(tie(hit), [cursor[1], cursor[2]]) > 0));
92
- const following = start === -1 ? [] : found.slice(start);
93
- if (limit === null || following.length <= limit)
94
- return { kept: following, cursor: null };
95
- const kept = following.slice(0, limit);
96
- const last = kept[kept.length - 1];
97
- return { kept, cursor: last === undefined ? cursor : [last.score, ...tie(last)] };
98
- }
99
- export function createSearchIndex(source) {
100
- const generation = indexGeneration();
101
- const index = new MiniSearch({ fields: FIELDS });
102
- const documents = new Map();
103
- const messages = new Map();
104
- const rooms = new Set();
105
- const filling = new Set();
106
- const conversations = new Set();
107
- const acquiring = new Set();
108
- const changedDocuments = new Map();
109
- let changes = 0;
110
- function addDocument(document) {
111
- const id = documentId(document.room, document.path);
112
- discard(id, documents);
113
- index.add({
114
- id,
115
- fields: scalars(document.fields).join('\n'),
116
- sections: Object.entries(document.sections)
117
- .map(([heading, text]) => `${heading}\n${text}`)
118
- .join('\n'),
119
- preamble: document.preamble,
120
- path: document.path,
121
- });
122
- documents.set(id, { room: document.room, path: document.path, type: document.type });
123
- }
124
- function addMessage(message) {
125
- const id = messageId(message.conversation, message.identity);
126
- discard(id, messages);
127
- index.add({ id, text: message.text });
128
- messages.set(id, { conversation: message.conversation, identity: message.identity });
129
- }
130
- function discard(id, entries) {
131
- if (entries.delete(id))
132
- index.discard(id);
133
- }
134
- function* pending() {
135
- for (;;) {
136
- const next = changedDocuments.entries().next();
137
- if (next.done === true)
138
- return;
139
- changedDocuments.delete(next.value[0]);
140
- yield next.value;
141
- }
142
- }
143
- let catching = null;
144
- function caughtUp() {
145
- if (catching !== null)
146
- return catching;
147
- const running = inUnits(pending(), ([id, { room, path }]) => {
148
- discard(id, documents);
149
- const document = source.document(room, path);
150
- if (document === null)
151
- return ROW_WEIGHT;
152
- addDocument(document);
153
- return Object.values(document.sections).reduce((total, text) => total + text.length, ROW_WEIGHT + document.preamble.length);
154
- });
155
- if (!(running instanceof Promise))
156
- return Promise.resolve();
157
- catching = running.finally(() => {
158
- catching = null;
159
- });
160
- return catching;
161
- }
162
- function ranked(text, entries, keep, tie) {
163
- const found = index.search(text, {
164
- filter: ({ id }) => {
165
- const entry = entries.get(id);
166
- return entry !== undefined && keep(entry, id);
167
- },
168
- });
169
- found.sort((left, right) => right.score - left.score ||
170
- pair(tie(entries.get(left.id)), tie(entries.get(right.id))));
171
- return found.map(({ id, score, match }) => ({
172
- ...entries.get(id),
173
- score,
174
- match,
175
- }));
176
- }
177
- return {
178
- generation: () => generation,
179
- rooms: () => rooms,
180
- conversations: () => conversations,
181
- async indexRoom(room) {
182
- if (rooms.has(room) || filling.has(room))
183
- return;
184
- filling.add(room);
185
- try {
186
- await inUnits(source.room(room), (path) => {
187
- const document = filling.has(room) ? source.document(room, path) : null;
188
- if (document === null)
189
- return ROW_WEIGHT;
190
- addDocument(document);
191
- return Object.values(document.sections).reduce((total, text) => total + text.length, ROW_WEIGHT + document.preamble.length);
192
- });
193
- if (filling.has(room))
194
- rooms.add(room);
195
- }
196
- finally {
197
- filling.delete(room);
198
- }
199
- },
200
- indexMessages(conversation, arriving, whole) {
201
- for (const message of arriving)
202
- addMessage(message);
203
- if (!whole) {
204
- acquiring.add(conversation);
205
- return;
206
- }
207
- acquiring.delete(conversation);
208
- conversations.add(conversation);
209
- },
210
- forget(leaving) {
211
- const gone = new Set(leaving);
212
- for (const [id, entry] of documents)
213
- if (gone.has(entry.room))
214
- discard(id, documents);
215
- for (const room of leaving) {
216
- rooms.delete(room);
217
- filling.delete(room);
218
- }
219
- },
220
- changed(set) {
221
- changes += 1;
222
- for (const { locator, path } of set.documents) {
223
- if (rooms.has(locator) || filling.has(locator)) {
224
- changedDocuments.set(documentId(locator, path), { room: locator, path });
225
- }
226
- }
227
- for (const { conversation, identity, text } of set.messages) {
228
- if (!conversations.has(conversation) && !acquiring.has(conversation))
229
- continue;
230
- const id = messageId(conversation, identity);
231
- if (text === null)
232
- discard(id, messages);
233
- else
234
- addMessage({ conversation, identity, text });
235
- }
236
- },
237
- changes: () => changes,
238
- caughtUp,
239
- search({ text, limit, after, total }, selected, named, within, selections) {
240
- const chosen = selected === null
241
- ? null
242
- : new Set(selected.map(({ room, path }) => documentId(room, path)));
243
- const asked = new Set(named);
244
- const documentTie = ({ room, path }) => [room, path];
245
- const messageTie = ({ conversation, identity }) => [conversation, identity];
246
- const foundDocuments = ranked(text, documents, ({ room, path }, id) => (chosen === null || chosen.has(id)) &&
247
- (within === null || within.has(room)) &&
248
- !(selections?.get(room) ?? []).some((root) => beneath(root, path)), documentTie);
249
- const foundMessages = ranked(text, messages, ({ conversation }) => asked.has(conversation), messageTie);
250
- const [documentsAfter, messagesAfter] = after ?? [[], []];
251
- const documentWindow = hitWindow(foundDocuments, documentsAfter, limit, documentTie);
252
- const messageWindow = hitWindow(foundMessages, messagesAfter, limit, messageTie);
253
- const more = documentWindow.cursor !== null || messageWindow.cursor !== null;
254
- return {
255
- documents: documentWindow.kept.map(({ match, ...hit }) => ({
256
- ...hit,
257
- matches: match,
258
- })),
259
- messages: messageWindow.kept.map(({ match, ...hit }) => ({
260
- ...hit,
261
- matches: match,
262
- })),
263
- ...(more ? { next: JSON.stringify([documentWindow.cursor, messageWindow.cursor]) } : {}),
264
- ...(total
265
- ? { total: { documents: foundDocuments.length, messages: foundMessages.length } }
266
- : {}),
267
- };
268
- },
269
- };
5
+ known(input, ['text', 'rooms'], '');
6
+ if (typeof input.text !== 'string' || input.text.trim() === '')
7
+ invalid('text', 'expects words');
8
+ const rooms = input.rooms;
9
+ if (rooms !== undefined &&
10
+ (!Array.isArray(rooms) || rooms.some((named) => typeof named !== 'string'))) {
11
+ invalid('rooms', 'expects a list of Rooms');
12
+ }
13
+ return { text: input.text, rooms: rooms ?? null };
270
14
  }
package/dist/seed.d.ts CHANGED
@@ -1,5 +1,9 @@
1
- import type { KeyedResult } from './observation.js';
2
- import type { QueryRows } from './query.js';
1
+ import type { Cover } from './live.js';
2
+ import { type KeyedResult } from './observation.js';
3
+ import type { Plan, QueryRows } from './query.js';
4
+ import type { Deliver } from './reach.js';
5
+ import type { Runtime } from './runtime.js';
6
+ import type { HeldCover, Store } from './store.js';
3
7
  export type EntrySeed = {
4
8
  readonly at: Readonly<Record<string, string>>;
5
9
  readonly queries: readonly {
@@ -11,6 +15,11 @@ export type Seeded = {
11
15
  readonly rows: QueryRows;
12
16
  readonly at: Readonly<Record<string, string>>;
13
17
  };
18
+ type SeededWatch = (coverOf: (cover: Cover, held: HeldCover) => Cover, deliver: (message: unknown) => void) => () => void;
14
19
  export declare function entrySeedOf(value: unknown): EntrySeed | null;
15
20
  export declare function seededResult(seed: Seeded): KeyedResult;
21
+ export declare function seedApplies(runtime: Runtime, plan: Plan, held: HeldCover): Seeded | null;
22
+ export declare function keepEntrySeed(store: Store, entry: EntrySeed): void;
23
+ export declare function watchSeeded(runtime: Runtime, plan: Plan, deliver: Deliver, watch: SeededWatch): () => void;
24
+ export {};
16
25
  //# sourceMappingURL=seed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAA4C,SAAS,EAAE,MAAM,YAAY,CAAC;AAGtF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;KAAE,EAAE,CAAC;CACpF,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC;AAwCjG,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAe5D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAoBtD"}
1
+ {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAwB,KAAK,WAAW,EAAqB,MAAM,kBAAkB,CAAC;AAC7F,OAAO,KAAK,EAAE,IAAI,EAA4C,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,SAAS;QAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;KAAE,EAAE,CAAC;CACpF,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC;AAEjG,KAAK,WAAW,GAAG,CACjB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,KAAK,KAAK,EACjD,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,KAChC,MAAM,IAAI,CAAC;AA0ChB,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAe5D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAmBtD;AA+BD,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAOxF;AAYD,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAMlE;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,WAAW,GACjB,MAAM,IAAI,CA4BZ"}
package/dist/seed.js CHANGED
@@ -1,4 +1,7 @@
1
+ import { queryKey } from '@agentshouse/mdmodel';
2
+ import { pendingChange, whole } from './observation.js';
1
3
  import { documentKey } from './rows.js';
4
+ const seedTopic = (key) => `seed\u0000${key}`;
2
5
  function plain(value) {
3
6
  return typeof value === 'object' && value !== null && !Array.isArray(value);
4
7
  }
@@ -59,7 +62,6 @@ export function seededResult(seed) {
59
62
  generation,
60
63
  current: false,
61
64
  })),
62
- indexes: [],
63
65
  overlay: [],
64
66
  };
65
67
  if ('groups' in seed.rows) {
@@ -73,3 +75,71 @@ export function seededResult(seed) {
73
75
  keys: seed.rows.documents.map((document) => documentKey(document.room, document.path)),
74
76
  };
75
77
  }
78
+ function seedRoomHeld({ socket }, room, version, held) {
79
+ const stored = held.rooms.get(room);
80
+ return (stored !== undefined &&
81
+ stored.indexed &&
82
+ socket.reads.reached(room, stored.roomVersion, version));
83
+ }
84
+ function seedHeld(runtime, at, held) {
85
+ const { socket, presence } = runtime;
86
+ return Object.entries(at).every(([room, version]) => (socket.session.now().roomsListed &&
87
+ presence.room(room) === undefined &&
88
+ !held.rooms.has(room)) ||
89
+ seedRoomHeld(runtime, room, version, held));
90
+ }
91
+ export function seedApplies(runtime, plan, held) {
92
+ const { seeds } = runtime.store;
93
+ const seed = seeds.of(plan.key);
94
+ if (seed === undefined)
95
+ return null;
96
+ if (!seedHeld(runtime, seed.at, held))
97
+ return seed;
98
+ seeds.drop(plan.key);
99
+ return null;
100
+ }
101
+ function seedBehind(runtime, plan, cover, held) {
102
+ const seed = seedApplies(runtime, plan, held);
103
+ if (seed === null || 'pending' in cover)
104
+ return cover;
105
+ return {
106
+ pending: Object.entries(seed.at)
107
+ .filter(([room, version]) => !seedRoomHeld(runtime, room, version, held))
108
+ .map(([room]) => ({ room, awaits: 'acquisition' })),
109
+ };
110
+ }
111
+ export function keepEntrySeed(store, entry) {
112
+ for (const { query, rows } of entry.queries) {
113
+ const key = queryKey(query);
114
+ store.seeds.keep(key, { rows, at: entry.at });
115
+ for (const watcher of store.watching(seedTopic(key)))
116
+ watcher.answer(null);
117
+ }
118
+ }
119
+ export function watchSeeded(runtime, plan, deliver, watch) {
120
+ const { store } = runtime;
121
+ let seeded = false;
122
+ let pending = true;
123
+ const shown = () => {
124
+ const seed = store.seeds.of(plan.key);
125
+ if (seed === undefined || seeded || !pending)
126
+ return;
127
+ seeded = true;
128
+ deliver(seededResult(seed));
129
+ };
130
+ const watcher = store.watch(seedTopic(plan.key), shown);
131
+ const stop = watch((cover, held) => seedBehind(runtime, plan, cover, held), (message) => {
132
+ const answered = message;
133
+ pending = whole(answered) ? 'pending' in answered.result : pendingChange(answered);
134
+ if (pending && store.seeds.of(plan.key) !== undefined) {
135
+ shown();
136
+ return;
137
+ }
138
+ seeded = false;
139
+ deliver(message);
140
+ });
141
+ return () => {
142
+ watcher.stop();
143
+ stop();
144
+ };
145
+ }
package/dist/shared.d.ts CHANGED
@@ -1,11 +1,10 @@
1
1
  export type Paths<V> = Readonly<Record<string, V>>;
2
- type Weigh<V> = (key: string, value: V) => number;
3
- export declare function shared<V>(map: Paths<V>): Paths<V>;
4
- export declare function patched<V>(base: Paths<V>, set: Iterable<readonly [string, V]>, removed?: Iterable<string>): Paths<V>;
5
- export declare function tally<V>(map: Paths<V>, weigh: Weigh<V>): number;
6
- export declare function sizeOf<V>(map: Paths<V>): number;
7
- export declare function differing<V>(left: Paths<V>, right: Paths<V>, same?: (left: V, right: V) => boolean): ReadonlySet<string>;
2
+ export declare function guarding<V>(values: Paths<V>, handler: ProxyHandler<Paths<V>>): Paths<V>;
3
+ export declare function entriesIn<V>(map: Paths<V>): Generator<readonly [string, V]>;
4
+ export declare function sortedKeys(map: Paths<unknown>): Generator<number, readonly string[], void>;
5
+ export declare function sorting(keys: Iterable<string>): Generator<number, readonly string[], void>;
6
+ export declare function patching<V>(base: Paths<V>, set: Iterable<readonly [string, V]>, removed?: Iterable<string>): Generator<number, Paths<V>, void>;
8
7
  export declare function drafted<V>(base: Paths<V>): Record<string, V>;
9
8
  export declare function settled<V>(draft: Record<string, V>): Paths<V>;
10
- export {};
9
+ export declare function settling<V>(draft: Record<string, V>): Generator<number, Paths<V>, void>;
11
10
  //# sourceMappingURL=shared.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AAkBnD,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;AA6LlD,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAEjD;AAED,wBAAgB,OAAO,CAAC,CAAC,EACvB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EACnC,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAM,GAC7B,KAAK,CAAC,CAAC,CAAC,CA8BV;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAY/D;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAE/C;AAuCD,wBAAgB,SAAS,CAAC,CAAC,EACzB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,IAAI,GAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAmB,GAC/C,WAAW,CAAC,MAAM,CAAC,CAcrB;AAMD,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAiD5D;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAS7D"}
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../src/shared.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;AA8LnD,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAIvF;AAED,wBAAiB,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAQ5E;AAqCD,wBAAiB,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,CAAC,CAE3F;AAED,wBAAiB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,CAAC,CAoB3F;AAED,wBAAiB,QAAQ,CAAC,CAAC,EACzB,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EACd,GAAG,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EACnC,OAAO,GAAE,QAAQ,CAAC,MAAM,CAAM,GAC7B,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAgBnC;AAMD,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAiD5D;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAE7D;AAED,wBAAiB,QAAQ,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAUxF"}
package/dist/shared.js CHANGED
@@ -1,7 +1,7 @@
1
+ import { finished, ROW_WEIGHT } from './turn.js';
1
2
  const BITS = 5;
2
3
  const MASK = (1 << BITS) - 1;
3
4
  const roots = new WeakMap();
4
- const tallies = new WeakMap();
5
5
  function hashOf(key) {
6
6
  let hash = 0x811c9dc5;
7
7
  for (let index = 0; index < key.length; index += 1) {
@@ -100,21 +100,15 @@ function lone(node) {
100
100
  }
101
101
  function taken(node, hash, key, shift) {
102
102
  if (isLeaf(node))
103
- return node.key === key ? undefined : node;
103
+ return undefined;
104
104
  if (isCollision(node)) {
105
105
  const leaves = node.leaves.filter((leaf) => leaf.key !== key);
106
- if (leaves.length === node.leaves.length)
107
- return node;
108
106
  return leaves.length === 1 ? leaves[0] : { hash: node.hash, leaves };
109
107
  }
110
108
  const bit = 1 << fragment(hash, shift);
111
- if ((node.bitmap & bit) === 0)
112
- return node;
113
109
  const at = slot(node.bitmap, bit);
114
110
  const child = node.children[at];
115
111
  const next = taken(child, hash, key, shift + BITS);
116
- if (next === child)
117
- return node;
118
112
  if (next === undefined) {
119
113
  if (node.children.length === 1)
120
114
  return undefined;
@@ -179,122 +173,95 @@ function facade(root) {
179
173
  roots.set(map, root);
180
174
  return map;
181
175
  }
182
- function rootOf(map) {
176
+ const guarded = new WeakMap();
177
+ export function guarding(values, handler) {
178
+ const map = new Proxy(values, handler);
179
+ guarded.set(map, values);
180
+ return map;
181
+ }
182
+ export function* entriesIn(map) {
183
+ const root = roots.get(map);
184
+ if (root === undefined) {
185
+ const values = guarded.get(map) ?? map;
186
+ for (const key of Object.keys(values))
187
+ yield [key, values[key]];
188
+ return;
189
+ }
190
+ for (const leaf of leavesOf(root.node))
191
+ yield [leaf.key, leaf.value];
192
+ }
193
+ function* rooted(map) {
183
194
  const held = roots.get(map);
184
195
  if (held !== undefined)
185
196
  return held;
186
197
  let node;
187
- let size = 0;
188
- for (const [key, value] of Object.entries(map)) {
198
+ for (const [key, value] of entriesIn(map)) {
189
199
  node = put(node, { key, hash: hashOf(key), value }, 0);
190
- size += 1;
200
+ yield ROW_WEIGHT;
191
201
  }
192
- return { node, size };
202
+ return { node };
193
203
  }
194
- export function shared(map) {
195
- return roots.has(map) ? map : facade(rootOf(map));
204
+ const RUN = 1 << 10;
205
+ function* merged(left, right) {
206
+ const into = [];
207
+ let at = 0;
208
+ let from = 0;
209
+ while (at < left.length || from < right.length) {
210
+ into.push(from === right.length || (at < left.length && left[at] < right[from])
211
+ ? left[at++]
212
+ : right[from++]);
213
+ yield ROW_WEIGHT;
214
+ }
215
+ return into;
196
216
  }
197
- export function patched(base, set, removed = []) {
198
- const root = rootOf(base);
199
- const weighed = [...(tallies.get(base) ?? [])];
200
- let node = root.node;
201
- let size = root.size;
202
- const shift = (key, before, after) => {
203
- for (const entry of weighed) {
204
- entry[1] +=
205
- (after === undefined ? 0 : entry[0](key, after)) -
206
- (before === undefined ? 0 : entry[0](key, before.value));
217
+ function* pathsOf(map) {
218
+ for (const [key] of entriesIn(map))
219
+ yield key;
220
+ }
221
+ export function* sortedKeys(map) {
222
+ return yield* sorting(pathsOf(map));
223
+ }
224
+ export function* sorting(keys) {
225
+ let runs = [];
226
+ let run = [];
227
+ for (const key of keys) {
228
+ run.push(key);
229
+ yield ROW_WEIGHT;
230
+ if (run.length === RUN) {
231
+ runs.push(run.sort());
232
+ run = [];
207
233
  }
208
- };
234
+ }
235
+ if (run.length > 0)
236
+ runs.push(run.sort());
237
+ while (runs.length > 1) {
238
+ const next = [];
239
+ for (let at = 0; at < runs.length; at += 2) {
240
+ next.push(at + 1 === runs.length ? runs[at] : yield* merged(runs[at], runs[at + 1]));
241
+ }
242
+ runs = next;
243
+ }
244
+ return runs[0] ?? [];
245
+ }
246
+ export function* patching(base, set, removed = []) {
247
+ const root = yield* rooted(base);
248
+ let node = root.node;
209
249
  for (const key of removed) {
210
250
  if (node === undefined)
211
251
  break;
212
- const before = lookup({ node, size }, key);
252
+ const before = lookup({ node }, key);
213
253
  if (before === undefined)
214
254
  continue;
215
255
  node = taken(node, before.hash, key, 0);
216
- size -= 1;
217
- shift(key, before, undefined);
256
+ yield ROW_WEIGHT;
218
257
  }
219
258
  for (const [key, value] of set) {
220
- const before = lookup({ node, size }, key);
221
259
  node = put(node, { key, hash: hashOf(key), value }, 0);
222
- if (before === undefined)
223
- size += 1;
224
- shift(key, before, value);
260
+ yield ROW_WEIGHT;
225
261
  }
226
262
  if (node === root.node && roots.has(base))
227
263
  return base;
228
- const map = facade({ node, size });
229
- if (weighed.length > 0)
230
- tallies.set(map, new Map(weighed));
231
- return map;
232
- }
233
- export function tally(map, weigh) {
234
- const held = tallies.get(map);
235
- const known = held?.get(weigh);
236
- if (known !== undefined)
237
- return known;
238
- let total = 0;
239
- for (const [key, value] of Object.entries(map))
240
- total += weigh(key, value);
241
- if (roots.has(map)) {
242
- const kept = held ?? new Map();
243
- kept.set(weigh, total);
244
- tallies.set(map, kept);
245
- }
246
- return total;
247
- }
248
- export function sizeOf(map) {
249
- return roots.get(map)?.size ?? Object.keys(map).length;
250
- }
251
- function collect(node, into) {
252
- for (const leaf of leavesOf(node))
253
- into.add(leaf.key);
254
- }
255
- function compared(left, right, shift, same, into) {
256
- if (left === right)
257
- return;
258
- if (left === undefined)
259
- return collect(right, into);
260
- if (right === undefined)
261
- return collect(left, into);
262
- if (!isLeaf(left) && !isCollision(left) && !isLeaf(right) && !isCollision(right)) {
263
- const bits = left.bitmap | right.bitmap;
264
- for (let remaining = bits; remaining !== 0; remaining &= remaining - 1) {
265
- const bit = remaining & -remaining;
266
- compared((left.bitmap & bit) === 0 ? undefined : left.children[slot(left.bitmap, bit)], (right.bitmap & bit) === 0 ? undefined : right.children[slot(right.bitmap, bit)], shift + BITS, same, into);
267
- }
268
- return;
269
- }
270
- const before = new Map([...leavesOf(left)].map((leaf) => [leaf.key, leaf.value]));
271
- for (const leaf of leavesOf(right)) {
272
- const held = before.get(leaf.key);
273
- before.delete(leaf.key);
274
- if (held === undefined || !same(held, leaf.value))
275
- into.add(leaf.key);
276
- }
277
- for (const key of before.keys())
278
- into.add(key);
279
- }
280
- export function differing(left, right, same = Object.is) {
281
- const into = new Set();
282
- if (left === right)
283
- return into;
284
- const leftRoot = roots.get(left);
285
- const rightRoot = roots.get(right);
286
- if (leftRoot !== undefined && rightRoot !== undefined) {
287
- compared(leftRoot.node, rightRoot.node, 0, same, into);
288
- return into;
289
- }
290
- for (const key of Object.keys(left)) {
291
- if (!Object.hasOwn(right, key) || !same(left[key], right[key]))
292
- into.add(key);
293
- }
294
- for (const key of Object.keys(right))
295
- if (!Object.hasOwn(left, key))
296
- into.add(key);
297
- return into;
264
+ return facade({ node });
298
265
  }
299
266
  const drafts = new WeakMap();
300
267
  const GONE = Symbol('gone');
@@ -355,6 +322,9 @@ export function drafted(base) {
355
322
  return draft;
356
323
  }
357
324
  export function settled(draft) {
325
+ return finished(settling(draft));
326
+ }
327
+ export function* settling(draft) {
358
328
  const held = drafts.get(draft);
359
329
  const set = [];
360
330
  const removed = [];
@@ -363,6 +333,7 @@ export function settled(draft) {
363
333
  removed.push(key);
364
334
  else
365
335
  set.push([key, value]);
336
+ yield ROW_WEIGHT;
366
337
  }
367
- return patched(held.base, set, removed);
338
+ return yield* patching(held.base, set, removed);
368
339
  }