import { SearchResult } from 'minisearch'; /** * Platform-agnostic SQLite driver interface. * Each platform package (wiki-expo, wiki-react) provides an adapter * that wraps its native driver behind this interface. */ interface SQLiteAdapter { execAsync(sql: string): Promise; runAsync(sql: string, params?: unknown[]): Promise<{ changes: number; lastInsertRowId: number; }>; getAllAsync(sql: string, params?: unknown[]): Promise; getFirstAsync(sql: string, params?: unknown[]): Promise; /** * Runs `fn` inside a transaction. A bare adapter implementation is not required to * serialize concurrent calls itself — `WikiMemory` wraps every adapter it's given in * `withSerializedTransactions` (see `db/serializedAdapter.ts`), which is what makes * transactions serialize in practice. Once wrapped, inside the callback use ONLY the * provided `tx` handle — never the outer database handle (captured via closure or * `this.db`). Calling the outer handle deadlocks against the transaction mutex; * calling `tx.withTransactionAsync` throws (nested transactions are unsupported). */ withTransactionAsync(fn: (tx: SQLiteAdapter) => Promise): Promise; closeAsync(): Promise; } interface PromptOverrides { ingestSystemPrompt?: string; librarianSystemPrompt?: string; healSystemPrompt?: string; ontologyBackfillSystemPrompt?: string; } type OntologyMode = 'strict' | 'emergent' | 'off'; interface OntologyNodeType { type: string; description: string; } interface OntologyEdgeType { type: string; source_type: string; target_type: string; description: string; } /** * Allowed node and edge types for an entity's ontology graph. * Persisted per entity and injected into librarian/ingest prompts when mode ≠ `off`. */ interface OntologyManifest { node_types: OntologyNodeType[]; edge_types: OntologyEdgeType[]; } /** * Global ontology defaults and bootstrap manifests for known entities. * Per-entity mode and manifest overrides are stored in SQLite and managed via * `WikiMemory.getOntologyManifest` / `setOntologyManifest`. */ interface OntologyConfig { /** Global default mode. Default: `'off'` (backward compatible — no typed extraction). */ mode?: OntologyMode; /** * Bootstrap manifests for known entities at construction time. * Written to the database on first access if no row exists for that entity. */ seedManifests?: Record; } interface ExtractedFactEdge { edge_type: string; target_title: string; } interface OntologyUpdates { node_types?: OntologyNodeType[]; edge_types?: OntologyEdgeType[]; } interface OntologyPromptContext { ontologyManifest: string; ontologyModeInstructions: string; } /** Result of a single ontology backfill run. Omissions (facts the model declined * to classify) are derivable as scanned − typed − failedValidation. */ interface OntologyBackfillResult { /** Untyped facts sent to the model this run. */ scanned: number; /** Facts that received an okf_type. */ typed: number; /** Model classifications rejected (unknown/duplicate id, non-manifest type). */ failedValidation: number; /** Edges persisted. */ edgesAdded: number; /** Untyped facts still eligible after this run — safe host convergence signal: loop while > 0. * Always 0 when ontology mode is 'off' (nothing is eligible for typing while * disabled), so 0 does not imply queue exhaustion in that mode. */ remaining: number; /** Untyped facts inside the recheck cooldown. */ deferred: number; } interface WikiConfig { /** * Prefix applied to every SQL table/index/trigger name. Must match * `^[A-Za-z][A-Za-z0-9_]{0,30}_$` (letter, then alphanumeric/underscore, * ending in `_`, max 32 chars total) — enforced in the `WikiMemory` constructor. * Default: `'llm_wiki_'`. */ tablePrefix?: string; maxResults?: number; /** @deprecated Use maxResults */ maxFtsResults?: number; pruneEventsAfter?: number; pruneRetainSoftDeletedFor?: number; autoLibrarianThreshold?: number; autoHealThreshold?: number; orphanAfterDays?: number | null; staleInferredAfterDays?: number | null; maxChunkLength?: number; chunkOverlap?: number; chunkConcurrency?: number; /** * Max MiniSearch candidates passed to cosine scoring. * When set, MiniSearch pre-filters before the cosine scan. * Only applies when embed is provided and succeeds. * Default: undefined (full scan). */ preFilterLimit?: number; /** * Hybrid blend weight (0.0–1.0). * 0.0 = pure keyword (skips embed() entirely). * 1.0 = pure semantic. * Values outside [0,1] are clamped. Ignored when embed is absent or throws. * Default: undefined (pure semantic when embed provided). */ hybridWeight?: number; /** Global prompt overrides for text generation calls (`ingestDocument`, `runLibrarian`, `runHeal`). Does not affect embedding generation. Runtime overrides on individual method calls take precedence. */ prompts?: PromptOverrides; /** * When true, entry and task mutations append an event to the internal outbox table. * The table is always created; this flag only controls whether writes occur. * @default false */ enableOutbox?: boolean; ontology?: OntologyConfig; /** Default node cap for traverseGraph(), unless overridden per-call. Default 20. */ maxTraversalNodes?: number; /** Default minimum confidence tier for discovered traversal nodes. Default 'tentative'. */ minTraversalConfidence?: 'certain' | 'inferred' | 'tentative'; /** Default traversal direction. Default 'both'. */ traversalDirection?: 'inbound' | 'outbound' | 'both'; /** Default source_type dead-end list for discovered traversal nodes. Default []. */ excludeSourceTypes?: Array; } interface ReadOptions { maxResults?: number; /** * undefined → use WikiConfig.preFilterLimit (or no pre-filter if also unset). * null → explicitly disable a config-level preFilterLimit for this call. */ preFilterLimit?: number | null; hybridWeight?: number; /** * Per-entity score multiplier for multi-entity reads. Missing entries default to 1.0. * Entities with weight 0 are skipped during scored retrieval unless * `includeZeroWeightEntities` is true; in that case they rank below all finite scores. * Only meaningful when `entityId` is an array; ignored for single-string calls. */ tierWeights?: Record; /** * When true, entities with a tier weight of 0 are included in scored retrieval * as bottom fillers (ranked below every finite-scored candidate). * When false (default), zero-weight entities are skipped entirely. * Only meaningful when `entityId` is an array; ignored for single-string calls. */ includeZeroWeightEntities?: boolean; } interface WikiFact { id: string; entity_id: string; title: string; body: string; tags: string[]; confidence: 'certain' | 'inferred' | 'tentative'; /** * Source type of this fact. * - 'immutable_document': From ingestDocument(), cannot be modified by system (librarian/heal). * Only removable via forget() or replaced via re-ingest. * - 'librarian_inferred': Created by runLibrarian() from events, or by runHeal() when synthesizing new inferred facts. * - 'user_stated': Direct user statement. * - 'user_confirmed': User-confirmed fact. */ source_type: 'user_stated' | 'librarian_inferred' | 'user_confirmed' | 'immutable_document'; source_hash: string | null; source_ref: string | null; created_at: number; updated_at: number; /** * Raw Float32Array bytes for the fact's embedding vector. * Set when the fact was fetched via exportDump() with blob preservation. * Accepted in importDump() as a real Uint8Array (in-memory round-trip), * a Node.js Buffer JSON shape `{ type: 'Buffer', data: number[] }`, * or a numeric-keyed plain object `{ 0: byte, 1: byte, ... }` produced * by JSON.stringify(Uint8Array). */ embedding_blob?: Uint8Array | { type: 'Buffer'; data: number[]; } | Record | null; last_accessed_at: number | null; access_count: number; deleted_at: number | null; /** * Verbatim OKF `type:` frontmatter value when this fact originated from (or was * re-imported via) an OKF bundle. `null`/`undefined` for facts never touched by * OKF import. Distinct from `source_type`, which governs immutability rules. */ okf_type?: string | null; } interface WikiTask { id: string; entity_id: string; description: string; status: 'pending' | 'in_progress' | 'done' | 'abandoned'; priority: number; created_at: number; updated_at: number; resolved_at: number | null; deleted_at: number | null; /** Verbatim OKF `type:` frontmatter value when this task originated from an OKF bundle. */ okf_type?: string | null; } interface WikiEvent { id: string; entity_id: string; event_type: 'observation' | 'decision' | 'action' | 'outcome'; summary: string; related_entry_id?: string | null; created_at: number; } interface WikiEdge { id: string; entity_id: string; source_id: string; target_id: string; edge_type: string; created_at: number; } interface GraphTraversalOptions { sourceId: string; /** Hop count. Default 1. Clamped to [1, 3] regardless of input. */ maxDepth?: number; /** Default 'both'. Falls back to WikiConfig.traversalDirection, then 'both'. */ direction?: 'inbound' | 'outbound' | 'both'; /** * Allowed edge types. `undefined` = no filter (all types). * `[]` (explicit empty array) = match nothing — distinct from `undefined`. */ edgeTypes?: string[]; /** Total node cap (anchor + neighbors). Default 20 via WikiConfig.maxTraversalNodes. */ maxTraversalNodes?: number; /** Minimum confidence tier for *discovered* nodes. Does not gate the anchor. Default 'tentative'. */ minTraversalConfidence?: 'certain' | 'inferred' | 'tentative'; /** source_type values to dead-end on for *discovered* nodes. Does not gate the anchor. Default []. */ excludeSourceTypes?: Array; } interface GraphNeighborhood { /** Anchor node first, then discovered neighbors ordered by depth ASC, then updated_at DESC. */ nodes: WikiFact[]; /** Only edges where both endpoints are present in `nodes`. */ edges: WikiEdge[]; } interface WikiCheckpoint { entity_id: string; heal_checkpoint: number; memory_checkpoint: number; } interface ExtractedFact { title: string; body: string; tags: string[]; confidence: 'certain' | 'inferred' | 'tentative'; } interface ExtractedFactWithOntology extends ExtractedFact { okf_type?: string; edges?: ExtractedFactEdge[]; } interface ExtractedTask { description: string; priority: number; } interface LLMProvider { /** * Generates text using the developer's LLM of choice. * Expected to return the raw text response (typically a JSON string). */ generateText: (params: { systemPrompt: string; userPrompt: string; }) => Promise; /** * Optional. When provided, enables semantic similarity search in `read()`. * Must return a stable-dimension float array for any input text. * Called once per fact on creation/update, and once per `read()` query. * When absent or throws, `read()` falls back to MiniSearch. */ embed?: (text: string) => Promise; } /** * Result of semantic ranking for a single fact. */ interface VectorRankerSemanticResult { id: string; /** Cosine similarity in [-1, 1] when exact; implementations MAY document other monotonic scales. */ semanticScore: number; } /** * Arguments passed to VectorRanker.rankBySimilarity. */ interface VectorRankerRankArgs { entityId: string; /** * Query embedding. Treat as readonly — core provides a defensive copy, * but adapters MUST NOT mutate this array. Mutation can corrupt * WikiMemory's internal vector cache and JS-cosine fallback path. */ queryVec: Float32Array | number[]; /** * When set (MiniSearch pre-filter path): ranker MUST only produce results for ids in this set. * When omitted (full-entity semantic path): ranker scopes by entityId per its backing store contract. */ candidateIds?: readonly string[]; /** * Upper bound on how many distinct fact ids should receive a semanticScore in this call. * WikiMemory derives this from maxResults / candidate cardinality / documented oversampling policy. */ limit: number; } /** * Optional backend for semantic candidate scoring / top-k retrieval. * When omitted, WikiMemory scores rows with embedding_blob / embedding TEXT in JS (cosine). */ interface VectorRanker { /** * Return semantic scores for facts in scope, sorted descending by semanticScore (stable tie-breaking * not required — WikiMemory reapplies existing tie-breakers after blending). * Implementations SHOULD omit facts with no usable vector; callers treat missing ids like today's * "no embedding" rows (pure semantic: -2; hybrid: keyword-only portion). */ rankBySimilarity(args: VectorRankerRankArgs): Promise; /** * Called after a fact's embedding is successfully persisted to embedding_blob (or cleared). * Hosts use this to keep sqlite-vec / external indexes consistent with SQLite as source of truth. * * On deletion paths (forget, prune, hard-delete), core awaits this hook to ensure ANN cleanup * completes before the deletion call resolves (GDPR compliance). Hook failures or timeouts on * those paths reject the deletion call. * * Treat `vector` as readonly — core provides a defensive copy, but adapters MUST NOT mutate. * * Optional: if omitted, hosts MUST document "index rebuilt separately" and accept stale ANN until rebuild. */ onEmbeddingPersisted?(event: { entityId: string; factId: string; vector: Float32Array | null; }): void | Promise; } /** * Fallback policy when rankBySimilarity rejects. */ type VectorRankerFallback = 'js-cosine' | 'keyword' | 'empty' | 'throw'; interface WikiOptions { config?: WikiConfig; llmProvider: LLMProvider; /** * Called when embedding-based retrieval is degraded or unavailable during `read()`. * This can happen when: * - `embed()` throws (e.g. network error, model unavailable) → falls back to keyword search * - `embed()` returns a vector with non-finite values (NaN / Infinity) → falls back to keyword search * - The query vector's dimension doesn't match stored embeddings (model switch; * resolve by calling `runReembed()`) → falls back to keyword search * - `vectorRanker` returns IDs that don't belong to the requested entity or don't exist * (ranker integrity issue; returned rows will be filtered out, reducing result count) → * may still use semantic ranking, but with degraded quality * * `read()` returns results (keyword fallback or degraded semantic) — this is a notification, not an error path. */ onRetrievalFallback?: (error: Error) => void; /** * Optional backend for semantic candidate scoring / top-k retrieval. * When omitted, WikiMemory scores rows with embedding_blob / embedding TEXT in JS (cosine). */ vectorRanker?: VectorRanker; /** * When rankBySimilarity throws. Default `'js-cosine'`. * Ignored when vectorRanker is undefined. */ vectorRankerFallback?: VectorRankerFallback; /** * Called only when rankBySimilarity rejects (after embeddings path succeeded). * Invoked before applying vectorRankerFallback when that policy recovers or before rejecting when policy is 'throw'. */ onVectorRankerFallback?: (info: { error: Error; /** Effective policy core will apply for this read (same as WikiOptions.vectorRankerFallback, default js-cosine). */ policy: VectorRankerFallback; }) => void; /** * When true: after rankBySimilarity failure, once the recoverable fallback has finished * and read() will resolve, invoke onRetrievalFallback — after onVectorRankerFallback if set. * Ignored when vectorRankerFallback is 'throw'. Default false. */ propagateRankerFailureToRetrievalFallback?: boolean; /** * When true (default), sanitize ranker errors before exposing via error.cause * to prevent credential leakage in host telemetry. Disable only when you * control the ranker implementation. * * Sanitization replaces error message/stack with a generic message preserving * only the error type (constructor name). */ sanitizeRankerErrors?: boolean; /** * Timeout (ms) for onEmbeddingPersisted hook on GDPR deletion paths * (forget, _doPrune). Hook must complete within this window or the * deletion operation rejects. Default 30000. * Lower for interactive deletes; raise for slow remote ANN backends. */ deletionHookTimeoutMs?: number; /** * Escape hatch: skip onEmbeddingPersisted on deletion paths entirely. * Use ONLY when the ANN backend is permanently decommissioned. Vectors * orphaned in the (unreachable) external index are accepted as a tradeoff. * NOT GDPR-safe for live indexes. Default false. */ forceDeleteIgnoreRankerHook?: boolean; } interface MemoryBundle { facts: WikiFact[]; tasks: WikiTask[]; events: WikiEvent[]; edges?: WikiEdge[]; /** Entity summary prose for OKF profile ≥ 1 round-trip. Omitted = no summary (Clanker default). */ summary?: string; factScores?: Record; metadata?: { query: string; entityIds: string[]; tierWeights?: Record; }; } interface MemoryDump { generatedAt: number; entities: Record; } interface FormattedMemoryDump { manifest: string; files: Array<{ name: string; content: string; }>; } interface FormatContextOptions { format?: 'markdown' | 'plain'; maxFacts?: number; maxTasks?: number; maxEvents?: number; includeConfidence?: boolean; includeTags?: boolean; includeEntityIds?: boolean; includeFactScores?: boolean; factWeights?: { confidence?: number; accessCount?: number; recency?: number; }; } interface EntityStatus { ingesting: boolean; librarian: boolean; heal: boolean; } /** * All operations that can appear in a {@link WikiBusyError}. * * @remarks **Breaking change from v2.x** — the union previously only contained * `'ingest' | 'librarian' | 'heal' | 'prune' | 'reembed'`. The values `'import'` * and `'forget'` were added in v3.0. `'ontologyBackfill'` was added afterward. * Exhaustive `switch` / narrowing on this type must be updated (or given a * `default` arm) to compile without errors. */ type WikiBusyOperation = 'ingest' | 'librarian' | 'heal' | 'prune' | 'reembed' | 'import' | 'forget' | 'ontologyBackfill'; /** * Thrown when a background mutator is already running for the requested entity. */ declare class WikiBusyError extends Error { readonly operation: WikiBusyOperation; readonly entityId: string; constructor(operation: WikiBusyOperation, entityId: string); } /** * Thrown by the serialized transaction wrapper when a SQLite driver error * escapes a transaction callback (nested BEGIN, SQLITE_BUSY, constraint * violation). Domain errors thrown from callback logic pass through unwrapped. * Stable `instanceof` target for observability, mirroring {@link WikiBusyError}. */ declare class WikiTransactionError extends Error { /** Best-effort SQLite code lifted from the driver error, e.g. 'SQLITE_BUSY'. */ readonly sqliteErrorCode?: string; constructor(message: string, options: { cause: unknown; }); } declare class PrunePartialFailureError extends Error { readonly deleted: number; readonly failedAt: string; readonly remaining: number; readonly deletedTasks: number; readonly deletedEvents: number; readonly cause: Error; constructor(deleted: number, failedAt: string, remaining: number, cause: Error, deletedTasks?: number, deletedEvents?: number); } declare const HOOK_TIMEOUT_MARKER: unique symbol; interface WikiOutboxEvent { id: string; entity_id: string; table_name: string; record_id: string; operation: 'INSERT' | 'UPDATE' | 'DELETE'; payload: T; created_at: number; } /** * Abstract base for all repositories. * Provides db accessor + prefix-aware helpers. */ declare abstract class BaseRepository { protected db: SQLiteAdapter; protected prefix: string; constructor(db: SQLiteAdapter, prefix: string); /** * Return the DB executor for a given transaction handle. * If tx is provided, use it; otherwise fall back to this.db. */ protected getExecutor(tx?: SQLiteAdapter): SQLiteAdapter; } declare class OutboxRepository extends BaseRepository { private enableOutbox; constructor(db: SQLiteAdapter, prefix: string, enableOutbox?: boolean); /** * Insert a new outbox event within the provided transaction. * No-op when enableOutbox is false. * `tx` is required — callers must always pass the active transaction * so the write is atomic with the main table mutation. */ push(params: { entityId: string; tableName: string; recordId: string; operation: 'INSERT' | 'UPDATE' | 'DELETE'; payload: any; }, tx: SQLiteAdapter): Promise; /** * Fetch pending outbox rows ordered by created_at ASC, rowid ASC. * Reads directly from `this.db` (not a transaction). */ fetchPending(limit?: number): Promise; /** * Delete acknowledged outbox rows by their IDs. * No-op when `ids` is empty. * Deletes directly from `this.db` (not a transaction). */ acknowledge(ids: string[]): Promise; } type EntryRowMetadata = { id: string; entity_id: string; updated_at: number | null; access_count: number | null; }; type EntryRowWithEmbeddings = EntryRowMetadata & { embedding_blob: Uint8Array | null; embedding: string | null; }; declare class EntryRepository extends BaseRepository { private outbox; private chunkSize; constructor(db: SQLiteAdapter, prefix: string, outbox: OutboxRepository); /** * Fetch facts by IDs, optionally scoped to entity IDs. * Returns facts in the order of the input IDs (first match wins). */ findByIds(ids: readonly string[], scopedEntityIds?: readonly string[], tx?: SQLiteAdapter): Promise; /** * Upsert a WikiFact. Nullable fields set to null when fact value is null. * Returns { changes, lastInsertRowId }. * `tx` is REQUIRED to ensure atomic outbox staging. */ upsert(fact: WikiFact, tx: SQLiteAdapter): Promise<{ changes: number; lastInsertRowId: number; }>; /** * Normalize an embedding blob value to Uint8Array or null. */ private normalizeEmbeddingBlob; /** * Fetch existing rows by IDs and return id/entity_id/updated_at for import collision resolution. */ findExistingMetadataByIds(ids: readonly string[], tx?: SQLiteAdapter): Promise>; findIdById(id: string, entityId: string, tx?: SQLiteAdapter): Promise; findIdsBySource(entityId: string, sourceRef: string | null, sourceHash: string | null, tx?: SQLiteAdapter, includeDeleted?: boolean): Promise; upsertForImport(fact: WikiFact, tx: SQLiteAdapter): Promise<{ changes: number; lastInsertRowId: number; }>; /** * Soft-delete a single entry by ID scoped to entityId. Sets deleted_at + updated_at. * `tx` is REQUIRED to ensure atomic outbox staging. */ softDelete(entryId: string, entityId: string, tx: SQLiteAdapter): Promise<{ changes: number; }>; /** * Soft-delete entries by source_ref and/or source_hash within a transaction. * Stages a DELETE outbox entry for each row in the same transaction. * `tx` is REQUIRED. * Returns the number of rows deleted. */ softDeleteBySource(entityId: string, tx: SQLiteAdapter, sourceRef?: string | null, sourceHash?: string | null): Promise; /** * Fetch IDs + entity_ids of soft-deleted rows older than cutoff for a given entity. * Used by runPrune(). */ getPrunableMetadata(entityId: string, cutoff: number, tx?: SQLiteAdapter): Promise>; /** * Fetch all non-deleted entries for an entity, ordered by updated_at DESC. * Used by _getFullBundle(). */ findAllByEntityId(entityId: string, tx?: SQLiteAdapter): Promise; /** * Fetch recent non-deleted entries for an entity (limited), ordered by updated_at DESC. * Used by MaintenanceService.doRunLibrarian(). */ findRecentByEntityId(entityId: string, limit: number, tx?: SQLiteAdapter): Promise; /** * Fetch all non-deleted entries for an entity with embedding blobs preserved. * Used by ImportExportService for export/import round-tripping. */ findAllByEntityIdWithBlobs(entityId: string, tx?: SQLiteAdapter): Promise; /** * Count non-deleted entries for the given entities whose embedding_blob dimension * doesn't match queryVecLength. Used by read() to detect model-switch mismatches. */ countDimensionMismatched(entityIds: readonly string[], queryVecLength: number, tx?: SQLiteAdapter): Promise; /** * Count non-deleted entries for entityId that are stale relative to targetDim * (either no blob or wrong dimension). Used by runReembed() per-entity skip logic. */ countStaleForEntity(entityId: string, targetDim: number, tx?: SQLiteAdapter): Promise; /** * Count non-deleted entries with stale or unconverted embeddings relative to `dim`. * Used by _reconcileEmbeddingDimension() to decide when to promote the pending * embedding_dimension value. */ countStaleEmbeddings(dim: number, tx?: SQLiteAdapter): Promise; /** * Bulk delete pruned entries (already soft-deleted) by IDs. * Used by runPrune(). Returns total number of deleted rows. * `tx` is REQUIRED so outbox deletion events are staged atomically. */ bulkDeletePruned(entityId: string, cutoff: number, ids: string[], tx: SQLiteAdapter): Promise; /** * Mark orphaned entries (never accessed, old) as deleted. * Used by MaintenanceService.doRunHeal(). */ markOrphaned(entityId: string, orphanThreshold: number, tx: SQLiteAdapter): Promise; /** * Downgrade stale inferred entries to 'tentative'. * Used by MaintenanceService.doRunHeal(). */ downgradeStaleInferred(entityId: string, staleThreshold: number, tx: SQLiteAdapter): Promise; /** * Downgrade specific entries to 'tentative' by IDs. * Used by MaintenanceService.doRunHeal(). */ downgradeByIds(ids: string[], entityId: string, tx: SQLiteAdapter): Promise; /** * Soft-delete specific entries by IDs. * Used by MaintenanceService.doRunHeal(). */ softDeleteByIds(ids: string[], entityId: string, tx: SQLiteAdapter): Promise; /** * Bulk soft-delete all entries for an entity. * Stages DELETE outbox entries for each row in the same transaction. * `tx` is REQUIRED. */ bulkSoftDeleteByEntityId(entityId: string, tx: SQLiteAdapter): Promise; findMiniSearchRows(entityId?: string, tx?: SQLiteAdapter): Promise>; updateEmbeddingBlob(id: string, blob: Uint8Array, tx?: SQLiteAdapter): Promise; hasLegacySourceTypes(tx?: SQLiteAdapter): Promise; countLegacySourceTypes(tx?: SQLiteAdapter): Promise; findAllForReembed(entityId?: string, tx?: SQLiteAdapter): Promise>; findRowsForSourceRefMigration(tx?: SQLiteAdapter): Promise>; updateSourceRefByRowid(rowid: number, sourceRef: string | null, tx: SQLiteAdapter): Promise; findLatestSourceHash(entityId: string, sourceRef: string, tx?: SQLiteAdapter): Promise; findMetadataByIds(ids: readonly string[], tx?: SQLiteAdapter): Promise; findWithEmbeddingsByIds(ids: readonly string[], tx?: SQLiteAdapter): Promise; findMetadataByEntityIds(entityIds: readonly string[], tx?: SQLiteAdapter): Promise; findWithEmbeddingsByEntityIds(entityIds: readonly string[], tx?: SQLiteAdapter): Promise; findEmbeddingsByIds(ids: readonly string[], tx?: SQLiteAdapter): Promise>; trackAccess(ids: readonly string[], now: number, tx?: SQLiteAdapter): Promise; getLegacyMigrationSQL(): string; findRecentByEntityIds(entityIds: readonly string[], limit: number, tx?: SQLiteAdapter): Promise; /** * Live untyped facts eligible for ontology backfill, oldest first. * Skips facts checked within the recheck cooldown (ontology_checked_at > recheckCutoff). */ findUntypedByEntityId(entityId: string, limit: number, recheckCutoff: number, tx?: SQLiteAdapter): Promise; /** Counts live untyped facts: eligible (past cooldown) vs deferred (in cooldown). */ countUntypedByEntityId(entityId: string, recheckCutoff: number, tx?: SQLiteAdapter): Promise<{ eligible: number; deferred: number; }>; /** * Sets okf_type only when currently NULL — additive by construction: a * concurrently-typed fact is never overwritten. Returns changes for the caller * to distinguish applied vs skipped. */ updateOkfType(id: string, entityId: string, okfType: string, tx: SQLiteAdapter): Promise<{ changes: number; }>; /** * Stamps the backfill recheck cooldown. NEVER touches updated_at — import * merge resolution is last-write-wins on updated_at and a bump here would * make an unchanged local fact beat a genuinely newer remote edit. */ markOntologyChecked(ids: string[], entityId: string, now: number, tx: SQLiteAdapter): Promise; /** * Lightweight full-breadth title index (id, title, okf_type) over all live * typed facts. Used by ontology backfill edge resolution — a recent-N window * would miss an old fact's contemporaries. Untyped rows are excluded: they * can never pass the edge target-type check, and batch facts typed during * the run are re-added to the in-memory index by the caller. */ findTitleIndexByEntityId(entityId: string, tx?: SQLiteAdapter): Promise>; } declare class MetadataRepository extends BaseRepository { getCheckpoint(entityId: string, tx: SQLiteAdapter): Promise<{ memory?: number; heal?: number; }>; updateCheckpoint(entityId: string, updates: { memory?: number; heal?: number; }, tx: SQLiteAdapter): Promise; deleteCheckpoint(entityId: string, tx: SQLiteAdapter): Promise; getMeta(key: string, tx?: SQLiteAdapter): Promise; setMeta(key: string, value: string, tx: SQLiteAdapter): Promise; deleteMeta(key: string, tx?: SQLiteAdapter): Promise; clearDimensionMismatch(tx: SQLiteAdapter): Promise; tableExists(tableName: string, tx?: SQLiteAdapter): Promise; getTableDdl(tableName: string, tx?: SQLiteAdapter): Promise; vacuum(): Promise; getDistinctEntityIds(tx?: SQLiteAdapter): Promise; getManifest(entityId: string, tx?: SQLiteAdapter): Promise<{ mode: OntologyMode; manifest: OntologyManifest; } | null>; setManifest(entityId: string, data: { mode: OntologyMode; manifest: OntologyManifest; }, tx: SQLiteAdapter): Promise; mergeManifestUpdates(entityId: string, updates: OntologyUpdates, tx: SQLiteAdapter): Promise; } interface ScoredRow { id: string; entity_id: string; score: number; updated_at: number | null; access_count: number | null; } interface RankSemanticArgs { entityId: string; queryVec: Float32Array | number[]; candidateRows: Array<{ id: string; entity_id: string; embedding_blob: Uint8Array | null; embedding: string | null; updated_at: number | null; access_count: number | null; }>; weight: number | undefined; miniSearchScores: Map | undefined; populateCache: boolean; limit: number; skipSort?: boolean; } declare class SearchService { private entryRepo; /** * Maximum number of entities whose parsed embedding vectors are held in * memory. This cap is intentionally conservative so the cache remains safe * on memory-constrained runtimes (e.g., mobile/Expo). */ private static readonly MAX_VECTOR_CACHE_ENTITIES; /** * Maximum number of fact vectors cached per entity. Keep this high enough to * preserve the parsed-embedding reuse optimization for common mid-sized * entities while still maintaining a bounded memory footprint. */ private static readonly MAX_VECTOR_CACHE_FACTS_PER_ENTITY; private miniSearch; private miniSearchEntryIdsByEntity; private vectorCache; constructor(entryRepo: EntryRepository); /** * Rebuilds the search index and clears the vector cache for a given entity. * A direct replacement for manually syncing state after a DB transaction. */ sync(entityId?: string): Promise; /** * Clears the parsed vector cache. Useful for mid-loop flush guarantees * or memory pressure evictions. */ evictCache(entityId?: string): void; /** * Fully resets the search service. */ clearAll(): void; /** * Executes a keyword search against the active MiniSearch index. */ searchKeyword(query: string, entityIds: string[], limit: number): SearchResult[]; /** * Pre-fetches MiniSearch scores for candidate hydration, used during hybrid weighting. */ getMiniSearchScores(query: string, entityIds: string[], preFilterLimit?: number): Map; /** * Score candidate rows using in-process JS cosine similarity. * Applies hybrid blending (if weight set) and tie-break sorting before returning. */ rankSemantic(args: RankSemanticArgs): Promise; private rebuildIndex; private normalizeMiniSearchRow; private _tieBreakSort; private _compareScoredRows; } type OperationType = 'prune' | 'librarian' | 'heal' | 'ingest' | 'reembed' | 'global_reembed' | 'import' | 'global_import' | 'forget' | 'ontologyBackfill'; declare class JobManager { private prefix; private activeMaintenanceJobs; private activeIngestJobs; private statusSubscribers; constructor(prefix: string); private _pruneKey; private _reembedKey; private _globalReembedKey; private _importKey; private _globalImportKey; private _forgetKey; private _librarianKey; private _healKey; private _ontologyBackfillKey; /** * Lookup table for acquireLock/releaseLock's dynamic-dispatch branch. * Excludes 'ingest' | 'global_reembed' | 'global_import', which those * methods already handle via explicit if/else branches before reaching * this table. */ private readonly lockKeyFns; private _isReembedActive; private _isImportActiveFor; private _isForgetActiveFor; private _isAnyMaintenanceActiveWithSuffix; private _hasIngestJob; private _addIngestJob; private _removeIngestJob; private _isIngestActiveFor; acquireLock(operation: OperationType, entityId: string, sourceRef?: string): void; releaseLock(operation: OperationType, entityId: string, sourceRef?: string): void; /** * Returns true if acquireLock(operation, entityId) would throw WikiBusyError. * Use for non-throwing conflict checks (e.g. auto-trigger gating in write()). */ isBlocked(operation: OperationType, entityId: string): boolean; /** * Auto-heal historically only gated on the heal self-key. Keep that behavior * for write() auto-trigger paths while preserving stricter checks in acquireLock(). */ tryAcquireAutoHealLock(entityId: string): boolean; /** * Validates then acquires global + per-entity import locks atomically. * Validates all entities before acquiring any lock (same as current importDump semantics). */ acquireImportLocks(entityIds: string[]): void; releaseImportLocks(entityIds: string[]): void; getEntityStatus(entityId: string): EntityStatus; subscribeEntityStatus(entityId: string, callback: (status: EntityStatus) => void): () => void; private _copyEntityStatus; private _notifyStatusSubscribers; } declare class EmbeddingService { private db; private options; private entryRepo; private metadataRepo; constructor(db: SQLiteAdapter, options: WikiOptions, entryRepo: EntryRepository, metadataRepo: MetadataRepository); storeEmbeddingDimension(dim: number): Promise; /** Promotes embedding_dimension_mismatch to canonical embedding_dimension when safe. */ reconcileEmbeddingDimension(): Promise; embedFact(fact: { id: string; entity_id: string; title: string; body: string; tags: string | string[]; }): Promise; notifyEmbeddingPersisted(entityId: string, factId: string, vector: Float32Array | null): Promise; notifyEmbeddingPersistedOrThrow(entityId: string, factId: string, vector: Float32Array | null): Promise; } interface NeighborhoodQueryOptions { maxDepth: number; direction: 'inbound' | 'outbound' | 'both'; edgeTypes?: string[]; minConfidence: 'certain' | 'inferred' | 'tentative'; excludeSourceTypes: string[]; maxNodes: number; } declare class EdgeRepository extends BaseRepository { /** * Insert an edge, silently skipping on primary-key or uniqueness conflicts. * Returns true when a row was inserted, false when skipped as a duplicate. * Throws when the insert was skipped due to an id collision with a different edge tuple. */ addIgnoreDuplicate(edge: WikiEdge, tx?: SQLiteAdapter): Promise; getByEntityId(entityId: string, tx?: SQLiteAdapter): Promise; /** Hard delete — edges have no soft-delete concept, only presence/absence. `tx` is REQUIRED. */ bulkDeleteByEntityId(entityId: string, tx: SQLiteAdapter): Promise; /** * Multi-hop traversal from `sourceId` via SQLite `WITH RECURSIVE`. All filtering, * dead-ending, cycle-guarding, capping, and ordering happens in this one query. * The anchor is validated (exists, right entity, not soft-deleted) but never gated * by confidence/source_type — only nodes discovered beyond it are. */ getNeighborhood(entityId: string, sourceId: string, opts: NeighborhoodQueryOptions, tx?: SQLiteAdapter): Promise<{ nodeIds: string[]; edges: WikiEdge[]; }>; } type TitleIndexEntry = { id: string; okf_type: string | null; }; /** * Coordinates ontology mode resolution, manifest caching, LLM output validation, and edge persistence. * Cache is per WikiMemory instance (single-process); not shared across instances. */ declare class OntologyService { private metadataRepo; private edgeRepo; private ontologyConfig?; private cache; constructor(metadataRepo: MetadataRepository, edgeRepo: EdgeRepository, ontologyConfig?: OntologyConfig | undefined); resolveMode(storedMode?: OntologyMode): OntologyMode; invalidateCache(entityId: string): void; getEffectiveState(entityId: string, tx?: SQLiteAdapter): Promise<{ mode: OntologyMode; manifest: OntologyManifest; }>; buildPromptContext(entityId: string): Promise; mergeEmergentUpdates(entityId: string, updates: OntologyUpdates, tx: SQLiteAdapter): Promise; validateAndNormalizeFact(fact: ExtractedFactWithOntology, manifest: OntologyManifest): { okf_type: string | null; edges: ExtractedFactEdge[]; }; resolveAndPersistEdges(entityId: string, sourceId: string, sourceType: string | null, edges: ExtractedFactEdge[], manifest: OntologyManifest, titleIndex: Map, tx: SQLiteAdapter, now: number): Promise; } declare class PromptService { private globalOverrides?; constructor(globalOverrides?: PromptOverrides | undefined); private hydrate; private hasOntologyPlaceholders; private buildSystemPrompt; private appendOntology; buildIngestPrompt(documentChunk: string, runtimeOverride?: string, ontologyContext?: OntologyPromptContext | null): { systemPrompt: string; userPrompt: string; }; buildLibrarianPrompt(events: unknown[], currentFacts: unknown[], runtimeOverride?: string, ontologyContext?: OntologyPromptContext | null): { systemPrompt: string; userPrompt: string; }; buildHealPrompt(healCandidates: unknown[], documentAnchors: unknown[], allTasks: unknown[], recentEvents: unknown[], runtimeOverride?: string): { systemPrompt: string; userPrompt: string; }; buildOntologyBackfillPrompt(facts: unknown[], runtimeOverride?: string, ontologyContext?: OntologyPromptContext | null): { systemPrompt: string; userPrompt: string; }; } declare class IngestionService { private db; private prefix; private options; private entryRepo; private searchService; private jobManager; private embeddingService; private ontologyService?; private promptService; constructor(db: SQLiteAdapter, prefix: string, options: WikiOptions, entryRepo: EntryRepository, searchService: SearchService, jobManager: JobManager, embeddingService: EmbeddingService, promptService?: PromptService, ontologyService?: OntologyService | undefined); ingestDocument(entityId: string, params: { sourceRef: string; sourceHash: string; documentChunk: string; maxChunkLength?: number; chunkOverlap?: number; chunkConcurrency?: number; promptOverride?: string; }): Promise<{ truncated: boolean; chunks: number; }>; } declare class TaskRepository extends BaseRepository { private outbox; constructor(db: SQLiteAdapter, prefix: string, outbox: OutboxRepository); /** * Fetch a single task by ID. Returns null if not found or soft-deleted. */ findById(id: string): Promise; /** * Fetch all pending/in_progress tasks for the given entity IDs. * Returns empty array when entityIds is empty. */ findAllPending(entityIds: string[], limit?: number): Promise; findExistingMetadataByIds(ids: readonly string[], tx?: SQLiteAdapter): Promise>; /** * Upsert a WikiTask within the provided transaction. * Uses ON CONFLICT(id) DO UPDATE (not INSERT OR REPLACE). * Stages an outbox entry in the same transaction. * `tx` is REQUIRED. */ upsert(task: WikiTask, tx: SQLiteAdapter, updatedAt?: number): Promise; upsertForImport(task: WikiTask, tx: SQLiteAdapter, updatedAt?: number): Promise; /** * Soft-delete a task by ID. Sets deleted_at and updated_at. * Stages a DELETE outbox entry in the same transaction. * `tx` is REQUIRED. */ softDelete(id: string, entityId: string, tx: SQLiteAdapter): Promise; /** * Fetch all non-deleted tasks for an entity, ordered by priority DESC, created_at ASC. * Used by _getFullBundle(). */ findAllByEntityId(entityId: string, tx?: SQLiteAdapter): Promise; /** * Bulk delete pruned tasks (already soft-deleted) by cutoff date. * Used by runPrune(). Returns number of deleted rows. */ bulkDeletePruned(entityId: string, cutoff: number, tx: SQLiteAdapter): Promise; /** * Soft-delete a task by ID within a transaction. * Stages a DELETE outbox entry in the same transaction. * `tx` is REQUIRED. */ softDeleteById(id: string, entityId: string, tx: SQLiteAdapter): Promise<{ changes: number; }>; /** * Bulk soft-delete all tasks for an entity. * Stages DELETE outbox entries for each row in the same transaction. * `tx` is REQUIRED. */ bulkSoftDeleteByEntityId(entityId: string, tx: SQLiteAdapter): Promise; } declare class EventRepository extends BaseRepository { /** * Insert a new event row. * Pass `tx` to participate in a caller-owned transaction; omit to run against the default db. */ add(event: WikiEvent, tx?: SQLiteAdapter): Promise; addIgnoreDuplicate(event: WikiEvent, tx?: SQLiteAdapter): Promise; /** * Return the most recent events for an entity, newest first. * Defaults to a limit of 50. */ getRecent(entityId: string, limit?: number): Promise; /** * Return the most recent events for the given entity IDs, newest first. * Defaults to a limit of 50. */ getRecentForEntities(entityIds: string[], limit?: number): Promise; /** * Delete events for an entity that were created at or before the given cutoff timestamp. * Returns the number of deleted rows. */ prune(entityId: string, cutoff: number): Promise<{ changes: number; }>; /** * Return the total number of events stored for an entity. * `tx` is optional — pass an active transaction handle for atomic reads. */ count(entityId: string, tx?: SQLiteAdapter): Promise; /** * Return all events for an entity in chronological (ASC) order. * When limit is provided, fetches newest-first then reverses to preserve chronological order. */ getByEntityId(entityId: string, limit?: number): Promise; } declare const ONTOLOGY_BACKFILL_BATCH_SIZE = 25; declare const ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS = 40000; declare const ONTOLOGY_BACKFILL_RECHECK_MS: number; declare class MaintenanceService { private db; private prefix; private options; private entryRepo; private taskRepo; private eventRepo; private metadataRepo; private searchService; private jobManager; private embeddingService; private ontologyService?; private promptService; constructor(db: SQLiteAdapter, prefix: string, options: WikiOptions, entryRepo: EntryRepository, taskRepo: TaskRepository, eventRepo: EventRepository, metadataRepo: MetadataRepository, searchService: SearchService, jobManager: JobManager, embeddingService: EmbeddingService, promptService?: PromptService, ontologyService?: OntologyService | undefined); runPrune(entityId: string, options?: { retainSoftDeletedFor?: number | null; retainEventsFor?: number | null; vacuum?: boolean; }): Promise<{ entries: number; tasks: number; events: number; }>; runLibrarian(entityId: string, options?: { promptOverride?: string; }): Promise; runHeal(entityId: string, options?: { promptOverride?: string; }): Promise; runOntologyBackfill(entityId: string, options?: { promptOverride?: string; batchSize?: number; }): Promise; runReembed(entityId?: string, opts?: { force?: boolean; skipExisting?: boolean; }): Promise<{ embedded: number; skipped: number; failed: number; }>; forget(entityId: string, params: { entryId?: string; taskId?: string; sourceRef?: string; sourceHash?: string; clearAll?: boolean; }): Promise<{ deleted: { entries: number; tasks: number; }; }>; /** Core librarian pass (locks handled by {@link runLibrarian}). Package-internal orchestration hook. */ doRunLibrarian(entityId: string, promptOverride?: string): Promise; /** Core heal pass (locks handled by {@link runHeal}). Package-internal orchestration hook. */ doRunHeal(entityId: string, promptOverride?: string): Promise; /** Core ontology backfill pass (locks handled by {@link runOntologyBackfill}). Package-internal orchestration hook. */ doRunOntologyBackfill(entityId: string, options?: { promptOverride?: string; batchSize?: number; }): Promise; private _validatePruneDuration; private _sanitizeRankerError; } declare class ImportExportService { private db; private entryRepo; private taskRepo; private eventRepo; private edgeRepo; private metadataRepo; private searchService; private jobManager; private embeddingService; constructor(db: SQLiteAdapter, entryRepo: EntryRepository, taskRepo: TaskRepository, eventRepo: EventRepository, edgeRepo: EdgeRepository, metadataRepo: MetadataRepository, searchService: SearchService, jobManager: JobManager, embeddingService: EmbeddingService); exportDump(entityIds?: string[]): Promise; importDump(dump: MemoryDump, opts?: { merge?: boolean; }): Promise; getFullBundle(entityId: string, opts?: { maxEvents?: number; includeBlobs?: boolean; }): Promise; /** Single-entity import transaction + post-processing; package-internal hook for tests. */ doImportEntity(entityId: string, bundle: MemoryBundle, merge: boolean): Promise; private _warnCrossEntityCollision; private _normalizeImportedSourceType; assertNoLegacySourceTypes(): Promise; } declare class RetrievalService { private options; private entryRepo; private taskRepo; private eventRepo; private metadataRepo; private searchService; constructor(options: WikiOptions, entryRepo: EntryRepository, taskRepo: TaskRepository, eventRepo: EventRepository, metadataRepo: MetadataRepository, searchService: SearchService); read(entityId: string | string[], query: string, options?: ReadOptions): Promise; /** * Returns entity IDs that will participate in scored retrieval. * Excludes zero-weight entities unless includeZeroWeightEntities is true. */ private _filterScoredEntities; /** * Stable tie-break sort: score desc → access_count desc → updated_at desc → id asc. */ private _tieBreakSort; /** * Comparator for score + deterministic tie-break fields. * Negative return means "a ranks ahead of b" for descending score order. */ private _compareScoredRows; /** * Hydrate full facts by ID. Pass scopedEntityIds to restrict to requested namespaces in SQL * (defense-in-depth against a rogue VectorRanker returning cross-entity IDs). */ private _hydrateFactsByIds; private _sanitizeRankerError; /** * Delegate semantic ranking to the injected VectorRanker. * Caller should pass an oversampledLimit to preserve recall after re-ranking. * Returns scored results ready for hybrid blending and tie-break sorting. */ private _rankWithVectorRanker; } declare class WriteService { private db; private options; private entryRepo; private eventRepo; private metadataRepo; private jobManager; private maintenanceService; constructor(db: SQLiteAdapter, options: WikiOptions, entryRepo: EntryRepository, eventRepo: EventRepository, metadataRepo: MetadataRepository, jobManager: JobManager, maintenanceService: MaintenanceService); write(entityId: string, event: Omit): Promise; private runLibrarianThenMaybeHeal; } /** * Pure orchestrator — no SQL. Merges WikiConfig defaults with per-call options, * delegates the recursive walk to EdgeRepository, then hydrates node IDs into facts. */ declare class GraphTraversalService { private edgeRepo; private entryRepo; private config; constructor(edgeRepo: EdgeRepository, entryRepo: EntryRepository, config: WikiConfig); traverseGraph(entityId: string, options: GraphTraversalOptions): Promise; } /** Typed escape hatch for tests — not part of the supported consumer API. */ interface WikiMemoryTestAccess { embeddingService: EmbeddingService; importExportService: ImportExportService; ingestionService: IngestionService; maintenanceService: MaintenanceService; retrievalService: RetrievalService; searchService: SearchService; writeService: WriteService; promptService: PromptService; graphTraversalService: GraphTraversalService; entryRepo: EntryRepository; metadataRepo: MetadataRepository; jobManager: JobManager; } declare class WikiMemory { #private; private db; private prefix; private options; private entryRepo; private outboxRepo; private taskRepo; private eventRepo; private edgeRepo; private metadataRepo; private embeddingService; private searchService; private jobManager; private ingestionService; private maintenanceService; private importExportService; private retrievalService; private writeService; private promptService; private ontologyService; private graphTraversalService; constructor(db: SQLiteAdapter, options: WikiOptions); /** * Explicit escape hatch for test suites: typed access to composed services for mocks/spies. * If `NODE_ENV` is not `"test"`, emits a single `console.warn` per instance (skipped when `process` is undefined). */ get __testAccess(): WikiMemoryTestAccess; setup(): Promise; hasChanged(entityId: string, sourceRef: string, sourceHash: string): Promise; runPrune(entityId: string, options?: { retainSoftDeletedFor?: number | null; retainEventsFor?: number | null; vacuum?: boolean; }): Promise<{ entries: number; tasks: number; events: number; }>; read(entityId: string | string[], query: string, options?: ReadOptions): Promise; traverseGraph(entityId: string, options: GraphTraversalOptions): Promise; getMemoryBundle(entityId: string): Promise; write(entityId: string, event: Omit): Promise; /** * @param options.promptOverride - Applies only to this manual call. Does NOT affect * WriteService-triggered auto-runs. For persistent prompt customization across auto-runs, * set `options.config.prompts.librarianSystemPrompt` at WikiMemory construction time. */ runLibrarian(entityId: string, options?: { promptOverride?: string; }): Promise; /** * @param options.promptOverride - Applies only to this manual call. Does NOT affect * WriteService-triggered auto-runs. For persistent prompt customization across auto-runs, * set `options.config.prompts.healSystemPrompt` at WikiMemory construction time. */ runHeal(entityId: string, options?: { promptOverride?: string; }): Promise; /** * Types already-persisted untyped facts (okf_type IS NULL) in place via one * librarian-style LLM call. Strictly additive: never creates, deletes, or * rewrites facts; never overwrites an existing okf_type. Free when there is * nothing to do (ontology off, or zero eligible untyped facts). * * Hosts own the trigger cadence (e.g. after each sync); loop `while * result.remaining > 0` for convergence. Throws WikiBusyError when another * backfill (or conflicting maintenance op) is running for the entity. * * @param options.promptOverride - Applies only to this call. For persistent * customization set `options.config.prompts.ontologyBackfillSystemPrompt`. * @param options.batchSize - Facts per run (default 25) for providers with * tighter context limits. */ runOntologyBackfill(entityId: string, options?: { promptOverride?: string; batchSize?: number; }): Promise; runReembed(entityId?: string, opts?: { force?: boolean; skipExisting?: boolean; }): Promise<{ embedded: number; skipped: number; failed: number; }>; getEntityStatus(entityId: string): EntityStatus; subscribeEntityStatus(entityId: string, callback: (status: EntityStatus) => void): () => void; clearVectorCache(): void; exportDump(entityIds?: string[]): Promise; /** Entity summary prose persisted from an OKF profile ≥ 1 import; null when none stored. */ getEntitySummary(entityId: string): Promise; importDump(dump: MemoryDump, opts?: { merge?: boolean; }): Promise; forget(entityId: string, params: { entryId?: string; taskId?: string; sourceRef?: string; sourceHash?: string; clearAll?: boolean; }): Promise<{ deleted: { entries: number; tasks: number; }; }>; /** * @param params.promptOverride - Overrides the system prompt for this ingest call only. * For persistent customization, set `options.config.prompts.ingestSystemPrompt` at * WikiMemory construction time. */ ingestDocument(entityId: string, params: { sourceRef: string; sourceHash: string; documentChunk: string; maxChunkLength?: number; chunkOverlap?: number; chunkConcurrency?: number; promptOverride?: string; }): Promise<{ truncated: boolean; chunks: number; }>; /** * Returns up to `limit` unprocessed outbox events, oldest first. * Works regardless of enableOutbox value — allows draining after disabling. */ getUnprocessedOutboxEvents(limit?: number): Promise; /** * Deletes the given event IDs from the outbox table. * Call after successfully committing events to the external system. */ markOutboxEventsProcessed(eventIds: string[]): Promise; /** * Returns the effective ontology mode and manifest for an entity. * Resolution order: persisted DB row → `WikiConfig.ontology.seedManifests[entityId]` → `null`. */ getOntologyManifest(entityId: string): Promise<{ mode: OntologyMode; manifest: OntologyManifest; } | null>; /** * Seeds or replaces an entity's ontology manifest and optional mode override. * Validates manifest invariants (unique type slugs, edge endpoints reference node types). * Invalidates the in-memory ontology cache for this entity. */ setOntologyManifest(entityId: string, manifest: OntologyManifest, options?: { mode?: OntologyMode; }): Promise; } export { WriteService as $, type WikiConfig as A, type WikiEdge as B, type WikiEvent as C, type WikiFact as D, type EntityStatus as E, type FormatContextOptions as F, type GraphNeighborhood as G, HOOK_TIMEOUT_MARKER as H, type WikiMemoryTestAccess as I, type WikiOutboxEvent as J, type WikiTask as K, type LLMProvider as L, type MemoryBundle as M, WikiTransactionError as N, type OntologyManifest as O, type PromptOverrides as P, EmbeddingService as Q, type ReadOptions as R, type SQLiteAdapter as S, ImportExportService as T, IngestionService as U, type VectorRanker as V, type WikiOptions as W, JobManager as X, MaintenanceService as Y, RetrievalService as Z, SearchService as _, type MemoryDump as a, type FormattedMemoryDump as b, WikiMemory as c, type ExtractedFact as d, type ExtractedFactEdge as e, type ExtractedFactWithOntology as f, type ExtractedTask as g, type GraphTraversalOptions as h, ONTOLOGY_BACKFILL_BATCH_SIZE as i, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS as j, ONTOLOGY_BACKFILL_RECHECK_MS as k, type OntologyBackfillResult as l, type OntologyConfig as m, type OntologyEdgeType as n, type OntologyMode as o, type OntologyNodeType as p, type OntologyPromptContext as q, type OntologyUpdates as r, PromptService as s, PrunePartialFailureError as t, type VectorRankerFallback as u, type VectorRankerRankArgs as v, type VectorRankerSemanticResult as w, WikiBusyError as x, type WikiBusyOperation as y, type WikiCheckpoint as z };