@equationalapplications/core-llm-wiki 4.4.0 → 4.5.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 CHANGED
@@ -398,6 +398,71 @@ await wikiMemory.write('user-123', {
398
398
  const memory = await wikiMemory.read('user-123', 'coding style preferences');
399
399
  ```
400
400
 
401
+ ### Multi-entity weighted reads
402
+
403
+ `read()` accepts either one entity id or an array of entity ids. Facts are always merged globally before `maxResults` is applied. For single-entity reads, tasks are uncapped and events are capped at 10. For multi-entity reads, tasks are capped at `min(20 × entity count, 200)` and events at `min(10 × entity count, 100)` — per-entity representation in the returned bundle is not guaranteed.
404
+
405
+ ```ts
406
+ const memory = await wikiMemory.read(['tier_wisdom', 'tier_fact', 'tier_working'], 'Which source should I trust?', {
407
+ maxResults: 8,
408
+ tierWeights: {
409
+ tier_wisdom: 2,
410
+ tier_fact: 1,
411
+ tier_working: 0.25,
412
+ },
413
+ });
414
+
415
+ console.log(memory.metadata);
416
+ console.log(memory.factScores);
417
+ ```
418
+
419
+ ### Librarian prompt override contract
420
+
421
+ Core does not own a provider-specific synthesis API, but it exports prompt utilities for applications that synthesize answers from weighted retrieval results.
422
+
423
+ ```ts
424
+ import {
425
+ DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT,
426
+ formatContext,
427
+ hydrateLibrarianPrompt,
428
+ mapLibrarianOptionsToReadOptions,
429
+ validateLibrarianPromptTemplate,
430
+ } from '@equationalapplications/core-llm-wiki';
431
+
432
+ const options = {
433
+ entityWeights: { tier_wisdom: 2, tier_fact: 1, tier_working: 0.25 },
434
+ systemPrompt: `You are a strict fact checker.
435
+ Question:
436
+ {{query}}
437
+
438
+ Retrieved context:
439
+ {{context}}
440
+
441
+ {{tasks}}`,
442
+ };
443
+
444
+ const query = 'Which source should I trust for recent project decisions?';
445
+
446
+ const memory = await wikiMemory.read(['tier_wisdom', 'tier_fact', 'tier_working'], query, {
447
+ ...mapLibrarianOptionsToReadOptions(options),
448
+ maxResults: 8,
449
+ });
450
+
451
+ const template = options.systemPrompt ?? DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT;
452
+ const warnings = validateLibrarianPromptTemplate(template, {
453
+ custom: options.systemPrompt != null,
454
+ taskCount: memory.tasks.length,
455
+ });
456
+
457
+ for (const warning of warnings) console.warn(warning);
458
+
459
+ const finalPrompt = hydrateLibrarianPrompt(template, {
460
+ query,
461
+ context: formatContext(memory, { includeEntityIds: true, includeFactScores: true }),
462
+ tasks: formatContext({ facts: [], tasks: memory.tasks, events: [] }, { format: 'plain' }),
463
+ });
464
+ ```
465
+
401
466
  ## Adapter Interface
402
467
 
403
468
  Implement `SQLiteAdapter` to use your platform's SQLite driver:
package/dist/index.d.mts CHANGED
@@ -313,6 +313,8 @@ interface FormatContextOptions {
313
313
  maxEvents?: number;
314
314
  includeConfidence?: boolean;
315
315
  includeTags?: boolean;
316
+ includeEntityIds?: boolean;
317
+ includeFactScores?: boolean;
316
318
  factWeights?: {
317
319
  confidence?: number;
318
320
  accessCount?: number;
@@ -531,6 +533,28 @@ declare function formatMemoryDump(dump: MemoryDump): FormattedMemoryDump;
531
533
 
532
534
  declare function parseEmbedding(blob: Uint8Array | null | undefined, text: string | null | undefined): Float32Array | null;
533
535
 
536
+ interface LibrarianOptions {
537
+ /** If provided, replaces the default Librarian system instructions. */
538
+ systemPrompt?: string;
539
+ /** entity_id -> score multiplier, forwarded to WikiMemory.read() as tierWeights. */
540
+ entityWeights?: Record<string, number>;
541
+ /** Forwarded to WikiMemory.read() for zero-weight filler context. */
542
+ includeZeroWeightEntities?: boolean;
543
+ temperature?: number;
544
+ }
545
+ interface LibrarianPromptVariables {
546
+ context: string;
547
+ tasks: string;
548
+ query: string;
549
+ }
550
+ declare const DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT = "You are a careful memory synthesis assistant.\nUse only the retrieved context when answering the request.\nPreserve source provenance when facts come from different entity namespaces.\n\nRequest:\n{{query}}\n\nRetrieved context:\n{{context}}\n\nOpen tasks:\n{{tasks}}";
551
+ declare function hydrateLibrarianPrompt(template: string, variables: LibrarianPromptVariables): string;
552
+ declare function validateLibrarianPromptTemplate(template: string, options: {
553
+ custom: boolean;
554
+ taskCount: number;
555
+ }): string[];
556
+ declare function mapLibrarianOptionsToReadOptions(options: LibrarianOptions): Pick<ReadOptions, 'tierWeights' | 'includeZeroWeightEntities'>;
557
+
534
558
  declare function createWiki(db: SQLiteAdapter, options: WikiOptions): WikiMemory;
535
559
 
536
- export { type EntityStatus, type ExtractedFact, type ExtractedTask, type FormatContextOptions, type FormattedMemoryDump, type LLMProvider, type MemoryBundle, type MemoryDump, PrunePartialFailureError, type ReadOptions, type SQLiteAdapter, type VectorRanker, type VectorRankerFallback, type VectorRankerRankArgs, type VectorRankerSemanticResult, WikiBusyError, type WikiBusyOperation, type WikiCheckpoint, type WikiConfig, type WikiEvent, type WikiFact, WikiMemory, type WikiOptions, type WikiTask, createWiki, formatContext, formatMemoryDump, parseEmbedding };
560
+ export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, type EntityStatus, type ExtractedFact, type ExtractedTask, type FormatContextOptions, type FormattedMemoryDump, type LLMProvider, type LibrarianOptions, type LibrarianPromptVariables, type MemoryBundle, type MemoryDump, PrunePartialFailureError, type ReadOptions, type SQLiteAdapter, type VectorRanker, type VectorRankerFallback, type VectorRankerRankArgs, type VectorRankerSemanticResult, WikiBusyError, type WikiBusyOperation, type WikiCheckpoint, type WikiConfig, type WikiEvent, type WikiFact, WikiMemory, type WikiOptions, type WikiTask, createWiki, formatContext, formatMemoryDump, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, validateLibrarianPromptTemplate };
package/dist/index.d.ts CHANGED
@@ -313,6 +313,8 @@ interface FormatContextOptions {
313
313
  maxEvents?: number;
314
314
  includeConfidence?: boolean;
315
315
  includeTags?: boolean;
316
+ includeEntityIds?: boolean;
317
+ includeFactScores?: boolean;
316
318
  factWeights?: {
317
319
  confidence?: number;
318
320
  accessCount?: number;
@@ -531,6 +533,28 @@ declare function formatMemoryDump(dump: MemoryDump): FormattedMemoryDump;
531
533
 
532
534
  declare function parseEmbedding(blob: Uint8Array | null | undefined, text: string | null | undefined): Float32Array | null;
533
535
 
536
+ interface LibrarianOptions {
537
+ /** If provided, replaces the default Librarian system instructions. */
538
+ systemPrompt?: string;
539
+ /** entity_id -> score multiplier, forwarded to WikiMemory.read() as tierWeights. */
540
+ entityWeights?: Record<string, number>;
541
+ /** Forwarded to WikiMemory.read() for zero-weight filler context. */
542
+ includeZeroWeightEntities?: boolean;
543
+ temperature?: number;
544
+ }
545
+ interface LibrarianPromptVariables {
546
+ context: string;
547
+ tasks: string;
548
+ query: string;
549
+ }
550
+ declare const DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT = "You are a careful memory synthesis assistant.\nUse only the retrieved context when answering the request.\nPreserve source provenance when facts come from different entity namespaces.\n\nRequest:\n{{query}}\n\nRetrieved context:\n{{context}}\n\nOpen tasks:\n{{tasks}}";
551
+ declare function hydrateLibrarianPrompt(template: string, variables: LibrarianPromptVariables): string;
552
+ declare function validateLibrarianPromptTemplate(template: string, options: {
553
+ custom: boolean;
554
+ taskCount: number;
555
+ }): string[];
556
+ declare function mapLibrarianOptionsToReadOptions(options: LibrarianOptions): Pick<ReadOptions, 'tierWeights' | 'includeZeroWeightEntities'>;
557
+
534
558
  declare function createWiki(db: SQLiteAdapter, options: WikiOptions): WikiMemory;
535
559
 
536
- export { type EntityStatus, type ExtractedFact, type ExtractedTask, type FormatContextOptions, type FormattedMemoryDump, type LLMProvider, type MemoryBundle, type MemoryDump, PrunePartialFailureError, type ReadOptions, type SQLiteAdapter, type VectorRanker, type VectorRankerFallback, type VectorRankerRankArgs, type VectorRankerSemanticResult, WikiBusyError, type WikiBusyOperation, type WikiCheckpoint, type WikiConfig, type WikiEvent, type WikiFact, WikiMemory, type WikiOptions, type WikiTask, createWiki, formatContext, formatMemoryDump, parseEmbedding };
560
+ export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, type EntityStatus, type ExtractedFact, type ExtractedTask, type FormatContextOptions, type FormattedMemoryDump, type LLMProvider, type LibrarianOptions, type LibrarianPromptVariables, type MemoryBundle, type MemoryDump, PrunePartialFailureError, type ReadOptions, type SQLiteAdapter, type VectorRanker, type VectorRankerFallback, type VectorRankerRankArgs, type VectorRankerSemanticResult, WikiBusyError, type WikiBusyOperation, type WikiCheckpoint, type WikiConfig, type WikiEvent, type WikiFact, WikiMemory, type WikiOptions, type WikiTask, createWiki, formatContext, formatMemoryDump, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseEmbedding, validateLibrarianPromptTemplate };
package/dist/index.js CHANGED
@@ -2793,16 +2793,20 @@ function scoreFactFor(fact, weights, now) {
2793
2793
  const recencyDecay = Math.exp(-ageDays / 30);
2794
2794
  return confW * weights.confidence + Math.log(1 + fact.access_count) * weights.accessCount + recencyDecay * weights.recency;
2795
2795
  }
2796
- function renderFactMarkdown(fact, includeConfidence, includeTags) {
2796
+ function renderFactMarkdown(fact, includeConfidence, includeTags, includeEntityIds, score) {
2797
2797
  const confPart = includeConfidence ? ` (${fact.confidence})` : "";
2798
2798
  const tagPart = includeTags && fact.tags.length > 0 ? ` [${fact.tags.join(", ")}]` : "";
2799
- return `- **${fact.title}**${confPart}${tagPart}
2799
+ const sourcePart = includeEntityIds ? ` {entity_id=${fact.entity_id}}` : "";
2800
+ const scorePart = score !== void 0 ? ` {score=${score.toFixed(4)}}` : "";
2801
+ return `- **${fact.title}**${confPart}${tagPart}${sourcePart}${scorePart}
2800
2802
  ${fact.body.replace(/\n/g, "\n ")}`;
2801
2803
  }
2802
- function renderFactPlain(fact, includeConfidence, includeTags) {
2804
+ function renderFactPlain(fact, includeConfidence, includeTags, includeEntityIds, score) {
2803
2805
  const confPart = includeConfidence ? ` (${fact.confidence})` : "";
2804
2806
  const tagPart = includeTags && fact.tags.length > 0 ? ` [${fact.tags.join(", ")}]` : "";
2805
- return `${fact.title}${confPart}${tagPart}: ${fact.body}`;
2807
+ const sourcePart = includeEntityIds ? ` {entity_id=${fact.entity_id}}` : "";
2808
+ const scorePart = score !== void 0 ? ` {score=${score.toFixed(4)}}` : "";
2809
+ return `${fact.title}${confPart}${tagPart}${sourcePart}${scorePart}: ${fact.body}`;
2806
2810
  }
2807
2811
  function renderTaskMarkdown(task) {
2808
2812
  return `- [P${task.priority}] ${task.description.replace(/\n/g, "\n ")} (${task.status})`;
@@ -2826,6 +2830,8 @@ function formatContext(bundle, options) {
2826
2830
  maxEvents: options?.maxEvents ?? 10,
2827
2831
  includeConfidence: options?.includeConfidence ?? true,
2828
2832
  includeTags: options?.includeTags ?? true,
2833
+ includeEntityIds: options?.includeEntityIds ?? false,
2834
+ includeFactScores: options?.includeFactScores ?? false,
2829
2835
  factWeights: {
2830
2836
  confidence: options?.factWeights?.confidence ?? 1,
2831
2837
  accessCount: options?.factWeights?.accessCount ?? 0.3,
@@ -2837,7 +2843,7 @@ function formatContext(bundle, options) {
2837
2843
  validateMaxOption(opts.maxEvents, "maxEvents");
2838
2844
  const weights = opts.factWeights;
2839
2845
  const now = Date.now();
2840
- const sortedFacts = [...bundle.facts].sort((a, b) => scoreFactFor(b, weights, now) - scoreFactFor(a, weights, now)).slice(0, opts.maxFacts);
2846
+ const sortedFacts = bundle.factScores ? [...bundle.facts].slice(0, opts.maxFacts) : [...bundle.facts].sort((a, b) => scoreFactFor(b, weights, now) - scoreFactFor(a, weights, now)).slice(0, opts.maxFacts);
2841
2847
  const sortedTasks = [...bundle.tasks].sort((a, b) => b.priority - a.priority || a.created_at - b.created_at).slice(0, opts.maxTasks);
2842
2848
  const sortedEvents = [...bundle.events].sort((a, b) => b.created_at - a.created_at).slice(0, opts.maxEvents);
2843
2849
  if (sortedFacts.length === 0 && sortedTasks.length === 0 && sortedEvents.length === 0) {
@@ -2851,7 +2857,7 @@ function formatContext(bundle, options) {
2851
2857
  lines.push("");
2852
2858
  lines.push("### Known Facts");
2853
2859
  for (const fact of sortedFacts) {
2854
- lines.push(renderFactMarkdown(fact, opts.includeConfidence, opts.includeTags));
2860
+ lines.push(renderFactMarkdown(fact, opts.includeConfidence, opts.includeTags, opts.includeEntityIds, opts.includeFactScores ? bundle.factScores?.[fact.id] : void 0));
2855
2861
  }
2856
2862
  }
2857
2863
  if (sortedTasks.length > 0) {
@@ -2872,7 +2878,7 @@ function formatContext(bundle, options) {
2872
2878
  if (sortedFacts.length > 0) {
2873
2879
  lines.push("KNOWN FACTS:");
2874
2880
  for (const fact of sortedFacts) {
2875
- lines.push(renderFactPlain(fact, opts.includeConfidence, opts.includeTags));
2881
+ lines.push(renderFactPlain(fact, opts.includeConfidence, opts.includeTags, opts.includeEntityIds, opts.includeFactScores ? bundle.factScores?.[fact.id] : void 0));
2876
2882
  }
2877
2883
  }
2878
2884
  if (sortedTasks.length > 0) {
@@ -2991,17 +2997,60 @@ function formatMemoryDump(dump) {
2991
2997
  };
2992
2998
  }
2993
2999
 
3000
+ // src/librarianPrompt.ts
3001
+ var DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT = `You are a careful memory synthesis assistant.
3002
+ Use only the retrieved context when answering the request.
3003
+ Preserve source provenance when facts come from different entity namespaces.
3004
+
3005
+ Request:
3006
+ {{query}}
3007
+
3008
+ Retrieved context:
3009
+ {{context}}
3010
+
3011
+ Open tasks:
3012
+ {{tasks}}`;
3013
+ function hydrateLibrarianPrompt(template, variables) {
3014
+ return template.replace(/\{\{(context|tasks|query)\}\}/g, (_, key) => variables[key]);
3015
+ }
3016
+ function validateLibrarianPromptTemplate(template, options) {
3017
+ if (!options.custom) return [];
3018
+ const warnings = [];
3019
+ if (!template.includes("{{context}}")) {
3020
+ warnings.push("Custom Librarian systemPrompt omits {{context}}; retrieved memory will not be injected.");
3021
+ }
3022
+ if (!template.includes("{{query}}")) {
3023
+ warnings.push("Custom Librarian systemPrompt omits {{query}}; the original request will not be injected.");
3024
+ }
3025
+ if (options.taskCount > 0 && !template.includes("{{tasks}}")) {
3026
+ warnings.push("Custom Librarian systemPrompt omits {{tasks}} while retrieved tasks are available.");
3027
+ }
3028
+ return warnings;
3029
+ }
3030
+ function mapLibrarianOptionsToReadOptions(options) {
3031
+ const readOptions = {};
3032
+ if (options.entityWeights !== void 0) readOptions.tierWeights = options.entityWeights;
3033
+ if (options.includeZeroWeightEntities !== void 0) {
3034
+ readOptions.includeZeroWeightEntities = options.includeZeroWeightEntities;
3035
+ }
3036
+ return readOptions;
3037
+ }
3038
+
2994
3039
  // src/index.ts
2995
3040
  function createWiki(db, options) {
2996
3041
  return new WikiMemory(db, options);
2997
3042
  }
2998
3043
 
3044
+ exports.DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT = DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT;
2999
3045
  exports.PrunePartialFailureError = PrunePartialFailureError;
3000
3046
  exports.WikiBusyError = WikiBusyError;
3001
3047
  exports.WikiMemory = WikiMemory;
3002
3048
  exports.createWiki = createWiki;
3003
3049
  exports.formatContext = formatContext;
3004
3050
  exports.formatMemoryDump = formatMemoryDump;
3051
+ exports.hydrateLibrarianPrompt = hydrateLibrarianPrompt;
3052
+ exports.mapLibrarianOptionsToReadOptions = mapLibrarianOptionsToReadOptions;
3005
3053
  exports.parseEmbedding = parseEmbedding;
3054
+ exports.validateLibrarianPromptTemplate = validateLibrarianPromptTemplate;
3006
3055
  //# sourceMappingURL=index.js.map
3007
3056
  //# sourceMappingURL=index.js.map