sensemaking 0.27.0 → 0.27.1

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 (285) hide show
  1. package/dist/cjs/chunk/extract.js.map +1 -1
  2. package/dist/cjs/chunk/group.js.map +1 -1
  3. package/dist/cjs/chunk/index.js.map +1 -1
  4. package/dist/cjs/chunk/parse.js.map +1 -1
  5. package/dist/cjs/chunk/parser.js.map +1 -1
  6. package/dist/cjs/chunk/tokens.js.map +1 -1
  7. package/dist/cjs/chunk/version.js.map +1 -1
  8. package/dist/cjs/cli/build.js.map +1 -1
  9. package/dist/cjs/cli/download.js.map +1 -1
  10. package/dist/cjs/cli/index.js.map +1 -1
  11. package/dist/cjs/cli/init.js.map +1 -1
  12. package/dist/cjs/cli/map.js.map +1 -1
  13. package/dist/cjs/cli/named.js.map +1 -1
  14. package/dist/cjs/cli/path.js.map +1 -1
  15. package/dist/cjs/cli/peek.js.map +1 -1
  16. package/dist/cjs/cli/related.js.map +1 -1
  17. package/dist/cjs/cli/search.js.map +1 -1
  18. package/dist/cjs/cli/shared.js.map +1 -1
  19. package/dist/cjs/cli/sql.js.map +1 -1
  20. package/dist/cjs/cli/status.js.map +1 -1
  21. package/dist/cjs/cli/watch.js.map +1 -1
  22. package/dist/cjs/cli.js.map +1 -1
  23. package/dist/cjs/commands/index.js.map +1 -1
  24. package/dist/cjs/commands/map.js.map +1 -1
  25. package/dist/cjs/commands/path.js.map +1 -1
  26. package/dist/cjs/commands/peek.js.map +1 -1
  27. package/dist/cjs/commands/related.js.map +1 -1
  28. package/dist/cjs/commands/scope.js.map +1 -1
  29. package/dist/cjs/commands/search.js.map +1 -1
  30. package/dist/cjs/commands/signals.js.map +1 -1
  31. package/dist/cjs/commands/snapshot.js.map +1 -1
  32. package/dist/cjs/commands/status.js.map +1 -1
  33. package/dist/cjs/config/access.js.map +1 -1
  34. package/dist/cjs/config/index.js.map +1 -1
  35. package/dist/cjs/config/load.js.map +1 -1
  36. package/dist/cjs/config/resolve.js.map +1 -1
  37. package/dist/cjs/config/signals.js.map +1 -1
  38. package/dist/cjs/config/types.js.map +1 -1
  39. package/dist/cjs/config/validate.js.map +1 -1
  40. package/dist/cjs/embed/cohere.js.map +1 -1
  41. package/dist/cjs/embed/distribution.js.map +1 -1
  42. package/dist/cjs/embed/endpoint.js.map +1 -1
  43. package/dist/cjs/embed/handoff.js.map +1 -1
  44. package/dist/cjs/embed/http.js.map +1 -1
  45. package/dist/cjs/embed/identity.js.map +1 -1
  46. package/dist/cjs/embed/langfit.js.map +1 -1
  47. package/dist/cjs/embed/languages.js.map +1 -1
  48. package/dist/cjs/embed/openai.js.map +1 -1
  49. package/dist/cjs/embed/query.js.map +1 -1
  50. package/dist/cjs/embed/registry.js.map +1 -1
  51. package/dist/cjs/embed/static.js.map +1 -1
  52. package/dist/cjs/embed/store.js.map +1 -1
  53. package/dist/cjs/embed/types.js.map +1 -1
  54. package/dist/cjs/errors.js.map +1 -1
  55. package/dist/cjs/features/embed.js.map +1 -1
  56. package/dist/cjs/features/fences.js.map +1 -1
  57. package/dist/cjs/features/index.js.map +1 -1
  58. package/dist/cjs/features/links.js.map +1 -1
  59. package/dist/cjs/features/rank.js.map +1 -1
  60. package/dist/cjs/features/sections.js.map +1 -1
  61. package/dist/cjs/features/tags.js.map +1 -1
  62. package/dist/cjs/graph/graph.js.map +1 -1
  63. package/dist/cjs/graph/traverse.js.map +1 -1
  64. package/dist/cjs/index.js.map +1 -1
  65. package/dist/cjs/lib/atomic-write.js.map +1 -1
  66. package/dist/cjs/lib/guarded-tick.js.map +1 -1
  67. package/dist/cjs/lib/serial-query.js.map +1 -1
  68. package/dist/cjs/lib/watch-notification.js.map +1 -1
  69. package/dist/cjs/lib/worker-file.js.map +1 -1
  70. package/dist/cjs/output/column-hint.js.map +1 -1
  71. package/dist/cjs/output/output.js.map +1 -1
  72. package/dist/cjs/output/progress.js.map +1 -1
  73. package/dist/cjs/output/search-error.js.map +1 -1
  74. package/dist/cjs/scan/frontmatter.js.map +1 -1
  75. package/dist/cjs/scan/index.js.map +1 -1
  76. package/dist/cjs/scan/list.js.map +1 -1
  77. package/dist/cjs/scan/pool.js.map +1 -1
  78. package/dist/cjs/scan/reparse.js.map +1 -1
  79. package/dist/cjs/scan/worker-error.js.map +1 -1
  80. package/dist/cjs/store/batch.js.map +1 -1
  81. package/dist/cjs/store/builder.js.map +1 -1
  82. package/dist/cjs/store/cache.js.map +1 -1
  83. package/dist/cjs/store/duckdb/batch.js.map +1 -1
  84. package/dist/cjs/store/duckdb/connection.js.map +1 -1
  85. package/dist/cjs/store/duckdb/fieldStats.js.map +1 -1
  86. package/dist/cjs/store/duckdb/lexical.d.cts +1 -6
  87. package/dist/cjs/store/duckdb/lexical.d.ts +1 -6
  88. package/dist/cjs/store/duckdb/lexical.js +28 -39
  89. package/dist/cjs/store/duckdb/lexical.js.map +1 -1
  90. package/dist/cjs/store/duckdb/native.d.cts +1 -2
  91. package/dist/cjs/store/duckdb/native.d.ts +1 -2
  92. package/dist/cjs/store/duckdb/native.js +1 -6
  93. package/dist/cjs/store/duckdb/native.js.map +1 -1
  94. package/dist/cjs/store/duckdb/open.js.map +1 -1
  95. package/dist/cjs/store/duckdb/ordered-bm25.d.cts +3 -16
  96. package/dist/cjs/store/duckdb/ordered-bm25.d.ts +3 -16
  97. package/dist/cjs/store/duckdb/ordered-bm25.js +27 -79
  98. package/dist/cjs/store/duckdb/ordered-bm25.js.map +1 -1
  99. package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
  100. package/dist/cjs/store/duckdb/sql-functions.js.map +1 -1
  101. package/dist/cjs/store/duckdb/store.js.map +1 -1
  102. package/dist/cjs/store/duckdb/vectors.js.map +1 -1
  103. package/dist/cjs/store/embed-scope.js.map +1 -1
  104. package/dist/cjs/store/feature-scope.js.map +1 -1
  105. package/dist/cjs/store/index.js.map +1 -1
  106. package/dist/cjs/store/lock-wait.js.map +1 -1
  107. package/dist/cjs/store/native.js.map +1 -1
  108. package/dist/cjs/store/open.js.map +1 -1
  109. package/dist/cjs/store/preset-scope.js.map +1 -1
  110. package/dist/cjs/store/readiness.js.map +1 -1
  111. package/dist/cjs/store/reconcile.js.map +1 -1
  112. package/dist/cjs/store/shared.js.map +1 -1
  113. package/dist/cjs/store/signature.js.map +1 -1
  114. package/dist/cjs/store/sql-functions.js.map +1 -1
  115. package/dist/cjs/store/sqlite/connection.js.map +1 -1
  116. package/dist/cjs/store/sqlite/fieldStats.js.map +1 -1
  117. package/dist/cjs/store/sqlite/lexical.js.map +1 -1
  118. package/dist/cjs/store/sqlite/open.js.map +1 -1
  119. package/dist/cjs/store/sqlite/reconcile.js.map +1 -1
  120. package/dist/cjs/store/sqlite/sql-functions.js.map +1 -1
  121. package/dist/cjs/store/sqlite/store.js.map +1 -1
  122. package/dist/cjs/store/sqlite/vectors.js.map +1 -1
  123. package/dist/cjs/store/stages.js.map +1 -1
  124. package/dist/cjs/store/transaction.js.map +1 -1
  125. package/dist/cjs/store/turso/connection.js.map +1 -1
  126. package/dist/cjs/store/turso/fieldStats.js.map +1 -1
  127. package/dist/cjs/store/turso/lexical-text.js.map +1 -1
  128. package/dist/cjs/store/turso/lexical.js.map +1 -1
  129. package/dist/cjs/store/turso/native.js.map +1 -1
  130. package/dist/cjs/store/turso/open.js.map +1 -1
  131. package/dist/cjs/store/turso/reconcile.js.map +1 -1
  132. package/dist/cjs/store/turso/sql-functions.js.map +1 -1
  133. package/dist/cjs/store/turso/store.js.map +1 -1
  134. package/dist/cjs/store/turso/vectors.js.map +1 -1
  135. package/dist/cjs/store/types.js.map +1 -1
  136. package/dist/cjs/store/vectors.js.map +1 -1
  137. package/dist/cjs/text/segment.js.map +1 -1
  138. package/dist/cjs/text/strip.js.map +1 -1
  139. package/dist/cjs/watch-claim.js.map +1 -1
  140. package/dist/cjs/watch.js.map +1 -1
  141. package/dist/cjs/workers/parse.js.map +1 -1
  142. package/dist/cjs/workers/watch-heartbeat.js.map +1 -1
  143. package/dist/esm/chunk/extract.js.map +1 -1
  144. package/dist/esm/chunk/group.js.map +1 -1
  145. package/dist/esm/chunk/index.js.map +1 -1
  146. package/dist/esm/chunk/parse.js.map +1 -1
  147. package/dist/esm/chunk/parser.js.map +1 -1
  148. package/dist/esm/chunk/tokens.js.map +1 -1
  149. package/dist/esm/chunk/types.js.map +1 -1
  150. package/dist/esm/chunk/version.js.map +1 -1
  151. package/dist/esm/cli/build.js.map +1 -1
  152. package/dist/esm/cli/download.js.map +1 -1
  153. package/dist/esm/cli/index.js.map +1 -1
  154. package/dist/esm/cli/init.js.map +1 -1
  155. package/dist/esm/cli/map.js.map +1 -1
  156. package/dist/esm/cli/named.js.map +1 -1
  157. package/dist/esm/cli/path.js.map +1 -1
  158. package/dist/esm/cli/peek.js.map +1 -1
  159. package/dist/esm/cli/related.js.map +1 -1
  160. package/dist/esm/cli/search.js.map +1 -1
  161. package/dist/esm/cli/shared.js.map +1 -1
  162. package/dist/esm/cli/sql.js.map +1 -1
  163. package/dist/esm/cli/status.js.map +1 -1
  164. package/dist/esm/cli/types.js.map +1 -1
  165. package/dist/esm/cli/watch.js.map +1 -1
  166. package/dist/esm/cli.js.map +1 -1
  167. package/dist/esm/commands/index.js.map +1 -1
  168. package/dist/esm/commands/map.js.map +1 -1
  169. package/dist/esm/commands/path.js.map +1 -1
  170. package/dist/esm/commands/peek.js.map +1 -1
  171. package/dist/esm/commands/related.js.map +1 -1
  172. package/dist/esm/commands/scope.js.map +1 -1
  173. package/dist/esm/commands/search.js.map +1 -1
  174. package/dist/esm/commands/signals.js.map +1 -1
  175. package/dist/esm/commands/snapshot.js.map +1 -1
  176. package/dist/esm/commands/status.js.map +1 -1
  177. package/dist/esm/config/access.js.map +1 -1
  178. package/dist/esm/config/index.js.map +1 -1
  179. package/dist/esm/config/load.js.map +1 -1
  180. package/dist/esm/config/resolve.js.map +1 -1
  181. package/dist/esm/config/signals.js.map +1 -1
  182. package/dist/esm/config/types.js.map +1 -1
  183. package/dist/esm/config/validate.js.map +1 -1
  184. package/dist/esm/embed/cohere.js.map +1 -1
  185. package/dist/esm/embed/distribution.js.map +1 -1
  186. package/dist/esm/embed/endpoint.js.map +1 -1
  187. package/dist/esm/embed/handoff.js.map +1 -1
  188. package/dist/esm/embed/http.js.map +1 -1
  189. package/dist/esm/embed/identity.js.map +1 -1
  190. package/dist/esm/embed/langfit.js.map +1 -1
  191. package/dist/esm/embed/languages.js.map +1 -1
  192. package/dist/esm/embed/openai.js.map +1 -1
  193. package/dist/esm/embed/query.js.map +1 -1
  194. package/dist/esm/embed/registry.js.map +1 -1
  195. package/dist/esm/embed/static.js.map +1 -1
  196. package/dist/esm/embed/store.js.map +1 -1
  197. package/dist/esm/embed/types.js.map +1 -1
  198. package/dist/esm/errors.js.map +1 -1
  199. package/dist/esm/features/embed.js.map +1 -1
  200. package/dist/esm/features/fences.js.map +1 -1
  201. package/dist/esm/features/index.js.map +1 -1
  202. package/dist/esm/features/links.js.map +1 -1
  203. package/dist/esm/features/rank.js.map +1 -1
  204. package/dist/esm/features/sections.js.map +1 -1
  205. package/dist/esm/features/tags.js.map +1 -1
  206. package/dist/esm/features/types.js.map +1 -1
  207. package/dist/esm/graph/graph.js.map +1 -1
  208. package/dist/esm/graph/traverse.js.map +1 -1
  209. package/dist/esm/index.js.map +1 -1
  210. package/dist/esm/lib/atomic-write.js.map +1 -1
  211. package/dist/esm/lib/guarded-tick.js.map +1 -1
  212. package/dist/esm/lib/serial-query.js.map +1 -1
  213. package/dist/esm/lib/watch-notification.js.map +1 -1
  214. package/dist/esm/lib/worker-file.js.map +1 -1
  215. package/dist/esm/output/column-hint.js.map +1 -1
  216. package/dist/esm/output/output.js.map +1 -1
  217. package/dist/esm/output/progress.js.map +1 -1
  218. package/dist/esm/output/search-error.js.map +1 -1
  219. package/dist/esm/scan/frontmatter.js.map +1 -1
  220. package/dist/esm/scan/index.js.map +1 -1
  221. package/dist/esm/scan/list.js.map +1 -1
  222. package/dist/esm/scan/pool.js.map +1 -1
  223. package/dist/esm/scan/reparse.js.map +1 -1
  224. package/dist/esm/scan/worker-error.js.map +1 -1
  225. package/dist/esm/store/batch.js.map +1 -1
  226. package/dist/esm/store/builder.js.map +1 -1
  227. package/dist/esm/store/cache.js.map +1 -1
  228. package/dist/esm/store/duckdb/batch.js.map +1 -1
  229. package/dist/esm/store/duckdb/connection.js.map +1 -1
  230. package/dist/esm/store/duckdb/fieldStats.js.map +1 -1
  231. package/dist/esm/store/duckdb/lexical.d.ts +1 -6
  232. package/dist/esm/store/duckdb/lexical.js +13 -17
  233. package/dist/esm/store/duckdb/lexical.js.map +1 -1
  234. package/dist/esm/store/duckdb/native.d.ts +1 -2
  235. package/dist/esm/store/duckdb/native.js +1 -3
  236. package/dist/esm/store/duckdb/native.js.map +1 -1
  237. package/dist/esm/store/duckdb/open.js.map +1 -1
  238. package/dist/esm/store/duckdb/ordered-bm25.d.ts +3 -16
  239. package/dist/esm/store/duckdb/ordered-bm25.js +18 -54
  240. package/dist/esm/store/duckdb/ordered-bm25.js.map +1 -1
  241. package/dist/esm/store/duckdb/reconcile.js.map +1 -1
  242. package/dist/esm/store/duckdb/sql-functions.js.map +1 -1
  243. package/dist/esm/store/duckdb/store.js.map +1 -1
  244. package/dist/esm/store/duckdb/vectors.js.map +1 -1
  245. package/dist/esm/store/embed-scope.js.map +1 -1
  246. package/dist/esm/store/feature-scope.js.map +1 -1
  247. package/dist/esm/store/index.js.map +1 -1
  248. package/dist/esm/store/lock-wait.js.map +1 -1
  249. package/dist/esm/store/native.js.map +1 -1
  250. package/dist/esm/store/open.js.map +1 -1
  251. package/dist/esm/store/preset-scope.js.map +1 -1
  252. package/dist/esm/store/readiness.js.map +1 -1
  253. package/dist/esm/store/reconcile.js.map +1 -1
  254. package/dist/esm/store/shared.js.map +1 -1
  255. package/dist/esm/store/signature.js.map +1 -1
  256. package/dist/esm/store/sql-functions.js.map +1 -1
  257. package/dist/esm/store/sqlite/connection.js.map +1 -1
  258. package/dist/esm/store/sqlite/fieldStats.js.map +1 -1
  259. package/dist/esm/store/sqlite/lexical.js.map +1 -1
  260. package/dist/esm/store/sqlite/open.js.map +1 -1
  261. package/dist/esm/store/sqlite/reconcile.js.map +1 -1
  262. package/dist/esm/store/sqlite/sql-functions.js.map +1 -1
  263. package/dist/esm/store/sqlite/store.js.map +1 -1
  264. package/dist/esm/store/sqlite/vectors.js.map +1 -1
  265. package/dist/esm/store/stages.js.map +1 -1
  266. package/dist/esm/store/transaction.js.map +1 -1
  267. package/dist/esm/store/turso/connection.js.map +1 -1
  268. package/dist/esm/store/turso/fieldStats.js.map +1 -1
  269. package/dist/esm/store/turso/lexical-text.js.map +1 -1
  270. package/dist/esm/store/turso/lexical.js.map +1 -1
  271. package/dist/esm/store/turso/native.js.map +1 -1
  272. package/dist/esm/store/turso/open.js.map +1 -1
  273. package/dist/esm/store/turso/reconcile.js.map +1 -1
  274. package/dist/esm/store/turso/sql-functions.js.map +1 -1
  275. package/dist/esm/store/turso/store.js.map +1 -1
  276. package/dist/esm/store/turso/vectors.js.map +1 -1
  277. package/dist/esm/store/types.js.map +1 -1
  278. package/dist/esm/store/vectors.js.map +1 -1
  279. package/dist/esm/text/segment.js.map +1 -1
  280. package/dist/esm/text/strip.js.map +1 -1
  281. package/dist/esm/watch-claim.js.map +1 -1
  282. package/dist/esm/watch.js.map +1 -1
  283. package/dist/esm/workers/parse.js.map +1 -1
  284. package/dist/esm/workers/watch-heartbeat.js.map +1 -1
  285. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/store.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\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 { storeRowToJs } from './connection.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { createLexicalIndex } from './lexical.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\n// Portable surface, links/sections/tags/rank, raw sql passthrough, lexical (fts BM25 + contains(), lexical.ts), and vectors (native\n// FLOAT[N] + array_cosine_similarity, vectors.ts) are implemented. segment() registers as a UDF (sql-functions.ts).\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['vectors', 'segment']);\n\n// Shares one Connection instance (conn) with the builder's own reconcile call so transaction depth (transaction.ts) is tracked against the same object everywhere.\n// The instance is the native handle that owns the WAL: close() must close it, not just disconnect, or DuckDB never checkpoints and the next open reads a mismatched WAL.\nexport function createStore(instance: DuckDBInstance, duckdb: DuckDBConnection, conn: Connection): Store {\n const lex = createLexicalIndex(conn);\n return {\n name: 'duckdb',\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: lex.query,\n },\n // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the interface's per-call storeDims --\n // see vectors.ts's padded() for why a shorter vector remains correct against a wider column.\n vectors: {\n pending: () => pendingRows(conn),\n writeVectors: (rows) => writeVectorBatch(duckdb, conn, STORE_DIMS, rows),\n candidates: (qv, _storeDims, fetch, allowed) => scanCandidates(duckdb, qv, STORE_DIMS, fetch, allowed),\n similar: (path, opts) => scanSimilar(duckdb, conn, STORE_DIMS, path, opts),\n hasVector: (path) => hasVectorRow(conn, path),\n },\n // No comparable setting to report yet.\n async engineStatus() {\n return {};\n },\n raw: {\n async prepare(sql: string) {\n const prepared = await duckdb.prepare(sql);\n return {\n columns: () => {\n const out: Array<{ name: string }> = [];\n for (let i = 0; i < prepared.columnCount; i++) out.push({ name: prepared.columnName(i) });\n return out;\n },\n // Real incremental streaming: DuckDB reads its own result in row-group chunks, so\n // each readUntil only fetches what isn't already in hand.\n iterate: async function* (...params: unknown[]) {\n if (params.length > 0) prepared.bind(params as Parameters<typeof prepared.bind>[0]);\n const reader = await prepared.streamAndRead();\n let yielded = 0;\n do {\n await reader.readUntil(reader.currentRowCount + 2048);\n const rows = reader.getRowObjectsJS() as Array<Record<string, unknown>>;\n for (; yielded < rows.length; yielded++) yield storeRowToJs(rows[yielded]);\n } while (!reader.done);\n },\n };\n },\n },\n async close() {\n // Order matters: the connection must be gone before the instance closes the WAL.\n duckdb.disconnectSync();\n instance.closeSync();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","instance","duckdb","conn","lex","createLexicalIndex","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","STORE_DIMS","candidates","qv","_storeDims","fetch","allowed","scanCandidates","similar","path","opts","scanSimilar","hasVector","hasVectorRow","engineStatus","raw","prepared","out","i","columnCount","push","columnName","iterate","params","reader","yielded","length","bind","streamAndRead","readUntil","currentRowCount","getRowObjectsJS","storeRowToJs","done","close","disconnectSync","closeSync"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/duckdb/store.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\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 { storeRowToJs } from './connection.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { createLexicalIndex } from './lexical.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\n// Portable surface, links/sections/tags/rank, raw sql passthrough, lexical (fts BM25 + contains(), lexical.ts), and vectors (native\n// FLOAT[N] + array_cosine_similarity, vectors.ts) are implemented. segment() registers as a UDF (sql-functions.ts).\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['vectors', 'segment']);\n\n// Shares one Connection instance (conn) with the builder's own reconcile call so transaction depth (transaction.ts) is tracked against the same object everywhere.\n// The instance is the native handle that owns the WAL: close() must close it, not just disconnect, or DuckDB never checkpoints and the next open reads a mismatched WAL.\nexport function createStore(instance: DuckDBInstance, duckdb: DuckDBConnection, conn: Connection): Store {\n const lex = createLexicalIndex(conn);\n return {\n name: 'duckdb',\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: lex.query,\n },\n // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the interface's per-call storeDims --\n // see vectors.ts's padded() for why a shorter vector remains correct against a wider column.\n vectors: {\n pending: () => pendingRows(conn),\n writeVectors: (rows) => writeVectorBatch(duckdb, conn, STORE_DIMS, rows),\n candidates: (qv, _storeDims, fetch, allowed) => scanCandidates(duckdb, qv, STORE_DIMS, fetch, allowed),\n similar: (path, opts) => scanSimilar(duckdb, conn, STORE_DIMS, path, opts),\n hasVector: (path) => hasVectorRow(conn, path),\n },\n // No comparable setting to report yet.\n async engineStatus() {\n return {};\n },\n raw: {\n async prepare(sql: string) {\n const prepared = await duckdb.prepare(sql);\n return {\n columns: () => {\n const out: Array<{ name: string }> = [];\n for (let i = 0; i < prepared.columnCount; i++) out.push({ name: prepared.columnName(i) });\n return out;\n },\n // Real incremental streaming: DuckDB reads its own result in row-group chunks, so\n // each readUntil only fetches what isn't already in hand.\n iterate: async function* (...params: unknown[]) {\n if (params.length > 0) prepared.bind(params as Parameters<typeof prepared.bind>[0]);\n const reader = await prepared.streamAndRead();\n let yielded = 0;\n do {\n await reader.readUntil(reader.currentRowCount + 2048);\n const rows = reader.getRowObjectsJS() as Array<Record<string, unknown>>;\n for (; yielded < rows.length; yielded++) yield storeRowToJs(rows[yielded]);\n } while (!reader.done);\n },\n };\n },\n },\n async close() {\n // Order matters: the connection must be gone before the instance closes the WAL.\n duckdb.disconnectSync();\n instance.closeSync();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","instance","duckdb","conn","lex","createLexicalIndex","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","STORE_DIMS","candidates","qv","_storeDims","fetch","allowed","scanCandidates","similar","path","opts","scanSimilar","hasVector","hasVectorRow","engineStatus","raw","prepared","out","i","columnCount","push","columnName","iterate","params","reader","yielded","length","bind","streamAndRead","readUntil","currentRowCount","getRowObjectsJS","storeRowToJs","done","close","disconnectSync","closeSync"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/vectors.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBType, DuckDBValue } from '@duckdb/node-api';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, VectorCandidate, VectorSimilar, VectorWriteRow } from '../types.ts';\nimport { asCosine, sampleEvenly } from '../vectors.ts';\nimport { duckdbApi } from './native.ts';\n\n// This store keeps vectors as native FLOAT[dims] arrays (dims fixed at DDL time by open.ts's ensureSchema, from embed/types.ts's STORE_DIMS) and\n// scans them with array_cosine_similarity, pushing top-k into SQL instead of pulling every row into JS; sqlite's int8+scale BLOB scan is its own representation. Every function here takes `dims` as a parameter rather than importing STORE_DIMS directly, so it stays testable at any width.\n\n// A value import of '@duckdb/node-api' must never sit at module top level, or a sqlite-only tree would resolve this optional dependency\n// just by importing store/index.ts; native.ts's shared duckdbApi() keeps that lazy and reuses whatever open.ts already resolved.\n\n// A bind position whose type is left to auto-inference (safe for plain strings/numbers; only\n// the vector ARRAY positions below need an explicit type -- see writeVectorBatch's comment).\nconst untyped = undefined as unknown as DuckDBType;\nconst VECTOR_WRITE_STAGE = '_sense_vector_write_stage';\n\n// Created once per native connection outside write transactions; its lifetime follows that connection.\nexport async function createVectorWriteStage(duckdb: DuckDBConnection, dims: number): Promise<void> {\n await duckdb.run(`CREATE TEMP TABLE ${VECTOR_WRITE_STAGE} (\"path\" TEXT, chunk INTEGER, vector FLOAT[${dims}])`);\n}\n\n// The DDL-fixed array width can exceed a vector's actual length (a hypothetical model sliced under the column's width);\n// zero-padding leaves cosine scores unchanged since the added dimensions contribute nothing to either vector's dot product or norm.\nfunction padded(values: ArrayLike<number>, dims: number): number[] {\n const out = new Array<number>(dims).fill(0);\n for (let d = 0; d < Math.min(values.length, dims); d++) out[d] = values[d];\n return out;\n}\n\nfunction inClause(column: string, count: number): string {\n return `${column} IN (${Array.from({ length: count }, () => '?').join(', ')})`;\n}\n\n// Rows arrive int8-quantized with a per-vector scale (the wire format embed/query.ts produces for every store, see toStore);\n// dequantizing into a plain float array is this store's own representation choice, so both stores are handed the same vectors and diverge only here.\nfunction dequantize(row: VectorWriteRow, dims: number): number[] {\n const q = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n return padded(\n Array.from(q, (v) => v * row.scale),\n dims\n );\n}\n\n// The native appender needs an explicit FLOAT array type: inference from an integer first component\n// silently truncates fractional components. The fixed UPDATE keeps each provider batch keyed by path and chunk.\nexport async function writeVectorBatch(duckdb: DuckDBConnection, conn: Connection, dims: number, rows: VectorWriteRow[]): Promise<void> {\n if (rows.length === 0) return;\n const { ARRAY, FLOAT } = await duckdbApi();\n const vectorType = ARRAY(FLOAT, dims);\n\n await withTransaction(conn, async () => {\n await duckdb.run(`DELETE FROM ${VECTOR_WRITE_STAGE}`);\n const appender = await duckdb.createAppender(VECTOR_WRITE_STAGE);\n try {\n for (const row of rows) {\n appender.appendVarchar(row.path);\n appender.appendInteger(row.chunk);\n appender.appendArray(dequantize(row, dims), vectorType);\n appender.endRow();\n }\n appender.flushSync();\n } finally {\n appender.closeSync();\n }\n await duckdb.run(`UPDATE embeddings SET vector = staged.vector FROM ${VECTOR_WRITE_STAGE} AS staged WHERE embeddings.\"path\" = staged.\"path\" AND embeddings.chunk = staged.chunk`);\n });\n}\n\n// Best chunk per file by cosine, with the earliest chunk winning exact score ties.\n// An empty `allowed` set matches sqlite's scan (every row filtered out) without touching the table.\nexport async function scanCandidates(duckdb: DuckDBConnection, qv: Float32Array, dims: number, fetch: number, allowed?: Set<string>): Promise<VectorCandidate[]> {\n if (allowed && allowed.size === 0) return [];\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const allowedList = allowed ? [...allowed] : [];\n const query = padded(qv, dims);\n const queryNorm = Math.sqrt(query.reduce((sum, value) => sum + value * value, 0));\n const score = queryNorm === 0 ? '0.0' : 'CASE WHEN array_inner_product(vector, vector) = 0 THEN 0.0 ELSE array_cosine_similarity(vector, ?) END';\n const sql = `SELECT \"path\", start_line, end_line, score\n FROM (\n SELECT \"path\", start_line, end_line, score,\n row_number() OVER (PARTITION BY \"path\" ORDER BY score DESC, chunk ASC) AS selected\n FROM (\n SELECT \"path\", chunk, start_line, end_line, ${score} AS score\n FROM embeddings\n WHERE vector IS NOT NULL ${allowed ? `AND ${inClause('\"path\"', allowedList.length)}` : ''}\n ) sub\n ) ranked\n WHERE selected = 1\n ORDER BY score DESC, \"path\" ASC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [...(queryNorm === 0 ? [] : [arrayValue(query)]), ...allowedList, fetch];\n const types: DuckDBType[] = [...(queryNorm === 0 ? [] : [ARRAY(DOUBLE, dims)]), ...allowedList.map(() => untyped), untyped];\n stmt.bind(values, types);\n const reader = await stmt.runAndReadAll();\n const rows = reader.getRowObjectsJS() as Array<{ path: string; start_line: number; end_line: number; score: number }>;\n return rows.map((r) => ({ path: r.path, lines: `L${r.start_line}-${r.end_line}`, similarity: asCosine(r.score) }));\n } finally {\n stmt.destroySync();\n }\n}\n\n// Note-to-note similarity is the max cosine over (target chunk, other chunk) pairs, pushed into one native scan: the sampled target vectors become\n// a small VALUES list, cross-joined against every stored vector and reduced with max()/GROUP BY, so the O(target x stored) cost (12.7s at 201 chunks/note in JS) runs vectorized instead of scalar.\nexport async function scanSimilar(duckdb: DuckDBConnection, 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: number[] }>;\n if (targetRows.length === 0) return [];\n const targets = sampleEvenly(targetRows).map((row) => row.vector);\n\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const excludeList = [...opts.exclude];\n const allowedList = opts.allowed ? [...opts.allowed] : [];\n const sql = `WITH targets(tv) AS (VALUES ${targets.map(() => '(?)').join(', ')}), grouped AS (\n SELECT e.\"path\" AS path, max(CASE WHEN array_inner_product(e.vector, e.vector) = 0 OR array_inner_product(t.tv, t.tv) = 0 THEN 0.0 ELSE array_cosine_similarity(e.vector, t.tv) END) AS score\n FROM embeddings e, targets t\n WHERE e.vector IS NOT NULL AND e.\"path\" != ?\n ${excludeList.length > 0 ? `AND NOT ${inClause('e.\"path\"', excludeList.length)}` : ''}\n ${opts.allowed ? `AND ${inClause('e.\"path\"', allowedList.length)}` : ''}\n GROUP BY e.\"path\"\n )\n SELECT path, score FROM grouped\n ORDER BY score DESC, path ASC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [...targets.map((t) => arrayValue(padded(t, dims))), path, ...excludeList, ...allowedList, opts.k];\n const types: DuckDBType[] = [...targets.map(() => ARRAY(DOUBLE, dims)), untyped, ...excludeList.map(() => untyped), ...allowedList.map(() => untyped), untyped];\n stmt.bind(values, types);\n const reader = await stmt.runAndReadAll();\n const rows = reader.getRowObjectsJS() as Array<{ path: string; score: number }>;\n return rows.map((r) => ({ path: r.path, similarity: asCosine(r.score) }));\n } finally {\n stmt.destroySync();\n }\n}\n"],"names":["createVectorWriteStage","scanCandidates","scanSimilar","writeVectorBatch","untyped","undefined","VECTOR_WRITE_STAGE","duckdb","dims","run","padded","values","out","Array","fill","d","Math","min","length","inClause","column","count","from","join","dequantize","row","q","Int8Array","vector","buffer","byteOffset","byteLength","v","scale","conn","rows","ARRAY","FLOAT","vectorType","duckdbApi","withTransaction","appender","createAppender","appendVarchar","path","appendInteger","chunk","appendArray","endRow","flushSync","closeSync","qv","fetch","allowed","arrayValue","DOUBLE","allowedList","query","queryNorm","score","sql","stmt","types","reader","size","sqrt","reduce","sum","value","prepare","map","bind","runAndReadAll","getRowObjectsJS","r","lines","start_line","end_line","similarity","asCosine","destroySync","opts","targetStmt","targetRows","targets","excludeList","all","sampleEvenly","exclude","t","k"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/duckdb/vectors.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBType, DuckDBValue } from '@duckdb/node-api';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, VectorCandidate, VectorSimilar, VectorWriteRow } from '../types.ts';\nimport { asCosine, sampleEvenly } from '../vectors.ts';\nimport { duckdbApi } from './native.ts';\n\n// This store keeps vectors as native FLOAT[dims] arrays (dims fixed at DDL time by open.ts's ensureSchema, from embed/types.ts's STORE_DIMS) and\n// scans them with array_cosine_similarity, pushing top-k into SQL instead of pulling every row into JS; sqlite's int8+scale BLOB scan is its own representation. Every function here takes `dims` as a parameter rather than importing STORE_DIMS directly, so it stays testable at any width.\n\n// A value import of '@duckdb/node-api' must never sit at module top level, or a sqlite-only tree would resolve this optional dependency\n// just by importing store/index.ts; native.ts's shared duckdbApi() keeps that lazy and reuses whatever open.ts already resolved.\n\n// A bind position whose type is left to auto-inference (safe for plain strings/numbers; only\n// the vector ARRAY positions below need an explicit type -- see writeVectorBatch's comment).\nconst untyped = undefined as unknown as DuckDBType;\nconst VECTOR_WRITE_STAGE = '_sense_vector_write_stage';\n\n// Created once per native connection outside write transactions; its lifetime follows that connection.\nexport async function createVectorWriteStage(duckdb: DuckDBConnection, dims: number): Promise<void> {\n await duckdb.run(`CREATE TEMP TABLE ${VECTOR_WRITE_STAGE} (\"path\" TEXT, chunk INTEGER, vector FLOAT[${dims}])`);\n}\n\n// The DDL-fixed array width can exceed a vector's actual length (a hypothetical model sliced under the column's width);\n// zero-padding leaves cosine scores unchanged since the added dimensions contribute nothing to either vector's dot product or norm.\nfunction padded(values: ArrayLike<number>, dims: number): number[] {\n const out = new Array<number>(dims).fill(0);\n for (let d = 0; d < Math.min(values.length, dims); d++) out[d] = values[d];\n return out;\n}\n\nfunction inClause(column: string, count: number): string {\n return `${column} IN (${Array.from({ length: count }, () => '?').join(', ')})`;\n}\n\n// Rows arrive int8-quantized with a per-vector scale (the wire format embed/query.ts produces for every store, see toStore);\n// dequantizing into a plain float array is this store's own representation choice, so both stores are handed the same vectors and diverge only here.\nfunction dequantize(row: VectorWriteRow, dims: number): number[] {\n const q = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n return padded(\n Array.from(q, (v) => v * row.scale),\n dims\n );\n}\n\n// The native appender needs an explicit FLOAT array type: inference from an integer first component\n// silently truncates fractional components. The fixed UPDATE keeps each provider batch keyed by path and chunk.\nexport async function writeVectorBatch(duckdb: DuckDBConnection, conn: Connection, dims: number, rows: VectorWriteRow[]): Promise<void> {\n if (rows.length === 0) return;\n const { ARRAY, FLOAT } = await duckdbApi();\n const vectorType = ARRAY(FLOAT, dims);\n\n await withTransaction(conn, async () => {\n await duckdb.run(`DELETE FROM ${VECTOR_WRITE_STAGE}`);\n const appender = await duckdb.createAppender(VECTOR_WRITE_STAGE);\n try {\n for (const row of rows) {\n appender.appendVarchar(row.path);\n appender.appendInteger(row.chunk);\n appender.appendArray(dequantize(row, dims), vectorType);\n appender.endRow();\n }\n appender.flushSync();\n } finally {\n appender.closeSync();\n }\n await duckdb.run(`UPDATE embeddings SET vector = staged.vector FROM ${VECTOR_WRITE_STAGE} AS staged WHERE embeddings.\"path\" = staged.\"path\" AND embeddings.chunk = staged.chunk`);\n });\n}\n\n// Best chunk per file by cosine, with the earliest chunk winning exact score ties.\n// An empty `allowed` set matches sqlite's scan (every row filtered out) without touching the table.\nexport async function scanCandidates(duckdb: DuckDBConnection, qv: Float32Array, dims: number, fetch: number, allowed?: Set<string>): Promise<VectorCandidate[]> {\n if (allowed && allowed.size === 0) return [];\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const allowedList = allowed ? [...allowed] : [];\n const query = padded(qv, dims);\n const queryNorm = Math.sqrt(query.reduce((sum, value) => sum + value * value, 0));\n const score = queryNorm === 0 ? '0.0' : 'CASE WHEN array_inner_product(vector, vector) = 0 THEN 0.0 ELSE array_cosine_similarity(vector, ?) END';\n const sql = `SELECT \"path\", start_line, end_line, score\n FROM (\n SELECT \"path\", start_line, end_line, score,\n row_number() OVER (PARTITION BY \"path\" ORDER BY score DESC, chunk ASC) AS selected\n FROM (\n SELECT \"path\", chunk, start_line, end_line, ${score} AS score\n FROM embeddings\n WHERE vector IS NOT NULL ${allowed ? `AND ${inClause('\"path\"', allowedList.length)}` : ''}\n ) sub\n ) ranked\n WHERE selected = 1\n ORDER BY score DESC, \"path\" ASC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [...(queryNorm === 0 ? [] : [arrayValue(query)]), ...allowedList, fetch];\n const types: DuckDBType[] = [...(queryNorm === 0 ? [] : [ARRAY(DOUBLE, dims)]), ...allowedList.map(() => untyped), untyped];\n stmt.bind(values, types);\n const reader = await stmt.runAndReadAll();\n const rows = reader.getRowObjectsJS() as Array<{ path: string; start_line: number; end_line: number; score: number }>;\n return rows.map((r) => ({ path: r.path, lines: `L${r.start_line}-${r.end_line}`, similarity: asCosine(r.score) }));\n } finally {\n stmt.destroySync();\n }\n}\n\n// Note-to-note similarity is the max cosine over (target chunk, other chunk) pairs, pushed into one native scan: the sampled target vectors become\n// a small VALUES list, cross-joined against every stored vector and reduced with max()/GROUP BY, so the O(target x stored) cost (12.7s at 201 chunks/note in JS) runs vectorized instead of scalar.\nexport async function scanSimilar(duckdb: DuckDBConnection, 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: number[] }>;\n if (targetRows.length === 0) return [];\n const targets = sampleEvenly(targetRows).map((row) => row.vector);\n\n const { arrayValue, ARRAY, DOUBLE } = await duckdbApi();\n const excludeList = [...opts.exclude];\n const allowedList = opts.allowed ? [...opts.allowed] : [];\n const sql = `WITH targets(tv) AS (VALUES ${targets.map(() => '(?)').join(', ')}), grouped AS (\n SELECT e.\"path\" AS path, max(CASE WHEN array_inner_product(e.vector, e.vector) = 0 OR array_inner_product(t.tv, t.tv) = 0 THEN 0.0 ELSE array_cosine_similarity(e.vector, t.tv) END) AS score\n FROM embeddings e, targets t\n WHERE e.vector IS NOT NULL AND e.\"path\" != ?\n ${excludeList.length > 0 ? `AND NOT ${inClause('e.\"path\"', excludeList.length)}` : ''}\n ${opts.allowed ? `AND ${inClause('e.\"path\"', allowedList.length)}` : ''}\n GROUP BY e.\"path\"\n )\n SELECT path, score FROM grouped\n ORDER BY score DESC, path ASC\n LIMIT ?`;\n const stmt = await duckdb.prepare(sql);\n try {\n const values: DuckDBValue[] = [...targets.map((t) => arrayValue(padded(t, dims))), path, ...excludeList, ...allowedList, opts.k];\n const types: DuckDBType[] = [...targets.map(() => ARRAY(DOUBLE, dims)), untyped, ...excludeList.map(() => untyped), ...allowedList.map(() => untyped), untyped];\n stmt.bind(values, types);\n const reader = await stmt.runAndReadAll();\n const rows = reader.getRowObjectsJS() as Array<{ path: string; score: number }>;\n return rows.map((r) => ({ path: r.path, similarity: asCosine(r.score) }));\n } finally {\n stmt.destroySync();\n }\n}\n"],"names":["createVectorWriteStage","scanCandidates","scanSimilar","writeVectorBatch","untyped","undefined","VECTOR_WRITE_STAGE","duckdb","dims","run","padded","values","out","Array","fill","d","Math","min","length","inClause","column","count","from","join","dequantize","row","q","Int8Array","vector","buffer","byteOffset","byteLength","v","scale","conn","rows","ARRAY","FLOAT","vectorType","duckdbApi","withTransaction","appender","createAppender","appendVarchar","path","appendInteger","chunk","appendArray","endRow","flushSync","closeSync","qv","fetch","allowed","arrayValue","DOUBLE","allowedList","query","queryNorm","score","sql","stmt","types","reader","size","sqrt","reduce","sum","value","prepare","map","bind","runAndReadAll","getRowObjectsJS","r","lines","start_line","end_line","similarity","asCosine","destroySync","opts","targetStmt","targetRows","targets","excludeList","all","sampleEvenly","exclude","t","k"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/embed-scope.ts"],"sourcesContent":["// Decomposition of the `embed:` featureSignature segment (config/access.ts's featureSignature,\n// features/embed.ts's signature()), for open()'s narrow embed-invalidation routing.\n\nexport type EmbedChangeKind = 'model' | 'chunk';\n\ninterface EmbedSegment {\n provider: string;\n model: string;\n endpoint?: string;\n chunkVersion: string;\n}\n\n// One embed segment's provider/model/endpoint/chunkVersion, ignoring any trailing `@identity`.\n// The endpoint-less HTTP shape remains readable so upgrading invalidates vectors, not core data.\nfunction parseEmbedSegment(sig: string): EmbedSegment | null {\n const part = sig.split('|').find((p) => p.startsWith('embed:'));\n if (part === undefined || part === 'embed:off') return null;\n const at = part.indexOf('@');\n const body = at === -1 ? part : part.slice(0, at);\n const withEndpoint = /^embed:(openai|cohere):(.+):endpoint=([0-9a-f]{64}):(chunk:v\\d+(?::\\d+)?)$/.exec(body);\n if (withEndpoint) {\n const [, provider, model, endpoint, chunkVersion] = withEndpoint;\n return { provider, model, endpoint, chunkVersion };\n }\n const legacy = /^embed:(static|openai|cohere):(.+):(chunk:v\\d+(?::\\d+)?)$/.exec(body);\n if (!legacy) return null;\n const [, provider, model, chunkVersion] = legacy;\n return { provider, model, chunkVersion };\n}\n\n// 'chunk' when chunkTokens or the chunk version moved (boundaries changed, embeddings rebuild);\n// 'model' when only the provider or model moved (rows unchanged, values stale); null otherwise.\nexport function classifyEmbedChange(before: string, after: string): EmbedChangeKind | null {\n const b = parseEmbedSegment(before);\n const a = parseEmbedSegment(after);\n if (b === null || a === null) return null;\n if (b.chunkVersion !== a.chunkVersion) return 'chunk';\n if (b.provider !== a.provider || b.model !== a.model || b.endpoint !== a.endpoint) return 'model';\n return null;\n}\n"],"names":["classifyEmbedChange","parseEmbedSegment","sig","part","split","find","p","startsWith","undefined","at","indexOf","body","slice","withEndpoint","exec","provider","model","endpoint","chunkVersion","legacy","before","after","b","a"],"mappings":"AAAA,+FAA+F;AAC/F,oFAAoF;;;;;+BA+BpEA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AApBhB,+FAA+F;AAC/F,iGAAiG;AACjG,SAASC,kBAAkBC,GAAW;IACpC,IAAMC,OAAOD,IAAIE,KAAK,CAAC,KAAKC,IAAI,CAAC,SAACC;eAAMA,EAAEC,UAAU,CAAC;;IACrD,IAAIJ,SAASK,aAAaL,SAAS,aAAa,OAAO;IACvD,IAAMM,KAAKN,KAAKO,OAAO,CAAC;IACxB,IAAMC,OAAOF,OAAO,CAAC,IAAIN,OAAOA,KAAKS,KAAK,CAAC,GAAGH;IAC9C,IAAMI,eAAe,6EAA6EC,IAAI,CAACH;IACvG,IAAIE,cAAc;QAChB,IAAoDA,iCAAAA,kBAA3CE,WAA2CF,kBAAjCG,QAAiCH,kBAA1BI,WAA0BJ,kBAAhBK,eAAgBL;QACpD,OAAO;YAAEE,UAAAA;YAAUC,OAAAA;YAAOC,UAAAA;YAAUC,cAAAA;QAAa;IACnD;IACA,IAAMC,SAAS,4DAA4DL,IAAI,CAACH;IAChF,IAAI,CAACQ,QAAQ,OAAO;IACpB,IAA0CA,2BAAAA,YAAjCJ,YAAiCI,YAAvBH,SAAuBG,YAAhBD,gBAAgBC;IAC1C,OAAO;QAAEJ,UAAAA;QAAUC,OAAAA;QAAOE,cAAAA;IAAa;AACzC;AAIO,SAASlB,oBAAoBoB,MAAc,EAAEC,KAAa;IAC/D,IAAMC,IAAIrB,kBAAkBmB;IAC5B,IAAMG,IAAItB,kBAAkBoB;IAC5B,IAAIC,MAAM,QAAQC,MAAM,MAAM,OAAO;IACrC,IAAID,EAAEJ,YAAY,KAAKK,EAAEL,YAAY,EAAE,OAAO;IAC9C,IAAII,EAAEP,QAAQ,KAAKQ,EAAER,QAAQ,IAAIO,EAAEN,KAAK,KAAKO,EAAEP,KAAK,IAAIM,EAAEL,QAAQ,KAAKM,EAAEN,QAAQ,EAAE,OAAO;IAC1F,OAAO;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/embed-scope.ts"],"sourcesContent":["// Decomposition of the `embed:` featureSignature segment (config/access.ts's featureSignature,\n// features/embed.ts's signature()), for open()'s narrow embed-invalidation routing.\n\nexport type EmbedChangeKind = 'model' | 'chunk';\n\ninterface EmbedSegment {\n provider: string;\n model: string;\n endpoint?: string;\n chunkVersion: string;\n}\n\n// One embed segment's provider/model/endpoint/chunkVersion, ignoring any trailing `@identity`.\n// The endpoint-less HTTP shape remains readable so upgrading invalidates vectors, not core data.\nfunction parseEmbedSegment(sig: string): EmbedSegment | null {\n const part = sig.split('|').find((p) => p.startsWith('embed:'));\n if (part === undefined || part === 'embed:off') return null;\n const at = part.indexOf('@');\n const body = at === -1 ? part : part.slice(0, at);\n const withEndpoint = /^embed:(openai|cohere):(.+):endpoint=([0-9a-f]{64}):(chunk:v\\d+(?::\\d+)?)$/.exec(body);\n if (withEndpoint) {\n const [, provider, model, endpoint, chunkVersion] = withEndpoint;\n return { provider, model, endpoint, chunkVersion };\n }\n const legacy = /^embed:(static|openai|cohere):(.+):(chunk:v\\d+(?::\\d+)?)$/.exec(body);\n if (!legacy) return null;\n const [, provider, model, chunkVersion] = legacy;\n return { provider, model, chunkVersion };\n}\n\n// 'chunk' when chunkTokens or the chunk version moved (boundaries changed, embeddings rebuild);\n// 'model' when only the provider or model moved (rows unchanged, values stale); null otherwise.\nexport function classifyEmbedChange(before: string, after: string): EmbedChangeKind | null {\n const b = parseEmbedSegment(before);\n const a = parseEmbedSegment(after);\n if (b === null || a === null) return null;\n if (b.chunkVersion !== a.chunkVersion) return 'chunk';\n if (b.provider !== a.provider || b.model !== a.model || b.endpoint !== a.endpoint) return 'model';\n return null;\n}\n"],"names":["classifyEmbedChange","parseEmbedSegment","sig","part","split","find","p","startsWith","undefined","at","indexOf","body","slice","withEndpoint","exec","provider","model","endpoint","chunkVersion","legacy","before","after","b","a"],"mappings":"AAAA,+FAA+F;AAC/F,oFAAoF;;;;;+BA+BpEA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AApBhB,+FAA+F;AAC/F,iGAAiG;AACjG,SAASC,kBAAkBC,GAAW;IACpC,IAAMC,OAAOD,IAAIE,KAAK,CAAC,KAAKC,IAAI,CAAC,SAACC;eAAMA,EAAEC,UAAU,CAAC;;IACrD,IAAIJ,SAASK,aAAaL,SAAS,aAAa,OAAO;IACvD,IAAMM,KAAKN,KAAKO,OAAO,CAAC;IACxB,IAAMC,OAAOF,OAAO,CAAC,IAAIN,OAAOA,KAAKS,KAAK,CAAC,GAAGH;IAC9C,IAAMI,eAAe,6EAA6EC,IAAI,CAACH;IACvG,IAAIE,cAAc;QAChB,IAAoDA,iCAAAA,kBAA3CE,WAA2CF,kBAAjCG,QAAiCH,kBAA1BI,WAA0BJ,kBAAhBK,eAAgBL;QACpD,OAAO;YAAEE,UAAAA;YAAUC,OAAAA;YAAOC,UAAAA;YAAUC,cAAAA;QAAa;IACnD;IACA,IAAMC,SAAS,4DAA4DL,IAAI,CAACH;IAChF,IAAI,CAACQ,QAAQ,OAAO;IACpB,IAA0CA,2BAAAA,YAAjCJ,YAAiCI,YAAvBH,SAAuBG,YAAhBD,gBAAgBC;IAC1C,OAAO;QAAEJ,UAAAA;QAAUC,OAAAA;QAAOE,cAAAA;IAAa;AACzC;AAIO,SAASlB,oBAAoBoB,MAAc,EAAEC,KAAa;IAC/D,IAAMC,IAAIrB,kBAAkBmB;IAC5B,IAAMG,IAAItB,kBAAkBoB;IAC5B,IAAIC,MAAM,QAAQC,MAAM,MAAM,OAAO;IACrC,IAAID,EAAEJ,YAAY,KAAKK,EAAEL,YAAY,EAAE,OAAO;IAC9C,IAAII,EAAEP,QAAQ,KAAKQ,EAAER,QAAQ,IAAIO,EAAEN,KAAK,KAAKO,EAAEP,KAAK,IAAIM,EAAEL,QAAQ,KAAKM,EAAEN,QAAQ,EAAE,OAAO;IAC1F,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/feature-scope.ts"],"sourcesContent":["import type { FeatureName } from '../config/index.ts';\n\n// Decomposition of the `feature:<name>:<on|off>` featureSignature segments (config/access.ts's\n// featureSignature), for open()'s narrow feature-toggle invalidation routing.\n\n// Every narrow-supported feature but rank owns one dedicated table, dropped and (turning on)\n// fully re-derived. rank has no table -- it writes PageRank into frontmatter's own `_rank`\n// column -- so builder.ts handles it, and the links/rank pair, as special cases outside this map.\nexport const NARROW_FEATURE_TABLE: Readonly<Record<string, string>> = { tags: 'tags', sections: 'sections', links: 'links' };\n\n// links feeds rank's afterReconcile pass, so a links toggle always co-changes the `feature:rank`\n// segment too (featureEnabled's dependency); both are narrow-supported and builder.ts applies\n// them together. A changed set naming any other feature falls through to the existing full clear.\nconst NARROW_FEATURE_NAMES: ReadonlySet<string> = new Set([...Object.keys(NARROW_FEATURE_TABLE), 'rank']);\n\nexport interface FeatureToggle {\n name: FeatureName;\n // true: was off, now on (must fully re-derive). false: was on, now off (drop its rows).\n turnedOn: boolean;\n}\n\n// Every changed key is a `feature:<name>` segment for a narrow-supported feature.\nexport function isFeatureOnlyChange(changedKeys: ReadonlySet<string>): boolean {\n return changedKeys.size > 0 && [...changedKeys].every((key) => key.startsWith('feature:') && NARROW_FEATURE_NAMES.has(key.slice('feature:'.length)));\n}\n\n// One feature segment's old on/off, read back out of a stored `feature:<name>:on|off` segment.\n// Anything not in that exact shape returns null so the caller falls back to a full rebuild.\nfunction parseOnOff(sig: string, name: string): boolean | null {\n const part = sig.split('|').find((p) => p.startsWith(`feature:${name}:`));\n if (part === undefined) return null;\n const fields = part.split(':');\n if (fields.length !== 3 || (fields[2] !== 'on' && fields[2] !== 'off')) return null;\n return fields[2] === 'on';\n}\n\n// Old-vs-new on/off for every changed feature key, or null when a segment can't be parsed back\n// out of `before` or `after`, or when it parses to the same state on both sides (should never\n// happen for a genuinely changed key) -- either way the caller takes the full rebuild.\nexport function classifyFeatureToggles(before: string, after: string, changedKeys: ReadonlySet<string>): FeatureToggle[] | null {\n const toggles: FeatureToggle[] = [];\n for (const key of changedKeys) {\n const name = key.slice('feature:'.length) as FeatureName;\n const wasOn = parseOnOff(before, name);\n const isOn = parseOnOff(after, name);\n if (wasOn === null || isOn === null || wasOn === isOn) return null;\n toggles.push({ name, turnedOn: isOn });\n }\n return toggles;\n}\n"],"names":["NARROW_FEATURE_TABLE","classifyFeatureToggles","isFeatureOnlyChange","tags","sections","links","NARROW_FEATURE_NAMES","Set","Object","keys","changedKeys","size","every","key","startsWith","has","slice","length","parseOnOff","sig","name","part","split","find","p","undefined","fields","before","after","toggles","wasOn","isOn","push","turnedOn"],"mappings":";;;;;;;;;;;QAQaA;eAAAA;;QA+BGC;eAAAA;;QAjBAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAdT,IAAMF,uBAAyD;IAAEG,MAAM;IAAQC,UAAU;IAAYC,OAAO;AAAQ;AAE3H,iGAAiG;AACjG,8FAA8F;AAC9F,kGAAkG;AAClG,IAAMC,uBAA4C,IAAIC,IAAI,AAAC,qBAAGC,OAAOC,IAAI,CAACT,8BAAhB;IAAuC;CAAO;AASjG,SAASE,oBAAoBQ,WAAgC;IAClE,OAAOA,YAAYC,IAAI,GAAG,KAAK,AAAC,qBAAGD,aAAaE,KAAK,CAAC,SAACC;eAAQA,IAAIC,UAAU,CAAC,eAAeR,qBAAqBS,GAAG,CAACF,IAAIG,KAAK,CAAC,WAAWC,MAAM;;AACnJ;AAEA,+FAA+F;AAC/F,4FAA4F;AAC5F,SAASC,WAAWC,GAAW,EAAEC,IAAY;IAC3C,IAAMC,OAAOF,IAAIG,KAAK,CAAC,KAAKC,IAAI,CAAC,SAACC;eAAMA,EAAEV,UAAU,CAAC,AAAC,WAAe,OAALM,MAAK;;IACrE,IAAIC,SAASI,WAAW,OAAO;IAC/B,IAAMC,SAASL,KAAKC,KAAK,CAAC;IAC1B,IAAII,OAAOT,MAAM,KAAK,KAAMS,MAAM,CAAC,EAAE,KAAK,QAAQA,MAAM,CAAC,EAAE,KAAK,OAAQ,OAAO;IAC/E,OAAOA,MAAM,CAAC,EAAE,KAAK;AACvB;AAKO,SAASzB,uBAAuB0B,MAAc,EAAEC,KAAa,EAAElB,WAAgC;IACpG,IAAMmB,UAA2B,EAAE;QAC9B,kCAAA,2BAAA;;QAAL,QAAK,YAAanB,gCAAb,SAAA,6BAAA,QAAA,yBAAA,iCAA0B;YAA1B,IAAMG,MAAN;YACH,IAAMO,OAAOP,IAAIG,KAAK,CAAC,WAAWC,MAAM;YACxC,IAAMa,QAAQZ,WAAWS,QAAQP;YACjC,IAAMW,OAAOb,WAAWU,OAAOR;YAC/B,IAAIU,UAAU,QAAQC,SAAS,QAAQD,UAAUC,MAAM,OAAO;YAC9DF,QAAQG,IAAI,CAAC;gBAAEZ,MAAAA;gBAAMa,UAAUF;YAAK;QACtC;;QANK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAOL,OAAOF;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/feature-scope.ts"],"sourcesContent":["import type { FeatureName } from '../config/index.ts';\n\n// Decomposition of the `feature:<name>:<on|off>` featureSignature segments (config/access.ts's\n// featureSignature), for open()'s narrow feature-toggle invalidation routing.\n\n// Every narrow-supported feature but rank owns one dedicated table, dropped and (turning on)\n// fully re-derived. rank has no table -- it writes PageRank into frontmatter's own `_rank`\n// column -- so builder.ts handles it, and the links/rank pair, as special cases outside this map.\nexport const NARROW_FEATURE_TABLE: Readonly<Record<string, string>> = { tags: 'tags', sections: 'sections', links: 'links' };\n\n// links feeds rank's afterReconcile pass, so a links toggle always co-changes the `feature:rank`\n// segment too (featureEnabled's dependency); both are narrow-supported and builder.ts applies\n// them together. A changed set naming any other feature falls through to the existing full clear.\nconst NARROW_FEATURE_NAMES: ReadonlySet<string> = new Set([...Object.keys(NARROW_FEATURE_TABLE), 'rank']);\n\nexport interface FeatureToggle {\n name: FeatureName;\n // true: was off, now on (must fully re-derive). false: was on, now off (drop its rows).\n turnedOn: boolean;\n}\n\n// Every changed key is a `feature:<name>` segment for a narrow-supported feature.\nexport function isFeatureOnlyChange(changedKeys: ReadonlySet<string>): boolean {\n return changedKeys.size > 0 && [...changedKeys].every((key) => key.startsWith('feature:') && NARROW_FEATURE_NAMES.has(key.slice('feature:'.length)));\n}\n\n// One feature segment's old on/off, read back out of a stored `feature:<name>:on|off` segment.\n// Anything not in that exact shape returns null so the caller falls back to a full rebuild.\nfunction parseOnOff(sig: string, name: string): boolean | null {\n const part = sig.split('|').find((p) => p.startsWith(`feature:${name}:`));\n if (part === undefined) return null;\n const fields = part.split(':');\n if (fields.length !== 3 || (fields[2] !== 'on' && fields[2] !== 'off')) return null;\n return fields[2] === 'on';\n}\n\n// Old-vs-new on/off for every changed feature key, or null when a segment can't be parsed back\n// out of `before` or `after`, or when it parses to the same state on both sides (should never\n// happen for a genuinely changed key) -- either way the caller takes the full rebuild.\nexport function classifyFeatureToggles(before: string, after: string, changedKeys: ReadonlySet<string>): FeatureToggle[] | null {\n const toggles: FeatureToggle[] = [];\n for (const key of changedKeys) {\n const name = key.slice('feature:'.length) as FeatureName;\n const wasOn = parseOnOff(before, name);\n const isOn = parseOnOff(after, name);\n if (wasOn === null || isOn === null || wasOn === isOn) return null;\n toggles.push({ name, turnedOn: isOn });\n }\n return toggles;\n}\n"],"names":["NARROW_FEATURE_TABLE","classifyFeatureToggles","isFeatureOnlyChange","tags","sections","links","NARROW_FEATURE_NAMES","Set","Object","keys","changedKeys","size","every","key","startsWith","has","slice","length","parseOnOff","sig","name","part","split","find","p","undefined","fields","before","after","toggles","wasOn","isOn","push","turnedOn"],"mappings":";;;;;;;;;;;QAQaA;eAAAA;;QA+BGC;eAAAA;;QAjBAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAdT,IAAMF,uBAAyD;IAAEG,MAAM;IAAQC,UAAU;IAAYC,OAAO;AAAQ;AAE3H,iGAAiG;AACjG,8FAA8F;AAC9F,kGAAkG;AAClG,IAAMC,uBAA4C,IAAIC,IAAI,AAAC,qBAAGC,OAAOC,IAAI,CAACT,8BAAhB;IAAuC;CAAO;AASjG,SAASE,oBAAoBQ,WAAgC;IAClE,OAAOA,YAAYC,IAAI,GAAG,KAAK,AAAC,qBAAGD,aAAaE,KAAK,CAAC,SAACC;eAAQA,IAAIC,UAAU,CAAC,eAAeR,qBAAqBS,GAAG,CAACF,IAAIG,KAAK,CAAC,WAAWC,MAAM;;AACnJ;AAEA,+FAA+F;AAC/F,4FAA4F;AAC5F,SAASC,WAAWC,GAAW,EAAEC,IAAY;IAC3C,IAAMC,OAAOF,IAAIG,KAAK,CAAC,KAAKC,IAAI,CAAC,SAACC;eAAMA,EAAEV,UAAU,CAAC,AAAC,WAAe,OAALM,MAAK;;IACrE,IAAIC,SAASI,WAAW,OAAO;IAC/B,IAAMC,SAASL,KAAKC,KAAK,CAAC;IAC1B,IAAII,OAAOT,MAAM,KAAK,KAAMS,MAAM,CAAC,EAAE,KAAK,QAAQA,MAAM,CAAC,EAAE,KAAK,OAAQ,OAAO;IAC/E,OAAOA,MAAM,CAAC,EAAE,KAAK;AACvB;AAKO,SAASzB,uBAAuB0B,MAAc,EAAEC,KAAa,EAAElB,WAAgC;IACpG,IAAMmB,UAA2B,EAAE;QAC9B,kCAAA,2BAAA;;QAAL,QAAK,YAAanB,gCAAb,SAAA,6BAAA,QAAA,yBAAA,iCAA0B;YAA1B,IAAMG,MAAN;YACH,IAAMO,OAAOP,IAAIG,KAAK,CAAC,WAAWC,MAAM;YACxC,IAAMa,QAAQZ,WAAWS,QAAQP;YACjC,IAAMW,OAAOb,WAAWU,OAAOR;YAC/B,IAAIU,UAAU,QAAQC,SAAS,QAAQD,UAAUC,MAAM,OAAO;YAC9DF,QAAQG,IAAI,CAAC;gBAAEZ,MAAAA;gBAAMa,UAAUF;YAAK;QACtC;;QANK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAOL,OAAOF;AACT"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/index.ts"],"sourcesContent":["// Rows -> a backing store: registry + the public open/build boundary. Parsing lives in scan.ts;\n// everything beyond frontmatter + content lives in src/features/.\n\nimport type { ResolvedConfig, StoreName } from '../config/index.ts';\nimport { anyPresetEmbeds, storeName } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport { clearCache } from './cache.ts';\nimport { DB_FILENAME as DUCKDB_FILENAME, openDuckdb } from './duckdb/open.ts';\nimport { CAPABILITIES as DUCKDB_CAPABILITIES } from './duckdb/store.ts';\nimport type { BuildRequirement, InternalOpenOptions, OpenOptions, OpenResult } from './open.ts';\nimport { openSqlite, DB_FILENAME as SQLITE_FILENAME } from './sqlite/open.ts';\nimport { CAPABILITIES as SQLITE_CAPABILITIES } from './sqlite/store.ts';\nimport type { Stages } from './stages.ts';\nimport { openTurso, DB_FILENAME as TURSO_FILENAME } from './turso/open.ts';\nimport { CAPABILITIES as TURSO_CAPABILITIES } from './turso/store.ts';\nimport type { Capability } from './types.ts';\n\ninterface StoreEntry {\n capabilities: ReadonlySet<Capability>;\n filename: string;\n open: (cfg: ResolvedConfig, options?: InternalOpenOptions) => Promise<OpenResult>;\n}\n\nconst REGISTRY: Record<StoreName, StoreEntry> = {\n sqlite: { capabilities: SQLITE_CAPABILITIES, filename: SQLITE_FILENAME, open: openSqlite },\n duckdb: { capabilities: DUCKDB_CAPABILITIES, filename: DUCKDB_FILENAME, open: openDuckdb },\n turso: { capabilities: TURSO_CAPABILITIES, filename: TURSO_FILENAME, open: openTurso },\n};\n\nfunction entryFor(name: StoreName): StoreEntry {\n const entry = REGISTRY[name];\n if (!entry) throw new SenseError('STORE_UNKNOWN', `unknown backing store \"${name}\"; available: ${Object.keys(REGISTRY).join(', ')}`);\n return entry;\n}\n\nfunction requirementsFor(cfg: ResolvedConfig): Set<BuildRequirement> {\n const requirements = new Set<BuildRequirement>(['core', 'lexical']);\n if (anyPresetEmbeds(cfg)) requirements.add('vectors');\n return requirements;\n}\n\nfunction validateRequirements(cfg: ResolvedConfig, entry: StoreEntry, requirements: ReadonlySet<BuildRequirement>): void {\n if (requirements.has('vectors') && anyPresetEmbeds(cfg) && !entry.capabilities.has('vectors')) {\n const name = storeName(cfg);\n throw new SenseError('STORE_CAPABILITY_MISSING', `store \"${name}\" does not implement \"vectors\" in this build, but this config's \"embed\" block is in use by at least one preset; remove or narrow it, or set \"store\" to a store that supports vectors (sqlite)`);\n }\n}\n\nexport async function openStoreFor(cfg: ResolvedConfig, options: InternalOpenOptions): Promise<OpenResult> {\n options.signal?.throwIfAborted();\n const entry = entryFor(storeName(cfg));\n validateRequirements(cfg, entry, options.requirements ?? new Set<BuildRequirement>(['core']));\n return entry.open(cfg, options);\n}\n\n/** Opens a store through the root `open` API, preparing capabilities unless `build` is `false`. */\nexport async function openStore(cfg: ResolvedConfig, options: OpenOptions = {}): Promise<OpenResult> {\n const buildEnabled = options.build !== false;\n return openStoreFor(cfg, {\n build: buildEnabled,\n requirements: buildEnabled ? requirementsFor(cfg) : new Set<BuildRequirement>(['core']),\n signal: options.signal,\n });\n}\n\nexport async function lexicalReadiness(cfg: ResolvedConfig): Promise<{ ready: boolean; error: string | null }> {\n let opened: OpenResult;\n try {\n opened = await openStoreFor(cfg, { build: false, requirements: new Set<BuildRequirement>(['core', 'lexical']) });\n } catch (err) {\n if (err instanceof SenseError && err.code === 'INDEX_NOT_READY') return { ready: false, error: err.message };\n throw err;\n }\n try {\n return { ready: true, error: null };\n } finally {\n await opened.store.close();\n }\n}\n\n/** Options for the root `build(config, options)` API. */\nexport interface BuildOptions {\n /** Recreates the derived cache before building. */\n force?: boolean;\n /** Cancels supported provider I/O and stops between phases after active native work finishes. */\n signal?: AbortSignal;\n}\n\nexport interface BuildResult {\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n stages: Stages;\n}\n\n/** Builds every configured capability, waiting for active native work and cleanup before settling. */\nexport async function buildIndex(cfg: ResolvedConfig, options: BuildOptions = {}): Promise<BuildResult> {\n options.signal?.throwIfAborted();\n if (options.force) clearCache(cfg);\n const opened = await openStoreFor(cfg, { build: true, requirements: requirementsFor(cfg), signal: options.signal });\n try {\n const { store: _store, ...result } = opened;\n return result;\n } finally {\n await opened.store.close();\n }\n}\n\nexport function storeFilename(cfg: ResolvedConfig): string {\n return entryFor(storeName(cfg)).filename;\n}\n\nexport type { OpenOptions, OpenResult } from './open.ts';\nexport { docCount } from './open.ts';\nexport { getMeta, setMeta } from './shared.ts';\nexport { DB_FILENAME, SCHEMA_VERSION } from './sqlite/open.ts';\nexport type { Stages } from './stages.ts';\nexport type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.ts';\nexport { CAPABILITY_NAMES } from './types.ts';\nexport { clearCache };\n"],"names":["CAPABILITY_NAMES","DB_FILENAME","SCHEMA_VERSION","buildIndex","clearCache","docCount","getMeta","lexicalReadiness","openStore","openStoreFor","setMeta","storeFilename","REGISTRY","sqlite","capabilities","SQLITE_CAPABILITIES","filename","SQLITE_FILENAME","open","openSqlite","duckdb","DUCKDB_CAPABILITIES","DUCKDB_FILENAME","openDuckdb","turso","TURSO_CAPABILITIES","TURSO_FILENAME","openTurso","entryFor","name","entry","SenseError","Object","keys","join","requirementsFor","cfg","requirements","Set","anyPresetEmbeds","add","validateRequirements","has","storeName","options","signal","throwIfAborted","buildEnabled","build","opened","err","code","ready","error","message","store","close","_store","result","force"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/index.ts"],"sourcesContent":["// Rows -> a backing store: registry + the public open/build boundary. Parsing lives in scan.ts;\n// everything beyond frontmatter + content lives in src/features/.\n\nimport type { ResolvedConfig, StoreName } from '../config/index.ts';\nimport { anyPresetEmbeds, storeName } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport { clearCache } from './cache.ts';\nimport { DB_FILENAME as DUCKDB_FILENAME, openDuckdb } from './duckdb/open.ts';\nimport { CAPABILITIES as DUCKDB_CAPABILITIES } from './duckdb/store.ts';\nimport type { BuildRequirement, InternalOpenOptions, OpenOptions, OpenResult } from './open.ts';\nimport { openSqlite, DB_FILENAME as SQLITE_FILENAME } from './sqlite/open.ts';\nimport { CAPABILITIES as SQLITE_CAPABILITIES } from './sqlite/store.ts';\nimport type { Stages } from './stages.ts';\nimport { openTurso, DB_FILENAME as TURSO_FILENAME } from './turso/open.ts';\nimport { CAPABILITIES as TURSO_CAPABILITIES } from './turso/store.ts';\nimport type { Capability } from './types.ts';\n\ninterface StoreEntry {\n capabilities: ReadonlySet<Capability>;\n filename: string;\n open: (cfg: ResolvedConfig, options?: InternalOpenOptions) => Promise<OpenResult>;\n}\n\nconst REGISTRY: Record<StoreName, StoreEntry> = {\n sqlite: { capabilities: SQLITE_CAPABILITIES, filename: SQLITE_FILENAME, open: openSqlite },\n duckdb: { capabilities: DUCKDB_CAPABILITIES, filename: DUCKDB_FILENAME, open: openDuckdb },\n turso: { capabilities: TURSO_CAPABILITIES, filename: TURSO_FILENAME, open: openTurso },\n};\n\nfunction entryFor(name: StoreName): StoreEntry {\n const entry = REGISTRY[name];\n if (!entry) throw new SenseError('STORE_UNKNOWN', `unknown backing store \"${name}\"; available: ${Object.keys(REGISTRY).join(', ')}`);\n return entry;\n}\n\nfunction requirementsFor(cfg: ResolvedConfig): Set<BuildRequirement> {\n const requirements = new Set<BuildRequirement>(['core', 'lexical']);\n if (anyPresetEmbeds(cfg)) requirements.add('vectors');\n return requirements;\n}\n\nfunction validateRequirements(cfg: ResolvedConfig, entry: StoreEntry, requirements: ReadonlySet<BuildRequirement>): void {\n if (requirements.has('vectors') && anyPresetEmbeds(cfg) && !entry.capabilities.has('vectors')) {\n const name = storeName(cfg);\n throw new SenseError('STORE_CAPABILITY_MISSING', `store \"${name}\" does not implement \"vectors\" in this build, but this config's \"embed\" block is in use by at least one preset; remove or narrow it, or set \"store\" to a store that supports vectors (sqlite)`);\n }\n}\n\nexport async function openStoreFor(cfg: ResolvedConfig, options: InternalOpenOptions): Promise<OpenResult> {\n options.signal?.throwIfAborted();\n const entry = entryFor(storeName(cfg));\n validateRequirements(cfg, entry, options.requirements ?? new Set<BuildRequirement>(['core']));\n return entry.open(cfg, options);\n}\n\n/** Opens a store through the root `open` API, preparing capabilities unless `build` is `false`. */\nexport async function openStore(cfg: ResolvedConfig, options: OpenOptions = {}): Promise<OpenResult> {\n const buildEnabled = options.build !== false;\n return openStoreFor(cfg, {\n build: buildEnabled,\n requirements: buildEnabled ? requirementsFor(cfg) : new Set<BuildRequirement>(['core']),\n signal: options.signal,\n });\n}\n\nexport async function lexicalReadiness(cfg: ResolvedConfig): Promise<{ ready: boolean; error: string | null }> {\n let opened: OpenResult;\n try {\n opened = await openStoreFor(cfg, { build: false, requirements: new Set<BuildRequirement>(['core', 'lexical']) });\n } catch (err) {\n if (err instanceof SenseError && err.code === 'INDEX_NOT_READY') return { ready: false, error: err.message };\n throw err;\n }\n try {\n return { ready: true, error: null };\n } finally {\n await opened.store.close();\n }\n}\n\n/** Options for the root `build(config, options)` API. */\nexport interface BuildOptions {\n /** Recreates the derived cache before building. */\n force?: boolean;\n /** Cancels supported provider I/O and stops between phases after active native work finishes. */\n signal?: AbortSignal;\n}\n\nexport interface BuildResult {\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n stages: Stages;\n}\n\n/** Builds every configured capability, waiting for active native work and cleanup before settling. */\nexport async function buildIndex(cfg: ResolvedConfig, options: BuildOptions = {}): Promise<BuildResult> {\n options.signal?.throwIfAborted();\n if (options.force) clearCache(cfg);\n const opened = await openStoreFor(cfg, { build: true, requirements: requirementsFor(cfg), signal: options.signal });\n try {\n const { store: _store, ...result } = opened;\n return result;\n } finally {\n await opened.store.close();\n }\n}\n\nexport function storeFilename(cfg: ResolvedConfig): string {\n return entryFor(storeName(cfg)).filename;\n}\n\nexport type { OpenOptions, OpenResult } from './open.ts';\nexport { docCount } from './open.ts';\nexport { getMeta, setMeta } from './shared.ts';\nexport { DB_FILENAME, SCHEMA_VERSION } from './sqlite/open.ts';\nexport type { Stages } from './stages.ts';\nexport type { Capability, Connection, DocumentStore, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './types.ts';\nexport { CAPABILITY_NAMES } from './types.ts';\nexport { clearCache };\n"],"names":["CAPABILITY_NAMES","DB_FILENAME","SCHEMA_VERSION","buildIndex","clearCache","docCount","getMeta","lexicalReadiness","openStore","openStoreFor","setMeta","storeFilename","REGISTRY","sqlite","capabilities","SQLITE_CAPABILITIES","filename","SQLITE_FILENAME","open","openSqlite","duckdb","DUCKDB_CAPABILITIES","DUCKDB_FILENAME","openDuckdb","turso","TURSO_CAPABILITIES","TURSO_FILENAME","openTurso","entryFor","name","entry","SenseError","Object","keys","join","requirementsFor","cfg","requirements","Set","anyPresetEmbeds","add","validateRequirements","has","storeName","options","signal","throwIfAborted","buildEnabled","build","opened","err","code","ready","error","message","store","close","_store","result","force"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/lock-wait.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { STATE_DIR } from '../config/index.ts';\n\n// duckdb/turso lock the cache file exclusively, so a waiter can't connect and read reconcile_max_ms\n// from meta; this sidecar is plain fs, readable while locked. Same derivation as busy_timeout (open.ts).\nconst SIDECAR_FILENAME = 'lock-wait.json';\nconst FLOOR_MS = 5_000;\nconst CEILING_MS = 600_000;\n\nfunction sidecarPath(configDir: string): string {\n return join(configDir, STATE_DIR, SIDECAR_FILENAME);\n}\n\nfunction readRecordedMs(configDir: string): number | undefined {\n try {\n const raw = JSON.parse(readFileSync(sidecarPath(configDir), 'utf8'));\n const value = raw.reconcile_max_ms;\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\n// Called after every reconcile's write transaction, every store alike, so a fresh cache records\n// its first write even when the measured duration is zero.\nexport function recordLockWaitMs(configDir: string, ms: number): void {\n const recordedMs = readRecordedMs(configDir);\n if (recordedMs !== undefined && ms <= recordedMs) return;\n try {\n writeFileSync(sidecarPath(configDir), JSON.stringify({ reconcile_max_ms: ms }));\n } catch {\n // Best-effort: a write failure here only narrows the next waiter's budget back to the floor.\n }\n}\n\n// 3x the largest reconcile this cache has recorded, floored and capped -- a waiter outlasts a\n// real reconcile and still fails behind a hung one.\nexport function lockWaitBudgetMs(configDir: string): number {\n return Math.min(Math.max(FLOOR_MS, 3 * (readRecordedMs(configDir) ?? 0)), CEILING_MS);\n}\n"],"names":["lockWaitBudgetMs","recordLockWaitMs","SIDECAR_FILENAME","FLOOR_MS","CEILING_MS","sidecarPath","configDir","join","STATE_DIR","readRecordedMs","raw","JSON","parse","readFileSync","value","reconcile_max_ms","Number","isFinite","undefined","ms","recordedMs","writeFileSync","stringify","Math","min","max"],"mappings":";;;;;;;;;;;QAsCgBA;eAAAA;;QAZAC;eAAAA;;;sBA1B4B;wBACvB;uBACK;AAE1B,oGAAoG;AACpG,yGAAyG;AACzG,IAAMC,mBAAmB;AACzB,IAAMC,WAAW;AACjB,IAAMC,aAAa;AAEnB,SAASC,YAAYC,SAAiB;IACpC,OAAOC,IAAAA,cAAI,EAACD,WAAWE,kBAAS,EAAEN;AACpC;AAEA,SAASO,eAAeH,SAAiB;IACvC,IAAI;QACF,IAAMI,MAAMC,KAAKC,KAAK,CAACC,IAAAA,oBAAY,EAACR,YAAYC,YAAY;QAC5D,IAAMQ,QAAQJ,IAAIK,gBAAgB;QAClC,OAAO,OAAOD,UAAU,YAAYE,OAAOC,QAAQ,CAACH,UAAUA,SAAS,IAAIA,QAAQI;IACrF,EAAE,eAAM;QACN,OAAOA;IACT;AACF;AAIO,SAASjB,iBAAiBK,SAAiB,EAAEa,EAAU;IAC5D,IAAMC,aAAaX,eAAeH;IAClC,IAAIc,eAAeF,aAAaC,MAAMC,YAAY;IAClD,IAAI;QACFC,IAAAA,qBAAa,EAAChB,YAAYC,YAAYK,KAAKW,SAAS,CAAC;YAAEP,kBAAkBI;QAAG;IAC9E,EAAE,eAAM;IACN,6FAA6F;IAC/F;AACF;AAIO,SAASnB,iBAAiBM,SAAiB;QACRG;IAAxC,OAAOc,KAAKC,GAAG,CAACD,KAAKE,GAAG,CAACtB,UAAU,MAAKM,kBAAAA,eAAeH,wBAAfG,6BAAAA,kBAA6B,KAAKL;AAC5E"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/lock-wait.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { STATE_DIR } from '../config/index.ts';\n\n// duckdb/turso lock the cache file exclusively, so a waiter can't connect and read reconcile_max_ms\n// from meta; this sidecar is plain fs, readable while locked. Same derivation as busy_timeout (open.ts).\nconst SIDECAR_FILENAME = 'lock-wait.json';\nconst FLOOR_MS = 5_000;\nconst CEILING_MS = 600_000;\n\nfunction sidecarPath(configDir: string): string {\n return join(configDir, STATE_DIR, SIDECAR_FILENAME);\n}\n\nfunction readRecordedMs(configDir: string): number | undefined {\n try {\n const raw = JSON.parse(readFileSync(sidecarPath(configDir), 'utf8'));\n const value = raw.reconcile_max_ms;\n return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;\n } catch {\n return undefined;\n }\n}\n\n// Called after every reconcile's write transaction, every store alike, so a fresh cache records\n// its first write even when the measured duration is zero.\nexport function recordLockWaitMs(configDir: string, ms: number): void {\n const recordedMs = readRecordedMs(configDir);\n if (recordedMs !== undefined && ms <= recordedMs) return;\n try {\n writeFileSync(sidecarPath(configDir), JSON.stringify({ reconcile_max_ms: ms }));\n } catch {\n // Best-effort: a write failure here only narrows the next waiter's budget back to the floor.\n }\n}\n\n// 3x the largest reconcile this cache has recorded, floored and capped -- a waiter outlasts a\n// real reconcile and still fails behind a hung one.\nexport function lockWaitBudgetMs(configDir: string): number {\n return Math.min(Math.max(FLOOR_MS, 3 * (readRecordedMs(configDir) ?? 0)), CEILING_MS);\n}\n"],"names":["lockWaitBudgetMs","recordLockWaitMs","SIDECAR_FILENAME","FLOOR_MS","CEILING_MS","sidecarPath","configDir","join","STATE_DIR","readRecordedMs","raw","JSON","parse","readFileSync","value","reconcile_max_ms","Number","isFinite","undefined","ms","recordedMs","writeFileSync","stringify","Math","min","max"],"mappings":";;;;;;;;;;;QAsCgBA;eAAAA;;QAZAC;eAAAA;;;sBA1B4B;wBACvB;uBACK;AAE1B,oGAAoG;AACpG,yGAAyG;AACzG,IAAMC,mBAAmB;AACzB,IAAMC,WAAW;AACjB,IAAMC,aAAa;AAEnB,SAASC,YAAYC,SAAiB;IACpC,OAAOC,IAAAA,cAAI,EAACD,WAAWE,kBAAS,EAAEN;AACpC;AAEA,SAASO,eAAeH,SAAiB;IACvC,IAAI;QACF,IAAMI,MAAMC,KAAKC,KAAK,CAACC,IAAAA,oBAAY,EAACR,YAAYC,YAAY;QAC5D,IAAMQ,QAAQJ,IAAIK,gBAAgB;QAClC,OAAO,OAAOD,UAAU,YAAYE,OAAOC,QAAQ,CAACH,UAAUA,SAAS,IAAIA,QAAQI;IACrF,EAAE,eAAM;QACN,OAAOA;IACT;AACF;AAIO,SAASjB,iBAAiBK,SAAiB,EAAEa,EAAU;IAC5D,IAAMC,aAAaX,eAAeH;IAClC,IAAIc,eAAeF,aAAaC,MAAMC,YAAY;IAClD,IAAI;QACFC,IAAAA,qBAAa,EAAChB,YAAYC,YAAYK,KAAKW,SAAS,CAAC;YAAEP,kBAAkBI;QAAG;IAC9E,EAAE,eAAM;IACN,6FAA6F;IAC/F;AACF;AAIO,SAASnB,iBAAiBM,SAAiB;QACRG;IAAxC,OAAOc,KAAKC,GAAG,CAACD,KAAKE,GAAG,CAACtB,UAAU,MAAKM,kBAAAA,eAAeH,wBAAfG,6BAAAA,kBAA6B,KAAKL;AAC5E"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/native.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport Module from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SenseError } from '../errors.ts';\n\n// A store's optional native package, and the strings its error messages and install notice name.\nexport interface NativeDescriptor {\n store: string;\n pkg: string;\n sizeHint: string;\n /** Optional exact package version required by this native binding. */\n version?: string;\n /** npm specifier used only when installation is required (imports stay bare). */\n installSpec?: string;\n}\n\n// install-module-linked is small, but a target native package can be large (@duckdb/node-api's\n// ~110MB), so it is required lazily inside the gated branch below, not for every store/index.ts load.\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\nconst _dirname = dirname(typeof __filename !== 'undefined' ? __filename : fileURLToPath(import.meta.url));\n\n// Walks up from this file's own directory rather than a fixed dot-count: it sits at a\n// different depth under src/ than under built dist/{cjs,esm}/store output.\nexport function packageNodeModules(): string {\n let dir = _dirname;\n for (;;) {\n const candidate = join(dir, 'package.json');\n if (existsSync(candidate)) {\n const pkg = JSON.parse(readFileSync(candidate, 'utf8')) as { name?: string };\n if (pkg.name === 'sensemaking') return join(dir, 'node_modules');\n }\n const parent = dirname(dir);\n if (parent === dir) throw new Error('could not locate the sensemaking package root to install a native dependency into');\n dir = parent;\n }\n}\n\nconst installing = new Map<string, Promise<void>>();\n\n// De-dupes concurrent installs: since the install is async, concurrent callers await the same\n// in-flight promise, keyed by specifier and target. A failed install is not cached, so a later call retries.\nfunction installOnce(specifier: string, nodeModulesPath: string): Promise<void> {\n const key = `${specifier}\\n${nodeModulesPath}`;\n let promise = installing.get(key);\n if (!promise) {\n const installModuleLinked = (_require('install-module-linked') as { default: (specifier: string, nodeModulesPath: string) => Promise<string> }).default;\n promise = installModuleLinked(specifier, nodeModulesPath).then(\n () => {},\n (err) => {\n installing.delete(key);\n throw err;\n }\n );\n installing.set(key, promise);\n }\n return promise;\n}\n\n// Node caches a bare specifier's resolution, including a \"not found\" miss, for the process\n// lifetime; use the installed entry directly, as a URL for ESM and a path for CJS.\nfunction resolveEntrySpecifier(importName: string, nodeModulesPath: string): string {\n const pkgDir = join(nodeModulesPath, ...importName.split('/'));\n const pkg = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')) as { main?: string; exports?: string };\n const entry = typeof pkg.exports === 'string' ? pkg.exports : (pkg.main ?? 'index.js');\n const entryPath = join(pkgDir, entry);\n return typeof require === 'undefined' ? pathToFileURL(entryPath).href : entryPath;\n}\n\ntype PackageMetadata = { name?: string; version?: string };\n\nfunction readPackageMetadata(pkgDir: string): PackageMetadata | undefined {\n try {\n return JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')) as PackageMetadata;\n } catch {\n return undefined;\n }\n}\n\nfunction targetPackageMetadata(importName: string, nodeModulesPath: string): { exists: boolean; metadata?: PackageMetadata } {\n const pkgDir = join(nodeModulesPath, ...importName.split('/'));\n return { exists: existsSync(pkgDir), metadata: readPackageMetadata(pkgDir) };\n}\n\nfunction resolvedPackageMetadata(importName: string): PackageMetadata | undefined {\n try {\n let dir = dirname(_require.resolve(importName));\n for (;;) {\n const manifest = join(dir, 'package.json');\n if (existsSync(manifest)) {\n const pkg = readPackageMetadata(dir);\n if (!pkg) return undefined;\n if (pkg.name === importName) return pkg;\n }\n const parent = dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n } catch {\n return undefined;\n }\n}\n\nfunction versionContractError(descriptor: NativeDescriptor, installed?: string): SenseError {\n const installSpec = descriptor.installSpec ?? descriptor.pkg;\n const detail = installed ? `${descriptor.pkg}@${installed} is installed` : `${descriptor.pkg} has missing or unreadable version metadata`;\n return new SenseError('STORE_DEPENDENCY_MISSING', `store \"${descriptor.store}\" needs ${installSpec}, but ${detail}; refusing to overwrite it -- run \\`npm install ${installSpec}\\` yourself and try again`);\n}\n\nfunction assertExpectedVersion(descriptor: NativeDescriptor, metadata: PackageMetadata | undefined): void {\n if (!descriptor.version) return;\n if (!metadata?.version || metadata.version !== descriptor.version) throw versionContractError(descriptor, metadata?.version);\n}\n\n// Import-then-install-then-retry, over an injectable importName so the failure path can be\n// exercised in tests without a real native binding. Thrown errors always name descriptor.pkg.\nexport async function loadOrInstall<T>(descriptor: NativeDescriptor, nodeModulesPath: string, importName: string = descriptor.pkg): Promise<T> {\n if (descriptor.version) {\n const target = targetPackageMetadata(importName, nodeModulesPath);\n if (target.exists) assertExpectedVersion(descriptor, target.metadata);\n }\n let loaded: T;\n try {\n loaded = (await import(importName)) as T;\n } catch {\n const installSpec = descriptor.installSpec ?? importName;\n const displaySpec = descriptor.installSpec ?? descriptor.pkg;\n console.error(`sense: store \"${descriptor.store}\" needs ${displaySpec}; installing it now (one-time download, ${descriptor.sizeHint})...`);\n try {\n await installOnce(installSpec, nodeModulesPath);\n } catch (installErr) {\n throw new SenseError(\n 'STORE_DEPENDENCY_MISSING',\n `store \"${descriptor.store}\" needs ${displaySpec}, and installing it automatically failed (${(installErr as Error).message}); this can happen offline, in a sandboxed environment, or when node_modules is read-only or owned by another user (e.g. under a global install) -- run \\`npm install ${displaySpec}\\` yourself and try again`\n );\n }\n try {\n const loaded = (await import(resolveEntrySpecifier(importName, nodeModulesPath))) as T;\n assertExpectedVersion(descriptor, targetPackageMetadata(importName, nodeModulesPath).metadata);\n return loaded;\n } catch (loadErr) {\n throw new SenseError('STORE_DEPENDENCY_MISSING', `store \"${descriptor.store}\" installed ${displaySpec} but it could not be loaded (${(loadErr as Error).message}); it may not be available for this platform (${process.platform}-${process.arch}) -- run \\`npm install ${displaySpec}\\` to see the underlying error`);\n }\n }\n if (descriptor.version) assertExpectedVersion(descriptor, resolvedPackageMetadata(importName));\n return loaded;\n}\n"],"names":["loadOrInstall","packageNodeModules","_require","require","Module","createRequire","_dirname","dirname","__filename","fileURLToPath","dir","candidate","join","existsSync","pkg","JSON","parse","readFileSync","name","parent","Error","installing","Map","installOnce","specifier","nodeModulesPath","key","promise","get","installModuleLinked","default","then","err","delete","set","resolveEntrySpecifier","importName","pkgDir","split","entry","exports","main","entryPath","pathToFileURL","href","readPackageMetadata","undefined","targetPackageMetadata","exists","metadata","resolvedPackageMetadata","resolve","manifest","versionContractError","descriptor","installed","installSpec","detail","SenseError","store","assertExpectedVersion","version","target","loaded","displaySpec","installErr","loadErr","console","error","sizeHint","message","process","platform","arch"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/native.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport Module from 'node:module';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SenseError } from '../errors.ts';\n\n// A store's optional native package, and the strings its error messages and install notice name.\nexport interface NativeDescriptor {\n store: string;\n pkg: string;\n sizeHint: string;\n /** Optional exact package version required by this native binding. */\n version?: string;\n /** npm specifier used only when installation is required (imports stay bare). */\n installSpec?: string;\n}\n\n// install-module-linked is small, but a target native package can be large (@duckdb/node-api's\n// ~110MB), so it is required lazily inside the gated branch below, not for every store/index.ts load.\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\nconst _dirname = dirname(typeof __filename !== 'undefined' ? __filename : fileURLToPath(import.meta.url));\n\n// Walks up from this file's own directory rather than a fixed dot-count: it sits at a\n// different depth under src/ than under built dist/{cjs,esm}/store output.\nexport function packageNodeModules(): string {\n let dir = _dirname;\n for (;;) {\n const candidate = join(dir, 'package.json');\n if (existsSync(candidate)) {\n const pkg = JSON.parse(readFileSync(candidate, 'utf8')) as { name?: string };\n if (pkg.name === 'sensemaking') return join(dir, 'node_modules');\n }\n const parent = dirname(dir);\n if (parent === dir) throw new Error('could not locate the sensemaking package root to install a native dependency into');\n dir = parent;\n }\n}\n\nconst installing = new Map<string, Promise<void>>();\n\n// De-dupes concurrent installs: since the install is async, concurrent callers await the same\n// in-flight promise, keyed by specifier and target. A failed install is not cached, so a later call retries.\nfunction installOnce(specifier: string, nodeModulesPath: string): Promise<void> {\n const key = `${specifier}\\n${nodeModulesPath}`;\n let promise = installing.get(key);\n if (!promise) {\n const installModuleLinked = (_require('install-module-linked') as { default: (specifier: string, nodeModulesPath: string) => Promise<string> }).default;\n promise = installModuleLinked(specifier, nodeModulesPath).then(\n () => {},\n (err) => {\n installing.delete(key);\n throw err;\n }\n );\n installing.set(key, promise);\n }\n return promise;\n}\n\n// Node caches a bare specifier's resolution, including a \"not found\" miss, for the process\n// lifetime; use the installed entry directly, as a URL for ESM and a path for CJS.\nfunction resolveEntrySpecifier(importName: string, nodeModulesPath: string): string {\n const pkgDir = join(nodeModulesPath, ...importName.split('/'));\n const pkg = JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')) as { main?: string; exports?: string };\n const entry = typeof pkg.exports === 'string' ? pkg.exports : (pkg.main ?? 'index.js');\n const entryPath = join(pkgDir, entry);\n return typeof require === 'undefined' ? pathToFileURL(entryPath).href : entryPath;\n}\n\ntype PackageMetadata = { name?: string; version?: string };\n\nfunction readPackageMetadata(pkgDir: string): PackageMetadata | undefined {\n try {\n return JSON.parse(readFileSync(join(pkgDir, 'package.json'), 'utf8')) as PackageMetadata;\n } catch {\n return undefined;\n }\n}\n\nfunction targetPackageMetadata(importName: string, nodeModulesPath: string): { exists: boolean; metadata?: PackageMetadata } {\n const pkgDir = join(nodeModulesPath, ...importName.split('/'));\n return { exists: existsSync(pkgDir), metadata: readPackageMetadata(pkgDir) };\n}\n\nfunction resolvedPackageMetadata(importName: string): PackageMetadata | undefined {\n try {\n let dir = dirname(_require.resolve(importName));\n for (;;) {\n const manifest = join(dir, 'package.json');\n if (existsSync(manifest)) {\n const pkg = readPackageMetadata(dir);\n if (!pkg) return undefined;\n if (pkg.name === importName) return pkg;\n }\n const parent = dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n } catch {\n return undefined;\n }\n}\n\nfunction versionContractError(descriptor: NativeDescriptor, installed?: string): SenseError {\n const installSpec = descriptor.installSpec ?? descriptor.pkg;\n const detail = installed ? `${descriptor.pkg}@${installed} is installed` : `${descriptor.pkg} has missing or unreadable version metadata`;\n return new SenseError('STORE_DEPENDENCY_MISSING', `store \"${descriptor.store}\" needs ${installSpec}, but ${detail}; refusing to overwrite it -- run \\`npm install ${installSpec}\\` yourself and try again`);\n}\n\nfunction assertExpectedVersion(descriptor: NativeDescriptor, metadata: PackageMetadata | undefined): void {\n if (!descriptor.version) return;\n if (!metadata?.version || metadata.version !== descriptor.version) throw versionContractError(descriptor, metadata?.version);\n}\n\n// Import-then-install-then-retry, over an injectable importName so the failure path can be\n// exercised in tests without a real native binding. Thrown errors always name descriptor.pkg.\nexport async function loadOrInstall<T>(descriptor: NativeDescriptor, nodeModulesPath: string, importName: string = descriptor.pkg): Promise<T> {\n if (descriptor.version) {\n const target = targetPackageMetadata(importName, nodeModulesPath);\n if (target.exists) assertExpectedVersion(descriptor, target.metadata);\n }\n let loaded: T;\n try {\n loaded = (await import(importName)) as T;\n } catch {\n const installSpec = descriptor.installSpec ?? importName;\n const displaySpec = descriptor.installSpec ?? descriptor.pkg;\n console.error(`sense: store \"${descriptor.store}\" needs ${displaySpec}; installing it now (one-time download, ${descriptor.sizeHint})...`);\n try {\n await installOnce(installSpec, nodeModulesPath);\n } catch (installErr) {\n throw new SenseError(\n 'STORE_DEPENDENCY_MISSING',\n `store \"${descriptor.store}\" needs ${displaySpec}, and installing it automatically failed (${(installErr as Error).message}); this can happen offline, in a sandboxed environment, or when node_modules is read-only or owned by another user (e.g. under a global install) -- run \\`npm install ${displaySpec}\\` yourself and try again`\n );\n }\n try {\n const loaded = (await import(resolveEntrySpecifier(importName, nodeModulesPath))) as T;\n assertExpectedVersion(descriptor, targetPackageMetadata(importName, nodeModulesPath).metadata);\n return loaded;\n } catch (loadErr) {\n throw new SenseError('STORE_DEPENDENCY_MISSING', `store \"${descriptor.store}\" installed ${displaySpec} but it could not be loaded (${(loadErr as Error).message}); it may not be available for this platform (${process.platform}-${process.arch}) -- run \\`npm install ${displaySpec}\\` to see the underlying error`);\n }\n }\n if (descriptor.version) assertExpectedVersion(descriptor, resolvedPackageMetadata(importName));\n return loaded;\n}\n"],"names":["loadOrInstall","packageNodeModules","_require","require","Module","createRequire","_dirname","dirname","__filename","fileURLToPath","dir","candidate","join","existsSync","pkg","JSON","parse","readFileSync","name","parent","Error","installing","Map","installOnce","specifier","nodeModulesPath","key","promise","get","installModuleLinked","default","then","err","delete","set","resolveEntrySpecifier","importName","pkgDir","split","entry","exports","main","entryPath","pathToFileURL","href","readPackageMetadata","undefined","targetPackageMetadata","exists","metadata","resolvedPackageMetadata","resolve","manifest","versionContractError","descriptor","installed","installSpec","detail","SenseError","store","assertExpectedVersion","version","target","loaded","displaySpec","installErr","loadErr","console","error","sizeHint","message","process","platform","arch"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/open.ts"],"sourcesContent":["import { channel } from 'node:diagnostics_channel';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ResolvedConfig } from '../config/index.ts';\nimport { anyPresetEmbeds, featureSignature, STATE_DIR } from '../config/index.ts';\nimport { rekeyChunkText } from '../embed/handoff.ts';\nimport { embedPending } from '../embed/query.ts';\nimport type { EmbedCallOptions } from '../embed/types.ts';\nimport { SenseError } from '../errors.ts';\nimport { FEATURES } from '../features/index.ts';\nimport { createBuilder } from './builder.ts';\nimport { clearCache } from './cache.ts';\nimport { lockWaitBudgetMs } from './lock-wait.ts';\nimport { CORE_READY_META_KEY, FEATURE_SIGNATURE_META_KEY, isCoreReady, isPublishedFeatureSignature } from './readiness.ts';\nimport { getMeta } from './shared.ts';\nimport { changedSignatureKeys, embedIdentityAdopted } from './signature.ts';\nimport type { Stages } from './stages.ts';\nimport { stageRecorder } from './stages.ts';\nimport { withTransaction } from './transaction.ts';\nimport type { Connection, OpenDialect, Store } from './types.ts';\n\nexport type BuildRequirement = 'core' | 'lexical' | 'vectors';\n\n/** Options for the root `open(config, options)` API. */\nexport interface OpenOptions {\n /** Prepares configured capabilities by default; `false` opens compatible published state without repair. */\n build?: boolean;\n /** Cancels supported provider I/O and stops between phases after active native work finishes. */\n signal?: AbortSignal;\n}\n\nexport interface InternalOpenOptions extends OpenOptions {\n requirements?: ReadonlySet<BuildRequirement>;\n}\n\nexport interface OpenResult {\n store: Store;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n stages: Stages;\n}\n\ninterface ConnectResult<Handle> {\n handle: Handle;\n conn: Connection;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n stages: Stages;\n observational: boolean;\n}\n\nconst LOCK_POLL_MS = 50;\nconst lockWait = channel('sensemaking.store.lock-wait');\n\nfunction notReady(reason: string): SenseError {\n return new SenseError('INDEX_NOT_READY', `${reason}; run \"sense build\" or call build(config) before opening with { build: false }`);\n}\n\nfunction normaliseConfig(cfg: ResolvedConfig): ResolvedConfig {\n // `baseDir` was the original public open() input. Keep direct API callers working while\n // making the two ownership paths explicit for every internal operation.\n if (!cfg.rootDir) {\n if (!cfg.baseDir) throw new SenseError('CONFIG_INVALID', 'open requires rootDir (or legacy baseDir)');\n cfg.rootDir = cfg.baseDir;\n }\n if (!cfg.configDir) cfg.configDir = cfg.rootDir;\n return cfg;\n}\n\nfunction cachePath<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): string {\n return join(cfg.configDir ?? cfg.baseDir, STATE_DIR, dialect.filename);\n}\n\nasync function connectUnlocked<Handle>(dbPath: string, cfg: ResolvedConfig, configDir: string, dialect: OpenDialect<Handle>, options: { existingOnly: boolean; observational: boolean }): Promise<{ handle: Handle; conn: Connection }> {\n const budgetMs = lockWaitBudgetMs(configDir);\n const deadline = Date.now() + budgetMs;\n for (;;) {\n try {\n return await dialect.connect(dbPath, cfg, options);\n } catch (err) {\n if (options.existingOnly && !existsSync(dbPath)) {\n throw notReady(`the derived index does not exist at ${dbPath}`);\n }\n if (!dialect.isLocked?.(err as Error)) throw err;\n if (lockWait.hasSubscribers) lockWait.publish({ store: cfg.store, dbPath });\n if (Date.now() >= deadline) {\n throw new SenseError('STORE_BUSY', `another sense process is using this tree's ${cfg.store} cache (${dbPath}) and did not release it within ${Math.round(budgetMs / 1000)}s; wait for that command to finish, or set \"store\" to \"sqlite\" in sense.config.json, which serves concurrent commands`);\n }\n await new Promise((resolve) => setTimeout(resolve, LOCK_POLL_MS));\n }\n }\n}\n\nasync function assertCoreSchema(conn: Connection): Promise<void> {\n for (const table of ['frontmatter', 'content', 'preset_files', 'indexed_sources']) {\n await (await conn.prepare(`SELECT 1 FROM ${table} LIMIT 0`)).all();\n }\n}\n\nasync function connectExisting<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>, requirements: ReadonlySet<BuildRequirement>): Promise<ConnectResult<Handle>> {\n const configDir = cfg.configDir ?? cfg.baseDir;\n const dbPath = cachePath(cfg, dialect);\n if (!existsSync(dbPath)) throw notReady(`the derived index does not exist at ${dbPath}`);\n\n const { handle, conn } = await connectUnlocked(dbPath, cfg, configDir, dialect, { existingOnly: true, observational: true });\n try {\n let state: { version: string | null; features: string | null; ready: string | null };\n try {\n state = await withTransaction(conn, async () => {\n const version = await getMeta(conn, 'schema_version');\n const features = await getMeta(conn, FEATURE_SIGNATURE_META_KEY);\n const ready = await getMeta(conn, CORE_READY_META_KEY);\n await assertCoreSchema(conn);\n return { version, features, ready };\n });\n } catch {\n if (!existsSync(dbPath)) throw notReady(`the derived index was deleted while opening ${dbPath}`);\n throw notReady(`the derived index at ${dbPath} has no compatible schema`);\n }\n\n if (state.version !== dialect.schemaVersion) {\n throw notReady(`the derived index at ${dbPath} uses schema ${state.version ?? 'unknown'}, but this sense version requires ${dialect.schemaVersion}`);\n }\n const wantFeatures = featureSignature(cfg, FEATURES);\n if (!isPublishedFeatureSignature(state.features, wantFeatures)) {\n throw notReady(`the derived index at ${dbPath} was built for different configuration features`);\n }\n if (!isCoreReady(state.ready)) {\n throw notReady(`the derived index at ${dbPath} has an incomplete core build`);\n }\n if (requirements.has('lexical')) {\n await dialect.assertLexicalReady?.(conn);\n }\n if (!existsSync(dbPath)) throw notReady(`the derived index was deleted while opening ${dbPath}`);\n\n return {\n handle,\n conn,\n cfg,\n dbPath,\n parsed: 0,\n warnings: [],\n stages: stageRecorder().take(0, 0),\n observational: true,\n };\n } catch (err) {\n await dialect.close(handle, { observational: true });\n throw err;\n }\n}\n\nasync function connectForBuild<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>, requirements: ReadonlySet<BuildRequirement>, cacheReplaced = false): Promise<ConnectResult<Handle>> {\n const configDir = cfg.configDir ?? cfg.baseDir;\n const stateDir = join(configDir, STATE_DIR);\n mkdirSync(stateDir, { recursive: true });\n const dbPath = join(stateDir, dialect.filename);\n\n const { handle, conn } = await connectUnlocked(dbPath, cfg, configDir, dialect, { existingOnly: false, observational: false });\n let closed = false;\n let builder: ReturnType<typeof createBuilder> | undefined;\n try {\n await conn.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');\n\n const version = await getMeta(conn, 'schema_version');\n if (version !== null && version !== dialect.schemaVersion) {\n console.error('sense: cache format changed (new sensemaking version); rebuilding the index');\n await dialect.close(handle);\n closed = true;\n if (cacheReplaced) throw notReady(`the derived index at ${dbPath} still reports incompatible schema ${version} after cache replacement`);\n clearCache(cfg);\n return connectForBuild(cfg, dialect, requirements, true);\n }\n\n if (version === null) await dialect.ensureCoreSchema(handle, conn);\n await dialect.prepareConnection?.(handle, conn, cfg);\n\n if (dialect.setDerivedBusyTimeout) {\n const recordedMaxMs = Number((await getMeta(conn, 'reconcile_max_ms')) ?? '0');\n await dialect.setDerivedBusyTimeout(handle, conn, Math.min(Math.max(30000, 3 * recordedMaxMs), 600_000));\n }\n\n builder = createBuilder(conn, cfg, dialect.reconcileDialect, (snapshotCfg) => dialect.ensureFeatureSchema(handle, conn, snapshotCfg));\n const { parsed, warnings, stages, messages } = await builder.build();\n for (const message of messages) console.error(message);\n\n // Lexical preparation is a separate capability stage. A failure leaves core usable and the\n // dialect's own lexical marker stale, so unrelated map/peek/path/sql commands stay available.\n if (requirements.has('lexical')) {\n await dialect.prepareLexical?.(conn);\n }\n\n await builder.close();\n return { handle, conn, cfg, dbPath, parsed, warnings, stages, observational: false };\n } catch (err) {\n const cleanupTasks: Array<Promise<void>> = [];\n if (builder) {\n const builderToClose = builder;\n cleanupTasks.push(Promise.resolve().then(() => builderToClose.close()));\n }\n if (!closed) cleanupTasks.push(Promise.resolve().then(() => dialect.close(handle)));\n const cleanup = await Promise.allSettled(cleanupTasks);\n const cleanupErrors = cleanup.filter((result): result is PromiseRejectedResult => result.status === 'rejected').map((result) => result.reason);\n if (cleanupErrors.length > 0) throw new AggregateError([err, ...cleanupErrors], 'opening the derived index failed and cleanup also failed');\n throw err;\n }\n}\n\n// A static provider can resolve its identity while embedding. Publish it only after vectors\n// succeed and only when the durable signature still matches the prepared generation.\nexport async function prepareDocumentEmbeddings(store: Store, cfg: ResolvedConfig, allowed?: ReadonlySet<string>, options: EmbedCallOptions = {}): Promise<void> {\n options.signal?.throwIfAborted();\n const preparedSignature = await getMeta(store, FEATURE_SIGNATURE_META_KEY);\n options.signal?.throwIfAborted();\n await embedPending(store, cfg, allowed, preparedSignature, options);\n options.signal?.throwIfAborted();\n const actualSignature = featureSignature(cfg, FEATURES);\n if (preparedSignature === actualSignature) return;\n\n const changedKeys = changedSignatureKeys(preparedSignature ?? '', actualSignature);\n if (preparedSignature === null || changedKeys.size !== 1 || !changedKeys.has('embed') || !embedIdentityAdopted(preparedSignature, actualSignature)) {\n throw notReady('the index configuration changed while vectors were being prepared');\n }\n\n await store.transaction(async () => {\n options.signal?.throwIfAborted();\n const update = await store.prepare('UPDATE meta SET value = ? WHERE key = ? AND value = ?');\n options.signal?.throwIfAborted();\n const result = await update.run(actualSignature, FEATURE_SIGNATURE_META_KEY, preparedSignature);\n options.signal?.throwIfAborted();\n if (Number(result.changes) !== 1) throw notReady('another build changed the index configuration while vectors were being prepared');\n });\n}\n\nexport async function openWithDialect<Handle>(input: ResolvedConfig, dialect: OpenDialect<Handle>, options: InternalOpenOptions = {}): Promise<OpenResult> {\n options.signal?.throwIfAborted();\n const cfg = normaliseConfig(input);\n const buildEnabled = options.build !== false;\n const defaultRequirements = new Set<BuildRequirement>(buildEnabled ? ['core', 'lexical'] : ['core']);\n if (buildEnabled && anyPresetEmbeds(cfg)) defaultRequirements.add('vectors');\n const requirements = options.requirements ?? defaultRequirements;\n const connected = buildEnabled ? await connectForBuild(cfg, dialect, requirements) : await connectExisting(cfg, dialect, requirements);\n let store: Store | undefined;\n try {\n store = dialect.createStore(connected.handle, connected.conn, connected.cfg, { observational: connected.observational });\n rekeyChunkText(connected.conn, store);\n if (requirements.has('vectors') && buildEnabled) await prepareDocumentEmbeddings(store, connected.cfg, undefined, { signal: options.signal });\n options.signal?.throwIfAborted();\n return {\n store,\n cfg: connected.cfg,\n dbPath: connected.dbPath,\n parsed: connected.parsed,\n warnings: connected.warnings,\n stages: connected.stages,\n };\n } catch (err) {\n const cleanup = await Promise.allSettled([Promise.resolve().then(() => (store ? store.close() : dialect.close(connected.handle, { observational: connected.observational })))]);\n if (cleanup[0].status === 'rejected') throw new AggregateError([err, cleanup[0].reason], 'opening the derived index failed and cleanup also failed');\n throw err;\n }\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"],"names":["docCount","openWithDialect","prepareDocumentEmbeddings","LOCK_POLL_MS","lockWait","channel","notReady","reason","SenseError","normaliseConfig","cfg","rootDir","baseDir","configDir","cachePath","dialect","join","STATE_DIR","filename","connectUnlocked","dbPath","options","budgetMs","deadline","err","lockWaitBudgetMs","Date","now","connect","existingOnly","existsSync","isLocked","hasSubscribers","publish","store","Math","round","Promise","resolve","setTimeout","assertCoreSchema","conn","table","prepare","all","connectExisting","requirements","handle","state","wantFeatures","observational","withTransaction","version","features","ready","getMeta","FEATURE_SIGNATURE_META_KEY","CORE_READY_META_KEY","schemaVersion","featureSignature","FEATURES","isPublishedFeatureSignature","isCoreReady","has","assertLexicalReady","parsed","warnings","stages","stageRecorder","take","close","connectForBuild","cacheReplaced","stateDir","closed","builder","recordedMaxMs","messages","message","cleanupTasks","builderToClose","cleanup","cleanupErrors","mkdirSync","recursive","exec","console","error","clearCache","ensureCoreSchema","prepareConnection","setDerivedBusyTimeout","Number","min","max","createBuilder","reconcileDialect","snapshotCfg","ensureFeatureSchema","build","prepareLexical","push","then","allSettled","filter","result","status","map","length","AggregateError","allowed","preparedSignature","actualSignature","changedKeys","signal","throwIfAborted","embedPending","changedSignatureKeys","size","embedIdentityAdopted","transaction","update","run","changes","input","buildEnabled","defaultRequirements","connected","Set","anyPresetEmbeds","add","createStore","rekeyChunkText","undefined","stmt","get","n"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/open.ts"],"sourcesContent":["import { channel } from 'node:diagnostics_channel';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ResolvedConfig } from '../config/index.ts';\nimport { anyPresetEmbeds, featureSignature, STATE_DIR } from '../config/index.ts';\nimport { rekeyChunkText } from '../embed/handoff.ts';\nimport { embedPending } from '../embed/query.ts';\nimport type { EmbedCallOptions } from '../embed/types.ts';\nimport { SenseError } from '../errors.ts';\nimport { FEATURES } from '../features/index.ts';\nimport { createBuilder } from './builder.ts';\nimport { clearCache } from './cache.ts';\nimport { lockWaitBudgetMs } from './lock-wait.ts';\nimport { CORE_READY_META_KEY, FEATURE_SIGNATURE_META_KEY, isCoreReady, isPublishedFeatureSignature } from './readiness.ts';\nimport { getMeta } from './shared.ts';\nimport { changedSignatureKeys, embedIdentityAdopted } from './signature.ts';\nimport type { Stages } from './stages.ts';\nimport { stageRecorder } from './stages.ts';\nimport { withTransaction } from './transaction.ts';\nimport type { Connection, OpenDialect, Store } from './types.ts';\n\nexport type BuildRequirement = 'core' | 'lexical' | 'vectors';\n\n/** Options for the root `open(config, options)` API. */\nexport interface OpenOptions {\n /** Prepares configured capabilities by default; `false` opens compatible published state without repair. */\n build?: boolean;\n /** Cancels supported provider I/O and stops between phases after active native work finishes. */\n signal?: AbortSignal;\n}\n\nexport interface InternalOpenOptions extends OpenOptions {\n requirements?: ReadonlySet<BuildRequirement>;\n}\n\nexport interface OpenResult {\n store: Store;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n stages: Stages;\n}\n\ninterface ConnectResult<Handle> {\n handle: Handle;\n conn: Connection;\n cfg: ResolvedConfig;\n dbPath: string;\n parsed: number;\n warnings: string[];\n stages: Stages;\n observational: boolean;\n}\n\nconst LOCK_POLL_MS = 50;\nconst lockWait = channel('sensemaking.store.lock-wait');\n\nfunction notReady(reason: string): SenseError {\n return new SenseError('INDEX_NOT_READY', `${reason}; run \"sense build\" or call build(config) before opening with { build: false }`);\n}\n\nfunction normaliseConfig(cfg: ResolvedConfig): ResolvedConfig {\n // `baseDir` was the original public open() input. Keep direct API callers working while\n // making the two ownership paths explicit for every internal operation.\n if (!cfg.rootDir) {\n if (!cfg.baseDir) throw new SenseError('CONFIG_INVALID', 'open requires rootDir (or legacy baseDir)');\n cfg.rootDir = cfg.baseDir;\n }\n if (!cfg.configDir) cfg.configDir = cfg.rootDir;\n return cfg;\n}\n\nfunction cachePath<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>): string {\n return join(cfg.configDir ?? cfg.baseDir, STATE_DIR, dialect.filename);\n}\n\nasync function connectUnlocked<Handle>(dbPath: string, cfg: ResolvedConfig, configDir: string, dialect: OpenDialect<Handle>, options: { existingOnly: boolean; observational: boolean }): Promise<{ handle: Handle; conn: Connection }> {\n const budgetMs = lockWaitBudgetMs(configDir);\n const deadline = Date.now() + budgetMs;\n for (;;) {\n try {\n return await dialect.connect(dbPath, cfg, options);\n } catch (err) {\n if (options.existingOnly && !existsSync(dbPath)) {\n throw notReady(`the derived index does not exist at ${dbPath}`);\n }\n if (!dialect.isLocked?.(err as Error)) throw err;\n if (lockWait.hasSubscribers) lockWait.publish({ store: cfg.store, dbPath });\n if (Date.now() >= deadline) {\n throw new SenseError('STORE_BUSY', `another sense process is using this tree's ${cfg.store} cache (${dbPath}) and did not release it within ${Math.round(budgetMs / 1000)}s; wait for that command to finish, or set \"store\" to \"sqlite\" in sense.config.json, which serves concurrent commands`);\n }\n await new Promise((resolve) => setTimeout(resolve, LOCK_POLL_MS));\n }\n }\n}\n\nasync function assertCoreSchema(conn: Connection): Promise<void> {\n for (const table of ['frontmatter', 'content', 'preset_files', 'indexed_sources']) {\n await (await conn.prepare(`SELECT 1 FROM ${table} LIMIT 0`)).all();\n }\n}\n\nasync function connectExisting<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>, requirements: ReadonlySet<BuildRequirement>): Promise<ConnectResult<Handle>> {\n const configDir = cfg.configDir ?? cfg.baseDir;\n const dbPath = cachePath(cfg, dialect);\n if (!existsSync(dbPath)) throw notReady(`the derived index does not exist at ${dbPath}`);\n\n const { handle, conn } = await connectUnlocked(dbPath, cfg, configDir, dialect, { existingOnly: true, observational: true });\n try {\n let state: { version: string | null; features: string | null; ready: string | null };\n try {\n state = await withTransaction(conn, async () => {\n const version = await getMeta(conn, 'schema_version');\n const features = await getMeta(conn, FEATURE_SIGNATURE_META_KEY);\n const ready = await getMeta(conn, CORE_READY_META_KEY);\n await assertCoreSchema(conn);\n return { version, features, ready };\n });\n } catch {\n if (!existsSync(dbPath)) throw notReady(`the derived index was deleted while opening ${dbPath}`);\n throw notReady(`the derived index at ${dbPath} has no compatible schema`);\n }\n\n if (state.version !== dialect.schemaVersion) {\n throw notReady(`the derived index at ${dbPath} uses schema ${state.version ?? 'unknown'}, but this sense version requires ${dialect.schemaVersion}`);\n }\n const wantFeatures = featureSignature(cfg, FEATURES);\n if (!isPublishedFeatureSignature(state.features, wantFeatures)) {\n throw notReady(`the derived index at ${dbPath} was built for different configuration features`);\n }\n if (!isCoreReady(state.ready)) {\n throw notReady(`the derived index at ${dbPath} has an incomplete core build`);\n }\n if (requirements.has('lexical')) {\n await dialect.assertLexicalReady?.(conn);\n }\n if (!existsSync(dbPath)) throw notReady(`the derived index was deleted while opening ${dbPath}`);\n\n return {\n handle,\n conn,\n cfg,\n dbPath,\n parsed: 0,\n warnings: [],\n stages: stageRecorder().take(0, 0),\n observational: true,\n };\n } catch (err) {\n await dialect.close(handle, { observational: true });\n throw err;\n }\n}\n\nasync function connectForBuild<Handle>(cfg: ResolvedConfig, dialect: OpenDialect<Handle>, requirements: ReadonlySet<BuildRequirement>, cacheReplaced = false): Promise<ConnectResult<Handle>> {\n const configDir = cfg.configDir ?? cfg.baseDir;\n const stateDir = join(configDir, STATE_DIR);\n mkdirSync(stateDir, { recursive: true });\n const dbPath = join(stateDir, dialect.filename);\n\n const { handle, conn } = await connectUnlocked(dbPath, cfg, configDir, dialect, { existingOnly: false, observational: false });\n let closed = false;\n let builder: ReturnType<typeof createBuilder> | undefined;\n try {\n await conn.exec('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT)');\n\n const version = await getMeta(conn, 'schema_version');\n if (version !== null && version !== dialect.schemaVersion) {\n console.error('sense: cache format changed (new sensemaking version); rebuilding the index');\n await dialect.close(handle);\n closed = true;\n if (cacheReplaced) throw notReady(`the derived index at ${dbPath} still reports incompatible schema ${version} after cache replacement`);\n clearCache(cfg);\n return connectForBuild(cfg, dialect, requirements, true);\n }\n\n if (version === null) await dialect.ensureCoreSchema(handle, conn);\n await dialect.prepareConnection?.(handle, conn, cfg);\n\n if (dialect.setDerivedBusyTimeout) {\n const recordedMaxMs = Number((await getMeta(conn, 'reconcile_max_ms')) ?? '0');\n await dialect.setDerivedBusyTimeout(handle, conn, Math.min(Math.max(30000, 3 * recordedMaxMs), 600_000));\n }\n\n builder = createBuilder(conn, cfg, dialect.reconcileDialect, (snapshotCfg) => dialect.ensureFeatureSchema(handle, conn, snapshotCfg));\n const { parsed, warnings, stages, messages } = await builder.build();\n for (const message of messages) console.error(message);\n\n // Lexical preparation is a separate capability stage. A failure leaves core usable and the\n // dialect's own lexical marker stale, so unrelated map/peek/path/sql commands stay available.\n if (requirements.has('lexical')) {\n await dialect.prepareLexical?.(conn);\n }\n\n await builder.close();\n return { handle, conn, cfg, dbPath, parsed, warnings, stages, observational: false };\n } catch (err) {\n const cleanupTasks: Array<Promise<void>> = [];\n if (builder) {\n const builderToClose = builder;\n cleanupTasks.push(Promise.resolve().then(() => builderToClose.close()));\n }\n if (!closed) cleanupTasks.push(Promise.resolve().then(() => dialect.close(handle)));\n const cleanup = await Promise.allSettled(cleanupTasks);\n const cleanupErrors = cleanup.filter((result): result is PromiseRejectedResult => result.status === 'rejected').map((result) => result.reason);\n if (cleanupErrors.length > 0) throw new AggregateError([err, ...cleanupErrors], 'opening the derived index failed and cleanup also failed');\n throw err;\n }\n}\n\n// A static provider can resolve its identity while embedding. Publish it only after vectors\n// succeed and only when the durable signature still matches the prepared generation.\nexport async function prepareDocumentEmbeddings(store: Store, cfg: ResolvedConfig, allowed?: ReadonlySet<string>, options: EmbedCallOptions = {}): Promise<void> {\n options.signal?.throwIfAborted();\n const preparedSignature = await getMeta(store, FEATURE_SIGNATURE_META_KEY);\n options.signal?.throwIfAborted();\n await embedPending(store, cfg, allowed, preparedSignature, options);\n options.signal?.throwIfAborted();\n const actualSignature = featureSignature(cfg, FEATURES);\n if (preparedSignature === actualSignature) return;\n\n const changedKeys = changedSignatureKeys(preparedSignature ?? '', actualSignature);\n if (preparedSignature === null || changedKeys.size !== 1 || !changedKeys.has('embed') || !embedIdentityAdopted(preparedSignature, actualSignature)) {\n throw notReady('the index configuration changed while vectors were being prepared');\n }\n\n await store.transaction(async () => {\n options.signal?.throwIfAborted();\n const update = await store.prepare('UPDATE meta SET value = ? WHERE key = ? AND value = ?');\n options.signal?.throwIfAborted();\n const result = await update.run(actualSignature, FEATURE_SIGNATURE_META_KEY, preparedSignature);\n options.signal?.throwIfAborted();\n if (Number(result.changes) !== 1) throw notReady('another build changed the index configuration while vectors were being prepared');\n });\n}\n\nexport async function openWithDialect<Handle>(input: ResolvedConfig, dialect: OpenDialect<Handle>, options: InternalOpenOptions = {}): Promise<OpenResult> {\n options.signal?.throwIfAborted();\n const cfg = normaliseConfig(input);\n const buildEnabled = options.build !== false;\n const defaultRequirements = new Set<BuildRequirement>(buildEnabled ? ['core', 'lexical'] : ['core']);\n if (buildEnabled && anyPresetEmbeds(cfg)) defaultRequirements.add('vectors');\n const requirements = options.requirements ?? defaultRequirements;\n const connected = buildEnabled ? await connectForBuild(cfg, dialect, requirements) : await connectExisting(cfg, dialect, requirements);\n let store: Store | undefined;\n try {\n store = dialect.createStore(connected.handle, connected.conn, connected.cfg, { observational: connected.observational });\n rekeyChunkText(connected.conn, store);\n if (requirements.has('vectors') && buildEnabled) await prepareDocumentEmbeddings(store, connected.cfg, undefined, { signal: options.signal });\n options.signal?.throwIfAborted();\n return {\n store,\n cfg: connected.cfg,\n dbPath: connected.dbPath,\n parsed: connected.parsed,\n warnings: connected.warnings,\n stages: connected.stages,\n };\n } catch (err) {\n const cleanup = await Promise.allSettled([Promise.resolve().then(() => (store ? store.close() : dialect.close(connected.handle, { observational: connected.observational })))]);\n if (cleanup[0].status === 'rejected') throw new AggregateError([err, cleanup[0].reason], 'opening the derived index failed and cleanup also failed');\n throw err;\n }\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"],"names":["docCount","openWithDialect","prepareDocumentEmbeddings","LOCK_POLL_MS","lockWait","channel","notReady","reason","SenseError","normaliseConfig","cfg","rootDir","baseDir","configDir","cachePath","dialect","join","STATE_DIR","filename","connectUnlocked","dbPath","options","budgetMs","deadline","err","lockWaitBudgetMs","Date","now","connect","existingOnly","existsSync","isLocked","hasSubscribers","publish","store","Math","round","Promise","resolve","setTimeout","assertCoreSchema","conn","table","prepare","all","connectExisting","requirements","handle","state","wantFeatures","observational","withTransaction","version","features","ready","getMeta","FEATURE_SIGNATURE_META_KEY","CORE_READY_META_KEY","schemaVersion","featureSignature","FEATURES","isPublishedFeatureSignature","isCoreReady","has","assertLexicalReady","parsed","warnings","stages","stageRecorder","take","close","connectForBuild","cacheReplaced","stateDir","closed","builder","recordedMaxMs","messages","message","cleanupTasks","builderToClose","cleanup","cleanupErrors","mkdirSync","recursive","exec","console","error","clearCache","ensureCoreSchema","prepareConnection","setDerivedBusyTimeout","Number","min","max","createBuilder","reconcileDialect","snapshotCfg","ensureFeatureSchema","build","prepareLexical","push","then","allSettled","filter","result","status","map","length","AggregateError","allowed","preparedSignature","actualSignature","changedKeys","signal","throwIfAborted","embedPending","changedSignatureKeys","size","embedIdentityAdopted","transaction","update","run","changes","input","buildEnabled","defaultRequirements","connected","Set","anyPresetEmbeds","add","createStore","rekeyChunkText","undefined","stmt","get","n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/preset-scope.ts"],"sourcesContent":["import type { Config } from '../config/index.ts';\nimport { presetHasSignal } from '../config/index.ts';\nimport { listFiles } from '../scan/index.ts';\n\n// A signature change open() can route to a narrow reparse instead of a full clear: every changed\n// segment is a preset's own (glob or vector on/off), never a global feature or embed change.\nexport function isPresetOnlyChange(changedKeys: ReadonlySet<string>): boolean {\n return changedKeys.size > 0 && [...changedKeys].every((key) => key.startsWith('preset:'));\n}\n\ninterface PresetDef {\n include: string[];\n exclude: string[];\n vectors: boolean;\n}\n\n// One preset's old include/exclude/vectors-on-off, read back out of a stored `preset:<name>:...`\n// segment (config/access.ts's featureSignature format). Absent (a brand-new preset) is the empty\n// preset, not a parse failure; a segment present but not in that exact shape returns null so the\n// caller falls back to a full rebuild instead of guessing.\nfunction parseOldPreset(before: string, name: string): PresetDef | null {\n const part = before.split('|').find((p) => p.startsWith(`preset:${name}:`));\n if (part === undefined) return { include: [], exclude: [], vectors: false };\n const fields = part.split(':');\n if (fields.length !== 5) return null;\n const [, , includeStr, excludeStr, onOff] = fields;\n if (onOff !== 'on' && onOff !== 'off') return null;\n return { include: includeStr === '' ? [] : includeStr.split('+'), exclude: excludeStr === '' ? [] : excludeStr.split('+'), vectors: onOff === 'on' };\n}\n\n// Paths one preset definition covers, via the real listFiles so stat filtering (directories,\n// dangling symlinks) matches production coverage exactly.\nfunction matchPreset(cfg: Config, baseDir: string, name: string, def: PresetDef): Set<string> {\n const scoped: Config = { ...cfg, presets: { [name]: { include: def.include, exclude: def.exclude } } };\n return new Set(listFiles(scoped, baseDir).map((f) => f.relPath));\n}\n\n// Every path whose coverage by a changed preset genuinely moved: gained or lost it (a glob edit),\n// or kept it under a flipped vectors on/off (that preset's whole match set, since its contribution\n// to the file's union embed flag may have changed even though membership itself did not). Returns\n// null when a changed preset's stored segment can't be parsed, so the caller takes the full rebuild.\nexport function forcedPresetPaths(cfg: Config, baseDir: string, before: string, changedKeys: ReadonlySet<string>): Set<string> | null {\n const forced = new Set<string>();\n for (const key of changedKeys) {\n const name = key.slice('preset:'.length);\n const oldDef = parseOldPreset(before, name);\n if (oldDef === null) return null;\n const stillDeclared = Object.hasOwn(cfg.presets, name);\n const newDef: PresetDef = stillDeclared ? { include: cfg.presets[name].include, exclude: cfg.presets[name].exclude ?? [], vectors: presetHasSignal(cfg, name, 'vectors') } : { include: [], exclude: [], vectors: false };\n\n const oldMatch = matchPreset(cfg, baseDir, name, oldDef);\n const newMatch = stillDeclared ? matchPreset(cfg, baseDir, name, newDef) : new Set<string>();\n\n if (oldDef.vectors !== newDef.vectors) {\n for (const p of oldMatch) forced.add(p);\n for (const p of newMatch) forced.add(p);\n } else {\n for (const p of oldMatch) if (!newMatch.has(p)) forced.add(p);\n for (const p of newMatch) if (!oldMatch.has(p)) forced.add(p);\n }\n }\n return forced;\n}\n"],"names":["forcedPresetPaths","isPresetOnlyChange","changedKeys","size","every","key","startsWith","parseOldPreset","before","name","part","split","find","p","undefined","include","exclude","vectors","fields","length","includeStr","excludeStr","onOff","matchPreset","cfg","baseDir","def","scoped","presets","Set","listFiles","map","f","relPath","forced","slice","oldDef","stillDeclared","Object","hasOwn","newDef","presetHasSignal","oldMatch","newMatch","add","has"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/preset-scope.ts"],"sourcesContent":["import type { Config } from '../config/index.ts';\nimport { presetHasSignal } from '../config/index.ts';\nimport { listFiles } from '../scan/index.ts';\n\n// A signature change open() can route to a narrow reparse instead of a full clear: every changed\n// segment is a preset's own (glob or vector on/off), never a global feature or embed change.\nexport function isPresetOnlyChange(changedKeys: ReadonlySet<string>): boolean {\n return changedKeys.size > 0 && [...changedKeys].every((key) => key.startsWith('preset:'));\n}\n\ninterface PresetDef {\n include: string[];\n exclude: string[];\n vectors: boolean;\n}\n\n// One preset's old include/exclude/vectors-on-off, read back out of a stored `preset:<name>:...`\n// segment (config/access.ts's featureSignature format). Absent (a brand-new preset) is the empty\n// preset, not a parse failure; a segment present but not in that exact shape returns null so the\n// caller falls back to a full rebuild instead of guessing.\nfunction parseOldPreset(before: string, name: string): PresetDef | null {\n const part = before.split('|').find((p) => p.startsWith(`preset:${name}:`));\n if (part === undefined) return { include: [], exclude: [], vectors: false };\n const fields = part.split(':');\n if (fields.length !== 5) return null;\n const [, , includeStr, excludeStr, onOff] = fields;\n if (onOff !== 'on' && onOff !== 'off') return null;\n return { include: includeStr === '' ? [] : includeStr.split('+'), exclude: excludeStr === '' ? [] : excludeStr.split('+'), vectors: onOff === 'on' };\n}\n\n// Paths one preset definition covers, via the real listFiles so stat filtering (directories,\n// dangling symlinks) matches production coverage exactly.\nfunction matchPreset(cfg: Config, baseDir: string, name: string, def: PresetDef): Set<string> {\n const scoped: Config = { ...cfg, presets: { [name]: { include: def.include, exclude: def.exclude } } };\n return new Set(listFiles(scoped, baseDir).map((f) => f.relPath));\n}\n\n// Every path whose coverage by a changed preset genuinely moved: gained or lost it (a glob edit),\n// or kept it under a flipped vectors on/off (that preset's whole match set, since its contribution\n// to the file's union embed flag may have changed even though membership itself did not). Returns\n// null when a changed preset's stored segment can't be parsed, so the caller takes the full rebuild.\nexport function forcedPresetPaths(cfg: Config, baseDir: string, before: string, changedKeys: ReadonlySet<string>): Set<string> | null {\n const forced = new Set<string>();\n for (const key of changedKeys) {\n const name = key.slice('preset:'.length);\n const oldDef = parseOldPreset(before, name);\n if (oldDef === null) return null;\n const stillDeclared = Object.hasOwn(cfg.presets, name);\n const newDef: PresetDef = stillDeclared ? { include: cfg.presets[name].include, exclude: cfg.presets[name].exclude ?? [], vectors: presetHasSignal(cfg, name, 'vectors') } : { include: [], exclude: [], vectors: false };\n\n const oldMatch = matchPreset(cfg, baseDir, name, oldDef);\n const newMatch = stillDeclared ? matchPreset(cfg, baseDir, name, newDef) : new Set<string>();\n\n if (oldDef.vectors !== newDef.vectors) {\n for (const p of oldMatch) forced.add(p);\n for (const p of newMatch) forced.add(p);\n } else {\n for (const p of oldMatch) if (!newMatch.has(p)) forced.add(p);\n for (const p of newMatch) if (!oldMatch.has(p)) forced.add(p);\n }\n }\n return forced;\n}\n"],"names":["forcedPresetPaths","isPresetOnlyChange","changedKeys","size","every","key","startsWith","parseOldPreset","before","name","part","split","find","p","undefined","include","exclude","vectors","fields","length","includeStr","excludeStr","onOff","matchPreset","cfg","baseDir","def","scoped","presets","Set","listFiles","map","f","relPath","forced","slice","oldDef","stillDeclared","Object","hasOwn","newDef","presetHasSignal","oldMatch","newMatch","add","has"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/readiness.ts"],"sourcesContent":["// Published core state has one exact durable signature. Static model identity adoption is a\n// preparation transition, not permission for a read snapshot to accept a different signature.\nexport const CORE_READY_META_KEY = 'core_ready';\nexport const CORE_GENERATION_META_KEY = 'core_generation';\nexport const FEATURE_SIGNATURE_META_KEY = 'features';\n\nexport function isCoreReady(value: string | null): boolean {\n return value === '1';\n}\n\nexport function isPublishedFeatureSignature(actual: string | null, expected: string): boolean {\n return actual === expected;\n}\n"],"names":["CORE_GENERATION_META_KEY","CORE_READY_META_KEY","FEATURE_SIGNATURE_META_KEY","isCoreReady","isPublishedFeatureSignature","value","actual","expected"],"mappings":"AAAA,4FAA4F;AAC5F,8FAA8F;;;;;;;;;;;;QAEjFA;eAAAA;;QADAC;eAAAA;;QAEAC;eAAAA;;QAEGC;eAAAA;;QAIAC;eAAAA;;;AART,IAAMH,sBAAsB;AAC5B,IAAMD,2BAA2B;AACjC,IAAME,6BAA6B;AAEnC,SAASC,YAAYE,KAAoB;IAC9C,OAAOA,UAAU;AACnB;AAEO,SAASD,4BAA4BE,MAAqB,EAAEC,QAAgB;IACjF,OAAOD,WAAWC;AACpB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/readiness.ts"],"sourcesContent":["// Published core state has one exact durable signature. Static model identity adoption is a\n// preparation transition, not permission for a read snapshot to accept a different signature.\nexport const CORE_READY_META_KEY = 'core_ready';\nexport const CORE_GENERATION_META_KEY = 'core_generation';\nexport const FEATURE_SIGNATURE_META_KEY = 'features';\n\nexport function isCoreReady(value: string | null): boolean {\n return value === '1';\n}\n\nexport function isPublishedFeatureSignature(actual: string | null, expected: string): boolean {\n return actual === expected;\n}\n"],"names":["CORE_GENERATION_META_KEY","CORE_READY_META_KEY","FEATURE_SIGNATURE_META_KEY","isCoreReady","isPublishedFeatureSignature","value","actual","expected"],"mappings":"AAAA,4FAA4F;AAC5F,8FAA8F;;;;;;;;;;;;QAEjFA;eAAAA;;QADAC;eAAAA;;QAEAC;eAAAA;;QAEGC;eAAAA;;QAIAC;eAAAA;;;AART,IAAMH,sBAAsB;AAC5B,IAAMD,2BAA2B;AACjC,IAAME,6BAA6B;AAEnC,SAASC,YAAYE,KAAoB;IAC9C,OAAOA,UAAU;AACnB;AAEO,SAASD,4BAA4BE,MAAqB,EAAEC,QAAgB;IACjF,OAAOD,WAAWC;AACpB"}