@delali/narsil 0.3.1-next.73 → 0.3.1-next.74

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 (46) hide show
  1. package/dist/{capabilities-CYeAWYxQ.d.ts → capabilities-CAMzmkAg.d.ts} +2 -2
  2. package/dist/{chunk-PU43WDY4.mjs → chunk-2E35UM3G.mjs} +1 -13
  3. package/dist/chunk-3DDUNI6N.mjs +48 -0
  4. package/dist/{chunk-THMSFOJO.mjs → chunk-BVBIQQKG.mjs} +576 -547
  5. package/dist/{chunk-ZULSEZCE.mjs → chunk-CTOSGRM7.mjs} +100 -19
  6. package/dist/{chunk-CVFAFZSN.mjs → chunk-CUZOX6CN.mjs} +23 -15
  7. package/dist/chunk-I23G3IZC.mjs +593 -0
  8. package/dist/chunk-KEHK2O6P.mjs +13 -0
  9. package/dist/{chunk-AFKH4ZK3.mjs → chunk-LX4JERXI.mjs} +1 -1
  10. package/dist/{chunk-LPBWCHBE.mjs → chunk-NOZUQM7J.mjs} +2 -2
  11. package/dist/{chunk-WVDFG45M.mjs → chunk-PO53FV4Q.mjs} +2 -1
  12. package/dist/chunk-T5ZWEWVD.mjs +658 -0
  13. package/dist/{chunk-2WLD2NFW.mjs → chunk-TVFLHM7M.mjs} +2 -2
  14. package/dist/{chunk-3YKWSO54.mjs → chunk-VKX2BPXD.mjs} +147 -647
  15. package/dist/{chunk-AK3BLGCI.mjs → chunk-Z3DQPOJQ.mjs} +15 -48
  16. package/dist/{client-D698E5ge.d.ts → client-C-I70ArH.d.ts} +3 -3
  17. package/dist/client.d.ts +8 -8
  18. package/dist/{config-Bv8etwUZ.d.ts → config-C6Iw5rCX.d.ts} +2 -2
  19. package/dist/{config-QXU3HMpq.d.ts → config-DJPH3IQB.d.ts} +2 -2
  20. package/dist/direct-executor-KFAGILJC.mjs +17 -0
  21. package/dist/distribution/coordinator/etcd.d.ts +2 -2
  22. package/dist/distribution/coordinator/in-memory.d.ts +2 -2
  23. package/dist/distribution.d.ts +8 -8
  24. package/dist/distribution.mjs +19 -9
  25. package/dist/{engine-D_OzKZ-6.d.ts → engine-B8eRPO7m.d.ts} +2 -2
  26. package/dist/index.browser.mjs +1200 -808
  27. package/dist/index.d.ts +27 -8
  28. package/dist/index.mjs +12 -8
  29. package/dist/{memory-B4jMmygw.d.ts → memory-DJEwWoCi.d.ts} +1205 -1180
  30. package/dist/partial-words-DTIHO8G4.d.ts +19 -0
  31. package/dist/partial-words.d.ts +22 -0
  32. package/dist/partial-words.mjs +11 -0
  33. package/dist/persistence/durability/checkpoint-worker.d.ts +33 -13
  34. package/dist/persistence/durability/checkpoint-worker.mjs +12 -8
  35. package/dist/react.d.ts +7 -7
  36. package/dist/{schema-BBOCdhND.d.ts → schema-DgyDijhf.d.ts} +6 -2
  37. package/dist/server.d.ts +10 -10
  38. package/dist/server.mjs +8 -6
  39. package/dist/{tasks-DpgCpW1x.d.ts → tasks-BVmAKYBh.d.ts} +1 -1
  40. package/dist/{thread-3LNVA43V.mjs → thread-W6DPKEF6.mjs} +8 -5
  41. package/dist/{types-BiUmaiWT.d.ts → types-ChrVy4lH.d.ts} +1 -1
  42. package/dist/vector/search-worker.d.ts +1 -1
  43. package/dist/vector/search-worker.mjs +3 -2
  44. package/dist/workers/entry.mjs +3 -3
  45. package/package.json +15 -7
  46. package/dist/direct-executor-5SRDFZAS.mjs +0 -13
@@ -1,7 +1,9 @@
1
- import { clampRowCount, sortSignatureOf, requireSortableFields, decodePageCursor, requireMatchingCursor, resolveProjection, encodePageCursor, requireWithinResultWindow, normalizeSort, fanOutQuery, sortModesOf, applySorting, applyPagination, projectionKeepsField, countsWithoutScores, fanOutMatchCount, tokenize, fnv1aBytes, requireValidFilter, createPatternWorkMeter, everyValueFacetConfig, fulltextMatches, mergeFacets, pruneStatsToQueryTerms, partitionsIn, undeclaredFieldOnStrictIndex, fuzzyTermMatches } from './chunk-3YKWSO54.mjs';
2
- import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, MIN_PATTERN_VALUE_LIMIT, MAX_PATTERN_VALUE_LIMIT, DEFAULT_LIMIT, DEFAULT_MAX_PER_GROUP, flattenSchema, 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, isWordIndexedFieldType, isGeopointOrVectorType, MAX_TOLERANCE, MAX_PREFIX_LENGTH } from './chunk-AK3BLGCI.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-VKX2BPXD.mjs';
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-3DDUNI6N.mjs';
3
3
  import { MIN_OVERSAMPLE } from './chunk-ZJ4CSAB2.mjs';
4
- import { holdsUnpairedSurrogate, compareCodePoints, compareComparableKeys } from './chunk-LJYTW7GT.mjs';
4
+ import { tokenize, fuzzyTermMatches } from './chunk-I23G3IZC.mjs';
5
+ import { partialFieldsOf, MIN_PATTERN_VALUE_LIMIT, MAX_PATTERN_VALUE_LIMIT, flattenSchema, isWordIndexedFieldType, isGeopointOrVectorType } from './chunk-Z3DQPOJQ.mjs';
6
+ import { holdsUnpairedSurrogate, compareCodePoints, compareComparableKeys, codePointCount } from './chunk-LJYTW7GT.mjs';
5
7
  import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
6
8
 
7
9
  // src/search/cursor-binding.ts
@@ -129,7 +131,7 @@ function boundVectorOf(vector) {
129
131
  return bound;
130
132
  }
131
133
  var FILTERS_SLOT = 2;
132
- var BOUND_SLOT_COUNT = 15;
134
+ var BOUND_SLOT_COUNT = 16;
133
135
  function bindingOf(values) {
134
136
  const stream = { bytes: new Uint8Array(256), length: 0 };
135
137
  for (const value of values) {
@@ -148,6 +150,7 @@ function queryBindingOf(params) {
148
150
  params.tolerance,
149
151
  params.prefixLength,
150
152
  params.prefix,
153
+ params.partialWords,
151
154
  params.exact,
152
155
  params.pinned,
153
156
  params.mode,
@@ -316,9 +319,18 @@ function requireKnownMode(params) {
316
319
  { mode: String(params.mode), modes: [...SEARCH_MODES] }
317
320
  );
318
321
  }
322
+ function requireBooleanPartialWords(params) {
323
+ const setting = params.partialWords;
324
+ if (setting === void 0 || typeof setting === "boolean") return;
325
+ throw new NarsilError(ErrorCodes.CONFIG_INVALID, 'The "partialWords" query option takes true or false', {
326
+ option: "partialWords",
327
+ received: setting === null ? "null" : typeof setting
328
+ });
329
+ }
319
330
  function requireValidQueryOptions(params, config) {
320
331
  const strict = config.strict === true;
321
332
  requireValidTypoTolerance(params);
333
+ requireBooleanPartialWords(params);
322
334
  requireSortableFields(params.sort, config.schema, strict);
323
335
  requireValidQueryFilter(params.filters, config.schema);
324
336
  requireUsableQueryFields(params, config.schema, strict);
@@ -424,6 +436,16 @@ function validatePartitionConfig(partitions) {
424
436
  });
425
437
  }
426
438
  }
439
+ function requireSurfaceFormsForPartialFields(schema, surfaceForms) {
440
+ if (surfaceForms !== false) return;
441
+ const partialFields = partialFieldsOf(schema);
442
+ if (partialFields.length === 0) return;
443
+ throw new NarsilError(
444
+ ErrorCodes.CONFIG_INVALID,
445
+ `Field "${partialFields[0]}" declares "partial", which compares words as the documents wrote them, so its index needs surfaceForms left on`,
446
+ { fields: [...partialFields], surfaceForms: false }
447
+ );
448
+ }
427
449
  function validatePatternValueLimit(limit) {
428
450
  if (limit === void 0) return;
429
451
  if (typeof limit !== "number" || !Number.isInteger(limit) || limit < MIN_PATTERN_VALUE_LIMIT || limit > MAX_PATTERN_VALUE_LIMIT) {
@@ -813,6 +835,31 @@ function applySnippetTruncation(taggedText, originalText, positions, maxLen, pre
813
835
  if (needsTrailingEllipsis) snippet = `${snippet}...`;
814
836
  return { snippet, visiblePositions };
815
837
  }
838
+ function containsPartialWord(spelling, words) {
839
+ for (const word of words) {
840
+ if (spelling.length > word.length && spelling.includes(word)) return true;
841
+ }
842
+ return false;
843
+ }
844
+ function partialWordMatcher(text, language, partial) {
845
+ const indexed = tokenize(text, language, {
846
+ stem: true,
847
+ removeStopWords: true,
848
+ collectSurfaces: true,
849
+ customTokenizer: partial.customTokenizer,
850
+ stopWordOverride: partial.stopWordOverride
851
+ });
852
+ const positions = /* @__PURE__ */ new Set();
853
+ const spellings = /* @__PURE__ */ new Set();
854
+ for (let at = 0; at < indexed.tokens.length; at++) {
855
+ const spelling = indexed.surfaces?.[at] ?? indexed.tokens[at].token;
856
+ if (!containsPartialWord(spelling, partial.words)) continue;
857
+ positions.add(indexed.tokens[at].position);
858
+ spellings.add(spelling);
859
+ }
860
+ if (partial.customTokenizer !== void 0) return (_position, fieldToken) => spellings.has(fieldToken);
861
+ return (position) => positions.has(position);
862
+ }
816
863
  function highlightField(text, queryTokens, language, options) {
817
864
  const preTag = options?.preTag ?? "<mark>";
818
865
  const postTag = options?.postTag ?? "</mark>";
@@ -849,11 +896,13 @@ function highlightField(text, queryTokens, language, options) {
849
896
  matchByFieldToken.set(fieldToken, matches);
850
897
  return matches;
851
898
  };
899
+ const matchesInside = options?.partialWords === void 0 ? null : partialWordMatcher(text, language, options.partialWords);
852
900
  for (let i = 0; i < fieldResult.tokens.length; i++) {
853
901
  if (i >= charOffsets.length) break;
854
902
  const fieldToken = fieldResult.tokens[i].token;
855
903
  const prefixMatch = prefixToken !== void 0 && fieldToken.startsWith(prefixToken);
856
- if (prefixMatch || matchesQuery(fieldToken)) {
904
+ const insideMatch = matchesInside?.(fieldResult.tokens[i].position, fieldToken) === true;
905
+ if (prefixMatch || insideMatch || matchesQuery(fieldToken)) {
857
906
  matchedRanges.push({ start: charOffsets[i].start, end: charOffsets[i].end });
858
907
  }
859
908
  }
@@ -885,7 +934,39 @@ function highlightField(text, queryTokens, language, options) {
885
934
  }
886
935
 
887
936
  // src/engine/query/highlight.ts
888
- function applyHighlights(hits, params, language, analysis, readStoredDocument) {
937
+ function writtenWordsOf(params, language, analysis) {
938
+ return tokenize(params.term ?? "", language, {
939
+ stem: false,
940
+ removeStopWords: true,
941
+ customTokenizer: analysis.customTokenizer,
942
+ stopWordOverride: analysis.stopWords
943
+ }).tokens;
944
+ }
945
+ function partialWordTagging(params, schema, queryTokens, written, analysis) {
946
+ if (params.partialWords !== true || params.exact === true) return null;
947
+ const fields = partialFieldsOf(schema).filter((field) => params.fields === void 0 || params.fields.includes(field));
948
+ if (fields.length === 0) return null;
949
+ const writtenAt = /* @__PURE__ */ new Map();
950
+ for (const word of written) {
951
+ if (!writtenAt.has(word.position)) writtenAt.set(word.position, word.token);
952
+ }
953
+ const seenTokens = /* @__PURE__ */ new Set();
954
+ const words = [];
955
+ for (const queryToken of queryTokens) {
956
+ if (seenTokens.has(queryToken.token)) continue;
957
+ seenTokens.add(queryToken.token);
958
+ const word = writtenAt.get(queryToken.position);
959
+ if (word === void 0 || codePointCount(word) < PARTIAL_WORD_MIN_CODE_POINTS) continue;
960
+ words.push(word);
961
+ if (words.length === PARTIAL_WORDS_ADDED_PER_QUERY) break;
962
+ }
963
+ if (words.length === 0) return null;
964
+ return {
965
+ fields: new Set(fields),
966
+ highlight: { words, customTokenizer: analysis.customTokenizer, stopWordOverride: analysis.stopWords }
967
+ };
968
+ }
969
+ function applyHighlights(hits, params, language, analysis, schema, readStoredDocument) {
889
970
  if (!params.highlight) return;
890
971
  const queryTokenResult = tokenize(params.term ?? "", language, {
891
972
  stem: true,
@@ -893,17 +974,15 @@ function applyHighlights(hits, params, language, analysis, readStoredDocument) {
893
974
  customTokenizer: analysis.customTokenizer,
894
975
  stopWordOverride: analysis.stopWords
895
976
  });
977
+ const queryTokens = queryTokenResult.tokens;
978
+ const usesPrefix = params.prefix === true && params.exact !== true && queryTokens.length > 0;
979
+ const usesPartialWords = params.partialWords === true && params.exact !== true && queryTokens.length > 0;
980
+ const written = usesPrefix || usesPartialWords ? writtenWordsOf(params, language, analysis) : [];
896
981
  let prefixToken;
897
982
  let completedToken;
898
- if (params.prefix === true && params.exact !== true && queryTokenResult.tokens.length > 0) {
899
- const lastToken = queryTokenResult.tokens[queryTokenResult.tokens.length - 1];
900
- const unstemmed = tokenize(params.term ?? "", language, {
901
- stem: false,
902
- removeStopWords: true,
903
- customTokenizer: analysis.customTokenizer,
904
- stopWordOverride: analysis.stopWords
905
- });
906
- for (const t of unstemmed.tokens) {
983
+ if (usesPrefix) {
984
+ const lastToken = queryTokens[queryTokens.length - 1];
985
+ for (const t of written) {
907
986
  if (t.position === lastToken.position) {
908
987
  prefixToken = t.token;
909
988
  completedToken = lastToken.token;
@@ -911,6 +990,7 @@ function applyHighlights(hits, params, language, analysis, readStoredDocument) {
911
990
  }
912
991
  }
913
992
  }
993
+ const partialWords = usesPartialWords ? partialWordTagging(params, schema, queryTokens, written, analysis) : null;
914
994
  for (const hit of hits) {
915
995
  const highlights = {};
916
996
  const projected = hit.document;
@@ -922,14 +1002,15 @@ function applyHighlights(hits, params, language, analysis, readStoredDocument) {
922
1002
  fieldValue = stored?.[field];
923
1003
  }
924
1004
  if (typeof fieldValue === "string") {
925
- highlights[field] = highlightField(fieldValue, queryTokenResult.tokens, language, {
1005
+ highlights[field] = highlightField(fieldValue, queryTokens, language, {
926
1006
  preTag: params.highlight.preTag,
927
1007
  postTag: params.highlight.postTag,
928
1008
  maxSnippetLength: params.highlight.maxSnippetLength,
929
1009
  prefixToken,
930
1010
  completedToken,
931
1011
  tolerance: params.exact === true ? 0 : params.tolerance ?? 0,
932
- prefixLength: params.prefixLength ?? DEFAULT_FUZZY_PREFIX_LENGTH
1012
+ prefixLength: params.prefixLength ?? DEFAULT_FUZZY_PREFIX_LENGTH,
1013
+ partialWords: partialWords?.fields.has(field) === true ? partialWords.highlight : void 0
933
1014
  });
934
1015
  }
935
1016
  }
@@ -1439,7 +1520,7 @@ async function executeQuery(params, callerContext) {
1439
1520
  if (params.highlight) {
1440
1521
  const dropped = params.highlight.fields.some((field) => !projectionKeepsField(projection, field));
1441
1522
  const readStoredDocument = dropped ? (docId) => manager.get(docId, { kind: "full" }) : void 0;
1442
- applyHighlights(paginated, params, language, manager.analysis, readStoredDocument);
1523
+ applyHighlights(paginated, params, language, manager.analysis, manager.schema, readStoredDocument);
1443
1524
  }
1444
1525
  const elapsed = now() - startTime;
1445
1526
  return {
@@ -1557,4 +1638,4 @@ function pickDisplaySurface(surfaceOccurrences) {
1557
1638
  return best;
1558
1639
  }
1559
1640
 
1560
- export { clampLimit, dedupePinnedEntries, executeListDocuments, executePreflight, executeQuery, executeSuggest, foldGroupReducer, hitsKeptPerGroup, listBindingOf, now, queryBindingOf, resolveHybridFusion, validateBM25Params, validateDocId, validateIndexName, validatePartitionConfig, validatePatternValueLimit, validateWorkerConfig };
1641
+ export { clampLimit, dedupePinnedEntries, executeListDocuments, executePreflight, executeQuery, executeSuggest, foldGroupReducer, hitsKeptPerGroup, listBindingOf, now, queryBindingOf, requireSurfaceFormsForPartialFields, resolveHybridFusion, validateBM25Params, validateDocId, validateIndexName, validatePartitionConfig, validatePatternValueLimit, validateWorkerConfig };
@@ -1,13 +1,16 @@
1
+ import { validateWorkerConfig, validateIndexName, validatePatternValueLimit, requireSurfaceFormsForPartialFields, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-CTOSGRM7.mjs';
1
2
  import { ReplicationMessageTypes } from './chunk-GCM3JFVA.mjs';
2
- import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, restoredConfigFields, restoredEmbedding, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, requireDocumentObject, admitInsert, asBatchInsertError, requireMatchingDocId, embedDocumentFields, assertDocumentCarriesMappedVectors, admitBufferedUpsert, createPendingAdmissions, recordPendingAdmission } from './chunk-AFKH4ZK3.mjs';
3
- import { NATIVE_CRC32_MIN_BYTES, generateId, decodeEveryStoredDocument, createSharedFrozenSegment, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, requirePatternSearchFor, 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-THMSFOJO.mjs';
3
+ import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, restoredConfigFields, restoredEmbedding, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, requireDocumentObject, admitInsert, asBatchInsertError, requireMatchingDocId, embedDocumentFields, assertDocumentCarriesMappedVectors, admitBufferedUpsert, createPendingAdmissions, recordPendingAdmission } from './chunk-LX4JERXI.mjs';
4
+ import { NATIVE_CRC32_MIN_BYTES, generateId, decodeEveryStoredDocument, createSharedFrozenSegment, shareSegmentArrays, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, requirePatternSearchFor, 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-BVBIQQKG.mjs';
5
+ import { collectQueryTermStats, mergePartitionStats, oversampledFacetConfig, fnv1a, kWayMerge, mergeFacets, setNestedValue } from './chunk-VKX2BPXD.mjs';
4
6
  import { detectRuntime, getLanguage } from './chunk-4MQ5F4IL.mjs';
5
- import { validateWorkerConfig, validateIndexName, validatePatternValueLimit, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-ZULSEZCE.mjs';
6
- import { getNestedValue, collectQueryTermStats, mergePartitionStats, oversampledFacetConfig, fnv1a, kWayMerge, mergeFacets, parseVectorDimension, setNestedValue } from './chunk-3YKWSO54.mjs';
7
- import { extractVectorFieldsFromSchema, messagePackUpperBoundBytes, MAX_INDEX_CONFIGURATION_BYTES, validateSchema, requireCreatableSchema, validateVectorPromotion, validateVectorStorage, raiseEarlierReleaseGraphSetting, flattenSchema, isSingleStringFieldType, requireValidFieldTypes, encodeDocument, STATISTICS_BROADCAST_INTERVAL_MS, MAX_SWEEP_INTERVAL_MS, MIN_SWEEP_INTERVAL_MS, HEAP_PRESSURE_WARNING_FRACTION, MAX_EXPORT_LINE_BYTES, IMPORT_BATCH_DOCUMENTS, VECTOR_PATTERN, schemaFieldsOf, FOREIGN_STATS_TTL_MS, MAX_IMPORT_REFUSALS_REPORTED, BATCH_CHUNK_SIZE, MIN_DOCUMENTS_FOR_SEGMENTS, MAX_DOCUMENT_NESTING_DEPTH, isQuantizationMode, isStorageMode, HEAP_PRESSURE_REARM_FRACTION, EXPORT_CHUNK_BYTES, validateRequiredFields, requireDocumentWithinSizeLimit, validateDocument, validateDocumentStrict } from './chunk-AK3BLGCI.mjs';
8
- import { releaseLocksHeldBy } from './chunk-WVDFG45M.mjs';
9
- import { requireSearchBackendSettings, MIN_M } from './chunk-PU43WDY4.mjs';
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-3DDUNI6N.mjs';
8
+ import { releaseLocksHeldBy } from './chunk-PO53FV4Q.mjs';
9
+ import { requireSearchBackendSettings } from './chunk-2E35UM3G.mjs';
10
10
  import { DEFAULT_PATTERN_WORK_CAP, MATCHER_STATE_BUDGET_BYTES, MATCHER_SIMULATION_BYTES_PER_POSITION, MATCHER_STATE_OVERHEAD_BYTES, PATTERN_TEST_OPERATORS, MATCHER_CODE_POINT_BYTES } from './chunk-ZKRV5M2P.mjs';
11
+ import { getNestedValue, parseVectorDimension } from './chunk-I23G3IZC.mjs';
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-Z3DQPOJQ.mjs';
13
+ import { MIN_M } from './chunk-KEHK2O6P.mjs';
11
14
  import { compareCodePoints, foldedCodePointCount, codePointCount } from './chunk-LJYTW7GT.mjs';
12
15
  import { createRequestId, isValidWorkerResponse, threadSlotOfWorker } from './chunk-POWOTUKJ.mjs';
13
16
  import { ErrorCodes, NarsilError } from './chunk-I64LXKO3.mjs';
@@ -3502,7 +3505,7 @@ function selectionOfMask(segment, keep) {
3502
3505
  }
3503
3506
  function frozenLiveTail(live, shared) {
3504
3507
  if (live.count() === 0) return null;
3505
- const payload = live.encodeSegment();
3508
+ const payload = { ...live.encodeSegment(), partialSpellings: null };
3506
3509
  const documents = survivorDocumentsOf(partitionStateOf(live), payload);
3507
3510
  if (shared) {
3508
3511
  const snapshot = freezeSegmentShared(payload, documents);
@@ -5018,6 +5021,7 @@ function emptyPayload() {
5018
5021
  totalFieldLengths: {},
5019
5022
  docFrequencies: {},
5020
5023
  surfaceForms: null,
5024
+ partialSpellings: null,
5021
5025
  numeric: [],
5022
5026
  boolean: [],
5023
5027
  enums: [],
@@ -5123,7 +5127,7 @@ function chooseWindow(segments, wantedLength) {
5123
5127
  return null;
5124
5128
  }
5125
5129
  function frozenOf(contents) {
5126
- return createSharedFrozenSegment({ ...contents.arrays, segmentId: generateId() });
5130
+ return createSharedFrozenSegment(shareSegmentArrays(contents.arrays, null));
5127
5131
  }
5128
5132
  function applyTimeOrder(frozen, contents) {
5129
5133
  for (let newer = 1; newer < frozen.length; newer++) {
@@ -5391,7 +5395,7 @@ async function loadPartitionSegments(store, partition, manager, options) {
5391
5395
  const contents = await readSegmentFile(store, ref);
5392
5396
  requireAgreedSchema(options.schema, contents.schema, ref.key);
5393
5397
  if (options.decodesEveryDocument) decodeEveryStoredDocument(contents.arrays.documentTable);
5394
- const segment = createSharedFrozenSegment({ ...contents.arrays, segmentId: generateId() });
5398
+ const segment = createSharedFrozenSegment(shareSegmentArrays(contents.arrays, manager.partialWordAnalysis));
5395
5399
  removeWhatTheSegmentReplaces(manager, segment, contents);
5396
5400
  if (contents.arrays.documentCount > 0) manager.attachFrozenSegment(partition.partitionId, segment);
5397
5401
  await yieldToEventLoop4();
@@ -7881,6 +7885,7 @@ async function createIndexFromMetadata(deps, metadata, loadData) {
7881
7885
  try {
7882
7886
  indexConfig.schema = validateSchema(indexConfig.schema);
7883
7887
  validatePatternValueLimit(indexConfig.patternValueLimit);
7888
+ requireSurfaceFormsForPartialFields(indexConfig.schema, indexConfig.surfaceForms);
7884
7889
  } catch (err) {
7885
7890
  throw recoveryFailure(metadata, err);
7886
7891
  }
@@ -8594,7 +8599,7 @@ function checkHeapAfterRecovery(core) {
8594
8599
  }
8595
8600
 
8596
8601
  // src/core/partition/frozen/share.ts
8597
- function shareFrozenSegment(segment) {
8602
+ function shareFrozenSegment(segment, analysis) {
8598
8603
  if (segment.sharedSnapshot !== null) {
8599
8604
  return { snapshot: segment.sharedSnapshot, tombstonedDocIds: segment.tombstonedDocIds() };
8600
8605
  }
@@ -8608,7 +8613,7 @@ function shareFrozenSegment(segment) {
8608
8613
  }
8609
8614
  return stored.fields;
8610
8615
  });
8611
- const snapshot = freezeSegmentShared(payload, documents, segment.segmentId);
8616
+ const snapshot = freezeSegmentShared(payload, documents, segment.segmentId, analysis);
8612
8617
  return snapshot === null ? null : { snapshot, tombstonedDocIds: [] };
8613
8618
  }
8614
8619
 
@@ -8619,7 +8624,7 @@ function captureComposite(manager, partitionId) {
8619
8624
  const segmentIds = partition.frozenSegmentSizes().map((size) => size.segmentId);
8620
8625
  const frozen = [];
8621
8626
  for (const segment of partition.frozenSegmentsById(segmentIds)) {
8622
- const shared = shareFrozenSegment(segment);
8627
+ const shared = shareFrozenSegment(segment, manager.partialWordAnalysis);
8623
8628
  if (shared === null) return null;
8624
8629
  frozen.push(shared);
8625
8630
  }
@@ -9004,7 +9009,7 @@ function liveTailCount(manager, partitionId) {
9004
9009
  }
9005
9010
  function freezeIntoSharedSegment(manager, partitionId) {
9006
9011
  return manager.freezeLiveTail(partitionId, (payload, documents) => {
9007
- const snapshot = freezeSegmentShared(payload, documents);
9012
+ const snapshot = freezeSegmentShared(payload, documents, void 0, manager.partialWordAnalysis);
9008
9013
  return snapshot === null ? null : createSharedFrozenSegment(snapshot);
9009
9014
  });
9010
9015
  }
@@ -9127,7 +9132,7 @@ async function compactPartitionSegments2(state, indexName, manager, partitionId,
9127
9132
  const mainCanMerge = composite !== null && mainHoldsAll(composite, segmentIds);
9128
9133
  let snapshot = await compactOnWorker(state, indexName, partitionId, segmentIds);
9129
9134
  if (snapshot === null && mainCanMerge && composite !== null) {
9130
- snapshot = mergeFrozenSegments(composite.frozenSegmentsById(segmentIds));
9135
+ snapshot = mergeFrozenSegments(composite.frozenSegmentsById(segmentIds), manager.partialWordAnalysis);
9131
9136
  }
9132
9137
  if (snapshot === null) {
9133
9138
  if (!mainCanMerge) forgetLedgerSegments(state, indexName, partitionId, segmentIds);
@@ -11117,7 +11122,9 @@ async function createEngineIndex(core, config, name, requestedConfig, creation =
11117
11122
  if (appliesCreationLimits) requireCreatableSchema(schema);
11118
11123
  const indexConfig = schema === requestedConfig.schema ? requestedConfig : { ...requestedConfig, schema };
11119
11124
  requirePatternSearchFor(schema);
11125
+ requirePartialWordSearchFor(schema);
11120
11126
  validatePatternValueLimit(indexConfig.patternValueLimit);
11127
+ requireSurfaceFormsForPartialFields(schema, indexConfig.surfaceForms);
11121
11128
  validateVectorPromotion(indexConfig.vectorPromotion);
11122
11129
  validateVectorStorage(indexConfig.vectorPromotion, core.filesystemDurability);
11123
11130
  validateBM25Params(indexConfig.bm25);
@@ -13918,6 +13925,7 @@ function prepareRestoredIndex(configuration, deps, reject) {
13918
13925
  const language = getLanguage(languageName);
13919
13926
  const schema = validateSchema(configuration.schema);
13920
13927
  validatePatternValueLimit(configFields.patternValueLimit);
13928
+ requireSurfaceFormsForPartialFields(schema, configFields.surfaceForms);
13921
13929
  validateVectorPromotion(configFields.vectorPromotion);
13922
13930
  validateVectorStorage(configFields.vectorPromotion, deps.filesystemDurability);
13923
13931
  if (configFields.required !== void 0 && configFields.required.length > 0) {