@delali/narsil 0.3.1-next.75 → 0.3.1-next.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/{capabilities-BHNksicw.d.ts → capabilities-1lEYL3WK.d.ts} +2 -2
  2. package/dist/{chunk-7ODNRREZ.mjs → chunk-4344I4MR.mjs} +168 -1
  3. package/dist/{chunk-NAMGDK45.mjs → chunk-D4EF7J3I.mjs} +31 -3
  4. package/dist/{chunk-YOVS4EV5.mjs → chunk-DFFQOA7S.mjs} +14 -10
  5. package/dist/{chunk-WL2GDSCV.mjs → chunk-G7IP3UDZ.mjs} +3 -2
  6. package/dist/chunk-GES7U2PM.mjs +68 -0
  7. package/dist/{chunk-LOARLB4F.mjs → chunk-HH6ALOUZ.mjs} +5 -5
  8. package/dist/{chunk-UOJIV2NG.mjs → chunk-NO3ABFLE.mjs} +1 -62
  9. package/dist/{chunk-AIUOAN7Y.mjs → chunk-PJU6EF22.mjs} +2 -1
  10. package/dist/{client-D4sXFS9f.d.ts → client-ZXcbSViH.d.ts} +2 -2
  11. package/dist/client.d.ts +6 -6
  12. package/dist/{config-B-GRonqw.d.ts → config-DHL2KsfD.d.ts} +1 -1
  13. package/dist/{config-C1kbq1X2.d.ts → config-DTe5EbWW.d.ts} +4 -2
  14. package/dist/{direct-executor-AVNWB73C.mjs → direct-executor-Q7PNCGZB.mjs} +6 -5
  15. package/dist/distribution.d.ts +5 -5
  16. package/dist/distribution.mjs +14 -7
  17. package/dist/{engine-DcGSd5vh.d.ts → engine-BjPBzWkA.d.ts} +1 -1
  18. package/dist/index.browser.mjs +86 -12
  19. package/dist/index.d.ts +5 -5
  20. package/dist/index.mjs +8 -7
  21. package/dist/{memory-M9kPmYP8.d.ts → memory-DW3OJ0im.d.ts} +27 -0
  22. package/dist/partial-words.mjs +3 -2
  23. package/dist/pattern.mjs +2 -1
  24. package/dist/persistence/durability/checkpoint-worker.mjs +8 -7
  25. package/dist/react.d.ts +6 -6
  26. package/dist/server.d.ts +8 -8
  27. package/dist/{tasks-A8se0J98.d.ts → tasks-BTbwBqar.d.ts} +1 -1
  28. package/dist/{thread-BSIKT6ED.mjs → thread-YOTNJEVY.mjs} +5 -4
  29. package/dist/workers/entry.mjs +3 -3
  30. package/package.json +7 -7
@@ -1,6 +1,6 @@
1
1
  import { E as EmbeddingAdapter } from './adapters-79OIa4xm.js';
2
- import { C as ClusterNamespace } from './config-B-GRonqw.js';
3
- import { h as TaskStore } from './tasks-A8se0J98.js';
2
+ import { C as ClusterNamespace } from './config-DHL2KsfD.js';
3
+ import { h as TaskStore } from './tasks-BTbwBqar.js';
4
4
 
5
5
  /**
6
6
  * Context handed to {@link OnRequestHook} for every inbound request, captured
@@ -1,3 +1,4 @@
1
+ import { tabulatedLevenshtein } from './chunk-GES7U2PM.mjs';
1
2
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
2
3
 
3
4
  // src/core/bitset.ts
@@ -72,6 +73,7 @@ var MATCHER_SIMULATION_BYTES_PER_POSITION = 16;
72
73
  var MATCHER_STATE_OVERHEAD_BYTES = 96;
73
74
  var PATTERN_WORK_FLUSH_UNITS = 65536;
74
75
  var PATTERN_RUN_CODE_POINTS = 3;
76
+ var MAX_PATTERN_TOLERANCE = 2;
75
77
  var PATTERN_TEST_OPERATORS = ["eq", "ne", "in", "nin", "startsWith", "endsWith", "contains"];
76
78
  var PATTERN_EXPRESSION_OPERATORS = ["wildcard", "regex"];
77
79
 
@@ -1598,6 +1600,160 @@ function shortlist(index, query, tally) {
1598
1600
  return candidates;
1599
1601
  }
1600
1602
 
1603
+ // src/core/pattern-index/typo-runs.ts
1604
+ var BASIC_PLANE_LAST2 = 65535;
1605
+ function isPatternTolerance(value) {
1606
+ if (value === "auto") return true;
1607
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= MAX_PATTERN_TOLERANCE;
1608
+ }
1609
+ function foldTypoText(text, host) {
1610
+ const folded = [];
1611
+ let longestFold = 0;
1612
+ for (let at = 0; at < text.length; at++) {
1613
+ const codePoint = text.codePointAt(at) ?? 0;
1614
+ if (codePoint > BASIC_PLANE_LAST2) at++;
1615
+ const before = folded.length;
1616
+ host.appendFoldedCodePoint(codePoint, folded);
1617
+ longestFold = Math.max(longestFold, folded.length - before);
1618
+ }
1619
+ return { folded, longestFold };
1620
+ }
1621
+ function distinctTypoRuns(text, limit) {
1622
+ const { folded } = text;
1623
+ const seen = /* @__PURE__ */ new Set();
1624
+ const runs = [];
1625
+ for (let at = 0; at + PATTERN_RUN_CODE_POINTS <= folded.length && seen.size < limit; at++) {
1626
+ const key = String.fromCodePoint(folded[at], folded[at + 1], folded[at + 2]);
1627
+ if (seen.has(key)) continue;
1628
+ seen.add(key);
1629
+ runs.push(folded[at], folded[at + 1], folded[at + 2]);
1630
+ }
1631
+ return runs;
1632
+ }
1633
+ function typoRunsNeeded(tolerance, longestFold) {
1634
+ return tolerance * (2 + longestFold) + 1;
1635
+ }
1636
+ function distinctTypoRunCount(text, limit) {
1637
+ return distinctTypoRuns(text, limit).length / PATTERN_RUN_CODE_POINTS;
1638
+ }
1639
+ function resolvedTypoTolerance(tolerance, text) {
1640
+ if (tolerance !== "auto") return tolerance;
1641
+ for (let candidate = MAX_PATTERN_TOLERANCE; candidate > 0; candidate--) {
1642
+ const needed = typoRunsNeeded(candidate, text.longestFold);
1643
+ if (distinctTypoRunCount(text, needed) >= needed) return candidate;
1644
+ }
1645
+ return 0;
1646
+ }
1647
+
1648
+ // src/pattern/typo.ts
1649
+ var TypoComparison = class {
1650
+ constructor(text, caseFold, tolerance, host) {
1651
+ this.caseFold = caseFold;
1652
+ this.tolerance = tolerance;
1653
+ this.host = host;
1654
+ const codePoints = [];
1655
+ appendTextCodePoints(text, caseFold, host, codePoints);
1656
+ this.text = caseFold ? String.fromCodePoint(...codePoints) : text;
1657
+ this.shortest = codePoints.length - tolerance;
1658
+ this.longest = codePoints.length + tolerance;
1659
+ }
1660
+ text;
1661
+ shortest;
1662
+ longest;
1663
+ folded = [];
1664
+ within(value, tally) {
1665
+ const compared = this.comparedForm(value);
1666
+ if (compared === null) return false;
1667
+ const { withinTolerance, cells } = tabulatedLevenshtein(this.text, compared, this.tolerance);
1668
+ tally.add(cells);
1669
+ return withinTolerance;
1670
+ }
1671
+ comparedForm(value) {
1672
+ const folded = this.folded;
1673
+ folded.length = 0;
1674
+ let counted = 0;
1675
+ for (let at = 0; at < value.length && counted <= this.longest; at++) {
1676
+ const codePoint = value.codePointAt(at) ?? 0;
1677
+ if (codePoint > BASIC_PLANE_LAST) at++;
1678
+ if (this.caseFold) {
1679
+ this.host.appendFoldedCodePoint(codePoint, folded);
1680
+ counted = folded.length;
1681
+ } else {
1682
+ counted++;
1683
+ }
1684
+ }
1685
+ if (counted > this.longest || counted < this.shortest) return null;
1686
+ return this.caseFold ? String.fromCodePoint(...folded) : value;
1687
+ }
1688
+ };
1689
+ var typoTestsBySearch = /* @__PURE__ */ new WeakMap();
1690
+ function spreadSample(runs, picks) {
1691
+ const count = runs.length / PATTERN_RUN_CODE_POINTS;
1692
+ if (count <= picks) return Uint32Array.from(runs);
1693
+ const sample = new Uint32Array(picks * PATTERN_RUN_CODE_POINTS);
1694
+ for (let pick = 0; pick < picks; pick++) {
1695
+ const run = Math.round(pick * (count - 1) / (picks - 1));
1696
+ for (let offset = 0; offset < PATTERN_RUN_CODE_POINTS; offset++) {
1697
+ sample[pick * PATTERN_RUN_CODE_POINTS + offset] = runs[run * PATTERN_RUN_CODE_POINTS + offset];
1698
+ }
1699
+ }
1700
+ return sample;
1701
+ }
1702
+ function preparedTypoTest(request) {
1703
+ const text = foldTypoText(request.text, request.host);
1704
+ const tolerance = resolvedTypoTolerance(request.tolerance, text);
1705
+ if (tolerance === 0) return null;
1706
+ const needed = typoRunsNeeded(tolerance, text.longestFold);
1707
+ return {
1708
+ needed,
1709
+ runs: spreadSample(distinctTypoRuns(text, Number.POSITIVE_INFINITY), Math.max(needed, SHORTLIST_RUN_LOOKUPS)),
1710
+ comparison: new TypoComparison(request.text, request.caseFold, tolerance, request.host)
1711
+ };
1712
+ }
1713
+ function typoTestFor(request) {
1714
+ let tests = typoTestsBySearch.get(request.meter);
1715
+ if (tests === void 0) {
1716
+ tests = /* @__PURE__ */ new Map();
1717
+ typoTestsBySearch.set(request.meter, tests);
1718
+ }
1719
+ const key = `${request.caseFold}|${request.tolerance}|${request.text}`;
1720
+ const known = tests.get(key);
1721
+ if (known !== void 0) return known;
1722
+ const test = preparedTypoTest(request);
1723
+ tests.set(key, test);
1724
+ return test;
1725
+ }
1726
+ function rarestLists(index, test, tally) {
1727
+ const { runs, needed } = test;
1728
+ if (runs.length < needed * PATTERN_RUN_CODE_POINTS) return [index.documents()];
1729
+ const lists = [];
1730
+ for (let at = 0; at < runs.length; at += PATTERN_RUN_CODE_POINTS) {
1731
+ tally.add(1);
1732
+ lists.push(index.postings(runs[at], runs[at + 1], runs[at + 2]));
1733
+ }
1734
+ lists.sort((left, right) => left.length - right.length);
1735
+ return lists.slice(0, needed);
1736
+ }
1737
+ function matchWithinTolerance(request, test, tally) {
1738
+ const { index, matches } = request;
1739
+ const checked = new Uint32Array(matches.length);
1740
+ let matched = false;
1741
+ const testValue = (value) => {
1742
+ if (!matched) matched = test.comparison.within(value, tally);
1743
+ };
1744
+ for (const list of rarestLists(index, test, tally)) {
1745
+ tally.add(list.length);
1746
+ for (const ordinal of list) {
1747
+ if (ordinal >>> 5 >= matches.length || bitsetHas(checked, ordinal)) continue;
1748
+ bitsetSet(checked, ordinal);
1749
+ if (bitsetHas(matches, ordinal)) continue;
1750
+ matched = false;
1751
+ forEachTextValue(request.valueOf(ordinal), testValue);
1752
+ if (matched) bitsetSet(matches, ordinal);
1753
+ }
1754
+ }
1755
+ }
1756
+
1601
1757
  // src/pattern/work-tally.ts
1602
1758
  var WorkTally = class {
1603
1759
  constructor(meter) {
@@ -1675,9 +1831,20 @@ function matchesText(matcher, text, caseFold, host, folded, tally) {
1675
1831
  }
1676
1832
  return matcher.matched();
1677
1833
  }
1834
+ function answeredByTypoTest(request, tally) {
1835
+ if (request.operator !== "eq" || request.tolerance === 0) return false;
1836
+ const test = typoTestFor(request);
1837
+ if (test === null) return false;
1838
+ matchWithinTolerance(request, test, tally);
1839
+ return true;
1840
+ }
1678
1841
  function matchPattern(request) {
1679
1842
  const { operator, caseFold, index, matches, host } = request;
1680
1843
  const tally = new WorkTally(request.meter);
1844
+ if (answeredByTypoTest(request, tally)) {
1845
+ tally.flush();
1846
+ return;
1847
+ }
1681
1848
  const test = operator === "wildcard" || operator === "regex" ? expressionTest(request, operator) : literalTest(request);
1682
1849
  const shortlisted = shortlist(index, test.runs, tally);
1683
1850
  const scanning = shortlisted === null;
@@ -2047,4 +2214,4 @@ var patternSearchModule = {
2047
2214
  expressionFootprint
2048
2215
  };
2049
2216
 
2050
- export { DEFAULT_PATTERN_WORK_CAP, GrowableUint32, MATCHER_CODE_POINT_BYTES, MATCHER_SIMULATION_BYTES_PER_POSITION, MATCHER_STATE_BUDGET_BYTES, MATCHER_STATE_OVERHEAD_BYTES, MAX_PATTERN_POSITIONS, MAX_PATTERN_TEXT_CODE_POINTS, PATTERN_EXPRESSION_OPERATORS, PATTERN_RUN_CODE_POINTS, PATTERN_TEST_OPERATORS, PATTERN_WORK_FLUSH_UNITS, bitsetAnd, bitsetAndInto, bitsetAndNotInto, bitsetFromSet, bitsetHas, bitsetIsEmpty, bitsetNot, bitsetOrInto, bitsetSet, createBitSet, patternSearchModule };
2217
+ export { DEFAULT_PATTERN_WORK_CAP, GrowableUint32, MATCHER_CODE_POINT_BYTES, MATCHER_SIMULATION_BYTES_PER_POSITION, MATCHER_STATE_BUDGET_BYTES, MATCHER_STATE_OVERHEAD_BYTES, MAX_PATTERN_POSITIONS, MAX_PATTERN_TEXT_CODE_POINTS, PATTERN_EXPRESSION_OPERATORS, PATTERN_RUN_CODE_POINTS, PATTERN_TEST_OPERATORS, PATTERN_WORK_FLUSH_UNITS, bitsetAnd, bitsetAndInto, bitsetAndNotInto, bitsetFromSet, bitsetHas, bitsetIsEmpty, bitsetNot, bitsetOrInto, bitsetSet, createBitSet, distinctTypoRunCount, foldTypoText, isPatternTolerance, patternSearchModule, typoRunsNeeded };
@@ -1,7 +1,8 @@
1
1
  import { MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MAX_CURSOR_LENGTH, MAX_CURSOR_ANCHOR_CODE_POINTS, RESULT_WINDOW, DEFAULT_FUZZY_PREFIX_LENGTH, MAX_FILTER_DEPTH, DEFAULT_PAGE_SIZE, MAX_FILTER_ARRAY_SIZE, GEO_UNIT_METRES, MAX_FILTER_TESTS, PREFIX_MAX_EXPANSIONS, PARTIAL_WORD_MIN_CODE_POINTS, PARTIAL_WORDS_ADDED_PER_QUERY } from './chunk-V3B24XR7.mjs';
2
- import { DEFAULT_PATTERN_WORK_CAP, patternSearchModule, PATTERN_TEST_OPERATORS, bitsetIsEmpty, PATTERN_EXPRESSION_OPERATORS, MAX_PATTERN_POSITIONS, createBitSet, bitsetSet, MAX_PATTERN_TEXT_CODE_POINTS, PATTERN_WORK_FLUSH_UNITS, MATCHER_STATE_BUDGET_BYTES } from './chunk-7ODNRREZ.mjs';
3
- import { getFlatSchema, tokenize, getFieldValueByInternalId, getFieldValueForDoc, fuzzyTermMatches } from './chunk-UOJIV2NG.mjs';
2
+ import { DEFAULT_PATTERN_WORK_CAP, patternSearchModule, PATTERN_TEST_OPERATORS, bitsetIsEmpty, PATTERN_EXPRESSION_OPERATORS, MAX_PATTERN_POSITIONS, isPatternTolerance, foldTypoText, typoRunsNeeded, distinctTypoRunCount, createBitSet, bitsetSet, MAX_PATTERN_TEXT_CODE_POINTS, PATTERN_WORK_FLUSH_UNITS, MATCHER_STATE_BUDGET_BYTES } from './chunk-4344I4MR.mjs';
3
+ import { getFlatSchema, tokenize, getFieldValueByInternalId, getFieldValueForDoc } from './chunk-NO3ABFLE.mjs';
4
4
  import { schemaFieldsOf, MAX_LATITUDE_DEGREES, MAX_LONGITUDE_DEGREES, MIN_POLYGON_POINTS, flattenSchema, parsedTypeOf, isStringValuedBase, withSortableOption, isGeopointOrVectorType, EARTH_RADIUS_METERS, RADIUS_BOX_MARGIN_RATIO, RADIUS_BOX_MARGIN_RADIANS, FULL_TURN_DEGREES, ANTIMERIDIAN_SPAN_DEGREES, PROTOTYPE_POLLUTION_KEYS, DEG_TO_RAD, LOCATION_CODE_BITS_PER_AXIS, isLatitude, isLongitude, isWordIndexedFieldType, partialFieldsOf, MAX_COVERING_CELLS } from './chunk-356UOTK2.mjs';
5
+ import { fuzzyTermMatches } from './chunk-GES7U2PM.mjs';
5
6
  import { appendFoldedCodePoint, compareCodePoints, sortModeOf, defaultSortMode, SORT_VALUE_MAX_CODE_POINTS, toReducedSortValue, readSortField, compareComparableKeys, toComparableSortValue, exceedsCodePoints, singleFoldTable, holdsUnpairedSurrogate, isSortMode, SORT_MODES, compareSortValues, foldedCodePointCount, codePointCount } from './chunk-IBR6634K.mjs';
6
7
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
7
8
 
@@ -1074,6 +1075,7 @@ function requirePatternOperands(fieldPath, filter, type) {
1074
1075
  requirePatternField(fieldPath, "caseFold", type);
1075
1076
  }
1076
1077
  requireExpressions(fieldPath, filter, type);
1078
+ if (filter.tolerance !== void 0) requirePatternField(fieldPath, "tolerance", type);
1077
1079
  if (parsedTypeOf(type)?.pattern !== true) return;
1078
1080
  const caseFold = filter.caseFold === true;
1079
1081
  for (const operator of PATTERN_TEST_OPERATORS) {
@@ -1091,6 +1093,31 @@ function requirePatternOperands(fieldPath, filter, type) {
1091
1093
  if (typeof text === "string") requirePatternText(fieldPath, operator, text, false);
1092
1094
  }
1093
1095
  }
1096
+ requireTolerance(fieldPath, filter);
1097
+ }
1098
+ function requireTolerance(fieldPath, filter) {
1099
+ const { tolerance, eq } = filter;
1100
+ if (tolerance === void 0) return;
1101
+ if (!isPatternTolerance(tolerance)) {
1102
+ invalid(`"tolerance" on field "${fieldPath}" must be 0, 1, 2, or "auto"`, fieldPath, "tolerance");
1103
+ }
1104
+ if (typeof eq !== "string") {
1105
+ invalid(
1106
+ `"tolerance" applies only to an "eq" test, while the filter on field "${fieldPath}" sets no "eq" with text`,
1107
+ fieldPath,
1108
+ "tolerance"
1109
+ );
1110
+ }
1111
+ if (tolerance === 0 || tolerance === "auto") return;
1112
+ const text = foldTypoText(eq, PATTERN_HOST);
1113
+ const requiredRuns = typoRunsNeeded(tolerance, text.longestFold);
1114
+ const distinctRuns = distinctTypoRunCount(text, requiredRuns);
1115
+ if (distinctRuns >= requiredRuns) return;
1116
+ throw new NarsilError(
1117
+ ErrorCodes.SEARCH_INVALID_FILTER,
1118
+ `A tolerance of ${tolerance} on "eq" of pattern field "${fieldPath}" needs ${requiredRuns} distinct runs of three code points in the case fold of the text, while the text holds ${distinctRuns}. Lengthen the text, lower the tolerance, or set it to "auto"`,
1119
+ { fieldPath, operator: "tolerance", requiredRuns, distinctRuns }
1120
+ );
1094
1121
  }
1095
1122
  function requireWellFormedText(fieldPath, filter) {
1096
1123
  for (const [operator, operand] of Object.entries(filter)) {
@@ -1112,6 +1139,7 @@ var TEXT_OPERATORS = ["startsWith", "endsWith"];
1112
1139
  var EQUALITY_OPERATORS = ["eq", "ne"];
1113
1140
  var LIST_OPERATORS = ["in", "nin"];
1114
1141
  var GEO_OPERATORS = ["radius", "polygon"];
1142
+ var TEST_MODIFIERS = /* @__PURE__ */ new Set(["caseFold", "tolerance"]);
1115
1143
  function invalidShape(message) {
1116
1144
  throw new NarsilError(ErrorCodes.SEARCH_INVALID_FILTER, message);
1117
1145
  }
@@ -1215,7 +1243,7 @@ function filterTestCount(expression) {
1215
1243
  function testsIn(filter) {
1216
1244
  let tests = 0;
1217
1245
  for (const [operator, operand] of Object.entries(filter)) {
1218
- if (operator === "caseFold") continue;
1246
+ if (TEST_MODIFIERS.has(operator)) continue;
1219
1247
  tests += operator === "size" && isObjectRecord(operand) ? Math.max(1, Object.keys(operand).length) : 1;
1220
1248
  }
1221
1249
  return Math.max(1, tests);
@@ -1,13 +1,14 @@
1
- import { requirePatternSearchFor, patternIndexOf, joinPatternWorkMeter, countsWithoutScores, fanOutMatchCount, fanOutQuery, sanitizeGlobalStats, computeFacets, cloneProjected, projectionKeepsField, setNestedValue, fnv1a, requirePatternSearch, PATTERN_HOST, everyValueFacetConfig, mergeFacets, undeclaredFilterField, requireValidOperands, kWayMerge, polygonContainment, polygonBoxes, radiusBoxes, locationCode, coveringRanges } from './chunk-NAMGDK45.mjs';
1
+ import { requirePatternSearchFor, patternIndexOf, joinPatternWorkMeter, countsWithoutScores, fanOutMatchCount, fanOutQuery, sanitizeGlobalStats, computeFacets, cloneProjected, projectionKeepsField, setNestedValue, fnv1a, requirePatternSearch, PATTERN_HOST, everyValueFacetConfig, mergeFacets, undeclaredFilterField, requireValidOperands, kWayMerge, polygonContainment, polygonBoxes, radiusBoxes, locationCode, coveringRanges } from './chunk-D4EF7J3I.mjs';
2
2
  import { getLanguage, detectRuntime } from './chunk-4MQ5F4IL.mjs';
3
3
  import { MAX_DOC_ID_LENGTH, GEO_UNIT_METRES } from './chunk-V3B24XR7.mjs';
4
4
  import { SCRATCH_SLOTS_PER_THREAD_POOL, osqRecordBytes, openSharedVectorField, osqBitsOf, createVectorStore, DISK_STORAGE_BLOCK_BYTES, createOsqQuantizer, magnitude, createHNSWIndex, nativeStoreScratchBytes, createOrdinalFilter, isTombstoned, addToOrdinalFilter, ordinalFilterValues, nativeScoresOf, toScore, removeFromOrdinalFilter, euclideanDistance, dotProduct, cosineSimilarityWithMagnitudes, ordinalFilterHas, STORE_CALIBRATION_GENERATION, entryForOrd, toDistance, sharedMemoryAvailable, requireWholeNeighbourLists, topLayerInParts, GRAPH_BUILD_CHUNKS_IN_FLIGHT_PER_WORKER, GRAPH_BUILD_DISPATCH_CHUNK, releaseLocksHeldBy, VECTOR_SEARCH_TIMEOUT_MS, VECTOR_SEARCH_LOAD_TIMEOUT_MS, VECTOR_INSERT_TIMEOUT_MS, VECTOR_SCRATCH_SLOTS } from './chunk-AMGDG4ZJ.mjs';
5
5
  import { noteFallback } from './chunk-2E35UM3G.mjs';
6
- import { GrowableUint32, bitsetHas, createBitSet, bitsetSet, bitsetOrInto, bitsetAndNotInto, bitsetAndInto, PATTERN_RUN_CODE_POINTS, bitsetFromSet, bitsetIsEmpty, bitsetAnd, bitsetNot } from './chunk-7ODNRREZ.mjs';
7
- import { encodePartialSpellings, countSpelling, expandTermPrefix, suggestDisplayTerms, spellingCountsOf, codePointOrder, encodeStringBlob, partialWordSearchModule, partitionDocumentFrequency } from './chunk-AIUOAN7Y.mjs';
8
- import { tokenizeOptions, getNestedValue, visitTokens, textFieldsChanged, fuzzyPrefixOf, boundedLevenshtein, getFlatSchema, tokenize, getOrCreateFieldNameIndex, tokenizeIterator, getFieldValueByInternalId } from './chunk-UOJIV2NG.mjs';
6
+ import { GrowableUint32, bitsetHas, createBitSet, bitsetSet, bitsetOrInto, bitsetAndNotInto, bitsetAndInto, PATTERN_RUN_CODE_POINTS, bitsetFromSet, isPatternTolerance, bitsetIsEmpty, bitsetAnd, bitsetNot } from './chunk-4344I4MR.mjs';
7
+ import { encodePartialSpellings, countSpelling, expandTermPrefix, suggestDisplayTerms, spellingCountsOf, codePointOrder, encodeStringBlob, partialWordSearchModule, partitionDocumentFrequency } from './chunk-PJU6EF22.mjs';
8
+ import { tokenizeOptions, getNestedValue, visitTokens, textFieldsChanged, getFlatSchema, tokenize, getOrCreateFieldNameIndex, tokenizeIterator, getFieldValueByInternalId } from './chunk-NO3ABFLE.mjs';
9
9
  import { partialFieldsOf, schemaFieldsOf, isWordIndexedBase, validateDocument, validateDocumentStrict, encodeDocument, extractVectorFieldsFromSchema, parsedTypeOf, isListBase, VINCENTY_CONVERGENCE_THRESHOLD, EARTH_RADIUS_METERS, VINCENTY_MAX_ITERATIONS, DEG_TO_RAD } from './chunk-356UOTK2.mjs';
10
10
  import { MAX_M, EARLIER_RELEASE_MIN_M, MIN_M } from './chunk-KEHK2O6P.mjs';
11
+ import { fuzzyPrefixOf, boundedLevenshtein } from './chunk-GES7U2PM.mjs';
11
12
  import { compareCodePoints, toReducedSortValue, readSortField, defaultSortMode, compareComparableValues, truncateSortString, SORT_VALUE_MAX_CODE_POINTS } from './chunk-IBR6634K.mjs';
12
13
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
13
14
  import { totalmem } from 'os';
@@ -1974,12 +1975,13 @@ function textsOf(operand) {
1974
1975
  }
1975
1976
  function evaluatePatternTests(fieldPath, filter, context, bitsets) {
1976
1977
  const caseFold = filter.caseFold === true;
1977
- const matching = (operator, texts) => {
1978
+ const matching = (operator, texts, tolerance = 0) => {
1978
1979
  const into = createBitSet(context.capacity);
1979
- for (const text of texts) context.matchPattern(fieldPath, operator, text, caseFold, into);
1980
+ for (const text of texts) context.matchPattern(fieldPath, operator, text, caseFold, tolerance, into);
1980
1981
  return into;
1981
1982
  };
1982
- if (typeof filter.eq === "string") bitsets.push(matching("eq", [filter.eq]));
1983
+ const eqTolerance = isPatternTolerance(filter.tolerance) ? filter.tolerance : 0;
1984
+ if (typeof filter.eq === "string") bitsets.push(matching("eq", [filter.eq], eqTolerance));
1983
1985
  if (typeof filter.ne === "string") bitsets.push(excluding(context, fieldPath, matching("eq", [filter.ne])));
1984
1986
  if (filter.in !== void 0) bitsets.push(matching("eq", textsOf(filter.in)));
1985
1987
  if (filter.nin !== void 0) bitsets.push(excluding(context, fieldPath, matching("eq", textsOf(filter.nin))));
@@ -2035,7 +2037,7 @@ function elementBits(context, fieldPath, parsed, value) {
2035
2037
  const { capacity } = context;
2036
2038
  if (parsed.pattern) {
2037
2039
  const matches = createBitSet(capacity);
2038
- context.matchPattern(fieldPath, "eq", value, false, matches);
2040
+ context.matchPattern(fieldPath, "eq", value, false, 0, matches);
2039
2041
  return matches;
2040
2042
  }
2041
2043
  if (typeof value === "number")
@@ -2048,7 +2050,7 @@ function anyElementBits(context, fieldPath, parsed, values) {
2048
2050
  const { capacity } = context;
2049
2051
  const union = createBitSet(capacity);
2050
2052
  if (parsed.pattern) {
2051
- for (const value of values) context.matchPattern(fieldPath, "eq", value, false, union);
2053
+ for (const value of values) context.matchPattern(fieldPath, "eq", value, false, 0, union);
2052
2054
  return union;
2053
2055
  }
2054
2056
  if (parsed.base === "enum[]") {
@@ -2195,6 +2197,7 @@ var FIELD_FILTER_OPERATORS = [
2195
2197
  "wildcard",
2196
2198
  "regex",
2197
2199
  "caseFold",
2200
+ "tolerance",
2198
2201
  "containsAll",
2199
2202
  "matchesAny",
2200
2203
  "size",
@@ -2928,13 +2931,14 @@ function buildFilterContext(state, schema, meter) {
2928
2931
  sizeIndex: (fieldPath) => state.sizeIndexes.get(fieldPath),
2929
2932
  textRangeBitset: (fieldPath, bounds) => textRangeBitsetOf(state, fieldPath, flat[fieldPath], bounds, capacity),
2930
2933
  isPatternField: (fieldPath) => patternFields.has(fieldPath),
2931
- matchPattern: (fieldPath, operator, text, caseFold, into) => {
2934
+ matchPattern: (fieldPath, operator, text, caseFold, tolerance, into) => {
2932
2935
  const index = state.patternIndexes.get(fieldPath);
2933
2936
  if (index === void 0) return;
2934
2937
  requirePatternSearch(fieldPath).matchInto({
2935
2938
  operator,
2936
2939
  text,
2937
2940
  caseFold,
2941
+ tolerance,
2938
2942
  index,
2939
2943
  matches: into,
2940
2944
  meter,
@@ -1,8 +1,9 @@
1
- import { clampRowCount, sortSignatureOf, requireSortableFields, decodePageCursor, requireMatchingCursor, resolveProjection, encodePageCursor, requireWithinResultWindow, normalizeSort, fanOutQuery, sortModesOf, applySorting, applyPagination, projectionKeepsField, countsWithoutScores, fanOutMatchCount, fnv1aBytes, requireValidFilter, createPatternWorkMeter, everyValueFacetConfig, fulltextMatches, mergeFacets, pruneStatsToQueryTerms, partitionsIn, undeclaredFieldOnStrictIndex } from './chunk-NAMGDK45.mjs';
1
+ import { clampRowCount, sortSignatureOf, requireSortableFields, decodePageCursor, requireMatchingCursor, resolveProjection, encodePageCursor, requireWithinResultWindow, normalizeSort, fanOutQuery, sortModesOf, applySorting, applyPagination, projectionKeepsField, countsWithoutScores, fanOutMatchCount, fnv1aBytes, requireValidFilter, createPatternWorkMeter, everyValueFacetConfig, fulltextMatches, mergeFacets, pruneStatsToQueryTerms, partitionsIn, undeclaredFieldOnStrictIndex } from './chunk-D4EF7J3I.mjs';
2
2
  import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, DEFAULT_LIMIT, DEFAULT_MAX_PER_GROUP, DEFAULT_SUGGEST_LIMIT, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, ABSOLUTE_WINDOWS_PATH_PATTERN, MODULE_URL_SCHEME_PATTERN, DEFAULT_LINEAR_ALPHA, MIN_LINEAR_ALPHA, MAX_LINEAR_ALPHA, DEFAULT_RANK_CONSTANT, MIN_RANK_CONSTANT, DEFAULT_OFFSET, DEFAULT_FUZZY_PREFIX_LENGTH, RESULT_WINDOW, PARTIAL_WORD_MIN_CODE_POINTS, PARTIAL_WORDS_ADDED_PER_QUERY, MAX_TOLERANCE, MAX_PREFIX_LENGTH } from './chunk-V3B24XR7.mjs';
3
3
  import { MIN_OVERSAMPLE } from './chunk-ZJ4CSAB2.mjs';
4
- import { tokenize, fuzzyTermMatches } from './chunk-UOJIV2NG.mjs';
4
+ import { tokenize } from './chunk-NO3ABFLE.mjs';
5
5
  import { partialFieldsOf, MIN_PATTERN_VALUE_LIMIT, MAX_PATTERN_VALUE_LIMIT, flattenSchema, isWordIndexedFieldType, isGeopointOrVectorType } from './chunk-356UOTK2.mjs';
6
+ import { fuzzyTermMatches } from './chunk-GES7U2PM.mjs';
6
7
  import { holdsUnpairedSurrogate, compareCodePoints, compareComparableKeys, codePointCount } from './chunk-IBR6634K.mjs';
7
8
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
8
9
 
@@ -0,0 +1,68 @@
1
+ // src/core/fuzzy.ts
2
+ var FIRST_SURROGATE = 55296;
3
+ var LAST_SURROGATE = 57343;
4
+ var LAST_BASIC_PLANE_CODE_POINT = 65535;
5
+ function hasSurrogate(text) {
6
+ for (let index = 0; index < text.length; index++) {
7
+ const unit = text.charCodeAt(index);
8
+ if (unit >= FIRST_SURROGATE && unit <= LAST_SURROGATE) return true;
9
+ }
10
+ return false;
11
+ }
12
+ function fuzzyPrefixOf(queryTerm, prefixLength) {
13
+ let end = 0;
14
+ for (let counted = 0; counted < prefixLength && end < queryTerm.length; counted++) {
15
+ const codePoint = queryTerm.codePointAt(end);
16
+ end += codePoint !== void 0 && codePoint > LAST_BASIC_PLANE_CODE_POINT ? 2 : 1;
17
+ }
18
+ return queryTerm.slice(0, end);
19
+ }
20
+ function fuzzyTermMatches(queryTerm, indexTerm, tolerance, prefixLength) {
21
+ if (queryTerm === indexTerm) return true;
22
+ if (tolerance <= 0) return false;
23
+ if (!indexTerm.startsWith(fuzzyPrefixOf(queryTerm, prefixLength))) return false;
24
+ return boundedLevenshtein(queryTerm, indexTerm, tolerance).withinTolerance;
25
+ }
26
+ function boundedLevenshtein(a, b, tolerance) {
27
+ if (tolerance < 0) return { distance: -1, withinTolerance: false, cells: 0 };
28
+ if (a === b) return { distance: 0, withinTolerance: true, cells: 0 };
29
+ return tabulatedLevenshtein(a, b, tolerance);
30
+ }
31
+ function tabulatedLevenshtein(a, b, tolerance) {
32
+ if (tolerance < 0) return { distance: -1, withinTolerance: false, cells: 0 };
33
+ if (hasSurrogate(a) || hasSurrogate(b)) return bandedDistance(Array.from(a), Array.from(b), tolerance);
34
+ return bandedDistance(a, b, tolerance);
35
+ }
36
+ function bandedDistance(a, b, tolerance) {
37
+ const m = a.length;
38
+ const n = b.length;
39
+ const beyond = tolerance + 1;
40
+ if (Math.abs(m - n) > tolerance) return { distance: beyond, withinTolerance: false, cells: 0 };
41
+ let previous = new Uint32Array(n + 1).fill(beyond);
42
+ let current = new Uint32Array(n + 1).fill(beyond);
43
+ const firstRowEnd = Math.min(n, tolerance);
44
+ for (let j = 0; j <= firstRowEnd; j++) previous[j] = j;
45
+ let cells = 0;
46
+ for (let i = 1; i <= m; i++) {
47
+ const low = Math.max(1, i - tolerance);
48
+ const high = Math.min(n, i + tolerance);
49
+ current[low - 1] = low === 1 ? i : beyond;
50
+ let rowMin = current[low - 1];
51
+ const character = a[i - 1];
52
+ if (high >= low) cells += high - low + 1;
53
+ for (let j = low; j <= high; j++) {
54
+ const substitution = previous[j - 1] + (character === b[j - 1] ? 0 : 1);
55
+ const cell = Math.min(previous[j] + 1, current[j - 1] + 1, substitution, beyond);
56
+ current[j] = cell;
57
+ if (cell < rowMin) rowMin = cell;
58
+ }
59
+ if (rowMin > tolerance) return { distance: beyond, withinTolerance: false, cells };
60
+ const finished = previous;
61
+ previous = current;
62
+ current = finished;
63
+ }
64
+ const distance = previous[n];
65
+ return { distance, withinTolerance: distance <= tolerance, cells };
66
+ }
67
+
68
+ export { boundedLevenshtein, fuzzyPrefixOf, fuzzyTermMatches, tabulatedLevenshtein };
@@ -1,14 +1,14 @@
1
- import { validateWorkerConfig, validateIndexName, validatePatternValueLimit, requireSurfaceFormsForPartialFields, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-WL2GDSCV.mjs';
1
+ import { validateWorkerConfig, validateIndexName, validatePatternValueLimit, requireSurfaceFormsForPartialFields, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-G7IP3UDZ.mjs';
2
2
  import { ReplicationMessageTypes } from './chunk-GCM3JFVA.mjs';
3
3
  import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, restoredConfigFields, restoredEmbedding, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, requireDocumentObject, admitInsert, asBatchInsertError, requireMatchingDocId, embedDocumentFields, assertDocumentCarriesMappedVectors, admitBufferedUpsert, createPendingAdmissions, recordPendingAdmission } from './chunk-BT62MUM5.mjs';
4
- import { NATIVE_CRC32_MIN_BYTES, generateId, decodeEveryStoredDocument, createSharedFrozenSegment, shareSegmentArrays, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, requirePartialWordSearchFor, MAX_FILE_BYTES, resolveWorkerEntry, missingWorkerEntry, readHeapStatistics, nodeThreadId, CHECKSUM_YIELD_CHUNK_BYTES, createPartitionManager, buildSegmentPayload, resolvePartitionInsertOptions, createFrozenSegment, resolveRequestThreadCount, vectorsPerFile, vectorsToBytes, VECTOR_FILE_PAYLOAD_VERSION, deadBitsWhere, NO_LIVE_VECTOR_AT_POSITION, createPartitionIndex, selectionKeeps, decodeMapWithoutFields, isCompositePartition, segmentArraysOf, mergeSegmentContents, survivorDocumentsOf, partitionStateOf, VECTOR_FILE_MAX_VECTORS, deadBytesFor, resolveIndexAnalysis, mergeFrozenSegments, workerResourceLimits, decodeVectorIndexParts, bytesToVectors, freezeSegmentShared, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, SHUTDOWN_TIMEOUT_MS, decodeVectorFilePayload, decodeVectorGraphPartPayload, assembleGraphParts, countDead, encodeSegmentState, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, VALID_HNSW_METRICS, spawnNodeWorker, decodeVectorGraphPayload, graphPartsOfEarlierPayload, decodeStoredDocument, isDead } from './chunk-YOVS4EV5.mjs';
5
- import { requirePatternSearchFor, collectQueryTermStats, mergePartitionStats, oversampledFacetConfig, fnv1a, availablePatternSearch, kWayMerge, mergeFacets, PATTERN_HOST, setNestedValue } from './chunk-NAMGDK45.mjs';
4
+ import { NATIVE_CRC32_MIN_BYTES, generateId, decodeEveryStoredDocument, createSharedFrozenSegment, shareSegmentArrays, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, requirePartialWordSearchFor, MAX_FILE_BYTES, resolveWorkerEntry, missingWorkerEntry, readHeapStatistics, nodeThreadId, CHECKSUM_YIELD_CHUNK_BYTES, createPartitionManager, buildSegmentPayload, resolvePartitionInsertOptions, createFrozenSegment, resolveRequestThreadCount, vectorsPerFile, vectorsToBytes, VECTOR_FILE_PAYLOAD_VERSION, deadBitsWhere, NO_LIVE_VECTOR_AT_POSITION, createPartitionIndex, selectionKeeps, decodeMapWithoutFields, isCompositePartition, segmentArraysOf, mergeSegmentContents, survivorDocumentsOf, partitionStateOf, VECTOR_FILE_MAX_VECTORS, deadBytesFor, resolveIndexAnalysis, mergeFrozenSegments, workerResourceLimits, decodeVectorIndexParts, bytesToVectors, freezeSegmentShared, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, SHUTDOWN_TIMEOUT_MS, decodeVectorFilePayload, decodeVectorGraphPartPayload, assembleGraphParts, countDead, encodeSegmentState, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, VALID_HNSW_METRICS, spawnNodeWorker, decodeVectorGraphPayload, graphPartsOfEarlierPayload, decodeStoredDocument, isDead } from './chunk-DFFQOA7S.mjs';
5
+ import { requirePatternSearchFor, collectQueryTermStats, mergePartitionStats, oversampledFacetConfig, fnv1a, availablePatternSearch, kWayMerge, mergeFacets, PATTERN_HOST, setNestedValue } from './chunk-D4EF7J3I.mjs';
6
6
  import { detectRuntime, getLanguage } from './chunk-4MQ5F4IL.mjs';
7
7
  import { MAX_INDEX_CONFIGURATION_BYTES, STATISTICS_BROADCAST_INTERVAL_MS, MAX_SWEEP_INTERVAL_MS, MIN_SWEEP_INTERVAL_MS, HEAP_PRESSURE_WARNING_FRACTION, MAX_EXPORT_LINE_BYTES, IMPORT_BATCH_DOCUMENTS, FOREIGN_STATS_TTL_MS, MAX_IMPORT_REFUSALS_REPORTED, BATCH_CHUNK_SIZE, MIN_DOCUMENTS_FOR_SEGMENTS, HEAP_PRESSURE_REARM_FRACTION, EXPORT_CHUNK_BYTES } from './chunk-V3B24XR7.mjs';
8
8
  import { releaseLocksHeldBy } from './chunk-AMGDG4ZJ.mjs';
9
9
  import { requireSearchBackendSettings } from './chunk-2E35UM3G.mjs';
10
- import { DEFAULT_PATTERN_WORK_CAP, MATCHER_STATE_BUDGET_BYTES, PATTERN_TEST_OPERATORS, PATTERN_EXPRESSION_OPERATORS, MATCHER_CODE_POINT_BYTES, MATCHER_SIMULATION_BYTES_PER_POSITION, MATCHER_STATE_OVERHEAD_BYTES } from './chunk-7ODNRREZ.mjs';
11
- import { getNestedValue, parseVectorDimension } from './chunk-UOJIV2NG.mjs';
10
+ import { DEFAULT_PATTERN_WORK_CAP, MATCHER_STATE_BUDGET_BYTES, PATTERN_TEST_OPERATORS, PATTERN_EXPRESSION_OPERATORS, MATCHER_CODE_POINT_BYTES, MATCHER_SIMULATION_BYTES_PER_POSITION, MATCHER_STATE_OVERHEAD_BYTES } from './chunk-4344I4MR.mjs';
11
+ import { getNestedValue, parseVectorDimension } from './chunk-NO3ABFLE.mjs';
12
12
  import { extractVectorFieldsFromSchema, messagePackUpperBoundBytes, validateSchema, requireCreatableSchema, validateVectorPromotion, validateVectorStorage, raiseEarlierReleaseGraphSetting, flattenSchema, isSingleStringFieldType, requireValidFieldTypes, encodeDocument, VECTOR_PATTERN, schemaFieldsOf, MAX_DOCUMENT_NESTING_DEPTH, isQuantizationMode, isStorageMode, validateRequiredFields, requireDocumentWithinSizeLimit, validateDocument, validateDocumentStrict } from './chunk-356UOTK2.mjs';
13
13
  import { MIN_M } from './chunk-KEHK2O6P.mjs';
14
14
  import { compareCodePoints, foldedCodePointCount, codePointCount } from './chunk-IBR6634K.mjs';
@@ -457,67 +457,6 @@ function* tokenizeIterator(text, language, options) {
457
457
  }
458
458
  }
459
459
 
460
- // src/core/fuzzy.ts
461
- var FIRST_SURROGATE = 55296;
462
- var LAST_SURROGATE = 57343;
463
- var LAST_BASIC_PLANE_CODE_POINT = 65535;
464
- function hasSurrogate(text) {
465
- for (let index = 0; index < text.length; index++) {
466
- const unit = text.charCodeAt(index);
467
- if (unit >= FIRST_SURROGATE && unit <= LAST_SURROGATE) return true;
468
- }
469
- return false;
470
- }
471
- function fuzzyPrefixOf(queryTerm, prefixLength) {
472
- let end = 0;
473
- for (let counted = 0; counted < prefixLength && end < queryTerm.length; counted++) {
474
- const codePoint = queryTerm.codePointAt(end);
475
- end += codePoint !== void 0 && codePoint > LAST_BASIC_PLANE_CODE_POINT ? 2 : 1;
476
- }
477
- return queryTerm.slice(0, end);
478
- }
479
- function fuzzyTermMatches(queryTerm, indexTerm, tolerance, prefixLength) {
480
- if (queryTerm === indexTerm) return true;
481
- if (tolerance <= 0) return false;
482
- if (!indexTerm.startsWith(fuzzyPrefixOf(queryTerm, prefixLength))) return false;
483
- return boundedLevenshtein(queryTerm, indexTerm, tolerance).withinTolerance;
484
- }
485
- function boundedLevenshtein(a, b, tolerance) {
486
- if (tolerance < 0) return { distance: -1, withinTolerance: false };
487
- if (a === b) return { distance: 0, withinTolerance: true };
488
- if (hasSurrogate(a) || hasSurrogate(b)) return bandedDistance(Array.from(a), Array.from(b), tolerance);
489
- return bandedDistance(a, b, tolerance);
490
- }
491
- function bandedDistance(a, b, tolerance) {
492
- const m = a.length;
493
- const n = b.length;
494
- const beyond = tolerance + 1;
495
- if (Math.abs(m - n) > tolerance) return { distance: beyond, withinTolerance: false };
496
- let previous = new Uint32Array(n + 1).fill(beyond);
497
- let current = new Uint32Array(n + 1).fill(beyond);
498
- const firstRowEnd = Math.min(n, tolerance);
499
- for (let j = 0; j <= firstRowEnd; j++) previous[j] = j;
500
- for (let i = 1; i <= m; i++) {
501
- const low = Math.max(1, i - tolerance);
502
- const high = Math.min(n, i + tolerance);
503
- current[low - 1] = low === 1 ? i : beyond;
504
- let rowMin = current[low - 1];
505
- const character = a[i - 1];
506
- for (let j = low; j <= high; j++) {
507
- const substitution = previous[j - 1] + (character === b[j - 1] ? 0 : 1);
508
- const cell = Math.min(previous[j] + 1, current[j - 1] + 1, substitution, beyond);
509
- current[j] = cell;
510
- if (cell < rowMin) rowMin = cell;
511
- }
512
- if (rowMin > tolerance) return { distance: beyond, withinTolerance: false };
513
- const finished = previous;
514
- previous = current;
515
- current = finished;
516
- }
517
- const distance = previous[n];
518
- return { distance, withinTolerance: distance <= tolerance };
519
- }
520
-
521
460
  // src/core/partition/utils.ts
522
461
  function getOrCreateFieldNameIndex(table, fieldName) {
523
462
  const existing = table.indexMap.get(fieldName);
@@ -590,4 +529,4 @@ function getFieldValueByInternalId(docStore, internalId, fieldPath) {
590
529
  return getFieldValueForDoc(docStore, externalId, fieldPath);
591
530
  }
592
531
 
593
- export { boundedLevenshtein, clearNormalizationCache, configureNormalizationCache, fuzzyPrefixOf, fuzzyTermMatches, getFieldValueByInternalId, getFieldValueForDoc, getFlatSchema, getNestedValue, getNormalizationCacheSize, getOrCreateFieldNameIndex, parseVectorDimension, resetNormalizationCache, textFieldsChanged, tokenize, tokenizeIterator, tokenizeOptions, visitTokens };
532
+ export { clearNormalizationCache, configureNormalizationCache, getFieldValueByInternalId, getFieldValueForDoc, getFlatSchema, getNestedValue, getNormalizationCacheSize, getOrCreateFieldNameIndex, parseVectorDimension, resetNormalizationCache, textFieldsChanged, tokenize, tokenizeIterator, tokenizeOptions, visitTokens };
@@ -1,4 +1,5 @@
1
- import { tokenizeOptions, getNestedValue, tokenizeIterator, fuzzyTermMatches } from './chunk-UOJIV2NG.mjs';
1
+ import { tokenizeOptions, getNestedValue, tokenizeIterator } from './chunk-NO3ABFLE.mjs';
2
+ import { fuzzyTermMatches } from './chunk-GES7U2PM.mjs';
2
3
  import { compareCodePoints } from './chunk-IBR6634K.mjs';
3
4
 
4
5
  // src/core/partition/suggestions.ts
@@ -1,6 +1,6 @@
1
1
  import { P as PartitionConfig, A as AnyDocument, a as InsertOptions, W as WriteOptions } from './schema-DgyDijhf.js';
2
- import { V as VectorMaintenanceResult, B as BatchResult, L as ListParams, h as ListResult, I as IndexInfo, g as IndexStats, P as PartitionStatsResult, Q as QueryParams, e as QueryResult, j as PreflightResult, k as SuggestParams, l as SuggestResult } from './memory-M9kPmYP8.js';
3
- import { e as TaskRecord, M as MemoryStatsResponse, b as ImportResult, H as HttpIndexConfig, c as TaskListQuery, T as TaskListPage } from './tasks-A8se0J98.js';
2
+ import { V as VectorMaintenanceResult, B as BatchResult, L as ListParams, h as ListResult, I as IndexInfo, g as IndexStats, P as PartitionStatsResult, Q as QueryParams, e as QueryResult, j as PreflightResult, k as SuggestParams, l as SuggestResult } from './memory-DW3OJ0im.js';
3
+ import { e as TaskRecord, M as MemoryStatsResponse, b as ImportResult, H as HttpIndexConfig, c as TaskListQuery, T as TaskListPage } from './tasks-BTbwBqar.js';
4
4
 
5
5
  /**
6
6
  * This is the `fetch` implementation the client sends every request through.
package/dist/client.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, N as NarsilError, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-M9kPmYP8.js';
2
- export { A as ASYNC_IMPORT_CAPABILITY, D as DOCUMENT_EXPORT_CAPABILITY, E as ErrorEnvelope, I as INDEX_LIFECYCLE_CAPABILITY, R as REBUILD_ANALYSIS_CAPABILITY, S as SERVER_CAPABILITIES, T as TASK_CANCEL_CAPABILITY, a as TASK_FILTER_CAPABILITY } from './capabilities-BHNksicw.js';
3
- export { C as CapabilitiesResponse, a as CreateIndexEmbedding, H as HttpIndexConfig, I as ImportError, b as ImportResult, M as MemoryStatsResponse, T as TaskListPage, c as TaskListQuery, d as TaskProgress, e as TaskRecord, f as TaskStatus, g as TaskType } from './tasks-A8se0J98.js';
4
- export { A as AdminOperations, B as BulkOperations, D as DocumentOperations, F as FetchFunction, I as ImportSource, a as IndexOperations, N as NarsilClient, b as NarsilClientOptions, P as PutResult, R as RequestOptions, S as SearchOperations, c as ServerOperations, d as ServerVersion, T as TaskOperations, W as WaitForTaskOptions, e as createNarsilClient } from './client-D4sXFS9f.js';
1
+ export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, N as NarsilError, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-DW3OJ0im.js';
2
+ export { A as ASYNC_IMPORT_CAPABILITY, D as DOCUMENT_EXPORT_CAPABILITY, E as ErrorEnvelope, I as INDEX_LIFECYCLE_CAPABILITY, R as REBUILD_ANALYSIS_CAPABILITY, S as SERVER_CAPABILITIES, T as TASK_CANCEL_CAPABILITY, a as TASK_FILTER_CAPABILITY } from './capabilities-1lEYL3WK.js';
3
+ export { C as CapabilitiesResponse, a as CreateIndexEmbedding, H as HttpIndexConfig, I as ImportError, b as ImportResult, M as MemoryStatsResponse, T as TaskListPage, c as TaskListQuery, d as TaskProgress, e as TaskRecord, f as TaskStatus, g as TaskType } from './tasks-BTbwBqar.js';
4
+ export { A as AdminOperations, B as BulkOperations, D as DocumentOperations, F as FetchFunction, I as ImportSource, a as IndexOperations, N as NarsilClient, b as NarsilClientOptions, P as PutResult, R as RequestOptions, S as SearchOperations, c as ServerOperations, d as ServerVersion, T as TaskOperations, W as WaitForTaskOptions, e as createNarsilClient } from './client-ZXcbSViH.js';
5
5
  import './schema-DgyDijhf.js';
6
6
  import './adapters-79OIa4xm.js';
7
- import './config-B-GRonqw.js';
8
- import './config-C1kbq1X2.js';
7
+ import './config-DHL2KsfD.js';
8
+ import './config-DTe5EbWW.js';
9
9
  import './types-ChrVy4lH.js';
10
10
  import './types-Cb9kiY5P.js';
@@ -1,4 +1,4 @@
1
- import { N as NarsilConfig } from './config-C1kbq1X2.js';
1
+ import { N as NarsilConfig } from './config-DTe5EbWW.js';
2
2
  import { A as AllocationTable, N as NodeRole, a as NodeRegistration, C as ClusterCoordinator, b as NodeCapacity } from './types-ChrVy4lH.js';
3
3
  import { N as NodeTransport } from './types-Cb9kiY5P.js';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import { P as PersistenceAdapter, I as InvalidationAdapter, E as EmbeddingAdapter } from './adapters-79OIa4xm.js';
2
- import { Q as QueryParams, e as QueryResult, f as NarsilEventHandlers } from './memory-M9kPmYP8.js';
2
+ import { Q as QueryParams, e as QueryResult, f as NarsilEventHandlers } from './memory-DW3OJ0im.js';
3
3
  import { I as IndexConfig, A as AnyDocument } from './schema-DgyDijhf.js';
4
4
 
5
5
  /**
@@ -214,7 +214,9 @@ interface NarsilConfig {
214
214
  * each step of its matcher. For a text whose case fold is shorter than three
215
215
  * code points, it counts each document that it checks as an entry that it
216
216
  * reads. It counts an `in` or `nin` test as one `eq` test for each distinct
217
- * value in its list. Once the count passes the cap, the engine throws
217
+ * value in its list. For an `eq` test with a `tolerance`, it also adds one
218
+ * unit for each cell that it fills in the table of edit distances between
219
+ * the text and a value. Once the count passes the cap, the engine throws
218
220
  * `SEARCH_WORK_CAP_EXCEEDED`. The cap
219
221
  * defaults to 25,000,000 units. For any value other than a whole number from
220
222
  * 1 to `Number.MAX_SAFE_INTEGER`, {@link createNarsil} throws
@@ -1,16 +1,17 @@
1
- export { createDirectExecutor } from './chunk-YOVS4EV5.mjs';
2
- import './chunk-NAMGDK45.mjs';
1
+ export { createDirectExecutor } from './chunk-DFFQOA7S.mjs';
2
+ import './chunk-D4EF7J3I.mjs';
3
3
  import './chunk-4MQ5F4IL.mjs';
4
4
  import './chunk-V3B24XR7.mjs';
5
5
  import './chunk-TGP5M5R7.mjs';
6
6
  import './chunk-AMGDG4ZJ.mjs';
7
7
  import './chunk-ZJ4CSAB2.mjs';
8
8
  import './chunk-2E35UM3G.mjs';
9
- import './chunk-7ODNRREZ.mjs';
10
- import './chunk-AIUOAN7Y.mjs';
11
- import './chunk-UOJIV2NG.mjs';
9
+ import './chunk-4344I4MR.mjs';
10
+ import './chunk-PJU6EF22.mjs';
11
+ import './chunk-NO3ABFLE.mjs';
12
12
  import './chunk-356UOTK2.mjs';
13
13
  import './chunk-KEHK2O6P.mjs';
14
+ import './chunk-GES7U2PM.mjs';
14
15
  import './chunk-U2BKYEC7.mjs';
15
16
  import './chunk-IBR6634K.mjs';
16
17
  import './chunk-I64LXKO3.mjs';
@@ -1,12 +1,12 @@
1
- import { a as CreateIndexOptions, C as ClusterNamespace, b as ClusterNodeConfig } from './config-B-GRonqw.js';
2
- export { c as ClusterControllerConfig, d as ClusterNodeInfo, e as ClusterQueryConfig, N as NodeReadiness, R as ReplicationConfig } from './config-B-GRonqw.js';
3
- import { B as BatchResult, L as ListParams, h as ListResult, k as SuggestParams, l as SuggestResult, Q as QueryParams, j as PreflightResult, g as IndexStats, P as PartitionStatsResult, M as MemoryStats, m as NarsilEventMap, e as QueryResult } from './memory-M9kPmYP8.js';
1
+ import { a as CreateIndexOptions, C as ClusterNamespace, b as ClusterNodeConfig } from './config-DHL2KsfD.js';
2
+ export { c as ClusterControllerConfig, d as ClusterNodeInfo, e as ClusterQueryConfig, N as NodeReadiness, R as ReplicationConfig } from './config-DHL2KsfD.js';
3
+ import { B as BatchResult, L as ListParams, h as ListResult, k as SuggestParams, l as SuggestResult, Q as QueryParams, j as PreflightResult, g as IndexStats, P as PartitionStatsResult, M as MemoryStats, m as NarsilEventMap, e as QueryResult } from './memory-DW3OJ0im.js';
4
4
  import { I as IndexConfig, A as AnyDocument, a as InsertOptions } from './schema-DgyDijhf.js';
5
5
  import { b as NodeCapacity, N as NodeRole } from './types-ChrVy4lH.js';
6
6
  export { c as AllocationConstraints, d as AllocationEvent, A as AllocationTable, C as ClusterCoordinator, e as NodeEvent, a as NodeRegistration, P as PartitionAssignment, f as PartitionState, S as SchemaEvent, U as UnassignedReason } from './types-ChrVy4lH.js';
7
- import { N as Narsil } from './engine-DcGSd5vh.js';
7
+ import { N as Narsil } from './engine-BjPBzWkA.js';
8
8
  export { L as ListenHandler, N as NodeTransport, R as RespondFn, T as TransportConfig, a as TransportMessage } from './types-Cb9kiY5P.js';
9
- import './config-C1kbq1X2.js';
9
+ import './config-DTe5EbWW.js';
10
10
  import './adapters-79OIa4xm.js';
11
11
 
12
12
  /**
@@ -1,22 +1,23 @@
1
1
  import { MAX_MESSAGE_SIZE_BYTES } from './chunk-UNEEFTEU.mjs';
2
2
  import { validateIndexName, indexConfigKey, withPartitionCount, indexSettingsOf, putIndexMetadata, getIndexMetadata, getClusterIndexConfig } from './chunk-PXDY5VRT.mjs';
3
- import { requireKnownConfig, resolveRunnableConfig, createEngineCore, startEngineCore, createNarsilFromCore, runEngineQueryStats, runEngineListDocuments, runEngineSuggest, runEnginePreflight, runEngineQuery, createEngineIndex, buildArchiveFromMemory, indexMetadataOf, encodeIndexConfiguration, archiveStream, applyIndexEntry, applyDeleteEntry, requireConfigurationWithinSizeLimit, validateEntryBatchPayload, createAckMessage, validateEntryPayload, validateForwardBatchPayload, createForwardBatchResultMessage, memoryCheckpointStore, readSnapshotArchive, createByteReader, openChecksummedEnvelope, loadPartitionSegments, readListedFile, createForwardBatchMessage, validateForwardBatchResultPayload, createForwardMessage, validateReplicationEntry, crc32Init, crc32Final, crc32Update, computeEntryChecksum, createEntryMessage, createEntryBatchMessage, createInsyncConfirmMessage, validateAckPayload, createInsyncRemoveMessage, validateInsyncConfirmPayload, createInsyncAddMessage } from './chunk-LOARLB4F.mjs';
4
- import { now, listBindingOf, requireSurfaceFormsForPartialFields, queryBindingOf, hitsKeptPerGroup, clampLimit, resolveHybridFusion, dedupePinnedEntries, foldGroupReducer } from './chunk-WL2GDSCV.mjs';
3
+ import { requireKnownConfig, resolveRunnableConfig, createEngineCore, startEngineCore, createNarsilFromCore, runEngineQueryStats, runEngineListDocuments, runEngineSuggest, runEnginePreflight, runEngineQuery, createEngineIndex, buildArchiveFromMemory, indexMetadataOf, encodeIndexConfiguration, archiveStream, applyIndexEntry, applyDeleteEntry, requireConfigurationWithinSizeLimit, validateEntryBatchPayload, createAckMessage, validateEntryPayload, validateForwardBatchPayload, createForwardBatchResultMessage, memoryCheckpointStore, readSnapshotArchive, createByteReader, openChecksummedEnvelope, loadPartitionSegments, readListedFile, createForwardBatchMessage, validateForwardBatchResultPayload, createForwardMessage, validateReplicationEntry, crc32Init, crc32Final, crc32Update, computeEntryChecksum, createEntryMessage, createEntryBatchMessage, createInsyncConfirmMessage, validateAckPayload, createInsyncRemoveMessage, validateInsyncConfirmPayload, createInsyncAddMessage } from './chunk-HH6ALOUZ.mjs';
4
+ import { now, listBindingOf, requireSurfaceFormsForPartialFields, queryBindingOf, hitsKeptPerGroup, clampLimit, resolveHybridFusion, dedupePinnedEntries, foldGroupReducer } from './chunk-G7IP3UDZ.mjs';
5
5
  import { ReplicationMessageTypes, TransportErrorCodes, ClusterMessageTypes, QueryMessageTypes, TransportError } from './chunk-GCM3JFVA.mjs';
6
6
  import { providedDocId, MAX_PARTITION_COUNT, MAX_REPLICATION_FACTOR, WIRE_BATCH_BUDGET } from './chunk-BT62MUM5.mjs';
7
- import { generateId, decodeVectorFilePayload, bytesToVectors, isDead, FILTER_EXPRESSION_KEYS, FIELD_FILTER_OPERATORS } from './chunk-YOVS4EV5.mjs';
8
- import { oversampledShardSize, resolveProjection, clampRowCount, sortSignatureOf, requireMatchingCursor, decodePageCursor, normalizeSort, sortModesOf, encodePageCursor, applyProjection, readSortValues, requireWithinResultWindow, fnv1a, sortSignatureEntry, filterTestCount, fnv1aUint32s, mergePartitionStats } from './chunk-NAMGDK45.mjs';
7
+ import { generateId, decodeVectorFilePayload, bytesToVectors, isDead, FILTER_EXPRESSION_KEYS, FIELD_FILTER_OPERATORS } from './chunk-DFFQOA7S.mjs';
8
+ import { oversampledShardSize, resolveProjection, clampRowCount, sortSignatureOf, requireMatchingCursor, decodePageCursor, normalizeSort, sortModesOf, encodePageCursor, applyProjection, readSortValues, requireWithinResultWindow, fnv1a, sortSignatureEntry, filterTestCount, fnv1aUint32s, mergePartitionStats } from './chunk-D4EF7J3I.mjs';
9
9
  import { getLanguage } from './chunk-4MQ5F4IL.mjs';
10
10
  import { DEFAULT_SUGGEST_LIMIT, MAX_SUGGEST_LIMIT, DEFAULT_PAGE_SIZE, MAX_SUGGEST_SCATTER_LIMIT, MAX_INDEX_NAME_LENGTH, MAX_FILTER_DEPTH, MAX_FILTER_TESTS, MAX_SORT_FIELDS, MAX_DOC_ID_LENGTH, MAX_CURSOR_LENGTH, MAX_TOLERANCE, SUGGEST_OVERSAMPLE_FACTOR, SUGGEST_OVERSAMPLE_PADDING, INDEX_NAME_PATTERN, MAX_PREFIX_LENGTH, RESULT_WINDOW, MAX_FILTER_ARRAY_SIZE } from './chunk-V3B24XR7.mjs';
11
11
  import './chunk-TGP5M5R7.mjs';
12
12
  import './chunk-AMGDG4ZJ.mjs';
13
13
  import { MIN_OVERSAMPLE } from './chunk-ZJ4CSAB2.mjs';
14
14
  import './chunk-2E35UM3G.mjs';
15
- import './chunk-7ODNRREZ.mjs';
16
- import './chunk-AIUOAN7Y.mjs';
17
- import './chunk-UOJIV2NG.mjs';
15
+ import { isPatternTolerance } from './chunk-4344I4MR.mjs';
16
+ import './chunk-PJU6EF22.mjs';
17
+ import './chunk-NO3ABFLE.mjs';
18
18
  import { validateSchema, requireCreatableSchema, encodeDocument, MAX_STORED_VECTOR_DIMENSION, MIN_POLYGON_POINTS, isLatitude, MAX_LATITUDE_DEGREES, isLongitude, MAX_LONGITUDE_DEGREES, MAX_NESTING_DEPTH } from './chunk-356UOTK2.mjs';
19
19
  import './chunk-KEHK2O6P.mjs';
20
+ import './chunk-GES7U2PM.mjs';
20
21
  import './chunk-U2BKYEC7.mjs';
21
22
  import { compareCodePoints, toComparableSortValue, compareComparableKeys, isSortMode, SORT_MODES, exceedsCodePoints, compareSortValues } from './chunk-IBR6634K.mjs';
22
23
  import './chunk-POWOTUKJ.mjs';
@@ -6781,6 +6782,12 @@ function validateLeafOperator(opKey, opValue, leafLabel, errorCode) {
6781
6782
  validateBooleanOperand(opValue, opLabel, errorCode);
6782
6783
  return;
6783
6784
  }
6785
+ if (opKey === "tolerance") {
6786
+ if (!isPatternTolerance(opValue)) {
6787
+ throwInvalid(errorCode, `Invalid payload: "${opLabel}" must be 0, 1, 2, or "auto"`);
6788
+ }
6789
+ return;
6790
+ }
6784
6791
  if (opKey === "in" || opKey === "nin") {
6785
6792
  validateStringList(opValue, opLabel, errorCode);
6786
6793
  return;
@@ -1,5 +1,5 @@
1
1
  import { E as EmbeddingAdapter } from './adapters-79OIa4xm.js';
2
- import { B as BatchResult, I as IndexInfo, g as IndexStats, P as PartitionStatsResult, L as ListParams, h as ListResult, Q as QueryParams, e as QueryResult, j as PreflightResult, k as SuggestParams, l as SuggestResult, D as DocumentImportResult, M as MemoryStats, V as VectorMaintenanceResult, m as NarsilEventMap } from './memory-M9kPmYP8.js';
2
+ import { B as BatchResult, I as IndexInfo, g as IndexStats, P as PartitionStatsResult, L as ListParams, h as ListResult, Q as QueryParams, e as QueryResult, j as PreflightResult, k as SuggestParams, l as SuggestResult, D as DocumentImportResult, M as MemoryStats, V as VectorMaintenanceResult, m as NarsilEventMap } from './memory-DW3OJ0im.js';
3
3
  import { A as AnyDocument, a as InsertOptions, W as WriteOptions, I as IndexConfig, P as PartitionConfig } from './schema-DgyDijhf.js';
4
4
 
5
5
  /**
@@ -2631,6 +2631,7 @@ var MATCHER_SIMULATION_BYTES_PER_POSITION = 16;
2631
2631
  var MATCHER_STATE_OVERHEAD_BYTES = 96;
2632
2632
  var PATTERN_WORK_FLUSH_UNITS = 65536;
2633
2633
  var PATTERN_RUN_CODE_POINTS = 3;
2634
+ var MAX_PATTERN_TOLERANCE = 2;
2634
2635
  var PATTERN_TEST_OPERATORS = ["eq", "ne", "in", "nin", "startsWith", "endsWith", "contains"];
2635
2636
  var PATTERN_EXPRESSION_OPERATORS = ["wildcard", "regex"];
2636
2637
 
@@ -3433,8 +3434,12 @@ function fuzzyTermMatches(queryTerm, indexTerm, tolerance, prefixLength) {
3433
3434
  return boundedLevenshtein(queryTerm, indexTerm, tolerance).withinTolerance;
3434
3435
  }
3435
3436
  function boundedLevenshtein(a, b, tolerance) {
3436
- if (tolerance < 0) return { distance: -1, withinTolerance: false };
3437
- if (a === b) return { distance: 0, withinTolerance: true };
3437
+ if (tolerance < 0) return { distance: -1, withinTolerance: false, cells: 0 };
3438
+ if (a === b) return { distance: 0, withinTolerance: true, cells: 0 };
3439
+ return tabulatedLevenshtein(a, b, tolerance);
3440
+ }
3441
+ function tabulatedLevenshtein(a, b, tolerance) {
3442
+ if (tolerance < 0) return { distance: -1, withinTolerance: false, cells: 0 };
3438
3443
  if (hasSurrogate(a) || hasSurrogate(b)) return bandedDistance(Array.from(a), Array.from(b), tolerance);
3439
3444
  return bandedDistance(a, b, tolerance);
3440
3445
  }
@@ -3442,30 +3447,32 @@ function bandedDistance(a, b, tolerance) {
3442
3447
  const m = a.length;
3443
3448
  const n = b.length;
3444
3449
  const beyond = tolerance + 1;
3445
- if (Math.abs(m - n) > tolerance) return { distance: beyond, withinTolerance: false };
3450
+ if (Math.abs(m - n) > tolerance) return { distance: beyond, withinTolerance: false, cells: 0 };
3446
3451
  let previous = new Uint32Array(n + 1).fill(beyond);
3447
3452
  let current = new Uint32Array(n + 1).fill(beyond);
3448
3453
  const firstRowEnd = Math.min(n, tolerance);
3449
3454
  for (let j = 0; j <= firstRowEnd; j++) previous[j] = j;
3455
+ let cells = 0;
3450
3456
  for (let i = 1; i <= m; i++) {
3451
3457
  const low = Math.max(1, i - tolerance);
3452
3458
  const high = Math.min(n, i + tolerance);
3453
3459
  current[low - 1] = low === 1 ? i : beyond;
3454
3460
  let rowMin = current[low - 1];
3455
3461
  const character = a[i - 1];
3462
+ if (high >= low) cells += high - low + 1;
3456
3463
  for (let j = low; j <= high; j++) {
3457
3464
  const substitution = previous[j - 1] + (character === b[j - 1] ? 0 : 1);
3458
3465
  const cell = Math.min(previous[j] + 1, current[j - 1] + 1, substitution, beyond);
3459
3466
  current[j] = cell;
3460
3467
  if (cell < rowMin) rowMin = cell;
3461
3468
  }
3462
- if (rowMin > tolerance) return { distance: beyond, withinTolerance: false };
3469
+ if (rowMin > tolerance) return { distance: beyond, withinTolerance: false, cells };
3463
3470
  const finished = previous;
3464
3471
  previous = current;
3465
3472
  current = finished;
3466
3473
  }
3467
3474
  const distance = previous[n];
3468
- return { distance, withinTolerance: distance <= tolerance };
3475
+ return { distance, withinTolerance: distance <= tolerance, cells };
3469
3476
  }
3470
3477
 
3471
3478
  // src/core/posting-list.ts
@@ -5732,6 +5739,43 @@ var MAX_FILTER_TESTS = 1024;
5732
5739
  var MAX_FILTER_ARRAY_SIZE = 65536;
5733
5740
  var GEO_UNIT_METRES = { km: 1e3, mi: 1609.344, m: 1 };
5734
5741
 
5742
+ // src/core/pattern-index/typo-runs.ts
5743
+ var BASIC_PLANE_LAST = 65535;
5744
+ function isPatternTolerance(value) {
5745
+ if (value === "auto") return true;
5746
+ return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= MAX_PATTERN_TOLERANCE;
5747
+ }
5748
+ function foldTypoText(text, host) {
5749
+ const folded = [];
5750
+ let longestFold = 0;
5751
+ for (let at = 0; at < text.length; at++) {
5752
+ const codePoint = text.codePointAt(at) ?? 0;
5753
+ if (codePoint > BASIC_PLANE_LAST) at++;
5754
+ const before = folded.length;
5755
+ host.appendFoldedCodePoint(codePoint, folded);
5756
+ longestFold = Math.max(longestFold, folded.length - before);
5757
+ }
5758
+ return { folded, longestFold };
5759
+ }
5760
+ function distinctTypoRuns(text, limit) {
5761
+ const { folded } = text;
5762
+ const seen = /* @__PURE__ */ new Set();
5763
+ const runs = [];
5764
+ for (let at = 0; at + PATTERN_RUN_CODE_POINTS <= folded.length && seen.size < limit; at++) {
5765
+ const key = String.fromCodePoint(folded[at], folded[at + 1], folded[at + 2]);
5766
+ if (seen.has(key)) continue;
5767
+ seen.add(key);
5768
+ runs.push(folded[at], folded[at + 1], folded[at + 2]);
5769
+ }
5770
+ return runs;
5771
+ }
5772
+ function typoRunsNeeded(tolerance, longestFold) {
5773
+ return tolerance * (2 + longestFold) + 1;
5774
+ }
5775
+ function distinctTypoRunCount(text, limit) {
5776
+ return distinctTypoRuns(text, limit).length / PATTERN_RUN_CODE_POINTS;
5777
+ }
5778
+
5735
5779
  // src/filters/pattern-tests.ts
5736
5780
  function excluding(context, fieldPath, excluded) {
5737
5781
  const universe = bitsetAnd(context.presentBitset(fieldPath), context.allDocIdsBitset);
@@ -5745,12 +5789,13 @@ function textsOf2(operand) {
5745
5789
  }
5746
5790
  function evaluatePatternTests(fieldPath, filter, context, bitsets) {
5747
5791
  const caseFold = filter.caseFold === true;
5748
- const matching = (operator, texts) => {
5792
+ const matching = (operator, texts, tolerance = 0) => {
5749
5793
  const into = createBitSet(context.capacity);
5750
- for (const text of texts) context.matchPattern(fieldPath, operator, text, caseFold, into);
5794
+ for (const text of texts) context.matchPattern(fieldPath, operator, text, caseFold, tolerance, into);
5751
5795
  return into;
5752
5796
  };
5753
- if (typeof filter.eq === "string") bitsets.push(matching("eq", [filter.eq]));
5797
+ const eqTolerance = isPatternTolerance(filter.tolerance) ? filter.tolerance : 0;
5798
+ if (typeof filter.eq === "string") bitsets.push(matching("eq", [filter.eq], eqTolerance));
5754
5799
  if (typeof filter.ne === "string") bitsets.push(excluding(context, fieldPath, matching("eq", [filter.ne])));
5755
5800
  if (filter.in !== void 0) bitsets.push(matching("eq", textsOf2(filter.in)));
5756
5801
  if (filter.nin !== void 0) bitsets.push(excluding(context, fieldPath, matching("eq", textsOf2(filter.nin))));
@@ -5806,7 +5851,7 @@ function elementBits(context, fieldPath, parsed, value) {
5806
5851
  const { capacity } = context;
5807
5852
  if (parsed.pattern) {
5808
5853
  const matches = createBitSet(capacity);
5809
- context.matchPattern(fieldPath, "eq", value, false, matches);
5854
+ context.matchPattern(fieldPath, "eq", value, false, 0, matches);
5810
5855
  return matches;
5811
5856
  }
5812
5857
  if (typeof value === "number")
@@ -5819,7 +5864,7 @@ function anyElementBits(context, fieldPath, parsed, values) {
5819
5864
  const { capacity } = context;
5820
5865
  const union = createBitSet(capacity);
5821
5866
  if (parsed.pattern) {
5822
- for (const value of values) context.matchPattern(fieldPath, "eq", value, false, union);
5867
+ for (const value of values) context.matchPattern(fieldPath, "eq", value, false, 0, union);
5823
5868
  return union;
5824
5869
  }
5825
5870
  if (parsed.base === "enum[]") {
@@ -5966,6 +6011,7 @@ var FIELD_FILTER_OPERATORS = [
5966
6011
  "wildcard",
5967
6012
  "regex",
5968
6013
  "caseFold",
6014
+ "tolerance",
5969
6015
  "containsAll",
5970
6016
  "matchesAny",
5971
6017
  "size",
@@ -6230,6 +6276,7 @@ function requirePatternOperands(fieldPath, filter, type) {
6230
6276
  requirePatternField(fieldPath, "caseFold", type);
6231
6277
  }
6232
6278
  requireExpressions(fieldPath, filter, type);
6279
+ if (filter.tolerance !== void 0) requirePatternField(fieldPath, "tolerance", type);
6233
6280
  if (parsedTypeOf(type)?.pattern !== true) return;
6234
6281
  const caseFold = filter.caseFold === true;
6235
6282
  for (const operator of PATTERN_TEST_OPERATORS) {
@@ -6247,6 +6294,31 @@ function requirePatternOperands(fieldPath, filter, type) {
6247
6294
  if (typeof text === "string") requirePatternText(fieldPath, operator, text, false);
6248
6295
  }
6249
6296
  }
6297
+ requireTolerance(fieldPath, filter);
6298
+ }
6299
+ function requireTolerance(fieldPath, filter) {
6300
+ const { tolerance, eq } = filter;
6301
+ if (tolerance === void 0) return;
6302
+ if (!isPatternTolerance(tolerance)) {
6303
+ invalid(`"tolerance" on field "${fieldPath}" must be 0, 1, 2, or "auto"`, fieldPath, "tolerance");
6304
+ }
6305
+ if (typeof eq !== "string") {
6306
+ invalid(
6307
+ `"tolerance" applies only to an "eq" test, while the filter on field "${fieldPath}" sets no "eq" with text`,
6308
+ fieldPath,
6309
+ "tolerance"
6310
+ );
6311
+ }
6312
+ if (tolerance === 0 || tolerance === "auto") return;
6313
+ const text = foldTypoText(eq, PATTERN_HOST);
6314
+ const requiredRuns = typoRunsNeeded(tolerance, text.longestFold);
6315
+ const distinctRuns = distinctTypoRunCount(text, requiredRuns);
6316
+ if (distinctRuns >= requiredRuns) return;
6317
+ throw new NarsilError(
6318
+ ErrorCodes.SEARCH_INVALID_FILTER,
6319
+ `A tolerance of ${tolerance} on "eq" of pattern field "${fieldPath}" needs ${requiredRuns} distinct runs of three code points in the case fold of the text, while the text holds ${distinctRuns}. Lengthen the text, lower the tolerance, or set it to "auto"`,
6320
+ { fieldPath, operator: "tolerance", requiredRuns, distinctRuns }
6321
+ );
6250
6322
  }
6251
6323
  function requireWellFormedText(fieldPath, filter) {
6252
6324
  for (const [operator, operand] of Object.entries(filter)) {
@@ -6268,6 +6340,7 @@ var TEXT_OPERATORS = ["startsWith", "endsWith"];
6268
6340
  var EQUALITY_OPERATORS = ["eq", "ne"];
6269
6341
  var LIST_OPERATORS = ["in", "nin"];
6270
6342
  var GEO_OPERATORS = ["radius", "polygon"];
6343
+ var TEST_MODIFIERS = /* @__PURE__ */ new Set(["caseFold", "tolerance"]);
6271
6344
  function invalidShape(message) {
6272
6345
  throw new NarsilError(ErrorCodes.SEARCH_INVALID_FILTER, message);
6273
6346
  }
@@ -6361,7 +6434,7 @@ function requireValidOperands(fieldPath, filter, type) {
6361
6434
  function testsIn(filter) {
6362
6435
  let tests = 0;
6363
6436
  for (const [operator, operand] of Object.entries(filter)) {
6364
- if (operator === "caseFold") continue;
6437
+ if (TEST_MODIFIERS.has(operator)) continue;
6365
6438
  tests += operator === "size" && isObjectRecord(operand) ? Math.max(1, Object.keys(operand).length) : 1;
6366
6439
  }
6367
6440
  return Math.max(1, tests);
@@ -7129,13 +7202,14 @@ function buildFilterContext(state, schema, meter) {
7129
7202
  sizeIndex: (fieldPath) => state.sizeIndexes.get(fieldPath),
7130
7203
  textRangeBitset: (fieldPath, bounds) => textRangeBitsetOf(state, fieldPath, flat[fieldPath], bounds, capacity),
7131
7204
  isPatternField: (fieldPath) => patternFields.has(fieldPath),
7132
- matchPattern: (fieldPath, operator, text, caseFold, into) => {
7205
+ matchPattern: (fieldPath, operator, text, caseFold, tolerance, into) => {
7133
7206
  const index = state.patternIndexes.get(fieldPath);
7134
7207
  if (index === void 0) return;
7135
7208
  requirePatternSearch(fieldPath).matchInto({
7136
7209
  operator,
7137
7210
  text,
7138
7211
  caseFold,
7212
+ tolerance,
7139
7213
  index,
7140
7214
  matches: into,
7141
7215
  meter,
package/dist/index.d.ts CHANGED
@@ -4,11 +4,11 @@ import { P as PartialWordSearch } from './partial-words-DTIHO8G4.js';
4
4
  import { P as PatternSearch } from './pattern-Cledccbl.js';
5
5
  import { L as LanguageModule } from './language-DB8KG1z5.js';
6
6
  export { T as TokenizerConfig } from './language-DB8KG1z5.js';
7
- export { A as ArrayFilter, B as BatchResult, C as ClientErrorCode, a as ClientErrorCodes, n as ComparisonFilter, D as DocumentImportResult, o as DocumentProjection, E as ErrorCode, b as ErrorCodes, F as FacetConfig, p as FacetResult, q as FieldFilter, r as FilterExpression, G as GeoFilter, s as GeoPolygonFilter, t as GeoRadiusFilter, u as GroupConfig, v as GroupReducer, w as GroupResult, H as HighlightConfig, x as HighlightMatch, y as Hit, z as HybridConfig, I as IndexInfo, g as IndexStats, L as ListParams, h as ListResult, J as ListedDocument, M as MemoryStats, N as NarsilError, c as NarsilErrorCode, f as NarsilEventHandlers, m as NarsilEventMap, P as PartitionStatsResult, j as PreflightResult, K as PresenceFilter, O as ProcessMemoryReport, R as QueryCoverage, Q as QueryParams, e as QueryResult, T as ScoreComponents, U as SearchMode, S as ServerErrorCode, d as ServerErrorCodes, W as SortField, X as SortSpec, Y as StringFilter, k as SuggestParams, l as SuggestResult, Z as TermMatchPolicy, V as VectorMaintenanceResult, _ as VectorQueryConfig, $ as WorkerCopyReport, i as isNarsilError } from './memory-M9kPmYP8.js';
8
- import { N as NarsilConfig } from './config-C1kbq1X2.js';
9
- export { A as AnalysisConfig, D as DurabilityConfig, I as IndexContext, a as IndexLifecycleConfig, b as InsertContext, M as MainCopyQueries, c as NarsilPlugin, P as PartitionContext, R as RemoveContext, S as SearchContext, d as StaleAnalysis, U as UpdateContext, W as WorkerConfig, e as WorkerContext } from './config-C1kbq1X2.js';
10
- import { N as Narsil } from './engine-DcGSd5vh.js';
11
- export { B as ByteSource, D as DocumentWriteOperations, I as IndexLifecycleOperations } from './engine-DcGSd5vh.js';
7
+ export { A as ArrayFilter, B as BatchResult, C as ClientErrorCode, a as ClientErrorCodes, n as ComparisonFilter, D as DocumentImportResult, o as DocumentProjection, E as ErrorCode, b as ErrorCodes, F as FacetConfig, p as FacetResult, q as FieldFilter, r as FilterExpression, G as GeoFilter, s as GeoPolygonFilter, t as GeoRadiusFilter, u as GroupConfig, v as GroupReducer, w as GroupResult, H as HighlightConfig, x as HighlightMatch, y as Hit, z as HybridConfig, I as IndexInfo, g as IndexStats, L as ListParams, h as ListResult, J as ListedDocument, M as MemoryStats, N as NarsilError, c as NarsilErrorCode, f as NarsilEventHandlers, m as NarsilEventMap, P as PartitionStatsResult, j as PreflightResult, K as PresenceFilter, O as ProcessMemoryReport, R as QueryCoverage, Q as QueryParams, e as QueryResult, T as ScoreComponents, U as SearchMode, S as ServerErrorCode, d as ServerErrorCodes, W as SortField, X as SortSpec, Y as StringFilter, k as SuggestParams, l as SuggestResult, Z as TermMatchPolicy, V as VectorMaintenanceResult, _ as VectorQueryConfig, $ as WorkerCopyReport, i as isNarsilError } from './memory-DW3OJ0im.js';
8
+ import { N as NarsilConfig } from './config-DTe5EbWW.js';
9
+ export { A as AnalysisConfig, D as DurabilityConfig, I as IndexContext, a as IndexLifecycleConfig, b as InsertContext, M as MainCopyQueries, c as NarsilPlugin, P as PartitionContext, R as RemoveContext, S as SearchContext, d as StaleAnalysis, U as UpdateContext, W as WorkerConfig, e as WorkerContext } from './config-DTe5EbWW.js';
10
+ import { N as Narsil } from './engine-BjPBzWkA.js';
11
+ export { B as ByteSource, D as DocumentWriteOperations, I as IndexLifecycleOperations } from './engine-BjPBzWkA.js';
12
12
  export { E as EmbeddingAdapter, I as InvalidationAdapter, a as InvalidationEvent, b as PartitionStatistics, P as PersistenceAdapter } from './adapters-79OIa4xm.js';
13
13
  export { i as isSimdAvailable } from './simd-DW5AtJ6B.js';
14
14
 
package/dist/index.mjs CHANGED
@@ -1,20 +1,21 @@
1
- export { VERSION, createNarsil } from './chunk-LOARLB4F.mjs';
2
- import './chunk-WL2GDSCV.mjs';
1
+ export { VERSION, createNarsil } from './chunk-HH6ALOUZ.mjs';
2
+ import './chunk-G7IP3UDZ.mjs';
3
3
  import './chunk-GCM3JFVA.mjs';
4
4
  import './chunk-BT62MUM5.mjs';
5
- export { getStopWords, getTokenizer, hasStopWords, hasTokenizer, registerPartialWordSearch, registerStopWords, registerTokenizer } from './chunk-YOVS4EV5.mjs';
6
- export { registerPatternSearch } from './chunk-NAMGDK45.mjs';
5
+ export { getStopWords, getTokenizer, hasStopWords, hasTokenizer, registerPartialWordSearch, registerStopWords, registerTokenizer } from './chunk-DFFQOA7S.mjs';
6
+ export { registerPatternSearch } from './chunk-D4EF7J3I.mjs';
7
7
  export { getLanguage, registerLanguage } from './chunk-4MQ5F4IL.mjs';
8
8
  import './chunk-V3B24XR7.mjs';
9
9
  import './chunk-TGP5M5R7.mjs';
10
10
  export { isSimdAvailable } from './chunk-AMGDG4ZJ.mjs';
11
11
  import './chunk-ZJ4CSAB2.mjs';
12
12
  import './chunk-2E35UM3G.mjs';
13
- import './chunk-7ODNRREZ.mjs';
14
- import './chunk-AIUOAN7Y.mjs';
15
- export { clearNormalizationCache, configureNormalizationCache, getNormalizationCacheSize, resetNormalizationCache } from './chunk-UOJIV2NG.mjs';
13
+ import './chunk-4344I4MR.mjs';
14
+ import './chunk-PJU6EF22.mjs';
15
+ export { clearNormalizationCache, configureNormalizationCache, getNormalizationCacheSize, resetNormalizationCache } from './chunk-NO3ABFLE.mjs';
16
16
  import './chunk-356UOTK2.mjs';
17
17
  import './chunk-KEHK2O6P.mjs';
18
+ import './chunk-GES7U2PM.mjs';
18
19
  import './chunk-U2BKYEC7.mjs';
19
20
  import './chunk-IBR6634K.mjs';
20
21
  import './chunk-POWOTUKJ.mjs';
@@ -140,6 +140,33 @@ type StringFilter = Pick<ComparisonFilter, 'eq' | 'ne'> & {
140
140
  * `ss`.
141
141
  */
142
142
  caseFold?: boolean;
143
+ /**
144
+ * This lets the `eq` test of a pattern field match a value within this many
145
+ * edits of the text, so a test for `INV-2O24` with a tolerance of 1 matches
146
+ * `INV-2024`. An edit inserts, deletes, or replaces one code point, so a
147
+ * swap of two neighbouring code points counts as two edits. With `caseFold`,
148
+ * the engine counts the edits between the case folds of the value and the
149
+ * text. The tolerance applies to `eq` alone, so the other tests of the field
150
+ * still compare exactly.
151
+ *
152
+ * The engine takes its candidates from the pattern index, so the case fold
153
+ * of the text has to hold enough distinct runs of three code points. For a
154
+ * tolerance of `k`, the engine needs `k × (2 + f) + 1` runs, where `f` is
155
+ * the number of code points in the longest case fold among the text's code
156
+ * points, which is 1 for most text. A tolerance of 1 on `INV-2O24`
157
+ * therefore needs 4 of its 6 runs, while a tolerance of 2 needs 7. Under
158
+ * `'auto'`, the engine uses 2 where the text holds enough runs for 2,
159
+ * otherwise 1 where it holds enough for 1, and otherwise 0.
160
+ *
161
+ * The engine throws `SEARCH_INVALID_FILTER` for a tolerance of 1 or 2 on a
162
+ * text with too few runs, stating how many runs that tolerance needs. It
163
+ * throws the same error for any other tolerance, for a tolerance on a field
164
+ * that is not a pattern field, and for a tolerance in a filter without an
165
+ * `eq` test. Towards the pattern work cap, it counts one unit for each cell
166
+ * that it fills in the table of edit distances between the text and a
167
+ * value.
168
+ */
169
+ tolerance?: 0 | 1 | 2 | 'auto';
143
170
  };
144
171
  /**
145
172
  * Tests the contents of a list field, which is a `number[]`, `boolean[]`,
@@ -1,7 +1,8 @@
1
- import { partialWordSearchModule } from './chunk-AIUOAN7Y.mjs';
2
- import './chunk-UOJIV2NG.mjs';
1
+ import { partialWordSearchModule } from './chunk-PJU6EF22.mjs';
2
+ import './chunk-NO3ABFLE.mjs';
3
3
  import './chunk-356UOTK2.mjs';
4
4
  import './chunk-KEHK2O6P.mjs';
5
+ import './chunk-GES7U2PM.mjs';
5
6
  import './chunk-IBR6634K.mjs';
6
7
  import './chunk-I64LXKO3.mjs';
7
8
 
package/dist/pattern.mjs CHANGED
@@ -1,4 +1,5 @@
1
- import { patternSearchModule } from './chunk-7ODNRREZ.mjs';
1
+ import { patternSearchModule } from './chunk-4344I4MR.mjs';
2
+ import './chunk-GES7U2PM.mjs';
2
3
  import './chunk-I64LXKO3.mjs';
3
4
 
4
5
  // src/pattern/index.ts
@@ -1,20 +1,21 @@
1
- import { CHECKPOINT_WORKER_HEARTBEAT_MS, createDurableDirectory, writeCheckpointSegments, directoryCheckpointStore } from '../../chunk-LOARLB4F.mjs';
2
- import '../../chunk-WL2GDSCV.mjs';
1
+ import { CHECKPOINT_WORKER_HEARTBEAT_MS, createDurableDirectory, writeCheckpointSegments, directoryCheckpointStore } from '../../chunk-HH6ALOUZ.mjs';
2
+ import '../../chunk-G7IP3UDZ.mjs';
3
3
  import '../../chunk-GCM3JFVA.mjs';
4
4
  import '../../chunk-BT62MUM5.mjs';
5
- import '../../chunk-YOVS4EV5.mjs';
6
- import '../../chunk-NAMGDK45.mjs';
5
+ import '../../chunk-DFFQOA7S.mjs';
6
+ import '../../chunk-D4EF7J3I.mjs';
7
7
  import '../../chunk-4MQ5F4IL.mjs';
8
8
  import '../../chunk-V3B24XR7.mjs';
9
9
  import '../../chunk-TGP5M5R7.mjs';
10
10
  import '../../chunk-AMGDG4ZJ.mjs';
11
11
  import '../../chunk-ZJ4CSAB2.mjs';
12
12
  import '../../chunk-2E35UM3G.mjs';
13
- import '../../chunk-7ODNRREZ.mjs';
14
- import '../../chunk-AIUOAN7Y.mjs';
15
- import '../../chunk-UOJIV2NG.mjs';
13
+ import '../../chunk-4344I4MR.mjs';
14
+ import '../../chunk-PJU6EF22.mjs';
15
+ import '../../chunk-NO3ABFLE.mjs';
16
16
  import '../../chunk-356UOTK2.mjs';
17
17
  import '../../chunk-KEHK2O6P.mjs';
18
+ import '../../chunk-GES7U2PM.mjs';
18
19
  import '../../chunk-U2BKYEC7.mjs';
19
20
  import '../../chunk-IBR6634K.mjs';
20
21
  import '../../chunk-POWOTUKJ.mjs';
package/dist/react.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { N as NarsilError, L as ListParams, h as ListResult, I as IndexInfo, g as IndexStats, Q as QueryParams, j as PreflightResult, e as QueryResult, k as SuggestParams, l as SuggestResult } from './memory-M9kPmYP8.js';
2
- export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-M9kPmYP8.js';
3
- import { e as TaskRecord, d as TaskProgress, b as ImportResult, c as TaskListQuery, T as TaskListPage } from './tasks-A8se0J98.js';
4
- export { I as ImportError, f as TaskStatus, g as TaskType } from './tasks-A8se0J98.js';
1
+ import { N as NarsilError, L as ListParams, h as ListResult, I as IndexInfo, g as IndexStats, Q as QueryParams, j as PreflightResult, e as QueryResult, k as SuggestParams, l as SuggestResult } from './memory-DW3OJ0im.js';
2
+ export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-DW3OJ0im.js';
3
+ import { e as TaskRecord, d as TaskProgress, b as ImportResult, c as TaskListQuery, T as TaskListPage } from './tasks-BTbwBqar.js';
4
+ export { I as ImportError, f as TaskStatus, g as TaskType } from './tasks-BTbwBqar.js';
5
5
  import { ReactNode, ReactElement } from 'react';
6
- import { N as Narsil } from './engine-DcGSd5vh.js';
7
- import { N as NarsilClient, I as ImportSource } from './client-D4sXFS9f.js';
6
+ import { N as Narsil } from './engine-BjPBzWkA.js';
7
+ import { N as NarsilClient, I as ImportSource } from './client-ZXcbSViH.js';
8
8
  import { A as AnyDocument } from './schema-DgyDijhf.js';
9
9
  import './adapters-79OIa4xm.js';
10
10
 
package/dist/server.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, N as NarsilError, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-M9kPmYP8.js';
2
- import { b as ServerOptions, N as NarsilServer } from './capabilities-BHNksicw.js';
3
- export { A as ASYNC_IMPORT_CAPABILITY, C as CorsOptions, D as DOCUMENT_EXPORT_CAPABILITY, E as ErrorEnvelope, I as INDEX_LIFECYCLE_CAPABILITY, O as OnRequestHook, R as REBUILD_ANALYSIS_CAPABILITY, c as RequestContext, d as RequestDenial, S as SERVER_CAPABILITIES, e as ServerLimits, T as TASK_CANCEL_CAPABILITY, a as TASK_FILTER_CAPABILITY } from './capabilities-BHNksicw.js';
4
- import { N as Narsil } from './engine-DcGSd5vh.js';
5
- import { d as TaskProgress, b as ImportResult, h as TaskStore, e as TaskRecord } from './tasks-A8se0J98.js';
6
- export { C as CapabilitiesResponse, a as CreateIndexEmbedding, i as CreateIndexRequest, H as HttpIndexConfig, I as ImportError, M as MemoryStatsResponse, T as TaskListPage, c as TaskListQuery, f as TaskStatus, g as TaskType } from './tasks-A8se0J98.js';
1
+ export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, N as NarsilError, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-DW3OJ0im.js';
2
+ import { b as ServerOptions, N as NarsilServer } from './capabilities-1lEYL3WK.js';
3
+ export { A as ASYNC_IMPORT_CAPABILITY, C as CorsOptions, D as DOCUMENT_EXPORT_CAPABILITY, E as ErrorEnvelope, I as INDEX_LIFECYCLE_CAPABILITY, O as OnRequestHook, R as REBUILD_ANALYSIS_CAPABILITY, c as RequestContext, d as RequestDenial, S as SERVER_CAPABILITIES, e as ServerLimits, T as TASK_CANCEL_CAPABILITY, a as TASK_FILTER_CAPABILITY } from './capabilities-1lEYL3WK.js';
4
+ import { N as Narsil } from './engine-BjPBzWkA.js';
5
+ import { d as TaskProgress, b as ImportResult, h as TaskStore, e as TaskRecord } from './tasks-BTbwBqar.js';
6
+ export { C as CapabilitiesResponse, a as CreateIndexEmbedding, i as CreateIndexRequest, H as HttpIndexConfig, I as ImportError, M as MemoryStatsResponse, T as TaskListPage, c as TaskListQuery, f as TaskStatus, g as TaskType } from './tasks-BTbwBqar.js';
7
7
  import './schema-DgyDijhf.js';
8
8
  import './adapters-79OIa4xm.js';
9
- import './config-B-GRonqw.js';
10
- import './config-C1kbq1X2.js';
9
+ import './config-DHL2KsfD.js';
10
+ import './config-DTe5EbWW.js';
11
11
  import './types-ChrVy4lH.js';
12
12
  import './types-Cb9kiY5P.js';
13
13
 
@@ -1,4 +1,4 @@
1
- import { M as MemoryStats } from './memory-M9kPmYP8.js';
1
+ import { M as MemoryStats } from './memory-DW3OJ0im.js';
2
2
 
3
3
  /** Declarative index configuration accepted over HTTP. Function-valued engine
4
4
  * options (custom tokenizer, stopWords-as-function, group reducer, embedding
@@ -1,13 +1,14 @@
1
1
  import { loadUWebSockets, childAppOf, createRouteRunner, corsHeaderReader, createSharedRequestGate, registerServerRoutes, sendRelayed, createDocumentReadHandlers, respondJson, SERVER_CAPABILITIES, versionReport, statusLine, sendError, serverRoutes, parseJson, validateSuggest, rejectInvalid, respondError, validateQuery, refuseRegex } from './chunk-BT6BI4GV.mjs';
2
- import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-WL2GDSCV.mjs';
3
- import { resolveProjection, projectionKeepsField, setNestedValue } from './chunk-NAMGDK45.mjs';
2
+ import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-G7IP3UDZ.mjs';
3
+ import { resolveProjection, projectionKeepsField, setNestedValue } from './chunk-D4EF7J3I.mjs';
4
4
  import './chunk-V3B24XR7.mjs';
5
5
  import './chunk-ZJ4CSAB2.mjs';
6
6
  import './chunk-2E35UM3G.mjs';
7
- import './chunk-7ODNRREZ.mjs';
8
- import './chunk-UOJIV2NG.mjs';
7
+ import './chunk-4344I4MR.mjs';
8
+ import './chunk-NO3ABFLE.mjs';
9
9
  import { extractVectorFieldsFromSchema } from './chunk-356UOTK2.mjs';
10
10
  import './chunk-KEHK2O6P.mjs';
11
+ import './chunk-GES7U2PM.mjs';
11
12
  import './chunk-IBR6634K.mjs';
12
13
  import { ServerErrorCodes, NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
13
14
 
@@ -18,7 +18,7 @@ async function importBootstrapModule(moduleUrl) {
18
18
  await import(moduleUrl);
19
19
  }
20
20
  async function stopServingRequests() {
21
- const { closeRequestThread } = await import('../thread-BSIKT6ED.mjs');
21
+ const { closeRequestThread } = await import('../thread-YOTNJEVY.mjs');
22
22
  closeRequestThread();
23
23
  }
24
24
  function holdsCopies(executor) {
@@ -49,7 +49,7 @@ function createActionHandler(executor) {
49
49
  if (!holdsCopies(executor)) {
50
50
  throw new NarsilError(ErrorCodes.CONFIG_INVALID, "This executor holds no copies to answer requests from");
51
51
  }
52
- const starting = import('../thread-BSIKT6ED.mjs').then(
52
+ const starting = import('../thread-YOTNJEVY.mjs').then(
53
53
  ({ serveRequests }) => serveRequests(executor, action.settings)
54
54
  );
55
55
  serving.start = starting.then(
@@ -102,7 +102,7 @@ async function setup() {
102
102
  } catch {
103
103
  parentPort = null;
104
104
  }
105
- const { createDirectExecutor } = await import('../direct-executor-AVNWB73C.mjs');
105
+ const { createDirectExecutor } = await import('../direct-executor-Q7PNCGZB.mjs');
106
106
  const handleAction = createActionHandler(createDirectExecutor({ threadSlot }));
107
107
  if (parentPort) {
108
108
  const port = parentPort;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delali/narsil",
3
- "version": "0.3.1-next.75",
3
+ "version": "0.3.1-next.77",
4
4
  "type": "module",
5
5
  "description": "Distributed search engine with full-text, vector, hybrid, and geosearch. One engine, embedded or on a server, with a cross-language .nrsl format.",
6
6
  "author": "Delali (https://sondelali.com)",
@@ -240,11 +240,11 @@
240
240
  }
241
241
  },
242
242
  "optionalDependencies": {
243
- "@delali/narsil-native-darwin-arm64": "0.3.1-next.75",
244
- "@delali/narsil-native-darwin-x64": "0.3.1-next.75",
245
- "@delali/narsil-native-linux-arm64": "0.3.1-next.75",
246
- "@delali/narsil-native-linux-x64": "0.3.1-next.75",
247
- "@delali/narsil-native-win32-arm64": "0.3.1-next.75",
248
- "@delali/narsil-native-win32-x64": "0.3.1-next.75"
243
+ "@delali/narsil-native-darwin-arm64": "0.3.1-next.77",
244
+ "@delali/narsil-native-darwin-x64": "0.3.1-next.77",
245
+ "@delali/narsil-native-linux-arm64": "0.3.1-next.77",
246
+ "@delali/narsil-native-linux-x64": "0.3.1-next.77",
247
+ "@delali/narsil-native-win32-arm64": "0.3.1-next.77",
248
+ "@delali/narsil-native-win32-x64": "0.3.1-next.77"
249
249
  }
250
250
  }