@equationalapplications/core-llm-wiki 4.23.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -2
- package/dist/{chunk-MYZJLVX4.mjs → chunk-DM7BKDCV.mjs} +220 -154
- package/dist/chunk-DM7BKDCV.mjs.map +1 -0
- package/dist/index.d.mts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.js +184 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +101 -12
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-CBjAuTSl.d.mts → testing-DCRNie7k.d.mts} +118 -10
- package/dist/{testing-CBjAuTSl.d.ts → testing-DCRNie7k.d.ts} +118 -10
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +79 -13
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/chunk-MYZJLVX4.mjs.map +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,53 @@
|
|
|
1
|
-
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, O as OntologyManifest, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-
|
|
2
|
-
export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as ExtractedFactWithOntology, g as ExtractedTask, h as GraphTraversalOptions, H as HOOK_TIMEOUT_MARKER, L as LLMProvider,
|
|
1
|
+
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, O as OntologyManifest, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-DCRNie7k.mjs';
|
|
2
|
+
export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as ExtractedFactWithOntology, g as ExtractedTask, h as GraphTraversalOptions, H as HEAL_BATCH_SIZE, i as HEAL_RECHECK_MS, j as HOOK_TIMEOUT_MARKER, k as HealResult, L as LLMProvider, l as ONTOLOGY_BACKFILL_BATCH_SIZE, m as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, n as ONTOLOGY_BACKFILL_RECHECK_MS, o as OntologyBackfillResult, p as OntologyConfig, q as OntologyEdgeType, r as OntologyMode, s as OntologyNodeType, t as OntologyPromptContext, u as OntologyUpdates, P as PromptOverrides, v as PromptService, w as PrunePartialFailureError, V as VectorRanker, x as VectorRankerFallback, y as VectorRankerRankArgs, z as VectorRankerSemanticResult, A as WikiBusyError, B as WikiBusyOperation, C as WikiCheckpoint, D as WikiConfig, I as WikiEdge, J as WikiEvent, K as WikiFact, N as WikiMemoryTestAccess, Q as WikiOutboxEvent, T as WikiTask, U as WikiTransactionError } from './testing-DCRNie7k.mjs';
|
|
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
|
@@ -1,8 +1,53 @@
|
|
|
1
|
-
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, O as OntologyManifest, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-
|
|
2
|
-
export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as ExtractedFactWithOntology, g as ExtractedTask, h as GraphTraversalOptions, H as HOOK_TIMEOUT_MARKER, L as LLMProvider,
|
|
1
|
+
import { M as MemoryBundle, F as FormatContextOptions, G as GraphNeighborhood, a as MemoryDump, b as FormattedMemoryDump, O as OntologyManifest, R as ReadOptions, S as SQLiteAdapter, W as WikiOptions, c as WikiMemory } from './testing-DCRNie7k.js';
|
|
2
|
+
export { E as EntityStatus, d as ExtractedFact, e as ExtractedFactEdge, f as ExtractedFactWithOntology, g as ExtractedTask, h as GraphTraversalOptions, H as HEAL_BATCH_SIZE, i as HEAL_RECHECK_MS, j as HOOK_TIMEOUT_MARKER, k as HealResult, L as LLMProvider, l as ONTOLOGY_BACKFILL_BATCH_SIZE, m as ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, n as ONTOLOGY_BACKFILL_RECHECK_MS, o as OntologyBackfillResult, p as OntologyConfig, q as OntologyEdgeType, r as OntologyMode, s as OntologyNodeType, t as OntologyPromptContext, u as OntologyUpdates, P as PromptOverrides, v as PromptService, w as PrunePartialFailureError, V as VectorRanker, x as VectorRankerFallback, y as VectorRankerRankArgs, z as VectorRankerSemanticResult, A as WikiBusyError, B as WikiBusyOperation, C as WikiCheckpoint, D as WikiConfig, I as WikiEdge, J as WikiEvent, K as WikiFact, N as WikiMemoryTestAccess, Q as WikiOutboxEvent, T as WikiTask, U as WikiTransactionError } from './testing-DCRNie7k.js';
|
|
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
|
@@ -36,7 +36,8 @@ async function setupDatabase(db, prefix) {
|
|
|
36
36
|
embedding TEXT,
|
|
37
37
|
embedding_blob BLOB,
|
|
38
38
|
okf_type TEXT,
|
|
39
|
-
ontology_checked_at INTEGER
|
|
39
|
+
ontology_checked_at INTEGER,
|
|
40
|
+
heal_checked_at INTEGER
|
|
40
41
|
);
|
|
41
42
|
|
|
42
43
|
CREATE INDEX IF NOT EXISTS ${prefix}entries_entity_idx ON ${prefix}entries(entity_id);
|
|
@@ -353,6 +354,20 @@ var MIGRATIONS = [
|
|
|
353
354
|
);
|
|
354
355
|
}
|
|
355
356
|
}
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
version: 8,
|
|
360
|
+
description: "Add heal_checked_at to entries for heal recheck cooldown",
|
|
361
|
+
run: async (db, prefix) => {
|
|
362
|
+
const cols = await db.getAllAsync(
|
|
363
|
+
`PRAGMA table_info(${prefix}entries)`
|
|
364
|
+
);
|
|
365
|
+
if (!cols.some((c) => c.name === "heal_checked_at")) {
|
|
366
|
+
await db.execAsync(
|
|
367
|
+
`ALTER TABLE ${prefix}entries ADD COLUMN heal_checked_at INTEGER`
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
356
371
|
}
|
|
357
372
|
];
|
|
358
373
|
for (let i = 1; i < MIGRATIONS.length; i++) {
|
|
@@ -709,17 +724,21 @@ var EntryRepository = class extends BaseRepository {
|
|
|
709
724
|
}
|
|
710
725
|
/**
|
|
711
726
|
* Fetch live, mutable entries for an entity — everything heal is allowed to
|
|
712
|
-
* downgrade or delete
|
|
713
|
-
*
|
|
714
|
-
*
|
|
727
|
+
* downgrade or delete — oldest first, capped at `limit`, skipping anything
|
|
728
|
+
* stamped inside the recheck cooldown (heal_checked_at > recheckCutoff).
|
|
729
|
+
*
|
|
730
|
+
* Oldest-first rather than newest-first: with a cooldown in place, newest-first
|
|
731
|
+
* would keep re-selecting recently-touched facts every pass while older ones
|
|
732
|
+
* wait indefinitely to even enter a batch.
|
|
715
733
|
*/
|
|
716
|
-
async findHealCandidatesByEntityId(entityId, tx) {
|
|
734
|
+
async findHealCandidatesByEntityId(entityId, limit, recheckCutoff, tx) {
|
|
717
735
|
const executor = this.getExecutor(tx);
|
|
718
736
|
const rows = await executor.getAllAsync(
|
|
719
737
|
`SELECT * FROM ${this.prefix}entries
|
|
720
738
|
WHERE entity_id = ? AND deleted_at IS NULL AND source_type != 'immutable_document'
|
|
721
|
-
|
|
722
|
-
|
|
739
|
+
AND (heal_checked_at IS NULL OR heal_checked_at <= ?)
|
|
740
|
+
ORDER BY updated_at ASC LIMIT ?`,
|
|
741
|
+
[entityId, recheckCutoff, limit]
|
|
723
742
|
);
|
|
724
743
|
return rows.map(mapRowToFact);
|
|
725
744
|
}
|
|
@@ -882,6 +901,10 @@ var EntryRepository = class extends BaseRepository {
|
|
|
882
901
|
/**
|
|
883
902
|
* Downgrade stale inferred entries to 'tentative'.
|
|
884
903
|
* Used by MaintenanceService.doRunHeal().
|
|
904
|
+
*
|
|
905
|
+
* Returns the ids it downgraded so the caller can fold them into
|
|
906
|
+
* {@link HealResult.downgraded} without double-counting a fact the model also
|
|
907
|
+
* downgraded in the same pass.
|
|
885
908
|
*/
|
|
886
909
|
async downgradeStaleInferred(entityId, staleThreshold, tx) {
|
|
887
910
|
const executor = this.getExecutor(tx);
|
|
@@ -893,8 +916,8 @@ var EntryRepository = class extends BaseRepository {
|
|
|
893
916
|
AND source_type != 'immutable_document' AND deleted_at IS NULL`,
|
|
894
917
|
[entityId, staleThreshold, staleThreshold]
|
|
895
918
|
);
|
|
896
|
-
if (eligibleRows.length === 0) return
|
|
897
|
-
|
|
919
|
+
if (eligibleRows.length === 0) return [];
|
|
920
|
+
await executor.runAsync(
|
|
898
921
|
`UPDATE ${this.prefix}entries
|
|
899
922
|
SET confidence = 'tentative', updated_at = ?
|
|
900
923
|
WHERE entity_id = ? AND confidence = 'inferred' AND (last_accessed_at <= ? OR (last_accessed_at IS NULL AND created_at <= ?)) AND source_type != 'immutable_document' AND deleted_at IS NULL`,
|
|
@@ -909,7 +932,7 @@ var EntryRepository = class extends BaseRepository {
|
|
|
909
932
|
payload: { id: row.id, entity_id: entityId, confidence: "tentative", updated_at: now }
|
|
910
933
|
}, tx);
|
|
911
934
|
}
|
|
912
|
-
return
|
|
935
|
+
return eligibleRows.map((r) => r.id);
|
|
913
936
|
}
|
|
914
937
|
/**
|
|
915
938
|
* Downgrade specific entries to 'tentative' by IDs.
|
|
@@ -1228,6 +1251,58 @@ var EntryRepository = class extends BaseRepository {
|
|
|
1228
1251
|
);
|
|
1229
1252
|
return rows.map((r) => ({ id: r.id, title: r.title, okf_type: r.okf_type ?? null }));
|
|
1230
1253
|
}
|
|
1254
|
+
/** Counts live mutable facts: eligible (past cooldown) vs deferred (in cooldown). */
|
|
1255
|
+
async countHealCandidatesByEntityId(entityId, recheckCutoff, tx) {
|
|
1256
|
+
const executor = this.getExecutor(tx);
|
|
1257
|
+
const row = await executor.getFirstAsync(
|
|
1258
|
+
`SELECT
|
|
1259
|
+
SUM(CASE WHEN heal_checked_at IS NULL OR heal_checked_at <= ? THEN 1 ELSE 0 END) AS eligible,
|
|
1260
|
+
SUM(CASE WHEN heal_checked_at IS NOT NULL AND heal_checked_at > ? THEN 1 ELSE 0 END) AS deferred
|
|
1261
|
+
FROM ${this.prefix}entries
|
|
1262
|
+
WHERE entity_id = ? AND deleted_at IS NULL AND source_type != 'immutable_document'`,
|
|
1263
|
+
[recheckCutoff, recheckCutoff, entityId]
|
|
1264
|
+
);
|
|
1265
|
+
return { eligible: Number(row?.eligible ?? 0), deferred: Number(row?.deferred ?? 0) };
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Stamps the heal recheck cooldown. NEVER touches updated_at — import merge
|
|
1269
|
+
* resolution is last-write-wins on updated_at and a bump here would make an
|
|
1270
|
+
* unchanged local fact beat a genuinely newer remote edit.
|
|
1271
|
+
*
|
|
1272
|
+
* Soft-deleted rows are skipped: a candidate heal deleted earlier in the same
|
|
1273
|
+
* transaction is no longer a candidate under any future pass, so its cooldown
|
|
1274
|
+
* value is irrelevant. This means the stamped count can be lower than the
|
|
1275
|
+
* offered-candidate count.
|
|
1276
|
+
*/
|
|
1277
|
+
async markHealChecked(ids, entityId, now, tx) {
|
|
1278
|
+
if (ids.length === 0) return;
|
|
1279
|
+
for (let i = 0; i < ids.length; i += this.chunkSize) {
|
|
1280
|
+
const chunk = ids.slice(i, i + this.chunkSize);
|
|
1281
|
+
const placeholders = chunk.map(() => "?").join(",");
|
|
1282
|
+
await tx.runAsync(
|
|
1283
|
+
`UPDATE ${this.prefix}entries SET heal_checked_at = ?
|
|
1284
|
+
WHERE id IN (${placeholders}) AND entity_id = ? AND deleted_at IS NULL`,
|
|
1285
|
+
[now, ...chunk, entityId]
|
|
1286
|
+
);
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Lightweight full-breadth index (id, title) over all live librarian_inferred
|
|
1291
|
+
* facts. This is heal's fuzzy-dedupe corpus, deliberately kept independent of
|
|
1292
|
+
* the bounded candidate window: seeding dedupe from a batchSize-limited read
|
|
1293
|
+
* would let a synthesized fact duplicating a fact outside the window pass the
|
|
1294
|
+
* Jaccard check, and a convergence loop would multiply those duplicates across
|
|
1295
|
+
* passes. Mirrors findTitleIndexByEntityId — full breadth, two columns, cheap.
|
|
1296
|
+
*/
|
|
1297
|
+
async findInferredTitlesByEntityId(entityId, tx) {
|
|
1298
|
+
const executor = this.getExecutor(tx);
|
|
1299
|
+
const rows = await executor.getAllAsync(
|
|
1300
|
+
`SELECT id, title FROM ${this.prefix}entries
|
|
1301
|
+
WHERE entity_id = ? AND deleted_at IS NULL AND source_type = 'librarian_inferred'`,
|
|
1302
|
+
[entityId]
|
|
1303
|
+
);
|
|
1304
|
+
return rows.map((r) => ({ id: r.id, title: r.title }));
|
|
1305
|
+
}
|
|
1231
1306
|
};
|
|
1232
1307
|
|
|
1233
1308
|
// src/utils/ids.ts
|
|
@@ -2988,6 +3063,10 @@ ${JSON.stringify(facts, null, 2)}`
|
|
|
2988
3063
|
}
|
|
2989
3064
|
};
|
|
2990
3065
|
|
|
3066
|
+
// src/utils/chunkingDefaults.ts
|
|
3067
|
+
var DEFAULT_MAX_CHUNK_LENGTH = 12e3;
|
|
3068
|
+
var DEFAULT_CHUNK_OVERLAP = 400;
|
|
3069
|
+
|
|
2991
3070
|
// src/services/IngestionService.ts
|
|
2992
3071
|
var IngestionService = class {
|
|
2993
3072
|
constructor(db, prefix, options, entryRepo, searchService, jobManager, embeddingService, promptService, ontologyService) {
|
|
@@ -3006,10 +3085,10 @@ var IngestionService = class {
|
|
|
3006
3085
|
if (!sourceRef) throw new Error("Invalid sourceRef");
|
|
3007
3086
|
const sourceHash = normalizeSourceHash(params.sourceHash);
|
|
3008
3087
|
if (!sourceHash) throw new Error("Invalid sourceHash (must be 64-char hex string)");
|
|
3009
|
-
const maxChunkLength = params.maxChunkLength ?? this.options.config?.maxChunkLength ??
|
|
3010
|
-
const rawOverlap = params.chunkOverlap ?? this.options.config?.chunkOverlap ??
|
|
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;
|
|
3011
3090
|
const chunkOverlap = Math.min(
|
|
3012
|
-
Number.isFinite(rawOverlap) && rawOverlap >= 0 ? Math.floor(rawOverlap) :
|
|
3091
|
+
Number.isFinite(rawOverlap) && rawOverlap >= 0 ? Math.floor(rawOverlap) : DEFAULT_CHUNK_OVERLAP,
|
|
3013
3092
|
maxChunkLength - 1
|
|
3014
3093
|
);
|
|
3015
3094
|
const rawConcurrency = params.chunkConcurrency ?? this.options.config?.chunkConcurrency ?? 1;
|
|
@@ -3252,6 +3331,8 @@ var ONTOLOGY_BACKFILL_RECHECK_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
3252
3331
|
var HEAL_MAX_ANCHORS = 50;
|
|
3253
3332
|
var HEAL_ANCHOR_SEARCH_OVERFETCH = 4;
|
|
3254
3333
|
var HEAL_MAX_PROMPT_CHARS = 4e4;
|
|
3334
|
+
var HEAL_BATCH_SIZE = 25;
|
|
3335
|
+
var HEAL_RECHECK_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
3255
3336
|
var MaintenanceService = class {
|
|
3256
3337
|
constructor(db, prefix, options, entryRepo, taskRepo, eventRepo, metadataRepo, searchService, jobManager, embeddingService, promptService, ontologyService) {
|
|
3257
3338
|
this.db = db;
|
|
@@ -3352,7 +3433,7 @@ var MaintenanceService = class {
|
|
|
3352
3433
|
async runHeal(entityId, options) {
|
|
3353
3434
|
this.jobManager.acquireLock("heal", entityId);
|
|
3354
3435
|
try {
|
|
3355
|
-
await this.doRunHeal(entityId, options
|
|
3436
|
+
return await this.doRunHeal(entityId, options);
|
|
3356
3437
|
} finally {
|
|
3357
3438
|
this.jobManager.releaseLock("heal", entityId);
|
|
3358
3439
|
}
|
|
@@ -3604,9 +3685,21 @@ var MaintenanceService = class {
|
|
|
3604
3685
|
}
|
|
3605
3686
|
this.searchService.evictCache(entityId);
|
|
3606
3687
|
}
|
|
3607
|
-
/**
|
|
3608
|
-
|
|
3688
|
+
/**
|
|
3689
|
+
* Core heal pass (locks handled by {@link runHeal}). Package-internal orchestration hook.
|
|
3690
|
+
*
|
|
3691
|
+
* Bounded: at most `batchSize` candidates per pass (#67). Loop on
|
|
3692
|
+
* `result.remaining > 0` for convergence — see {@link HealResult.remaining}
|
|
3693
|
+
* for what convergence means here.
|
|
3694
|
+
*/
|
|
3695
|
+
async doRunHeal(entityId, options) {
|
|
3696
|
+
const promptOverride = options?.promptOverride;
|
|
3697
|
+
const batchSize = options?.batchSize ?? HEAL_BATCH_SIZE;
|
|
3698
|
+
if (!Number.isInteger(batchSize) || batchSize < 1) {
|
|
3699
|
+
throw new Error("Invalid batchSize: must be an integer >= 1");
|
|
3700
|
+
}
|
|
3609
3701
|
const now = Date.now();
|
|
3702
|
+
const recheckCutoff = now - HEAL_RECHECK_MS;
|
|
3610
3703
|
const orphanAfterDays = this.options.config?.orphanAfterDays !== void 0 ? this.options.config?.orphanAfterDays : 30;
|
|
3611
3704
|
const staleInferredAfterDays = this.options.config?.staleInferredAfterDays !== void 0 ? this.options.config?.staleInferredAfterDays : 60;
|
|
3612
3705
|
const MS_PER_DAY = 24 * 60 * 60 * 1e3;
|
|
@@ -3617,6 +3710,7 @@ var MaintenanceService = class {
|
|
|
3617
3710
|
throw new Error("Invalid staleInferredAfterDays: must be a finite number >= 0 or null");
|
|
3618
3711
|
}
|
|
3619
3712
|
const orphanedIds = [];
|
|
3713
|
+
const staleDowngradedIds = [];
|
|
3620
3714
|
await this.db.withTransactionAsync(async (tx) => {
|
|
3621
3715
|
if (orphanAfterDays !== null) {
|
|
3622
3716
|
const orphanThreshold = now - orphanAfterDays * MS_PER_DAY;
|
|
@@ -3624,7 +3718,7 @@ var MaintenanceService = class {
|
|
|
3624
3718
|
}
|
|
3625
3719
|
if (staleInferredAfterDays !== null) {
|
|
3626
3720
|
const staleThreshold = now - staleInferredAfterDays * MS_PER_DAY;
|
|
3627
|
-
await this.entryRepo.downgradeStaleInferred(entityId, staleThreshold, tx);
|
|
3721
|
+
staleDowngradedIds.push(...await this.entryRepo.downgradeStaleInferred(entityId, staleThreshold, tx));
|
|
3628
3722
|
}
|
|
3629
3723
|
});
|
|
3630
3724
|
for (const factId of orphanedIds) {
|
|
@@ -3634,7 +3728,21 @@ var MaintenanceService = class {
|
|
|
3634
3728
|
console.warn(`[WikiMemory] onEmbeddingPersisted hook failed during heal orphan pass for ${factId}:`, hookErr);
|
|
3635
3729
|
}
|
|
3636
3730
|
}
|
|
3637
|
-
const healCandidates = await this.entryRepo.findHealCandidatesByEntityId(entityId);
|
|
3731
|
+
const healCandidates = await this.entryRepo.findHealCandidatesByEntityId(entityId, batchSize, recheckCutoff);
|
|
3732
|
+
if (healCandidates.length === 0) {
|
|
3733
|
+
await this.searchService.sync(entityId);
|
|
3734
|
+
this.searchService.evictCache(entityId);
|
|
3735
|
+
const counts2 = await this.entryRepo.countHealCandidatesByEntityId(entityId, recheckCutoff);
|
|
3736
|
+
return {
|
|
3737
|
+
scanned: 0,
|
|
3738
|
+
downgraded: staleDowngradedIds.length,
|
|
3739
|
+
deleted: orphanedIds.length,
|
|
3740
|
+
newFactsCreated: 0,
|
|
3741
|
+
skipped: 0,
|
|
3742
|
+
remaining: counts2.eligible,
|
|
3743
|
+
deferred: counts2.deferred
|
|
3744
|
+
};
|
|
3745
|
+
}
|
|
3638
3746
|
const allTasks = await this.taskRepo.findAllPending([entityId]);
|
|
3639
3747
|
const recentEvents = await this.eventRepo.getRecent(entityId, 20);
|
|
3640
3748
|
const toPromptShape = (f) => {
|
|
@@ -3687,7 +3795,7 @@ var MaintenanceService = class {
|
|
|
3687
3795
|
const validNewFacts = newFacts.map(validateFact).filter((f) => f !== null);
|
|
3688
3796
|
const insertedFacts = [];
|
|
3689
3797
|
const uniqueDeletedFactIds = Array.from(new Set(safeDeleted));
|
|
3690
|
-
const healFactsForDedupe =
|
|
3798
|
+
const healFactsForDedupe = (await this.entryRepo.findInferredTitlesByEntityId(entityId)).filter((f) => !safeDeletedSet.has(f.id));
|
|
3691
3799
|
await this.db.withTransactionAsync(async (tx) => {
|
|
3692
3800
|
await this.entryRepo.downgradeByIds(safeDowngraded, entityId, tx);
|
|
3693
3801
|
await this.entryRepo.softDeleteByIds(safeDeleted, entityId, tx);
|
|
@@ -3696,7 +3804,6 @@ var MaintenanceService = class {
|
|
|
3696
3804
|
let skip = false;
|
|
3697
3805
|
if (newTokens.size >= MIN_TOKENS_TO_QUALIFY) {
|
|
3698
3806
|
for (const existing of healFactsForDedupe) {
|
|
3699
|
-
if (existing.source_type !== "librarian_inferred") continue;
|
|
3700
3807
|
const existingTokens = titleTokens(existing.title);
|
|
3701
3808
|
if (existingTokens.size >= MIN_TOKENS_TO_QUALIFY) {
|
|
3702
3809
|
if (jaccardScore(newTokens, existingTokens) >= FUZZY_THRESHOLD) {
|
|
@@ -3726,8 +3833,14 @@ var MaintenanceService = class {
|
|
|
3726
3833
|
};
|
|
3727
3834
|
await this.entryRepo.upsert(factObj, tx);
|
|
3728
3835
|
insertedFacts.push({ id, entity_id: entityId, title: fact.title, body: fact.body, tags: JSON.stringify(fact.tags) });
|
|
3729
|
-
healFactsForDedupe.push(
|
|
3836
|
+
healFactsForDedupe.push({ id, title: fact.title });
|
|
3730
3837
|
}
|
|
3838
|
+
await this.entryRepo.markHealChecked(
|
|
3839
|
+
[...healCandidates.map((f) => f.id), ...insertedFacts.map((f) => f.id)],
|
|
3840
|
+
entityId,
|
|
3841
|
+
now,
|
|
3842
|
+
tx
|
|
3843
|
+
);
|
|
3731
3844
|
});
|
|
3732
3845
|
await this.searchService.sync(entityId);
|
|
3733
3846
|
for (const factId of uniqueDeletedFactIds) {
|
|
@@ -3741,6 +3854,20 @@ var MaintenanceService = class {
|
|
|
3741
3854
|
await this.embeddingService.embedFact(fact);
|
|
3742
3855
|
}
|
|
3743
3856
|
this.searchService.evictCache(entityId);
|
|
3857
|
+
let scanned = outcome.skipped.length;
|
|
3858
|
+
for (const batchResult of outcome.results) scanned += batchResult.batch.length;
|
|
3859
|
+
const allDowngraded = /* @__PURE__ */ new Set([...staleDowngradedIds, ...safeDowngraded]);
|
|
3860
|
+
const allDeleted = /* @__PURE__ */ new Set([...orphanedIds, ...uniqueDeletedFactIds]);
|
|
3861
|
+
const counts = await this.entryRepo.countHealCandidatesByEntityId(entityId, recheckCutoff);
|
|
3862
|
+
return {
|
|
3863
|
+
scanned,
|
|
3864
|
+
downgraded: allDowngraded.size,
|
|
3865
|
+
deleted: allDeleted.size,
|
|
3866
|
+
newFactsCreated: insertedFacts.length,
|
|
3867
|
+
skipped: outcome.skipped.length,
|
|
3868
|
+
remaining: counts.eligible,
|
|
3869
|
+
deferred: counts.deferred
|
|
3870
|
+
};
|
|
3744
3871
|
}
|
|
3745
3872
|
/** Core ontology backfill pass (locks handled by {@link runOntologyBackfill}). Package-internal orchestration hook. */
|
|
3746
3873
|
async doRunOntologyBackfill(entityId, options) {
|
|
@@ -5116,6 +5243,7 @@ var WriteService = class {
|
|
|
5116
5243
|
let shouldRunLibrarian = false;
|
|
5117
5244
|
let librarianCount = 0;
|
|
5118
5245
|
let prevMemoryCheckpoint = 0;
|
|
5246
|
+
let eventCount = 0;
|
|
5119
5247
|
await this.db.withTransactionAsync(async (tx) => {
|
|
5120
5248
|
await this.eventRepo.add(newEvent, tx);
|
|
5121
5249
|
const threshold = this.options.config?.autoLibrarianThreshold || 20;
|
|
@@ -5123,6 +5251,7 @@ var WriteService = class {
|
|
|
5123
5251
|
this.eventRepo.count(entityId, tx),
|
|
5124
5252
|
this.metadataRepo.getCheckpoint(entityId, tx)
|
|
5125
5253
|
]);
|
|
5254
|
+
eventCount = count;
|
|
5126
5255
|
let memoryCheckpoint = cp.memory ?? 0;
|
|
5127
5256
|
if (memoryCheckpoint > count) memoryCheckpoint = 0;
|
|
5128
5257
|
if (count - memoryCheckpoint >= threshold) {
|
|
@@ -5144,6 +5273,8 @@ var WriteService = class {
|
|
|
5144
5273
|
if (!(e instanceof WikiBusyError)) throw e;
|
|
5145
5274
|
await this.metadataRepo.updateCheckpoint(entityId, { memory: prevMemoryCheckpoint }, this.db);
|
|
5146
5275
|
}
|
|
5276
|
+
} else if (!this.jobManager.isBlocked("librarian", entityId)) {
|
|
5277
|
+
this.maybeRunHeal(entityId, eventCount).catch(console.error);
|
|
5147
5278
|
}
|
|
5148
5279
|
}
|
|
5149
5280
|
async runLibrarianThenMaybeHeal(entityId, currentEventCount, prevCheckpoint) {
|
|
@@ -5154,6 +5285,14 @@ var WriteService = class {
|
|
|
5154
5285
|
await this.metadataRepo.updateCheckpoint(entityId, { memory: prevCheckpoint }, this.db);
|
|
5155
5286
|
throw e;
|
|
5156
5287
|
}
|
|
5288
|
+
await this.maybeRunHeal(entityId, currentEventCount);
|
|
5289
|
+
}
|
|
5290
|
+
/**
|
|
5291
|
+
* Run one bounded auto-heal pass if the heal checkpoint has fallen
|
|
5292
|
+
* `autoHealThreshold` events behind. Called after every write (see
|
|
5293
|
+
* {@link write}) so a partial pass retries on the next write.
|
|
5294
|
+
*/
|
|
5295
|
+
async maybeRunHeal(entityId, currentEventCount) {
|
|
5157
5296
|
const autoHealThreshold = this.options.config?.autoHealThreshold || 100;
|
|
5158
5297
|
const cp = await this.metadataRepo.getCheckpoint(entityId, this.db);
|
|
5159
5298
|
let healCheckpoint = cp.heal ?? 0;
|
|
@@ -5161,8 +5300,10 @@ var WriteService = class {
|
|
|
5161
5300
|
const shouldRunHeal = currentEventCount - healCheckpoint >= autoHealThreshold;
|
|
5162
5301
|
if (shouldRunHeal && this.jobManager.tryAcquireAutoHealLock(entityId)) {
|
|
5163
5302
|
try {
|
|
5164
|
-
await this.maintenanceService.doRunHeal(entityId);
|
|
5165
|
-
|
|
5303
|
+
const result = await this.maintenanceService.doRunHeal(entityId);
|
|
5304
|
+
if (result.remaining === 0) {
|
|
5305
|
+
await this.metadataRepo.updateCheckpoint(entityId, { heal: currentEventCount }, this.db);
|
|
5306
|
+
}
|
|
5166
5307
|
} finally {
|
|
5167
5308
|
this.jobManager.releaseLock("heal", entityId);
|
|
5168
5309
|
}
|
|
@@ -5513,9 +5654,23 @@ var WikiMemory = class {
|
|
|
5513
5654
|
return this.maintenanceService.runLibrarian(entityId, options);
|
|
5514
5655
|
}
|
|
5515
5656
|
/**
|
|
5657
|
+
* Reviews stored facts with the LLM: removes orphans, downgrades stale
|
|
5658
|
+
* inferences, synthesizes corrections.
|
|
5659
|
+
*
|
|
5660
|
+
* Bounded per call: covers at most `batchSize` candidates (default 25), so
|
|
5661
|
+
* one call no longer sweeps the whole entity. Hosts own the cadence; loop
|
|
5662
|
+
* `while (result.remaining > 0)` for convergence.
|
|
5663
|
+
*
|
|
5664
|
+
* `remaining === 0` means "every mutable fact is inside the 7-day recheck
|
|
5665
|
+
* cooldown", not "there is no more work" — heal's candidate set is the live
|
|
5666
|
+
* mutable corpus, not a draining backlog, so it climbs back as the cooldown
|
|
5667
|
+
* lapses and as new facts are written. Do not write a loop expecting a drain.
|
|
5668
|
+
*
|
|
5516
5669
|
* @param options.promptOverride - Applies only to this manual call. Does NOT affect
|
|
5517
5670
|
* WriteService-triggered auto-runs. For persistent prompt customization across auto-runs,
|
|
5518
5671
|
* set `options.config.prompts.healSystemPrompt` at WikiMemory construction time.
|
|
5672
|
+
* @param options.batchSize - Candidates per run (default 25) for providers with
|
|
5673
|
+
* tighter context limits.
|
|
5519
5674
|
*/
|
|
5520
5675
|
async runHeal(entityId, options) {
|
|
5521
5676
|
return this.maintenanceService.runHeal(entityId, options);
|
|
@@ -6375,7 +6530,11 @@ function createWiki(db, options) {
|
|
|
6375
6530
|
return new WikiMemory(db, options);
|
|
6376
6531
|
}
|
|
6377
6532
|
|
|
6533
|
+
exports.DEFAULT_CHUNK_OVERLAP = DEFAULT_CHUNK_OVERLAP;
|
|
6378
6534
|
exports.DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT = DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT;
|
|
6535
|
+
exports.DEFAULT_MAX_CHUNK_LENGTH = DEFAULT_MAX_CHUNK_LENGTH;
|
|
6536
|
+
exports.HEAL_BATCH_SIZE = HEAL_BATCH_SIZE;
|
|
6537
|
+
exports.HEAL_RECHECK_MS = HEAL_RECHECK_MS;
|
|
6379
6538
|
exports.HOOK_TIMEOUT_MARKER = HOOK_TIMEOUT_MARKER;
|
|
6380
6539
|
exports.ONTOLOGY_BACKFILL_BATCH_SIZE = ONTOLOGY_BACKFILL_BATCH_SIZE;
|
|
6381
6540
|
exports.ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS = ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS;
|
|
@@ -6386,6 +6545,7 @@ exports.PrunePartialFailureError = PrunePartialFailureError;
|
|
|
6386
6545
|
exports.WikiBusyError = WikiBusyError;
|
|
6387
6546
|
exports.WikiMemory = WikiMemory;
|
|
6388
6547
|
exports.WikiTransactionError = WikiTransactionError;
|
|
6548
|
+
exports.chunkText = chunkText;
|
|
6389
6549
|
exports.configureRandomSource = configureRandomSource;
|
|
6390
6550
|
exports.createWiki = createWiki;
|
|
6391
6551
|
exports.formatContext = formatContext;
|
|
@@ -6396,6 +6556,7 @@ exports.hydrateLibrarianPrompt = hydrateLibrarianPrompt;
|
|
|
6396
6556
|
exports.mapLibrarianOptionsToReadOptions = mapLibrarianOptionsToReadOptions;
|
|
6397
6557
|
exports.parseEmbedding = parseEmbedding;
|
|
6398
6558
|
exports.parseOkfBundle = parseOkfBundle;
|
|
6559
|
+
exports.safeSlice = safeSlice;
|
|
6399
6560
|
exports.validateLibrarianPromptTemplate = validateLibrarianPromptTemplate;
|
|
6400
6561
|
exports.validateManifest = validateManifest;
|
|
6401
6562
|
//# sourceMappingURL=index.js.map
|