@equationalapplications/core-llm-wiki 7.13.1 → 7.15.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/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { BaseRepository, WikiGraphNodeOwnershipConflict, parseJsonObject, parseJsonArray, liveAtSql, reanchorRebuildFingerprint, __privateAdd, MetadataRepository, EmbeddingService, SearchService, TemporalService, JobManager, PromptService, resolveGrounding, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, createLegacySourceTypeIndex, writeNormalizeStamp, CURRENT_SCHEMA_VERSION, detectSchemaVersion, MIGRATIONS, runSourceRefNormalize, normalizeSourceRef, normalizeSourceHash, entitySummaryMetaKey, WikiSourceRefHashCollision, DiagnosticBuffer, validateManifest, WikiDraftNotFound, generateId, emptyManifest, resolveNodeType, WikiStrictOntologyViolation, validateInlineEdges, resolveEdgeDefinitions, typeSatisfies, normalizeTitleKey, edgeTripleAllowed, MAX_EMBED_ATTEMPTS, UsageMeter, isWikiSearchUnavailableError, WikiBusyError, WikiInvalidReadOptions, isLiveAt, packFactsByBudget, factTokenCost, probePendingWork, WikiMigrationRequiredError, setupDatabase, UnavailableIndexStrategy, FTS5_STATE_KEY, fts5LedgerDropSql, fts5TablesDdl, fts5PendingIndexesDdl, fts5TriggersDdl, writeRebuildStart, FTS5_RETIRED_COUNTER_KEY, retiredTableName, FTS5_RETIRED_TABLES_KEY, isRetiredTableName, idReindexChunkSql, readRebuildProgress, FTS5_DRAIN_CHUNK, FTS5_RECLAIM_MERGE_PAGES, windowHiSql, windowChunkSql, FTS5_REBUILD_WM_KEY, sweepHiSql, sweepChunkSql, FTS5_SWEEP_CURSOR_KEY, drainHiSql, drainChunkSql, FTS5_REBUILD_SNAPSHOT_KEY, idDrainChunkSql, entityDrainHiSql, entityDrainChunkSql, fts5TriggerNames, extractSqliteCode, WikiTransactionError } from './chunk-PCRYIUV5.mjs';
2
- export { DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, DEFAULT_MAX_EMBED_CHARS, EMBED_CHARS_CEILING, HEAL_ANCHORS_PER_CANDIDATE, HEAL_BATCH_SIZE, HEAL_MAX_FACT_BODY_CHARS_L3, HEAL_MAX_TASKS, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, WikiBusyError, WikiDraftNotFound, WikiDuplicateHashError, WikiGraphNodeOwnershipConflict, WikiIngestEmptyError, WikiInvalidReadOptions, WikiMigrationRequiredError, WikiParseError, WikiSearchUnavailableError, WikiSourceRefHashCollision, WikiStrictOntologyViolation, WikiSupersedeError, WikiTransactionError, chunkText, configureRandomSource, isWikiSearchUnavailableError, parseEmbedding, safeSlice, validateManifest } from './chunk-PCRYIUV5.mjs';
1
+ import { BaseRepository, WikiGraphNodeOwnershipConflict, parseJsonObject, parseJsonArray, liveAtSql, reanchorRebuildFingerprint, __privateAdd, MetadataRepository, EmbeddingService, SearchService, TemporalService, JobManager, PromptService, resolveGrounding, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, createLegacySourceTypeIndex, writeNormalizeStamp, CURRENT_SCHEMA_VERSION, detectSchemaVersion, MIGRATIONS, runSourceRefNormalize, normalizeSourceRef, normalizeSourceHash, entitySummaryMetaKey, WikiSourceRefHashCollision, DiagnosticBuffer, validateManifest, WikiDraftNotFound, generateId, emptyManifest, resolveNodeType, WikiStrictOntologyViolation, validateInlineEdges, resolveEdgeDefinitions, typeSatisfies, normalizeTitleKey, edgeTripleAllowed, MAX_EMBED_ATTEMPTS, UsageMeter, isWikiSearchUnavailableError, WikiBusyError, WikiInvalidReadOptions, isLiveAt, packFactsByBudget, factTokenCost, probePendingWork, WikiMigrationRequiredError, setupDatabase, UnavailableIndexStrategy, assertEntityId, assertEpochMs, FTS5_STATE_KEY, fts5LedgerDropSql, fts5TablesDdl, fts5PendingIndexesDdl, fts5TriggersDdl, writeRebuildStart, FTS5_RETIRED_COUNTER_KEY, retiredTableName, FTS5_RETIRED_TABLES_KEY, isRetiredTableName, idReindexChunkSql, readRebuildProgress, FTS5_DRAIN_CHUNK, FTS5_RECLAIM_MERGE_PAGES, windowHiSql, windowChunkSql, FTS5_REBUILD_WM_KEY, sweepHiSql, sweepChunkSql, FTS5_SWEEP_CURSOR_KEY, drainHiSql, drainChunkSql, FTS5_REBUILD_SNAPSHOT_KEY, idDrainChunkSql, entityDrainHiSql, entityDrainChunkSql, fts5TriggerNames, extractSqliteCode, WikiTransactionError } from './chunk-BC3QHSF3.mjs';
2
+ export { DEFAULT_CHUNK_OVERLAP, DEFAULT_MAX_CHUNK_LENGTH, DEFAULT_MAX_EMBED_CHARS, EMBED_CHARS_CEILING, HEAL_ANCHORS_PER_CANDIDATE, HEAL_BATCH_SIZE, HEAL_MAX_FACT_BODY_CHARS_L3, HEAL_MAX_TASKS, HEAL_RECHECK_MS, HOOK_TIMEOUT_MARKER, ONTOLOGY_BACKFILL_BATCH_SIZE, ONTOLOGY_BACKFILL_MAX_PROMPT_CHARS, ONTOLOGY_BACKFILL_RECHECK_MS, ONTOLOGY_BACKFILL_SYSTEM_PROMPT, PromptService, PrunePartialFailureError, WikiBusyError, WikiDraftNotFound, WikiDuplicateHashError, WikiGraphNodeOwnershipConflict, WikiIngestEmptyError, WikiInvalidReadOptions, WikiMigrationRequiredError, WikiParseError, WikiSearchUnavailableError, WikiSourceRefHashCollision, WikiStrictOntologyViolation, WikiSupersedeError, WikiTransactionError, chunkText, configureRandomSource, isWikiSearchUnavailableError, parseEmbedding, safeSlice, validateManifest } from './chunk-BC3QHSF3.mjs';
3
3
  import { deriveTrustTier, isStaleAfter, appendRelatedSection, buildConceptDocument, buildLogMd, buildEntityIndexMd, buildRootIndexMd, isAllowedOkfPath, parseRootIndexMd, parseEntityIndexMd, parseConcept, splitRelatedSection, extractMarkdownLinks, parseLogMd, parseEventIdComment, latestVerified, formatSourcesJson, appendEventIdComment, parseVerifiedFlexible, parseCitationsList } from '@equationalapplications/core-okf';
4
4
  import MiniSearch from 'minisearch';
5
5
 
@@ -3787,6 +3787,110 @@ var OkfTrustWritesRepository = class {
3787
3787
  }
3788
3788
  };
3789
3789
 
3790
+ // src/utils/rememberInput.ts
3791
+ var CONFIDENCE_VALUES = /* @__PURE__ */ new Set(["certain", "inferred", "tentative"]);
3792
+ var SOURCE_TYPE_VALUES = /* @__PURE__ */ new Set(["user_stated", "user_confirmed"]);
3793
+ function normalizeRememberInput(entityId, input, now) {
3794
+ assertEntityId(entityId);
3795
+ if (input === null || typeof input !== "object" || Array.isArray(input)) {
3796
+ throw new TypeError("remember(): input must be a non-null object.");
3797
+ }
3798
+ if (typeof input.title !== "string" || input.title.trim() === "") {
3799
+ throw new TypeError("remember(): input.title must be a non-empty string.");
3800
+ }
3801
+ if (typeof input.body !== "string") {
3802
+ throw new TypeError("remember(): input.body must be a string.");
3803
+ }
3804
+ let tags = [];
3805
+ if (input.tags !== void 0) {
3806
+ if (!Array.isArray(input.tags)) {
3807
+ throw new TypeError("remember(): input.tags must be an array of strings.");
3808
+ }
3809
+ for (let i = 0; i < input.tags.length; i++) {
3810
+ if (typeof input.tags[i] !== "string") {
3811
+ throw new TypeError("remember(): input.tags must be an array of strings.");
3812
+ }
3813
+ }
3814
+ tags = [...input.tags];
3815
+ }
3816
+ const confidence = input.confidence === void 0 ? "certain" : input.confidence;
3817
+ if (!CONFIDENCE_VALUES.has(confidence)) {
3818
+ throw new TypeError(`remember(): input.confidence must be certain | inferred | tentative; got ${JSON.stringify(input.confidence)}.`);
3819
+ }
3820
+ const sourceType = input.source_type === void 0 ? "user_stated" : input.source_type;
3821
+ if (!SOURCE_TYPE_VALUES.has(sourceType)) {
3822
+ throw new TypeError(`remember(): input.source_type must be user_stated | user_confirmed; got ${JSON.stringify(input.source_type)}.`);
3823
+ }
3824
+ let okfType = null;
3825
+ if (input.okf_type !== void 0 && input.okf_type !== null) {
3826
+ if (typeof input.okf_type !== "string" || input.okf_type.trim() === "") {
3827
+ throw new TypeError("remember(): input.okf_type must be a non-empty string or null.");
3828
+ }
3829
+ okfType = input.okf_type;
3830
+ }
3831
+ const validFrom = input.valid_from === void 0 ? void 0 : assertEpochMs("input.valid_from", input.valid_from);
3832
+ const fact = {
3833
+ id: generateId("fact_"),
3834
+ entity_id: entityId,
3835
+ title: input.title,
3836
+ body: input.body,
3837
+ tags,
3838
+ confidence,
3839
+ source_type: sourceType,
3840
+ source_hash: null,
3841
+ source_ref: null,
3842
+ created_at: now,
3843
+ updated_at: now,
3844
+ last_accessed_at: null,
3845
+ access_count: 0,
3846
+ deleted_at: null,
3847
+ okf_type: null
3848
+ };
3849
+ return { fact, validFrom, okfType };
3850
+ }
3851
+
3852
+ // src/services/RememberService.ts
3853
+ var RememberService = class {
3854
+ constructor(db, entryRepo, ontologyService, searchService, embeddingService) {
3855
+ this.db = db;
3856
+ this.entryRepo = entryRepo;
3857
+ this.ontologyService = ontologyService;
3858
+ this.searchService = searchService;
3859
+ this.embeddingService = embeddingService;
3860
+ }
3861
+ async remember(entityId, input) {
3862
+ const now = Date.now();
3863
+ const { fact, validFrom, okfType } = normalizeRememberInput(entityId, input, now);
3864
+ let stored;
3865
+ await this.db.withTransactionAsync(async (tx) => {
3866
+ if (okfType !== null) {
3867
+ const { mode, manifest } = await this.ontologyService.getEffectiveState(entityId, tx);
3868
+ const factLike = { okf_type: okfType, edges: [] };
3869
+ fact.okf_type = this.ontologyService.validateAndNormalizeFact(factLike, manifest, {
3870
+ strict: mode === "strict",
3871
+ entityId
3872
+ }).okf_type;
3873
+ }
3874
+ await this.entryRepo.upsert(fact, tx);
3875
+ if (validFrom !== void 0) {
3876
+ await this.entryRepo.setTemporal(fact.id, entityId, { valid_from: validFrom }, tx);
3877
+ }
3878
+ const [readBack] = await this.entryRepo.findByIds([fact.id], [entityId], tx);
3879
+ if (!readBack) {
3880
+ throw new Error("remember(): the stored fact could not be read back; the SQLiteAdapter did not perform the write");
3881
+ }
3882
+ stored = readBack;
3883
+ });
3884
+ await this.searchService.syncEntries(entityId, [fact.id]);
3885
+ await this.embeddingService.embedFact(
3886
+ { id: fact.id, entity_id: entityId, title: fact.title, body: fact.body, tags: fact.tags },
3887
+ { operation: "remember", trigger: "call" }
3888
+ );
3889
+ this.searchService.evictCache(entityId);
3890
+ return stored;
3891
+ }
3892
+ };
3893
+
3790
3894
  // src/WikiMemory.ts
3791
3895
  var TABLE_PREFIX_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,30}_$/;
3792
3896
  var SEARCH_REINIT_COOLDOWN_MS = 5e3;
@@ -3849,6 +3953,7 @@ var WikiMemory = class {
3849
3953
  new MiniSearchIndexStrategy()
3850
3954
  );
3851
3955
  this.temporalService = new TemporalService(this.db, this.options, this.entryRepo, this.searchService, this.embeddingService);
3956
+ this.rememberService = new RememberService(this.db, this.entryRepo, this.ontologyService, this.searchService, this.embeddingService);
3852
3957
  this.jobManager = new JobManager(this.prefix);
3853
3958
  this.promptService = new PromptService(options.config?.prompts, resolveGrounding(options.config?.grounding));
3854
3959
  this.ingestionService = new IngestionService(
@@ -3946,6 +4051,7 @@ var WikiMemory = class {
3946
4051
  promptService: this.promptService,
3947
4052
  graphTraversalService: this.graphTraversalService,
3948
4053
  temporalService: this.temporalService,
4054
+ rememberService: this.rememberService,
3949
4055
  entryRepo: this.entryRepo,
3950
4056
  sourceRefIndexRepo: this.sourceRefIndexRepo,
3951
4057
  metadataRepo: this.metadataRepo,
@@ -4107,7 +4213,7 @@ var WikiMemory = class {
4107
4213
  * in a sparse array), throws a `TypeError` before any SQL runs.
4108
4214
  */
4109
4215
  async pendingSources(entityId, sources) {
4110
- assertEntityId(entityId);
4216
+ assertEntityId2(entityId);
4111
4217
  if (!Array.isArray(sources)) {
4112
4218
  throw new TypeError("Invalid sources: must be an array of { sourceRef, sourceHash } objects.");
4113
4219
  }
@@ -4139,7 +4245,7 @@ var WikiMemory = class {
4139
4245
  }
4140
4246
  /** Read-only maintenance report for one entity (spec §8.1). Reports, never repairs. */
4141
4247
  async lint(entityId) {
4142
- assertEntityId(entityId);
4248
+ assertEntityId2(entityId);
4143
4249
  return this.lintService.lint(entityId);
4144
4250
  }
4145
4251
  /**
@@ -4148,7 +4254,7 @@ var WikiMemory = class {
4148
4254
  * overrides are returned verbatim, so keep secrets out of `WikiConfig.prompts`.
4149
4255
  */
4150
4256
  async getInstructions(entityId) {
4151
- assertEntityId(entityId);
4257
+ assertEntityId2(entityId);
4152
4258
  const ontologyContext = await this.ontologyService.buildPromptContext(entityId);
4153
4259
  return this.promptService.buildInstructionTemplates(ontologyContext);
4154
4260
  }
@@ -4365,7 +4471,7 @@ var WikiMemory = class {
4365
4471
  if (await this.syncDrained(this.searchService.syncStale({ ids }))) this.dropStashedIds(stashed2);
4366
4472
  return;
4367
4473
  }
4368
- assertEntityId(entityId);
4474
+ assertEntityId2(entityId);
4369
4475
  const stashed = this.peekStashedIds(entityId);
4370
4476
  if (await this.syncDrained(this.searchService.syncEntries(entityId, stashed.get(entityId)?.keys() ?? []))) {
4371
4477
  this.dropStashedIds(stashed);
@@ -4404,6 +4510,23 @@ var WikiMemory = class {
4404
4510
  async history(entityId, factId) {
4405
4511
  return this.temporalService.history(entityId, factId);
4406
4512
  }
4513
+ /**
4514
+ * Store one mutable fact directly, with no LLM step (spec
4515
+ * `specs/core-remember/spec.md`). One transaction; resolves with the stored
4516
+ * row read back (`id`, timestamps, defaults, `isStale`, `trustTier`). Never
4517
+ * starts the librarian or heal and writes no event, in `'auto'` and
4518
+ * `'deferred'` mode alike. Embeds through `llmProvider.embed` when present;
4519
+ * keyword-only otherwise. Not idempotent. To replace an existing fact use
4520
+ * `supersede()` so history is kept. Opens its own transaction: do not call
4521
+ * it inside `withTransactionAsync` (the serialized adapter would deadlock).
4522
+ *
4523
+ * Throws `TypeError` on invalid input and `WikiStrictOntologyViolation` for
4524
+ * an `okf_type` the entity's strict manifest does not define; nothing is
4525
+ * written in either case.
4526
+ */
4527
+ async remember(entityId, input) {
4528
+ return this.rememberService.remember(entityId, input);
4529
+ }
4407
4530
  /**
4408
4531
  * Full and partial ingestion both reject foreign-owned generated fact IDs with
4409
4532
  * `WikiGraphNodeOwnershipConflict`. Such collisions are unexpected. Ingestion
@@ -4672,7 +4795,7 @@ var WikiMemory = class {
4672
4795
  _testAccessNonTestEnvWarned = new WeakMap();
4673
4796
  /** Max upsertGraph node ids held for their post-commit sync (spec #280 id threading). */
4674
4797
  WikiMemory.UPSERT_ID_STASH_CAP = 1e4;
4675
- function assertEntityId(entityId) {
4798
+ function assertEntityId2(entityId) {
4676
4799
  if (typeof entityId !== "string" || entityId.length === 0) {
4677
4800
  throw new TypeError("Invalid entityId: must be a non-empty string.");
4678
4801
  }
@@ -5194,7 +5317,7 @@ function formatOkfBundle(dump, options) {
5194
5317
  });
5195
5318
  return { files };
5196
5319
  }
5197
- var CONFIDENCE_VALUES = /* @__PURE__ */ new Set(["certain", "inferred", "tentative"]);
5320
+ var CONFIDENCE_VALUES2 = /* @__PURE__ */ new Set(["certain", "inferred", "tentative"]);
5198
5321
  var SOURCE_TYPES = /* @__PURE__ */ new Set([
5199
5322
  "user_stated",
5200
5323
  "librarian_inferred",
@@ -5340,7 +5463,7 @@ function frontmatterToFact(entityId, id, frontmatter, body, now) {
5340
5463
  title: typeof frontmatter.title === "string" ? frontmatter.title : "",
5341
5464
  body,
5342
5465
  tags: Array.isArray(frontmatter.tags) ? frontmatter.tags.filter((t) => typeof t === "string") : [],
5343
- confidence: CONFIDENCE_VALUES.has(String(frontmatter.confidence)) ? frontmatter.confidence : "tentative",
5466
+ confidence: CONFIDENCE_VALUES2.has(String(frontmatter.confidence)) ? frontmatter.confidence : "tentative",
5344
5467
  source_type: SOURCE_TYPES.has(String(frontmatter.source_type)) ? frontmatter.source_type : "user_stated",
5345
5468
  source_hash: typeof frontmatter.source_hash === "string" ? frontmatter.source_hash : null,
5346
5469
  source_ref: typeof frontmatter.resource === "string" ? frontmatter.resource : null,