sensemaking 0.20.0 → 0.21.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.
- package/README.md +0 -1
- package/dist/cjs/chunk/group.d.cts +0 -2
- package/dist/cjs/chunk/group.d.ts +0 -2
- package/dist/cjs/chunk/group.js +12 -53
- package/dist/cjs/chunk/group.js.map +1 -1
- package/dist/cjs/chunk/index.d.cts +1 -1
- package/dist/cjs/chunk/index.d.ts +1 -1
- package/dist/cjs/chunk/index.js +3 -2
- package/dist/cjs/chunk/index.js.map +1 -1
- package/dist/cjs/chunk/parse.js +46 -29
- package/dist/cjs/chunk/parse.js.map +1 -1
- package/dist/cjs/chunk/tokens.d.cts +2 -0
- package/dist/cjs/chunk/tokens.d.ts +2 -0
- package/dist/cjs/chunk/tokens.js +50 -0
- package/dist/cjs/chunk/tokens.js.map +1 -0
- package/dist/cjs/config/access.d.cts +0 -1
- package/dist/cjs/config/access.d.ts +0 -1
- package/dist/cjs/config/access.js +10 -17
- package/dist/cjs/config/access.js.map +1 -1
- package/dist/cjs/config/index.d.cts +1 -1
- package/dist/cjs/config/index.d.ts +1 -1
- package/dist/cjs/config/index.js +0 -3
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/config/types.d.cts +0 -3
- package/dist/cjs/config/types.d.ts +0 -3
- package/dist/cjs/config/types.js.map +1 -1
- package/dist/cjs/config/validate.js +6 -24
- package/dist/cjs/config/validate.js.map +1 -1
- package/dist/cjs/errors.d.cts +1 -1
- package/dist/cjs/errors.d.ts +1 -1
- package/dist/cjs/errors.js.map +1 -1
- package/dist/cjs/features/links.js +4 -5
- package/dist/cjs/features/links.js.map +1 -1
- package/dist/cjs/features/sections.js +4 -1
- package/dist/cjs/features/sections.js.map +1 -1
- package/dist/cjs/store/builder.d.cts +9 -1
- package/dist/cjs/store/builder.d.ts +9 -1
- package/dist/cjs/store/builder.js +593 -2
- package/dist/cjs/store/builder.js.map +1 -1
- package/dist/cjs/store/duckdb/connection.d.cts +4 -1
- package/dist/cjs/store/duckdb/connection.d.ts +4 -1
- package/dist/cjs/store/duckdb/connection.js +1 -0
- package/dist/cjs/store/duckdb/connection.js.map +1 -1
- package/dist/cjs/store/duckdb/open.js +7 -1
- package/dist/cjs/store/duckdb/open.js.map +1 -1
- package/dist/cjs/store/duckdb/reconcile.js +135 -6
- package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
- package/dist/cjs/store/embed-scope.d.cts +2 -0
- package/dist/cjs/store/embed-scope.d.ts +2 -0
- package/dist/cjs/store/embed-scope.js +85 -0
- package/dist/cjs/store/embed-scope.js.map +1 -0
- package/dist/cjs/store/feature-scope.d.cts +8 -0
- package/dist/cjs/store/feature-scope.d.ts +8 -0
- package/dist/cjs/store/feature-scope.js +107 -0
- package/dist/cjs/store/feature-scope.js.map +1 -0
- package/dist/cjs/store/open.js +193 -101
- package/dist/cjs/store/open.js.map +1 -1
- package/dist/cjs/store/preset-scope.d.cts +3 -0
- package/dist/cjs/store/preset-scope.d.ts +3 -0
- package/dist/cjs/store/preset-scope.js +293 -0
- package/dist/cjs/store/preset-scope.js.map +1 -0
- package/dist/cjs/store/reconcile.d.cts +2 -1
- package/dist/cjs/store/reconcile.d.ts +2 -1
- package/dist/cjs/store/reconcile.js +223 -189
- package/dist/cjs/store/reconcile.js.map +1 -1
- package/dist/cjs/store/signature.js +7 -5
- package/dist/cjs/store/signature.js.map +1 -1
- package/dist/cjs/store/sqlite/lexical.d.cts +1 -1
- package/dist/cjs/store/sqlite/lexical.d.ts +1 -1
- package/dist/cjs/store/sqlite/lexical.js +2 -2
- package/dist/cjs/store/sqlite/lexical.js.map +1 -1
- package/dist/cjs/store/sqlite/open.d.cts +0 -1
- package/dist/cjs/store/sqlite/open.d.ts +0 -1
- package/dist/cjs/store/sqlite/open.js +14 -231
- package/dist/cjs/store/sqlite/open.js.map +1 -1
- package/dist/cjs/store/sqlite/reconcile.d.cts +1 -1
- package/dist/cjs/store/sqlite/reconcile.d.ts +1 -1
- package/dist/cjs/store/sqlite/reconcile.js +78 -16
- package/dist/cjs/store/sqlite/reconcile.js.map +1 -1
- package/dist/cjs/store/sqlite/sql-functions.d.cts +1 -1
- package/dist/cjs/store/sqlite/sql-functions.d.ts +1 -1
- package/dist/cjs/store/sqlite/sql-functions.js +3 -3
- package/dist/cjs/store/sqlite/sql-functions.js.map +1 -1
- package/dist/cjs/store/sqlite/store.d.cts +1 -2
- package/dist/cjs/store/sqlite/store.d.ts +1 -2
- package/dist/cjs/store/sqlite/store.js +2 -3
- package/dist/cjs/store/sqlite/store.js.map +1 -1
- package/dist/cjs/store/turso/open.js +6 -0
- package/dist/cjs/store/turso/open.js.map +1 -1
- package/dist/cjs/store/turso/reconcile.js +72 -3
- package/dist/cjs/store/turso/reconcile.js.map +1 -1
- package/dist/cjs/store/types.d.cts +3 -4
- package/dist/cjs/store/types.d.ts +3 -4
- package/dist/cjs/store/types.js.map +1 -1
- package/dist/esm/chunk/group.d.ts +0 -2
- package/dist/esm/chunk/group.js +1 -15
- package/dist/esm/chunk/group.js.map +1 -1
- package/dist/esm/chunk/index.d.ts +1 -1
- package/dist/esm/chunk/index.js +1 -1
- package/dist/esm/chunk/index.js.map +1 -1
- package/dist/esm/chunk/parse.js +41 -29
- package/dist/esm/chunk/parse.js.map +1 -1
- package/dist/esm/chunk/tokens.d.ts +2 -0
- package/dist/esm/chunk/tokens.js +15 -0
- package/dist/esm/chunk/tokens.js.map +1 -0
- package/dist/esm/config/access.d.ts +0 -1
- package/dist/esm/config/access.js +12 -17
- package/dist/esm/config/access.js.map +1 -1
- package/dist/esm/config/index.d.ts +1 -1
- package/dist/esm/config/index.js +1 -1
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/config/types.d.ts +0 -3
- package/dist/esm/config/types.js.map +1 -1
- package/dist/esm/config/validate.js +8 -24
- package/dist/esm/config/validate.js.map +1 -1
- package/dist/esm/errors.d.ts +1 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/features/links.js +3 -4
- package/dist/esm/features/links.js.map +1 -1
- package/dist/esm/features/sections.js +4 -1
- package/dist/esm/features/sections.js.map +1 -1
- package/dist/esm/store/builder.d.ts +9 -1
- package/dist/esm/store/builder.js +152 -3
- package/dist/esm/store/builder.js.map +1 -1
- package/dist/esm/store/duckdb/connection.d.ts +4 -1
- package/dist/esm/store/duckdb/connection.js +1 -0
- package/dist/esm/store/duckdb/connection.js.map +1 -1
- package/dist/esm/store/duckdb/open.js +5 -1
- package/dist/esm/store/duckdb/open.js.map +1 -1
- package/dist/esm/store/duckdb/reconcile.js +45 -4
- package/dist/esm/store/duckdb/reconcile.js.map +1 -1
- package/dist/esm/store/embed-scope.d.ts +2 -0
- package/dist/esm/store/embed-scope.js +28 -0
- package/dist/esm/store/embed-scope.js.map +1 -0
- package/dist/esm/store/feature-scope.d.ts +8 -0
- package/dist/esm/store/feature-scope.js +49 -0
- package/dist/esm/store/feature-scope.js.map +1 -0
- package/dist/esm/store/open.js +78 -28
- package/dist/esm/store/open.js.map +1 -1
- package/dist/esm/store/preset-scope.d.ts +3 -0
- package/dist/esm/store/preset-scope.js +77 -0
- package/dist/esm/store/preset-scope.js.map +1 -0
- package/dist/esm/store/reconcile.d.ts +2 -1
- package/dist/esm/store/reconcile.js +43 -9
- package/dist/esm/store/reconcile.js.map +1 -1
- package/dist/esm/store/signature.js +7 -5
- package/dist/esm/store/signature.js.map +1 -1
- package/dist/esm/store/sqlite/lexical.d.ts +1 -1
- package/dist/esm/store/sqlite/lexical.js +4 -4
- package/dist/esm/store/sqlite/lexical.js.map +1 -1
- package/dist/esm/store/sqlite/open.d.ts +0 -1
- package/dist/esm/store/sqlite/open.js +14 -88
- package/dist/esm/store/sqlite/open.js.map +1 -1
- package/dist/esm/store/sqlite/reconcile.d.ts +1 -1
- package/dist/esm/store/sqlite/reconcile.js +14 -14
- package/dist/esm/store/sqlite/reconcile.js.map +1 -1
- package/dist/esm/store/sqlite/sql-functions.d.ts +1 -1
- package/dist/esm/store/sqlite/sql-functions.js +3 -3
- package/dist/esm/store/sqlite/sql-functions.js.map +1 -1
- package/dist/esm/store/sqlite/store.d.ts +1 -2
- package/dist/esm/store/sqlite/store.js +2 -3
- package/dist/esm/store/sqlite/store.js.map +1 -1
- package/dist/esm/store/turso/open.js +4 -0
- package/dist/esm/store/turso/open.js.map +1 -1
- package/dist/esm/store/turso/reconcile.js +6 -2
- package/dist/esm/store/turso/reconcile.js.map +1 -1
- package/dist/esm/store/types.d.ts +3 -4
- package/dist/esm/store/types.js.map +1 -1
- package/package.json +2 -1
- package/schema.json +0 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/builder.ts"],"sourcesContent":["import type { Config } from '../config/index.ts';\nimport { ParsePool } from '../scan/pool.ts';\nimport { reconcile } from './reconcile.ts';\nimport type { Connection, ReconcileDialect } from './types.ts';\n\n// Owns bringing a store's index current: the write half `Store` (types.ts) deliberately does not\n// carry. A one-shot open calls build() once; a watcher calls it repeatedly on the same instance.\nexport interface Builder {\n build(): Promise<{ parsed: number; warnings: string[] }>;\n // Releases the parse worker pool, if this lifetime ever created one; never the connection.\n close(): Promise<void>;\n // Pools this lifetime has constructed, so reuse is observable rather than inferred.\n readonly poolsCreated: number;\n}\n\n// The pool is created at most once, lazily, on whichever build() call first needs it, and reused\n// by every later build() on this instance.\nexport function createBuilder(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect): Builder {\n const pool = new ParsePool();\n return {\n build: () => reconcile(conn, cfg, baseDir, dialect, pool),\n close: () => pool.close(),\n get poolsCreated() {\n return pool.poolsCreated;\n },\n };\n}\n"],"names":["createBuilder","conn","cfg","baseDir","dialect","pool","ParsePool","build","reconcile","close","poolsCreated"],"mappings":";;;;+BAiBgBA;;;eAAAA;;;sBAhBU;2BACA;AAenB,SAASA,cAAcC,IAAgB,EAAEC,GAAW,EAAEC,OAAe,EAAEC,OAAyB;IACrG,IAAMC,OAAO,IAAIC,iBAAS;IAC1B,OAAO;QACLC,OAAO,SAAPA;mBAAaC,IAAAA,sBAAS,EAACP,MAAMC,KAAKC,SAASC,SAASC;;QACpDI,OAAO,SAAPA;mBAAaJ,KAAKI,KAAK;;QACvB,IAAIC;YACF,OAAOL,KAAKK,YAAY;QAC1B;IACF;AACF"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/builder.ts"],"sourcesContent":["import type { Config } from '../config/index.ts';\nimport { embed } from '../features/embed.ts';\nimport { FEATURES } from '../features/index.ts';\nimport { rank } from '../features/rank.ts';\nimport type { ReconcileDelta } from '../features/types.ts';\nimport { listFiles } from '../scan/index.ts';\nimport { ParsePool } from '../scan/pool.ts';\nimport { reparseFiles } from '../scan/reparse.ts';\nimport type { EmbedChangeKind } from './embed-scope.ts';\nimport type { FeatureToggle } from './feature-scope.ts';\nimport { NARROW_FEATURE_TABLE } from './feature-scope.ts';\nimport { reconcile } from './reconcile.ts';\nimport { getColumns } from './shared.ts';\nimport { withTransaction } from './transaction.ts';\nimport type { Connection, ReconcileDialect } from './types.ts';\n\n// Owns bringing a store's index current: the write half `Store` (types.ts) deliberately does not\n// carry. A one-shot open calls build() once; a watcher calls it repeatedly on the same instance.\nexport interface Builder {\n // forcedPaths (open.ts's preset-only narrow rebuild) applies to this call alone, not future ones.\n build(forcedPaths?: ReadonlySet<string>): Promise<{ parsed: number; warnings: string[] }>;\n // Narrow embed invalidation (open.ts, embed-scope.ts's classifyEmbedChange): 'model' nulls every\n // vector/scale in place; 'chunk' rebuilds every embedding row. Neither touches another table.\n invalidate(kind: EmbedChangeKind): Promise<{ parsed: number }>;\n // Narrow feature-toggle invalidation (open.ts, feature-scope.ts's classifyFeatureToggles): a\n // toggle drops (or, turning back on, fully re-derives) that feature's own table; rank instead\n // nulls or recomputes its `_rank` column, since rows written while a feature was off are\n // untrustworthy (reconcile.ts's activeFeatures skips a disabled feature's hooks entirely).\n invalidateFeatures(toggles: FeatureToggle[]): Promise<{ parsed: number }>;\n // Releases the parse worker pool, if this lifetime ever created one; never the connection.\n close(): Promise<void>;\n // Pools this lifetime has constructed, so reuse is observable rather than inferred.\n readonly poolsCreated: number;\n}\n\n// 'model': the provider or model name moved but chunk boundaries did not, so only the vector\n// values are stale. No reparse, and no table but embeddings is touched.\nasync function nullEmbedVectors(conn: Connection, dialect: ReconcileDialect): Promise<{ parsed: number }> {\n await withTransaction(conn, () => conn.exec('UPDATE embeddings SET vector = NULL, scale = NULL'), dialect.beginMode());\n return { parsed: 0 };\n}\n\n// 'chunk': chunkTokens or the chunk version moved, so chunk boundaries genuinely changed. Rebuilds\n// every embedding row through the embed feature's own remove/store, touching no other table.\nasync function rebuildEmbeddings(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect, pool: ParsePool): Promise<{ parsed: number }> {\n const existingStmt = await conn.prepare('SELECT \"path\" FROM frontmatter');\n const existingPaths = new Set((await existingStmt.all()).map((r) => (r as { path: string }).path));\n // A file added since the last build has no row yet; leaving it for build() to insert avoids a\n // primary-key collision between this INSERT and build()'s own insert for the same new file.\n const files = listFiles(cfg, baseDir).filter((f) => f.embed && existingPaths.has(f.relPath));\n if (files.length === 0) return { parsed: 0 };\n\n const { docs } = await reparseFiles(files, [embed], cfg, new Set(), undefined, { pool });\n const paths = docs.map((d) => d.relPath);\n const delta: ReconcileDelta = { files, reparsed: paths, added: [], vanished: [] };\n await withTransaction(\n conn,\n async () => {\n await embed.remove?.(conn, paths, delta);\n await embed.store?.(\n conn,\n docs.map((d) => ({ path: d.relPath, extracted: d.extracted.embed })),\n delta\n );\n },\n dialect.beginMode()\n );\n return { parsed: docs.length };\n}\n\n// One feature's own table, dropped and (turning on) fully re-derived across every indexed file.\n// Rows left over from before this feature was disabled are untrustworthy by construction (files\n// added, edited, or deleted got no remove/store for it), so this never diffs against them --\n// dropping every row and reparsing the whole tree is the only safe path back to consistent state.\nasync function invalidateFeatureTable(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect, pool: ParsePool, toggle: FeatureToggle): Promise<{ parsed: number }> {\n const table = NARROW_FEATURE_TABLE[toggle.name];\n const feature = FEATURES.find((f) => f.name === toggle.name);\n if (!feature) throw new Error(`invalidateFeatureTable: no registered feature named \"${toggle.name}\"`);\n\n if (!toggle.turnedOn) {\n await withTransaction(conn, () => conn.exec(`DELETE FROM ${table}`), dialect.beginMode());\n return { parsed: 0 };\n }\n\n const files = listFiles(cfg, baseDir);\n const { docs } = await reparseFiles(files, [feature], cfg, new Set(), undefined, { pool });\n const docsForFeature = docs.map((d) => ({ path: d.relPath, extracted: d.extracted[feature.name] }));\n const paths = docs.map((d) => d.relPath);\n // Every path counts as added, not just touched: the table was just dropped, so there is nothing\n // stale to diff against, and links' own afterReconcile takes its cold-build (resolveAll) path\n // only when added.length equals files.length.\n const delta: ReconcileDelta = { files, reparsed: paths, added: paths, vanished: [] };\n await withTransaction(\n conn,\n async () => {\n await conn.exec(`DELETE FROM ${table}`);\n await feature.store?.(conn, docsForFeature, delta);\n await feature.afterReconcile?.(conn, delta);\n },\n dialect.beginMode()\n );\n return { parsed: docs.length };\n}\n\n// rank has no table of its own: frontmatter._rank is the only state it owns. Guarded on column\n// presence, since links can toggle off while rank has never been enabled for this tree.\nasync function nullRank(conn: Connection, dialect: ReconcileDialect): Promise<void> {\n const columns = await getColumns(conn);\n if (!columns.has('_rank')) return;\n await withTransaction(conn, () => conn.exec('UPDATE frontmatter SET \"_rank\" = NULL'), dialect.beginMode());\n}\n\n// Whole-tree and reparse-free: PageRank is computed from the links table, not from files, so\n// turning rank back on needs no reparseFiles pass at all.\nasync function rerunRank(conn: Connection, dialect: ReconcileDialect): Promise<void> {\n const delta: ReconcileDelta = { files: [], reparsed: [], added: [], vanished: [] };\n await withTransaction(\n conn,\n async () => {\n await rank.afterReconcile?.(conn, delta);\n },\n dialect.beginMode()\n );\n}\n\nasync function invalidateFeatureToggles(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect, pool: ParsePool, toggles: FeatureToggle[]): Promise<{ parsed: number }> {\n const byName = new Map(toggles.map((toggle) => [toggle.name, toggle]));\n let parsed = 0;\n\n // links first, if present: rank's rerun below (whether from its own toggle or the co-change\n // rankToggle carries) must read the links table after it is back in its new state.\n const linksToggle = byName.get('links');\n if (linksToggle) {\n parsed += (await invalidateFeatureTable(conn, cfg, baseDir, dialect, pool, linksToggle)).parsed;\n // Unconditional, per rank's dependency on links: nulling is a no-op (guarded) when rank was\n // never enabled for this tree, so this is safe even when no feature:rank segment changed.\n if (!linksToggle.turnedOn) await nullRank(conn, dialect);\n }\n\n // rank's effective on/off (featureEnabled's links dependency) only appears as a changed\n // `feature:rank` segment when it actually flips -- whether that's rank's own config or a\n // links toggle taking it along -- so honoring it here is complete on its own.\n const rankToggle = byName.get('rank');\n if (rankToggle) {\n if (rankToggle.turnedOn) await rerunRank(conn, dialect);\n else await nullRank(conn, dialect);\n }\n\n for (const toggle of toggles) {\n if (toggle.name === 'links' || toggle.name === 'rank') continue;\n parsed += (await invalidateFeatureTable(conn, cfg, baseDir, dialect, pool, toggle)).parsed;\n }\n return { parsed };\n}\n\n// The pool is created at most once, lazily, on whichever build() or invalidate() call first\n// needs it, and reused by every later call on this instance.\nexport function createBuilder(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect): Builder {\n const pool = new ParsePool();\n return {\n build: (forcedPaths) => reconcile(conn, cfg, baseDir, dialect, pool, forcedPaths),\n invalidate: (kind) => (kind === 'model' ? nullEmbedVectors(conn, dialect) : rebuildEmbeddings(conn, cfg, baseDir, dialect, pool)),\n invalidateFeatures: (toggles) => invalidateFeatureToggles(conn, cfg, baseDir, dialect, pool, toggles),\n close: () => pool.close(),\n get poolsCreated() {\n return pool.poolsCreated;\n },\n };\n}\n"],"names":["createBuilder","nullEmbedVectors","conn","dialect","withTransaction","exec","beginMode","parsed","rebuildEmbeddings","cfg","baseDir","pool","existingStmt","existingPaths","files","docs","paths","delta","prepare","Set","all","map","r","path","listFiles","filter","f","embed","has","relPath","length","reparseFiles","undefined","d","reparsed","added","vanished","remove","store","extracted","invalidateFeatureTable","toggle","table","feature","docsForFeature","NARROW_FEATURE_TABLE","name","FEATURES","find","Error","turnedOn","afterReconcile","nullRank","columns","getColumns","rerunRank","rank","invalidateFeatureToggles","toggles","byName","linksToggle","rankToggle","Map","get","ParsePool","build","forcedPaths","reconcile","invalidate","kind","invalidateFeatures","close","poolsCreated"],"mappings":";;;;+BA6JgBA;;;eAAAA;;;uBA5JM;uBACG;sBACJ;wBAEK;sBACA;yBACG;8BAGQ;2BACX;wBACC;6BACK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBhC,6FAA6F;AAC7F,wEAAwE;AACxE,SAAeC,iBAAiBC,IAAgB,EAAEC,OAAyB;;;;;oBACzE;;wBAAMC,IAAAA,8BAAe,EAACF,MAAM;mCAAMA,KAAKG,IAAI,CAAC;2BAAsDF,QAAQG,SAAS;;;oBAAnH;oBACA;;wBAAO;4BAAEC,QAAQ;wBAAE;;;;IACrB;;AAEA,mGAAmG;AACnG,6FAA6F;AAC7F,SAAeC,kBAAkBN,IAAgB,EAAEO,GAAW,EAAEC,OAAe,EAAEP,OAAyB,EAAEQ,IAAe;;YACnHC,cACAC,kBAGAC,OAGEC,MACFC,OACAC;;;;oBATe;;wBAAMf,KAAKgB,OAAO,CAAC;;;oBAAlCN,eAAe;wBACKO;oBAAK;;wBAAMP,aAAaQ,GAAG;;;oBAA/CP,gBAAgB,IAAA,CAAA,EAAA,MAAIM;;wBAAK,cAA0BE,GAAG,CAAC,SAACC;mCAAM,AAACA,EAAuBC,IAAI;;sBAAC;oBACjG,8FAA8F;oBAC9F,4FAA4F;oBACtFT,QAAQU,IAAAA,mBAAS,EAACf,KAAKC,SAASe,MAAM,CAAC,SAACC;+BAAMA,EAAEC,KAAK,IAAId,cAAce,GAAG,CAACF,EAAEG,OAAO;;oBAC1F,IAAIf,MAAMgB,MAAM,KAAK,GAAG;;wBAAO;4BAAEvB,QAAQ;wBAAE;;oBAE1B;;wBAAMwB,IAAAA,uBAAY,EAACjB;4BAAQa,cAAK;2BAAGlB,KAAK,IAAIU,OAAOa,WAAW;4BAAErB,MAAAA;wBAAK;;;oBAA9EI,OAAS,cAATA;oBACFC,QAAQD,KAAKM,GAAG,CAAC,SAACY;+BAAMA,EAAEJ,OAAO;;oBACjCZ,QAAwB;wBAAEH,OAAAA;wBAAOoB,UAAUlB;wBAAOmB,KAAK;wBAAMC,QAAQ;oBAAK;oBAChF;;wBAAMhC,IAAAA,8BAAe,EACnBF,MACA;;oCACQyB,eACAA;;;;4CADN;;iDAAMA,gBAAAA,cAAK,CAACU,MAAM,cAAZV,oCAAAA,mBAAAA,cAAK,EAAUzB,MAAMc,OAAOC;;;4CAAlC;4CACA;;iDAAMU,eAAAA,cAAK,CAACW,KAAK,cAAXX,mCAAAA,kBAAAA,cAAK,EACTzB,MACAa,KAAKM,GAAG,CAAC,SAACY;2DAAO;wDAAEV,MAAMU,EAAEJ,OAAO;wDAAEU,WAAWN,EAAEM,SAAS,CAACZ,KAAK;oDAAC;oDACjEV;;;4CAHF;;;;;;4BAKF;2BACAd,QAAQG,SAAS;;;oBAVnB;oBAYA;;wBAAO;4BAAEC,QAAQQ,KAAKe,MAAM;wBAAC;;;;IAC/B;;AAEA,gGAAgG;AAChG,gGAAgG;AAChG,6FAA6F;AAC7F,kGAAkG;AAClG,SAAeU,uBAAuBtC,IAAgB,EAAEO,GAAW,EAAEC,OAAe,EAAEP,OAAyB,EAAEQ,IAAe,EAAE8B,MAAqB;;YAC/IC,OACAC,SAQA7B,OACEC,MACF6B,gBACA5B,OAIAC;;;;oBAhBAyB,QAAQG,oCAAoB,CAACJ,OAAOK,IAAI,CAAC;oBACzCH,UAAUI,iBAAQ,CAACC,IAAI,CAAC,SAACtB;+BAAMA,EAAEoB,IAAI,KAAKL,OAAOK,IAAI;;oBAC3D,IAAI,CAACH,SAAS,MAAM,IAAIM,MAAM,AAAC,wDAAmE,OAAZR,OAAOK,IAAI,EAAC;yBAE9F,CAACL,OAAOS,QAAQ,EAAhB;;;;oBACF;;wBAAM9C,IAAAA,8BAAe,EAACF,MAAM;mCAAMA,KAAKG,IAAI,CAAC,AAAC,eAAoB,OAANqC;2BAAUvC,QAAQG,SAAS;;;oBAAtF;oBACA;;wBAAO;4BAAEC,QAAQ;wBAAE;;;oBAGfO,QAAQU,IAAAA,mBAAS,EAACf,KAAKC;oBACZ;;wBAAMqB,IAAAA,uBAAY,EAACjB;4BAAQ6B;2BAAUlC,KAAK,IAAIU,OAAOa,WAAW;4BAAErB,MAAAA;wBAAK;;;oBAAhFI,OAAS,cAATA;oBACF6B,iBAAiB7B,KAAKM,GAAG,CAAC,SAACY;+BAAO;4BAAEV,MAAMU,EAAEJ,OAAO;4BAAEU,WAAWN,EAAEM,SAAS,CAACI,QAAQG,IAAI,CAAC;wBAAC;;oBAC1F9B,QAAQD,KAAKM,GAAG,CAAC,SAACY;+BAAMA,EAAEJ,OAAO;;oBACvC,gGAAgG;oBAChG,8FAA8F;oBAC9F,8CAA8C;oBACxCZ,QAAwB;wBAAEH,OAAAA;wBAAOoB,UAAUlB;wBAAOmB,OAAOnB;wBAAOoB,QAAQ;oBAAK;oBACnF;;wBAAMhC,IAAAA,8BAAe,EACnBF,MACA;;oCAEQyC,gBACAA;;;;4CAFN;;gDAAMzC,KAAKG,IAAI,CAAC,AAAC,eAAoB,OAANqC;;;4CAA/B;4CACA;;iDAAMC,iBAAAA,QAAQL,KAAK,cAAbK,qCAAAA,oBAAAA,SAAgBzC,MAAM0C,gBAAgB3B;;;4CAA5C;4CACA;;iDAAM0B,0BAAAA,QAAQQ,cAAc,cAAtBR,8CAAAA,6BAAAA,SAAyBzC,MAAMe;;;4CAArC;;;;;;4BACF;2BACAd,QAAQG,SAAS;;;oBAPnB;oBASA;;wBAAO;4BAAEC,QAAQQ,KAAKe,MAAM;wBAAC;;;;IAC/B;;AAEA,+FAA+F;AAC/F,wFAAwF;AACxF,SAAesB,SAASlD,IAAgB,EAAEC,OAAyB;;YAC3DkD;;;;oBAAU;;wBAAMC,IAAAA,oBAAU,EAACpD;;;oBAA3BmD,UAAU;oBAChB,IAAI,CAACA,QAAQzB,GAAG,CAAC,UAAU;;;oBAC3B;;wBAAMxB,IAAAA,8BAAe,EAACF,MAAM;mCAAMA,KAAKG,IAAI,CAAC;2BAA0CF,QAAQG,SAAS;;;oBAAvG;;;;;;IACF;;AAEA,6FAA6F;AAC7F,0DAA0D;AAC1D,SAAeiD,UAAUrD,IAAgB,EAAEC,OAAyB;;YAC5Dc;;;;oBAAAA,QAAwB;wBAAEH,KAAK;wBAAMoB,QAAQ;wBAAMC,KAAK;wBAAMC,QAAQ;oBAAK;oBACjF;;wBAAMhC,IAAAA,8BAAe,EACnBF,MACA;;oCACQsD;;;;4CAAN;;iDAAMA,uBAAAA,YAAI,CAACL,cAAc,cAAnBK,2CAAAA,0BAAAA,YAAI,EAAkBtD,MAAMe;;;4CAAlC;;;;;;4BACF;2BACAd,QAAQG,SAAS;;;oBALnB;;;;;;IAOF;;AAEA,SAAemD,yBAAyBvD,IAAgB,EAAEO,GAAW,EAAEC,OAAe,EAAEP,OAAyB,EAAEQ,IAAe,EAAE+C,OAAwB;;YACpJC,QACFpD,QAIEqD,aAWAC,YAMD,2BAAA,mBAAA,gBAAA,WAAA,OAAMpB;;;;oBAtBLkB,SAAS,IAAIG,IAAIJ,QAAQrC,GAAG,CAAC,SAACoB;+BAAW;4BAACA,OAAOK,IAAI;4BAAEL;yBAAO;;oBAChElC,SAAS;oBAEb,4FAA4F;oBAC5F,mFAAmF;oBAC7EqD,cAAcD,OAAOI,GAAG,CAAC;yBAC3BH,aAAAA;;;;oBACS;;wBAAMpB,uBAAuBtC,MAAMO,KAAKC,SAASP,SAASQ,MAAMiD;;;oBAA3ErD,SAAAA,SAAU,AAAC,cAA8EA,MAAM;yBAG3F,CAACqD,YAAYV,QAAQ,EAArB;;;;oBAAuB;;wBAAME,SAASlD,MAAMC;;;oBAArB;;;oBAG7B,wFAAwF;oBACxF,yFAAyF;oBACzF,8EAA8E;oBACxE0D,aAAaF,OAAOI,GAAG,CAAC;yBAC1BF,YAAAA;;;;yBACEA,WAAWX,QAAQ,EAAnBW;;;;oBAAqB;;wBAAMN,UAAUrD,MAAMC;;;oBAAtB;;;;;;oBACpB;;wBAAMiD,SAASlD,MAAMC;;;oBAArB;;;oBAGF,kCAAA,2BAAA;;;;;;;;;oBAAA,YAAgBuD;;;2BAAhB,6BAAA,QAAA;;;;oBAAMjB,SAAN;oBACH,IAAIA,OAAOK,IAAI,KAAK,WAAWL,OAAOK,IAAI,KAAK,QAAQ;;;;oBAC5C;;wBAAMN,uBAAuBtC,MAAMO,KAAKC,SAASP,SAASQ,MAAM8B;;;oBAA3ElC,SAAAA,SAAU,AAAC,cAAyEA,MAAM;;;oBAFvF;;;;;;;;;;;;oBAAA;oBAAA;;;;;;;6BAAA,6BAAA;4BAAA;;;4BAAA;kCAAA;;;;;;;oBAIL;;wBAAO;4BAAEA,QAAAA;wBAAO;;;;IAClB;;AAIO,SAASP,cAAcE,IAAgB,EAAEO,GAAW,EAAEC,OAAe,EAAEP,OAAyB;IACrG,IAAMQ,OAAO,IAAIqD,iBAAS;IAC1B,OAAO;QACLC,OAAO,SAAPA,MAAQC;mBAAgBC,IAAAA,sBAAS,EAACjE,MAAMO,KAAKC,SAASP,SAASQ,MAAMuD;;QACrEE,YAAY,SAAZA,WAAaC;mBAAUA,SAAS,UAAUpE,iBAAiBC,MAAMC,WAAWK,kBAAkBN,MAAMO,KAAKC,SAASP,SAASQ;;QAC3H2D,oBAAoB,SAApBA,mBAAqBZ;mBAAYD,yBAAyBvD,MAAMO,KAAKC,SAASP,SAASQ,MAAM+C;;QAC7Fa,OAAO,SAAPA;mBAAa5D,KAAK4D,KAAK;;QACvB,IAAIC;YACF,OAAO7D,KAAK6D,YAAY;QAC1B;IACF;AACF"}
|
|
@@ -2,4 +2,7 @@ import type { DuckDBConnection } from '@duckdb/node-api';
|
|
|
2
2
|
import type { Connection } from '../types.js';
|
|
3
3
|
export declare function storeValueToJs(value: unknown): unknown;
|
|
4
4
|
export declare function storeRowToJs(row: Record<string, unknown>): Record<string, unknown>;
|
|
5
|
-
export
|
|
5
|
+
export interface DuckdbConnection extends Connection {
|
|
6
|
+
readonly duckdb: DuckDBConnection;
|
|
7
|
+
}
|
|
8
|
+
export declare function createConnection(duckdb: DuckDBConnection): DuckdbConnection;
|
|
@@ -2,4 +2,7 @@ import type { DuckDBConnection } from '@duckdb/node-api';
|
|
|
2
2
|
import type { Connection } from '../types.js';
|
|
3
3
|
export declare function storeValueToJs(value: unknown): unknown;
|
|
4
4
|
export declare function storeRowToJs(row: Record<string, unknown>): Record<string, unknown>;
|
|
5
|
-
export
|
|
5
|
+
export interface DuckdbConnection extends Connection {
|
|
6
|
+
readonly duckdb: DuckDBConnection;
|
|
7
|
+
}
|
|
8
|
+
export declare function createConnection(duckdb: DuckDBConnection): DuckdbConnection;
|
|
@@ -568,6 +568,7 @@ var DuckdbStatement = /*#__PURE__*/ function() {
|
|
|
568
568
|
}();
|
|
569
569
|
function createConnection(duckdb) {
|
|
570
570
|
var conn = {
|
|
571
|
+
duckdb: duckdb,
|
|
571
572
|
exec: function exec(sql) {
|
|
572
573
|
return _async_to_generator(function() {
|
|
573
574
|
return _ts_generator(this, function(_state) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/connection.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBPreparedStatement, DuckDBValue } from '@duckdb/node-api';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\nimport { rewriteBatch } from './batch.ts';\n\n// getRowObjectsJS returns INT64 columns as BigInt regardless of magnitude, while sqlite's small\n// ints are numbers and consumers assume number; in-range values convert here, out-of-range stays BigInt.\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\nexport function storeValueToJs(value: unknown): unknown {\n return typeof value === 'bigint' && value >= -MAX_SAFE && value <= MAX_SAFE ? Number(value) : value;\n}\nexport function storeRowToJs(row: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) out[key] = storeValueToJs(value);\n return out;\n}\n\n// @duckdb/node-api only destroys a prepared statement when its connection closes, but a connection can stay open for a whole `sense watch` session.\n// Statement has no dispose (callers reuse one instance across several calls), so this FinalizationRegistry reclaims it once nothing references the wrapper.\nconst preparedFinalizer = new FinalizationRegistry<DuckDBPreparedStatement>((prepared) => {\n prepared.destroySync();\n});\n\n// Wraps one already-prepared DuckDB statement: prepare() is the only async step, so run/get/all rebind and\n// re-execute the same native statement, matching how callers like graph/traverse.ts's ring loop reuse one Statement across several calls.\nclass DuckdbStatement implements Statement {\n private prepared: DuckDBPreparedStatement;\n\n constructor(prepared: DuckDBPreparedStatement) {\n this.prepared = prepared;\n preparedFinalizer.register(this, prepared);\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n if (params.length > 0) this.prepared.bind(params as DuckDBValue[]);\n const result = await this.prepared.run();\n return { changes: result.rowsChanged, lastInsertRowid: 0 };\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n const rows = await this.all(...params);\n return rows[0];\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n if (params.length > 0) this.prepared.bind(params as DuckDBValue[]);\n const reader = await this.prepared.runAndReadAll();\n return (reader.getRowObjectsJS() as Array<Record<string, unknown>>).map(storeRowToJs);\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n // Never called on the portable Connection/Statement surface today (only Store.raw streams);\n // materializing keeps this a correct, if eager, AsyncIterable.\n yield* await this.all(...params);\n }\n\n columns(): Array<{ name: string }> {\n const out: Array<{ name: string }> = [];\n for (let i = 0; i < this.prepared.columnCount; i++) out.push({ name: this.prepared.columnName(i) });\n return out;\n }\n\n setReadBigInts(_enabled: boolean): void {\n // No-op: in-range ints are already numbers here (storeRowToJs converts what getRowObjectsJS\n // hands back as BigInt), so the node:sqlite throw-at-step-time problem does not exist.\n }\n}\n\nexport function createConnection(duckdb: DuckDBConnection):
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/connection.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBPreparedStatement, DuckDBValue } from '@duckdb/node-api';\nimport { withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\nimport { rewriteBatch } from './batch.ts';\n\n// getRowObjectsJS returns INT64 columns as BigInt regardless of magnitude, while sqlite's small\n// ints are numbers and consumers assume number; in-range values convert here, out-of-range stays BigInt.\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\nexport function storeValueToJs(value: unknown): unknown {\n return typeof value === 'bigint' && value >= -MAX_SAFE && value <= MAX_SAFE ? Number(value) : value;\n}\nexport function storeRowToJs(row: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) out[key] = storeValueToJs(value);\n return out;\n}\n\n// @duckdb/node-api only destroys a prepared statement when its connection closes, but a connection can stay open for a whole `sense watch` session.\n// Statement has no dispose (callers reuse one instance across several calls), so this FinalizationRegistry reclaims it once nothing references the wrapper.\nconst preparedFinalizer = new FinalizationRegistry<DuckDBPreparedStatement>((prepared) => {\n prepared.destroySync();\n});\n\n// Wraps one already-prepared DuckDB statement: prepare() is the only async step, so run/get/all rebind and\n// re-execute the same native statement, matching how callers like graph/traverse.ts's ring loop reuse one Statement across several calls.\nclass DuckdbStatement implements Statement {\n private prepared: DuckDBPreparedStatement;\n\n constructor(prepared: DuckDBPreparedStatement) {\n this.prepared = prepared;\n preparedFinalizer.register(this, prepared);\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n if (params.length > 0) this.prepared.bind(params as DuckDBValue[]);\n const result = await this.prepared.run();\n return { changes: result.rowsChanged, lastInsertRowid: 0 };\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n const rows = await this.all(...params);\n return rows[0];\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n if (params.length > 0) this.prepared.bind(params as DuckDBValue[]);\n const reader = await this.prepared.runAndReadAll();\n return (reader.getRowObjectsJS() as Array<Record<string, unknown>>).map(storeRowToJs);\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n // Never called on the portable Connection/Statement surface today (only Store.raw streams);\n // materializing keeps this a correct, if eager, AsyncIterable.\n yield* await this.all(...params);\n }\n\n columns(): Array<{ name: string }> {\n const out: Array<{ name: string }> = [];\n for (let i = 0; i < this.prepared.columnCount; i++) out.push({ name: this.prepared.columnName(i) });\n return out;\n }\n\n setReadBigInts(_enabled: boolean): void {\n // No-op: in-range ints are already numbers here (storeRowToJs converts what getRowObjectsJS\n // hands back as BigInt), so the node:sqlite throw-at-step-time problem does not exist.\n }\n}\n\n// Adds the native DuckDBConnection to the portable Connection, so duckdb's own dialect code\n// (reconcile.ts's insertNew) can reach createAppender(); sqlite/turso have no such member.\nexport interface DuckdbConnection extends Connection {\n readonly duckdb: DuckDBConnection;\n}\n\nexport function createConnection(duckdb: DuckDBConnection): DuckdbConnection {\n const conn: DuckdbConnection = {\n duckdb,\n async exec(sql: string): Promise<void> {\n await duckdb.run(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return new DuckdbStatement(await duckdb.prepare(sql));\n },\n // One crossing regardless of row count: rewriteBatch folds recognized shapes into a multi-row statement (batch.ts),\n // else falls back to a bind-and-run loop, one call either way. Joins the caller's transaction when there is one, else opens its own.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(conn, async () => {\n const rewritten = rewriteBatch(sql, paramRows.length);\n if (rewritten) {\n const stmt = await duckdb.prepare(rewritten.sql);\n try {\n stmt.bind(paramRows.flat() as DuckDBValue[]);\n await stmt.run();\n } finally {\n stmt.destroySync();\n }\n return;\n }\n const stmt = await duckdb.prepare(sql);\n try {\n for (const row of paramRows) {\n stmt.bind(row as DuckDBValue[]);\n await stmt.run();\n }\n } finally {\n stmt.destroySync();\n }\n });\n },\n };\n return conn;\n}\n"],"names":["createConnection","storeRowToJs","storeValueToJs","MAX_SAFE","BigInt","Number","MAX_SAFE_INTEGER","value","row","out","Object","entries","key","preparedFinalizer","FinalizationRegistry","prepared","destroySync","DuckdbStatement","register","run","params","result","length","bind","changes","rowsChanged","lastInsertRowid","get","rows","all","reader","runAndReadAll","getRowObjectsJS","map","iterate","columns","i","columnCount","push","name","columnName","setReadBigInts","_enabled","duckdb","conn","exec","sql","prepare","runBatch","paramRows","withTransaction","rewritten","stmt","rewriteBatch","flat"],"mappings":"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"}
|
|
@@ -167,7 +167,7 @@ function _ts_generator(thisArg, body) {
|
|
|
167
167
|
var DB_FILENAME = 'cache.duckdb';
|
|
168
168
|
var SCHEMA_VERSION = '3';
|
|
169
169
|
// `content` is a plain table (not FTS-virtual): the fts index is built over it lazily, only when a lexical query runs (lexical.ts), and read directly for contains() verification either way.
|
|
170
|
-
// No tokenizer resolution: this store always uses the fts extension's default (porter) stemmer
|
|
170
|
+
// No tokenizer resolution: this store always uses the fts extension's default (porter) stemmer.
|
|
171
171
|
function ensureSchema(_handle, conn, cfg) {
|
|
172
172
|
return _async_to_generator(function() {
|
|
173
173
|
var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, feature, err;
|
|
@@ -431,6 +431,12 @@ var duckdbOpenDialect = {
|
|
|
431
431
|
reconcileDialect: _reconcilets.duckdbDialect,
|
|
432
432
|
connect: connect,
|
|
433
433
|
close: close,
|
|
434
|
+
// duckdb's file lock spans the connection's life, and each platform words the refusal its own
|
|
435
|
+
// way: posix "Could not set lock on file ... Conflicting lock is held in <exe> (PID n)", Windows
|
|
436
|
+
// "Cannot open file ... being used by another process". Both are the same condition.
|
|
437
|
+
isLocked: function isLocked(err) {
|
|
438
|
+
return /Could not set lock on file|being used by another process/.test(err.message);
|
|
439
|
+
},
|
|
434
440
|
ensureSchema: ensureSchema,
|
|
435
441
|
createStore: function createStore(handle, conn) {
|
|
436
442
|
return (0, _storets.createStore)(handle.instance, handle.duckdb, conn);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/open.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\nimport type { Config, ResolvedConfig } from '../../config/index.ts';\nimport { featureSignature } from '../../config/index.ts';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { SenseError } from '../../errors.ts';\nimport { activeFeatures, FEATURES } from '../../features/index.ts';\nimport type { OpenResult } from '../open.ts';\nimport { openWithDialect } from '../open.ts';\nimport { getMeta, setMeta } from '../shared.ts';\nimport type { Connection, OpenDialect } from '../types.ts';\nimport { createConnection } from './connection.ts';\nimport { DUCKDB_PACKAGE, duckdbApi } from './native.ts';\nimport { duckdbDialect } from './reconcile.ts';\nimport { registerFunctions } from './sql-functions.ts';\nimport { createStore } from './store.ts';\n\nexport const DB_FILENAME = 'cache.duckdb';\n// Independent of sqlite's SCHEMA_VERSION -- the two stores' cache shapes evolve separately (VARIANT frontmatter columns vs untyped).\n// The store name already joins the feature signature, so switching a config's `store` key rebuilds rather than reusing the other engine's cache.\nexport const SCHEMA_VERSION = '3';\n\nexport type { OpenResult };\n\n// The connection plus this store's own native handles (types.ts's OpenDialect<Handle>): the\n// instance owns the WAL and must outlive the connection borrowed from it.\ninterface DuckdbHandle {\n instance: DuckDBInstance;\n duckdb: DuckDBConnection;\n}\n\n// `content` is a plain table (not FTS-virtual): the fts index is built over it lazily, only when a lexical query runs (lexical.ts), and read directly for contains() verification either way.\n// No tokenizer resolution: this store always uses the fts extension's default (porter) stemmer
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/open.ts"],"sourcesContent":["import type { DuckDBConnection, DuckDBInstance } from '@duckdb/node-api';\nimport type { Config, ResolvedConfig } from '../../config/index.ts';\nimport { featureSignature } from '../../config/index.ts';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { SenseError } from '../../errors.ts';\nimport { activeFeatures, FEATURES } from '../../features/index.ts';\nimport type { OpenResult } from '../open.ts';\nimport { openWithDialect } from '../open.ts';\nimport { getMeta, setMeta } from '../shared.ts';\nimport type { Connection, OpenDialect } from '../types.ts';\nimport { createConnection } from './connection.ts';\nimport { DUCKDB_PACKAGE, duckdbApi } from './native.ts';\nimport { duckdbDialect } from './reconcile.ts';\nimport { registerFunctions } from './sql-functions.ts';\nimport { createStore } from './store.ts';\n\nexport const DB_FILENAME = 'cache.duckdb';\n// Independent of sqlite's SCHEMA_VERSION -- the two stores' cache shapes evolve separately (VARIANT frontmatter columns vs untyped).\n// The store name already joins the feature signature, so switching a config's `store` key rebuilds rather than reusing the other engine's cache.\nexport const SCHEMA_VERSION = '3';\n\nexport type { OpenResult };\n\n// The connection plus this store's own native handles (types.ts's OpenDialect<Handle>): the\n// instance owns the WAL and must outlive the connection borrowed from it.\ninterface DuckdbHandle {\n instance: DuckDBInstance;\n duckdb: DuckDBConnection;\n}\n\n// `content` is a plain table (not FTS-virtual): the fts index is built over it lazily, only when a lexical query runs (lexical.ts), and read directly for contains() verification either way.\n// No tokenizer resolution: this store always uses the fts extension's default (porter) stemmer.\nasync function ensureSchema(_handle: DuckdbHandle, conn: Connection, cfg: Config): Promise<void> {\n await conn.exec(`CREATE TABLE IF NOT EXISTS frontmatter (\"path\" TEXT PRIMARY KEY, \"_mtime\" DOUBLE, \"_ctime\" DOUBLE, \"_size\" INTEGER, \"_parse_error\" TEXT)`);\n await conn.exec(`CREATE TABLE IF NOT EXISTS content (\"path\" TEXT PRIMARY KEY, title TEXT, summary TEXT, text TEXT)`);\n await conn.exec(`CREATE TABLE IF NOT EXISTS preset_files (\"path\" TEXT, preset TEXT, PRIMARY KEY (\"path\", preset))`);\n await conn.exec('CREATE INDEX IF NOT EXISTS preset_files_preset ON preset_files(preset)');\n for (const feature of activeFeatures(cfg)) {\n // Native FLOAT[STORE_DIMS] instead of the embed feature's engine-neutral BLOB+scale DDL (vectors.ts). `scale` is kept, unused,\n // so the feature's shared reconcile-time INSERT/DELETE (features/embed.ts) names a column that exists on both stores.\n if (feature.name === 'embed') {\n await conn.exec(`CREATE TABLE IF NOT EXISTS embeddings (\"path\" TEXT, chunk INTEGER, start_line INTEGER, end_line INTEGER, scale REAL, vector FLOAT[${STORE_DIMS}], PRIMARY KEY (\"path\", chunk))`);\n continue;\n }\n await feature.schema(conn);\n }\n if ((await getMeta(conn, 'schema_version')) === null) await setMeta(conn, 'schema_version', SCHEMA_VERSION);\n if ((await getMeta(conn, 'features')) === null) await setMeta(conn, 'features', featureSignature(cfg, FEATURES));\n}\n\n// Order matters: the connection must be gone before the instance closes the WAL.\nasync function close(handle: DuckdbHandle): Promise<void> {\n handle.duckdb.disconnectSync();\n handle.instance.closeSync();\n}\n\nasync function connect(dbPath: string, _cfg: ResolvedConfig): Promise<{ handle: DuckdbHandle; conn: Connection }> {\n // Dynamic, not a top-level import: sqlite trees must never attempt to resolve this optional peer dependency, so nothing imports\n // it as a value until a duckdb tree opens (types-only imports are erased). Installed on first use if missing, shared with sql-functions.ts and vectors.ts via native.ts's duckdbApi.\n let DuckDBInstance: typeof import('@duckdb/node-api').DuckDBInstance;\n try {\n ({ DuckDBInstance } = await duckdbApi());\n } catch (err) {\n if (err instanceof SenseError) throw err;\n throw new SenseError('STORE_DEPENDENCY_MISSING', `store \"duckdb\" needs the ${DUCKDB_PACKAGE} package (${(err as Error).message})`);\n }\n\n let duckdb: DuckDBConnection;\n let instance: DuckDBInstance | undefined;\n try {\n // On-disk files default to an older storage format for cross-version compatibility, which rejects VARIANT columns (\"VARIANT\n // columns are not supported in storage versions prior to v1.5.0\"); this store's dynamic frontmatter columns need VARIANT (reconcile.ts), so the floor is pinned explicitly.\n instance = await DuckDBInstance.create(dbPath, { storage_compatibility_version: 'v1.5.0' });\n duckdb = await instance.connect();\n } catch (err) {\n // create() may have succeeded before connect() failed: close it, or its WAL stays open.\n instance?.closeSync();\n throw new SenseError('STORE_DEPENDENCY_MISSING', `store \"duckdb\" failed to open ${dbPath}: ${(err as Error).message}`);\n }\n // A throw below would leak the open instance, whose WAL then locks the .duckdb file undeletable on Windows.\n try {\n await registerFunctions(duckdb);\n const conn = createConnection(duckdb);\n return { handle: { instance, duckdb }, conn };\n } catch (err) {\n await close({ instance, duckdb });\n throw err;\n }\n}\n\n// This store's dialect (types.ts's OpenDialect) for the shared orchestration in store/open.ts.\nexport const duckdbOpenDialect: OpenDialect<DuckdbHandle> = {\n filename: DB_FILENAME,\n schemaVersion: SCHEMA_VERSION,\n reconcileDialect: duckdbDialect,\n connect,\n close,\n // duckdb's file lock spans the connection's life, and each platform words the refusal its own\n // way: posix \"Could not set lock on file ... Conflicting lock is held in <exe> (PID n)\", Windows\n // \"Cannot open file ... being used by another process\". Both are the same condition.\n isLocked: (err) => /Could not set lock on file|being used by another process/.test(err.message),\n ensureSchema,\n createStore: (handle, conn) => createStore(handle.instance, handle.duckdb, conn),\n};\n\nexport async function openDuckdb(cfg: ResolvedConfig): Promise<OpenResult> {\n return openWithDialect(cfg, duckdbOpenDialect);\n}\n"],"names":["DB_FILENAME","SCHEMA_VERSION","duckdbOpenDialect","openDuckdb","ensureSchema","_handle","conn","cfg","feature","exec","activeFeatures","name","STORE_DIMS","schema","getMeta","setMeta","featureSignature","FEATURES","close","handle","duckdb","disconnectSync","instance","closeSync","connect","dbPath","_cfg","DuckDBInstance","err","duckdbApi","SenseError","DUCKDB_PACKAGE","message","create","storage_compatibility_version","registerFunctions","createConnection","filename","schemaVersion","reconcileDialect","duckdbDialect","isLocked","test","createStore","openWithDialect"],"mappings":"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"}
|
|
@@ -9,7 +9,10 @@ Object.defineProperty(exports, "duckdbDialect", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
var _errorsts = require("../../errors.js");
|
|
12
|
+
var _reconcilets = require("../reconcile.js");
|
|
13
|
+
var _sharedts = require("../shared.js");
|
|
12
14
|
var _lexicalts = require("./lexical.js");
|
|
15
|
+
var _nativets = require("./native.js");
|
|
13
16
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
14
17
|
try {
|
|
15
18
|
var info = gen[key](arg);
|
|
@@ -196,6 +199,135 @@ function reconcileContent(conn, touched, docs, _delta) {
|
|
|
196
199
|
});
|
|
197
200
|
})();
|
|
198
201
|
}
|
|
202
|
+
// DuckDB rejects more than one ALTER command per statement ("Parser Error: Only one ALTER
|
|
203
|
+
// command per statement is supported", measured), so every name's clause joins into one string
|
|
204
|
+
// and runs as a single exec() -- one column-add "leg" through the driver instead of `names.length`.
|
|
205
|
+
// VARIANT is the only type that can hold the mixed bigint/number/string/null shapes mapValue()
|
|
206
|
+
// produces for one key across files.
|
|
207
|
+
function addColumns(conn, names) {
|
|
208
|
+
return _async_to_generator(function() {
|
|
209
|
+
return _ts_generator(this, function(_state) {
|
|
210
|
+
switch(_state.label){
|
|
211
|
+
case 0:
|
|
212
|
+
if (names.length === 0) return [
|
|
213
|
+
2
|
|
214
|
+
];
|
|
215
|
+
return [
|
|
216
|
+
4,
|
|
217
|
+
conn.exec(names.map(function(name) {
|
|
218
|
+
return "ALTER TABLE frontmatter ADD COLUMN ".concat((0, _sharedts.quoteIdent)(name), " VARIANT");
|
|
219
|
+
}).join('; '))
|
|
220
|
+
];
|
|
221
|
+
case 1:
|
|
222
|
+
_state.sent();
|
|
223
|
+
return [
|
|
224
|
+
2
|
|
225
|
+
];
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
})();
|
|
229
|
+
}
|
|
230
|
+
// Appender path for rows that cannot conflict (reconcile.ts's `added`); no ON CONFLICT support, so
|
|
231
|
+
// alignment reads the table's own physical column order fresh -- `columns` omits feature-owned reserved columns (e.g. "_rank") that still exist on the table, and get appendDefault().
|
|
232
|
+
function insertNew(conn, table, columns, rows) {
|
|
233
|
+
return _async_to_generator(function() {
|
|
234
|
+
var variantValue, infoStmt, physicalColumns, rowIndexOf, native, appender, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, row, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, name, idx, value;
|
|
235
|
+
return _ts_generator(this, function(_state) {
|
|
236
|
+
switch(_state.label){
|
|
237
|
+
case 0:
|
|
238
|
+
if (rows.length === 0) return [
|
|
239
|
+
2
|
|
240
|
+
];
|
|
241
|
+
return [
|
|
242
|
+
4,
|
|
243
|
+
(0, _nativets.duckdbApi)()
|
|
244
|
+
];
|
|
245
|
+
case 1:
|
|
246
|
+
variantValue = _state.sent().variantValue;
|
|
247
|
+
return [
|
|
248
|
+
4,
|
|
249
|
+
conn.prepare("PRAGMA table_info(".concat((0, _sharedts.quoteIdent)(table), ")"))
|
|
250
|
+
];
|
|
251
|
+
case 2:
|
|
252
|
+
infoStmt = _state.sent();
|
|
253
|
+
return [
|
|
254
|
+
4,
|
|
255
|
+
infoStmt.all()
|
|
256
|
+
];
|
|
257
|
+
case 3:
|
|
258
|
+
physicalColumns = _state.sent().map(function(c) {
|
|
259
|
+
return c.name;
|
|
260
|
+
});
|
|
261
|
+
rowIndexOf = new Map(columns.map(function(name, i) {
|
|
262
|
+
return [
|
|
263
|
+
name,
|
|
264
|
+
i
|
|
265
|
+
];
|
|
266
|
+
}));
|
|
267
|
+
native = conn.duckdb;
|
|
268
|
+
return [
|
|
269
|
+
4,
|
|
270
|
+
native.createAppender(table)
|
|
271
|
+
];
|
|
272
|
+
case 4:
|
|
273
|
+
appender = _state.sent();
|
|
274
|
+
try {
|
|
275
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
276
|
+
try {
|
|
277
|
+
for(_iterator = rows[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
278
|
+
row = _step.value;
|
|
279
|
+
_iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
|
|
280
|
+
try {
|
|
281
|
+
for(_iterator1 = physicalColumns[Symbol.iterator](); !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
|
|
282
|
+
name = _step1.value;
|
|
283
|
+
idx = rowIndexOf.get(name);
|
|
284
|
+
value = idx === undefined ? undefined : row[idx];
|
|
285
|
+
if (idx === undefined) appender.appendDefault();
|
|
286
|
+
else if (value === null || value === undefined) appender.appendNull();
|
|
287
|
+
else if (_reconcilets.CORE_FRONTMATTER_COLUMNS.has(name)) appender.appendValue(value);
|
|
288
|
+
else appender.appendVariant(variantValue(value));
|
|
289
|
+
}
|
|
290
|
+
} catch (err) {
|
|
291
|
+
_didIteratorError1 = true;
|
|
292
|
+
_iteratorError1 = err;
|
|
293
|
+
} finally{
|
|
294
|
+
try {
|
|
295
|
+
if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
|
|
296
|
+
_iterator1.return();
|
|
297
|
+
}
|
|
298
|
+
} finally{
|
|
299
|
+
if (_didIteratorError1) {
|
|
300
|
+
throw _iteratorError1;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
appender.endRow();
|
|
305
|
+
}
|
|
306
|
+
} catch (err) {
|
|
307
|
+
_didIteratorError = true;
|
|
308
|
+
_iteratorError = err;
|
|
309
|
+
} finally{
|
|
310
|
+
try {
|
|
311
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
312
|
+
_iterator.return();
|
|
313
|
+
}
|
|
314
|
+
} finally{
|
|
315
|
+
if (_didIteratorError) {
|
|
316
|
+
throw _iteratorError;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
appender.flushSync();
|
|
321
|
+
} finally{
|
|
322
|
+
appender.closeSync();
|
|
323
|
+
}
|
|
324
|
+
return [
|
|
325
|
+
2
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
})();
|
|
330
|
+
}
|
|
199
331
|
var duckdbDialect = {
|
|
200
332
|
beginMode: function beginMode() {
|
|
201
333
|
return 'BEGIN';
|
|
@@ -205,11 +337,8 @@ var duckdbDialect = {
|
|
|
205
337
|
throw new _errorsts.SenseError('COLUMN_LIMIT', "frontmatter would need ".concat(count, " columns, crossing this store's sanity limit (").concat(MAX_FRONTMATTER_COLUMNS, "). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys."));
|
|
206
338
|
}
|
|
207
339
|
},
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return ' VARIANT';
|
|
212
|
-
},
|
|
213
|
-
reconcileContent: reconcileContent
|
|
340
|
+
addColumns: addColumns,
|
|
341
|
+
reconcileContent: reconcileContent,
|
|
342
|
+
insertNew: insertNew
|
|
214
343
|
};
|
|
215
344
|
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/reconcile.ts"],"sourcesContent":["import { SenseError } from '../../errors.ts';\nimport type { ReconcileDelta } from '../../features/types.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport type { Connection, ReconcileDialect } from '../types.ts';\nimport { markContentStale } from './lexical.ts';\n\n// This store's dialect (types.ts's ReconcileDialect) for the shared orchestration in\n// store/reconcile.ts. `content` is a plain table, not FTS-virtual, so rows are maintained here\n// unconditionally; DuckDB's ALTER TABLE needs a declared type, so every dynamic frontmatter\n// column is VARIANT (holds mapValue()'s mixed JS types for one key across files).\n\n// No rowid coupling needed (unlike sqlite's content, which links to frontmatter's rowid):\n// `path` is content's own primary key, so this is a plain per-doc row.\nconst INSERT_CONTENT_SQL = `INSERT INTO content (\"path\", title, summary, text) VALUES (?, ?, ?, ?)`;\n\nfunction contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text];\n}\n\n// No compile-time column cap in DuckDB (unlike SQLite's SQLITE_MAX_COLUMN); kept as a sanity fence anyway\n// so a runaway frontmatter generator fails with a clear message instead of an unbounded ALTER TABLE loop.\nconst MAX_FRONTMATTER_COLUMNS = 10_000;\n\nasync function reconcileContent(conn: Connection, touched: string[], docs: ParsedDoc[], _delta: ReconcileDelta): Promise<void> {\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n if (docs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, docs.map(contentRow));\n // content changed: the fts index is rebuilt lazily, on the next lexical query that needs it,\n // not here (lexical.ts's FtsIndexState).\n markContentStale(conn);\n}\n\nexport const duckdbDialect: ReconcileDialect = {\n beginMode: () => 'BEGIN',\n checkColumnLimit(count) {\n if (count > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError('COLUMN_LIMIT', `frontmatter would need ${count} columns, crossing this store's sanity limit (${MAX_FRONTMATTER_COLUMNS}). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`);\n }\n },\n
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/duckdb/reconcile.ts"],"sourcesContent":["import type { DuckDBValue } from '@duckdb/node-api';\nimport { SenseError } from '../../errors.ts';\nimport type { ReconcileDelta } from '../../features/types.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport { CORE_FRONTMATTER_COLUMNS } from '../reconcile.ts';\nimport { quoteIdent } from '../shared.ts';\nimport type { Connection, ReconcileDialect } from '../types.ts';\nimport type { DuckdbConnection } from './connection.ts';\nimport { markContentStale } from './lexical.ts';\nimport { duckdbApi } from './native.ts';\n\n// This store's dialect (types.ts's ReconcileDialect) for the shared orchestration in\n// store/reconcile.ts. `content` is a plain table, not FTS-virtual, so rows are maintained here\n// unconditionally; DuckDB's ALTER TABLE needs a declared type, so every dynamic frontmatter\n// column is VARIANT (holds mapValue()'s mixed JS types for one key across files).\n\n// No rowid coupling needed (unlike sqlite's content, which links to frontmatter's rowid):\n// `path` is content's own primary key, so this is a plain per-doc row.\nconst INSERT_CONTENT_SQL = `INSERT INTO content (\"path\", title, summary, text) VALUES (?, ?, ?, ?)`;\n\nfunction contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text];\n}\n\n// No compile-time column cap in DuckDB (unlike SQLite's SQLITE_MAX_COLUMN); kept as a sanity fence anyway\n// so a runaway frontmatter generator fails with a clear message instead of an unbounded ALTER TABLE loop.\nconst MAX_FRONTMATTER_COLUMNS = 10_000;\n\nasync function reconcileContent(conn: Connection, touched: string[], docs: ParsedDoc[], _delta: ReconcileDelta): Promise<void> {\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n if (docs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, docs.map(contentRow));\n // content changed: the fts index is rebuilt lazily, on the next lexical query that needs it,\n // not here (lexical.ts's FtsIndexState).\n markContentStale(conn);\n}\n\n// DuckDB rejects more than one ALTER command per statement (\"Parser Error: Only one ALTER\n// command per statement is supported\", measured), so every name's clause joins into one string\n// and runs as a single exec() -- one column-add \"leg\" through the driver instead of `names.length`.\n// VARIANT is the only type that can hold the mixed bigint/number/string/null shapes mapValue()\n// produces for one key across files.\nasync function addColumns(conn: Connection, names: string[]): Promise<void> {\n if (names.length === 0) return;\n await conn.exec(names.map((name) => `ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(name)} VARIANT`).join('; '));\n}\n\n// Appender path for rows that cannot conflict (reconcile.ts's `added`); no ON CONFLICT support, so\n// alignment reads the table's own physical column order fresh -- `columns` omits feature-owned reserved columns (e.g. \"_rank\") that still exist on the table, and get appendDefault().\nasync function insertNew(conn: Connection, table: string, columns: string[], rows: unknown[][]): Promise<void> {\n if (rows.length === 0) return;\n const { variantValue } = await duckdbApi();\n const infoStmt = await conn.prepare(`PRAGMA table_info(${quoteIdent(table)})`);\n const physicalColumns = ((await infoStmt.all()) as Array<{ name: string }>).map((c) => c.name);\n const rowIndexOf = new Map(columns.map((name, i) => [name, i]));\n\n const native = (conn as DuckdbConnection).duckdb;\n const appender = await native.createAppender(table);\n try {\n for (const row of rows) {\n for (const name of physicalColumns) {\n const idx = rowIndexOf.get(name);\n const value = idx === undefined ? undefined : row[idx];\n if (idx === undefined) appender.appendDefault();\n else if (value === null || value === undefined) appender.appendNull();\n else if (CORE_FRONTMATTER_COLUMNS.has(name)) appender.appendValue(value as DuckDBValue);\n else appender.appendVariant(variantValue(value as DuckDBValue));\n }\n appender.endRow();\n }\n appender.flushSync();\n } finally {\n appender.closeSync();\n }\n}\n\nexport const duckdbDialect: ReconcileDialect = {\n beginMode: () => 'BEGIN',\n checkColumnLimit(count) {\n if (count > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError('COLUMN_LIMIT', `frontmatter would need ${count} columns, crossing this store's sanity limit (${MAX_FRONTMATTER_COLUMNS}). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`);\n }\n },\n addColumns,\n reconcileContent,\n insertNew,\n};\n"],"names":["duckdbDialect","INSERT_CONTENT_SQL","contentRow","doc","relPath","search","title","summary","text","MAX_FRONTMATTER_COLUMNS","reconcileContent","conn","touched","docs","_delta","length","runBatch","map","p","markContentStale","addColumns","names","exec","name","quoteIdent","join","insertNew","table","columns","rows","variantValue","infoStmt","physicalColumns","rowIndexOf","native","appender","row","idx","value","duckdbApi","prepare","all","c","Map","i","duckdb","createAppender","get","undefined","appendDefault","appendNull","CORE_FRONTMATTER_COLUMNS","has","appendValue","appendVariant","endRow","flushSync","closeSync","beginMode","checkColumnLimit","count","SenseError"],"mappings":";;;;+BA+EaA;;;eAAAA;;;wBA9Ec;2BAGc;wBACd;yBAGM;wBACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE1B,qFAAqF;AACrF,+FAA+F;AAC/F,4FAA4F;AAC5F,kFAAkF;AAElF,0FAA0F;AAC1F,uEAAuE;AACvE,IAAMC,qBAAqB;AAE3B,SAASC,WAAWC,GAAc;IAChC,OAAO;QAACA,IAAIC,OAAO;QAAED,IAAIE,MAAM,CAACC,KAAK;QAAEH,IAAIE,MAAM,CAACE,OAAO;QAAEJ,IAAIE,MAAM,CAACG,IAAI;KAAC;AAC7E;AAEA,0GAA0G;AAC1G,0GAA0G;AAC1G,IAAMC,0BAA0B;AAEhC,SAAeC,iBAAiBC,IAAgB,EAAEC,OAAiB,EAAEC,IAAiB,EAAEC,MAAsB;;;;;yBACxGF,CAAAA,QAAQG,MAAM,GAAG,CAAA,GAAjBH;;;;oBACF;;wBAAMD,KAAKK,QAAQ,CACjB,wCACAJ,QAAQK,GAAG,CAAC,SAACC;mCAAM;gCAACA;6BAAE;;;;oBAFxB;;;yBAIEL,CAAAA,KAAKE,MAAM,GAAG,CAAA,GAAdF;;;;oBAAiB;;wBAAMF,KAAKK,QAAQ,CAACf,oBAAoBY,KAAKI,GAAG,CAACf;;;oBAAjD;;;oBACrB,6FAA6F;oBAC7F,yCAAyC;oBACzCiB,IAAAA,2BAAgB,EAACR;;;;;;IACnB;;AAEA,0FAA0F;AAC1F,+FAA+F;AAC/F,oGAAoG;AACpG,+FAA+F;AAC/F,qCAAqC;AACrC,SAAeS,WAAWT,IAAgB,EAAEU,KAAe;;;;;oBACzD,IAAIA,MAAMN,MAAM,KAAK,GAAG;;;oBACxB;;wBAAMJ,KAAKW,IAAI,CAACD,MAAMJ,GAAG,CAAC,SAACM;mCAAS,AAAC,sCAAsD,OAAjBC,IAAAA,oBAAU,EAACD,OAAM;2BAAWE,IAAI,CAAC;;;oBAA3G;;;;;;IACF;;AAEA,mGAAmG;AACnG,uLAAuL;AACvL,SAAeC,UAAUf,IAAgB,EAAEgB,KAAa,EAAEC,OAAiB,EAAEC,IAAiB;;YAEpFC,cACFC,UACAC,iBACAC,YAEAC,QACAC,UAEC,2BAAA,mBAAA,gBAAA,WAAA,OAAMC,KACJ,4BAAA,oBAAA,iBAAA,YAAA,QAAMb,MACHc,KACAC;;;;oBAZZ,IAAIT,KAAKd,MAAM,KAAK,GAAG;;;oBACE;;wBAAMwB,IAAAA,mBAAS;;;oBAAhCT,eAAiB,cAAjBA;oBACS;;wBAAMnB,KAAK6B,OAAO,CAAC,AAAC,qBAAsC,OAAlBhB,IAAAA,oBAAU,EAACG,QAAO;;;oBAArEI,WAAW;oBACS;;wBAAMA,SAASU,GAAG;;;oBAAtCT,kBAAkB,AAAE,cAAkDf,GAAG,CAAC,SAACyB;+BAAMA,EAAEnB,IAAI;;oBACvFU,aAAa,IAAIU,IAAIf,QAAQX,GAAG,CAAC,SAACM,MAAMqB;+BAAM;4BAACrB;4BAAMqB;yBAAE;;oBAEvDV,SAAS,AAACvB,KAA0BkC,MAAM;oBAC/B;;wBAAMX,OAAOY,cAAc,CAACnB;;;oBAAvCQ,WAAW;oBACjB,IAAI;wBACG,kCAAA,2BAAA;;4BAAL,IAAK,YAAaN,2BAAb,6BAAA,QAAA,yBAAA,iCAAmB;gCAAbO,MAAN;gCACE,mCAAA,4BAAA;;oCAAL,IAAK,aAAcJ,sCAAd,8BAAA,SAAA,0BAAA,kCAA+B;wCAAzBT,OAAN;wCACGc,MAAMJ,WAAWc,GAAG,CAACxB;wCACrBe,QAAQD,QAAQW,YAAYA,YAAYZ,GAAG,CAACC,IAAI;wCACtD,IAAIA,QAAQW,WAAWb,SAASc,aAAa;6CACxC,IAAIX,UAAU,QAAQA,UAAUU,WAAWb,SAASe,UAAU;6CAC9D,IAAIC,qCAAwB,CAACC,GAAG,CAAC7B,OAAOY,SAASkB,WAAW,CAACf;6CAC7DH,SAASmB,aAAa,CAACxB,aAAaQ;oCAC3C;;oCAPK;oCAAA;;;6CAAA,8BAAA;4CAAA;;;4CAAA;kDAAA;;;;gCAQLH,SAASoB,MAAM;4BACjB;;4BAVK;4BAAA;;;qCAAA,6BAAA;oCAAA;;;oCAAA;0CAAA;;;;wBAWLpB,SAASqB,SAAS;oBACpB,SAAU;wBACRrB,SAASsB,SAAS;oBACpB;;;;;;IACF;;AAEO,IAAMzD,gBAAkC;IAC7C0D,WAAW,SAAXA;eAAiB;;IACjBC,kBAAAA,SAAAA,iBAAiBC,KAAK;QACpB,IAAIA,QAAQnD,yBAAyB;YACnC,MAAM,IAAIoD,oBAAU,CAAC,gBAAgB,AAAC,0BAA+EpD,OAAtDmD,OAAM,kDAAwE,OAAxBnD,yBAAwB;QAC/I;IACF;IACAW,YAAAA;IACAV,kBAAAA;IACAgB,WAAAA;AACF"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Decomposition of the `embed:` featureSignature segment (config/access.ts's featureSignature,
|
|
2
|
+
// features/embed.ts's signature()), for open()'s narrow embed-invalidation routing.
|
|
3
|
+
"use strict";
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
Object.defineProperty(exports, "classifyEmbedChange", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function() {
|
|
10
|
+
return classifyEmbedChange;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
function _array_like_to_array(arr, len) {
|
|
14
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
15
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
16
|
+
return arr2;
|
|
17
|
+
}
|
|
18
|
+
function _array_with_holes(arr) {
|
|
19
|
+
if (Array.isArray(arr)) return arr;
|
|
20
|
+
}
|
|
21
|
+
function _iterable_to_array_limit(arr, i) {
|
|
22
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
23
|
+
if (_i == null) return;
|
|
24
|
+
var _arr = [];
|
|
25
|
+
var _n = true;
|
|
26
|
+
var _d = false;
|
|
27
|
+
var _s, _e;
|
|
28
|
+
try {
|
|
29
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
30
|
+
_arr.push(_s.value);
|
|
31
|
+
if (i && _arr.length === i) break;
|
|
32
|
+
}
|
|
33
|
+
} catch (err) {
|
|
34
|
+
_d = true;
|
|
35
|
+
_e = err;
|
|
36
|
+
} finally{
|
|
37
|
+
try {
|
|
38
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
39
|
+
} finally{
|
|
40
|
+
if (_d) throw _e;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return _arr;
|
|
44
|
+
}
|
|
45
|
+
function _non_iterable_rest() {
|
|
46
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
47
|
+
}
|
|
48
|
+
function _sliced_to_array(arr, i) {
|
|
49
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
50
|
+
}
|
|
51
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
52
|
+
if (!o) return;
|
|
53
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
54
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
55
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
56
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
57
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
58
|
+
}
|
|
59
|
+
// One embed segment's provider/model/chunkVersion, ignoring any trailing `@identity`. `embed:off`
|
|
60
|
+
// and any segment not in that exact shape return null, so the caller falls back to a full rebuild.
|
|
61
|
+
function parseEmbedSegment(sig) {
|
|
62
|
+
var part = sig.split('|').find(function(p) {
|
|
63
|
+
return p.startsWith('embed:');
|
|
64
|
+
});
|
|
65
|
+
if (part === undefined || part === 'embed:off') return null;
|
|
66
|
+
var at = part.indexOf('@');
|
|
67
|
+
var body = at === -1 ? part : part.slice(0, at);
|
|
68
|
+
var match = /^embed:(static|openai|cohere):(.+):(chunk:v\d+(?::\d+)?)$/.exec(body);
|
|
69
|
+
if (!match) return null;
|
|
70
|
+
var _match = _sliced_to_array(match, 4), provider = _match[1], model = _match[2], chunkVersion = _match[3];
|
|
71
|
+
return {
|
|
72
|
+
provider: provider,
|
|
73
|
+
model: model,
|
|
74
|
+
chunkVersion: chunkVersion
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function classifyEmbedChange(before, after) {
|
|
78
|
+
var b = parseEmbedSegment(before);
|
|
79
|
+
var a = parseEmbedSegment(after);
|
|
80
|
+
if (b === null || a === null) return null;
|
|
81
|
+
if (b.chunkVersion !== a.chunkVersion) return 'chunk';
|
|
82
|
+
if (b.provider !== a.provider || b.model !== a.model) return 'model';
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/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 chunkVersion: string;\n}\n\n// One embed segment's provider/model/chunkVersion, ignoring any trailing `@identity`. `embed:off`\n// and any segment not in that exact shape return null, so the caller falls back to a full rebuild.\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 match = /^embed:(static|openai|cohere):(.+):(chunk:v\\d+(?::\\d+)?)$/.exec(body);\n if (!match) return null;\n const [, provider, model, chunkVersion] = match;\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) return 'model';\n return null;\n}\n"],"names":["classifyEmbedChange","parseEmbedSegment","sig","part","split","find","p","startsWith","undefined","at","indexOf","body","slice","match","exec","provider","model","chunkVersion","before","after","b","a"],"mappings":"AAAA,+FAA+F;AAC/F,oFAAoF;;;;;+BAyBpEA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAfhB,kGAAkG;AAClG,mGAAmG;AACnG,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,QAAQ,4DAA4DC,IAAI,CAACH;IAC/E,IAAI,CAACE,OAAO,OAAO;IACnB,IAA0CA,0BAAAA,WAAjCE,WAAiCF,WAAvBG,QAAuBH,WAAhBI,eAAgBJ;IAC1C,OAAO;QAAEE,UAAAA;QAAUC,OAAAA;QAAOC,cAAAA;IAAa;AACzC;AAIO,SAASjB,oBAAoBkB,MAAc,EAAEC,KAAa;IAC/D,IAAMC,IAAInB,kBAAkBiB;IAC5B,IAAMG,IAAIpB,kBAAkBkB;IAC5B,IAAIC,MAAM,QAAQC,MAAM,MAAM,OAAO;IACrC,IAAID,EAAEH,YAAY,KAAKI,EAAEJ,YAAY,EAAE,OAAO;IAC9C,IAAIG,EAAEL,QAAQ,KAAKM,EAAEN,QAAQ,IAAIK,EAAEJ,KAAK,KAAKK,EAAEL,KAAK,EAAE,OAAO;IAC7D,OAAO;AACT"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FeatureName } from '../config/index.js';
|
|
2
|
+
export declare const NARROW_FEATURE_TABLE: Readonly<Record<string, string>>;
|
|
3
|
+
export interface FeatureToggle {
|
|
4
|
+
name: FeatureName;
|
|
5
|
+
turnedOn: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function isFeatureOnlyChange(changedKeys: ReadonlySet<string>): boolean;
|
|
8
|
+
export declare function classifyFeatureToggles(before: string, after: string, changedKeys: ReadonlySet<string>): FeatureToggle[] | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FeatureName } from '../config/index.js';
|
|
2
|
+
export declare const NARROW_FEATURE_TABLE: Readonly<Record<string, string>>;
|
|
3
|
+
export interface FeatureToggle {
|
|
4
|
+
name: FeatureName;
|
|
5
|
+
turnedOn: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function isFeatureOnlyChange(changedKeys: ReadonlySet<string>): boolean;
|
|
8
|
+
export declare function classifyFeatureToggles(before: string, after: string, changedKeys: ReadonlySet<string>): FeatureToggle[] | null;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get NARROW_FEATURE_TABLE () {
|
|
13
|
+
return NARROW_FEATURE_TABLE;
|
|
14
|
+
},
|
|
15
|
+
get classifyFeatureToggles () {
|
|
16
|
+
return classifyFeatureToggles;
|
|
17
|
+
},
|
|
18
|
+
get isFeatureOnlyChange () {
|
|
19
|
+
return isFeatureOnlyChange;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
function _array_like_to_array(arr, len) {
|
|
23
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
24
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
25
|
+
return arr2;
|
|
26
|
+
}
|
|
27
|
+
function _array_without_holes(arr) {
|
|
28
|
+
if (Array.isArray(arr)) return _array_like_to_array(arr);
|
|
29
|
+
}
|
|
30
|
+
function _iterable_to_array(iter) {
|
|
31
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
|
|
32
|
+
return Array.from(iter);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function _non_iterable_spread() {
|
|
36
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
37
|
+
}
|
|
38
|
+
function _to_consumable_array(arr) {
|
|
39
|
+
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
|
|
40
|
+
}
|
|
41
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
42
|
+
if (!o) return;
|
|
43
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
44
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
45
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
46
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
47
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
48
|
+
}
|
|
49
|
+
var NARROW_FEATURE_TABLE = {
|
|
50
|
+
tags: 'tags',
|
|
51
|
+
sections: 'sections',
|
|
52
|
+
links: 'links'
|
|
53
|
+
};
|
|
54
|
+
// links feeds rank's afterReconcile pass, so a links toggle always co-changes the `feature:rank`
|
|
55
|
+
// segment too (featureEnabled's dependency); both are narrow-supported and builder.ts applies
|
|
56
|
+
// them together. A changed set naming any other feature falls through to the existing full clear.
|
|
57
|
+
var NARROW_FEATURE_NAMES = new Set(_to_consumable_array(Object.keys(NARROW_FEATURE_TABLE)).concat([
|
|
58
|
+
'rank'
|
|
59
|
+
]));
|
|
60
|
+
function isFeatureOnlyChange(changedKeys) {
|
|
61
|
+
return changedKeys.size > 0 && _to_consumable_array(changedKeys).every(function(key) {
|
|
62
|
+
return key.startsWith('feature:') && NARROW_FEATURE_NAMES.has(key.slice('feature:'.length));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// One feature segment's old on/off, read back out of a stored `feature:<name>:on|off` segment.
|
|
66
|
+
// Anything not in that exact shape returns null so the caller falls back to a full rebuild.
|
|
67
|
+
function parseOnOff(sig, name) {
|
|
68
|
+
var part = sig.split('|').find(function(p) {
|
|
69
|
+
return p.startsWith("feature:".concat(name, ":"));
|
|
70
|
+
});
|
|
71
|
+
if (part === undefined) return null;
|
|
72
|
+
var fields = part.split(':');
|
|
73
|
+
if (fields.length !== 3 || fields[2] !== 'on' && fields[2] !== 'off') return null;
|
|
74
|
+
return fields[2] === 'on';
|
|
75
|
+
}
|
|
76
|
+
function classifyFeatureToggles(before, after, changedKeys) {
|
|
77
|
+
var toggles = [];
|
|
78
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
79
|
+
try {
|
|
80
|
+
for(var _iterator = changedKeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
81
|
+
var key = _step.value;
|
|
82
|
+
var name = key.slice('feature:'.length);
|
|
83
|
+
var wasOn = parseOnOff(before, name);
|
|
84
|
+
var isOn = parseOnOff(after, name);
|
|
85
|
+
if (wasOn === null || isOn === null || wasOn === isOn) return null;
|
|
86
|
+
toggles.push({
|
|
87
|
+
name: name,
|
|
88
|
+
turnedOn: isOn
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
} catch (err) {
|
|
92
|
+
_didIteratorError = true;
|
|
93
|
+
_iteratorError = err;
|
|
94
|
+
} finally{
|
|
95
|
+
try {
|
|
96
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
97
|
+
_iterator.return();
|
|
98
|
+
}
|
|
99
|
+
} finally{
|
|
100
|
+
if (_didIteratorError) {
|
|
101
|
+
throw _iteratorError;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return toggles;
|
|
106
|
+
}
|
|
107
|
+
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|