sensemaking 0.18.2 → 0.18.3

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 (179) hide show
  1. package/dist/cjs/cli/status.js +32 -31
  2. package/dist/cjs/cli/status.js.map +1 -1
  3. package/dist/cjs/commands/map.js +50 -67
  4. package/dist/cjs/commands/map.js.map +1 -1
  5. package/dist/cjs/config/access.d.cts +2 -2
  6. package/dist/cjs/config/access.d.ts +2 -2
  7. package/dist/cjs/config/access.js.map +1 -1
  8. package/dist/cjs/config/index.d.cts +1 -1
  9. package/dist/cjs/config/index.d.ts +1 -1
  10. package/dist/cjs/config/index.js.map +1 -1
  11. package/dist/cjs/config/load.js +3 -2
  12. package/dist/cjs/config/load.js.map +1 -1
  13. package/dist/cjs/config/types.d.cts +2 -1
  14. package/dist/cjs/config/types.d.ts +2 -1
  15. package/dist/cjs/config/types.js.map +1 -1
  16. package/dist/cjs/config/validate.js +3 -0
  17. package/dist/cjs/config/validate.js.map +1 -1
  18. package/dist/cjs/embed/identity.js +3 -2
  19. package/dist/cjs/embed/identity.js.map +1 -1
  20. package/dist/cjs/embed/store.js +3 -3
  21. package/dist/cjs/embed/store.js.map +1 -1
  22. package/dist/cjs/index.d.cts +2 -2
  23. package/dist/cjs/index.d.ts +2 -2
  24. package/dist/cjs/index.js.map +1 -1
  25. package/dist/cjs/lib/atomic-write.d.cts +1 -0
  26. package/dist/cjs/lib/atomic-write.d.ts +1 -0
  27. package/dist/cjs/lib/atomic-write.js +26 -0
  28. package/dist/cjs/lib/atomic-write.js.map +1 -0
  29. package/dist/cjs/store/duckdb/batch.js +3 -2
  30. package/dist/cjs/store/duckdb/batch.js.map +1 -1
  31. package/dist/cjs/store/duckdb/connection.js +12 -0
  32. package/dist/cjs/store/duckdb/connection.js.map +1 -1
  33. package/dist/cjs/store/duckdb/fieldStats.d.cts +2 -0
  34. package/dist/cjs/store/duckdb/fieldStats.d.ts +2 -0
  35. package/dist/cjs/store/duckdb/fieldStats.js +219 -0
  36. package/dist/cjs/store/duckdb/fieldStats.js.map +1 -0
  37. package/dist/cjs/store/duckdb/lexical.js +3 -2
  38. package/dist/cjs/store/duckdb/lexical.js.map +1 -1
  39. package/dist/cjs/store/duckdb/native.d.cts +0 -1
  40. package/dist/cjs/store/duckdb/native.d.ts +0 -1
  41. package/dist/cjs/store/duckdb/native.js +7 -336
  42. package/dist/cjs/store/duckdb/native.js.map +1 -1
  43. package/dist/cjs/store/duckdb/sql-functions.js +1 -1
  44. package/dist/cjs/store/duckdb/sql-functions.js.map +1 -1
  45. package/dist/cjs/store/duckdb/store.js +16 -1
  46. package/dist/cjs/store/duckdb/store.js.map +1 -1
  47. package/dist/cjs/store/duckdb/vectors.js +5 -17
  48. package/dist/cjs/store/duckdb/vectors.js.map +1 -1
  49. package/dist/cjs/store/index.js +6 -0
  50. package/dist/cjs/store/index.js.map +1 -1
  51. package/dist/cjs/store/native.d.cts +7 -0
  52. package/dist/cjs/store/native.d.ts +7 -0
  53. package/dist/cjs/store/native.js +350 -0
  54. package/dist/cjs/store/native.js.map +1 -0
  55. package/dist/cjs/store/sqlite/fieldStats.d.cts +2 -0
  56. package/dist/cjs/store/sqlite/fieldStats.d.ts +2 -0
  57. package/dist/cjs/store/sqlite/fieldStats.js +201 -0
  58. package/dist/cjs/store/sqlite/fieldStats.js.map +1 -0
  59. package/dist/cjs/store/sqlite/open.js +82 -29
  60. package/dist/cjs/store/sqlite/open.js.map +1 -1
  61. package/dist/cjs/store/sqlite/store.js +32 -4
  62. package/dist/cjs/store/sqlite/store.js.map +1 -1
  63. package/dist/cjs/store/sqlite/vectors.d.cts +0 -5
  64. package/dist/cjs/store/sqlite/vectors.d.ts +0 -5
  65. package/dist/cjs/store/sqlite/vectors.js +5 -71
  66. package/dist/cjs/store/sqlite/vectors.js.map +1 -1
  67. package/dist/cjs/store/turso/connection.d.cts +3 -0
  68. package/dist/cjs/store/turso/connection.d.ts +3 -0
  69. package/dist/cjs/store/turso/connection.js +529 -0
  70. package/dist/cjs/store/turso/connection.js.map +1 -0
  71. package/dist/cjs/store/turso/fieldStats.d.cts +2 -0
  72. package/dist/cjs/store/turso/fieldStats.d.ts +2 -0
  73. package/dist/cjs/store/turso/fieldStats.js +201 -0
  74. package/dist/cjs/store/turso/fieldStats.js.map +1 -0
  75. package/dist/cjs/store/turso/native.d.cts +2 -0
  76. package/dist/cjs/store/turso/native.d.ts +2 -0
  77. package/dist/cjs/store/turso/native.js +31 -0
  78. package/dist/cjs/store/turso/native.js.map +1 -0
  79. package/dist/cjs/store/turso/open.d.cts +12 -0
  80. package/dist/cjs/store/turso/open.d.ts +12 -0
  81. package/dist/cjs/store/turso/open.js +500 -0
  82. package/dist/cjs/store/turso/open.js.map +1 -0
  83. package/dist/cjs/store/turso/reconcile.d.cts +6 -0
  84. package/dist/cjs/store/turso/reconcile.d.ts +6 -0
  85. package/dist/cjs/store/turso/reconcile.js +793 -0
  86. package/dist/cjs/store/turso/reconcile.js.map +1 -0
  87. package/dist/cjs/store/turso/store.d.cts +5 -0
  88. package/dist/cjs/store/turso/store.d.ts +5 -0
  89. package/dist/cjs/store/turso/store.js +609 -0
  90. package/dist/cjs/store/turso/store.js.map +1 -0
  91. package/dist/cjs/store/types.d.cts +9 -1
  92. package/dist/cjs/store/types.d.ts +9 -1
  93. package/dist/cjs/store/types.js +0 -7
  94. package/dist/cjs/store/types.js.map +1 -1
  95. package/dist/cjs/store/vectors.d.cts +9 -0
  96. package/dist/cjs/store/vectors.d.ts +9 -0
  97. package/dist/cjs/store/vectors.js +215 -0
  98. package/dist/cjs/store/vectors.js.map +1 -0
  99. package/dist/esm/cli/status.js +5 -7
  100. package/dist/esm/cli/status.js.map +1 -1
  101. package/dist/esm/commands/map.js +7 -19
  102. package/dist/esm/commands/map.js.map +1 -1
  103. package/dist/esm/config/access.d.ts +2 -2
  104. package/dist/esm/config/access.js.map +1 -1
  105. package/dist/esm/config/index.d.ts +1 -1
  106. package/dist/esm/config/index.js.map +1 -1
  107. package/dist/esm/config/load.js +4 -3
  108. package/dist/esm/config/load.js.map +1 -1
  109. package/dist/esm/config/types.d.ts +2 -1
  110. package/dist/esm/config/types.js.map +1 -1
  111. package/dist/esm/config/validate.js +3 -0
  112. package/dist/esm/config/validate.js.map +1 -1
  113. package/dist/esm/embed/identity.js +4 -3
  114. package/dist/esm/embed/identity.js.map +1 -1
  115. package/dist/esm/embed/store.js +3 -3
  116. package/dist/esm/embed/store.js.map +1 -1
  117. package/dist/esm/index.d.ts +2 -2
  118. package/dist/esm/index.js.map +1 -1
  119. package/dist/esm/lib/atomic-write.d.ts +1 -0
  120. package/dist/esm/lib/atomic-write.js +17 -0
  121. package/dist/esm/lib/atomic-write.js.map +1 -0
  122. package/dist/esm/store/duckdb/batch.js +3 -2
  123. package/dist/esm/store/duckdb/batch.js.map +1 -1
  124. package/dist/esm/store/duckdb/connection.js +12 -0
  125. package/dist/esm/store/duckdb/connection.js.map +1 -1
  126. package/dist/esm/store/duckdb/fieldStats.d.ts +2 -0
  127. package/dist/esm/store/duckdb/fieldStats.js +39 -0
  128. package/dist/esm/store/duckdb/fieldStats.js.map +1 -0
  129. package/dist/esm/store/duckdb/lexical.js +3 -2
  130. package/dist/esm/store/duckdb/lexical.js.map +1 -1
  131. package/dist/esm/store/duckdb/native.d.ts +0 -1
  132. package/dist/esm/store/duckdb/native.js +7 -84
  133. package/dist/esm/store/duckdb/native.js.map +1 -1
  134. package/dist/esm/store/duckdb/sql-functions.js +1 -1
  135. package/dist/esm/store/duckdb/sql-functions.js.map +1 -1
  136. package/dist/esm/store/duckdb/store.js +8 -5
  137. package/dist/esm/store/duckdb/store.js.map +1 -1
  138. package/dist/esm/store/duckdb/vectors.js +2 -12
  139. package/dist/esm/store/duckdb/vectors.js.map +1 -1
  140. package/dist/esm/store/index.js +6 -0
  141. package/dist/esm/store/index.js.map +1 -1
  142. package/dist/esm/store/native.d.ts +7 -0
  143. package/dist/esm/store/native.js +83 -0
  144. package/dist/esm/store/native.js.map +1 -0
  145. package/dist/esm/store/sqlite/fieldStats.d.ts +2 -0
  146. package/dist/esm/store/sqlite/fieldStats.js +25 -0
  147. package/dist/esm/store/sqlite/fieldStats.js.map +1 -0
  148. package/dist/esm/store/sqlite/open.js +21 -8
  149. package/dist/esm/store/sqlite/open.js.map +1 -1
  150. package/dist/esm/store/sqlite/store.js +14 -1
  151. package/dist/esm/store/sqlite/store.js.map +1 -1
  152. package/dist/esm/store/sqlite/vectors.d.ts +0 -5
  153. package/dist/esm/store/sqlite/vectors.js +2 -22
  154. package/dist/esm/store/sqlite/vectors.js.map +1 -1
  155. package/dist/esm/store/turso/connection.d.ts +3 -0
  156. package/dist/esm/store/turso/connection.js +52 -0
  157. package/dist/esm/store/turso/connection.js.map +1 -0
  158. package/dist/esm/store/turso/fieldStats.d.ts +2 -0
  159. package/dist/esm/store/turso/fieldStats.js +24 -0
  160. package/dist/esm/store/turso/fieldStats.js.map +1 -0
  161. package/dist/esm/store/turso/native.d.ts +2 -0
  162. package/dist/esm/store/turso/native.js +19 -0
  163. package/dist/esm/store/turso/native.js.map +1 -0
  164. package/dist/esm/store/turso/open.d.ts +12 -0
  165. package/dist/esm/store/turso/open.js +113 -0
  166. package/dist/esm/store/turso/open.js.map +1 -0
  167. package/dist/esm/store/turso/reconcile.d.ts +6 -0
  168. package/dist/esm/store/turso/reconcile.js +158 -0
  169. package/dist/esm/store/turso/reconcile.js.map +1 -0
  170. package/dist/esm/store/turso/store.d.ts +5 -0
  171. package/dist/esm/store/turso/store.js +93 -0
  172. package/dist/esm/store/turso/store.js.map +1 -0
  173. package/dist/esm/store/types.d.ts +9 -1
  174. package/dist/esm/store/types.js +0 -7
  175. package/dist/esm/store/types.js.map +1 -1
  176. package/dist/esm/store/vectors.d.ts +9 -0
  177. package/dist/esm/store/vectors.js +26 -0
  178. package/dist/esm/store/vectors.js.map +1 -0
  179. package/package.json +2 -1
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "fieldStats", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return fieldStats;
9
+ }
10
+ });
11
+ var _sharedts = require("../shared.js");
12
+ function _array_like_to_array(arr, len) {
13
+ if (len == null || len > arr.length) len = arr.length;
14
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
15
+ return arr2;
16
+ }
17
+ function _array_without_holes(arr) {
18
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
19
+ }
20
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
21
+ try {
22
+ var info = gen[key](arg);
23
+ var value = info.value;
24
+ } catch (error) {
25
+ reject(error);
26
+ return;
27
+ }
28
+ if (info.done) resolve(value);
29
+ else Promise.resolve(value).then(_next, _throw);
30
+ }
31
+ function _async_to_generator(fn) {
32
+ return function() {
33
+ var self = this, args = arguments;
34
+ return new Promise(function(resolve, reject) {
35
+ var gen = fn.apply(self, args);
36
+ function _next(value) {
37
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
38
+ }
39
+ function _throw(err) {
40
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
41
+ }
42
+ _next(undefined);
43
+ });
44
+ };
45
+ }
46
+ function _iterable_to_array(iter) {
47
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
48
+ return Array.from(iter);
49
+ }
50
+ }
51
+ function _non_iterable_spread() {
52
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
53
+ }
54
+ function _to_consumable_array(arr) {
55
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
56
+ }
57
+ function _ts_generator(thisArg, body) {
58
+ var f, y, t, _ = {
59
+ label: 0,
60
+ sent: function() {
61
+ if (t[0] & 1) throw t[1];
62
+ return t[1];
63
+ },
64
+ trys: [],
65
+ ops: []
66
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
67
+ return d(g, "next", {
68
+ value: verb(0)
69
+ }), d(g, "throw", {
70
+ value: verb(1)
71
+ }), d(g, "return", {
72
+ value: verb(2)
73
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
74
+ value: function() {
75
+ return this;
76
+ }
77
+ }), g;
78
+ function verb(n) {
79
+ return function(v) {
80
+ return step([
81
+ n,
82
+ v
83
+ ]);
84
+ };
85
+ }
86
+ function step(op) {
87
+ if (f) throw new TypeError("Generator is already executing.");
88
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
89
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
90
+ if (y = 0, t) op = [
91
+ op[0] & 2,
92
+ t.value
93
+ ];
94
+ switch(op[0]){
95
+ case 0:
96
+ case 1:
97
+ t = op;
98
+ break;
99
+ case 4:
100
+ _.label++;
101
+ return {
102
+ value: op[1],
103
+ done: false
104
+ };
105
+ case 5:
106
+ _.label++;
107
+ y = op[1];
108
+ op = [
109
+ 0
110
+ ];
111
+ continue;
112
+ case 7:
113
+ op = _.ops.pop();
114
+ _.trys.pop();
115
+ continue;
116
+ default:
117
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
118
+ _ = 0;
119
+ continue;
120
+ }
121
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
122
+ _.label = op[1];
123
+ break;
124
+ }
125
+ if (op[0] === 6 && _.label < t[1]) {
126
+ _.label = t[1];
127
+ t = op;
128
+ break;
129
+ }
130
+ if (t && _.label < t[2]) {
131
+ _.label = t[2];
132
+ _.ops.push(op);
133
+ break;
134
+ }
135
+ if (t[2]) _.ops.pop();
136
+ _.trys.pop();
137
+ continue;
138
+ }
139
+ op = body.call(thisArg, _);
140
+ } catch (e) {
141
+ op = [
142
+ 6,
143
+ e
144
+ ];
145
+ y = 0;
146
+ } finally{
147
+ f = t = 0;
148
+ }
149
+ if (op[0] & 5) throw op[1];
150
+ return {
151
+ value: op[0] ? op[1] : void 0,
152
+ done: true
153
+ };
154
+ }
155
+ }
156
+ function _unsupported_iterable_to_array(o, minLen) {
157
+ if (!o) return;
158
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
159
+ var n = Object.prototype.toString.call(o).slice(8, -1);
160
+ if (n === "Object" && o.constructor) n = o.constructor.name;
161
+ if (n === "Map" || n === "Set") return Array.from(n);
162
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
163
+ }
164
+ function fieldStats(conn, columns, scopeWhere) {
165
+ return _async_to_generator(function() {
166
+ var exprs, stmt, row;
167
+ return _ts_generator(this, function(_state) {
168
+ switch(_state.label){
169
+ case 0:
170
+ exprs = columns.map(function(name, i) {
171
+ var quoted = (0, _sharedts.quoteIdent)(name);
172
+ return "COUNT(".concat(quoted, ") AS n").concat(i, ", GROUP_CONCAT(DISTINCT typeof(").concat(quoted, ")) FILTER (WHERE ").concat(quoted, " IS NOT NULL) AS t").concat(i);
173
+ });
174
+ return [
175
+ 4,
176
+ conn.prepare("SELECT ".concat(exprs.join(', '), " FROM frontmatter ").concat(scopeWhere))
177
+ ];
178
+ case 1:
179
+ stmt = _state.sent();
180
+ return [
181
+ 4,
182
+ stmt.get()
183
+ ];
184
+ case 2:
185
+ row = _state.sent();
186
+ return [
187
+ 2,
188
+ columns.map(function(name, i) {
189
+ var _row_, _row_1;
190
+ return {
191
+ field: name,
192
+ coverage: Number((_row_ = row["n".concat(i)]) !== null && _row_ !== void 0 ? _row_ : 0),
193
+ type: _to_consumable_array(new Set(((_row_1 = row["t".concat(i)]) !== null && _row_1 !== void 0 ? _row_1 : '').split(',').filter(Boolean))).sort().join(',')
194
+ };
195
+ })
196
+ ];
197
+ }
198
+ });
199
+ })();
200
+ }
201
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/fieldStats.ts"],"sourcesContent":["import { quoteIdent } from '../shared.ts';\nimport type { Connection, FieldStat } from '../types.ts';\n\n// One aggregate query, one result row: COUNT + GROUP_CONCAT(DISTINCT typeof()) per column, so\n// the query stays O(columns) rather than O(rows x columns). typeof()'s output already is the\n// shared vocabulary (integer/real/text -- mapValue() never binds a boolean or blob), so no\n// mapping step is needed here (contrast duckdb/fieldStats.ts). GROUP_CONCAT(DISTINCT ...)'s\n// order is not guaranteed sorted (spike-verified: 3+ distinct types come back in insertion\n// order), so the type set is sorted in JS.\nexport async function fieldStats(conn: Connection, columns: string[], scopeWhere: string): Promise<FieldStat[]> {\n const exprs = columns.map((name, i) => {\n const quoted = quoteIdent(name);\n return `COUNT(${quoted}) AS n${i}, GROUP_CONCAT(DISTINCT typeof(${quoted})) FILTER (WHERE ${quoted} IS NOT NULL) AS t${i}`;\n });\n const stmt = await conn.prepare(`SELECT ${exprs.join(', ')} FROM frontmatter ${scopeWhere}`);\n const row = (await stmt.get()) as Record<string, number | string | null>;\n return columns.map((name, i) => ({\n field: name,\n coverage: Number(row[`n${i}`] ?? 0),\n type: [...new Set(((row[`t${i}`] as string) ?? '').split(',').filter(Boolean))].sort().join(','),\n }));\n}\n"],"names":["fieldStats","conn","columns","scopeWhere","exprs","stmt","row","map","name","i","quoted","quoteIdent","prepare","join","get","field","coverage","Number","type","Set","split","filter","Boolean","sort"],"mappings":";;;;+BASsBA;;;eAAAA;;;wBATK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASpB,SAAeA,WAAWC,IAAgB,EAAEC,OAAiB,EAAEC,UAAkB;;YAChFC,OAIAC,MACAC;;;;oBALAF,QAAQF,QAAQK,GAAG,CAAC,SAACC,MAAMC;wBAC/B,IAAMC,SAASC,IAAAA,oBAAU,EAACH;wBAC1B,OAAO,AAAC,SAAuBC,OAAfC,QAAO,UAA2CA,OAAnCD,GAAE,mCAA2DC,OAA1BA,QAAO,qBAA8CD,OAA3BC,QAAO,sBAAsB,OAAFD;oBACzH;oBACa;;wBAAMR,KAAKW,OAAO,CAAC,AAAC,UAA8CT,OAArCC,MAAMS,IAAI,CAAC,OAAM,sBAA+B,OAAXV;;;oBAAzEE,OAAO;oBACA;;wBAAMA,KAAKS,GAAG;;;oBAArBR,MAAO;oBACb;;wBAAOJ,QAAQK,GAAG,CAAC,SAACC,MAAMC;gCAEPH,OACGA;mCAHW;gCAC/BS,OAAOP;gCACPQ,UAAUC,QAAOX,QAAAA,GAAG,CAAC,AAAC,IAAK,OAAFG,GAAI,cAAZH,mBAAAA,QAAgB;gCACjCY,MAAM,AAAC,qBAAG,IAAIC,IAAI,EAAEb,SAAAA,GAAG,CAAC,AAAC,IAAK,OAAFG,GAAI,cAAZH,oBAAAA,SAA2B,IAAIc,KAAK,CAAC,KAAKC,MAAM,CAACC,WAAWC,IAAI,GAAGV,IAAI,CAAC;4BAC9F;;;;;IACF"}
@@ -34,6 +34,7 @@ var _indexts = require("../../config/index.js");
34
34
  var _errorsts = require("../../errors.js");
35
35
  var _indexts1 = require("../../features/index.js");
36
36
  var _sharedts = require("../shared.js");
37
+ var _transactionts = require("../transaction.js");
37
38
  var _connectionts = require("./connection.js");
38
39
  var _reconcilets = require("./reconcile.js");
39
40
  var _sqlfunctionsts = require("./sql-functions.js");
@@ -223,6 +224,29 @@ function storedTokenize(db) {
223
224
  var m = row.sql.match(/tokenize = '((?:[^']|'')*)'/);
224
225
  return m ? m[1] : null;
225
226
  }
227
+ // The three `_seg` sidecars are appended after path, never inserted: bm25(content, ...) and
228
+ // snippet(content, 2, ...) are documented against the first three columns and keep working
229
+ // (FTS5 defaults the weights it was not given). Each carries its field's exploded unspaced
230
+ // runs for text that needs it, and an empty string for text that does not. Shared by
231
+ // ensureSchema and the tokenize-only rebuild in connect(), so both create identical DDL.
232
+ function createContentTable(conn, tokenize) {
233
+ return _async_to_generator(function() {
234
+ return _ts_generator(this, function(_state) {
235
+ switch(_state.label){
236
+ case 0:
237
+ return [
238
+ 4,
239
+ conn.exec("CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, title_seg, summary_seg, text_seg, tokenize = '".concat(tokenize, "')"))
240
+ ];
241
+ case 1:
242
+ _state.sent();
243
+ return [
244
+ 2
245
+ ];
246
+ }
247
+ });
248
+ })();
249
+ }
226
250
  // Content is a separate table (not a column on frontmatter) so `SELECT * FROM frontmatter`
227
251
  // can't dump file text into context. Features add their own tables after the core ones.
228
252
  function ensureSchema(conn, cfg, tokenize) {
@@ -239,13 +263,9 @@ function ensureSchema(conn, cfg, tokenize) {
239
263
  _state.sent();
240
264
  // IF NOT EXISTS is safe against a tokenizer change: open() compares the table's own DDL
241
265
  // against the resolved tokenizer before this runs, so a stale table is already gone by now.
242
- // The three `_seg` sidecars are appended after path, never inserted: bm25(content, ...) and
243
- // snippet(content, 2, ...) are documented against the first three columns and keep working
244
- // (FTS5 defaults the weights it was not given). Each carries its field's exploded unspaced
245
- // runs for text that needs it, and an empty string for text that does not.
246
266
  return [
247
267
  4,
248
- conn.exec("CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, title_seg, summary_seg, text_seg, tokenize = '".concat(tokenize, "')"))
268
+ createContentTable(conn, tokenize)
249
269
  ];
250
270
  case 2:
251
271
  _state.sent();
@@ -381,9 +401,9 @@ function connect(cfg) {
381
401
  case 1:
382
402
  _state.trys.push([
383
403
  1,
384
- 14,
404
+ 15,
385
405
  ,
386
- 15
406
+ 16
387
407
  ]);
388
408
  db.exec('PRAGMA journal_mode = WAL');
389
409
  // Covers a concurrent watcher's bulk reconcile (~5s for 500 files at 26k notes). A query
@@ -411,7 +431,7 @@ function connect(cfg) {
411
431
  tokenizeOnlyRebuild = false;
412
432
  if (!(version !== null && version !== SCHEMA_VERSION || features !== null && features !== wantFeatures)) return [
413
433
  3,
414
- 7
434
+ 8
415
435
  ];
416
436
  // Indexing derives from presets, so a config edit rebuilding the cache must say so and
417
437
  // name what changed -- silent rebuilds make derived indexing look like a hang or a bug.
@@ -428,19 +448,52 @@ function connect(cfg) {
428
448
  changedKeys = (0, _reconcilets.changedSignatureKeys)(features !== null && features !== void 0 ? features : '', wantFeatures);
429
449
  if (!(changedKeys.size === 1 && changedKeys.has('tokenize'))) return [
430
450
  3,
431
- 4
451
+ 5
432
452
  ];
433
453
  console.error('sense: config change (content tokenizer) rebuilds the text index; vectors, links, and sections are kept');
434
- db.exec('DROP TABLE content');
454
+ // Drop and recreate as one transaction: a crash before COMMIT rolls back to the table
455
+ // that was there before (old tokenizer, still queryable), never to no table at all.
456
+ // IF EXISTS also makes a retry after such a crash a no-op instead of a raw SQLite error --
457
+ // meta.features is only updated once rebuildContentTable (below) finishes, so a retry
458
+ // re-enters this branch and repopulates from scratch either way.
459
+ return [
460
+ 4,
461
+ (0, _transactionts.withTransaction)(conn, function() {
462
+ return _async_to_generator(function() {
463
+ return _ts_generator(this, function(_state) {
464
+ switch(_state.label){
465
+ case 0:
466
+ return [
467
+ 4,
468
+ conn.exec('DROP TABLE IF EXISTS content')
469
+ ];
470
+ case 1:
471
+ _state.sent();
472
+ return [
473
+ 4,
474
+ createContentTable(conn, tokenize)
475
+ ];
476
+ case 2:
477
+ _state.sent();
478
+ return [
479
+ 2
480
+ ];
481
+ }
482
+ });
483
+ })();
484
+ })
485
+ ];
486
+ case 4:
487
+ _state.sent();
435
488
  tokenizeOnlyRebuild = true;
436
489
  return [
437
490
  3,
438
- 7
491
+ 8
439
492
  ];
440
- case 4:
493
+ case 5:
441
494
  if (!(changedKeys.size === 1 && changedKeys.has('embed') && (0, _reconcilets.embedIdentityAdopted)(features !== null && features !== void 0 ? features : '', wantFeatures))) return [
442
495
  3,
443
- 6
496
+ 7
444
497
  ];
445
498
  // First sight of a resolved weight identity: the model itself hasn't changed, so
446
499
  // adopt it into meta with no rebuild and no re-embed, mirroring the tokenize precedent.
@@ -449,13 +502,13 @@ function connect(cfg) {
449
502
  4,
450
503
  (0, _sharedts.setMeta)(conn, 'features', wantFeatures)
451
504
  ];
452
- case 5:
505
+ case 6:
453
506
  _state.sent();
454
507
  return [
455
508
  3,
456
- 7
509
+ 8
457
510
  ];
458
- case 6:
511
+ case 7:
459
512
  changed = (0, _reconcilets.signatureDiff)(features !== null && features !== void 0 ? features : '', wantFeatures);
460
513
  console.error("sense: config change (".concat(changed, ") rebuilds the index"));
461
514
  closed = true;
@@ -465,11 +518,11 @@ function connect(cfg) {
465
518
  2,
466
519
  connect(cfg)
467
520
  ];
468
- case 7:
521
+ case 8:
469
522
  // Meta can lie after a crash between table creation and the signature write; the table's
470
523
  // own DDL cannot. A mismatch here rebuilds no matter what meta says. A tokenize-only rebuild
471
- // just dropped content above, so storedTokenize sees no table and this guard is skipped
472
- // naturally rather than needing its own case.
524
+ // already recreated content with this tokenize above, so stored already matches and this
525
+ // guard is skipped naturally rather than needing its own case.
473
526
  stored = storedTokenize(db);
474
527
  if (stored !== null && stored !== tokenize) {
475
528
  console.error('sense: cache was built with a different content tokenizer; rebuilding the index');
@@ -485,32 +538,32 @@ function connect(cfg) {
485
538
  4,
486
539
  ensureSchema(conn, cfg, tokenize)
487
540
  ];
488
- case 8:
541
+ case 9:
489
542
  _state.sent();
490
543
  rebuildWarnings = [];
491
544
  if (!tokenizeOnlyRebuild) return [
492
545
  3,
493
- 11
546
+ 12
494
547
  ];
495
548
  return [
496
549
  4,
497
550
  (0, _reconcilets.rebuildContentTable)(conn, cfg, cfg.baseDir)
498
551
  ];
499
- case 9:
552
+ case 10:
500
553
  rebuildWarnings = _state.sent();
501
554
  return [
502
555
  4,
503
556
  (0, _sharedts.setMeta)(conn, 'features', wantFeatures)
504
557
  ];
505
- case 10:
506
- _state.sent();
507
- _state.label = 11;
508
558
  case 11:
559
+ _state.sent();
560
+ _state.label = 12;
561
+ case 12:
509
562
  return [
510
563
  4,
511
564
  (0, _sharedts.getMeta)(conn, 'reconcile_max_ms')
512
565
  ];
513
- case 12:
566
+ case 13:
514
567
  recordedMaxMs = Number.apply(void 0, [
515
568
  (_ref = _state.sent()) !== null && _ref !== void 0 ? _ref : '0'
516
569
  ]);
@@ -519,7 +572,7 @@ function connect(cfg) {
519
572
  4,
520
573
  (0, _reconcilets.reconcile)(conn, cfg, cfg.baseDir)
521
574
  ];
522
- case 13:
575
+ case 14:
523
576
  _ref1 = _state.sent(), parsed = _ref1.parsed, warnings = _ref1.warnings;
524
577
  return [
525
578
  2,
@@ -532,11 +585,11 @@ function connect(cfg) {
532
585
  warnings: _to_consumable_array(rebuildWarnings).concat(_to_consumable_array(warnings))
533
586
  }
534
587
  ];
535
- case 14:
588
+ case 15:
536
589
  err = _state.sent();
537
590
  if (!closed) db.close();
538
591
  throw err;
539
- case 15:
592
+ case 16:
540
593
  return [
541
594
  2
542
595
  ];
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/open.ts"],"sourcesContent":["// The Node floor (>=22.20) is explained here and nowhere else: 22.20 is the first release with\n// both FTS5 and row-returning INSERT ... RETURNING. Raise it only for a load-bearing capability.\nimport { mkdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\nimport type { Config, ResolvedConfig } from '../../config/index.ts';\nimport { contentTokenize, featureSignature, STATE_DIR } from '../../config/index.ts';\nimport { SenseError } from '../../errors.ts';\nimport { activeFeatures, FEATURES } from '../../features/index.ts';\nimport { getMeta, setMeta } from '../shared.ts';\nimport type { Connection, Store } from '../types.ts';\nimport { createConnection } from './connection.ts';\nimport { changedSignatureKeys, embedIdentityAdopted, rebuildContentTable, reconcile, signatureDiff } from './reconcile.ts';\nimport { registerFunctions } from './sql-functions.ts';\nimport { createStore } from './store.ts';\n\nexport const DB_FILENAME = 'cache.db';\n// Cache shape version, independent of the config's own `version`. Bumping it rebuilds\n// existing trees on first query.\nexport const SCHEMA_VERSION = '18';\n\ninterface ConnectResult {\n db: DatabaseSync;\n conn: Connection;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n}\n\nexport interface OpenResult {\n store: Store;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n}\n\n// Stemming is English-only, but the segmentation underneath it is what decides coverage:\n// unicode61 splits on spaces, so a language written without them (Chinese, Japanese, Thai)\n// indexes a whole run as one token and word search finds nothing. `content.tokenize` is how\n// such a tree picks trigram instead.\nconst DEFAULT_TOKENIZE = 'porter unicode61';\n\n// FTS5 takes its tokenizer as a string literal inside DDL, where nothing can bind, so a\n// configured value has to be concatenated. Probing a throwaway table is what makes that safe\n// and is also the whole validation: anything the linked SQLite accepts passes, anything else\n// fails here with SQLite's own message rather than against the real table. It means no table\n// of which version added which tokenizer has to be maintained.\nfunction resolveTokenize(db: DatabaseSync, cfg: Config): string {\n const configured = contentTokenize(cfg);\n if (configured === undefined) return DEFAULT_TOKENIZE;\n const literal = configured.replace(/'/g, \"''\");\n try {\n db.exec('DROP TABLE IF EXISTS temp.sense_tokenize_probe');\n db.exec(`CREATE VIRTUAL TABLE temp.sense_tokenize_probe USING fts5(x, tokenize = '${literal}')`);\n db.exec('DROP TABLE IF EXISTS temp.sense_tokenize_probe');\n } catch (err) {\n throw new SenseError('CONFIG_INVALID', `content.tokenize \"${configured}\" is not a tokenizer this SQLite accepts (${(err as Error).message}); the built-in choices are unicode61, ascii, porter, and trigram, each with their own options`);\n }\n return literal;\n}\n\n// The tokenizer the content table was actually built with, from its own DDL -- the one\n// record that cannot desynchronize from the table. NULL when the table does not exist yet.\nfunction storedTokenize(db: DatabaseSync): string | null {\n const row = db.prepare(`SELECT sql FROM sqlite_master WHERE name = 'content'`).get() as { sql: string } | undefined;\n if (!row) return null;\n const m = row.sql.match(/tokenize = '((?:[^']|'')*)'/);\n return m ? m[1] : null;\n}\n\n// Content is a separate table (not a column on frontmatter) so `SELECT * FROM frontmatter`\n// can't dump file text into context. Features add their own tables after the core ones.\nasync function ensureSchema(conn: Connection, cfg: Config, tokenize: string): Promise<void> {\n await conn.exec(`CREATE TABLE IF NOT EXISTS frontmatter (\"path\" TEXT PRIMARY KEY, \"_mtime\" REAL, \"_ctime\" REAL, \"_size\" INTEGER, \"_parse_error\" TEXT)`);\n // IF NOT EXISTS is safe against a tokenizer change: open() compares the table's own DDL\n // against the resolved tokenizer before this runs, so a stale table is already gone by now.\n // The three `_seg` sidecars are appended after path, never inserted: bm25(content, ...) and\n // snippet(content, 2, ...) are documented against the first three columns and keep working\n // (FTS5 defaults the weights it was not given). Each carries its field's exploded unspaced\n // runs for text that needs it, and an empty string for text that does not.\n await conn.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, title_seg, summary_seg, text_seg, tokenize = '${tokenize}')`);\n // Coverage, not ownership: a path can appear under several presets. path leads the PK so the\n // per-doc delete is an index hit -- keyed the other way, cold builds went quadratic.\n await conn.exec(`CREATE TABLE IF NOT EXISTS preset_files (\"path\" TEXT, preset TEXT, PRIMARY KEY (\"path\", preset))`);\n await conn.exec('CREATE INDEX IF NOT EXISTS preset_files_preset ON preset_files(preset)');\n for (const feature of activeFeatures(cfg)) await feature.schema(conn);\n if ((await getMeta(conn, 'schema_version')) === null) await setMeta(conn, 'schema_version', SCHEMA_VERSION);\n if ((await getMeta(conn, 'features')) === null) await setMeta(conn, 'features', featureSignature(cfg, FEATURES));\n}\n\nasync function connect(cfg: ResolvedConfig): Promise<ConnectResult> {\n const stateDir = join(cfg.baseDir, STATE_DIR);\n mkdirSync(stateDir, { recursive: true });\n const dbPath = join(stateDir, DB_FILENAME);\n\n const db = new DatabaseSync(dbPath);\n // A throw below (tokenizer probe, schema, reconcile's COLUMN_LIMIT) must release this handle,\n // or on Windows the leaked WAL db is undeletable and scratch cleanup fails with EPERM/EBUSY.\n // closed marks the rebuild branches that close-and-recurse, so the catch never double-closes.\n let closed = false;\n try {\n db.exec('PRAGMA journal_mode = WAL');\n // Covers a concurrent watcher's bulk reconcile (~5s for 500 files at 26k notes). A query\n // that outwaits it still fails loudly.\n db.exec('PRAGMA busy_timeout = 30000');\n registerFunctions(db, contentTokenize(cfg) === undefined);\n const conn = createConnection(db);\n\n db.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');\n\n // Before the rebuild branch below, never after: that branch deletes the cache, so a typo'd\n // tokenizer validated later would cost a full re-index (and re-embed) to reach its own error.\n const tokenize = resolveTokenize(db, cfg);\n\n // Schema-version or feature-set mismatch: reconcile only reparses changed files, so an\n // old cache can't be patched incrementally -- rebuild instead (cheap: nothing expensive lives here).\n const version = await getMeta(conn, 'schema_version');\n const features = await getMeta(conn, 'features');\n const wantFeatures = featureSignature(cfg, FEATURES);\n let tokenizeOnlyRebuild = false;\n if ((version !== null && version !== SCHEMA_VERSION) || (features !== null && features !== wantFeatures)) {\n // Indexing derives from presets, so a config edit rebuilding the cache must say so and\n // name what changed -- silent rebuilds make derived indexing look like a hang or a bug.\n if (version !== null && version !== SCHEMA_VERSION) {\n console.error('sense: cache format changed (new sensemaking version); rebuilding the index');\n closed = true;\n db.close();\n clearCache(cfg);\n return connect(cfg);\n }\n const changedKeys = changedSignatureKeys(features ?? '', wantFeatures);\n // Only the tokenizer moved: frontmatter, links, sections, and embeddings are file-derived\n // and tokenizer-independent, so they don't need re-deriving. Everything else -- a preset\n // edit, an embed model change -- still takes the full clear/reopen below.\n if (changedKeys.size === 1 && changedKeys.has('tokenize')) {\n console.error('sense: config change (content tokenizer) rebuilds the text index; vectors, links, and sections are kept');\n db.exec('DROP TABLE content');\n tokenizeOnlyRebuild = true;\n } else if (changedKeys.size === 1 && changedKeys.has('embed') && embedIdentityAdopted(features ?? '', wantFeatures)) {\n // First sight of a resolved weight identity: the model itself hasn't changed, so\n // adopt it into meta with no rebuild and no re-embed, mirroring the tokenize precedent.\n console.error(\"sense: recorded the embedding model's resolved identity; vectors are unaffected\");\n await setMeta(conn, 'features', wantFeatures);\n } else {\n const changed = signatureDiff(features ?? '', wantFeatures);\n console.error(`sense: config change (${changed}) rebuilds the index`);\n closed = true;\n db.close();\n clearCache(cfg);\n return connect(cfg);\n }\n }\n\n // Meta can lie after a crash between table creation and the signature write; the table's\n // own DDL cannot. A mismatch here rebuilds no matter what meta says. A tokenize-only rebuild\n // just dropped content above, so storedTokenize sees no table and this guard is skipped\n // naturally rather than needing its own case.\n const stored = storedTokenize(db);\n if (stored !== null && stored !== tokenize) {\n console.error('sense: cache was built with a different content tokenizer; rebuilding the index');\n closed = true;\n db.close();\n clearCache(cfg);\n return connect(cfg);\n }\n\n await ensureSchema(conn, cfg, tokenize);\n\n let rebuildWarnings: string[] = [];\n if (tokenizeOnlyRebuild) {\n rebuildWarnings = await rebuildContentTable(conn, cfg, cfg.baseDir);\n await setMeta(conn, 'features', wantFeatures);\n }\n\n // 3x the largest reconcile this cache has recorded, floored at 30s and capped at 10min.\n // Installed before reconcile() -- that call is the one that races a watcher's transaction.\n const recordedMaxMs = Number((await getMeta(conn, 'reconcile_max_ms')) ?? '0');\n db.exec(`PRAGMA busy_timeout = ${Math.min(Math.max(30000, 3 * recordedMaxMs), 600_000)}`);\n\n const { parsed, warnings } = await reconcile(conn, cfg, cfg.baseDir);\n\n return { db, conn, cfg, dbPath, parsed, warnings: [...rebuildWarnings, ...warnings] };\n } catch (err) {\n if (!closed) db.close();\n throw err;\n }\n}\n\n// The sqlite store's open: connects synchronously (see connect() above), then wraps the\n// resulting connection in the async Store interface.\nexport async function openSqlite(cfg: ResolvedConfig): Promise<OpenResult> {\n const { db, conn, cfg: resolvedCfg, dbPath, parsed, warnings } = await connect(cfg);\n return { store: createStore(db, conn, resolvedCfg, resolvedCfg.baseDir), cfg: resolvedCfg, dbPath, parsed, warnings };\n}\n\nexport async function docCount(store: Store): Promise<number> {\n const stmt = await store.prepare('SELECT COUNT(*) AS n FROM frontmatter');\n return ((await stmt.get()) as { n: number }).n;\n}\n\n// Deletes the cache directory, and only that. The rebuild is not this function's job: the next\n// open() reconciles, which is what running any command already does, so a verb that bundled the\n// two described the half that was not its own. Manual reset for a doubted cache; the schema and\n// config-signature mismatches below reset themselves.\nexport function clearCache(cfg: ResolvedConfig): void {\n rmSync(join(cfg.baseDir, STATE_DIR), { recursive: true, force: true });\n}\n"],"names":["DB_FILENAME","SCHEMA_VERSION","clearCache","docCount","openSqlite","DEFAULT_TOKENIZE","resolveTokenize","db","cfg","configured","contentTokenize","undefined","literal","replace","exec","err","SenseError","message","storedTokenize","row","prepare","get","m","sql","match","ensureSchema","conn","tokenize","feature","activeFeatures","schema","getMeta","setMeta","featureSignature","FEATURES","connect","stateDir","dbPath","closed","version","features","wantFeatures","tokenizeOnlyRebuild","changedKeys","changed","stored","rebuildWarnings","recordedMaxMs","parsed","warnings","join","baseDir","STATE_DIR","mkdirSync","recursive","DatabaseSync","registerFunctions","createConnection","console","error","close","changedSignatureKeys","size","has","embedIdentityAdopted","signatureDiff","rebuildContentTable","Number","Math","min","max","reconcile","resolvedCfg","store","createStore","stmt","n","rmSync","force"],"mappings":"AAAA,+FAA+F;AAC/F,iGAAiG;;;;;;;;;;;;QAepFA;eAAAA;;QAGAC;eAAAA;;QA2LGC;eAAAA;;QATMC;eAAAA;;QALAC;eAAAA;;;sBA9LY;wBACb;0BACQ;uBAEgC;wBAClC;wBACc;wBACR;4BAEA;2BACyE;8BACxE;uBACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAErB,IAAMJ,cAAc;AAGpB,IAAMC,iBAAiB;AAmB9B,yFAAyF;AACzF,2FAA2F;AAC3F,4FAA4F;AAC5F,qCAAqC;AACrC,IAAMI,mBAAmB;AAEzB,wFAAwF;AACxF,6FAA6F;AAC7F,6FAA6F;AAC7F,6FAA6F;AAC7F,+DAA+D;AAC/D,SAASC,gBAAgBC,EAAgB,EAAEC,GAAW;IACpD,IAAMC,aAAaC,IAAAA,wBAAe,EAACF;IACnC,IAAIC,eAAeE,WAAW,OAAON;IACrC,IAAMO,UAAUH,WAAWI,OAAO,CAAC,MAAM;IACzC,IAAI;QACFN,GAAGO,IAAI,CAAC;QACRP,GAAGO,IAAI,CAAC,AAAC,4EAAmF,OAARF,SAAQ;QAC5FL,GAAGO,IAAI,CAAC;IACV,EAAE,OAAOC,KAAK;QACZ,MAAM,IAAIC,oBAAU,CAAC,kBAAkB,AAAC,qBAA2E,OAAvDP,YAAW,8CAAmE,OAAvB,AAACM,IAAcE,OAAO,EAAC;IAC5I;IACA,OAAOL;AACT;AAEA,uFAAuF;AACvF,2FAA2F;AAC3F,SAASM,eAAeX,EAAgB;IACtC,IAAMY,MAAMZ,GAAGa,OAAO,CAAC,wDAAwDC,GAAG;IAClF,IAAI,CAACF,KAAK,OAAO;IACjB,IAAMG,IAAIH,IAAII,GAAG,CAACC,KAAK,CAAC;IACxB,OAAOF,IAAIA,CAAC,CAAC,EAAE,GAAG;AACpB;AAEA,2FAA2F;AAC3F,wFAAwF;AACxF,SAAeG,aAAaC,IAAgB,EAAElB,GAAW,EAAEmB,QAAgB;;YAapE,2BAAA,mBAAA,gBAAA,WAAA,OAAMC;;;;oBAZX;;wBAAMF,KAAKZ,IAAI,CAAC;;;oBAAhB;oBACA,wFAAwF;oBACxF,4FAA4F;oBAC5F,4FAA4F;oBAC5F,2FAA2F;oBAC3F,2FAA2F;oBAC3F,2EAA2E;oBAC3E;;wBAAMY,KAAKZ,IAAI,CAAC,AAAC,6IAAqJ,OAATa,UAAS;;;oBAAtK;oBACA,6FAA6F;oBAC7F,qFAAqF;oBACrF;;wBAAMD,KAAKZ,IAAI,CAAC;;;oBAAhB;oBACA;;wBAAMY,KAAKZ,IAAI,CAAC;;;oBAAhB;oBACK,kCAAA,2BAAA;;;;;;;;;oBAAA,YAAiBe,IAAAA,wBAAc,EAACrB;;;2BAAhC,6BAAA,QAAA;;;;oBAAMoB,UAAN;oBAAsC;;wBAAMA,QAAQE,MAAM,CAACJ;;;oBAArB;;;oBAAtC;;;;;;;;;;;;oBAAA;oBAAA;;;;;;;6BAAA,6BAAA;4BAAA;;;4BAAA;kCAAA;;;;;;;oBACA;;wBAAMK,IAAAA,iBAAO,EAACL,MAAM;;;yBAArB,CAAA,AAAC,kBAA2C,IAAG,GAA/C;;;;oBAAkD;;wBAAMM,IAAAA,iBAAO,EAACN,MAAM,kBAAkBzB;;;oBAAtC;;;oBACjD;;wBAAM8B,IAAAA,iBAAO,EAACL,MAAM;;;yBAArB,CAAA,AAAC,kBAAqC,IAAG,GAAzC;;;;oBAA4C;;wBAAMM,IAAAA,iBAAO,EAACN,MAAM,YAAYO,IAAAA,yBAAgB,EAACzB,KAAK0B,kBAAQ;;;oBAA9D;;;;;;;;IAClD;;AAEA,SAAeC,QAAQ3B,GAAmB;;YAClC4B,UAEAC,QAEA9B,IAIF+B,QA6E4B,MAtExBZ,MAMAC,UAIAY,SACAC,UACAC,cACFC,qBAWIC,aAcEC,SAaJC,QAWFC,iBAQEC,eAGuB,OAArBC,QAAQC,UAGTlC;;;;oBA3FHqB,WAAWc,IAAAA,cAAI,EAAC1C,IAAI2C,OAAO,EAAEC,kBAAS;oBAC5CC,IAAAA,iBAAS,EAACjB,UAAU;wBAAEkB,WAAW;oBAAK;oBAChCjB,SAASa,IAAAA,cAAI,EAACd,UAAUpC;oBAExBO,KAAK,IAAIgD,wBAAY,CAAClB;oBAC5B,8FAA8F;oBAC9F,6FAA6F;oBAC7F,8FAA8F;oBAC1FC,SAAS;;;;;;;;;oBAEX/B,GAAGO,IAAI,CAAC;oBACR,yFAAyF;oBACzF,uCAAuC;oBACvCP,GAAGO,IAAI,CAAC;oBACR0C,IAAAA,iCAAiB,EAACjD,IAAIG,IAAAA,wBAAe,EAACF,SAASG;oBACzCe,OAAO+B,IAAAA,8BAAgB,EAAClD;oBAE9BA,GAAGO,IAAI,CAAC;oBAER,2FAA2F;oBAC3F,8FAA8F;oBACxFa,WAAWrB,gBAAgBC,IAAIC;oBAIrB;;wBAAMuB,IAAAA,iBAAO,EAACL,MAAM;;;oBAA9Ba,UAAU;oBACC;;wBAAMR,IAAAA,iBAAO,EAACL,MAAM;;;oBAA/Bc,WAAW;oBACXC,eAAeR,IAAAA,yBAAgB,EAACzB,KAAK0B,kBAAQ;oBAC/CQ,sBAAsB;yBACtB,CAAA,AAACH,YAAY,QAAQA,YAAYtC,kBAAoBuC,aAAa,QAAQA,aAAaC,YAAY,GAAnG;;;;oBACF,uFAAuF;oBACvF,wFAAwF;oBACxF,IAAIF,YAAY,QAAQA,YAAYtC,gBAAgB;wBAClDyD,QAAQC,KAAK,CAAC;wBACdrB,SAAS;wBACT/B,GAAGqD,KAAK;wBACR1D,WAAWM;wBACX;;4BAAO2B,QAAQ3B;;oBACjB;oBACMmC,cAAckB,IAAAA,iCAAoB,EAACrB,qBAAAA,sBAAAA,WAAY,IAAIC;yBAIrDE,CAAAA,YAAYmB,IAAI,KAAK,KAAKnB,YAAYoB,GAAG,CAAC,WAAU,GAApDpB;;;;oBACFe,QAAQC,KAAK,CAAC;oBACdpD,GAAGO,IAAI,CAAC;oBACR4B,sBAAsB;;;;;;yBACbC,CAAAA,YAAYmB,IAAI,KAAK,KAAKnB,YAAYoB,GAAG,CAAC,YAAYC,IAAAA,iCAAoB,EAACxB,qBAAAA,sBAAAA,WAAY,IAAIC,aAAY,GAAvGE;;;;oBACT,iFAAiF;oBACjF,wFAAwF;oBACxFe,QAAQC,KAAK,CAAC;oBACd;;wBAAM3B,IAAAA,iBAAO,EAACN,MAAM,YAAYe;;;oBAAhC;;;;;;oBAEMG,UAAUqB,IAAAA,0BAAa,EAACzB,qBAAAA,sBAAAA,WAAY,IAAIC;oBAC9CiB,QAAQC,KAAK,CAAC,AAAC,yBAAgC,OAARf,SAAQ;oBAC/CN,SAAS;oBACT/B,GAAGqD,KAAK;oBACR1D,WAAWM;oBACX;;wBAAO2B,QAAQ3B;;;oBAInB,yFAAyF;oBACzF,6FAA6F;oBAC7F,wFAAwF;oBACxF,8CAA8C;oBACxCqC,SAAS3B,eAAeX;oBAC9B,IAAIsC,WAAW,QAAQA,WAAWlB,UAAU;wBAC1C+B,QAAQC,KAAK,CAAC;wBACdrB,SAAS;wBACT/B,GAAGqD,KAAK;wBACR1D,WAAWM;wBACX;;4BAAO2B,QAAQ3B;;oBACjB;oBAEA;;wBAAMiB,aAAaC,MAAMlB,KAAKmB;;;oBAA9B;oBAEImB;yBACAJ,qBAAAA;;;;oBACgB;;wBAAMwB,IAAAA,gCAAmB,EAACxC,MAAMlB,KAAKA,IAAI2C,OAAO;;;oBAAlEL,kBAAkB;oBAClB;;wBAAMd,IAAAA,iBAAO,EAACN,MAAM,YAAYe;;;oBAAhC;;;oBAK4B;;wBAAMV,IAAAA,iBAAO,EAACL,MAAM;;;oBAA5CqB,gBAAgBoB;yBAAQ,OAAA,2BAAA,kBAAA,OAA4C;;oBAC1E5D,GAAGO,IAAI,CAAC,AAAC,yBAA8E,OAAtDsD,KAAKC,GAAG,CAACD,KAAKE,GAAG,CAAC,OAAO,IAAIvB,gBAAgB;oBAEjD;;wBAAMwB,IAAAA,sBAAS,EAAC7C,MAAMlB,KAAKA,IAAI2C,OAAO;;;oBAAtC,QAAA,eAArBH,SAAqB,MAArBA,QAAQC,WAAa,MAAbA;oBAEhB;;wBAAO;4BAAE1C,IAAAA;4BAAImB,MAAAA;4BAAMlB,KAAAA;4BAAK6B,QAAAA;4BAAQW,QAAAA;4BAAQC,UAAU,AAAC,qBAAGH,wBAAiB,qBAAGG;wBAAU;;;oBAC7ElC;oBACP,IAAI,CAACuB,QAAQ/B,GAAGqD,KAAK;oBACrB,MAAM7C;;;;;;;IAEV;;AAIO,SAAeX,WAAWI,GAAmB;;YACe,MAAzDD,IAAImB,MAAW8C,aAAanC,QAAQW,QAAQC;;;;oBAAa;;wBAAMd,QAAQ3B;;;oBAAd,OAAA,eAAzDD,KAAyD,KAAzDA,IAAImB,OAAqD,KAArDA,MAAW8C,cAA0C,KAA/ChE,KAAkB6B,SAA6B,KAA7BA,QAAQW,SAAqB,KAArBA,QAAQC,WAAa,KAAbA;oBACpD;;wBAAO;4BAAEwB,OAAOC,IAAAA,oBAAW,EAACnE,IAAImB,MAAM8C,aAAaA,YAAYrB,OAAO;4BAAG3C,KAAKgE;4BAAanC,QAAAA;4BAAQW,QAAAA;4BAAQC,UAAAA;wBAAS;;;;IACtH;;AAEO,SAAe9C,SAASsE,KAAY;;YACnCE;;;;oBAAO;;wBAAMF,MAAMrD,OAAO,CAAC;;;oBAA3BuD,OAAO;oBACJ;;wBAAMA,KAAKtD,GAAG;;;oBAAvB;;wBAAS,cAAoCuD,CAAC;;;;IAChD;;AAMO,SAAS1E,WAAWM,GAAmB;IAC5CqE,IAAAA,cAAM,EAAC3B,IAAAA,cAAI,EAAC1C,IAAI2C,OAAO,EAAEC,kBAAS,GAAG;QAAEE,WAAW;QAAMwB,OAAO;IAAK;AACtE"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/open.ts"],"sourcesContent":["// The Node floor (>=22.20) is explained here and nowhere else: 22.20 is the first release with\n// both FTS5 and row-returning INSERT ... RETURNING. Raise it only for a load-bearing capability.\nimport { mkdirSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { DatabaseSync } from 'node:sqlite';\nimport type { Config, ResolvedConfig } from '../../config/index.ts';\nimport { contentTokenize, featureSignature, STATE_DIR } from '../../config/index.ts';\nimport { SenseError } from '../../errors.ts';\nimport { activeFeatures, FEATURES } from '../../features/index.ts';\nimport { getMeta, setMeta } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, Store } from '../types.ts';\nimport { createConnection } from './connection.ts';\nimport { changedSignatureKeys, embedIdentityAdopted, rebuildContentTable, reconcile, signatureDiff } from './reconcile.ts';\nimport { registerFunctions } from './sql-functions.ts';\nimport { createStore } from './store.ts';\n\nexport const DB_FILENAME = 'cache.db';\n// Cache shape version, independent of the config's own `version`. Bumping it rebuilds\n// existing trees on first query.\nexport const SCHEMA_VERSION = '18';\n\ninterface ConnectResult {\n db: DatabaseSync;\n conn: Connection;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n}\n\nexport interface OpenResult {\n store: Store;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n}\n\n// Stemming is English-only, but the segmentation underneath it is what decides coverage:\n// unicode61 splits on spaces, so a language written without them (Chinese, Japanese, Thai)\n// indexes a whole run as one token and word search finds nothing. `content.tokenize` is how\n// such a tree picks trigram instead.\nconst DEFAULT_TOKENIZE = 'porter unicode61';\n\n// FTS5 takes its tokenizer as a string literal inside DDL, where nothing can bind, so a\n// configured value has to be concatenated. Probing a throwaway table is what makes that safe\n// and is also the whole validation: anything the linked SQLite accepts passes, anything else\n// fails here with SQLite's own message rather than against the real table. It means no table\n// of which version added which tokenizer has to be maintained.\nfunction resolveTokenize(db: DatabaseSync, cfg: Config): string {\n const configured = contentTokenize(cfg);\n if (configured === undefined) return DEFAULT_TOKENIZE;\n const literal = configured.replace(/'/g, \"''\");\n try {\n db.exec('DROP TABLE IF EXISTS temp.sense_tokenize_probe');\n db.exec(`CREATE VIRTUAL TABLE temp.sense_tokenize_probe USING fts5(x, tokenize = '${literal}')`);\n db.exec('DROP TABLE IF EXISTS temp.sense_tokenize_probe');\n } catch (err) {\n throw new SenseError('CONFIG_INVALID', `content.tokenize \"${configured}\" is not a tokenizer this SQLite accepts (${(err as Error).message}); the built-in choices are unicode61, ascii, porter, and trigram, each with their own options`);\n }\n return literal;\n}\n\n// The tokenizer the content table was actually built with, from its own DDL -- the one\n// record that cannot desynchronize from the table. NULL when the table does not exist yet.\nfunction storedTokenize(db: DatabaseSync): string | null {\n const row = db.prepare(`SELECT sql FROM sqlite_master WHERE name = 'content'`).get() as { sql: string } | undefined;\n if (!row) return null;\n const m = row.sql.match(/tokenize = '((?:[^']|'')*)'/);\n return m ? m[1] : null;\n}\n\n// The three `_seg` sidecars are appended after path, never inserted: bm25(content, ...) and\n// snippet(content, 2, ...) are documented against the first three columns and keep working\n// (FTS5 defaults the weights it was not given). Each carries its field's exploded unspaced\n// runs for text that needs it, and an empty string for text that does not. Shared by\n// ensureSchema and the tokenize-only rebuild in connect(), so both create identical DDL.\nasync function createContentTable(conn: Connection, tokenize: string): Promise<void> {\n await conn.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, title_seg, summary_seg, text_seg, tokenize = '${tokenize}')`);\n}\n\n// Content is a separate table (not a column on frontmatter) so `SELECT * FROM frontmatter`\n// can't dump file text into context. Features add their own tables after the core ones.\nasync function ensureSchema(conn: Connection, cfg: Config, tokenize: string): Promise<void> {\n await conn.exec(`CREATE TABLE IF NOT EXISTS frontmatter (\"path\" TEXT PRIMARY KEY, \"_mtime\" REAL, \"_ctime\" REAL, \"_size\" INTEGER, \"_parse_error\" TEXT)`);\n // IF NOT EXISTS is safe against a tokenizer change: open() compares the table's own DDL\n // against the resolved tokenizer before this runs, so a stale table is already gone by now.\n await createContentTable(conn, tokenize);\n // Coverage, not ownership: a path can appear under several presets. path leads the PK so the\n // per-doc delete is an index hit -- keyed the other way, cold builds went quadratic.\n await conn.exec(`CREATE TABLE IF NOT EXISTS preset_files (\"path\" TEXT, preset TEXT, PRIMARY KEY (\"path\", preset))`);\n await conn.exec('CREATE INDEX IF NOT EXISTS preset_files_preset ON preset_files(preset)');\n for (const feature of activeFeatures(cfg)) await feature.schema(conn);\n if ((await getMeta(conn, 'schema_version')) === null) await setMeta(conn, 'schema_version', SCHEMA_VERSION);\n if ((await getMeta(conn, 'features')) === null) await setMeta(conn, 'features', featureSignature(cfg, FEATURES));\n}\n\nasync function connect(cfg: ResolvedConfig): Promise<ConnectResult> {\n const stateDir = join(cfg.baseDir, STATE_DIR);\n mkdirSync(stateDir, { recursive: true });\n const dbPath = join(stateDir, DB_FILENAME);\n\n const db = new DatabaseSync(dbPath);\n // A throw below (tokenizer probe, schema, reconcile's COLUMN_LIMIT) must release this handle,\n // or on Windows the leaked WAL db is undeletable and scratch cleanup fails with EPERM/EBUSY.\n // closed marks the rebuild branches that close-and-recurse, so the catch never double-closes.\n let closed = false;\n try {\n db.exec('PRAGMA journal_mode = WAL');\n // Covers a concurrent watcher's bulk reconcile (~5s for 500 files at 26k notes). A query\n // that outwaits it still fails loudly.\n db.exec('PRAGMA busy_timeout = 30000');\n registerFunctions(db, contentTokenize(cfg) === undefined);\n const conn = createConnection(db);\n\n db.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');\n\n // Before the rebuild branch below, never after: that branch deletes the cache, so a typo'd\n // tokenizer validated later would cost a full re-index (and re-embed) to reach its own error.\n const tokenize = resolveTokenize(db, cfg);\n\n // Schema-version or feature-set mismatch: reconcile only reparses changed files, so an\n // old cache can't be patched incrementally -- rebuild instead (cheap: nothing expensive lives here).\n const version = await getMeta(conn, 'schema_version');\n const features = await getMeta(conn, 'features');\n const wantFeatures = featureSignature(cfg, FEATURES);\n let tokenizeOnlyRebuild = false;\n if ((version !== null && version !== SCHEMA_VERSION) || (features !== null && features !== wantFeatures)) {\n // Indexing derives from presets, so a config edit rebuilding the cache must say so and\n // name what changed -- silent rebuilds make derived indexing look like a hang or a bug.\n if (version !== null && version !== SCHEMA_VERSION) {\n console.error('sense: cache format changed (new sensemaking version); rebuilding the index');\n closed = true;\n db.close();\n clearCache(cfg);\n return connect(cfg);\n }\n const changedKeys = changedSignatureKeys(features ?? '', wantFeatures);\n // Only the tokenizer moved: frontmatter, links, sections, and embeddings are file-derived\n // and tokenizer-independent, so they don't need re-deriving. Everything else -- a preset\n // edit, an embed model change -- still takes the full clear/reopen below.\n if (changedKeys.size === 1 && changedKeys.has('tokenize')) {\n console.error('sense: config change (content tokenizer) rebuilds the text index; vectors, links, and sections are kept');\n // Drop and recreate as one transaction: a crash before COMMIT rolls back to the table\n // that was there before (old tokenizer, still queryable), never to no table at all.\n // IF EXISTS also makes a retry after such a crash a no-op instead of a raw SQLite error --\n // meta.features is only updated once rebuildContentTable (below) finishes, so a retry\n // re-enters this branch and repopulates from scratch either way.\n await withTransaction(conn, async () => {\n await conn.exec('DROP TABLE IF EXISTS content');\n await createContentTable(conn, tokenize);\n });\n tokenizeOnlyRebuild = true;\n } else if (changedKeys.size === 1 && changedKeys.has('embed') && embedIdentityAdopted(features ?? '', wantFeatures)) {\n // First sight of a resolved weight identity: the model itself hasn't changed, so\n // adopt it into meta with no rebuild and no re-embed, mirroring the tokenize precedent.\n console.error(\"sense: recorded the embedding model's resolved identity; vectors are unaffected\");\n await setMeta(conn, 'features', wantFeatures);\n } else {\n const changed = signatureDiff(features ?? '', wantFeatures);\n console.error(`sense: config change (${changed}) rebuilds the index`);\n closed = true;\n db.close();\n clearCache(cfg);\n return connect(cfg);\n }\n }\n\n // Meta can lie after a crash between table creation and the signature write; the table's\n // own DDL cannot. A mismatch here rebuilds no matter what meta says. A tokenize-only rebuild\n // already recreated content with this tokenize above, so stored already matches and this\n // guard is skipped naturally rather than needing its own case.\n const stored = storedTokenize(db);\n if (stored !== null && stored !== tokenize) {\n console.error('sense: cache was built with a different content tokenizer; rebuilding the index');\n closed = true;\n db.close();\n clearCache(cfg);\n return connect(cfg);\n }\n\n await ensureSchema(conn, cfg, tokenize);\n\n let rebuildWarnings: string[] = [];\n if (tokenizeOnlyRebuild) {\n rebuildWarnings = await rebuildContentTable(conn, cfg, cfg.baseDir);\n await setMeta(conn, 'features', wantFeatures);\n }\n\n // 3x the largest reconcile this cache has recorded, floored at 30s and capped at 10min.\n // Installed before reconcile() -- that call is the one that races a watcher's transaction.\n const recordedMaxMs = Number((await getMeta(conn, 'reconcile_max_ms')) ?? '0');\n db.exec(`PRAGMA busy_timeout = ${Math.min(Math.max(30000, 3 * recordedMaxMs), 600_000)}`);\n\n const { parsed, warnings } = await reconcile(conn, cfg, cfg.baseDir);\n\n return { db, conn, cfg, dbPath, parsed, warnings: [...rebuildWarnings, ...warnings] };\n } catch (err) {\n if (!closed) db.close();\n throw err;\n }\n}\n\n// The sqlite store's open: connects synchronously (see connect() above), then wraps the\n// resulting connection in the async Store interface.\nexport async function openSqlite(cfg: ResolvedConfig): Promise<OpenResult> {\n const { db, conn, cfg: resolvedCfg, dbPath, parsed, warnings } = await connect(cfg);\n return { store: createStore(db, conn, resolvedCfg, resolvedCfg.baseDir), cfg: resolvedCfg, dbPath, parsed, warnings };\n}\n\nexport async function docCount(store: Store): Promise<number> {\n const stmt = await store.prepare('SELECT COUNT(*) AS n FROM frontmatter');\n return ((await stmt.get()) as { n: number }).n;\n}\n\n// Deletes the cache directory, and only that. The rebuild is not this function's job: the next\n// open() reconciles, which is what running any command already does, so a verb that bundled the\n// two described the half that was not its own. Manual reset for a doubted cache; the schema and\n// config-signature mismatches below reset themselves.\nexport function clearCache(cfg: ResolvedConfig): void {\n rmSync(join(cfg.baseDir, STATE_DIR), { recursive: true, force: true });\n}\n"],"names":["DB_FILENAME","SCHEMA_VERSION","clearCache","docCount","openSqlite","DEFAULT_TOKENIZE","resolveTokenize","db","cfg","configured","contentTokenize","undefined","literal","replace","exec","err","SenseError","message","storedTokenize","row","prepare","get","m","sql","match","createContentTable","conn","tokenize","ensureSchema","feature","activeFeatures","schema","getMeta","setMeta","featureSignature","FEATURES","connect","stateDir","dbPath","closed","version","features","wantFeatures","tokenizeOnlyRebuild","changedKeys","changed","stored","rebuildWarnings","recordedMaxMs","parsed","warnings","join","baseDir","STATE_DIR","mkdirSync","recursive","DatabaseSync","registerFunctions","createConnection","console","error","close","changedSignatureKeys","size","has","withTransaction","embedIdentityAdopted","signatureDiff","rebuildContentTable","Number","Math","min","max","reconcile","resolvedCfg","store","createStore","stmt","n","rmSync","force"],"mappings":"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"}
@@ -19,9 +19,11 @@ _export(exports, {
19
19
  var _indexts = require("../../config/index.js");
20
20
  var _sharedts = require("../shared.js");
21
21
  var _transactionts = require("../transaction.js");
22
+ var _vectorsts = require("../vectors.js");
23
+ var _fieldStatsts = require("./fieldStats.js");
22
24
  var _lexicalts = require("./lexical.js");
23
25
  var _reconcilets = require("./reconcile.js");
24
- var _vectorsts = require("./vectors.js");
26
+ var _vectorsts1 = require("./vectors.js");
25
27
  function _array_like_to_array(arr, len) {
26
28
  if (len == null || len > arr.length) len = arr.length;
27
29
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
@@ -457,6 +459,16 @@ function createStore(db, conn, cfg, baseDir) {
457
459
  }
458
460
  });
459
461
  })();
462
+ },
463
+ fieldStats: function fieldStats(columns, scopeWhere) {
464
+ return _async_to_generator(function() {
465
+ return _ts_generator(this, function(_state) {
466
+ return [
467
+ 2,
468
+ (0, _fieldStatsts.fieldStats)(conn, columns, scopeWhere)
469
+ ];
470
+ });
471
+ })();
460
472
  }
461
473
  },
462
474
  lexical: {
@@ -489,7 +501,7 @@ function createStore(db, conn, cfg, baseDir) {
489
501
  case 0:
490
502
  return [
491
503
  4,
492
- (0, _vectorsts.writeVectorBatch)(conn, rows)
504
+ (0, _vectorsts1.writeVectorBatch)(conn, rows)
493
505
  ];
494
506
  case 1:
495
507
  _state.sent();
@@ -505,7 +517,7 @@ function createStore(db, conn, cfg, baseDir) {
505
517
  return _ts_generator(this, function(_state) {
506
518
  return [
507
519
  2,
508
- (0, _vectorsts.scanCandidates)(conn, qv, storeDims, fetch, allowed)
520
+ (0, _vectorsts1.scanCandidates)(conn, qv, storeDims, fetch, allowed)
509
521
  ];
510
522
  });
511
523
  })();
@@ -515,7 +527,7 @@ function createStore(db, conn, cfg, baseDir) {
515
527
  return _ts_generator(this, function(_state) {
516
528
  return [
517
529
  2,
518
- (0, _vectorsts.scanSimilar)(conn, path, opts)
530
+ (0, _vectorsts1.scanSimilar)(conn, path, opts)
519
531
  ];
520
532
  });
521
533
  })();
@@ -531,6 +543,22 @@ function createStore(db, conn, cfg, baseDir) {
531
543
  })();
532
544
  }
533
545
  },
546
+ engineStatus: function engineStatus() {
547
+ return _async_to_generator(function() {
548
+ var row;
549
+ return _ts_generator(this, function(_state) {
550
+ // Read back rather than recomputed: this is what open() actually set (3x the largest
551
+ // recorded reconcile, floored at 30s, capped at 10min), not a value re-derived here.
552
+ row = db.prepare('PRAGMA busy_timeout').get();
553
+ return [
554
+ 2,
555
+ {
556
+ busy_timeout: "".concat(row.timeout, "ms (derived: 3x the largest reconcile this cache has recorded, floored at 30000ms)")
557
+ }
558
+ ];
559
+ });
560
+ })();
561
+ },
534
562
  raw: {
535
563
  prepare: function prepare(sql) {
536
564
  return _async_to_generator(function() {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/store.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport type { Config } from '../../config/index.ts';\nimport { contentTokenize } from '../../config/index.ts';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store, VectorWriteRow } from '../types.ts';\nimport { queryLexical } from './lexical.ts';\nimport { reconcile } from './reconcile.ts';\nimport { hasVectorRow, pendingRows, scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['phrases', 'snippets', 'watch-concurrency', 'lexical', 'vectors']);\n\n// Wraps the synchronous DatabaseSync connection in the async Store interface, sharing one\n// Connection instance (conn) with open()'s own reconcile call so transaction depth (see\n// transaction.ts) is tracked against the same object everywhere.\nexport function createStore(db: DatabaseSync, conn: Connection, cfg: Config, baseDir: string): Store {\n return {\n name: 'sqlite',\n capabilities: CAPABILITIES,\n async exec(sql: string): Promise<void> {\n await conn.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return conn.prepare(sql);\n },\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n await conn.runBatch(sql, paramRows);\n },\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n return withTransaction(conn, fn);\n },\n async reconcile() {\n return reconcile(conn, cfg, baseDir);\n },\n docs: {\n async columns() {\n return [...(await getColumns(conn))];\n },\n },\n lexical: {\n async query(terms, opts) {\n return queryLexical(conn, terms, opts, contentTokenize(cfg) === undefined);\n },\n },\n vectors: {\n async pending() {\n return pendingRows(conn);\n },\n async writeVectors(rows: VectorWriteRow[]) {\n await writeVectorBatch(conn, rows);\n },\n async candidates(qv, storeDims, fetch, allowed) {\n return scanCandidates(conn, qv, storeDims, fetch, allowed);\n },\n async similar(path, opts) {\n return scanSimilar(conn, path, opts);\n },\n async hasVector(path) {\n return hasVectorRow(conn, path);\n },\n },\n raw: {\n async prepare(sql: string) {\n const stmt = db.prepare(sql);\n stmt.setReadBigInts(true); // int64 past 2^53 arrives as BigInt instead of throwing at step time\n return {\n columns: () => stmt.columns(),\n // sense sql streams through an async iterator wrapping the sync iterate().\n iterate: async function* (...params: unknown[]) {\n yield* stmt.iterate(...(params as Parameters<typeof stmt.iterate>));\n },\n };\n },\n },\n async close() {\n db.close();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","db","conn","cfg","baseDir","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","reconcile","docs","columns","getColumns","lexical","query","terms","opts","queryLexical","contentTokenize","undefined","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","candidates","qv","storeDims","fetch","allowed","scanCandidates","similar","path","scanSimilar","hasVector","hasVectorRow","raw","stmt","setReadBigInts","iterate","params","close"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/store.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport type { Config } from '../../config/index.ts';\nimport { contentTokenize } from '../../config/index.ts';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store, VectorWriteRow } from '../types.ts';\nimport { hasVectorRow, pendingRows } from '../vectors.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { queryLexical } from './lexical.ts';\nimport { reconcile } from './reconcile.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['phrases', 'snippets', 'watch-concurrency', 'lexical', 'vectors']);\n\n// Wraps the synchronous DatabaseSync connection in the async Store interface, sharing one\n// Connection instance (conn) with open()'s own reconcile call so transaction depth (see\n// transaction.ts) is tracked against the same object everywhere.\nexport function createStore(db: DatabaseSync, conn: Connection, cfg: Config, baseDir: string): Store {\n return {\n name: 'sqlite',\n capabilities: CAPABILITIES,\n async exec(sql: string): Promise<void> {\n await conn.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return conn.prepare(sql);\n },\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n await conn.runBatch(sql, paramRows);\n },\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n return withTransaction(conn, fn);\n },\n async reconcile() {\n return reconcile(conn, cfg, baseDir);\n },\n docs: {\n async columns() {\n return [...(await getColumns(conn))];\n },\n async fieldStats(columns, scopeWhere) {\n return fieldStats(conn, columns, scopeWhere);\n },\n },\n lexical: {\n async query(terms, opts) {\n return queryLexical(conn, terms, opts, contentTokenize(cfg) === undefined);\n },\n },\n vectors: {\n async pending() {\n return pendingRows(conn);\n },\n async writeVectors(rows: VectorWriteRow[]) {\n await writeVectorBatch(conn, rows);\n },\n async candidates(qv, storeDims, fetch, allowed) {\n return scanCandidates(conn, qv, storeDims, fetch, allowed);\n },\n async similar(path, opts) {\n return scanSimilar(conn, path, opts);\n },\n async hasVector(path) {\n return hasVectorRow(conn, path);\n },\n },\n async engineStatus() {\n // Read back rather than recomputed: this is what open() actually set (3x the largest\n // recorded reconcile, floored at 30s, capped at 10min), not a value re-derived here.\n const row = db.prepare('PRAGMA busy_timeout').get() as { timeout: number };\n return { busy_timeout: `${row.timeout}ms (derived: 3x the largest reconcile this cache has recorded, floored at 30000ms)` };\n },\n raw: {\n async prepare(sql: string) {\n const stmt = db.prepare(sql);\n stmt.setReadBigInts(true); // int64 past 2^53 arrives as BigInt instead of throwing at step time\n return {\n columns: () => stmt.columns(),\n // sense sql streams through an async iterator wrapping the sync iterate().\n iterate: async function* (...params: unknown[]) {\n yield* stmt.iterate(...(params as Parameters<typeof stmt.iterate>));\n },\n };\n },\n },\n async close() {\n db.close();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","db","conn","cfg","baseDir","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","reconcile","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","opts","queryLexical","contentTokenize","undefined","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","candidates","qv","storeDims","fetch","allowed","scanCandidates","similar","path","scanSimilar","hasVector","hasVectorRow","engineStatus","row","get","busy_timeout","timeout","raw","stmt","setReadBigInts","iterate","params","close"],"mappings":"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"}