sensemaking 0.23.0 → 0.24.0

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 (193) hide show
  1. package/README.md +13 -9
  2. package/dist/cjs/cli/index.d.cts +1 -1
  3. package/dist/cjs/cli/index.d.ts +1 -1
  4. package/dist/cjs/cli/index.js +1 -1
  5. package/dist/cjs/cli/index.js.map +1 -1
  6. package/dist/cjs/cli/named.js +6 -2
  7. package/dist/cjs/cli/named.js.map +1 -1
  8. package/dist/cjs/cli/search.js +6 -2
  9. package/dist/cjs/cli/search.js.map +1 -1
  10. package/dist/cjs/cli/shared.d.cts +2 -0
  11. package/dist/cjs/cli/shared.d.ts +2 -0
  12. package/dist/cjs/cli/shared.js +24 -0
  13. package/dist/cjs/cli/shared.js.map +1 -1
  14. package/dist/cjs/commands/map.js +2 -2
  15. package/dist/cjs/commands/map.js.map +1 -1
  16. package/dist/cjs/commands/search.d.cts +10 -0
  17. package/dist/cjs/commands/search.d.ts +10 -0
  18. package/dist/cjs/commands/search.js +488 -180
  19. package/dist/cjs/commands/search.js.map +1 -1
  20. package/dist/cjs/output/output.js +45 -8
  21. package/dist/cjs/output/output.js.map +1 -1
  22. package/dist/cjs/output/search-error.d.cts +1 -0
  23. package/dist/cjs/output/search-error.d.ts +1 -0
  24. package/dist/cjs/output/search-error.js +28 -4
  25. package/dist/cjs/output/search-error.js.map +1 -1
  26. package/dist/cjs/scan/frontmatter.js +1 -1
  27. package/dist/cjs/scan/frontmatter.js.map +1 -1
  28. package/dist/cjs/scan/index.js +1 -0
  29. package/dist/cjs/scan/index.js.map +1 -1
  30. package/dist/cjs/store/batch.d.cts +4 -0
  31. package/dist/cjs/store/batch.d.ts +4 -0
  32. package/dist/cjs/store/batch.js +80 -0
  33. package/dist/cjs/store/batch.js.map +1 -0
  34. package/dist/cjs/store/duckdb/batch.d.cts +0 -4
  35. package/dist/cjs/store/duckdb/batch.d.ts +0 -4
  36. package/dist/cjs/store/duckdb/batch.js +5 -27
  37. package/dist/cjs/store/duckdb/batch.js.map +1 -1
  38. package/dist/cjs/store/duckdb/fieldStats.js +4 -7
  39. package/dist/cjs/store/duckdb/fieldStats.js.map +1 -1
  40. package/dist/cjs/store/duckdb/lexical.d.cts +2 -2
  41. package/dist/cjs/store/duckdb/lexical.d.ts +2 -2
  42. package/dist/cjs/store/duckdb/lexical.js +215 -64
  43. package/dist/cjs/store/duckdb/lexical.js.map +1 -1
  44. package/dist/cjs/store/duckdb/reconcile.js +7 -2
  45. package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
  46. package/dist/cjs/store/duckdb/store.js +1 -3
  47. package/dist/cjs/store/duckdb/store.js.map +1 -1
  48. package/dist/cjs/store/duckdb/vectors.js +13 -8
  49. package/dist/cjs/store/duckdb/vectors.js.map +1 -1
  50. package/dist/cjs/store/native.js +5 -4
  51. package/dist/cjs/store/native.js.map +1 -1
  52. package/dist/cjs/store/open.js +7 -0
  53. package/dist/cjs/store/open.js.map +1 -1
  54. package/dist/cjs/store/shared.js.map +1 -1
  55. package/dist/cjs/store/sqlite/lexical.js +1 -4
  56. package/dist/cjs/store/sqlite/lexical.js.map +1 -1
  57. package/dist/cjs/store/sqlite/store.js +1 -4
  58. package/dist/cjs/store/sqlite/store.js.map +1 -1
  59. package/dist/cjs/store/sqlite/vectors.js +78 -24
  60. package/dist/cjs/store/sqlite/vectors.js.map +1 -1
  61. package/dist/cjs/store/turso/connection.d.cts +3 -0
  62. package/dist/cjs/store/turso/connection.d.ts +3 -0
  63. package/dist/cjs/store/turso/connection.js +302 -31
  64. package/dist/cjs/store/turso/connection.js.map +1 -1
  65. package/dist/cjs/store/turso/lexical-text.d.cts +1 -0
  66. package/dist/cjs/store/turso/lexical-text.d.ts +1 -0
  67. package/dist/cjs/store/turso/lexical-text.js +40 -0
  68. package/dist/cjs/store/turso/lexical-text.js.map +1 -0
  69. package/dist/cjs/store/turso/lexical.js +89 -16
  70. package/dist/cjs/store/turso/lexical.js.map +1 -1
  71. package/dist/cjs/store/turso/native.d.cts +4 -0
  72. package/dist/cjs/store/turso/native.d.ts +4 -0
  73. package/dist/cjs/store/turso/native.js +9 -0
  74. package/dist/cjs/store/turso/native.js.map +1 -1
  75. package/dist/cjs/store/turso/open.d.cts +1 -1
  76. package/dist/cjs/store/turso/open.d.ts +1 -1
  77. package/dist/cjs/store/turso/open.js +83 -10
  78. package/dist/cjs/store/turso/open.js.map +1 -1
  79. package/dist/cjs/store/turso/reconcile.d.cts +1 -1
  80. package/dist/cjs/store/turso/reconcile.d.ts +1 -1
  81. package/dist/cjs/store/turso/reconcile.js +6 -2
  82. package/dist/cjs/store/turso/reconcile.js.map +1 -1
  83. package/dist/cjs/store/turso/sql-functions.d.cts +1 -0
  84. package/dist/cjs/store/turso/sql-functions.d.ts +1 -0
  85. package/dist/cjs/store/turso/sql-functions.js +174 -0
  86. package/dist/cjs/store/turso/sql-functions.js.map +1 -0
  87. package/dist/cjs/store/turso/store.js +105 -4
  88. package/dist/cjs/store/turso/store.js.map +1 -1
  89. package/dist/cjs/store/turso/vectors.js +50 -14
  90. package/dist/cjs/store/turso/vectors.js.map +1 -1
  91. package/dist/cjs/store/types.d.cts +1 -2
  92. package/dist/cjs/store/types.d.ts +1 -2
  93. package/dist/cjs/store/types.js +1 -4
  94. package/dist/cjs/store/types.js.map +1 -1
  95. package/dist/cjs/store/vectors.d.cts +7 -0
  96. package/dist/cjs/store/vectors.d.ts +7 -0
  97. package/dist/cjs/store/vectors.js +8 -0
  98. package/dist/cjs/store/vectors.js.map +1 -1
  99. package/dist/cjs/text/segment.d.cts +13 -0
  100. package/dist/cjs/text/segment.d.ts +13 -0
  101. package/dist/cjs/text/segment.js +109 -4
  102. package/dist/cjs/text/segment.js.map +1 -1
  103. package/dist/esm/cli/index.d.ts +1 -1
  104. package/dist/esm/cli/index.js +1 -1
  105. package/dist/esm/cli/index.js.map +1 -1
  106. package/dist/esm/cli/named.js +6 -2
  107. package/dist/esm/cli/named.js.map +1 -1
  108. package/dist/esm/cli/search.js +5 -1
  109. package/dist/esm/cli/search.js.map +1 -1
  110. package/dist/esm/cli/shared.d.ts +2 -0
  111. package/dist/esm/cli/shared.js +19 -0
  112. package/dist/esm/cli/shared.js.map +1 -1
  113. package/dist/esm/commands/map.js +2 -2
  114. package/dist/esm/commands/map.js.map +1 -1
  115. package/dist/esm/commands/search.d.ts +10 -0
  116. package/dist/esm/commands/search.js +271 -91
  117. package/dist/esm/commands/search.js.map +1 -1
  118. package/dist/esm/output/output.js +27 -4
  119. package/dist/esm/output/output.js.map +1 -1
  120. package/dist/esm/output/search-error.d.ts +1 -0
  121. package/dist/esm/output/search-error.js +17 -1
  122. package/dist/esm/output/search-error.js.map +1 -1
  123. package/dist/esm/scan/frontmatter.js +1 -1
  124. package/dist/esm/scan/frontmatter.js.map +1 -1
  125. package/dist/esm/scan/index.js +1 -0
  126. package/dist/esm/scan/index.js.map +1 -1
  127. package/dist/esm/store/batch.d.ts +4 -0
  128. package/dist/esm/store/batch.js +21 -0
  129. package/dist/esm/store/batch.js.map +1 -0
  130. package/dist/esm/store/duckdb/batch.d.ts +0 -4
  131. package/dist/esm/store/duckdb/batch.js +2 -19
  132. package/dist/esm/store/duckdb/batch.js.map +1 -1
  133. package/dist/esm/store/duckdb/fieldStats.js +4 -7
  134. package/dist/esm/store/duckdb/fieldStats.js.map +1 -1
  135. package/dist/esm/store/duckdb/lexical.d.ts +2 -2
  136. package/dist/esm/store/duckdb/lexical.js +94 -40
  137. package/dist/esm/store/duckdb/lexical.js.map +1 -1
  138. package/dist/esm/store/duckdb/reconcile.js +2 -2
  139. package/dist/esm/store/duckdb/reconcile.js.map +1 -1
  140. package/dist/esm/store/duckdb/store.js +2 -4
  141. package/dist/esm/store/duckdb/store.js.map +1 -1
  142. package/dist/esm/store/duckdb/vectors.js +26 -13
  143. package/dist/esm/store/duckdb/vectors.js.map +1 -1
  144. package/dist/esm/store/native.js +5 -4
  145. package/dist/esm/store/native.js.map +1 -1
  146. package/dist/esm/store/open.js +7 -0
  147. package/dist/esm/store/open.js.map +1 -1
  148. package/dist/esm/store/shared.js +1 -2
  149. package/dist/esm/store/shared.js.map +1 -1
  150. package/dist/esm/store/sqlite/lexical.js +2 -5
  151. package/dist/esm/store/sqlite/lexical.js.map +1 -1
  152. package/dist/esm/store/sqlite/store.js +1 -4
  153. package/dist/esm/store/sqlite/store.js.map +1 -1
  154. package/dist/esm/store/sqlite/vectors.js +48 -19
  155. package/dist/esm/store/sqlite/vectors.js.map +1 -1
  156. package/dist/esm/store/turso/connection.d.ts +3 -0
  157. package/dist/esm/store/turso/connection.js +61 -5
  158. package/dist/esm/store/turso/connection.js.map +1 -1
  159. package/dist/esm/store/turso/lexical-text.d.ts +1 -0
  160. package/dist/esm/store/turso/lexical-text.js +12 -0
  161. package/dist/esm/store/turso/lexical-text.js.map +1 -0
  162. package/dist/esm/store/turso/lexical.js +56 -21
  163. package/dist/esm/store/turso/lexical.js.map +1 -1
  164. package/dist/esm/store/turso/native.d.ts +4 -0
  165. package/dist/esm/store/turso/native.js +8 -0
  166. package/dist/esm/store/turso/native.js.map +1 -1
  167. package/dist/esm/store/turso/open.d.ts +1 -1
  168. package/dist/esm/store/turso/open.js +7 -7
  169. package/dist/esm/store/turso/open.js.map +1 -1
  170. package/dist/esm/store/turso/reconcile.d.ts +1 -1
  171. package/dist/esm/store/turso/reconcile.js +6 -2
  172. package/dist/esm/store/turso/reconcile.js.map +1 -1
  173. package/dist/esm/store/turso/sql-functions.d.ts +1 -0
  174. package/dist/esm/store/turso/sql-functions.js +179 -0
  175. package/dist/esm/store/turso/sql-functions.js.map +1 -0
  176. package/dist/esm/store/turso/store.js +32 -7
  177. package/dist/esm/store/turso/store.js.map +1 -1
  178. package/dist/esm/store/turso/vectors.js +19 -10
  179. package/dist/esm/store/turso/vectors.js.map +1 -1
  180. package/dist/esm/store/types.d.ts +1 -2
  181. package/dist/esm/store/types.js +6 -8
  182. package/dist/esm/store/types.js.map +1 -1
  183. package/dist/esm/store/vectors.d.ts +7 -0
  184. package/dist/esm/store/vectors.js +8 -2
  185. package/dist/esm/store/vectors.js.map +1 -1
  186. package/dist/esm/text/segment.d.ts +13 -0
  187. package/dist/esm/text/segment.js +70 -0
  188. package/dist/esm/text/segment.js.map +1 -1
  189. package/package.json +4 -3
  190. package/schema.json +1 -1
  191. package/skills/sense/EXAMPLES.md +3 -3
  192. package/skills/sense/SKILL.md +6 -6
  193. package/skills/sense-setup/SKILL.md +1 -1
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "rewriteFunctions", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return rewriteFunctions;
9
+ }
10
+ });
11
+ var _errorsts = require("../../errors.js");
12
+ // Turso can't register UDFs: has()/basename() are rewritten into portable SQL below; segment()
13
+ // (Intl.Segmenter grapheme clustering, types.ts's 'segment' capability) has none, so it's rejected like an unsupported FTS5 operator.
14
+ // Non-global: recursion (readArgs' contents rewritten via rewriteFunctions) reenters this module's
15
+ // regexes before the outer scan resumes, and a global regex's lastIndex does not nest across that.
16
+ var CALL_ANYWHERE = /\b(has|basename|segment)\s*\(/i;
17
+ var CALL_AT_START = /^(has|basename|segment)\s*\(/i;
18
+ function isWordChar(ch) {
19
+ return ch !== undefined && /[A-Za-z0-9_]/.test(ch);
20
+ }
21
+ // The index just past the quoted literal or SQL comment starting at i, or null if i starts
22
+ // neither. Shared by the scan and readArgs so both leave quoted/comment text opaque to a call match.
23
+ function skipOpaque(sql, i) {
24
+ var ch = sql[i];
25
+ if (ch === "'" || ch === '"') {
26
+ var j = i + 1;
27
+ while(j < sql.length){
28
+ if (sql[j] === ch) {
29
+ if (sql[j + 1] === ch) {
30
+ j += 2;
31
+ continue;
32
+ }
33
+ return j + 1;
34
+ }
35
+ j++;
36
+ }
37
+ return j; // unterminated literal: consume to end rather than loop forever
38
+ }
39
+ if (ch === '-' && sql[i + 1] === '-') {
40
+ var nl = sql.indexOf('\n', i);
41
+ return nl === -1 ? sql.length : nl + 1;
42
+ }
43
+ if (ch === '/' && sql[i + 1] === '*') {
44
+ var close = sql.indexOf('*/', i + 2);
45
+ return close === -1 ? sql.length : close + 2;
46
+ }
47
+ return null;
48
+ }
49
+ // `?N`/named placeholders bind by number/name, so repeating one is safe; an anonymous `?` takes
50
+ // the next slot per occurrence, so it's numbered here first -- sqlHas/sqlBasename duplicate their arguments.
51
+ function numberPlaceholders(sql) {
52
+ var out = '';
53
+ var i = 0;
54
+ var n = 0;
55
+ while(i < sql.length){
56
+ var _sql_;
57
+ var skip = skipOpaque(sql, i);
58
+ if (skip !== null) {
59
+ out += sql.slice(i, skip);
60
+ i = skip;
61
+ continue;
62
+ }
63
+ if (sql[i] === '?' && !/[0-9]/.test((_sql_ = sql[i + 1]) !== null && _sql_ !== void 0 ? _sql_ : '')) {
64
+ n++;
65
+ out += "?".concat(n);
66
+ i++;
67
+ continue;
68
+ }
69
+ out += sql[i];
70
+ i++;
71
+ }
72
+ return out;
73
+ }
74
+ // The un-rewritten argument texts of the call whose '(' sits at parenStart, and the index just
75
+ // past its matching ')'. Paren depth is tracked so a nested call's commas/parens aren't mistaken for ours.
76
+ function readArgs(sql, parenStart) {
77
+ var args = [];
78
+ var depth = 1;
79
+ var cur = '';
80
+ var i = parenStart + 1;
81
+ while(i < sql.length){
82
+ var skip = skipOpaque(sql, i);
83
+ if (skip !== null) {
84
+ cur += sql.slice(i, skip);
85
+ i = skip;
86
+ continue;
87
+ }
88
+ var ch = sql[i];
89
+ if (ch === '(') {
90
+ depth++;
91
+ cur += ch;
92
+ i++;
93
+ continue;
94
+ }
95
+ if (ch === ')') {
96
+ depth--;
97
+ i++;
98
+ if (depth === 0) break;
99
+ cur += ch;
100
+ continue;
101
+ }
102
+ if (ch === ',' && depth === 1) {
103
+ args.push(cur.trim());
104
+ cur = '';
105
+ i++;
106
+ continue;
107
+ }
108
+ cur += ch;
109
+ i++;
110
+ }
111
+ if (depth !== 0) throw new Error('turso: unterminated argument list starting at "'.concat(sql.slice(parenStart, parenStart + 30), '..."'));
112
+ if (cur.trim() !== '') args.push(cur.trim());
113
+ return {
114
+ args: args,
115
+ end: i
116
+ };
117
+ }
118
+ // field.startsWith('[') && JSON.parse(field) is an array, matched by membership; every other
119
+ // field, stringified, matched by substring (sql-functions.ts's hasImpl, mirrored branch for branch).
120
+ function sqlHas(fieldExpr, valueExpr) {
121
+ var isArray = "substr(".concat(fieldExpr, ",1,1) = '[' AND json_valid(").concat(fieldExpr, ")");
122
+ // json_each's argument is re-guarded by its own CASE (falling back to '[]'): turso evaluates a
123
+ // CASE branch's table function even when untaken, and a non-array argument there raises rather than yielding 0 rows (spike-verified).
124
+ return "(CASE\n WHEN ".concat(fieldExpr, " IS NULL THEN 0\n WHEN ").concat(isArray, " THEN\n (SELECT COUNT(*) FROM json_each(CASE WHEN ").concat(isArray, " THEN ").concat(fieldExpr, " ELSE '[]' END) je WHERE CAST(je.value AS TEXT) = CAST(").concat(valueExpr, " AS TEXT)) > 0\n ELSE instr(CAST(").concat(fieldExpr, " AS TEXT), CAST(").concat(valueExpr, " AS TEXT)) > 0\n END)");
125
+ }
126
+ // posix.basename(String(path)), suffix stripped Unix-style (sql-functions.ts's basenameImpl). No
127
+ // last-'/' primitive exists, so reverse() finds the first '/' from the end, then reverse() restores order.
128
+ function sqlBasename(pathExpr, suffixExpr) {
129
+ var trimmed = "rtrim(CAST(".concat(pathExpr, " AS TEXT), '/')");
130
+ var name = "CASE\n WHEN ".concat(trimmed, " = '' THEN ''\n WHEN instr(").concat(trimmed, ", '/') = 0 THEN ").concat(trimmed, "\n ELSE reverse(substr(reverse(").concat(trimmed, "), 1, instr(reverse(").concat(trimmed, "), '/') - 1))\n END");
131
+ return "(CASE WHEN ".concat(pathExpr, " IS NULL THEN NULL ELSE\n (CASE WHEN ").concat(suffixExpr, " IS NOT NULL AND CAST(").concat(suffixExpr, " AS TEXT) != '' AND CAST(").concat(suffixExpr, " AS TEXT) != (").concat(name, ")\n AND substr((").concat(name, "), -length(CAST(").concat(suffixExpr, " AS TEXT))) = CAST(").concat(suffixExpr, " AS TEXT)\n THEN substr((").concat(name, "), 1, length((").concat(name, ")) - length(CAST(").concat(suffixExpr, " AS TEXT)))\n ELSE (").concat(name, ") END)\n END)");
132
+ }
133
+ function rewriteFunctions(sql) {
134
+ if (!CALL_ANYWHERE.test(sql)) return sql;
135
+ // Numbered once, over the whole statement, before any argument is duplicated below -- rewrite()
136
+ // recurses over already-numbered substrings, never renumbering them a second time.
137
+ return rewrite(numberPlaceholders(sql));
138
+ }
139
+ function rewrite(sql) {
140
+ var out = '';
141
+ var i = 0;
142
+ while(i < sql.length){
143
+ var skip = skipOpaque(sql, i);
144
+ if (skip !== null) {
145
+ out += sql.slice(i, skip);
146
+ i = skip;
147
+ continue;
148
+ }
149
+ var m = !isWordChar(sql[i - 1]) ? CALL_AT_START.exec(sql.slice(i)) : null;
150
+ if (m) {
151
+ var name = m[1].toLowerCase();
152
+ var parenStart = i + m[0].length - 1;
153
+ if (name === 'segment') {
154
+ throw new _errorsts.SenseError('STORE_CAPABILITY_MISSING', 'store "turso" does not implement segment() as a SQL function in this build (its client cannot register UDFs); rephrase the query without it, or set "store" to "sqlite" in this tree\'s config to run it as written');
155
+ }
156
+ var _readArgs = readArgs(sql, parenStart), args = _readArgs.args, end = _readArgs.end;
157
+ var rewrittenArgs = args.map(rewrite);
158
+ if (name === 'has') {
159
+ if (rewrittenArgs.length !== 2) throw new Error("turso: has() takes exactly 2 arguments (field, value), got ".concat(rewrittenArgs.length));
160
+ out += sqlHas(rewrittenArgs[0], rewrittenArgs[1]);
161
+ } else {
162
+ var _rewrittenArgs_;
163
+ if (rewrittenArgs.length < 1 || rewrittenArgs.length > 2) throw new Error("turso: basename() takes 1 or 2 arguments (path, suffix?), got ".concat(rewrittenArgs.length));
164
+ out += sqlBasename(rewrittenArgs[0], (_rewrittenArgs_ = rewrittenArgs[1]) !== null && _rewrittenArgs_ !== void 0 ? _rewrittenArgs_ : 'NULL');
165
+ }
166
+ i = end;
167
+ continue;
168
+ }
169
+ out += sql[i];
170
+ i++;
171
+ }
172
+ return out;
173
+ }
174
+ /* 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/turso/sql-functions.ts"],"sourcesContent":["import { SenseError } from '../../errors.ts';\n\n// Turso can't register UDFs: has()/basename() are rewritten into portable SQL below; segment()\n// (Intl.Segmenter grapheme clustering, types.ts's 'segment' capability) has none, so it's rejected like an unsupported FTS5 operator.\n\n// Non-global: recursion (readArgs' contents rewritten via rewriteFunctions) reenters this module's\n// regexes before the outer scan resumes, and a global regex's lastIndex does not nest across that.\nconst CALL_ANYWHERE = /\\b(has|basename|segment)\\s*\\(/i;\nconst CALL_AT_START = /^(has|basename|segment)\\s*\\(/i;\n\nfunction isWordChar(ch: string | undefined): boolean {\n return ch !== undefined && /[A-Za-z0-9_]/.test(ch);\n}\n\n// The index just past the quoted literal or SQL comment starting at i, or null if i starts\n// neither. Shared by the scan and readArgs so both leave quoted/comment text opaque to a call match.\nfunction skipOpaque(sql: string, i: number): number | null {\n const ch = sql[i];\n if (ch === \"'\" || ch === '\"') {\n let j = i + 1;\n while (j < sql.length) {\n if (sql[j] === ch) {\n if (sql[j + 1] === ch) {\n j += 2;\n continue;\n }\n return j + 1;\n }\n j++;\n }\n return j; // unterminated literal: consume to end rather than loop forever\n }\n if (ch === '-' && sql[i + 1] === '-') {\n const nl = sql.indexOf('\\n', i);\n return nl === -1 ? sql.length : nl + 1;\n }\n if (ch === '/' && sql[i + 1] === '*') {\n const close = sql.indexOf('*/', i + 2);\n return close === -1 ? sql.length : close + 2;\n }\n return null;\n}\n\n// `?N`/named placeholders bind by number/name, so repeating one is safe; an anonymous `?` takes\n// the next slot per occurrence, so it's numbered here first -- sqlHas/sqlBasename duplicate their arguments.\nfunction numberPlaceholders(sql: string): string {\n let out = '';\n let i = 0;\n let n = 0;\n while (i < sql.length) {\n const skip = skipOpaque(sql, i);\n if (skip !== null) {\n out += sql.slice(i, skip);\n i = skip;\n continue;\n }\n if (sql[i] === '?' && !/[0-9]/.test(sql[i + 1] ?? '')) {\n n++;\n out += `?${n}`;\n i++;\n continue;\n }\n out += sql[i];\n i++;\n }\n return out;\n}\n\n// The un-rewritten argument texts of the call whose '(' sits at parenStart, and the index just\n// past its matching ')'. Paren depth is tracked so a nested call's commas/parens aren't mistaken for ours.\nfunction readArgs(sql: string, parenStart: number): { args: string[]; end: number } {\n const args: string[] = [];\n let depth = 1;\n let cur = '';\n let i = parenStart + 1;\n while (i < sql.length) {\n const skip = skipOpaque(sql, i);\n if (skip !== null) {\n cur += sql.slice(i, skip);\n i = skip;\n continue;\n }\n const ch = sql[i];\n if (ch === '(') {\n depth++;\n cur += ch;\n i++;\n continue;\n }\n if (ch === ')') {\n depth--;\n i++;\n if (depth === 0) break;\n cur += ch;\n continue;\n }\n if (ch === ',' && depth === 1) {\n args.push(cur.trim());\n cur = '';\n i++;\n continue;\n }\n cur += ch;\n i++;\n }\n if (depth !== 0) throw new Error(`turso: unterminated argument list starting at \"${sql.slice(parenStart, parenStart + 30)}...\"`);\n if (cur.trim() !== '') args.push(cur.trim());\n return { args, end: i };\n}\n\n// field.startsWith('[') && JSON.parse(field) is an array, matched by membership; every other\n// field, stringified, matched by substring (sql-functions.ts's hasImpl, mirrored branch for branch).\nfunction sqlHas(fieldExpr: string, valueExpr: string): string {\n const isArray = `substr(${fieldExpr},1,1) = '[' AND json_valid(${fieldExpr})`;\n // json_each's argument is re-guarded by its own CASE (falling back to '[]'): turso evaluates a\n // CASE branch's table function even when untaken, and a non-array argument there raises rather than yielding 0 rows (spike-verified).\n return `(CASE\n WHEN ${fieldExpr} IS NULL THEN 0\n WHEN ${isArray} THEN\n (SELECT COUNT(*) FROM json_each(CASE WHEN ${isArray} THEN ${fieldExpr} ELSE '[]' END) je WHERE CAST(je.value AS TEXT) = CAST(${valueExpr} AS TEXT)) > 0\n ELSE instr(CAST(${fieldExpr} AS TEXT), CAST(${valueExpr} AS TEXT)) > 0\n END)`;\n}\n\n// posix.basename(String(path)), suffix stripped Unix-style (sql-functions.ts's basenameImpl). No\n// last-'/' primitive exists, so reverse() finds the first '/' from the end, then reverse() restores order.\nfunction sqlBasename(pathExpr: string, suffixExpr: string): string {\n const trimmed = `rtrim(CAST(${pathExpr} AS TEXT), '/')`;\n const name = `CASE\n WHEN ${trimmed} = '' THEN ''\n WHEN instr(${trimmed}, '/') = 0 THEN ${trimmed}\n ELSE reverse(substr(reverse(${trimmed}), 1, instr(reverse(${trimmed}), '/') - 1))\n END`;\n return `(CASE WHEN ${pathExpr} IS NULL THEN NULL ELSE\n (CASE WHEN ${suffixExpr} IS NOT NULL AND CAST(${suffixExpr} AS TEXT) != '' AND CAST(${suffixExpr} AS TEXT) != (${name})\n AND substr((${name}), -length(CAST(${suffixExpr} AS TEXT))) = CAST(${suffixExpr} AS TEXT)\n THEN substr((${name}), 1, length((${name})) - length(CAST(${suffixExpr} AS TEXT)))\n ELSE (${name}) END)\n END)`;\n}\n\n// Rewrites every has()/basename() call into the portable SQL above, recursing into each call's own\n// arguments first so a nested `instr(basename(f.path), 'x')` resolves inside out; segment() instead raises STORE_CAPABILITY_MISSING, named, like an unsupported FTS5 operator.\nexport function rewriteFunctions(sql: string): string {\n if (!CALL_ANYWHERE.test(sql)) return sql;\n // Numbered once, over the whole statement, before any argument is duplicated below -- rewrite()\n // recurses over already-numbered substrings, never renumbering them a second time.\n return rewrite(numberPlaceholders(sql));\n}\n\nfunction rewrite(sql: string): string {\n let out = '';\n let i = 0;\n while (i < sql.length) {\n const skip = skipOpaque(sql, i);\n if (skip !== null) {\n out += sql.slice(i, skip);\n i = skip;\n continue;\n }\n const m = !isWordChar(sql[i - 1]) ? CALL_AT_START.exec(sql.slice(i)) : null;\n if (m) {\n const name = m[1].toLowerCase();\n const parenStart = i + m[0].length - 1;\n if (name === 'segment') {\n throw new SenseError('STORE_CAPABILITY_MISSING', `store \"turso\" does not implement segment() as a SQL function in this build (its client cannot register UDFs); rephrase the query without it, or set \"store\" to \"sqlite\" in this tree's config to run it as written`);\n }\n const { args, end } = readArgs(sql, parenStart);\n const rewrittenArgs = args.map(rewrite);\n if (name === 'has') {\n if (rewrittenArgs.length !== 2) throw new Error(`turso: has() takes exactly 2 arguments (field, value), got ${rewrittenArgs.length}`);\n out += sqlHas(rewrittenArgs[0], rewrittenArgs[1]);\n } else {\n if (rewrittenArgs.length < 1 || rewrittenArgs.length > 2) throw new Error(`turso: basename() takes 1 or 2 arguments (path, suffix?), got ${rewrittenArgs.length}`);\n out += sqlBasename(rewrittenArgs[0], rewrittenArgs[1] ?? 'NULL');\n }\n i = end;\n continue;\n }\n out += sql[i];\n i++;\n }\n return out;\n}\n"],"names":["rewriteFunctions","CALL_ANYWHERE","CALL_AT_START","isWordChar","ch","undefined","test","skipOpaque","sql","i","j","length","nl","indexOf","close","numberPlaceholders","out","n","skip","slice","readArgs","parenStart","args","depth","cur","push","trim","Error","end","sqlHas","fieldExpr","valueExpr","isArray","sqlBasename","pathExpr","suffixExpr","trimmed","name","rewrite","m","exec","toLowerCase","SenseError","rewrittenArgs","map"],"mappings":"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"}
@@ -23,6 +23,7 @@ var _vectorsts = require("../vectors.js");
23
23
  var _connectionts = require("./connection.js");
24
24
  var _fieldStatsts = require("./fieldStats.js");
25
25
  var _lexicalts = require("./lexical.js");
26
+ var _sqlfunctionsts = require("./sql-functions.js");
26
27
  var _vectorsts1 = require("./vectors.js");
27
28
  function _array_like_to_array(arr, len) {
28
29
  if (len == null || len > arr.length) len = arr.length;
@@ -363,10 +364,11 @@ function _wrap_async_generator(fn) {
363
364
  };
364
365
  }
365
366
  var CAPABILITIES = new Set([
366
- 'lexical',
367
- 'phrases',
368
367
  'vectors'
369
368
  ]);
369
+ // close() reclaims once the cache file outgrows its compact size by this factor: the disk
370
+ // overhead a user should accept (PLAN 3.52), in postgres autovacuum scale-factor shape.
371
+ var BLOAT_FACTOR = 1.5;
370
372
  function createStore(db, conn) {
371
373
  return {
372
374
  name: 'turso',
@@ -512,7 +514,7 @@ function createStore(db, conn) {
512
514
  case 0:
513
515
  return [
514
516
  4,
515
- db.prepare(sql)
517
+ db.prepare((0, _sqlfunctionsts.rewriteFunctions)(sql))
516
518
  ];
517
519
  case 1:
518
520
  stmt = _state.sent();
@@ -555,21 +557,120 @@ function createStore(db, conn) {
555
557
  },
556
558
  close: function close() {
557
559
  return _async_to_generator(function() {
560
+ var reclaimPath, _ref, path, base, size, _tmp, err;
558
561
  return _ts_generator(this, function(_state) {
559
562
  switch(_state.label){
560
563
  case 0:
564
+ // Checkpoint before measuring: the last reconcile's pages sit in the WAL, not the file yet.
561
565
  return [
562
566
  4,
563
567
  (0, _connectionts.checkpointWal)(db)
564
568
  ];
565
569
  case 1:
566
570
  _state.sent();
571
+ reclaimPath = null;
572
+ _state.label = 2;
573
+ case 2:
574
+ _state.trys.push([
575
+ 2,
576
+ 12,
577
+ ,
578
+ 13
579
+ ]);
580
+ return [
581
+ 4,
582
+ (0, _connectionts.cacheFilePath)(conn)
583
+ ];
584
+ case 3:
585
+ path = _state.sent();
586
+ return [
587
+ 4,
588
+ (0, _sharedts.getMeta)(conn, 'compact_size')
589
+ ];
590
+ case 4:
591
+ base = Number.apply(void 0, [
592
+ (_ref = _state.sent()) !== null && _ref !== void 0 ? _ref : '0'
593
+ ]);
594
+ if (!(path === null)) return [
595
+ 3,
596
+ 5
597
+ ];
598
+ _tmp = null;
599
+ return [
600
+ 3,
601
+ 7
602
+ ];
603
+ case 5:
604
+ return [
605
+ 4,
606
+ (0, _connectionts.fileSize)(path)
607
+ ];
608
+ case 6:
609
+ _tmp = _state.sent();
610
+ _state.label = 7;
611
+ case 7:
612
+ size = _tmp;
613
+ if (!(size !== null)) return [
614
+ 3,
615
+ 11
616
+ ];
617
+ if (!(base === 0)) return [
618
+ 3,
619
+ 10
620
+ ];
621
+ return [
622
+ 4,
623
+ (0, _sharedts.setMeta)(conn, 'compact_size', String(size))
624
+ ];
625
+ case 8:
626
+ _state.sent();
627
+ // The meta write landed past the checkpoint; leave no WAL for the next opener.
628
+ return [
629
+ 4,
630
+ (0, _connectionts.checkpointWal)(db)
631
+ ];
632
+ case 9:
633
+ _state.sent();
634
+ return [
635
+ 3,
636
+ 11
637
+ ];
638
+ case 10:
639
+ if (size > BLOAT_FACTOR * base) {
640
+ reclaimPath = path;
641
+ }
642
+ _state.label = 11;
643
+ case 11:
644
+ return [
645
+ 3,
646
+ 13
647
+ ];
648
+ case 12:
649
+ err = _state.sent();
650
+ console.error("sense: turso cache bloat check failed, the cache will keep its space until one succeeds: ".concat(err.message));
651
+ return [
652
+ 3,
653
+ 13
654
+ ];
655
+ case 13:
567
656
  return [
568
657
  4,
569
658
  db.close()
570
659
  ];
571
- case 2:
660
+ case 14:
661
+ _state.sent();
662
+ if (!(reclaimPath !== null)) return [
663
+ 3,
664
+ 16
665
+ ];
666
+ return [
667
+ 4,
668
+ (0, _connectionts.reclaimSpace)(reclaimPath)
669
+ ];
670
+ case 15:
572
671
  _state.sent();
672
+ _state.label = 16;
673
+ case 16:
573
674
  return [
574
675
  2
575
676
  ];
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/turso/store.ts"],"sourcesContent":["import type { Database } from '@tursodatabase/database';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store } from '../types.ts';\nimport { hasVectorRow, pendingRows } from '../vectors.ts';\nimport { checkpointWal } from './connection.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { queryLexical } from './lexical.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\n// No 'snippets': fts_highlight returns the whole column, not a bounded window, so hits use\n// the caller's JS excerpt.\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['lexical', 'phrases', 'vectors']);\n\n// Shares one Connection instance (conn) with the builder's own reconcile call so transaction depth\n// (see transaction.ts) is tracked against the same object everywhere.\nexport function createStore(db: Database, conn: Connection): Store {\n return {\n name: 'turso',\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 docs: {\n async columns() {\n return [...(await getColumns(conn))];\n },\n fieldStats: (columns, scopeWhere) => fieldStats(conn, columns, scopeWhere),\n },\n lexical: {\n query: (terms, opts) => queryLexical(conn, terms, opts),\n },\n // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the\n // interface's per-call storeDims -- see vectors.ts's padded() for why a shorter vector is still correct against a wider column.\n vectors: {\n pending: () => pendingRows(conn),\n writeVectors: (rows) => writeVectorBatch(conn, STORE_DIMS, rows),\n candidates: (qv, _storeDims, fetch, allowed) => scanCandidates(conn, qv, STORE_DIMS, fetch, allowed),\n similar: (path, opts) => scanSimilar(conn, STORE_DIMS, path, opts),\n hasVector: (path) => hasVectorRow(conn, path),\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). Turso's PRAGMA busy_timeout names its column \"busy_timeout\" (spike-verified), not \"timeout\" like real SQLite.\n const row = (await (await db.prepare('PRAGMA busy_timeout')).get()) as { busy_timeout: number };\n return { busy_timeout: `${row.busy_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 = await db.prepare(sql);\n stmt.safeIntegers(true); // int64 past 2^53 arrives as BigInt instead of losing precision\n return {\n columns: () => stmt.columns(),\n // sense sql streams through the client's own async generator.\n iterate: async function* (...params: unknown[]) {\n yield* stmt.iterate(...params);\n },\n };\n },\n },\n async close() {\n await checkpointWal(db);\n await db.close();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","db","conn","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","opts","queryLexical","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","STORE_DIMS","candidates","qv","_storeDims","fetch","allowed","scanCandidates","similar","path","scanSimilar","hasVector","hasVectorRow","engineStatus","row","get","busy_timeout","raw","stmt","safeIntegers","iterate","params","close","checkpointWal"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/turso/store.ts"],"sourcesContent":["import type { Database } from '@tursodatabase/database';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { getColumns, getMeta, setMeta } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store } from '../types.ts';\nimport { hasVectorRow, pendingRows } from '../vectors.ts';\nimport { cacheFilePath, checkpointWal, fileSize, reclaimSpace } from './connection.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { queryLexical } from './lexical.ts';\nimport { rewriteFunctions } from './sql-functions.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\n// No 'segment': has()/basename() resolve via SQL rewrite below (sql-functions.ts), but segment() has no SQL form and the client cannot register it as a UDF.\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['vectors']);\n\n// close() reclaims once the cache file outgrows its compact size by this factor: the disk\n// overhead a user should accept (PLAN 3.52), in postgres autovacuum scale-factor shape.\nconst BLOAT_FACTOR = 1.5;\n\n// Shares one Connection instance (conn) with the builder's own reconcile call so transaction depth\n// (see transaction.ts) is tracked against the same object everywhere.\nexport function createStore(db: Database, conn: Connection): Store {\n return {\n name: 'turso',\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 docs: {\n async columns() {\n return [...(await getColumns(conn))];\n },\n fieldStats: (columns, scopeWhere) => fieldStats(conn, columns, scopeWhere),\n },\n lexical: {\n query: (terms, opts) => queryLexical(conn, terms, opts),\n },\n // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the\n // interface's per-call storeDims -- see vectors.ts's padded() for why a shorter vector is still correct against a wider column.\n vectors: {\n pending: () => pendingRows(conn),\n writeVectors: (rows) => writeVectorBatch(conn, STORE_DIMS, rows),\n candidates: (qv, _storeDims, fetch, allowed) => scanCandidates(conn, qv, STORE_DIMS, fetch, allowed),\n similar: (path, opts) => scanSimilar(conn, STORE_DIMS, path, opts),\n hasVector: (path) => hasVectorRow(conn, path),\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). Turso's PRAGMA busy_timeout names its column \"busy_timeout\" (spike-verified), not \"timeout\" like real SQLite.\n const row = (await (await db.prepare('PRAGMA busy_timeout')).get()) as { busy_timeout: number };\n return { busy_timeout: `${row.busy_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 = await db.prepare(rewriteFunctions(sql));\n stmt.safeIntegers(true); // int64 past 2^53 arrives as BigInt instead of losing precision\n return {\n columns: () => stmt.columns(),\n // sense sql streams through the client's own async generator.\n iterate: async function* (...params: unknown[]) {\n yield* stmt.iterate(...params);\n },\n };\n },\n },\n async close() {\n // Checkpoint before measuring: the last reconcile's pages sit in the WAL, not the file yet.\n await checkpointWal(db);\n let reclaimPath: string | null = null;\n try {\n const path = await cacheFilePath(conn);\n const base = Number((await getMeta(conn, 'compact_size')) ?? '0');\n const size = path === null ? null : await fileSize(path);\n if (size !== null) {\n // No baseline yet (cold build or an upgraded cache): record it, never reclaim here, so a\n // cold build pays no VACUUM (PLAN 3.49 Track A) and an upgraded cache heals on a crossing.\n if (base === 0) {\n await setMeta(conn, 'compact_size', String(size));\n // The meta write landed past the checkpoint; leave no WAL for the next opener.\n await checkpointWal(db);\n } else if (size > BLOAT_FACTOR * base) {\n reclaimPath = path;\n }\n }\n } catch (err) {\n console.error(`sense: turso cache bloat check failed, the cache will keep its space until one succeeds: ${(err as Error).message}`);\n }\n await db.close();\n // After this store's connection is closed, never before: turso hands the file to one\n // connection at a time, and reclaimSpace opens its own to carry the `vacuum` flag (PLAN 3.54).\n if (reclaimPath !== null) await reclaimSpace(reclaimPath);\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","BLOAT_FACTOR","db","conn","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","opts","queryLexical","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","STORE_DIMS","candidates","qv","_storeDims","fetch","allowed","scanCandidates","similar","path","scanSimilar","hasVector","hasVectorRow","engineStatus","row","get","busy_timeout","raw","stmt","rewriteFunctions","safeIntegers","iterate","params","close","reclaimPath","base","size","err","checkpointWal","cacheFilePath","getMeta","Number","fileSize","setMeta","String","console","error","message","reclaimSpace"],"mappings":"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"}
@@ -57,6 +57,17 @@ function _async_to_generator(fn) {
57
57
  });
58
58
  };
59
59
  }
60
+ function _define_property(obj, key, value) {
61
+ if (key in obj) {
62
+ Object.defineProperty(obj, key, {
63
+ value: value,
64
+ enumerable: true,
65
+ configurable: true,
66
+ writable: true
67
+ });
68
+ } else obj[key] = value;
69
+ return obj;
70
+ }
60
71
  function _iterable_to_array(iter) {
61
72
  if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
62
73
  return Array.from(iter);
@@ -92,6 +103,21 @@ function _non_iterable_rest() {
92
103
  function _non_iterable_spread() {
93
104
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
94
105
  }
106
+ function _object_spread(target) {
107
+ for(var i = 1; i < arguments.length; i++){
108
+ var source = arguments[i] != null ? arguments[i] : {};
109
+ var ownKeys = Object.keys(source);
110
+ if (typeof Object.getOwnPropertySymbols === "function") {
111
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
112
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
113
+ }));
114
+ }
115
+ ownKeys.forEach(function(key) {
116
+ _define_property(target, key, source[key]);
117
+ });
118
+ }
119
+ return target;
120
+ }
95
121
  function _sliced_to_array(arr, i) {
96
122
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
97
123
  }
@@ -277,7 +303,7 @@ function scanCandidates(conn, qv, dims, fetch, allowed) {
277
303
  q = padded(qv, dims);
278
304
  return [
279
305
  4,
280
- conn.prepare('SELECT "path", start_line, end_line, vector FROM embeddings WHERE vector IS NOT NULL')
306
+ conn.prepare('SELECT "path", chunk, start_line, end_line, vector FROM embeddings WHERE vector IS NOT NULL ORDER BY "path", chunk')
281
307
  ];
282
308
  case 1:
283
309
  stmt = _state.sent();
@@ -295,10 +321,13 @@ function scanCandidates(conn, qv, dims, fetch, allowed) {
295
321
  if (allowed && !allowed.has(row.path)) continue;
296
322
  score = cosineSimilarity(q, decode(row.vector, dims));
297
323
  existing = best.get(row.path);
298
- if (!existing || score > existing.score) best.set(row.path, {
299
- score: score,
300
- lines: "L".concat(row.start_line, "-").concat(row.end_line)
301
- });
324
+ if (!existing || score > existing.score || score === existing.score && row.chunk < existing.chunk) {
325
+ best.set(row.path, {
326
+ score: score,
327
+ chunk: row.chunk,
328
+ lines: "L".concat(row.start_line, "-").concat(row.end_line)
329
+ });
330
+ }
302
331
  }
303
332
  } catch (err) {
304
333
  _didIteratorError = true;
@@ -316,14 +345,17 @@ function scanCandidates(conn, qv, dims, fetch, allowed) {
316
345
  }
317
346
  return [
318
347
  2,
319
- _to_consumable_array(best.entries()).sort(function(a, b) {
320
- return b[1].score - a[1].score;
321
- }).slice(0, fetch).map(function(param) {
322
- var _param = _sliced_to_array(param, 2), path = _param[0], b = _param[1];
348
+ _to_consumable_array(best.entries()).map(function(param) {
349
+ var _param = _sliced_to_array(param, 2), path = _param[0], value = _param[1];
350
+ return _object_spread({
351
+ path: path
352
+ }, value);
353
+ }).sort(_vectorsts.compareVectorScores).slice(0, fetch).map(function(param) {
354
+ var path = param.path, lines = param.lines, score = param.score;
323
355
  return {
324
356
  path: path,
325
- lines: b.lines,
326
- similarity: (0, _vectorsts.asCosine)(b.score)
357
+ lines: lines,
358
+ similarity: (0, _vectorsts.asCosine)(score)
327
359
  };
328
360
  })
329
361
  ];
@@ -418,10 +450,14 @@ function scanSimilar(conn, dims, path, opts) {
418
450
  }
419
451
  return [
420
452
  2,
421
- _to_consumable_array(best.entries()).sort(function(a, b) {
422
- return b[1] - a[1];
423
- }).slice(0, opts.k).map(function(param) {
453
+ _to_consumable_array(best.entries()).map(function(param) {
424
454
  var _param = _sliced_to_array(param, 2), p = _param[0], score = _param[1];
455
+ return {
456
+ path: p,
457
+ score: score
458
+ };
459
+ }).sort(_vectorsts.compareVectorScores).slice(0, opts.k).map(function(param) {
460
+ var p = param.path, score = param.score;
425
461
  return {
426
462
  path: p,
427
463
  similarity: (0, _vectorsts.asCosine)(score)
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/turso/vectors.ts"],"sourcesContent":["import type { Connection, VectorCandidate, VectorSimilar, VectorWriteRow } from '../types.ts';\nimport { asCosine, sampleEvenly } from '../vectors.ts';\n\n// Native F32_BLOB(dims) columns, dims fixed at DDL time (open.ts, STORE_DIMS). Both scans\n// score in JS: a per-row vector_distance_cos measured 3.5-8x slower on this row engine.\n\n// A model narrower than the column zero-pads: the added dimensions contribute nothing to\n// either dot product or norm, so cosine is unchanged.\nfunction padded(values: ArrayLike<number>, dims: number): Float32Array {\n const out = new Float32Array(dims);\n for (let d = 0; d < Math.min(values.length, dims); d++) out[d] = values[d];\n return out;\n}\n\n// A bound Float32Array stores truncated bytes with no error; a Buffer view over the same\n// bytes round-trips exact (measured 0.7.2).\nfunction toBlob(v: Float32Array): Buffer {\n return Buffer.from(v.buffer, v.byteOffset, v.byteLength);\n}\n\nfunction decode(vector: Buffer, dims: number): Float32Array {\n return new Float32Array(vector.buffer, vector.byteOffset, dims);\n}\n\n// Rows arrive int8-quantized with a per-vector scale (embed/query.ts's toStore); this store\n// dequantizes to floats, as duckdb does.\nfunction dequantize(row: VectorWriteRow, dims: number): Float32Array {\n const q = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n const out = new Float32Array(dims);\n for (let d = 0; d < Math.min(q.length, dims); d++) out[d] = q[d] * row.scale;\n return out;\n}\n\nfunction cosineSimilarity(a: Float32Array, b: Float32Array): number {\n let dot = 0;\n let na = 0;\n let nb = 0;\n for (let d = 0; d < a.length; d++) {\n dot += a[d] * b[d];\n na += a[d] * a[d];\n nb += b[d] * b[d];\n }\n return dot / (Math.sqrt(na) * Math.sqrt(nb) + 1e-32);\n}\n\n// `scale` stays NULL: the column exists so the row shape matches the other stores, and\n// cosine is scale-invariant once the value is dequantized here.\nexport async function writeVectorBatch(conn: Connection, dims: number, rows: VectorWriteRow[]): Promise<void> {\n if (rows.length === 0) return;\n await conn.runBatch(\n 'UPDATE embeddings SET vector = ? WHERE \"path\" = ? AND chunk = ?',\n rows.map((row) => [toBlob(dequantize(row, dims)), row.path, row.chunk])\n );\n}\n\n// Best chunk per file by cosine. GROUP BY with MIN() cannot do this on 0.7.2: the aggregate\n// is right but the bare start_line/end_line come from an arbitrary row in the group.\nexport async function scanCandidates(conn: Connection, qv: Float32Array, dims: number, fetch: number, allowed?: Set<string>): Promise<VectorCandidate[]> {\n const q = padded(qv, dims);\n const stmt = await conn.prepare('SELECT \"path\", start_line, end_line, vector FROM embeddings WHERE vector IS NOT NULL');\n const rows = (await stmt.all()) as Array<{ path: string; start_line: number; end_line: number; vector: Buffer }>;\n\n const best = new Map<string, { score: number; lines: string }>();\n for (const row of rows) {\n if (allowed && !allowed.has(row.path)) continue;\n const score = cosineSimilarity(q, decode(row.vector, dims));\n const existing = best.get(row.path);\n if (!existing || score > existing.score) best.set(row.path, { score, lines: `L${row.start_line}-${row.end_line}` });\n }\n return [...best.entries()]\n .sort((a, b) => b[1].score - a[1].score)\n .slice(0, fetch)\n .map(([path, b]) => ({ path, lines: b.lines, similarity: asCosine(b.score) }));\n}\n\n// Max cosine over (target chunk, other chunk) pairs. The SQL cross-join duckdb uses measured\n// 6-8x slower here at 26k chunks (2026-08-30).\nexport async function scanSimilar(conn: Connection, dims: number, path: string, opts: { exclude: Set<string>; allowed?: Set<string>; k: number }): Promise<VectorSimilar[]> {\n if (opts.allowed && opts.allowed.size === 0) return [];\n const targetStmt = await conn.prepare('SELECT vector FROM embeddings WHERE \"path\" = ? AND vector IS NOT NULL ORDER BY chunk');\n const targetRows = (await targetStmt.all(path)) as Array<{ vector: Buffer }>;\n if (targetRows.length === 0) return [];\n const targets = sampleEvenly(targetRows).map((row) => decode(row.vector, dims));\n\n const stmt = await conn.prepare('SELECT \"path\", vector FROM embeddings WHERE vector IS NOT NULL');\n const rows = (await stmt.all()) as Array<{ path: string; vector: Buffer }>;\n const best = new Map<string, number>();\n for (const row of rows) {\n if (row.path === path || opts.exclude.has(row.path) || (opts.allowed && !opts.allowed.has(row.path))) continue;\n const other = decode(row.vector, dims);\n for (const t of targets) {\n const score = cosineSimilarity(t, other);\n const existing = best.get(row.path);\n if (existing === undefined || score > existing) best.set(row.path, score);\n }\n }\n\n return [...best.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, opts.k)\n .map(([p, score]) => ({ path: p, similarity: asCosine(score) }));\n}\n"],"names":["scanCandidates","scanSimilar","writeVectorBatch","padded","values","dims","out","Float32Array","d","Math","min","length","toBlob","v","Buffer","from","buffer","byteOffset","byteLength","decode","vector","dequantize","row","q","Int8Array","scale","cosineSimilarity","a","b","dot","na","nb","sqrt","conn","rows","runBatch","map","path","chunk","qv","fetch","allowed","stmt","best","score","existing","prepare","all","Map","has","get","set","lines","start_line","end_line","entries","sort","slice","similarity","asCosine","opts","targetStmt","targetRows","targets","other","t","size","sampleEvenly","exclude","undefined","k","p"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/turso/vectors.ts"],"sourcesContent":["import type { Connection, VectorCandidate, VectorSimilar, VectorWriteRow } from '../types.ts';\nimport { asCosine, compareVectorScores, sampleEvenly } from '../vectors.ts';\n\n// Native F32_BLOB(dims) columns, dims fixed at DDL time (open.ts, STORE_DIMS). Both scans\n// score in JS: a per-row vector_distance_cos measured 3.5-8x slower on this row engine.\n\n// A model narrower than the column zero-pads: the added dimensions contribute nothing to\n// either dot product or norm, so cosine is unchanged.\nfunction padded(values: ArrayLike<number>, dims: number): Float32Array {\n const out = new Float32Array(dims);\n for (let d = 0; d < Math.min(values.length, dims); d++) out[d] = values[d];\n return out;\n}\n\n// A bound Float32Array stores truncated bytes with no error; a Buffer view over the same\n// bytes round-trips exact (measured 0.7.2).\nfunction toBlob(v: Float32Array): Buffer {\n return Buffer.from(v.buffer, v.byteOffset, v.byteLength);\n}\n\nfunction decode(vector: Buffer, dims: number): Float32Array {\n return new Float32Array(vector.buffer, vector.byteOffset, dims);\n}\n\n// Rows arrive int8-quantized with a per-vector scale (embed/query.ts's toStore); this store\n// dequantizes to floats, as duckdb does.\nfunction dequantize(row: VectorWriteRow, dims: number): Float32Array {\n const q = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n const out = new Float32Array(dims);\n for (let d = 0; d < Math.min(q.length, dims); d++) out[d] = q[d] * row.scale;\n return out;\n}\n\nfunction cosineSimilarity(a: Float32Array, b: Float32Array): number {\n let dot = 0;\n let na = 0;\n let nb = 0;\n for (let d = 0; d < a.length; d++) {\n dot += a[d] * b[d];\n na += a[d] * a[d];\n nb += b[d] * b[d];\n }\n return dot / (Math.sqrt(na) * Math.sqrt(nb) + 1e-32);\n}\n\n// `scale` stays NULL: the column exists so the row shape matches the other stores, and\n// cosine is scale-invariant once the value is dequantized here.\nexport async function writeVectorBatch(conn: Connection, dims: number, rows: VectorWriteRow[]): Promise<void> {\n if (rows.length === 0) return;\n await conn.runBatch(\n 'UPDATE embeddings SET vector = ? WHERE \"path\" = ? AND chunk = ?',\n rows.map((row) => [toBlob(dequantize(row, dims)), row.path, row.chunk])\n );\n}\n\n// Best chunk per file by cosine. GROUP BY with MIN() cannot do this on 0.7.2: the aggregate\n// is right but the bare start_line/end_line come from an arbitrary row in the group.\nexport async function scanCandidates(conn: Connection, qv: Float32Array, dims: number, fetch: number, allowed?: Set<string>): Promise<VectorCandidate[]> {\n const q = padded(qv, dims);\n const stmt = await conn.prepare('SELECT \"path\", chunk, start_line, end_line, vector FROM embeddings WHERE vector IS NOT NULL ORDER BY \"path\", chunk');\n const rows = (await stmt.all()) as Array<{ path: string; chunk: number; start_line: number; end_line: number; vector: Buffer }>;\n\n const best = new Map<string, { score: number; chunk: number; lines: string }>();\n for (const row of rows) {\n if (allowed && !allowed.has(row.path)) continue;\n const score = cosineSimilarity(q, decode(row.vector, dims));\n const existing = best.get(row.path);\n if (!existing || score > existing.score || (score === existing.score && row.chunk < existing.chunk)) {\n best.set(row.path, { score, chunk: row.chunk, lines: `L${row.start_line}-${row.end_line}` });\n }\n }\n return [...best.entries()]\n .map(([path, value]) => ({ path, ...value }))\n .sort(compareVectorScores)\n .slice(0, fetch)\n .map(({ path, lines, score }) => ({ path, lines, similarity: asCosine(score) }));\n}\n\n// Max cosine over (target chunk, other chunk) pairs. The SQL cross-join duckdb uses measured\n// 6-8x slower here at 26k chunks (2026-08-30).\nexport async function scanSimilar(conn: Connection, dims: number, path: string, opts: { exclude: Set<string>; allowed?: Set<string>; k: number }): Promise<VectorSimilar[]> {\n if (opts.allowed && opts.allowed.size === 0) return [];\n const targetStmt = await conn.prepare('SELECT vector FROM embeddings WHERE \"path\" = ? AND vector IS NOT NULL ORDER BY chunk');\n const targetRows = (await targetStmt.all(path)) as Array<{ vector: Buffer }>;\n if (targetRows.length === 0) return [];\n const targets = sampleEvenly(targetRows).map((row) => decode(row.vector, dims));\n\n const stmt = await conn.prepare('SELECT \"path\", vector FROM embeddings WHERE vector IS NOT NULL');\n const rows = (await stmt.all()) as Array<{ path: string; vector: Buffer }>;\n const best = new Map<string, number>();\n for (const row of rows) {\n if (row.path === path || opts.exclude.has(row.path) || (opts.allowed && !opts.allowed.has(row.path))) continue;\n const other = decode(row.vector, dims);\n for (const t of targets) {\n const score = cosineSimilarity(t, other);\n const existing = best.get(row.path);\n if (existing === undefined || score > existing) best.set(row.path, score);\n }\n }\n\n return [...best.entries()]\n .map(([p, score]) => ({ path: p, score }))\n .sort(compareVectorScores)\n .slice(0, opts.k)\n .map(({ path: p, score }) => ({ path: p, similarity: asCosine(score) }));\n}\n"],"names":["scanCandidates","scanSimilar","writeVectorBatch","padded","values","dims","out","Float32Array","d","Math","min","length","toBlob","v","Buffer","from","buffer","byteOffset","byteLength","decode","vector","dequantize","row","q","Int8Array","scale","cosineSimilarity","a","b","dot","na","nb","sqrt","conn","rows","runBatch","map","path","chunk","qv","fetch","allowed","stmt","best","score","existing","prepare","all","Map","has","get","set","lines","start_line","end_line","entries","value","sort","compareVectorScores","slice","similarity","asCosine","opts","targetStmt","targetRows","targets","other","t","size","sampleEvenly","exclude","undefined","p","k"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import type { Config, ResolvedConfig, StoreName } from '../config/index.js';
2
2
  import type { ReconcileDelta } from '../features/types.js';
3
3
  import type { ParsedDoc } from '../scan/index.js';
4
- export declare const CAPABILITY_NAMES: readonly ["phrases", "snippets", "lexical", "vectors", "sql-functions"];
4
+ export declare const CAPABILITY_NAMES: readonly ["vectors", "segment"];
5
5
  export type Capability = (typeof CAPABILITY_NAMES)[number];
6
6
  export interface RunResult {
7
7
  changes: number | bigint;
@@ -55,7 +55,6 @@ export interface DocumentStore {
55
55
  }
56
56
  export interface LexicalHit {
57
57
  path: string;
58
- hit: string | null;
59
58
  }
60
59
  export interface LexicalQueryOptions {
61
60
  whereJoin: string;
@@ -1,7 +1,7 @@
1
1
  import type { Config, ResolvedConfig, StoreName } from '../config/index.js';
2
2
  import type { ReconcileDelta } from '../features/types.js';
3
3
  import type { ParsedDoc } from '../scan/index.js';
4
- export declare const CAPABILITY_NAMES: readonly ["phrases", "snippets", "lexical", "vectors", "sql-functions"];
4
+ export declare const CAPABILITY_NAMES: readonly ["vectors", "segment"];
5
5
  export type Capability = (typeof CAPABILITY_NAMES)[number];
6
6
  export interface RunResult {
7
7
  changes: number | bigint;
@@ -55,7 +55,6 @@ export interface DocumentStore {
55
55
  }
56
56
  export interface LexicalHit {
57
57
  path: string;
58
- hit: string | null;
59
58
  }
60
59
  export interface LexicalQueryOptions {
61
60
  whereJoin: string;
@@ -11,10 +11,7 @@ Object.defineProperty(exports, "CAPABILITY_NAMES", {
11
11
  }
12
12
  });
13
13
  var CAPABILITY_NAMES = [
14
- 'phrases',
15
- 'snippets',
16
- 'lexical',
17
14
  'vectors',
18
- 'sql-functions'
15
+ 'segment'
19
16
  ];
20
17
  /* 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; }