sensemaking 0.18.3 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -4
- package/dist/cjs/chunk/group.js +10 -23
- package/dist/cjs/chunk/group.js.map +1 -1
- package/dist/cjs/chunk/parse.js +2 -5
- package/dist/cjs/chunk/parse.js.map +1 -1
- package/dist/cjs/cli/index.js.map +1 -1
- package/dist/cjs/cli/shared.js +6 -10
- package/dist/cjs/cli/shared.js.map +1 -1
- package/dist/cjs/cli/status.js +44 -10
- package/dist/cjs/cli/status.js.map +1 -1
- package/dist/cjs/cli.js +2 -8
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/commands/map.js +1 -3
- package/dist/cjs/commands/map.js.map +1 -1
- package/dist/cjs/commands/peek.js.map +1 -1
- package/dist/cjs/commands/related.js +3 -5
- package/dist/cjs/commands/related.js.map +1 -1
- package/dist/cjs/commands/scope.js.map +1 -1
- package/dist/cjs/commands/search.js +6 -8
- package/dist/cjs/commands/search.js.map +1 -1
- package/dist/cjs/commands/signals.js.map +1 -1
- 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 +3 -0
- package/dist/cjs/config/index.js.map +1 -1
- package/dist/cjs/config/load.js +10 -24
- package/dist/cjs/config/load.js.map +1 -1
- package/dist/cjs/config/resolve.js.map +1 -1
- package/dist/cjs/config/signals.js +2 -3
- package/dist/cjs/config/signals.js.map +1 -1
- package/dist/cjs/config/types.d.cts +2 -1
- package/dist/cjs/config/types.d.ts +2 -1
- package/dist/cjs/config/types.js +8 -0
- package/dist/cjs/config/types.js.map +1 -1
- package/dist/cjs/config/validate.d.cts +1 -1
- package/dist/cjs/config/validate.d.ts +1 -1
- package/dist/cjs/config/validate.js +9 -10
- package/dist/cjs/config/validate.js.map +1 -1
- package/dist/cjs/embed/cohere.js +2 -2
- package/dist/cjs/embed/cohere.js.map +1 -1
- package/dist/cjs/embed/distribution.js +3 -3
- package/dist/cjs/embed/distribution.js.map +1 -1
- package/dist/cjs/embed/handoff.d.cts +3 -0
- package/dist/cjs/embed/handoff.d.ts +3 -0
- package/dist/cjs/embed/handoff.js +39 -0
- package/dist/cjs/embed/handoff.js.map +1 -0
- package/dist/cjs/embed/identity.d.cts +11 -10
- package/dist/cjs/embed/identity.d.ts +11 -10
- package/dist/cjs/embed/identity.js +30 -15
- package/dist/cjs/embed/identity.js.map +1 -1
- package/dist/cjs/embed/langfit.js +2 -3
- package/dist/cjs/embed/langfit.js.map +1 -1
- package/dist/cjs/embed/languages.js +2 -4
- package/dist/cjs/embed/languages.js.map +1 -1
- package/dist/cjs/embed/openai.js +2 -2
- package/dist/cjs/embed/openai.js.map +1 -1
- package/dist/cjs/embed/query.js +58 -20
- package/dist/cjs/embed/query.js.map +1 -1
- package/dist/cjs/embed/registry.js +1 -2
- package/dist/cjs/embed/registry.js.map +1 -1
- package/dist/cjs/embed/static.d.cts +1 -1
- package/dist/cjs/embed/static.d.ts +1 -1
- package/dist/cjs/embed/static.js +8 -10
- package/dist/cjs/embed/static.js.map +1 -1
- package/dist/cjs/embed/store.d.cts +2 -2
- package/dist/cjs/embed/store.d.ts +2 -2
- package/dist/cjs/embed/store.js +48 -34
- package/dist/cjs/embed/store.js.map +1 -1
- package/dist/cjs/embed/types.js +1 -3
- package/dist/cjs/embed/types.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/embed.js +19 -17
- package/dist/cjs/features/embed.js.map +1 -1
- package/dist/cjs/features/fences.js +5 -10
- package/dist/cjs/features/fences.js.map +1 -1
- package/dist/cjs/features/links.js +20 -37
- package/dist/cjs/features/links.js.map +1 -1
- package/dist/cjs/features/sections.js +21 -19
- package/dist/cjs/features/sections.js.map +1 -1
- package/dist/cjs/features/tags.js +5 -8
- package/dist/cjs/features/tags.js.map +1 -1
- package/dist/cjs/graph/traverse.js +1 -2
- package/dist/cjs/graph/traverse.js.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/index.d.ts +1 -1
- package/dist/cjs/index.js +3 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/output/column-hint.js +3 -6
- package/dist/cjs/output/column-hint.js.map +1 -1
- package/dist/cjs/output/output.js +7 -14
- package/dist/cjs/output/output.js.map +1 -1
- package/dist/cjs/output/search-error.js +2 -5
- package/dist/cjs/output/search-error.js.map +1 -1
- package/dist/cjs/scan/frontmatter.d.cts +1 -0
- package/dist/cjs/scan/frontmatter.d.ts +1 -0
- package/dist/cjs/scan/frontmatter.js +14 -18
- package/dist/cjs/scan/frontmatter.js.map +1 -1
- package/dist/cjs/scan/list.js +2 -3
- package/dist/cjs/scan/list.js.map +1 -1
- package/dist/cjs/scan/reparse.js +12 -26
- package/dist/cjs/scan/reparse.js.map +1 -1
- package/dist/cjs/scan/worker-error.js.map +1 -1
- package/dist/cjs/store/cache.d.cts +2 -0
- package/dist/cjs/store/cache.d.ts +2 -0
- package/dist/cjs/store/cache.js +20 -0
- package/dist/cjs/store/cache.js.map +1 -0
- package/dist/cjs/store/duckdb/batch.js +4 -16
- package/dist/cjs/store/duckdb/batch.js.map +1 -1
- package/dist/cjs/store/duckdb/connection.js +8 -20
- package/dist/cjs/store/duckdb/connection.js.map +1 -1
- package/dist/cjs/store/duckdb/fieldStats.js +2 -8
- package/dist/cjs/store/duckdb/fieldStats.js.map +1 -1
- package/dist/cjs/store/duckdb/lexical.js +21 -29
- package/dist/cjs/store/duckdb/lexical.js.map +1 -1
- package/dist/cjs/store/duckdb/native.js.map +1 -1
- package/dist/cjs/store/duckdb/open.js +12 -13
- package/dist/cjs/store/duckdb/open.js.map +1 -1
- package/dist/cjs/store/duckdb/reconcile.js +4 -11
- package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
- package/dist/cjs/store/duckdb/sql-functions.js +2 -4
- package/dist/cjs/store/duckdb/sql-functions.js.map +1 -1
- package/dist/cjs/store/duckdb/store.js +2 -3
- package/dist/cjs/store/duckdb/store.js.map +1 -1
- package/dist/cjs/store/duckdb/vectors.js +8 -18
- package/dist/cjs/store/duckdb/vectors.js.map +1 -1
- package/dist/cjs/store/index.d.cts +3 -2
- package/dist/cjs/store/index.d.ts +3 -2
- package/dist/cjs/store/index.js +7 -8
- package/dist/cjs/store/index.js.map +1 -1
- package/dist/cjs/store/native.js +6 -16
- package/dist/cjs/store/native.js.map +1 -1
- package/dist/cjs/store/sql-functions.js.map +1 -1
- package/dist/cjs/store/sqlite/connection.js +4 -8
- package/dist/cjs/store/sqlite/connection.js.map +1 -1
- package/dist/cjs/store/sqlite/fieldStats.js.map +1 -1
- package/dist/cjs/store/sqlite/lexical.js +3 -5
- 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 +22 -40
- package/dist/cjs/store/sqlite/open.js.map +1 -1
- package/dist/cjs/store/sqlite/reconcile.js +2 -3
- package/dist/cjs/store/sqlite/reconcile.js.map +1 -1
- package/dist/cjs/store/sqlite/sql-functions.js +2 -4
- package/dist/cjs/store/sqlite/sql-functions.js.map +1 -1
- package/dist/cjs/store/sqlite/store.js.map +1 -1
- package/dist/cjs/store/transaction.js +1 -3
- package/dist/cjs/store/transaction.js.map +1 -1
- package/dist/cjs/store/turso/connection.js +2 -6
- package/dist/cjs/store/turso/connection.js.map +1 -1
- package/dist/cjs/store/turso/fieldStats.js.map +1 -1
- package/dist/cjs/store/turso/lexical.d.cts +2 -0
- package/dist/cjs/store/turso/lexical.d.ts +2 -0
- package/dist/cjs/store/turso/lexical.js +347 -0
- package/dist/cjs/store/turso/lexical.js.map +1 -0
- package/dist/cjs/store/turso/native.js.map +1 -1
- package/dist/cjs/store/turso/open.d.cts +1 -1
- package/dist/cjs/store/turso/open.d.ts +1 -1
- package/dist/cjs/store/turso/open.js +81 -54
- package/dist/cjs/store/turso/open.js.map +1 -1
- package/dist/cjs/store/turso/reconcile.js +22 -22
- package/dist/cjs/store/turso/reconcile.js.map +1 -1
- package/dist/cjs/store/turso/store.js +18 -41
- package/dist/cjs/store/turso/store.js.map +1 -1
- package/dist/cjs/store/turso/vectors.d.cts +8 -0
- package/dist/cjs/store/turso/vectors.d.ts +8 -0
- package/dist/cjs/store/turso/vectors.js +435 -0
- package/dist/cjs/store/turso/vectors.js.map +1 -0
- package/dist/cjs/store/types.js +2 -3
- package/dist/cjs/store/types.js.map +1 -1
- package/dist/cjs/store/vectors.js.map +1 -1
- package/dist/cjs/text/segment.d.cts +1 -0
- package/dist/cjs/text/segment.d.ts +1 -0
- package/dist/cjs/text/segment.js +10 -14
- package/dist/cjs/text/segment.js.map +1 -1
- package/dist/cjs/watch.js +2 -5
- package/dist/cjs/watch.js.map +1 -1
- package/dist/cjs/workers/parse.js.map +1 -1
- package/dist/esm/chunk/group.js +10 -23
- package/dist/esm/chunk/group.js.map +1 -1
- package/dist/esm/chunk/parse.js +4 -8
- package/dist/esm/chunk/parse.js.map +1 -1
- package/dist/esm/cli/index.js +3 -5
- package/dist/esm/cli/index.js.map +1 -1
- package/dist/esm/cli/shared.js +12 -22
- package/dist/esm/cli/shared.js.map +1 -1
- package/dist/esm/cli/status.js +43 -9
- package/dist/esm/cli/status.js.map +1 -1
- package/dist/esm/cli.js +2 -8
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/commands/map.js +1 -3
- package/dist/esm/commands/map.js.map +1 -1
- package/dist/esm/commands/peek.js.map +1 -1
- package/dist/esm/commands/related.js +3 -5
- package/dist/esm/commands/related.js.map +1 -1
- package/dist/esm/commands/scope.js +3 -5
- package/dist/esm/commands/scope.js.map +1 -1
- package/dist/esm/commands/search.js +10 -16
- package/dist/esm/commands/search.js.map +1 -1
- package/dist/esm/commands/signals.js +3 -7
- package/dist/esm/commands/signals.js.map +1 -1
- package/dist/esm/config/access.js +8 -13
- 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/load.js +10 -24
- package/dist/esm/config/load.js.map +1 -1
- package/dist/esm/config/resolve.js +2 -3
- package/dist/esm/config/resolve.js.map +1 -1
- package/dist/esm/config/signals.js +3 -5
- package/dist/esm/config/signals.js.map +1 -1
- package/dist/esm/config/types.d.ts +2 -1
- package/dist/esm/config/types.js +8 -2
- package/dist/esm/config/types.js.map +1 -1
- package/dist/esm/config/validate.d.ts +1 -1
- package/dist/esm/config/validate.js +7 -10
- package/dist/esm/config/validate.js.map +1 -1
- package/dist/esm/embed/cohere.js +2 -2
- package/dist/esm/embed/cohere.js.map +1 -1
- package/dist/esm/embed/distribution.js +1 -1
- package/dist/esm/embed/distribution.js.map +1 -1
- package/dist/esm/embed/handoff.d.ts +3 -0
- package/dist/esm/embed/handoff.js +21 -0
- package/dist/esm/embed/handoff.js.map +1 -0
- package/dist/esm/embed/identity.d.ts +11 -10
- package/dist/esm/embed/identity.js +29 -26
- package/dist/esm/embed/identity.js.map +1 -1
- package/dist/esm/embed/langfit.js +2 -3
- package/dist/esm/embed/langfit.js.map +1 -1
- package/dist/esm/embed/languages.js +2 -4
- package/dist/esm/embed/languages.js.map +1 -1
- package/dist/esm/embed/openai.js +2 -2
- package/dist/esm/embed/openai.js.map +1 -1
- package/dist/esm/embed/query.js +21 -6
- package/dist/esm/embed/query.js.map +1 -1
- package/dist/esm/embed/registry.js +1 -2
- package/dist/esm/embed/registry.js.map +1 -1
- package/dist/esm/embed/static.d.ts +1 -1
- package/dist/esm/embed/static.js +8 -10
- package/dist/esm/embed/static.js.map +1 -1
- package/dist/esm/embed/store.d.ts +2 -2
- package/dist/esm/embed/store.js +28 -23
- package/dist/esm/embed/store.js.map +1 -1
- package/dist/esm/embed/types.js +1 -3
- package/dist/esm/embed/types.js.map +1 -1
- package/dist/esm/errors.d.ts +1 -1
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/features/embed.js +16 -16
- package/dist/esm/features/embed.js.map +1 -1
- package/dist/esm/features/fences.js +9 -19
- package/dist/esm/features/fences.js.map +1 -1
- package/dist/esm/features/links.js +24 -49
- package/dist/esm/features/links.js.map +1 -1
- package/dist/esm/features/sections.js +20 -20
- package/dist/esm/features/sections.js.map +1 -1
- package/dist/esm/features/tags.js +5 -8
- package/dist/esm/features/tags.js.map +1 -1
- package/dist/esm/features/types.js.map +1 -1
- package/dist/esm/graph/traverse.js +1 -2
- package/dist/esm/graph/traverse.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/output/column-hint.js +3 -6
- package/dist/esm/output/column-hint.js.map +1 -1
- package/dist/esm/output/output.js +9 -20
- package/dist/esm/output/output.js.map +1 -1
- package/dist/esm/output/search-error.js +2 -5
- package/dist/esm/output/search-error.js.map +1 -1
- package/dist/esm/scan/frontmatter.d.ts +1 -0
- package/dist/esm/scan/frontmatter.js +13 -18
- package/dist/esm/scan/frontmatter.js.map +1 -1
- package/dist/esm/scan/list.js +2 -3
- package/dist/esm/scan/list.js.map +1 -1
- package/dist/esm/scan/reparse.js +16 -34
- package/dist/esm/scan/reparse.js.map +1 -1
- package/dist/esm/scan/worker-error.js.map +1 -1
- package/dist/esm/store/cache.d.ts +2 -0
- package/dist/esm/store/cache.js +11 -0
- package/dist/esm/store/cache.js.map +1 -0
- package/dist/esm/store/duckdb/batch.js +4 -16
- package/dist/esm/store/duckdb/batch.js.map +1 -1
- package/dist/esm/store/duckdb/connection.js +8 -20
- package/dist/esm/store/duckdb/connection.js.map +1 -1
- package/dist/esm/store/duckdb/fieldStats.js +4 -12
- package/dist/esm/store/duckdb/fieldStats.js.map +1 -1
- package/dist/esm/store/duckdb/lexical.js +29 -36
- package/dist/esm/store/duckdb/lexical.js.map +1 -1
- package/dist/esm/store/duckdb/native.js +2 -7
- package/dist/esm/store/duckdb/native.js.map +1 -1
- package/dist/esm/store/duckdb/open.js +16 -23
- package/dist/esm/store/duckdb/open.js.map +1 -1
- package/dist/esm/store/duckdb/reconcile.js +4 -11
- package/dist/esm/store/duckdb/reconcile.js.map +1 -1
- package/dist/esm/store/duckdb/sql-functions.js +4 -9
- package/dist/esm/store/duckdb/sql-functions.js.map +1 -1
- package/dist/esm/store/duckdb/store.js +6 -14
- package/dist/esm/store/duckdb/store.js.map +1 -1
- package/dist/esm/store/duckdb/vectors.js +14 -31
- package/dist/esm/store/duckdb/vectors.js.map +1 -1
- package/dist/esm/store/index.d.ts +3 -2
- package/dist/esm/store/index.js +5 -6
- package/dist/esm/store/index.js.map +1 -1
- package/dist/esm/store/native.js +10 -25
- package/dist/esm/store/native.js.map +1 -1
- package/dist/esm/store/sql-functions.js +3 -5
- package/dist/esm/store/sql-functions.js.map +1 -1
- package/dist/esm/store/sqlite/connection.js +4 -8
- package/dist/esm/store/sqlite/connection.js.map +1 -1
- package/dist/esm/store/sqlite/fieldStats.js +2 -6
- package/dist/esm/store/sqlite/fieldStats.js.map +1 -1
- package/dist/esm/store/sqlite/lexical.js +5 -9
- 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 +21 -41
- package/dist/esm/store/sqlite/open.js.map +1 -1
- package/dist/esm/store/sqlite/reconcile.js +6 -13
- package/dist/esm/store/sqlite/reconcile.js.map +1 -1
- package/dist/esm/store/sqlite/sql-functions.js +2 -4
- package/dist/esm/store/sqlite/sql-functions.js.map +1 -1
- package/dist/esm/store/sqlite/store.js +1 -2
- package/dist/esm/store/sqlite/store.js.map +1 -1
- package/dist/esm/store/transaction.js +2 -5
- package/dist/esm/store/transaction.js.map +1 -1
- package/dist/esm/store/turso/connection.js +2 -6
- package/dist/esm/store/turso/connection.js.map +1 -1
- package/dist/esm/store/turso/fieldStats.js +2 -5
- package/dist/esm/store/turso/fieldStats.js.map +1 -1
- package/dist/esm/store/turso/lexical.d.ts +2 -0
- package/dist/esm/store/turso/lexical.js +128 -0
- package/dist/esm/store/turso/lexical.js.map +1 -0
- package/dist/esm/store/turso/native.js +2 -7
- package/dist/esm/store/turso/native.js.map +1 -1
- package/dist/esm/store/turso/open.d.ts +1 -1
- package/dist/esm/store/turso/open.js +36 -29
- package/dist/esm/store/turso/open.js.map +1 -1
- package/dist/esm/store/turso/reconcile.js +22 -22
- package/dist/esm/store/turso/reconcile.js.map +1 -1
- package/dist/esm/store/turso/store.js +17 -28
- package/dist/esm/store/turso/store.js.map +1 -1
- package/dist/esm/store/turso/vectors.d.ts +8 -0
- package/dist/esm/store/turso/vectors.js +98 -0
- package/dist/esm/store/turso/vectors.js.map +1 -0
- package/dist/esm/store/types.js +2 -3
- package/dist/esm/store/types.js.map +1 -1
- package/dist/esm/store/vectors.js +2 -3
- package/dist/esm/store/vectors.js.map +1 -1
- package/dist/esm/text/segment.d.ts +1 -0
- package/dist/esm/text/segment.js +13 -21
- package/dist/esm/text/segment.js.map +1 -1
- package/dist/esm/watch.js +2 -5
- package/dist/esm/watch.js.map +1 -1
- package/dist/esm/workers/parse.js.map +1 -1
- package/package.json +3 -1
- package/schema.json +2 -2
- package/skills/sense/SKILL.md +2 -2
- package/skills/sense-setup/SKILL.md +3 -3
- package/dist/cjs/store/meta.d.cts +0 -3
- package/dist/cjs/store/meta.d.ts +0 -3
- package/dist/cjs/store/meta.js +0 -215
- package/dist/cjs/store/meta.js.map +0 -1
- package/dist/esm/store/meta.d.ts +0 -3
- package/dist/esm/store/meta.js +0 -17
- package/dist/esm/store/meta.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/config/validate.ts"],"sourcesContent":["import { SenseError } from '../errors.ts';\nimport { SIGNAL_NAMES, SIGNAL_PREREQUISITES, type SignalName } from './signals.ts';\nimport type { Config } from './types.ts';\n\n// Shape check for hand-edited files, so a typo names itself instead of surfacing as a\n// TypeError. Unknown top-level keys warn (forward compat); unknown keys inside a block error.\nconst KNOWN_KEYS = new Set(['$schema', 'version', 'presets', 'features', 'embed', 'content', 'store', 'queries']);\nconst KNOWN_PRESET_KEYS = new Set(['include', 'exclude', 'k', 'signals', 'where']);\nconst KNOWN_FEATURE_KEYS = new Set(['links', 'sections', 'tags', 'rank']);\n// Exported so a docs test can assert every key here has a schema.json property -- one source\n// of truth for what the embed block accepts, checked against the other for drift.\nexport const KNOWN_EMBED_KEYS = new Set(['model', 'provider', 'url', 'key', 'languages', 'chunkTokens']);\nconst KNOWN_CONTENT_KEYS = new Set(['tokenize']);\nconst SAVED_SEARCH_KEYS = new Set(['search', 'preset', 'include', 'exclude', 'where', 'k']);\n\nexport function unknownConfigKeys(cfg: Record<string, unknown>): string[] {\n return Object.keys(cfg).filter((k) => !KNOWN_KEYS.has(k));\n}\n\nfunction isNonEmptyStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.length > 0 && value.every((g) => typeof g === 'string' && g.length > 0);\n}\n\n// Pre-v3 shape check, just enough for migrateConfig to run safely (it reads scan.include\n// directly). The full v3 shape is checked by validateConfig once migration has produced it.\nexport function validateLegacyScan(parsed: unknown, configPath: string): void {\n const cfg = typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) ? (parsed as Record<string, unknown>) : null;\n const scan = cfg?.scan as { include?: unknown } | undefined;\n if (!cfg || !scan || !isNonEmptyStringArray(scan.include)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: scan.include must be a non-empty array of glob strings`);\n }\n}\n\n// Only the shape is checked here. Whether the linked SQLite accepts the tokenizer is settled\n// by probing it in store/sqlite/open.ts, so this never has to carry a table of which version added what.\nfunction validateContentBlock(value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: content must be an object of { tokenize?: string }`);\n }\n const block = value as Record<string, unknown>;\n const unknown = Object.keys(block).filter((k) => !KNOWN_CONTENT_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: content has unknown key(s) ${unknown.join(', ')}; content takes tokenize`);\n }\n if (block.tokenize !== undefined && (typeof block.tokenize !== 'string' || block.tokenize.trim() === '')) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: content.tokenize must be a non-empty string, e.g. \"trigram\" or \"unicode61 tokenchars '-_'\"`);\n }\n}\n\n// \"turso\" is implemented but not offered: it has no lexical or vector search yet, so a tree\n// naming it could not search. Registered in the store registry and exercised by the parity\n// suite; re-add here and in schema.json's enum when those land.\nfunction validateStoreKey(value: unknown, configPath: string): void {\n if (value !== 'sqlite' && value !== 'duckdb') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: store must be \"sqlite\" or \"duckdb\"`);\n }\n}\n\nfunction validateFeaturesBlock(value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features must be an object of name -> boolean`);\n }\n const block = value as Record<string, unknown>;\n const unknown = Object.keys(block).filter((k) => !KNOWN_FEATURE_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features has unknown key(s) ${unknown.join(', ')}; embed is not a features key -- see the top-level \"embed\" block`);\n }\n for (const [name, v] of Object.entries(block)) {\n if (typeof v !== 'boolean') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features.${name} must be a boolean`);\n }\n }\n}\n\nfunction validateEmbedBlock(value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed must be an object of { model?, provider?: \"static\"|\"openai\"|\"cohere\", url?, key? }`);\n }\n const embed = value as Record<string, unknown>;\n const unknown = Object.keys(embed).filter((k) => !KNOWN_EMBED_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed has unknown key(s) ${unknown.join(', ')}`);\n }\n if (embed.model !== undefined && typeof embed.model !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.model must be a string`);\n }\n // The block exists to name a model; provider settings without one would read as \"vectors\n // configured\" while embedding stays off, which is the ambiguity v4 removed.\n if (embed.model === undefined || embed.model === '') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.model is required when the \"embed\" block is present (it is what turns vectors on); remove the block to index without vectors`);\n }\n if (embed.provider !== undefined && embed.provider !== 'static' && embed.provider !== 'openai' && embed.provider !== 'cohere') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.provider must be \"static\", \"openai\", or \"cohere\"`);\n }\n if (embed.url !== undefined && typeof embed.url !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.url must be a string`);\n }\n if (embed.key !== undefined && typeof embed.key !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.key must be a string`);\n }\n // openai has no default host, so a missing url would otherwise only surface at the first\n // vector search; a config error belongs at config time.\n if (embed.provider === 'openai' && (embed.url === undefined || embed.url === '')) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.provider \"openai\" requires embed.url (e.g. \"http://localhost:11434/v1\" for Ollama)`);\n }\n if (embed.languages !== undefined && (!Array.isArray(embed.languages) || embed.languages.length === 0 || embed.languages.some((l) => typeof l !== 'string' || l === ''))) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.languages must be a non-empty array of language tags (e.g. [\"en\", \"zh\"])`);\n }\n if (embed.chunkTokens !== undefined && (typeof embed.chunkTokens !== 'number' || !Number.isInteger(embed.chunkTokens) || embed.chunkTokens <= 0)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.chunkTokens must be a positive integer`);\n }\n}\n\nfunction isSignalName(value: unknown): value is SignalName {\n return typeof value === 'string' && (SIGNAL_NAMES as readonly string[]).includes(value);\n}\n\nfunction isSignalWeight(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0;\n}\n\n// Shape (an object of signal name -> weight) plus the one cross-signal prerequisite that\n// doesn't need the top-level embed block: links is seeded by word-match rows, so declaring it\n// without words is always empty.\nfunction validatePresetSignals(name: string, value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value) || Object.keys(value).length === 0) {\n throw new SenseError(\n 'CONFIG_INVALID',\n `${configPath}: presets.${name}.signals must be a non-empty object of signal name -> weight (a finite number > 0), naming ${SIGNAL_NAMES.join(', ')} -- a preset that searches nothing is a mistake; name at least \"words\", or omit \"signals\" to use every signal whose prerequisites hold at weight 1`\n );\n }\n const entries = Object.entries(value as Record<string, unknown>);\n const unknown = entries.filter(([k]) => !isSignalName(k)).map(([k]) => k);\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.signals names unknown signal(s) ${unknown.join(', ')}; valid signals are ${SIGNAL_NAMES.join(', ')}`);\n }\n for (const [signal, weight] of entries) {\n if (!isSignalWeight(weight)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.signals.${signal} must be a finite number > 0`);\n }\n }\n const names = new Set(entries.map(([k]) => k));\n for (const [signal, requires] of Object.entries(SIGNAL_PREREQUISITES) as Array<[SignalName, SignalName]>) {\n if (names.has(signal) && !names.has(requires)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.signals has \"${signal}\" without \"${requires}\"; add \"${requires}\" to presets.${name}.signals, or drop \"${signal}\"`);\n }\n }\n}\n\nfunction validatePreset(name: string, value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name} must be an object`);\n }\n const preset = value as Record<string, unknown>;\n const unknown = Object.keys(preset).filter((k) => !KNOWN_PRESET_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name} has unknown key(s) ${unknown.join(', ')}; a preset takes include, exclude, k, signals, where`);\n }\n if (!isNonEmptyStringArray(preset.include)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.include must be a non-empty array of glob strings`);\n }\n if (preset.exclude !== undefined && !isNonEmptyStringArray(preset.exclude)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.exclude must be a non-empty array of glob strings`);\n }\n if (preset.signals !== undefined) validatePresetSignals(name, preset.signals, configPath);\n if (preset.k !== undefined && (typeof preset.k !== 'number' || !Number.isInteger(preset.k) || preset.k <= 0)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.k must be a positive integer`);\n }\n if (preset.where !== undefined && typeof preset.where !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.where must be a SQL condition string`);\n }\n}\n\n// A queries.<name> entry: { sql } or a saved search { search, preset?, include?, exclude?, where?, k? }.\nfunction validateSavedQuery(name: string, value: unknown, configPath: string): void {\n // A bare string used to mean SQL. It now fails rather than being inferred: an entry says\n // which of the two verbs it runs, the same choice the CLI makes explicit.\n if (typeof value === 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} must say which verb it runs: { \"sql\": ${JSON.stringify(value.length > 40 ? `${value.slice(0, 37)}...` : value)} } to run it as SQL, or { \"search\": \"...\" } for a ranked search`);\n }\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} must be { sql } or { search, preset?, include?, exclude?, where?, k? }`);\n }\n const entry = value as Record<string, unknown>;\n if ('sql' in entry) {\n const unknown = Object.keys(entry).filter((k) => k !== 'sql');\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} has unknown key(s) ${unknown.join(', ')}; a { sql } query takes only sql`);\n }\n if (typeof entry.sql !== 'string' || entry.sql.trim() === '') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.sql must be a non-empty string`);\n }\n return;\n }\n if ('search' in entry) {\n const unknown = Object.keys(entry).filter((k) => !SAVED_SEARCH_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} has unknown key(s) ${unknown.join(', ')}; a saved search takes search, preset, include, exclude, where, k`);\n }\n // A saved entry saves a question; a scope without a question is just flags.\n if (typeof entry.search !== 'string' || entry.search.trim() === '') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.search must be non-empty text`);\n }\n if (entry.preset !== undefined && (typeof entry.preset !== 'string' || entry.preset.length === 0)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.preset must be a preset name`);\n }\n if (entry.include !== undefined && !isNonEmptyStringArray(entry.include)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.include must be a non-empty array of glob strings`);\n }\n if (entry.exclude !== undefined && !isNonEmptyStringArray(entry.exclude)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.exclude must be a non-empty array of glob strings`);\n }\n if (entry.where !== undefined && typeof entry.where !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.where must be a SQL condition string`);\n }\n if (entry.k !== undefined && (typeof entry.k !== 'number' || !Number.isInteger(entry.k) || entry.k <= 0)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.k must be a positive integer`);\n }\n return;\n }\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} must be { sql } or { search, preset?, include?, exclude?, where?, k? }`);\n}\n\nexport function validateConfig(parsed: unknown, configPath: string): Config {\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: config must be a JSON object`);\n }\n const cfg = parsed as Record<string, unknown>;\n\n // `checks` is rejected by name, not warned: silence would hide that assertions are gone.\n if (cfg.checks !== undefined) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: checks was removed in v3 -- sense check no longer asserts on saved queries; a returned row set is the reader's judgment`);\n }\n\n const presets = cfg.presets as Record<string, unknown> | undefined;\n if (!presets || typeof presets !== 'object' || Array.isArray(presets) || Object.keys(presets).length === 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets must be a non-empty object of preset name -> { include, exclude?, k?, signals?, where? }`);\n }\n for (const [name, value] of Object.entries(presets)) {\n validatePreset(name, value, configPath);\n }\n if (presets.default === undefined) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets must include a \"default\" preset`);\n }\n\n if (cfg.queries === undefined) cfg.queries = {};\n if (typeof cfg.queries !== 'object' || cfg.queries === null || Array.isArray(cfg.queries)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries must be an object of name -> { sql } or { search }`);\n }\n const queries = cfg.queries as Record<string, unknown>;\n for (const [name, value] of Object.entries(queries)) {\n validateSavedQuery(name, value, configPath);\n }\n\n if (cfg.features !== undefined) {\n validateFeaturesBlock(cfg.features, configPath);\n }\n if (cfg.embed !== undefined) {\n validateEmbedBlock(cfg.embed, configPath);\n }\n if (cfg.content !== undefined) {\n validateContentBlock(cfg.content, configPath);\n }\n if (cfg.store !== undefined) {\n validateStoreKey(cfg.store, configPath);\n }\n\n // vectors' prerequisite is a named model, checked here once embed is known valid (or absent).\n if (cfg.embed === undefined) {\n for (const [name, value] of Object.entries(presets)) {\n const signals = (value as Record<string, unknown>).signals as Record<string, unknown> | undefined;\n if (signals && 'vectors' in signals) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.signals includes \"vectors\", but no \"embed\" block names a model; add one, or drop \"vectors\" from presets.${name}.signals`);\n }\n }\n }\n\n return cfg as unknown as Config;\n}\n"],"names":["KNOWN_EMBED_KEYS","unknownConfigKeys","validateConfig","validateLegacyScan","KNOWN_KEYS","Set","KNOWN_PRESET_KEYS","KNOWN_FEATURE_KEYS","KNOWN_CONTENT_KEYS","SAVED_SEARCH_KEYS","cfg","Object","keys","filter","k","has","isNonEmptyStringArray","value","Array","isArray","length","every","g","parsed","configPath","scan","include","SenseError","validateContentBlock","block","unknown","join","tokenize","undefined","trim","validateStoreKey","validateFeaturesBlock","entries","name","v","validateEmbedBlock","embed","model","provider","url","key","languages","some","l","chunkTokens","Number","isInteger","isSignalName","SIGNAL_NAMES","includes","isSignalWeight","isFinite","validatePresetSignals","map","signal","weight","names","SIGNAL_PREREQUISITES","requires","validatePreset","preset","exclude","signals","where","validateSavedQuery","JSON","stringify","slice","entry","sql","search","checks","presets","default","queries","features","content","store"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/config/validate.ts"],"sourcesContent":["import { SenseError } from '../errors.ts';\nimport { SIGNAL_NAMES, SIGNAL_PREREQUISITES, type SignalName } from './signals.ts';\nimport { type Config, STORE_NAMES, type StoreName } from './types.ts';\n\n// Shape check for hand-edited files, so a typo names itself instead of surfacing as a\n// TypeError. Unknown top-level keys warn (forward compat); unknown keys inside a block error.\nconst KNOWN_KEYS = new Set(['$schema', 'version', 'presets', 'features', 'embed', 'content', 'store', 'queries']);\nconst KNOWN_PRESET_KEYS = new Set(['include', 'exclude', 'k', 'signals', 'where']);\nconst KNOWN_FEATURE_KEYS = new Set(['links', 'sections', 'tags', 'rank']);\n// Exported so a docs test can assert every key here has a schema.json property -- one source\n// of truth for what the embed block accepts, checked against the other for drift.\nexport const KNOWN_EMBED_KEYS = new Set(['model', 'provider', 'url', 'key', 'languages', 'chunkTokens']);\nconst KNOWN_CONTENT_KEYS = new Set(['tokenize']);\nconst SAVED_SEARCH_KEYS = new Set(['search', 'preset', 'include', 'exclude', 'where', 'k']);\n\nexport function unknownConfigKeys(cfg: Record<string, unknown>): string[] {\n return Object.keys(cfg).filter((k) => !KNOWN_KEYS.has(k));\n}\n\nfunction isNonEmptyStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.length > 0 && value.every((g) => typeof g === 'string' && g.length > 0);\n}\n\n// Pre-v3 shape check, just enough for migrateConfig to run safely (it reads scan.include\n// directly). The full v3 shape is checked by validateConfig once migration has produced it.\nexport function validateLegacyScan(parsed: unknown, configPath: string): void {\n const cfg = typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) ? (parsed as Record<string, unknown>) : null;\n const scan = cfg?.scan as { include?: unknown } | undefined;\n if (!cfg || !scan || !isNonEmptyStringArray(scan.include)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: scan.include must be a non-empty array of glob strings`);\n }\n}\n\n// Only the shape is checked here. Whether the linked SQLite accepts the tokenizer is settled\n// by probing it in store/sqlite/open.ts, so this never has to carry a table of which version added what.\nfunction validateContentBlock(value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: content must be an object of { tokenize?: string }`);\n }\n const block = value as Record<string, unknown>;\n const unknown = Object.keys(block).filter((k) => !KNOWN_CONTENT_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: content has unknown key(s) ${unknown.join(', ')}; content takes tokenize`);\n }\n if (block.tokenize !== undefined && (typeof block.tokenize !== 'string' || block.tokenize.trim() === '')) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: content.tokenize must be a non-empty string, e.g. \"trigram\" or \"unicode61 tokenchars '-_'\"`);\n }\n}\n\nfunction validateStoreKey(value: unknown, configPath: string): void {\n if (!STORE_NAMES.includes(value as StoreName)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: store must be ${STORE_NAMES.map((name) => `\"${name}\"`).join(' or ')}`);\n }\n}\n\nfunction validateFeaturesBlock(value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features must be an object of name -> boolean`);\n }\n const block = value as Record<string, unknown>;\n const unknown = Object.keys(block).filter((k) => !KNOWN_FEATURE_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features has unknown key(s) ${unknown.join(', ')}; embed is not a features key -- see the top-level \"embed\" block`);\n }\n for (const [name, v] of Object.entries(block)) {\n if (typeof v !== 'boolean') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: features.${name} must be a boolean`);\n }\n }\n}\n\nfunction validateEmbedBlock(value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed must be an object of { model?, provider?: \"static\"|\"openai\"|\"cohere\", url?, key? }`);\n }\n const embed = value as Record<string, unknown>;\n const unknown = Object.keys(embed).filter((k) => !KNOWN_EMBED_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed has unknown key(s) ${unknown.join(', ')}`);\n }\n if (embed.model !== undefined && typeof embed.model !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.model must be a string`);\n }\n // The block exists to name a model; provider settings without one would read as \"vectors\n // configured\" while embedding stays off, which is the ambiguity v4 removed.\n if (embed.model === undefined || embed.model === '') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.model is required when the \"embed\" block is present (it is what turns vectors on); remove the block to index without vectors`);\n }\n if (embed.provider !== undefined && embed.provider !== 'static' && embed.provider !== 'openai' && embed.provider !== 'cohere') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.provider must be \"static\", \"openai\", or \"cohere\"`);\n }\n if (embed.url !== undefined && typeof embed.url !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.url must be a string`);\n }\n if (embed.key !== undefined && typeof embed.key !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.key must be a string`);\n }\n // openai has no default host, so a missing url would otherwise only surface at the first\n // vector search; a config error belongs at config time.\n if (embed.provider === 'openai' && (embed.url === undefined || embed.url === '')) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.provider \"openai\" requires embed.url (e.g. \"http://localhost:11434/v1\" for Ollama)`);\n }\n if (embed.languages !== undefined && (!Array.isArray(embed.languages) || embed.languages.length === 0 || embed.languages.some((l) => typeof l !== 'string' || l === ''))) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.languages must be a non-empty array of language tags (e.g. [\"en\", \"zh\"])`);\n }\n if (embed.chunkTokens !== undefined && (typeof embed.chunkTokens !== 'number' || !Number.isInteger(embed.chunkTokens) || embed.chunkTokens <= 0)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: embed.chunkTokens must be a positive integer`);\n }\n}\n\nfunction isSignalName(value: unknown): value is SignalName {\n return typeof value === 'string' && (SIGNAL_NAMES as readonly string[]).includes(value);\n}\n\nfunction isSignalWeight(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0;\n}\n\n// Shape (an object of signal name -> weight) plus the one cross-signal prerequisite that doesn't\n// need the top-level embed block: links is seeded by word-match rows, so declaring it without words is always empty.\nfunction validatePresetSignals(name: string, value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value) || Object.keys(value).length === 0) {\n throw new SenseError(\n 'CONFIG_INVALID',\n `${configPath}: presets.${name}.signals must be a non-empty object of signal name -> weight (a finite number > 0), naming ${SIGNAL_NAMES.join(', ')} -- a preset that searches nothing is a mistake; name at least \"words\", or omit \"signals\" to use every signal whose prerequisites hold at weight 1`\n );\n }\n const entries = Object.entries(value as Record<string, unknown>);\n const unknown = entries.filter(([k]) => !isSignalName(k)).map(([k]) => k);\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.signals names unknown signal(s) ${unknown.join(', ')}; valid signals are ${SIGNAL_NAMES.join(', ')}`);\n }\n for (const [signal, weight] of entries) {\n if (!isSignalWeight(weight)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.signals.${signal} must be a finite number > 0`);\n }\n }\n const names = new Set(entries.map(([k]) => k));\n for (const [signal, requires] of Object.entries(SIGNAL_PREREQUISITES) as Array<[SignalName, SignalName]>) {\n if (names.has(signal) && !names.has(requires)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.signals has \"${signal}\" without \"${requires}\"; add \"${requires}\" to presets.${name}.signals, or drop \"${signal}\"`);\n }\n }\n}\n\nfunction validatePreset(name: string, value: unknown, configPath: string): void {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name} must be an object`);\n }\n const preset = value as Record<string, unknown>;\n const unknown = Object.keys(preset).filter((k) => !KNOWN_PRESET_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name} has unknown key(s) ${unknown.join(', ')}; a preset takes include, exclude, k, signals, where`);\n }\n if (!isNonEmptyStringArray(preset.include)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.include must be a non-empty array of glob strings`);\n }\n if (preset.exclude !== undefined && !isNonEmptyStringArray(preset.exclude)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.exclude must be a non-empty array of glob strings`);\n }\n if (preset.signals !== undefined) validatePresetSignals(name, preset.signals, configPath);\n if (preset.k !== undefined && (typeof preset.k !== 'number' || !Number.isInteger(preset.k) || preset.k <= 0)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.k must be a positive integer`);\n }\n if (preset.where !== undefined && typeof preset.where !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.where must be a SQL condition string`);\n }\n}\n\n// A queries.<name> entry: { sql } or a saved search { search, preset?, include?, exclude?, where?, k? }.\nfunction validateSavedQuery(name: string, value: unknown, configPath: string): void {\n // A bare string is rejected rather than inferred to be SQL: an entry says which of the two\n // verbs it runs, the same choice the CLI makes explicit.\n if (typeof value === 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} must say which verb it runs: { \"sql\": ${JSON.stringify(value.length > 40 ? `${value.slice(0, 37)}...` : value)} } to run it as SQL, or { \"search\": \"...\" } for a ranked search`);\n }\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} must be { sql } or { search, preset?, include?, exclude?, where?, k? }`);\n }\n const entry = value as Record<string, unknown>;\n if ('sql' in entry) {\n const unknown = Object.keys(entry).filter((k) => k !== 'sql');\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} has unknown key(s) ${unknown.join(', ')}; a { sql } query takes only sql`);\n }\n if (typeof entry.sql !== 'string' || entry.sql.trim() === '') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.sql must be a non-empty string`);\n }\n return;\n }\n if ('search' in entry) {\n const unknown = Object.keys(entry).filter((k) => !SAVED_SEARCH_KEYS.has(k));\n if (unknown.length > 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} has unknown key(s) ${unknown.join(', ')}; a saved search takes search, preset, include, exclude, where, k`);\n }\n // A saved entry saves a question; a scope without a question is just flags.\n if (typeof entry.search !== 'string' || entry.search.trim() === '') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.search must be non-empty text`);\n }\n if (entry.preset !== undefined && (typeof entry.preset !== 'string' || entry.preset.length === 0)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.preset must be a preset name`);\n }\n if (entry.include !== undefined && !isNonEmptyStringArray(entry.include)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.include must be a non-empty array of glob strings`);\n }\n if (entry.exclude !== undefined && !isNonEmptyStringArray(entry.exclude)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.exclude must be a non-empty array of glob strings`);\n }\n if (entry.where !== undefined && typeof entry.where !== 'string') {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.where must be a SQL condition string`);\n }\n if (entry.k !== undefined && (typeof entry.k !== 'number' || !Number.isInteger(entry.k) || entry.k <= 0)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name}.k must be a positive integer`);\n }\n return;\n }\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries.${name} must be { sql } or { search, preset?, include?, exclude?, where?, k? }`);\n}\n\nexport function validateConfig(parsed: unknown, configPath: string): Config {\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: config must be a JSON object`);\n }\n const cfg = parsed as Record<string, unknown>;\n\n // `checks` is rejected by name, not warned: silence would hide that assertions are gone.\n if (cfg.checks !== undefined) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: checks was removed in v3 -- sense check no longer asserts on saved queries; a returned row set is the reader's judgment`);\n }\n\n const presets = cfg.presets as Record<string, unknown> | undefined;\n if (!presets || typeof presets !== 'object' || Array.isArray(presets) || Object.keys(presets).length === 0) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets must be a non-empty object of preset name -> { include, exclude?, k?, signals?, where? }`);\n }\n for (const [name, value] of Object.entries(presets)) {\n validatePreset(name, value, configPath);\n }\n if (presets.default === undefined) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets must include a \"default\" preset`);\n }\n\n if (cfg.queries === undefined) cfg.queries = {};\n if (typeof cfg.queries !== 'object' || cfg.queries === null || Array.isArray(cfg.queries)) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: queries must be an object of name -> { sql } or { search }`);\n }\n const queries = cfg.queries as Record<string, unknown>;\n for (const [name, value] of Object.entries(queries)) {\n validateSavedQuery(name, value, configPath);\n }\n\n if (cfg.features !== undefined) {\n validateFeaturesBlock(cfg.features, configPath);\n }\n if (cfg.embed !== undefined) {\n validateEmbedBlock(cfg.embed, configPath);\n }\n if (cfg.content !== undefined) {\n validateContentBlock(cfg.content, configPath);\n }\n if (cfg.store !== undefined) {\n validateStoreKey(cfg.store, configPath);\n }\n\n // vectors' prerequisite is a named model, checked here once embed is known valid (or absent).\n if (cfg.embed === undefined) {\n for (const [name, value] of Object.entries(presets)) {\n const signals = (value as Record<string, unknown>).signals as Record<string, unknown> | undefined;\n if (signals && 'vectors' in signals) {\n throw new SenseError('CONFIG_INVALID', `${configPath}: presets.${name}.signals includes \"vectors\", but no \"embed\" block names a model; add one, or drop \"vectors\" from presets.${name}.signals`);\n }\n }\n }\n\n return cfg as unknown as Config;\n}\n"],"names":["KNOWN_EMBED_KEYS","unknownConfigKeys","validateConfig","validateLegacyScan","KNOWN_KEYS","Set","KNOWN_PRESET_KEYS","KNOWN_FEATURE_KEYS","KNOWN_CONTENT_KEYS","SAVED_SEARCH_KEYS","cfg","Object","keys","filter","k","has","isNonEmptyStringArray","value","Array","isArray","length","every","g","parsed","configPath","scan","include","SenseError","validateContentBlock","block","unknown","join","tokenize","undefined","trim","validateStoreKey","STORE_NAMES","includes","map","name","validateFeaturesBlock","entries","v","validateEmbedBlock","embed","model","provider","url","key","languages","some","l","chunkTokens","Number","isInteger","isSignalName","SIGNAL_NAMES","isSignalWeight","isFinite","validatePresetSignals","signal","weight","names","SIGNAL_PREREQUISITES","requires","validatePreset","preset","exclude","signals","where","validateSavedQuery","JSON","stringify","slice","entry","sql","search","checks","presets","default","queries","features","content","store"],"mappings":"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"}
|
package/dist/cjs/embed/cohere.js
CHANGED
|
@@ -169,8 +169,8 @@ function cohereProvider(model, url, keyEnv) {
|
|
|
169
169
|
];
|
|
170
170
|
case 2:
|
|
171
171
|
body = _state.sent();
|
|
172
|
-
// Cohere returns one vector per text in order, with no index field to re-sort by;
|
|
173
|
-
//
|
|
172
|
+
// Cohere returns one vector per text in order, with no index field to re-sort by; a caller
|
|
173
|
+
// maps them positionally, so the count below must be trustworthy.
|
|
174
174
|
vectors = body.embeddings.float;
|
|
175
175
|
if (vectors.length !== texts.length) throw new _errorsts.SenseError('EMBED_MODEL', "".concat(base, "/v2/embed returned ").concat(vectors.length, " embeddings for ").concat(texts.length, " inputs"));
|
|
176
176
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/cohere.ts"],"sourcesContent":["import { SenseError } from '../errors.ts';\nimport { fetchWithRetry } from './http.ts';\nimport type { EmbedProvider } from './types.ts';\n\nconst BATCH_CAP = 96;\n\n// Cohere's native /v2/embed: input_type distinguishes doc vs query embeddings, which the\n// OpenAI-compatible shape cannot express.\nexport async function cohereProvider(model: string, url: string | undefined, keyEnv: string | undefined): Promise<EmbedProvider> {\n const base = (url ?? 'https://api.cohere.com').replace(/\\/+$/, '');\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n const key = keyEnv ? process.env[keyEnv] : undefined;\n if (key) headers.authorization = `Bearer ${key}`;\n\n async function post(texts: string[], inputType: 'search_document' | 'search_query'): Promise<Float32Array[]> {\n const res = await fetchWithRetry(`${base}/v2/embed`, { method: 'POST', headers, body: JSON.stringify({ model, input_type: inputType, texts, embedding_types: ['float'] }) });\n if (!res.ok) throw new SenseError('EMBED_MODEL', `${base}/v2/embed -> HTTP ${res.status}`);\n const body = (await res.json()) as { embeddings: { float: number[][] } };\n // Cohere returns one vector per text in order, with no index field to re-sort by;
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/cohere.ts"],"sourcesContent":["import { SenseError } from '../errors.ts';\nimport { fetchWithRetry } from './http.ts';\nimport type { EmbedProvider } from './types.ts';\n\nconst BATCH_CAP = 96;\n\n// Cohere's native /v2/embed: input_type distinguishes doc vs query embeddings, which the\n// OpenAI-compatible shape cannot express.\nexport async function cohereProvider(model: string, url: string | undefined, keyEnv: string | undefined): Promise<EmbedProvider> {\n const base = (url ?? 'https://api.cohere.com').replace(/\\/+$/, '');\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n const key = keyEnv ? process.env[keyEnv] : undefined;\n if (key) headers.authorization = `Bearer ${key}`;\n\n async function post(texts: string[], inputType: 'search_document' | 'search_query'): Promise<Float32Array[]> {\n const res = await fetchWithRetry(`${base}/v2/embed`, { method: 'POST', headers, body: JSON.stringify({ model, input_type: inputType, texts, embedding_types: ['float'] }) });\n if (!res.ok) throw new SenseError('EMBED_MODEL', `${base}/v2/embed -> HTTP ${res.status}`);\n const body = (await res.json()) as { embeddings: { float: number[][] } };\n // Cohere returns one vector per text in order, with no index field to re-sort by; a caller\n // maps them positionally, so the count below must be trustworthy.\n const vectors = body.embeddings.float;\n if (vectors.length !== texts.length) throw new SenseError('EMBED_MODEL', `${base}/v2/embed returned ${vectors.length} embeddings for ${texts.length} inputs`);\n return vectors.map((v) => Float32Array.from(v));\n }\n\n const dims = (await post(['dimension probe'], 'search_query'))[0].length;\n return { id: `cohere:${base}:${model}`, dims, batchCap: BATCH_CAP, embedDocuments: (texts) => post(texts, 'search_document'), embedQuery: async (text) => (await post([text], 'search_query'))[0] };\n}\n"],"names":["cohereProvider","BATCH_CAP","model","url","keyEnv","base","headers","key","dims","post","texts","inputType","res","body","vectors","fetchWithRetry","method","JSON","stringify","input_type","embedding_types","ok","SenseError","status","json","embeddings","float","length","map","v","Float32Array","from","replace","process","env","undefined","authorization","id","batchCap","embedDocuments","embedQuery","text"],"mappings":";;;;+BAQsBA;;;eAAAA;;;wBARK;sBACI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG/B,IAAMC,YAAY;AAIX,SAAeD,eAAeE,KAAa,EAAEC,GAAuB,EAAEC,MAA0B;;YAC/FC,MACAC,SACAC,KAcAC;QAXN,SAAeC,KAAKC,KAAe,EAAEC,SAA6C;;oBAC1EC,KAEAC,MAGAC;;;;4BALM;;gCAAMC,IAAAA,sBAAc,EAAC,AAAC,GAAO,OAALV,MAAK,cAAY;oCAAEW,QAAQ;oCAAQV,SAAAA;oCAASO,MAAMI,KAAKC,SAAS,CAAC;wCAAEhB,OAAAA;wCAAOiB,YAAYR;wCAAWD,OAAAA;wCAAOU,eAAe;4CAAG;;oCAAS;gCAAG;;;4BAApKR,MAAM;4BACZ,IAAI,CAACA,IAAIS,EAAE,EAAE,MAAM,IAAIC,oBAAU,CAAC,eAAe,AAAC,GAA2BV,OAAzBP,MAAK,sBAA+B,OAAXO,IAAIW,MAAM;4BACzE;;gCAAMX,IAAIY,IAAI;;;4BAAtBX,OAAQ;4BACd,2FAA2F;4BAC3F,kEAAkE;4BAC5DC,UAAUD,KAAKY,UAAU,CAACC,KAAK;4BACrC,IAAIZ,QAAQa,MAAM,KAAKjB,MAAMiB,MAAM,EAAE,MAAM,IAAIL,oBAAU,CAAC,eAAe,AAAC,GAA4BR,OAA1BT,MAAK,uBAAsDK,OAAjCI,QAAQa,MAAM,EAAC,oBAA+B,OAAbjB,MAAMiB,MAAM,EAAC;4BACpJ;;gCAAOb,QAAQc,GAAG,CAAC,SAACC;2CAAMC,aAAaC,IAAI,CAACF;;;;;YAC9C;;;;;oBAdMxB,OAAO,CAACF,gBAAAA,iBAAAA,MAAO,0BAA0B6B,OAAO,CAAC,QAAQ;oBACzD1B,UAAkC;wBAAE,gBAAgB;oBAAmB;oBACvEC,MAAMH,SAAS6B,QAAQC,GAAG,CAAC9B,OAAO,GAAG+B;oBAC3C,IAAI5B,KAAKD,QAAQ8B,aAAa,GAAG,AAAC,UAAa,OAAJ7B;oBAa7B;;wBAAME;4BAAM;2BAAoB;;;oBAAxCD,OAAO,AAAC,aAAgD,CAAC,EAAE,CAACmB,MAAM;oBACxE;;wBAAO;4BAAEU,IAAI,AAAC,UAAiBnC,OAARG,MAAK,KAAS,OAANH;4BAASM,MAAAA;4BAAM8B,UAAUrC;4BAAWsC,gBAAgB,SAAhBA,eAAiB7B;uCAAUD,KAAKC,OAAO;;4BAAoB8B,YAAY,SAAZA,WAAmBC;;;;;gDAAU;;oDAAMhC;wDAAMgC;uDAAO;;;;;oDAAnB,aAAmC,CAAC,EAAE;;;;;;wBAAC;;;;IACpM"}
|
|
@@ -16,7 +16,7 @@ _export(exports, {
|
|
|
16
16
|
return saveLanguageDistribution;
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
|
-
var
|
|
19
|
+
var _sharedts = require("../store/shared.js");
|
|
20
20
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
21
21
|
try {
|
|
22
22
|
var info = gen[key](arg);
|
|
@@ -153,7 +153,7 @@ function languageDistribution(store) {
|
|
|
153
153
|
case 0:
|
|
154
154
|
return [
|
|
155
155
|
4,
|
|
156
|
-
(0,
|
|
156
|
+
(0, _sharedts.getMeta)(store, META_KEY)
|
|
157
157
|
];
|
|
158
158
|
case 1:
|
|
159
159
|
raw = _state.sent();
|
|
@@ -172,7 +172,7 @@ function saveLanguageDistribution(store, counts) {
|
|
|
172
172
|
case 0:
|
|
173
173
|
return [
|
|
174
174
|
4,
|
|
175
|
-
(0,
|
|
175
|
+
(0, _sharedts.setMeta)(store, META_KEY, JSON.stringify(counts))
|
|
176
176
|
];
|
|
177
177
|
case 1:
|
|
178
178
|
_state.sent();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/distribution.ts"],"sourcesContent":["import { getMeta, setMeta } from '../store/
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/distribution.ts"],"sourcesContent":["import { getMeta, setMeta } from '../store/shared.ts';\nimport type { Store } from '../store/types.ts';\n\n// Split out of langfit.ts so reading the persisted counts (status.ts's only need) never pulls in\n// franc-min; only checkLanguageFit's classify path needs the classifier itself.\nconst META_KEY = 'embed_languages';\n\nexport type LangCounts = Record<string, number>;\n\nexport async function languageDistribution(store: Store): Promise<LangCounts | undefined> {\n const raw = await getMeta(store, META_KEY);\n return raw ? JSON.parse(raw) : undefined;\n}\n\nexport async function saveLanguageDistribution(store: Store, counts: LangCounts): Promise<void> {\n await setMeta(store, META_KEY, JSON.stringify(counts));\n}\n"],"names":["languageDistribution","saveLanguageDistribution","META_KEY","store","raw","getMeta","JSON","parse","undefined","counts","setMeta","stringify"],"mappings":";;;;;;;;;;;QASsBA;eAAAA;;QAKAC;eAAAA;;;wBAdW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGjC,iGAAiG;AACjG,gFAAgF;AAChF,IAAMC,WAAW;AAIV,SAAeF,qBAAqBG,KAAY;;YAC/CC;;;;oBAAM;;wBAAMC,IAAAA,iBAAO,EAACF,OAAOD;;;oBAA3BE,MAAM;oBACZ;;wBAAOA,MAAME,KAAKC,KAAK,CAACH,OAAOI;;;;IACjC;;AAEO,SAAeP,yBAAyBE,KAAY,EAAEM,MAAkB;;;;;oBAC7E;;wBAAMC,IAAAA,iBAAO,EAACP,OAAOD,UAAUI,KAAKK,SAAS,CAACF;;;oBAA9C;;;;;;IACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
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 rekeyChunkText () {
|
|
13
|
+
return rekeyChunkText;
|
|
14
|
+
},
|
|
15
|
+
get stashChunkText () {
|
|
16
|
+
return stashChunkText;
|
|
17
|
+
},
|
|
18
|
+
get takeChunkText () {
|
|
19
|
+
return takeChunkText;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
// Chunk text from reconcile to embed time when both run in one process, so the text is neither
|
|
23
|
+
// re-derived nor persisted. Keyed by the store it was stashed against, so an entry dies with it.
|
|
24
|
+
var HANDOFF = new WeakMap();
|
|
25
|
+
function stashChunkText(key, texts) {
|
|
26
|
+
if (texts.size > 0) HANDOFF.set(key, texts);
|
|
27
|
+
}
|
|
28
|
+
function rekeyChunkText(from, to) {
|
|
29
|
+
var texts = HANDOFF.get(from);
|
|
30
|
+
if (!texts) return;
|
|
31
|
+
HANDOFF.delete(from);
|
|
32
|
+
HANDOFF.set(to, texts);
|
|
33
|
+
}
|
|
34
|
+
function takeChunkText(key) {
|
|
35
|
+
var texts = HANDOFF.get(key);
|
|
36
|
+
HANDOFF.delete(key);
|
|
37
|
+
return texts;
|
|
38
|
+
}
|
|
39
|
+
/* 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/embed/handoff.ts"],"sourcesContent":["// Chunk text from reconcile to embed time when both run in one process, so the text is neither\n// re-derived nor persisted. Keyed by the store it was stashed against, so an entry dies with it.\nconst HANDOFF = new WeakMap<object, Map<string, string[]>>();\n\nexport function stashChunkText(key: object, texts: Map<string, string[]>): void {\n if (texts.size > 0) HANDOFF.set(key, texts);\n}\n\n// Moves an entry from one key to another: reconcile runs before the store object exists, so it\n// stashes against the connection and open() re-keys onto the store it then builds.\nexport function rekeyChunkText(from: object, to: object): void {\n const texts = HANDOFF.get(from);\n if (!texts) return;\n HANDOFF.delete(from);\n HANDOFF.set(to, texts);\n}\n\n// Read once and drop: the text is consumed by the embed pass that follows reconcile, and holding\n// it past that would pin the tree's prose in memory for the life of the store.\nexport function takeChunkText(key: object): Map<string, string[]> | undefined {\n const texts = HANDOFF.get(key);\n HANDOFF.delete(key);\n return texts;\n}\n"],"names":["rekeyChunkText","stashChunkText","takeChunkText","HANDOFF","WeakMap","key","texts","size","set","from","to","get","delete"],"mappings":";;;;;;;;;;;QAUgBA;eAAAA;;QANAC;eAAAA;;QAeAC;eAAAA;;;AAnBhB,+FAA+F;AAC/F,iGAAiG;AACjG,IAAMC,UAAU,IAAIC;AAEb,SAASH,eAAeI,GAAW,EAAEC,KAA4B;IACtE,IAAIA,MAAMC,IAAI,GAAG,GAAGJ,QAAQK,GAAG,CAACH,KAAKC;AACvC;AAIO,SAASN,eAAeS,IAAY,EAAEC,EAAU;IACrD,IAAMJ,QAAQH,QAAQQ,GAAG,CAACF;IAC1B,IAAI,CAACH,OAAO;IACZH,QAAQS,MAAM,CAACH;IACfN,QAAQK,GAAG,CAACE,IAAIJ;AAClB;AAIO,SAASJ,cAAcG,GAAW;IACvC,IAAMC,QAAQH,QAAQQ,GAAG,CAACN;IAC1BF,QAAQS,MAAM,CAACP;IACf,OAAOC;AACT"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
export declare const MODEL_FILES: string[];
|
|
2
2
|
export declare const MODEL_FILENAMES: string;
|
|
3
3
|
export declare function isDownloadable(model: string): boolean;
|
|
4
|
-
export declare
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
12
|
-
export declare function
|
|
13
|
-
export declare function
|
|
4
|
+
export declare const DEFAULT_MODELS_ROOT: string;
|
|
5
|
+
export declare function refsMainPath(model: string, root?: string): string;
|
|
6
|
+
export declare function readRef(model: string, root?: string): string | undefined;
|
|
7
|
+
export declare function writeRef(model: string, sha: string, root?: string): void;
|
|
8
|
+
export declare function snapshotDir(model: string, sha: string, root?: string): string;
|
|
9
|
+
export declare function languagesPath(model: string, root?: string): string;
|
|
10
|
+
export declare function readLanguages(model: string, root?: string): string[] | undefined;
|
|
11
|
+
export declare function writeLanguages(model: string, languages: string[], root?: string): void;
|
|
12
|
+
export declare function modelDir(model: string, root?: string): string;
|
|
13
|
+
export declare function hasModelFiles(model: string, root?: string): boolean;
|
|
14
|
+
export declare function modelIdentity(model: string, root?: string): string | undefined;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
export declare const MODEL_FILES: string[];
|
|
2
2
|
export declare const MODEL_FILENAMES: string;
|
|
3
3
|
export declare function isDownloadable(model: string): boolean;
|
|
4
|
-
export declare
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
12
|
-
export declare function
|
|
13
|
-
export declare function
|
|
4
|
+
export declare const DEFAULT_MODELS_ROOT: string;
|
|
5
|
+
export declare function refsMainPath(model: string, root?: string): string;
|
|
6
|
+
export declare function readRef(model: string, root?: string): string | undefined;
|
|
7
|
+
export declare function writeRef(model: string, sha: string, root?: string): void;
|
|
8
|
+
export declare function snapshotDir(model: string, sha: string, root?: string): string;
|
|
9
|
+
export declare function languagesPath(model: string, root?: string): string;
|
|
10
|
+
export declare function readLanguages(model: string, root?: string): string[] | undefined;
|
|
11
|
+
export declare function writeLanguages(model: string, languages: string[], root?: string): void;
|
|
12
|
+
export declare function modelDir(model: string, root?: string): string;
|
|
13
|
+
export declare function hasModelFiles(model: string, root?: string): boolean;
|
|
14
|
+
export declare function modelIdentity(model: string, root?: string): string | undefined;
|
|
@@ -9,6 +9,9 @@ function _export(target, all) {
|
|
|
9
9
|
});
|
|
10
10
|
}
|
|
11
11
|
_export(exports, {
|
|
12
|
+
get DEFAULT_MODELS_ROOT () {
|
|
13
|
+
return DEFAULT_MODELS_ROOT;
|
|
14
|
+
},
|
|
12
15
|
get MODEL_FILENAMES () {
|
|
13
16
|
return MODEL_FILENAMES;
|
|
14
17
|
},
|
|
@@ -110,33 +113,41 @@ var HF_MODEL_ID = /^[A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*$/;
|
|
|
110
113
|
function isDownloadable(model) {
|
|
111
114
|
return HF_MODEL_ID.test(model);
|
|
112
115
|
}
|
|
116
|
+
var DEFAULT_MODELS_ROOT = (0, _nodepath.join)((0, _nodeos.homedir)(), '.sense', 'models');
|
|
113
117
|
function repoDir(model) {
|
|
118
|
+
var root = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MODELS_ROOT;
|
|
114
119
|
var _model_split = _sliced_to_array(model.split('/'), 2), org = _model_split[0], name = _model_split[1];
|
|
115
|
-
return (0, _nodepath.join)(
|
|
120
|
+
return (0, _nodepath.join)(root, "models--".concat(org, "--").concat(name));
|
|
116
121
|
}
|
|
117
122
|
function refsMainPath(model) {
|
|
118
|
-
|
|
123
|
+
var root = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MODELS_ROOT;
|
|
124
|
+
return (0, _nodepath.join)(repoDir(model, root), 'refs', 'main');
|
|
119
125
|
}
|
|
120
126
|
function readRef(model) {
|
|
121
|
-
var
|
|
127
|
+
var root = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MODELS_ROOT;
|
|
128
|
+
var p = refsMainPath(model, root);
|
|
122
129
|
if (!(0, _nodefs.existsSync)(p)) return undefined;
|
|
123
130
|
var sha = (0, _nodefs.readFileSync)(p, 'utf8').trim();
|
|
124
131
|
return sha.length > 0 ? sha : undefined;
|
|
125
132
|
}
|
|
126
133
|
function writeRef(model, sha) {
|
|
127
|
-
|
|
134
|
+
var root = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : DEFAULT_MODELS_ROOT;
|
|
135
|
+
(0, _nodefs.mkdirSync)((0, _nodepath.join)(repoDir(model, root), 'refs'), {
|
|
128
136
|
recursive: true
|
|
129
137
|
});
|
|
130
|
-
(0, _atomicwritets.writeFileAtomic)(refsMainPath(model), sha);
|
|
138
|
+
(0, _atomicwritets.writeFileAtomic)(refsMainPath(model, root), sha);
|
|
131
139
|
}
|
|
132
140
|
function snapshotDir(model, sha) {
|
|
133
|
-
|
|
141
|
+
var root = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : DEFAULT_MODELS_ROOT;
|
|
142
|
+
return (0, _nodepath.join)(repoDir(model, root), 'snapshots', sha);
|
|
134
143
|
}
|
|
135
144
|
function languagesPath(model) {
|
|
136
|
-
|
|
145
|
+
var root = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MODELS_ROOT;
|
|
146
|
+
return (0, _nodepath.join)(repoDir(model, root), 'languages.json');
|
|
137
147
|
}
|
|
138
148
|
function readLanguages(model) {
|
|
139
|
-
var
|
|
149
|
+
var root = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MODELS_ROOT;
|
|
150
|
+
var p = languagesPath(model, root);
|
|
140
151
|
if (!(0, _nodefs.existsSync)(p)) return undefined;
|
|
141
152
|
try {
|
|
142
153
|
return JSON.parse((0, _nodefs.readFileSync)(p, 'utf8'));
|
|
@@ -145,25 +156,29 @@ function readLanguages(model) {
|
|
|
145
156
|
}
|
|
146
157
|
}
|
|
147
158
|
function writeLanguages(model, languages) {
|
|
148
|
-
|
|
159
|
+
var root = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : DEFAULT_MODELS_ROOT;
|
|
160
|
+
(0, _nodefs.mkdirSync)(repoDir(model, root), {
|
|
149
161
|
recursive: true
|
|
150
162
|
});
|
|
151
|
-
(0, _atomicwritets.writeFileAtomic)(languagesPath(model), JSON.stringify(languages));
|
|
163
|
+
(0, _atomicwritets.writeFileAtomic)(languagesPath(model, root), JSON.stringify(languages));
|
|
152
164
|
}
|
|
153
165
|
function modelDir(model) {
|
|
166
|
+
var root = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MODELS_ROOT;
|
|
154
167
|
if (!isDownloadable(model)) return model;
|
|
155
|
-
var sha = readRef(model);
|
|
156
|
-
return sha ? snapshotDir(model, sha) : repoDir(model);
|
|
168
|
+
var sha = readRef(model, root);
|
|
169
|
+
return sha ? snapshotDir(model, sha, root) : repoDir(model, root);
|
|
157
170
|
}
|
|
158
171
|
function hasModelFiles(model) {
|
|
159
|
-
var
|
|
172
|
+
var root = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MODELS_ROOT;
|
|
173
|
+
var dir = modelDir(model, root);
|
|
160
174
|
return MODEL_FILES.every(function(file) {
|
|
161
175
|
return (0, _nodefs.existsSync)((0, _nodepath.join)(dir, file));
|
|
162
176
|
});
|
|
163
177
|
}
|
|
164
178
|
function modelIdentity(model) {
|
|
165
|
-
|
|
166
|
-
|
|
179
|
+
var root = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MODELS_ROOT;
|
|
180
|
+
if (isDownloadable(model)) return readRef(model, root);
|
|
181
|
+
var dir = modelDir(model, root);
|
|
167
182
|
var parts = [];
|
|
168
183
|
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
169
184
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/identity.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, statSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { writeFileAtomic } from '../lib/atomic-write.ts';\n\n// HF cache layout, no network: ~/.sense/models/models--<org>--<name>/{refs/main,\n// snapshots/<sha>/<files>}, files stored directly (hf_hub's blobs/symlinks layer skipped).\n\nexport const MODEL_FILES = ['model.safetensors', 'tokenizer.json'];\n// The pair, for messages that name what a local model directory must contain.\nexport const MODEL_FILENAMES = MODEL_FILES.join(' and ');\n\n// A Hugging Face repo id: one slash, HF's charset. Anything else is a path, used as one rather\n// than resolved against the HF cache.\nconst HF_MODEL_ID = /^[A-Za-z0-9][\\w.-]*\\/[A-Za-z0-9][\\w.-]*$/;\n\nexport function isDownloadable(model: string): boolean {\n return HF_MODEL_ID.test(model);\n}\n\nfunction repoDir(model: string): string {\n const [org, name] = model.split('/');\n return join(
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/identity.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, statSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { writeFileAtomic } from '../lib/atomic-write.ts';\n\n// HF cache layout, no network: ~/.sense/models/models--<org>--<name>/{refs/main,\n// snapshots/<sha>/<files>}, files stored directly (hf_hub's blobs/symlinks layer skipped).\n\nexport const MODEL_FILES = ['model.safetensors', 'tokenizer.json'];\n// The pair, for messages that name what a local model directory must contain.\nexport const MODEL_FILENAMES = MODEL_FILES.join(' and ');\n\n// A Hugging Face repo id: one slash, HF's charset. Anything else is a path, used as one rather\n// than resolved against the HF cache.\nconst HF_MODEL_ID = /^[A-Za-z0-9][\\w.-]*\\/[A-Za-z0-9][\\w.-]*$/;\n\nexport function isDownloadable(model: string): boolean {\n return HF_MODEL_ID.test(model);\n}\n\n// The one production default; tests pass their own scratch root through the same parameter\n// rather than seeding fixture ids into this machine cache.\nexport const DEFAULT_MODELS_ROOT = join(homedir(), '.sense', 'models');\n\nfunction repoDir(model: string, root: string = DEFAULT_MODELS_ROOT): string {\n const [org, name] = model.split('/');\n return join(root, `models--${org}--${name}`);\n}\n\nexport function refsMainPath(model: string, root: string = DEFAULT_MODELS_ROOT): string {\n return join(repoDir(model, root), 'refs', 'main');\n}\n\n// What `main` last resolved to, read from disk -- no network. Undefined until some resolution\n// (a download or an explicit prefetch) has written it once.\nexport function readRef(model: string, root: string = DEFAULT_MODELS_ROOT): string | undefined {\n const p = refsMainPath(model, root);\n if (!existsSync(p)) return undefined;\n const sha = readFileSync(p, 'utf8').trim();\n return sha.length > 0 ? sha : undefined;\n}\n\n// A recorded ref pins until its snapshot directory is removed; nothing here re-resolves it.\nexport function writeRef(model: string, sha: string, root: string = DEFAULT_MODELS_ROOT): void {\n mkdirSync(join(repoDir(model, root), 'refs'), { recursive: true });\n writeFileAtomic(refsMainPath(model, root), sha);\n}\n\nexport function snapshotDir(model: string, sha: string, root: string = DEFAULT_MODELS_ROOT): string {\n return join(repoDir(model, root), 'snapshots', sha);\n}\n\n// Languages describe the repo, not one weight snapshot, so this lives beside refs/, not\n// inside a snapshot dir.\nexport function languagesPath(model: string, root: string = DEFAULT_MODELS_ROOT): string {\n return join(repoDir(model, root), 'languages.json');\n}\n\n// undefined means \"never resolved yet\"; an empty array is a resolved fact (checked, none\n// declared) and is cached the same way, so a languageless model is not re-fetched every run.\nexport function readLanguages(model: string, root: string = DEFAULT_MODELS_ROOT): string[] | undefined {\n const p = languagesPath(model, root);\n if (!existsSync(p)) return undefined;\n try {\n return JSON.parse(readFileSync(p, 'utf8'));\n } catch {\n return undefined;\n }\n}\n\nexport function writeLanguages(model: string, languages: string[], root: string = DEFAULT_MODELS_ROOT): void {\n mkdirSync(repoDir(model, root), { recursive: true });\n writeFileAtomic(languagesPath(model, root), JSON.stringify(languages));\n}\n\n// A local directory the caller manages, or the resolved snapshot once `main` is pinned; an HF\n// id with no recorded ref yet has no known snapshot, so this names the (fileless) repo dir.\nexport function modelDir(model: string, root: string = DEFAULT_MODELS_ROOT): string {\n if (!isDownloadable(model)) return model;\n const sha = readRef(model, root);\n return sha ? snapshotDir(model, sha, root) : repoDir(model, root);\n}\n\n// Both files, so an interrupted download reads as absent and the next one resumes it.\nexport function hasModelFiles(model: string, root: string = DEFAULT_MODELS_ROOT): boolean {\n const dir = modelDir(model, root);\n return MODEL_FILES.every((file) => existsSync(join(dir, file)));\n}\n\n// Weight identity for the signature, no network: a HF id's resolved sha, or the two\n// files' size+mtime for a local path. Undefined when nothing is known yet.\nexport function modelIdentity(model: string, root: string = DEFAULT_MODELS_ROOT): string | undefined {\n if (isDownloadable(model)) return readRef(model, root);\n const dir = modelDir(model, root);\n const parts: string[] = [];\n for (const file of MODEL_FILES) {\n try {\n const st = statSync(join(dir, file));\n parts.push(`${st.size}:${Math.trunc(st.mtimeMs)}`);\n } catch {\n return undefined;\n }\n }\n return parts.join(',');\n}\n"],"names":["DEFAULT_MODELS_ROOT","MODEL_FILENAMES","MODEL_FILES","hasModelFiles","isDownloadable","languagesPath","modelDir","modelIdentity","readLanguages","readRef","refsMainPath","snapshotDir","writeLanguages","writeRef","join","HF_MODEL_ID","model","test","homedir","repoDir","root","split","org","name","p","existsSync","undefined","sha","readFileSync","trim","length","mkdirSync","recursive","writeFileAtomic","JSON","parse","languages","stringify","dir","every","file","parts","st","statSync","push","Math","size","trunc","mtimeMs"],"mappings":"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"}
|
|
@@ -220,9 +220,8 @@ var SAMPLE_CHARS = 300;
|
|
|
220
220
|
// A majority computed over a handful of chunks is noise, not a corpus signal; the decision rule
|
|
221
221
|
// never fires below this many classified chunks, declared languages or not.
|
|
222
222
|
var MIN_CLASSIFIED = 10;
|
|
223
|
-
// franc-min is a 148K static import; a top-level import put it on every command's module
|
|
224
|
-
// regardless of whether the semantic path ran,
|
|
225
|
-
// synchronous require inside checkLanguageFit so only the embed path pays for it.
|
|
223
|
+
// franc-min is a 148K static import; a top-level import would put it on every command's module
|
|
224
|
+
// graph regardless of whether the semantic path ran, so it's deferred to a synchronous require.
|
|
226
225
|
var _require = typeof require === 'undefined' ? _nodemodule.default.createRequire(require("url").pathToFileURL(__filename).toString()) : require;
|
|
227
226
|
function classify(franc, text) {
|
|
228
227
|
var code = franc(text.slice(0, SAMPLE_CHARS));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/langfit.ts"],"sourcesContent":["import Module from 'node:module';\nimport { SenseError } from '../errors.ts';\nimport type { Store } from '../store/types.ts';\nimport { languageDistribution, saveLanguageDistribution } from './distribution.ts';\nimport { toIso3 } from './languages.ts';\nimport type { EmbedProvider } from './types.ts';\n\n// franc's own reliability floor is a handful of characters; this is a cheap upper bound, not a\n// per-chunk minimum -- a short chunk is simply more likely to come back 'und' (unclassified).\nconst SAMPLE_CHARS = 300;\n// A majority computed over a handful of chunks is noise, not a corpus signal; the decision rule\n// never fires below this many classified chunks, declared languages or not.\nconst MIN_CLASSIFIED = 10;\n\n// franc-min is a 148K static import; a top-level import put it on every command's module
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/langfit.ts"],"sourcesContent":["import Module from 'node:module';\nimport { SenseError } from '../errors.ts';\nimport type { Store } from '../store/types.ts';\nimport { languageDistribution, saveLanguageDistribution } from './distribution.ts';\nimport { toIso3 } from './languages.ts';\nimport type { EmbedProvider } from './types.ts';\n\n// franc's own reliability floor is a handful of characters; this is a cheap upper bound, not a\n// per-chunk minimum -- a short chunk is simply more likely to come back 'und' (unclassified).\nconst SAMPLE_CHARS = 300;\n// A majority computed over a handful of chunks is noise, not a corpus signal; the decision rule\n// never fires below this many classified chunks, declared languages or not.\nconst MIN_CLASSIFIED = 10;\n\n// franc-min is a 148K static import; a top-level import would put it on every command's module\n// graph regardless of whether the semantic path ran, so it's deferred to a synchronous require.\nconst _require = typeof require === 'undefined' ? Module.createRequire(import.meta.url) : require;\n\nfunction classify(franc: typeof import('franc-min')['franc'], text: string): string | undefined {\n const code = franc(text.slice(0, SAMPLE_CHARS));\n return code === 'und' ? undefined : code;\n}\n\n// Merges chunk texts into the persisted distribution; throws (without persisting) if the model\n// declares languages and a clear majority classified so far is not among them.\nexport async function checkLanguageFit(store: Store, provider: EmbedProvider, texts: string[]): Promise<void> {\n if (texts.length === 0) return;\n const { franc } = _require('franc-min') as typeof import('franc-min');\n const persisted = (await languageDistribution(store)) ?? {};\n const merged = { ...persisted };\n for (const text of texts) {\n const code = classify(franc, text);\n if (code) merged[code] = (merged[code] ?? 0) + 1;\n }\n\n const total = Object.values(merged).reduce((a, b) => a + b, 0);\n if (provider.languages && provider.languages.length > 0 && total >= MIN_CLASSIFIED) {\n const declared = new Set(provider.languages.map(toIso3));\n const [majorityLang, majorityCount] = Object.entries(merged).sort((a, b) => b[1] - a[1])[0];\n if (majorityCount / total >= 0.5 && !declared.has(majorityLang)) {\n const pct = Math.round((majorityCount / total) * 100);\n throw new SenseError(\n 'EMBED_MODEL_MISMATCH',\n `embed model ${provider.id} declares languages [${provider.languages.join(', ')}], but ${pct}% of this tree's classified text is \"${majorityLang}\" (ISO 639-3), which is not among them; choose a model for this tree's languages: \\`sense init --model ...\\`, see the sense-setup skill or INTEGRATIONS.md`\n );\n }\n }\n await saveLanguageDistribution(store, merged);\n}\n"],"names":["checkLanguageFit","SAMPLE_CHARS","MIN_CLASSIFIED","_require","require","Module","createRequire","classify","franc","text","code","slice","undefined","store","provider","texts","persisted","merged","total","declared","Object","majorityLang","majorityCount","pct","length","languageDistribution","values","reduce","a","b","languages","Set","map","toIso3","entries","sort","has","Math","round","SenseError","id","join","saveLanguageDistribution"],"mappings":";;;;+BAyBsBA;;;eAAAA;;;iEAzBH;wBACQ;8BAEoC;2BACxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGvB,+FAA+F;AAC/F,8FAA8F;AAC9F,IAAMC,eAAe;AACrB,gGAAgG;AAChG,4EAA4E;AAC5E,IAAMC,iBAAiB;AAEvB,+FAA+F;AAC/F,gGAAgG;AAChG,IAAMC,WAAW,OAAOC,YAAY,cAAcC,mBAAM,CAACC,aAAa,CAAC,uDAAmBF;AAE1F,SAASG,SAASC,KAA0C,EAAEC,IAAY;IACxE,IAAMC,OAAOF,MAAMC,KAAKE,KAAK,CAAC,GAAGV;IACjC,OAAOS,SAAS,QAAQE,YAAYF;AACtC;AAIO,SAAeV,iBAAiBa,KAAY,EAAEC,QAAuB,EAAEC,KAAe;;YAGxE,MADXP,OACFQ,WACAC,QACD,2BAAA,mBAAA,gBAAA,WAAA,OAAMR,MAEiBQ,cADpBP,MAIFQ,OAEEC,UACgCC,uBAA/BC,cAAcC,eAEbC;;;;oBAdV,IAAIR,MAAMS,MAAM,KAAK,GAAG;;;oBAChBhB,QAAUL,SAAS,aAAnBK;oBACW;;wBAAMiB,IAAAA,oCAAoB,EAACZ;;;oBAAxCG,aAAa,OAAA,2BAAA,kBAAA,OAAsC,CAAC;oBACpDC,SAAS,mBAAKD;oBACf,kCAAA,2BAAA;;wBAAL,IAAK,YAAcD,4BAAd,6BAAA,QAAA,yBAAA,iCAAqB;4BAAfN,OAAN;;4BACGC,OAAOH,SAASC,OAAOC;4BAC7B,IAAIC,MAAMO,MAAM,CAACP,KAAK,GAAG,EAACO,eAAAA,MAAM,CAACP,KAAK,cAAZO,0BAAAA,eAAgB,KAAK;wBACjD;;wBAHK;wBAAA;;;iCAAA,6BAAA;gCAAA;;;gCAAA;sCAAA;;;;oBAKCC,QAAQE,OAAOM,MAAM,CAACT,QAAQU,MAAM,CAAC,SAACC,GAAGC;+BAAMD,IAAIC;uBAAG;oBAC5D,IAAIf,SAASgB,SAAS,IAAIhB,SAASgB,SAAS,CAACN,MAAM,GAAG,KAAKN,SAAShB,gBAAgB;wBAC5EiB,WAAW,IAAIY,IAAIjB,SAASgB,SAAS,CAACE,GAAG,CAACC,mBAAM;wBAChBb,yCAAAA,OAAOc,OAAO,CAACjB,QAAQkB,IAAI,CAAC,SAACP,GAAGC;mCAAMA,CAAC,CAAC,EAAE,GAAGD,CAAC,CAAC,EAAE;0BAAC,CAAC,EAAE,MAApFP,eAA+BD,0BAAjBE,gBAAiBF;wBACtC,IAAIE,gBAAgBJ,SAAS,OAAO,CAACC,SAASiB,GAAG,CAACf,eAAe;4BACzDE,MAAMc,KAAKC,KAAK,CAAC,AAAChB,gBAAgBJ,QAAS;4BACjD,MAAM,IAAIqB,oBAAU,CAClB,wBACA,AAAC,eAAiDzB,OAAnCA,SAAS0B,EAAE,EAAC,yBAA8DjB,OAAvCT,SAASgB,SAAS,CAACW,IAAI,CAAC,OAAM,WAAoDpB,OAA3CE,KAAI,0CAAoD,OAAbF,cAAa;wBAErJ;oBACF;oBACA;;wBAAMqB,IAAAA,wCAAwB,EAAC7B,OAAOI;;;oBAAtC;;;;;;IACF"}
|
|
@@ -19,10 +19,8 @@ _export(exports, {
|
|
|
19
19
|
return toIso3;
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
|
-
// HF model cards declare languages as ISO 639-1
|
|
23
|
-
//
|
|
24
|
-
// data (README table, https://github.com/wooorm/franc), so every value here is a code franc-min
|
|
25
|
-
// can actually emit; a declared tag with no entry here is compared as-is.
|
|
22
|
+
// HF model cards declare languages as ISO 639-1 (e.g. "zh"); franc-min reports ISO 639-3 (e.g.
|
|
23
|
+
// "cmn"). Limited to franc-min's own 82-language table (https://github.com/wooorm/franc).
|
|
26
24
|
var ISO_639_1_TO_3 = {
|
|
27
25
|
ar: 'arb',
|
|
28
26
|
am: 'amh',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/languages.ts"],"sourcesContent":["// HF model cards declare languages as ISO 639-1
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/embed/languages.ts"],"sourcesContent":["// HF model cards declare languages as ISO 639-1 (e.g. \"zh\"); franc-min reports ISO 639-3 (e.g.\n// \"cmn\"). Limited to franc-min's own 82-language table (https://github.com/wooorm/franc).\nconst ISO_639_1_TO_3: Record<string, string> = {\n ar: 'arb',\n am: 'amh',\n az: 'azj',\n be: 'bel',\n bg: 'bul',\n bn: 'ben',\n bs: 'bos',\n cs: 'ces',\n de: 'deu',\n el: 'ell',\n en: 'eng',\n es: 'spa',\n fa: 'pes',\n fr: 'fra',\n gu: 'guj',\n ha: 'hau',\n hi: 'hin',\n hr: 'hrv',\n hu: 'hun',\n id: 'ind',\n ig: 'ibo',\n it: 'ita',\n ja: 'jpn',\n jv: 'jav',\n kk: 'kaz',\n kn: 'kan',\n ko: 'kor',\n ml: 'mal',\n mr: 'mar',\n ms: 'zlm',\n my: 'mya',\n ne: 'npi',\n nl: 'nld',\n pa: 'pan',\n pl: 'pol',\n pt: 'por',\n ro: 'ron',\n ru: 'rus',\n rw: 'kin',\n si: 'sin',\n so: 'som',\n sr: 'srp',\n su: 'sun',\n sv: 'swe',\n sw: 'swh',\n ta: 'tam',\n te: 'tel',\n th: 'tha',\n tl: 'tgl',\n tr: 'tur',\n uk: 'ukr',\n ur: 'urd',\n uz: 'uzn',\n vi: 'vie',\n yo: 'yor',\n zh: 'cmn',\n zu: 'zul',\n};\n\nexport function isKnownLanguageTag(tag: string): boolean {\n return tag in ISO_639_1_TO_3;\n}\n\n// Normalizes a declared or detected language code to ISO 639-3 for comparison; strips a\n// region/script subtag (\"zh-cn\" -> \"zh\") first. Codes already in 639-3 form pass through.\nexport function toIso3(code: string): string {\n const base = code.toLowerCase().split('-')[0];\n return ISO_639_1_TO_3[base] ?? base;\n}\n\n// Languages this project measured for models whose cards declare none, so the fit check is\n// not silently off for the shipped default; asserted here because it was measured, not attested.\nexport const MEASURED_MODEL_LANGUAGES: Record<string, string[]> = {\n 'minishlab/potion-retrieval-32M': ['en'], // benchmark/reports/2026-08-27-embedding-model-selection.md\n};\n"],"names":["MEASURED_MODEL_LANGUAGES","isKnownLanguageTag","toIso3","ISO_639_1_TO_3","ar","am","az","be","bg","bn","bs","cs","de","el","en","es","fa","fr","gu","ha","hi","hr","hu","id","ig","it","ja","jv","kk","kn","ko","ml","mr","ms","my","ne","nl","pa","pl","pt","ro","ru","rw","si","so","sr","su","sv","sw","ta","te","th","tl","tr","uk","ur","uz","vi","yo","zh","zu","tag","code","base","toLowerCase","split"],"mappings":";;;;;;;;;;;QA2EaA;eAAAA;;QAbGC;eAAAA;;QAMAC;eAAAA;;;AApEhB,+FAA+F;AAC/F,0FAA0F;AAC1F,IAAMC,iBAAyC;IAC7CC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;IACJC,IAAI;AACN;AAEO,SAAS3D,mBAAmB4D,GAAW;IAC5C,OAAOA,OAAO1D;AAChB;AAIO,SAASD,OAAO4D,IAAY;QAE1B3D;IADP,IAAM4D,OAAOD,KAAKE,WAAW,GAAGC,KAAK,CAAC,IAAI,CAAC,EAAE;IAC7C,QAAO9D,uBAAAA,cAAc,CAAC4D,KAAK,cAApB5D,kCAAAA,uBAAwB4D;AACjC;AAIO,IAAM/D,2BAAqD;IAChE,kCAAkC;QAAC;KAAK;AAC1C"}
|
package/dist/cjs/embed/openai.js
CHANGED
|
@@ -230,8 +230,8 @@ function openaiProvider(model, url, keyEnv) {
|
|
|
230
230
|
];
|
|
231
231
|
case 1:
|
|
232
232
|
dims = _state.sent()[0].length;
|
|
233
|
-
//
|
|
234
|
-
//
|
|
233
|
+
// embedQuery and embedDocuments are symmetric here; per-model prefixes like nomic's
|
|
234
|
+
// search_document/search_query are not applied.
|
|
235
235
|
return [
|
|
236
236
|
2,
|
|
237
237
|
{
|