@agentshouse/mdruntime 0.1.0-c069136dcb4e8 → 0.1.0-c076b00ebf42a

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 (316) hide show
  1. package/README.md +21 -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 +108 -85
  12. package/dist/adapter.d.ts.map +1 -1
  13. package/dist/attached-model.d.ts +3 -11
  14. package/dist/attached-model.d.ts.map +1 -1
  15. package/dist/attached-model.js +20 -60
  16. package/dist/bootstrap.d.ts +9 -5
  17. package/dist/bootstrap.d.ts.map +1 -1
  18. package/dist/bootstrap.js +204 -85
  19. package/dist/cell.d.ts +6 -0
  20. package/dist/cell.d.ts.map +1 -0
  21. package/dist/cell.js +9 -0
  22. package/dist/chain.d.ts +2 -1
  23. package/dist/chain.d.ts.map +1 -1
  24. package/dist/change-set.d.ts +4 -0
  25. package/dist/change-set.d.ts.map +1 -1
  26. package/dist/change-set.js +6 -0
  27. package/dist/change.d.ts +1 -0
  28. package/dist/change.d.ts.map +1 -1
  29. package/dist/change.js +4 -2
  30. package/dist/chat-types.d.ts +3 -0
  31. package/dist/chat-types.d.ts.map +1 -0
  32. package/dist/chat-types.js +11 -0
  33. package/dist/client.d.ts +29 -22
  34. package/dist/client.d.ts.map +1 -1
  35. package/dist/client.js +36 -20
  36. package/dist/collection.d.ts +26 -4
  37. package/dist/collection.d.ts.map +1 -1
  38. package/dist/collection.js +19 -2
  39. package/dist/compile.d.ts +8 -6
  40. package/dist/compile.d.ts.map +1 -1
  41. package/dist/compile.js +286 -336
  42. package/dist/connection.d.ts +5 -142
  43. package/dist/connection.d.ts.map +1 -1
  44. package/dist/connection.js +110 -4970
  45. package/dist/context.d.ts +2 -0
  46. package/dist/context.d.ts.map +1 -0
  47. package/dist/context.js +7 -0
  48. package/dist/conversation-live.d.ts +150 -0
  49. package/dist/conversation-live.d.ts.map +1 -0
  50. package/dist/conversation-live.js +259 -0
  51. package/dist/conversation-row.d.ts +35 -0
  52. package/dist/conversation-row.d.ts.map +1 -0
  53. package/dist/conversation-row.js +55 -0
  54. package/dist/conversation.d.ts +65 -44
  55. package/dist/conversation.d.ts.map +1 -1
  56. package/dist/conversation.js +999 -881
  57. package/dist/declaration.d.ts +10 -0
  58. package/dist/declaration.d.ts.map +1 -0
  59. package/dist/declaration.js +24 -0
  60. package/dist/discovery.d.ts +10 -0
  61. package/dist/discovery.d.ts.map +1 -0
  62. package/dist/discovery.js +150 -0
  63. package/dist/durability.d.ts +19 -0
  64. package/dist/durability.d.ts.map +1 -1
  65. package/dist/durability.js +4 -0
  66. package/dist/entry.d.ts +2 -2
  67. package/dist/entry.d.ts.map +1 -1
  68. package/dist/entry.js +18 -8
  69. package/dist/expectation.d.ts +26 -13
  70. package/dist/expectation.d.ts.map +1 -1
  71. package/dist/expectation.js +72 -19
  72. package/dist/failure.d.ts +3 -0
  73. package/dist/failure.d.ts.map +1 -1
  74. package/dist/failure.js +6 -0
  75. package/dist/figures.d.ts +49 -0
  76. package/dist/figures.d.ts.map +1 -0
  77. package/dist/figures.js +199 -0
  78. package/dist/file.d.ts.map +1 -1
  79. package/dist/file.js +2 -1
  80. package/dist/holdings.d.ts +29 -0
  81. package/dist/holdings.d.ts.map +1 -0
  82. package/dist/holdings.js +95 -0
  83. package/dist/host.d.ts +21 -7
  84. package/dist/host.d.ts.map +1 -1
  85. package/dist/host.js +77 -41
  86. package/dist/identity.d.ts +0 -1
  87. package/dist/identity.d.ts.map +1 -1
  88. package/dist/identity.js +0 -3
  89. package/dist/index.d.ts +34 -12
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +16 -5
  92. package/dist/install.d.ts +60 -0
  93. package/dist/install.d.ts.map +1 -0
  94. package/dist/install.js +537 -0
  95. package/dist/lifecycle.d.ts +7 -0
  96. package/dist/lifecycle.d.ts.map +1 -0
  97. package/dist/lifecycle.js +278 -0
  98. package/dist/listing.d.ts +52 -0
  99. package/dist/listing.d.ts.map +1 -0
  100. package/dist/listing.js +152 -0
  101. package/dist/live.d.ts +9 -6
  102. package/dist/live.d.ts.map +1 -1
  103. package/dist/live.js +118 -36
  104. package/dist/locks.d.ts +7 -0
  105. package/dist/locks.d.ts.map +1 -0
  106. package/dist/locks.js +32 -0
  107. package/dist/lost.d.ts +5 -0
  108. package/dist/lost.d.ts.map +1 -0
  109. package/dist/lost.js +49 -0
  110. package/dist/media.d.ts +1 -1
  111. package/dist/media.d.ts.map +1 -1
  112. package/dist/media.js +10 -13
  113. package/dist/memory.d.ts +15 -6
  114. package/dist/memory.d.ts.map +1 -1
  115. package/dist/memory.js +178 -89
  116. package/dist/messages.d.ts +35 -5
  117. package/dist/messages.d.ts.map +1 -1
  118. package/dist/messages.js +108 -36
  119. package/dist/model.d.ts +2 -10
  120. package/dist/model.d.ts.map +1 -1
  121. package/dist/model.js +0 -14
  122. package/dist/models.d.ts +10 -0
  123. package/dist/models.d.ts.map +1 -0
  124. package/dist/models.js +153 -0
  125. package/dist/observation.d.ts +28 -13
  126. package/dist/observation.d.ts.map +1 -1
  127. package/dist/observation.js +185 -81
  128. package/dist/opened.d.ts +1 -1
  129. package/dist/opened.d.ts.map +1 -1
  130. package/dist/opened.js +5 -5
  131. package/dist/opening.d.ts +4 -0
  132. package/dist/opening.d.ts.map +1 -0
  133. package/dist/opening.js +53 -0
  134. package/dist/outcome.d.ts +11 -1
  135. package/dist/outcome.d.ts.map +1 -1
  136. package/dist/outcome.js +26 -2
  137. package/dist/overlay.d.ts +6 -1
  138. package/dist/overlay.d.ts.map +1 -1
  139. package/dist/overlay.js +47 -21
  140. package/dist/page-metadata.d.ts +8 -0
  141. package/dist/page-metadata.d.ts.map +1 -0
  142. package/dist/page-metadata.js +19 -0
  143. package/dist/parts.d.ts +4 -0
  144. package/dist/parts.d.ts.map +1 -0
  145. package/dist/parts.js +13 -0
  146. package/dist/paths.d.ts +1 -0
  147. package/dist/paths.d.ts.map +1 -1
  148. package/dist/paths.js +22 -0
  149. package/dist/preparation.d.ts +41 -0
  150. package/dist/preparation.d.ts.map +1 -0
  151. package/dist/preparation.js +314 -0
  152. package/dist/presence.d.ts +58 -0
  153. package/dist/presence.d.ts.map +1 -0
  154. package/dist/presence.js +233 -0
  155. package/dist/queries.d.ts +16 -0
  156. package/dist/queries.d.ts.map +1 -0
  157. package/dist/queries.js +308 -0
  158. package/dist/query.d.ts +14 -210
  159. package/dist/query.d.ts.map +1 -1
  160. package/dist/query.js +3 -505
  161. package/dist/questions.d.ts +29 -0
  162. package/dist/questions.d.ts.map +1 -0
  163. package/dist/questions.js +115 -0
  164. package/dist/queue.d.ts +40 -0
  165. package/dist/queue.d.ts.map +1 -0
  166. package/dist/queue.js +450 -0
  167. package/dist/reach.d.ts +16 -15
  168. package/dist/reach.d.ts.map +1 -1
  169. package/dist/reach.js +248 -147
  170. package/dist/react.d.ts +17 -3
  171. package/dist/react.d.ts.map +1 -1
  172. package/dist/react.js +33 -1
  173. package/dist/read.d.ts +7 -0
  174. package/dist/read.d.ts.map +1 -0
  175. package/dist/read.js +17 -0
  176. package/dist/readiness.d.ts +9 -6
  177. package/dist/readiness.d.ts.map +1 -1
  178. package/dist/readiness.js +3 -5
  179. package/dist/reads.d.ts +39 -0
  180. package/dist/reads.d.ts.map +1 -0
  181. package/dist/reads.js +178 -0
  182. package/dist/recovery.d.ts +3 -1
  183. package/dist/recovery.d.ts.map +1 -1
  184. package/dist/recovery.js +38 -8
  185. package/dist/refresh.d.ts +2 -1
  186. package/dist/refresh.d.ts.map +1 -1
  187. package/dist/refresh.js +31 -3
  188. package/dist/refusal.d.ts +5 -0
  189. package/dist/refusal.d.ts.map +1 -0
  190. package/dist/refusal.js +55 -0
  191. package/dist/replica.d.ts +11 -16
  192. package/dist/replica.d.ts.map +1 -1
  193. package/dist/replica.js +64 -30
  194. package/dist/retried.d.ts +30 -0
  195. package/dist/retried.d.ts.map +1 -0
  196. package/dist/retried.js +72 -0
  197. package/dist/room-draft.d.ts +7 -8
  198. package/dist/room-draft.d.ts.map +1 -1
  199. package/dist/room-draft.js +113 -111
  200. package/dist/room-drafts.d.ts +24 -0
  201. package/dist/room-drafts.d.ts.map +1 -0
  202. package/dist/room-drafts.js +217 -0
  203. package/dist/rows.d.ts +16 -22
  204. package/dist/rows.d.ts.map +1 -1
  205. package/dist/rows.js +49 -186
  206. package/dist/runtime.d.ts +34 -0
  207. package/dist/runtime.d.ts.map +1 -0
  208. package/dist/runtime.js +1 -0
  209. package/dist/save.d.ts +42 -86
  210. package/dist/save.d.ts.map +1 -1
  211. package/dist/save.js +344 -174
  212. package/dist/saves.d.ts +32 -0
  213. package/dist/saves.d.ts.map +1 -0
  214. package/dist/saves.js +409 -0
  215. package/dist/search.d.ts +12 -63
  216. package/dist/search.d.ts.map +1 -1
  217. package/dist/search.js +9 -52
  218. package/dist/seed.d.ts +11 -2
  219. package/dist/seed.d.ts.map +1 -1
  220. package/dist/seed.js +71 -1
  221. package/dist/shared.d.ts +1 -6
  222. package/dist/shared.d.ts.map +1 -1
  223. package/dist/shared.js +13 -95
  224. package/dist/shown.d.ts +33 -0
  225. package/dist/shown.d.ts.map +1 -0
  226. package/dist/shown.js +309 -0
  227. package/dist/socket/admission.d.ts +7 -0
  228. package/dist/socket/admission.d.ts.map +1 -0
  229. package/dist/socket/admission.js +39 -0
  230. package/dist/socket/answers.d.ts +6 -0
  231. package/dist/socket/answers.d.ts.map +1 -0
  232. package/dist/socket/answers.js +20 -0
  233. package/dist/socket/lanes.d.ts +28 -0
  234. package/dist/socket/lanes.d.ts.map +1 -0
  235. package/dist/socket/lanes.js +103 -0
  236. package/dist/socket/reads.d.ts +10 -0
  237. package/dist/socket/reads.d.ts.map +1 -0
  238. package/dist/socket/reads.js +31 -0
  239. package/dist/socket/session.d.ts +38 -0
  240. package/dist/socket/session.d.ts.map +1 -0
  241. package/dist/socket/session.js +23 -0
  242. package/dist/socket.d.ts +67 -0
  243. package/dist/socket.d.ts.map +1 -0
  244. package/dist/socket.js +164 -0
  245. package/dist/source.d.ts +54 -0
  246. package/dist/source.d.ts.map +1 -0
  247. package/dist/source.js +82 -0
  248. package/dist/status.d.ts +0 -2
  249. package/dist/status.d.ts.map +1 -1
  250. package/dist/status.js +0 -6
  251. package/dist/store/installs.d.ts +30 -0
  252. package/dist/store/installs.d.ts.map +1 -0
  253. package/dist/store/installs.js +40 -0
  254. package/dist/store/readiness.d.ts +11 -0
  255. package/dist/store/readiness.d.ts.map +1 -0
  256. package/dist/store/readiness.js +68 -0
  257. package/dist/store/records.d.ts +217 -0
  258. package/dist/store/records.d.ts.map +1 -0
  259. package/dist/store/records.js +464 -0
  260. package/dist/store/room-held.d.ts +8 -0
  261. package/dist/store/room-held.d.ts.map +1 -0
  262. package/dist/store/room-held.js +17 -0
  263. package/dist/store/rooms-shown.d.ts +8 -0
  264. package/dist/store/rooms-shown.d.ts.map +1 -0
  265. package/dist/store/rooms-shown.js +13 -0
  266. package/dist/store/space.d.ts +11 -0
  267. package/dist/store/space.d.ts.map +1 -0
  268. package/dist/store/space.js +41 -0
  269. package/dist/store/watchers.d.ts +17 -0
  270. package/dist/store/watchers.d.ts.map +1 -0
  271. package/dist/store/watchers.js +56 -0
  272. package/dist/store/writes.d.ts +24 -0
  273. package/dist/store/writes.d.ts.map +1 -0
  274. package/dist/store/writes.js +125 -0
  275. package/dist/store.d.ts +113 -144
  276. package/dist/store.d.ts.map +1 -1
  277. package/dist/store.js +171 -364
  278. package/dist/stored.d.ts +72 -35
  279. package/dist/stored.d.ts.map +1 -1
  280. package/dist/stored.js +340 -197
  281. package/dist/surface.d.ts +89 -0
  282. package/dist/surface.d.ts.map +1 -0
  283. package/dist/surface.js +222 -0
  284. package/dist/sync.d.ts +19 -0
  285. package/dist/sync.d.ts.map +1 -0
  286. package/dist/sync.js +535 -0
  287. package/dist/tables.d.ts +124 -30
  288. package/dist/tables.d.ts.map +1 -1
  289. package/dist/tables.js +242 -62
  290. package/dist/tallies.d.ts +18 -0
  291. package/dist/tallies.d.ts.map +1 -0
  292. package/dist/tallies.js +128 -0
  293. package/dist/validation.d.ts.map +1 -1
  294. package/dist/validation.js +9 -12
  295. package/dist/windows.d.ts +1 -12
  296. package/dist/windows.d.ts.map +1 -1
  297. package/dist/windows.js +2 -75
  298. package/dist/wire.d.ts +58 -9
  299. package/dist/wire.d.ts.map +1 -1
  300. package/dist/wire.js +21 -5
  301. package/package.json +3 -2
  302. package/dist/attempt.d.ts +0 -16
  303. package/dist/attempt.d.ts.map +0 -1
  304. package/dist/attempt.js +0 -70
  305. package/dist/fence.d.ts +0 -6
  306. package/dist/fence.d.ts.map +0 -1
  307. package/dist/fence.js +0 -10
  308. package/dist/fulltext.d.ts +0 -27
  309. package/dist/fulltext.d.ts.map +0 -1
  310. package/dist/fulltext.js +0 -370
  311. package/dist/log.d.ts +0 -5
  312. package/dist/log.d.ts.map +0 -1
  313. package/dist/log.js +0 -14
  314. package/dist/words.d.ts +0 -19
  315. package/dist/words.d.ts.map +0 -1
  316. package/dist/words.js +0 -156
package/dist/fulltext.js DELETED
@@ -1,370 +0,0 @@
1
- import { parse } from '@agentshouse/mdmodel';
2
- import { selected } from './compile.js';
3
- import { markdownPath } from './rows.js';
4
- import { indexed, matchClauses, matched, matchExpression, queryTerms, snippet, } from './words.js';
5
- const TOKENIZER = "porter unicode61 remove_diacritics 2 categories 'L* N* Co M* S*' separators '$+<=>^`|~'";
6
- const CONTENTLESS = `content='', contentless_delete=1, detail=full, tokenize="${TOKENIZER}"`;
7
- const DOCUMENTS = 'replica_search';
8
- const MESSAGES = 'conversation_search';
9
- export const SEARCH_TABLES = [
10
- `CREATE VIRTUAL TABLE ${DOCUMENTS} USING fts5(path, fields, sections, preamble, ${CONTENTLESS})`,
11
- `CREATE VIRTUAL TABLE ${MESSAGES} USING fts5(text, ${CONTENTLESS})`,
12
- ];
13
- const CHUNKS = 4096;
14
- const CHUNK_CHARACTERS = 32_768;
15
- const CANDIDATES = 5_000;
16
- const LEAST_WINDOW = 32;
17
- const SNIPPET_REACH = 80;
18
- function scalars(value) {
19
- if (value === null || value === undefined)
20
- return [];
21
- if (Array.isArray(value))
22
- return value.flatMap(scalars);
23
- if (typeof value === 'object')
24
- return Object.values(value).flatMap(scalars);
25
- return [String(value)];
26
- }
27
- function partsOf(path, content) {
28
- if (!markdownPath(path))
29
- return null;
30
- const read = parse(content, path);
31
- if (!read.ok)
32
- return null;
33
- return {
34
- fields: scalars(read.document.fields).join('\n'),
35
- sections: Object.entries(read.document.sections)
36
- .map(([heading, text]) => `${heading}\n${text}`)
37
- .join('\n'),
38
- preamble: read.document.preamble,
39
- path,
40
- };
41
- }
42
- function chunked(text) {
43
- const chunks = [];
44
- let start = 0;
45
- do {
46
- let end = Math.min(text.length, start + CHUNK_CHARACTERS);
47
- if (end < text.length) {
48
- const space = text.lastIndexOf(' ', end);
49
- if (space > start + CHUNK_CHARACTERS / 2)
50
- end = space;
51
- else if (/[\ud800-\udbff]/u.test(text[end - 1]))
52
- end -= 1;
53
- }
54
- chunks.push(text.slice(start, end));
55
- start = end;
56
- } while (start < text.length && chunks.length < CHUNKS);
57
- return chunks;
58
- }
59
- function rowOf(id, chunk) {
60
- return id * CHUNKS + chunk;
61
- }
62
- export function indexDocument(connection, id, path, content) {
63
- const parts = partsOf(path, content);
64
- if (parts === null)
65
- return;
66
- chunked(parts.sections).forEach((sections, chunk) => {
67
- const head = chunk === 0;
68
- connection.run(`INSERT INTO ${DOCUMENTS} (rowid, path, fields, sections, preamble) VALUES (?, ?, ?, ?, ?)`, [
69
- rowOf(id, chunk),
70
- head ? indexed(parts.path) : null,
71
- head ? indexed(parts.fields) : null,
72
- indexed(sections),
73
- head ? indexed(parts.preamble) : null,
74
- ]);
75
- });
76
- }
77
- export function indexMessage(connection, id, text) {
78
- chunked(text).forEach((chunk, at) => {
79
- connection.run(`INSERT INTO ${MESSAGES} (rowid, text) VALUES (?, ?)`, [
80
- rowOf(id, at),
81
- indexed(chunk),
82
- ]);
83
- });
84
- }
85
- function unindexed(connection, table, ids) {
86
- for (const id of ids) {
87
- connection.run(`DELETE FROM ${table} WHERE rowid >= ? AND rowid < ?`, [
88
- rowOf(id, 0),
89
- rowOf(id + 1, 0),
90
- ]);
91
- }
92
- }
93
- export function unindexDocuments(connection, ids) {
94
- unindexed(connection, DOCUMENTS, ids);
95
- }
96
- export function unindexMessages(connection, ids) {
97
- unindexed(connection, MESSAGES, ids);
98
- }
99
- export function unindexAll(connection) {
100
- for (const table of [DOCUMENTS, MESSAGES]) {
101
- connection.run(`INSERT INTO ${table} (${table}) VALUES ('delete-all')`);
102
- }
103
- }
104
- function pair(left, right) {
105
- if (left[0] !== right[0])
106
- return left[0] < right[0] ? -1 : 1;
107
- if (left[1] !== right[1])
108
- return left[1] < right[1] ? -1 : 1;
109
- return 0;
110
- }
111
- function byRank(left, right) {
112
- return right.score - left.score || pair(left.tie, right.tie);
113
- }
114
- function beyond(hit, cursor) {
115
- if (cursor.length === 0)
116
- return true;
117
- return (hit.score < cursor[0] || (hit.score === cursor[0] && pair(hit.tie, [cursor[1], cursor[2]]) > 0));
118
- }
119
- function rankedWithin(connection, listed, sources, cursor, needed) {
120
- const { table } = listed;
121
- let window = Math.max(needed * 2, LEAST_WINDOW);
122
- for (;;) {
123
- const rows = [];
124
- const boundaries = [];
125
- for (const source of sources) {
126
- const found = connection.rows(`SELECT rowid, bm25(${table}) AS score FROM ${table} WHERE ${table} MATCH ? ${source.sql} ORDER BY score, rowid LIMIT ?`, [source.expression, ...source.bind, window]);
127
- for (const row of found)
128
- rows.push([Number(row.rowid), Number(row.score)]);
129
- if (found.length === window)
130
- boundaries.push(-Number(found.at(-1).score));
131
- }
132
- rows.sort((left, right) => left[1] - right[1] || left[0] - right[0]);
133
- const best = new Map();
134
- for (const [row, score] of rows) {
135
- const id = Math.floor(row / CHUNKS);
136
- if (!best.has(id))
137
- best.set(id, { chunk: row % CHUNKS, score: -score });
138
- }
139
- const ties = listed.ties([...best.keys()]);
140
- const kept = [...best]
141
- .flatMap(([id, held]) => {
142
- const tie = ties.get(id);
143
- return tie === undefined ? [] : [{ id, ...held, tie }];
144
- })
145
- .sort(byRank)
146
- .filter((hit) => beyond(hit, cursor))
147
- .slice(0, needed);
148
- const last = kept.at(-1);
149
- if (boundaries.length === 0)
150
- return kept;
151
- if (kept.length === needed &&
152
- last !== undefined &&
153
- boundaries.every((boundary) => boundary < last.score)) {
154
- return kept;
155
- }
156
- window *= 4;
157
- }
158
- }
159
- function reaches(connection, listed, expression, reach) {
160
- const { table, scope } = listed;
161
- const [counted] = connection.rows(`SELECT count(*) AS held FROM (SELECT rowid FROM ${table} WHERE ${table} MATCH ? AND ${scope.sql} LIMIT ?)`, [expression, ...scope.bind, reach + 1]);
162
- return Number(counted?.held ?? 0) > reach;
163
- }
164
- function candidates(connection, listed, clauses, cursor, needed) {
165
- const { table, scope } = listed;
166
- const expression = matchExpression(clauses);
167
- const within = { sql: `AND ${scope.sql}`, bind: scope.bind };
168
- let reach = CANDIDATES;
169
- for (;;) {
170
- const [edge] = connection.rows(`SELECT rowid FROM ${table} WHERE ${table} MATCH ? ${within.sql} ORDER BY rowid LIMIT 1 OFFSET ?`, [expression, ...within.bind, reach]);
171
- const floor = edge === undefined ? null : Number(edge.rowid);
172
- const sources = [
173
- floor === null
174
- ? { expression, ...within }
175
- : { expression, sql: `${within.sql} AND rowid < ?`, bind: [...within.bind, floor] },
176
- ];
177
- if (floor !== null) {
178
- const common = new Set();
179
- const selective = [];
180
- const frequent = [];
181
- for (const clause of clauses) {
182
- if (clause.kind === 'phrase')
183
- continue;
184
- if (clause.kind !== 'term' && common.has(clause.term)) {
185
- frequent.push(clause);
186
- continue;
187
- }
188
- if (reaches(connection, listed, clause.text, reach)) {
189
- if (clause.kind === 'term')
190
- common.add(clause.term);
191
- frequent.push(clause);
192
- }
193
- else
194
- selective.push(clause);
195
- }
196
- const phrase = clauses.find((clause) => clause.kind === 'phrase');
197
- if (phrase !== undefined) {
198
- const rare = !clauses
199
- .filter((clause) => clause.kind === 'term')
200
- .every((clause) => common.has(clause.term)) ||
201
- !reaches(connection, listed, phrase.text, reach);
202
- (rare ? selective : frequent).push(phrase);
203
- }
204
- if (selective.length > 0) {
205
- const chosen = `(${matchExpression(selective)})`;
206
- const tail = { sql: `${within.sql} AND rowid >= ?`, bind: [...within.bind, floor] };
207
- if (frequent.length === 0)
208
- sources.push({ ...tail, expression: chosen });
209
- else {
210
- const rest = `(${matchExpression(frequent)})`;
211
- sources.push({ ...tail, expression: `${chosen} AND ${rest}` }, { ...tail, expression: `${chosen} NOT ${rest}` });
212
- }
213
- }
214
- }
215
- const kept = rankedWithin(connection, listed, sources, cursor, needed);
216
- if (floor === null || kept.length >= needed)
217
- return kept;
218
- reach *= 4;
219
- }
220
- }
221
- function windowOf(connection, listed, clauses, cursor, limit) {
222
- if (cursor === null || listed === null || clauses === null)
223
- return { kept: [], cursor: null };
224
- const found = candidates(connection, listed, clauses, cursor, limit + 1);
225
- if (found.length <= limit)
226
- return { kept: found, cursor: null };
227
- const kept = found.slice(0, limit);
228
- const last = kept.at(-1);
229
- return { kept, cursor: last === undefined ? cursor : [last.score, ...last.tie] };
230
- }
231
- function totalOf(connection, listed, clauses) {
232
- if (listed === null || clauses === null)
233
- return 0;
234
- const { table, scope } = listed;
235
- const [counted] = connection.rows(`SELECT count(DISTINCT rowid / ${CHUNKS}) AS held FROM ${table} WHERE ${table} MATCH ? AND ${scope.sql}`, [matchExpression(clauses), ...scope.bind]);
236
- return Number(counted?.held ?? 0);
237
- }
238
- function ids(found) {
239
- return JSON.stringify(found);
240
- }
241
- function documentsListed(connection, documents) {
242
- if (documents.rooms.length === 0)
243
- return null;
244
- const filter = selected(connection, documents.plan, documents.rooms);
245
- const outside = {
246
- sql: "NOT EXISTS (SELECT 1 FROM json_each(?) r WHERE d.key = r.value ->> 0 AND (d.path = r.value ->> 1 OR (d.path >= (r.value ->> 1) || '/' AND d.path < (r.value ->> 1) || '0')))",
247
- bind: [
248
- JSON.stringify(documents.beneath.flatMap(({ key, roots }) => roots.map((root) => [key, root]))),
249
- ],
250
- };
251
- const conditions = [filter, outside];
252
- const locators = new Map(documents.rooms.map(({ key, locator }) => [key, locator]));
253
- return {
254
- table: DOCUMENTS,
255
- scope: {
256
- sql: `EXISTS (SELECT 1 FROM replica_entries d WHERE d.id = ${DOCUMENTS}.rowid / ${CHUNKS} AND d.type IS NOT NULL AND ${conditions.map(({ sql }) => `(${sql})`).join(' AND ')})`,
257
- bind: conditions.flatMap(({ bind }) => bind),
258
- },
259
- ties(found) {
260
- const tied = new Map();
261
- for (const row of connection.rows('SELECT id, key, path FROM replica_entries WHERE id IN (SELECT value FROM json_each(?))', [ids(found)])) {
262
- const locator = locators.get(Number(row.key));
263
- if (locator !== undefined)
264
- tied.set(Number(row.id), [locator, String(row.path)]);
265
- }
266
- return tied;
267
- },
268
- };
269
- }
270
- function messagesListed(connection, conversations) {
271
- if (conversations.length === 0)
272
- return null;
273
- return {
274
- table: MESSAGES,
275
- scope: {
276
- sql: `EXISTS (SELECT 1 FROM conversation_messages m WHERE m.id = ${MESSAGES}.rowid / ${CHUNKS} AND m.conversation IN (SELECT value FROM json_each(?)))`,
277
- bind: [JSON.stringify(conversations)],
278
- },
279
- ties(found) {
280
- return new Map(connection
281
- .rows('SELECT id, conversation, identity FROM conversation_messages WHERE id IN (SELECT value FROM json_each(?))', [ids(found)])
282
- .map((row) => [Number(row.id), [String(row.conversation), String(row.identity)]]));
283
- },
284
- };
285
- }
286
- function cut(candidates, terms) {
287
- for (const [part, text] of candidates) {
288
- const found = snippet(text, terms, SNIPPET_REACH);
289
- if (found !== null)
290
- return { snippet: { part, text: found.text, at: [...found.at] } };
291
- }
292
- return {};
293
- }
294
- function documentHit(connection, hit, terms) {
295
- const [row] = connection.rows('SELECT type, content FROM replica_entries WHERE id = ?', [hit.id]);
296
- if (row === undefined)
297
- return null;
298
- const [room, path] = hit.tie;
299
- const parts = typeof row.content === 'string' ? partsOf(path, row.content) : null;
300
- const whole = parts === null
301
- ? []
302
- : [
303
- ['fields', parts.fields],
304
- ['sections', parts.sections],
305
- ['preamble', parts.preamble],
306
- ['path', parts.path],
307
- ];
308
- const matches = {};
309
- for (const [part, text] of whole) {
310
- for (const term of matched(text, terms))
311
- (matches[term] ??= []).push(part);
312
- }
313
- const sections = parts === null ? [] : chunked(parts.sections);
314
- const chunk = parts === null
315
- ? []
316
- : hit.chunk === 0
317
- ? [
318
- ['fields', parts.fields],
319
- ['sections', sections[0] ?? ''],
320
- ['preamble', parts.preamble],
321
- ['path', parts.path],
322
- ]
323
- : [['sections', sections[hit.chunk] ?? '']];
324
- return {
325
- room,
326
- path,
327
- type: String(row.type),
328
- score: hit.score,
329
- matches,
330
- ...cut(chunk, terms),
331
- };
332
- }
333
- function messageHit(connection, hit, terms) {
334
- const [row] = connection.rows('SELECT text FROM conversation_messages WHERE id = ?', [hit.id]);
335
- const text = typeof row?.text === 'string' ? row.text : '';
336
- const matches = {};
337
- for (const term of matched(text, terms))
338
- matches[term] = ['text'];
339
- const [conversation, identity] = hit.tie;
340
- return {
341
- conversation,
342
- identity,
343
- score: hit.score,
344
- matches,
345
- ...cut([['text', chunked(text)[hit.chunk] ?? '']], terms),
346
- };
347
- }
348
- export function searched(connection, ask) {
349
- const clauses = matchClauses(ask.text);
350
- const terms = queryTerms(ask.text);
351
- const documents = ask.documents === null ? null : documentsListed(connection, ask.documents);
352
- const messages = messagesListed(connection, ask.conversations);
353
- const [documentsAfter, messagesAfter] = ask.after ?? [[], []];
354
- const documentWindow = windowOf(connection, documents, clauses, documentsAfter, ask.limit);
355
- const messageWindow = windowOf(connection, messages, clauses, messagesAfter, ask.limit);
356
- const more = documentWindow.cursor !== null || messageWindow.cursor !== null;
357
- return {
358
- documents: documentWindow.kept.flatMap((hit) => documentHit(connection, hit, terms) ?? []),
359
- messages: messageWindow.kept.map((hit) => messageHit(connection, hit, terms)),
360
- ...(more ? { next: JSON.stringify([documentWindow.cursor, messageWindow.cursor]) } : {}),
361
- ...(ask.total
362
- ? {
363
- total: {
364
- documents: totalOf(connection, documents, clauses),
365
- messages: totalOf(connection, messages, clauses),
366
- },
367
- }
368
- : {}),
369
- };
370
- }
package/dist/log.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export declare function createLog(): {
2
- record(event: string): void;
3
- export(): string;
4
- };
5
- //# sourceMappingURL=log.d.ts.map
package/dist/log.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS;IAGrB,MAAM,QAAQ,MAAM;IAIpB,MAAM;EAIT"}
package/dist/log.js DELETED
@@ -1,14 +0,0 @@
1
- const BOUND = 256;
2
- export function createLog() {
3
- const events = [];
4
- return {
5
- record(event) {
6
- events.push(event);
7
- if (events.length > BOUND)
8
- events.splice(0, events.length - BOUND);
9
- },
10
- export() {
11
- return events.join('\n');
12
- },
13
- };
14
- }
package/dist/words.d.ts DELETED
@@ -1,19 +0,0 @@
1
- export type Clause = {
2
- readonly text: string;
3
- readonly kind: 'term' | 'stem' | 'prefix' | 'phrase';
4
- readonly term: string;
5
- };
6
- export type Located = {
7
- readonly start: number;
8
- readonly end: number;
9
- };
10
- export declare function indexed(text: string): string;
11
- export declare function matchClauses(text: string): Clause[] | null;
12
- export declare function matchExpression(clauses: readonly Clause[]): string;
13
- export declare function queryTerms(text: string): string[];
14
- export declare function snippet(part: string, terms: readonly string[], reach: number): {
15
- readonly text: string;
16
- readonly at: readonly [number, number];
17
- } | null;
18
- export declare function matched(part: string, terms: readonly string[]): string[];
19
- //# sourceMappingURL=words.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"words.d.ts","sourceRoot":"","sources":["../src/words.ts"],"names":[],"mappings":"AA0BA,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAYvE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO5C;AAgBD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAiB1D;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAElE;AAMD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjD;AAyDD,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,EAAE,MAAM,GACZ;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAW1E;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAQxE"}
package/dist/words.js DELETED
@@ -1,156 +0,0 @@
1
- const SPACELESS = /(?:[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Thai}\p{Script=Lao}\p{Script=Khmer}\p{Script=Myanmar}\p{Script=Hangul}]\p{M}*)+/gu;
2
- const SPACELESS_TERM = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Thai}\p{Script=Lao}\p{Script=Khmer}\p{Script=Myanmar}\p{Script=Hangul}]/u;
3
- const TOKEN = /(?![\x00-\x7f])\p{S}\p{M}*|[\p{L}\p{N}\p{M}\p{Co}]+/gu;
4
- const SYMBOL = /(?![\x00-\x7f])\p{S}\p{M}*/gu;
5
- const MARKED = /([\p{Script=Latin}\p{Script=Greek}\p{Script=Cyrillic}])\p{M}+/gu;
6
- const INFLECTED = /^[\p{Script=Cyrillic}\p{Script=Greek}]+$/u;
7
- const FOLD = /\p{M}+/gu;
8
- const ASCII = /^[\x00-\x7f]$/;
9
- const PREFIXED_LETTERS = 2;
10
- const INFLECTED_LETTERS = 4;
11
- const PHRASE_TERMS = { least: 2, most: 6 };
12
- const GRAPHEMES = new Intl.Segmenter(undefined, { granularity: 'grapheme' });
13
- function bigrams(run) {
14
- const characters = Array.from(run);
15
- if (characters.length < 2)
16
- return ` ${run} `;
17
- const pairs = [];
18
- for (let index = 0; index + 1 < characters.length; index += 1) {
19
- pairs.push(characters[index] + characters[index + 1]);
20
- }
21
- return ` ${pairs.join(' ')} `;
22
- }
23
- export function indexed(text) {
24
- return text
25
- .normalize('NFKD')
26
- .replace(MARKED, '$1')
27
- .normalize('NFKC')
28
- .replace(SPACELESS, bigrams)
29
- .replace(SYMBOL, (symbol) => ` ${symbol.replace(FOLD, '')} `);
30
- }
31
- function tokens(text) {
32
- return [...text.matchAll(TOKEN)].map(([token]) => token.toLowerCase());
33
- }
34
- function quoted(token) {
35
- return `"${token.replaceAll('"', '""')}"`;
36
- }
37
- function truncated(term) {
38
- const letters = Array.from(term);
39
- if (!INFLECTED.test(term) || letters.length < INFLECTED_LETTERS)
40
- return null;
41
- return letters.slice(0, letters.length - (letters.length >= 6 ? 2 : 1)).join('');
42
- }
43
- export function matchClauses(text) {
44
- const terms = tokens(indexed(text));
45
- if (terms.length === 0)
46
- return null;
47
- const unique = [...new Set(terms)];
48
- const clauses = unique.map((term) => ({ text: quoted(term), kind: 'term', term }));
49
- for (const term of unique) {
50
- const stem = truncated(term);
51
- if (stem !== null)
52
- clauses.push({ text: `${quoted(stem)}*`, kind: 'stem', term });
53
- }
54
- const last = terms[terms.length - 1];
55
- if (!/\s$/u.test(text) && Array.from(last).length >= PREFIXED_LETTERS) {
56
- clauses.push({ text: `${quoted(last)}*`, kind: 'prefix', term: last });
57
- }
58
- if (terms.length >= PHRASE_TERMS.least && terms.length <= PHRASE_TERMS.most) {
59
- clauses.push({ text: quoted(terms.join(' ')), kind: 'phrase', term: terms.join(' ') });
60
- }
61
- return clauses;
62
- }
63
- export function matchExpression(clauses) {
64
- return clauses.map(({ text }) => text).join(' OR ');
65
- }
66
- function folded(text) {
67
- return text.normalize('NFKD').replace(FOLD, '').toLowerCase();
68
- }
69
- export function queryTerms(text) {
70
- return [...new Set(tokens(text.normalize('NFKC')).map(folded))];
71
- }
72
- function agrees(token, term) {
73
- if (SPACELESS_TERM.test(term))
74
- return token.includes(term);
75
- if (token.startsWith(term))
76
- return true;
77
- return token.length >= 3 && term.startsWith(token.slice(0, Math.max(3, token.length - 2)));
78
- }
79
- function inside(token, offset, term) {
80
- const pieces = [...GRAPHEMES.segment(token)];
81
- const owner = [];
82
- let joined = '';
83
- for (const [at, { segment }] of pieces.entries()) {
84
- const part = folded(segment);
85
- joined += part;
86
- for (let index = 0; index < part.length; index += 1)
87
- owner.push(at);
88
- }
89
- const found = joined.indexOf(term);
90
- if (found < 0)
91
- return null;
92
- const first = pieces[owner[found]];
93
- const last = pieces[owner[found + term.length - 1]];
94
- return { start: offset + first.index, end: offset + last.index + last.segment.length };
95
- }
96
- function locate(part, terms) {
97
- for (const match of part.matchAll(TOKEN)) {
98
- const token = folded(match[0]);
99
- for (const term of terms) {
100
- if (!agrees(token, term))
101
- continue;
102
- if (!SPACELESS_TERM.test(term)) {
103
- return { start: match.index, end: match.index + match[0].length };
104
- }
105
- const found = inside(match[0], match.index, term);
106
- if (found !== null)
107
- return found;
108
- }
109
- }
110
- return null;
111
- }
112
- function settled(part, index) {
113
- if (index <= 0 || index >= part.length)
114
- return true;
115
- const before = part[index - 1];
116
- const after = part[index];
117
- if (before === '\n')
118
- return true;
119
- return ASCII.test(before) && ASCII.test(after) && !(before === '\r' && after === '\n');
120
- }
121
- function edgesAround(part, low, high) {
122
- let from = Math.max(0, low);
123
- while (!settled(part, from))
124
- from -= 1;
125
- let to = Math.min(part.length, high);
126
- while (!settled(part, to))
127
- to += 1;
128
- const edges = [...GRAPHEMES.segment(part.slice(from, to))].map(({ index }) => from + index);
129
- edges.push(to);
130
- return edges;
131
- }
132
- export function snippet(part, terms, reach) {
133
- const located = locate(part, terms);
134
- if (located === null)
135
- return null;
136
- const edges = edgesAround(part, located.start - 2 * reach, located.end + 2 * reach);
137
- const last = (limit) => edges.filter((edge) => edge <= limit).at(-1) ?? edges[0];
138
- const first = (limit) => edges.find((edge) => edge >= limit) ?? edges[edges.length - 1];
139
- const from = last(located.start);
140
- const to = Math.max(first(Math.min(located.end, from + reach)), first(from + 1));
141
- const start = first(Math.max(0, from - reach));
142
- const end = last(Math.min(part.length, to + reach));
143
- return { text: part.slice(start, end), at: [from - start, to - start] };
144
- }
145
- export function matched(part, terms) {
146
- const found = new Set();
147
- for (const match of part.matchAll(TOKEN)) {
148
- const token = folded(match[0]);
149
- for (const term of terms)
150
- if (agrees(token, term))
151
- found.add(term);
152
- if (found.size === terms.length)
153
- break;
154
- }
155
- return [...found];
156
- }