@semiont/make-meaning 0.5.24 → 0.5.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { JobQueue } from '@semiont/jobs';
2
2
  import { SemiontProject } from '@semiont/core/node';
3
- import { GraphServiceConfig, VectorsServiceConfig, EmbeddingServiceConfig, StateUnit, EventBus, Logger, ResourceId, ResourceDescriptor, AnnotationId, components, ITransport, BaseUrl, ConnectionState, SemiontError, UserDID, EventMap, IContentTransport, PutBinaryRequest, PutBinaryOptions, AccessToken, BusRequestPrimitive, StoredEvent, Annotation, UserId, GatheredContext, ResourceAnnotations, AnnotationCategory, GraphPath, GraphConnection } from '@semiont/core';
3
+ import { GraphServiceConfig, VectorsServiceConfig, EmbeddingServiceConfig, StateUnit, EventBus, Logger, ResourceId, ResourceDescriptor, AnnotationId, components, ITransport, BaseUrl, ConnectionState, SemiontError, UserDID, EventMap, IContentTransport, PutBinaryRequest, PutBinaryOptions, ExtractionOutcome, AccessToken, BusRequestPrimitive, ChunkingConfig, StoredEvent, Annotation, UserId, GatheredContext, ResourceAnnotations, AnnotationCategory, GraphPath, GraphConnection } from '@semiont/core';
4
4
  import { EventStore, ViewStorage } from '@semiont/event-sourcing';
5
- import { WorkingTreeStore } from '@semiont/content';
5
+ import { WorkingTreeStore, AnchoredTextStore } from '@semiont/content';
6
6
  import { GraphDatabase } from '@semiont/graph';
7
- import { VectorStore, EmbeddingProvider, ChunkingConfig } from '@semiont/vectors';
7
+ import { VectorStore, EmbeddingProvider } from '@semiont/vectors';
8
8
  import { InferenceClient } from '@semiont/inference';
9
9
  import { BehaviorSubject, Observable } from 'rxjs';
10
10
  import { WorkerBus } from '@semiont/sdk';
@@ -176,6 +176,8 @@ interface KnowledgeBase {
176
176
  eventStore: EventStore;
177
177
  views: ViewStorage;
178
178
  content: WorkingTreeStore;
179
+ /** Derived coordinate maps for resources whose text had to be recovered. */
180
+ anchoredText: AnchoredTextStore;
179
181
  graph: GraphDatabase;
180
182
  weaveProgress: WeaveProgress;
181
183
  smeltProgress: SmeltProgress;
@@ -328,7 +330,7 @@ declare class Matcher {
328
330
  * Context-driven search: multi-source retrieval + composite scoring
329
331
  *
330
332
  * Retrieval sources:
331
- * 1. Name match — graph.searchResources(searchTerm)
333
+ * 1. Name match — graph.listResources({ search: searchTerm })
332
334
  * 2. Entity type match — graph.listResources({ entityTypes })
333
335
  * 3. Graph neighborhood — connections from GatheredContext
334
336
  *
@@ -393,6 +395,21 @@ declare class Browser {
393
395
  private readonly logger;
394
396
  constructor(views: ViewStorage, kb: KnowledgeBase, eventBus: EventBus, project: SemiontProject, config: MakeMeaningConfig, logger: Logger);
395
397
  initialize(): Promise<void>;
398
+ /**
399
+ * Serve a resource's derived coordinate map (ANCHORED-TEXT-CACHE Lane 5).
400
+ *
401
+ * Read-your-writes on the same barrier `llm-context` uses for vectors: a
402
+ * caller may arrive before the Smelter has finished the resource it just
403
+ * uploaded, so a miss waits for that content generation to settle rather than
404
+ * reporting "no map" for a document that is merely still being read.
405
+ *
406
+ * **This path never invokes the engine.** The Smelter is the sole producer.
407
+ * A miss that survives the barrier answers `null`, and the caller degrades —
408
+ * for a PDF annotation that means geometry with no quoted text, which is what
409
+ * shipped before any of this existed. OCR in a request path is precisely what
410
+ * this design exists to avoid.
411
+ */
412
+ private handleAnchoredText;
396
413
  private handleBrowseResource;
397
414
  private handleBrowseResources;
398
415
  private handleBrowseAnnotations;
@@ -479,6 +496,17 @@ declare function stopKnowledgeSystem(ks: KnowledgeSystem): Promise<void>;
479
496
  interface MakeMeaningService {
480
497
  knowledgeSystem: KnowledgeSystem;
481
498
  jobQueue: JobQueue;
499
+ /**
500
+ * The one SemiontProject this backend is serving — the same instance the
501
+ * KnowledgeSystem, the job queue and the bus handlers were built from.
502
+ *
503
+ * Exposed so request handlers reach for it instead of improvising their own
504
+ * from `config._metadata`. Two of them used to do exactly that, casting an
505
+ * underscore-prefixed field twice per request to rebuild a project that
506
+ * already existed a few frames up — and a project rebuilt that way is
507
+ * missing everything the entry point supplied it with.
508
+ */
509
+ project: SemiontProject;
482
510
  stop: () => Promise<void>;
483
511
  }
484
512
  declare function startMakeMeaning(project: SemiontProject, config: MakeMeaningConfig, eventBus: EventBus, logger: Logger, options?: {
@@ -582,6 +610,36 @@ declare class LocalContentTransport implements IContentTransport {
582
610
  putBinary(_request: PutBinaryRequest, _options?: PutBinaryOptions): Promise<{
583
611
  resourceId: ResourceId;
584
612
  }>;
613
+ /**
614
+ * Store a derived coordinate map under the content checksum the producer
615
+ * read (PERSIST-ANCHORS decision A — see the interface doc for why the
616
+ * producer supplies the key). In local mode this is the same store the
617
+ * HTTP route writes to — one storage authority, reached the same way from
618
+ * every process (ANCHORED-TEXT-CACHE Lane 5).
619
+ */
620
+ putAnchoredText(checksum: string, outcome: ExtractionOutcome, _options?: {
621
+ auth?: AccessToken;
622
+ }): Promise<void>;
623
+ /** The stored outcome, or null when nothing has derived one — the common case. */
624
+ getAnchoredText(resourceId: ResourceId, _options?: {
625
+ auth?: AccessToken;
626
+ }): Promise<ExtractionOutcome | null>;
627
+ /**
628
+ * The cache-consult read (PERSIST-ANCHORS P2c), straight from the store —
629
+ * checksum-addressed, so no view resolution and no settle barrier: the
630
+ * caller holds the content identity already.
631
+ */
632
+ getAnchoredTextByChecksum(checksum: string, _options?: {
633
+ auth?: AccessToken;
634
+ }): Promise<ExtractionOutcome | null>;
635
+ /**
636
+ * The store's would-hit keys, straight from the store — planning data for
637
+ * the reconcile diff (PERSIST-ANCHORS P0), so no settle barrier applies:
638
+ * presence is being asked, not content at a moment.
639
+ */
640
+ listAnchoredTextKeys(_options?: {
641
+ auth?: AccessToken;
642
+ }): Promise<string[]>;
585
643
  getBinary(resourceId: ResourceId, _options?: {
586
644
  auth?: AccessToken;
587
645
  }): Promise<{
@@ -741,6 +799,8 @@ interface SmelterActorStateUnitOptions {
741
799
  }
742
800
  interface SmelterActorStateUnit extends StateUnit {
743
801
  events$: Observable<SmelterEvent>;
802
+ /** `smelt:rebuild-anchors` commands (PERSIST-ANCHORS P0) — see the command-channel note above. */
803
+ rebuildAnchors$: Observable<EventMap['smelt:rebuild-anchors']>;
744
804
  start(): void;
745
805
  }
746
806
  declare function createSmelterActorStateUnit(options: SmelterActorStateUnitOptions): SmelterActorStateUnit;
@@ -786,9 +846,18 @@ interface ReconcileSummary {
786
846
  resourcesEmbedded: number;
787
847
  /** Tag-only drift healed by payload restamps — never embedding calls (S13). */
788
848
  resourcesRestamped: number;
849
+ /** Lost anchored-text artifacts re-derived by re-extraction — never
850
+ * embedding calls (PERSIST-ANCHORS P0, the third drift class). */
851
+ resourcesReanchored: number;
789
852
  resourceVectorsDeleted: number;
790
853
  annotationsEmbedded: number;
791
854
  annotationVectorsDeleted: number;
855
+ /** Live resources whose media type has an extractor — the coverage
856
+ * denominator (SMELTER-MEDIA-TYPES extraction-coverage). */
857
+ resourcesEligible: number;
858
+ /** Resources with vectors after the drain — the coverage numerator;
859
+ * eligible − indexed is the decline gap. */
860
+ resourcesIndexed: number;
792
861
  }
793
862
  type ReconcileState = {
794
863
  phase: 'pending';
@@ -818,13 +887,15 @@ interface SmelterTiming {
818
887
  * lanes and batch paths serve both kinds of input.
819
888
  */
820
889
  interface SmelterWorkItem {
821
- type: 'smelt:embed' | 'smelt:restamp' | 'smelt:purge' | 'smelt:embed-annotation' | 'smelt:purge-annotation';
890
+ type: 'smelt:embed' | 'smelt:restamp' | 'smelt:reanchor' | 'smelt:purge' | 'smelt:embed-annotation' | 'smelt:purge-annotation';
822
891
  resourceId: string;
823
892
  payload: Record<string, unknown>;
824
893
  }
825
894
  type SmelterInput = SmelterEvent | SmelterWorkItem;
826
895
  declare class Smelter {
827
896
  private events$;
897
+ /** `smelt:rebuild-anchors` commands — a separate stream, never the event mailbox (see SmelterActorStateUnit). */
898
+ private rebuildAnchors$;
828
899
  private vectorStore;
829
900
  private embeddingProvider;
830
901
  private content;
@@ -837,12 +908,24 @@ declare class Smelter {
837
908
  private static readonly RECONCILE_WAVE;
838
909
  private eventSubject;
839
910
  private sourceSubscription;
911
+ private commandSubscription;
840
912
  private pipelineSubscription;
841
913
  private _eventsProcessed;
842
914
  private _reconcileState;
843
915
  private workDone;
916
+ private workFailed;
844
917
  private workWaiter;
845
- constructor(events$: Observable<SmelterEvent>, vectorStore: VectorStore, embeddingProvider: EmbeddingProvider, content: IContentTransport, bus: BusRequestPrimitive, chunkingConfig: ChunkingConfig, timing: SmelterTiming, logger: Logger);
918
+ /**
919
+ * Serializes every planner drain (reconcile, anchored-text rebuilds):
920
+ * there is one waiter slot, and the weave:rebuild rule — rebuilds never
921
+ * interleave — applies to every unit here being a potential multi-second
922
+ * OCR pass.
923
+ */
924
+ private drainChain;
925
+ constructor(events$: Observable<SmelterEvent>,
926
+ /** `smelt:rebuild-anchors` commands — a separate stream, never the event mailbox (see SmelterActorStateUnit). */
927
+ rebuildAnchors$: Observable<EventMap['smelt:rebuild-anchors']>, vectorStore: VectorStore, embeddingProvider: EmbeddingProvider, content: IContentTransport, bus: BusRequestPrimitive, chunkingConfig: ChunkingConfig, timing: SmelterTiming, logger: Logger);
928
+ private readonly anchoredStore;
846
929
  get eventsProcessed(): number;
847
930
  get reconcileState(): ReconcileState;
848
931
  initialize(): void;
@@ -870,6 +953,20 @@ declare class Smelter {
870
953
  * rides the next embed.
871
954
  */
872
955
  private restampResource;
956
+ /**
957
+ * Re-derive a lost anchored-text artifact from the resource's current
958
+ * bytes (PERSIST-ANCHORS P0, the third drift class). Extraction is the
959
+ * cost here — the vectors are already correct, so this NEVER calls the
960
+ * embedding provider, the vector store, or the settled signal: the index
961
+ * decision was already made and announced at its checksum; only the map
962
+ * is missing. Name the work for what it does (the S13 discipline).
963
+ *
964
+ * The publish is STRICT, unlike the embed path's best-effort side
965
+ * publish: here the artifact IS the job, so a store failure must throw —
966
+ * the pipeline logs and counts it, and the rebuild command's partial-
967
+ * failure accounting depends on that throw.
968
+ */
969
+ private reanchorResource;
873
970
  private handleResourcePurge;
874
971
  /**
875
972
  * Resolve a resource's embeddable text: bytes via the content transport,
@@ -944,8 +1041,44 @@ declare class Smelter {
944
1041
  * completion. The pipeline ticks `noteWorkDone` for every consumed work
945
1042
  * item (success or failure — failures are logged like any live event), so
946
1043
  * each wave's waiter resolves exactly when its items have been processed.
1044
+ *
1045
+ * Serialized through `drainChain`: there is ONE waiter slot, and the
1046
+ * planners that drain (reconcile, `smelt:rebuild-anchors`) must not
1047
+ * interleave — a rebuild command arriving mid-reconcile waits its turn.
1048
+ *
1049
+ * @returns how many of THESE items failed — the rebuild command's
1050
+ * partial-failure accounting (failure detail is in the logs).
947
1051
  */
948
1052
  private drain;
1053
+ /**
1054
+ * `smelt:rebuild-anchors` — the operator's explicit re-derivation of
1055
+ * anchored-text artifacts (PERSIST-ANCHORS P0), shaped after
1056
+ * `weave:rebuild`: optionally scoped, strictly serialized (concatMap on
1057
+ * the command stream + the drain chain), correlated ok/failed replies,
1058
+ * and partial completion FAILS — a rebuild that quietly skipped resources
1059
+ * would present exactly like a document with no text, which is the #845
1060
+ * failure mode wearing different clothes.
1061
+ *
1062
+ * Never destructive: nothing is deleted first, stale entries are simply
1063
+ * overwritten (the W5-frames lesson — a rebuild that clears before it
1064
+ * re-derives turns a partial failure into a loss). Re-anchoring makes
1065
+ * zero embedding calls; work items ride the normal per-resource lanes,
1066
+ * so a rebuild can never interleave with live processing of the same
1067
+ * resource (S1/S2).
1068
+ */
1069
+ private rebuildAnchors;
1070
+ /**
1071
+ * Embeddable live resources, each with the catalog's claims: the primary
1072
+ * representation's checksum (the bytes the smelter would read), the
1073
+ * current entity-type set (the discriminator the stamps must carry), and
1074
+ * whether the media type's extractor derives geometry (whether an
1075
+ * anchored-text artifact should exist). Embeddable ⇔ an extractor exists
1076
+ * for the media type's strategy — the same registry the live fetch
1077
+ * resolves, and `yieldsGeometry` is declared on the extractor itself, so
1078
+ * every gate here and the live fetch's behavior are twins by construction.
1079
+ * Shared by `reconcile()` and the `smelt:rebuild-anchors` planner.
1080
+ */
1081
+ private classifyEmbeddable;
949
1082
  /** Page through `browse:resources-requested` until the catalog is exhausted. */
950
1083
  private listAllResources;
951
1084
  }
@@ -1254,6 +1387,14 @@ declare class AnnotationOperations {
1254
1387
  interface ListResourcesFilters {
1255
1388
  search?: string;
1256
1389
  archived?: boolean;
1390
+ entityType?: string;
1391
+ offset?: number;
1392
+ limit?: number;
1393
+ }
1394
+ interface ListResourcesResult {
1395
+ resources: ResourceDescriptor[];
1396
+ /** Size of the whole match set, not of the returned page. */
1397
+ total: number;
1257
1398
  }
1258
1399
  declare class ResourceContext {
1259
1400
  /**
@@ -1261,17 +1402,20 @@ declare class ResourceContext {
1261
1402
  */
1262
1403
  static getResourceMetadata(resourceId: ResourceId, kb: KnowledgeBase): Promise<ResourceDescriptor | null>;
1263
1404
  /**
1264
- * List resources, optionally filtered.
1405
+ * List resources, optionally filtered, as one page plus the size of the whole
1406
+ * match set. Every filter is applied before pagination on both paths — a
1407
+ * filter applied afterwards narrows the page rather than the match set, which
1408
+ * is how a search scoped to an entity type can come back empty while hundreds
1409
+ * of resources match.
1265
1410
  *
1266
- * When `search` is set, delegates to `kb.graph.searchResources`, which runs
1267
- * the name match in the graph engine instead of scanning every view in JS.
1268
- * The graph result is then narrowed by `archived` if requested.
1411
+ * When `search` is set, the entire query filtering, ordering and
1412
+ * pagination runs inside the graph engine.
1269
1413
  *
1270
- * When `search` is unset, falls back to scanning all materialized views.
1271
- * (TODO: also push the listing path through the graph for large KBs.)
1414
+ * When `search` is unset, the materialized views answer instead. They are the
1415
+ * barrier-stamped projection, so an unsearched listing is read-your-writes
1416
+ * where the graph is only eventually consistent.
1272
1417
  */
1273
- static listResources(filters: ListResourcesFilters | undefined, kb: KnowledgeBase): Promise<ResourceDescriptor[]>;
1274
- private static sortByDateDesc;
1418
+ static listResources(filters: ListResourcesFilters | undefined, kb: KnowledgeBase): Promise<ListResourcesResult>;
1275
1419
  /**
1276
1420
  * Add content previews to resources (for search results)
1277
1421
  * Retrieves and decodes the first 200 characters of each resource's primary representation
@@ -1407,11 +1551,6 @@ declare class GraphContext {
1407
1551
  * Requires graph traversal - must use graph database
1408
1552
  */
1409
1553
  static getResourceConnections(resourceId: ResourceId, kb: KnowledgeBase): Promise<GraphConnection[]>;
1410
- /**
1411
- * Search resources by name (cross-resource query)
1412
- * Requires full-text search - must use graph database
1413
- */
1414
- static searchResources(query: string, kb: KnowledgeBase, limit?: number): Promise<ResourceDescriptor[]>;
1415
1554
  /**
1416
1555
  * Build the unified knowledge graph for a resource's neighborhood:
1417
1556
  * resources AND annotations as typed nodes, typed/directional edges.
@@ -1487,4 +1626,4 @@ declare function generateResourceSummary(resourceName: string, content: string,
1487
1626
  declare function generateReferenceSuggestions(referenceTitle: string, client: InferenceClient, entityType?: string, currentContent?: string): Promise<string[] | null>;
1488
1627
 
1489
1628
  export { AnnotationContext, AnnotationOperations, BACKUP_FORMAT, Browser, CloneTokenManager, FORMAT_VERSION, Gatherer$1 as Gatherer, GraphContext, LLMContext, LocalContentTransport, LocalTransport, Matcher, ResourceContext, ResourceOperations, Smelter, Stower, asBusRequestPrimitive, bootstrapEntityTypes, createKnowledgeBase, createSmelterActorStateUnit, exportBackup, exportLinkedData, generateReferenceSuggestions, generateResourceSummary, importBackup, importLinkedData, isBackupManifest, readEntityTypesProjection, registerAnnotationAssemblyHandler, registerAnnotationLookupHandlers, registerBindUpdateBodyHandler, registerBusHandlers, registerJobCommandHandlers, startMakeMeaning, stopKnowledgeSystem, validateManifestVersion };
1490
- export type { BackupContentReader, BackupEventStoreReader, BackupExporterOptions, BackupImportResult, BackupImporterOptions, BackupManifestHeader, BackupStreamSummary, BuildContextOptions, ContentBlobResolver, CreateAnnotationResult, CreateResourceInput, CreateResourceResult, KnowledgeBase, KnowledgeSystem, LLMContextOptions, LinkedDataContentReader, LinkedDataExporterOptions, LinkedDataImportResult, LinkedDataImporterOptions, LinkedDataViewReader, ListResourcesFilters, LocalTransportConfig, MakeMeaningConfig, MakeMeaningService, ReconcileState, ReconcileSummary, ReplayStats, SmelterActorStateUnit, SmelterActorStateUnitOptions, SmelterEvent, SmelterInput, SmelterTiming, SmelterWorkItem, UpdateAnnotationBodyResult };
1629
+ export type { BackupContentReader, BackupEventStoreReader, BackupExporterOptions, BackupImportResult, BackupImporterOptions, BackupManifestHeader, BackupStreamSummary, BuildContextOptions, ContentBlobResolver, CreateAnnotationResult, CreateResourceInput, CreateResourceResult, KnowledgeBase, KnowledgeSystem, LLMContextOptions, LinkedDataContentReader, LinkedDataExporterOptions, LinkedDataImportResult, LinkedDataImporterOptions, LinkedDataViewReader, ListResourcesFilters, ListResourcesResult, LocalTransportConfig, MakeMeaningConfig, MakeMeaningService, ReconcileState, ReconcileSummary, ReplayStats, SmelterActorStateUnit, SmelterActorStateUnitOptions, SmelterEvent, SmelterInput, SmelterTiming, SmelterWorkItem, UpdateAnnotationBodyResult };