@equationalapplications/core-llm-wiki 5.0.0 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -3,6 +3,51 @@ export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as Ext
3
3
  import { OkfFile } from '@equationalapplications/core-okf';
4
4
  import 'minisearch';
5
5
 
6
+ /**
7
+ * Slices a string like `String.prototype.slice`, but clamps out-of-range
8
+ * indices instead of relying on JS's implicit clamping, normalizes a
9
+ * start-after-end range by swapping the two bounds, and nudges either bound
10
+ * off a UTF-16 surrogate pair boundary so slicing never splits one code
11
+ * point in half.
12
+ *
13
+ * @param value - The source string to slice.
14
+ * @param start - Start index; negative counts from the end, out-of-range
15
+ * values are clamped to `[0, value.length]`.
16
+ * @param end - End index (exclusive); defaults to `value.length` when
17
+ * omitted. Same clamping/negative-index rules as `start`.
18
+ * @returns The sliced substring, never splitting a surrogate pair.
19
+ */
20
+ declare function safeSlice(value: string, start: number, end?: number): string;
21
+ /**
22
+ * Splits `input` into chunks of at most `maxChunkLength` characters,
23
+ * preferring to split on a paragraph break, then a sentence terminator,
24
+ * then whitespace, falling back to a hard cut only when none of those are
25
+ * found within the window. Consecutive chunks overlap by up to `overlap`
26
+ * characters so context isn't lost at a chunk boundary. This is the exact
27
+ * chunking algorithm `IngestionService.ingestDocument` uses before
28
+ * embedding, so callers can reproduce ingest-time chunk boundaries exactly
29
+ * given the same `maxChunkLength`/`overlap` (see `DEFAULT_MAX_CHUNK_LENGTH`
30
+ * and `DEFAULT_CHUNK_OVERLAP` for the defaults ingest uses).
31
+ *
32
+ * @param input - The text to chunk; leading/trailing whitespace is trimmed
33
+ * before chunking. Empty/whitespace-only input returns the empty result
34
+ * below without validating `maxChunkLength`/`overlap`.
35
+ * @param maxChunkLength - For non-empty input, maximum characters per chunk;
36
+ * must be an integer >= 2.
37
+ * @param overlap - For non-empty input, maximum number of characters each
38
+ * chunk repeats from the end of the previous chunk; must be a
39
+ * non-negative integer less than `maxChunkLength`. A chunk repeats fewer
40
+ * characters when the previous chunk was shorter than `overlap`.
41
+ * @returns `chunks` — the resulting chunk strings (empty array for
42
+ * empty/whitespace-only input); `truncated` — `true` if any split had to
43
+ * fall back to a hard cut (no paragraph/sentence/whitespace boundary
44
+ * found in the window).
45
+ */
46
+ declare function chunkText(input: string, maxChunkLength: number, overlap: number): {
47
+ chunks: string[];
48
+ truncated: boolean;
49
+ };
50
+
6
51
  declare function formatContext(bundle: MemoryBundle, options?: FormatContextOptions): string;
7
52
 
8
53
  /**
@@ -38,6 +83,22 @@ type GetRandomValues = (bytes: Uint8Array) => void;
38
83
  */
39
84
  declare function configureRandomSource(fn: GetRandomValues | null): void;
40
85
 
86
+ /**
87
+ * Default maximum characters per chunk that `ingestDocument` uses when a
88
+ * caller doesn't override `maxChunkLength` (directly or via
89
+ * `WikiOptions.config.maxChunkLength`).
90
+ */
91
+ declare const DEFAULT_MAX_CHUNK_LENGTH = 12000;
92
+ /**
93
+ * Default/fallback character overlap between consecutive chunks.
94
+ * `ingestDocument` uses this when a caller doesn't override `chunkOverlap`
95
+ * (directly or via `WikiOptions.config.chunkOverlap`), and clamps the
96
+ * effective overlap (including this default) to `maxChunkLength - 1` when
97
+ * needed. The clamp is a no-op for the shipped defaults; it can also apply
98
+ * when a custom `maxChunkLength` makes the resolved overlap too large.
99
+ */
100
+ declare const DEFAULT_CHUNK_OVERLAP = 400;
101
+
41
102
  interface LibrarianOptions {
42
103
  /** If provided, replaces the default Librarian system instructions. */
43
104
  systemPrompt?: string;
@@ -64,4 +125,4 @@ declare const ONTOLOGY_BACKFILL_SYSTEM_PROMPT = "You are a knowledge classificat
64
125
 
65
126
  declare function createWiki(db: SQLiteAdapter, options: WikiOptions): WikiMemory;
66
127
 
67
- export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, FormatContextOptions, FormattedMemoryDump, GraphNeighborhood, type LibrarianOptions, type LibrarianPromptVariables, MemoryBundle, MemoryDump, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, type OkfImportOptions, OntologyManifest, ReadOptions, SQLiteAdapter, WikiMemory, WikiOptions, configureRandomSource, createWiki, formatContext, formatGraphContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, parseOkfBundle, validateLibrarianPromptTemplate, validateManifest };
128
+ export { DEFAULT_CHUNK_OVERLAP, DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, DEFAULT_MAX_CHUNK_LENGTH, FormatContextOptions, FormattedMemoryDump, GraphNeighborhood, type LibrarianOptions, type LibrarianPromptVariables, MemoryBundle, MemoryDump, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, type OkfImportOptions, OntologyManifest, ReadOptions, SQLiteAdapter, WikiMemory, WikiOptions, chunkText, configureRandomSource, createWiki, formatContext, formatGraphContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, parseOkfBundle, safeSlice, validateLibrarianPromptTemplate, validateManifest };
package/dist/index.d.ts CHANGED
@@ -3,6 +3,51 @@ export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as Ext
3
3
  import { OkfFile } from '@equationalapplications/core-okf';
4
4
  import 'minisearch';
5
5
 
6
+ /**
7
+ * Slices a string like `String.prototype.slice`, but clamps out-of-range
8
+ * indices instead of relying on JS's implicit clamping, normalizes a
9
+ * start-after-end range by swapping the two bounds, and nudges either bound
10
+ * off a UTF-16 surrogate pair boundary so slicing never splits one code
11
+ * point in half.
12
+ *
13
+ * @param value - The source string to slice.
14
+ * @param start - Start index; negative counts from the end, out-of-range
15
+ * values are clamped to `[0, value.length]`.
16
+ * @param end - End index (exclusive); defaults to `value.length` when
17
+ * omitted. Same clamping/negative-index rules as `start`.
18
+ * @returns The sliced substring, never splitting a surrogate pair.
19
+ */
20
+ declare function safeSlice(value: string, start: number, end?: number): string;
21
+ /**
22
+ * Splits `input` into chunks of at most `maxChunkLength` characters,
23
+ * preferring to split on a paragraph break, then a sentence terminator,
24
+ * then whitespace, falling back to a hard cut only when none of those are
25
+ * found within the window. Consecutive chunks overlap by up to `overlap`
26
+ * characters so context isn't lost at a chunk boundary. This is the exact
27
+ * chunking algorithm `IngestionService.ingestDocument` uses before
28
+ * embedding, so callers can reproduce ingest-time chunk boundaries exactly
29
+ * given the same `maxChunkLength`/`overlap` (see `DEFAULT_MAX_CHUNK_LENGTH`
30
+ * and `DEFAULT_CHUNK_OVERLAP` for the defaults ingest uses).
31
+ *
32
+ * @param input - The text to chunk; leading/trailing whitespace is trimmed
33
+ * before chunking. Empty/whitespace-only input returns the empty result
34
+ * below without validating `maxChunkLength`/`overlap`.
35
+ * @param maxChunkLength - For non-empty input, maximum characters per chunk;
36
+ * must be an integer >= 2.
37
+ * @param overlap - For non-empty input, maximum number of characters each
38
+ * chunk repeats from the end of the previous chunk; must be a
39
+ * non-negative integer less than `maxChunkLength`. A chunk repeats fewer
40
+ * characters when the previous chunk was shorter than `overlap`.
41
+ * @returns `chunks` — the resulting chunk strings (empty array for
42
+ * empty/whitespace-only input); `truncated` — `true` if any split had to
43
+ * fall back to a hard cut (no paragraph/sentence/whitespace boundary
44
+ * found in the window).
45
+ */
46
+ declare function chunkText(input: string, maxChunkLength: number, overlap: number): {
47
+ chunks: string[];
48
+ truncated: boolean;
49
+ };
50
+
6
51
  declare function formatContext(bundle: MemoryBundle, options?: FormatContextOptions): string;
7
52
 
8
53
  /**
@@ -38,6 +83,22 @@ type GetRandomValues = (bytes: Uint8Array) => void;
38
83
  */
39
84
  declare function configureRandomSource(fn: GetRandomValues | null): void;
40
85
 
86
+ /**
87
+ * Default maximum characters per chunk that `ingestDocument` uses when a
88
+ * caller doesn't override `maxChunkLength` (directly or via
89
+ * `WikiOptions.config.maxChunkLength`).
90
+ */
91
+ declare const DEFAULT_MAX_CHUNK_LENGTH = 12000;
92
+ /**
93
+ * Default/fallback character overlap between consecutive chunks.
94
+ * `ingestDocument` uses this when a caller doesn't override `chunkOverlap`
95
+ * (directly or via `WikiOptions.config.chunkOverlap`), and clamps the
96
+ * effective overlap (including this default) to `maxChunkLength - 1` when
97
+ * needed. The clamp is a no-op for the shipped defaults; it can also apply
98
+ * when a custom `maxChunkLength` makes the resolved overlap too large.
99
+ */
100
+ declare const DEFAULT_CHUNK_OVERLAP = 400;
101
+
41
102
  interface LibrarianOptions {
42
103
  /** If provided, replaces the default Librarian system instructions. */
43
104
  systemPrompt?: string;
@@ -64,4 +125,4 @@ declare const ONTOLOGY_BACKFILL_SYSTEM_PROMPT = "You are a knowledge classificat
64
125
 
65
126
  declare function createWiki(db: SQLiteAdapter, options: WikiOptions): WikiMemory;
66
127
 
67
- export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, FormatContextOptions, FormattedMemoryDump, GraphNeighborhood, type LibrarianOptions, type LibrarianPromptVariables, MemoryBundle, MemoryDump, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, type OkfImportOptions, OntologyManifest, ReadOptions, SQLiteAdapter, WikiMemory, WikiOptions, configureRandomSource, createWiki, formatContext, formatGraphContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, parseOkfBundle, validateLibrarianPromptTemplate, validateManifest };
128
+ export { DEFAULT_CHUNK_OVERLAP, DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, DEFAULT_MAX_CHUNK_LENGTH, FormatContextOptions, FormattedMemoryDump, GraphNeighborhood, type LibrarianOptions, type LibrarianPromptVariables, MemoryBundle, MemoryDump, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, type OkfImportOptions, OntologyManifest, ReadOptions, SQLiteAdapter, WikiMemory, WikiOptions, chunkText, configureRandomSource, createWiki, formatContext, formatGraphContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, parseOkfBundle, safeSlice, validateLibrarianPromptTemplate, validateManifest };
package/dist/index.js CHANGED
@@ -3063,6 +3063,10 @@ ${JSON.stringify(facts, null, 2)}`
3063
3063
  }
3064
3064
  };
3065
3065
 
3066
+ // src/utils/chunkingDefaults.ts
3067
+ var DEFAULT_MAX_CHUNK_LENGTH = 12e3;
3068
+ var DEFAULT_CHUNK_OVERLAP = 400;
3069
+
3066
3070
  // src/services/IngestionService.ts
3067
3071
  var IngestionService = class {
3068
3072
  constructor(db, prefix, options, entryRepo, searchService, jobManager, embeddingService, promptService, ontologyService) {
@@ -3081,10 +3085,10 @@ var IngestionService = class {
3081
3085
  if (!sourceRef) throw new Error("Invalid sourceRef");
3082
3086
  const sourceHash = normalizeSourceHash(params.sourceHash);
3083
3087
  if (!sourceHash) throw new Error("Invalid sourceHash (must be 64-char hex string)");
3084
- const maxChunkLength = params.maxChunkLength ?? this.options.config?.maxChunkLength ?? 12e3;
3085
- const rawOverlap = params.chunkOverlap ?? this.options.config?.chunkOverlap ?? 400;
3088
+ const maxChunkLength = params.maxChunkLength ?? this.options.config?.maxChunkLength ?? DEFAULT_MAX_CHUNK_LENGTH;
3089
+ const rawOverlap = params.chunkOverlap ?? this.options.config?.chunkOverlap ?? DEFAULT_CHUNK_OVERLAP;
3086
3090
  const chunkOverlap = Math.min(
3087
- Number.isFinite(rawOverlap) && rawOverlap >= 0 ? Math.floor(rawOverlap) : 400,
3091
+ Number.isFinite(rawOverlap) && rawOverlap >= 0 ? Math.floor(rawOverlap) : DEFAULT_CHUNK_OVERLAP,
3088
3092
  maxChunkLength - 1
3089
3093
  );
3090
3094
  const rawConcurrency = params.chunkConcurrency ?? this.options.config?.chunkConcurrency ?? 1;
@@ -3791,10 +3795,10 @@ var MaintenanceService = class {
3791
3795
  const validNewFacts = newFacts.map(validateFact).filter((f) => f !== null);
3792
3796
  const insertedFacts = [];
3793
3797
  const uniqueDeletedFactIds = Array.from(new Set(safeDeleted));
3794
- const healFactsForDedupe = (await this.entryRepo.findInferredTitlesByEntityId(entityId)).filter((f) => !safeDeletedSet.has(f.id));
3795
3798
  await this.db.withTransactionAsync(async (tx) => {
3796
3799
  await this.entryRepo.downgradeByIds(safeDowngraded, entityId, tx);
3797
3800
  await this.entryRepo.softDeleteByIds(safeDeleted, entityId, tx);
3801
+ const healFactsForDedupe = await this.entryRepo.findInferredTitlesByEntityId(entityId, tx);
3798
3802
  for (const fact of validNewFacts) {
3799
3803
  const newTokens = titleTokens(fact.title);
3800
3804
  let skip = false;
@@ -6526,7 +6530,9 @@ function createWiki(db, options) {
6526
6530
  return new WikiMemory(db, options);
6527
6531
  }
6528
6532
 
6533
+ exports.DEFAULT_CHUNK_OVERLAP = DEFAULT_CHUNK_OVERLAP;
6529
6534
  exports.DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT = DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT;
6535
+ exports.DEFAULT_MAX_CHUNK_LENGTH = DEFAULT_MAX_CHUNK_LENGTH;
6530
6536
  exports.HEAL_BATCH_SIZE = HEAL_BATCH_SIZE;
6531
6537
  exports.HEAL_RECHECK_MS = HEAL_RECHECK_MS;
6532
6538
  exports.HOOK_TIMEOUT_MARKER = HOOK_TIMEOUT_MARKER;
@@ -6539,6 +6545,7 @@ exports.PrunePartialFailureError = PrunePartialFailureError;
6539
6545
  exports.WikiBusyError = WikiBusyError;
6540
6546
  exports.WikiMemory = WikiMemory;
6541
6547
  exports.WikiTransactionError = WikiTransactionError;
6548
+ exports.chunkText = chunkText;
6542
6549
  exports.configureRandomSource = configureRandomSource;
6543
6550
  exports.createWiki = createWiki;
6544
6551
  exports.formatContext = formatContext;
@@ -6549,6 +6556,7 @@ exports.hydrateLibrarianPrompt = hydrateLibrarianPrompt;
6549
6556
  exports.mapLibrarianOptionsToReadOptions = mapLibrarianOptionsToReadOptions;
6550
6557
  exports.parseEmbedding = parseEmbedding;
6551
6558
  exports.parseOkfBundle = parseOkfBundle;
6559
+ exports.safeSlice = safeSlice;
6552
6560
  exports.validateLibrarianPromptTemplate = validateLibrarianPromptTemplate;
6553
6561
  exports.validateManifest = validateManifest;
6554
6562
  //# sourceMappingURL=index.js.map