@semiont/make-meaning 0.4.18 → 0.4.20
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 +119 -22
- package/dist/index.js +391 -225
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10000,7 +10000,7 @@ import { WorkingTreeStore } from "@semiont/content";
|
|
|
10000
10000
|
var import_rxjs = __toESM(require_cjs(), 1);
|
|
10001
10001
|
var import_operators = __toESM(require_operators(), 1);
|
|
10002
10002
|
import { EventQuery } from "@semiont/event-sourcing";
|
|
10003
|
-
import { didToAgent, burstBuffer } from "@semiont/core";
|
|
10003
|
+
import { didToAgent, burstBuffer, errField } from "@semiont/core";
|
|
10004
10004
|
import { resourceId as makeResourceId, annotationId as makeAnnotationId, findBodyItem } from "@semiont/core";
|
|
10005
10005
|
|
|
10006
10006
|
// src/batch-utils.ts
|
|
@@ -10109,7 +10109,7 @@ var GraphDBConsumer = class _GraphDBConsumer {
|
|
|
10109
10109
|
this.logger.error("Failed to apply event to graph", {
|
|
10110
10110
|
eventType: storedEvent.type,
|
|
10111
10111
|
resourceId: storedEvent.resourceId,
|
|
10112
|
-
error
|
|
10112
|
+
error: errField(error)
|
|
10113
10113
|
});
|
|
10114
10114
|
}
|
|
10115
10115
|
}
|
|
@@ -10148,7 +10148,7 @@ var GraphDBConsumer = class _GraphDBConsumer {
|
|
|
10148
10148
|
this.logger.error("Failed to process batch run", {
|
|
10149
10149
|
eventType: run[0].type,
|
|
10150
10150
|
runSize: run.length,
|
|
10151
|
-
error
|
|
10151
|
+
error: errField(error)
|
|
10152
10152
|
});
|
|
10153
10153
|
}
|
|
10154
10154
|
const last = run[run.length - 1];
|
|
@@ -10218,7 +10218,8 @@ var GraphDBConsumer = class _GraphDBConsumer {
|
|
|
10218
10218
|
archived: false,
|
|
10219
10219
|
dateCreated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10220
10220
|
wasAttributedTo: didToAgent(event.userId),
|
|
10221
|
-
creationMethod: event.payload.creationMethod
|
|
10221
|
+
creationMethod: event.payload.creationMethod,
|
|
10222
|
+
...event.payload.storageUri ? { storageUri: event.payload.storageUri } : {}
|
|
10222
10223
|
};
|
|
10223
10224
|
}
|
|
10224
10225
|
/**
|
|
@@ -10304,8 +10305,7 @@ var GraphDBConsumer = class _GraphDBConsumer {
|
|
|
10304
10305
|
} catch (error) {
|
|
10305
10306
|
this.logger.error("Error in annotation.body.updated handler", {
|
|
10306
10307
|
annotationId: event.payload.annotationId,
|
|
10307
|
-
error
|
|
10308
|
-
stack: error instanceof Error ? error.stack : void 0
|
|
10308
|
+
error: errField(error)
|
|
10309
10309
|
});
|
|
10310
10310
|
}
|
|
10311
10311
|
break;
|
|
@@ -10417,23 +10417,25 @@ var GraphDBConsumer = class _GraphDBConsumer {
|
|
|
10417
10417
|
// src/smelter.ts
|
|
10418
10418
|
var import_rxjs2 = __toESM(require_cjs(), 1);
|
|
10419
10419
|
var import_operators2 = __toESM(require_operators(), 1);
|
|
10420
|
-
import {
|
|
10421
|
-
import { burstBuffer as burstBuffer2 } from "@semiont/core";
|
|
10420
|
+
import { burstBuffer as burstBuffer2, errField as errField2 } from "@semiont/core";
|
|
10422
10421
|
import { resourceId as makeResourceId2, annotationId as makeAnnotationId2 } from "@semiont/core";
|
|
10423
10422
|
import { chunkText, DEFAULT_CHUNKING_CONFIG } from "@semiont/vectors";
|
|
10424
10423
|
import { getExactText, getTargetSelector } from "@semiont/api-client";
|
|
10425
10424
|
var Smelter = class _Smelter {
|
|
10426
|
-
constructor(
|
|
10427
|
-
this.eventStore = eventStore;
|
|
10425
|
+
constructor(_eventStore, eventBus, vectorStore, embeddingProvider, contentStore, embeddingStore, viewStorage, logger, chunkingConfig) {
|
|
10428
10426
|
this.eventBus = eventBus;
|
|
10429
10427
|
this.vectorStore = vectorStore;
|
|
10430
10428
|
this.embeddingProvider = embeddingProvider;
|
|
10431
10429
|
this.contentStore = contentStore;
|
|
10430
|
+
this.embeddingStore = embeddingStore;
|
|
10431
|
+
this.viewStorage = viewStorage;
|
|
10432
10432
|
this.logger = logger;
|
|
10433
10433
|
this.chunkingConfig = chunkingConfig ?? DEFAULT_CHUNKING_CONFIG;
|
|
10434
10434
|
}
|
|
10435
10435
|
static SMELTER_RELEVANT_EVENTS = /* @__PURE__ */ new Set([
|
|
10436
10436
|
"yield:created",
|
|
10437
|
+
"yield:updated",
|
|
10438
|
+
"yield:representation-added",
|
|
10437
10439
|
"mark:archived",
|
|
10438
10440
|
"mark:added",
|
|
10439
10441
|
"mark:removed"
|
|
@@ -10485,68 +10487,121 @@ var Smelter = class _Smelter {
|
|
|
10485
10487
|
this.logger.info("Smelter actor stopped");
|
|
10486
10488
|
}
|
|
10487
10489
|
/**
|
|
10488
|
-
* Rebuild the vector store from
|
|
10489
|
-
*
|
|
10490
|
-
*
|
|
10490
|
+
* Rebuild the vector store from the EmbeddingStore (.semiont/embeddings/).
|
|
10491
|
+
*
|
|
10492
|
+
* For each stored file, checks whether the model matches the configured
|
|
10493
|
+
* provider. On mismatch, re-embeds from the stored text and overwrites the
|
|
10494
|
+
* file before upserting into Qdrant. On match, loads the stored vectors
|
|
10495
|
+
* directly — no embedding provider calls needed.
|
|
10491
10496
|
*/
|
|
10492
10497
|
async rebuildAll() {
|
|
10493
|
-
this.logger.info("Rebuilding vector store from
|
|
10498
|
+
this.logger.info("Rebuilding vector store from EmbeddingStore");
|
|
10494
10499
|
await this.vectorStore.clearAll();
|
|
10495
|
-
const
|
|
10496
|
-
this.
|
|
10497
|
-
const
|
|
10498
|
-
|
|
10499
|
-
|
|
10500
|
-
|
|
10501
|
-
const
|
|
10502
|
-
|
|
10503
|
-
);
|
|
10504
|
-
|
|
10505
|
-
|
|
10506
|
-
|
|
10507
|
-
|
|
10508
|
-
|
|
10509
|
-
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
|
|
10513
|
-
|
|
10514
|
-
|
|
10515
|
-
|
|
10516
|
-
|
|
10517
|
-
|
|
10518
|
-
|
|
10519
|
-
|
|
10520
|
-
|
|
10521
|
-
|
|
10522
|
-
|
|
10523
|
-
|
|
10524
|
-
|
|
10525
|
-
|
|
10526
|
-
|
|
10527
|
-
|
|
10528
|
-
|
|
10529
|
-
|
|
10530
|
-
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
|
|
10534
|
-
|
|
10535
|
-
|
|
10536
|
-
|
|
10537
|
-
|
|
10538
|
-
|
|
10539
|
-
|
|
10540
|
-
|
|
10541
|
-
|
|
10542
|
-
|
|
10543
|
-
|
|
10544
|
-
|
|
10500
|
+
const currentModel = this.embeddingProvider.model();
|
|
10501
|
+
const currentDimensions = this.embeddingProvider.dimensions();
|
|
10502
|
+
const resourceIds = await this.embeddingStore.getAllResourceIds();
|
|
10503
|
+
this.logger.info("Found resource embedding files", { count: resourceIds.length });
|
|
10504
|
+
let resourcesIndexed = 0;
|
|
10505
|
+
for (const rid of resourceIds) {
|
|
10506
|
+
const resourceId7 = makeResourceId2(rid);
|
|
10507
|
+
const stored = await this.embeddingStore.readResourceEmbeddings(resourceId7);
|
|
10508
|
+
if (!stored || stored.chunks.length === 0) continue;
|
|
10509
|
+
let chunks;
|
|
10510
|
+
if (stored.model !== currentModel) {
|
|
10511
|
+
this.logger.info("Re-embedding resource (model mismatch)", {
|
|
10512
|
+
resourceId: rid,
|
|
10513
|
+
storedModel: stored.model,
|
|
10514
|
+
currentModel
|
|
10515
|
+
});
|
|
10516
|
+
const texts = stored.chunks.map((c) => c.text);
|
|
10517
|
+
const embeddings = await this.embeddingProvider.embedBatch(texts);
|
|
10518
|
+
chunks = stored.chunks.map((c, i) => ({
|
|
10519
|
+
chunkIndex: c.chunkIndex,
|
|
10520
|
+
text: c.text,
|
|
10521
|
+
embedding: embeddings[i]
|
|
10522
|
+
}));
|
|
10523
|
+
await this.embeddingStore.writeResourceChunks(resourceId7, currentModel, currentDimensions, chunks);
|
|
10524
|
+
} else {
|
|
10525
|
+
chunks = stored.chunks;
|
|
10526
|
+
}
|
|
10527
|
+
await this.vectorStore.upsertResourceVectors(resourceId7, chunks);
|
|
10528
|
+
resourcesIndexed++;
|
|
10529
|
+
}
|
|
10530
|
+
const annotationIds = await this.embeddingStore.getAllAnnotationIds();
|
|
10531
|
+
this.logger.info("Found annotation embedding files", { count: annotationIds.length });
|
|
10532
|
+
let annotationsIndexed = 0;
|
|
10533
|
+
for (const aid of annotationIds) {
|
|
10534
|
+
const annotationId3 = makeAnnotationId2(aid);
|
|
10535
|
+
const stored = await this.embeddingStore.readAnnotationEmbedding(annotationId3);
|
|
10536
|
+
if (!stored) continue;
|
|
10537
|
+
let embedding;
|
|
10538
|
+
if (stored.model !== currentModel) {
|
|
10539
|
+
this.logger.info("Re-embedding annotation (model mismatch)", {
|
|
10540
|
+
annotationId: aid,
|
|
10541
|
+
storedModel: stored.model,
|
|
10542
|
+
currentModel
|
|
10543
|
+
});
|
|
10544
|
+
embedding = await this.embeddingProvider.embed(stored.text);
|
|
10545
|
+
await this.embeddingStore.writeAnnotationEmbedding(
|
|
10546
|
+
annotationId3,
|
|
10547
|
+
makeResourceId2(stored.resourceId),
|
|
10548
|
+
currentModel,
|
|
10549
|
+
currentDimensions,
|
|
10550
|
+
stored.text,
|
|
10551
|
+
embedding,
|
|
10552
|
+
stored.motivation,
|
|
10553
|
+
stored.entityTypes
|
|
10545
10554
|
);
|
|
10555
|
+
} else {
|
|
10556
|
+
embedding = stored.embedding;
|
|
10546
10557
|
}
|
|
10547
|
-
|
|
10558
|
+
const payload = {
|
|
10559
|
+
annotationId: annotationId3,
|
|
10560
|
+
resourceId: makeResourceId2(stored.resourceId),
|
|
10561
|
+
motivation: stored.motivation,
|
|
10562
|
+
entityTypes: stored.entityTypes,
|
|
10563
|
+
exactText: stored.text
|
|
10564
|
+
};
|
|
10565
|
+
await this.vectorStore.upsertAnnotationVector(annotationId3, embedding, payload);
|
|
10566
|
+
annotationsIndexed++;
|
|
10567
|
+
}
|
|
10568
|
+
const storedResourceIdSet = new Set(resourceIds);
|
|
10569
|
+
const allViews = await this.viewStorage.getAll();
|
|
10570
|
+
let backfilled = 0;
|
|
10571
|
+
for (const view of allViews) {
|
|
10572
|
+
const ridStr = view.resource["@id"];
|
|
10573
|
+
if (storedResourceIdSet.has(ridStr)) continue;
|
|
10574
|
+
if (view.resource.archived) continue;
|
|
10575
|
+
if (!view.resource.storageUri) continue;
|
|
10576
|
+
let content;
|
|
10577
|
+
try {
|
|
10578
|
+
content = await this.contentStore.retrieve(view.resource.storageUri);
|
|
10579
|
+
} catch (err) {
|
|
10580
|
+
this.logger.warn("Smelter back-fill skipped \u2014 content missing", {
|
|
10581
|
+
resourceId: ridStr,
|
|
10582
|
+
storageUri: view.resource.storageUri,
|
|
10583
|
+
error: err instanceof Error ? err.message : String(err)
|
|
10584
|
+
});
|
|
10585
|
+
continue;
|
|
10586
|
+
}
|
|
10587
|
+
const text = new TextDecoder().decode(content);
|
|
10588
|
+
if (!text.trim()) continue;
|
|
10589
|
+
const chunks = chunkText(text, this.chunkingConfig);
|
|
10590
|
+
if (chunks.length === 0) continue;
|
|
10591
|
+
const rid = makeResourceId2(ridStr);
|
|
10592
|
+
const embeddings = await this.embeddingProvider.embedBatch(chunks);
|
|
10593
|
+
const embeddingChunks = chunks.map((chunkText2, i) => ({
|
|
10594
|
+
chunkIndex: i,
|
|
10595
|
+
text: chunkText2,
|
|
10596
|
+
embedding: embeddings[i]
|
|
10597
|
+
}));
|
|
10598
|
+
await this.embeddingStore.writeResourceChunks(rid, currentModel, currentDimensions, embeddingChunks);
|
|
10599
|
+
await this.vectorStore.upsertResourceVectors(rid, embeddingChunks);
|
|
10600
|
+
backfilled++;
|
|
10601
|
+
resourcesIndexed++;
|
|
10602
|
+
this.logger.info("Smelter back-filled missing resource embedding", { resourceId: ridStr });
|
|
10548
10603
|
}
|
|
10549
|
-
this.logger.info("Vector store rebuild complete", { resourcesIndexed
|
|
10604
|
+
this.logger.info("Vector store rebuild complete", { resourcesIndexed, annotationsIndexed, backfilled });
|
|
10550
10605
|
}
|
|
10551
10606
|
async processBatch(events) {
|
|
10552
10607
|
const runs = partitionByType(events);
|
|
@@ -10561,15 +10616,13 @@ var Smelter = class _Smelter {
|
|
|
10561
10616
|
this.logger.error("Smelter failed to process batch run", {
|
|
10562
10617
|
eventType: run[0].type,
|
|
10563
10618
|
runSize: run.length,
|
|
10564
|
-
error
|
|
10619
|
+
error: errField2(error)
|
|
10565
10620
|
});
|
|
10566
10621
|
}
|
|
10567
10622
|
}
|
|
10568
10623
|
}
|
|
10569
10624
|
/**
|
|
10570
10625
|
* Batch-optimized processing for consecutive events of the same type.
|
|
10571
|
-
* Collects all texts across events, embeds in a single embedBatch() call,
|
|
10572
|
-
* then distributes results back to their respective resources/annotations.
|
|
10573
10626
|
*/
|
|
10574
10627
|
async applyBatchByType(events) {
|
|
10575
10628
|
const type = events[0].type;
|
|
@@ -10587,8 +10640,8 @@ var Smelter = class _Smelter {
|
|
|
10587
10640
|
}
|
|
10588
10641
|
}
|
|
10589
10642
|
/**
|
|
10590
|
-
* Batch-embed chunks from multiple
|
|
10591
|
-
* embedBatch() call, then
|
|
10643
|
+
* Batch-embed chunks from multiple yield:created events in a single
|
|
10644
|
+
* embedBatch() call, then write to EmbeddingStore and index per resource.
|
|
10592
10645
|
*/
|
|
10593
10646
|
async batchResourceCreated(events) {
|
|
10594
10647
|
const resourceData = [];
|
|
@@ -10613,18 +10666,12 @@ var Smelter = class _Smelter {
|
|
|
10613
10666
|
const dimensions = this.embeddingProvider.dimensions();
|
|
10614
10667
|
let offset = 0;
|
|
10615
10668
|
for (const { rid, chunks } of resourceData) {
|
|
10616
|
-
const embeddingChunks = chunks.map((text, i) => {
|
|
10617
|
-
|
|
10618
|
-
|
|
10619
|
-
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
embedding,
|
|
10623
|
-
model,
|
|
10624
|
-
dimensions
|
|
10625
|
-
});
|
|
10626
|
-
return { chunkIndex: i, text, embedding };
|
|
10627
|
-
});
|
|
10669
|
+
const embeddingChunks = chunks.map((text, i) => ({
|
|
10670
|
+
chunkIndex: i,
|
|
10671
|
+
text,
|
|
10672
|
+
embedding: allEmbeddings[offset + i]
|
|
10673
|
+
}));
|
|
10674
|
+
await this.embeddingStore.writeResourceChunks(rid, model, dimensions, embeddingChunks);
|
|
10628
10675
|
await this.vectorStore.upsertResourceVectors(rid, embeddingChunks);
|
|
10629
10676
|
this.logger.debug("Smelter batch-indexed resource", {
|
|
10630
10677
|
resourceId: String(rid),
|
|
@@ -10634,8 +10681,8 @@ var Smelter = class _Smelter {
|
|
|
10634
10681
|
}
|
|
10635
10682
|
}
|
|
10636
10683
|
/**
|
|
10637
|
-
* Batch-embed exact texts from multiple
|
|
10638
|
-
*
|
|
10684
|
+
* Batch-embed exact texts from multiple mark:added events in a single
|
|
10685
|
+
* embedBatch() call, then write to EmbeddingStore and index per annotation.
|
|
10639
10686
|
*/
|
|
10640
10687
|
async batchAnnotationAdded(events) {
|
|
10641
10688
|
const annotationData = [];
|
|
@@ -10650,30 +10697,34 @@ var Smelter = class _Smelter {
|
|
|
10650
10697
|
rid: makeResourceId2(event.resourceId),
|
|
10651
10698
|
aid: makeAnnotationId2(annotation.id),
|
|
10652
10699
|
exactText,
|
|
10653
|
-
annotation
|
|
10700
|
+
motivation: annotation.motivation ?? "",
|
|
10701
|
+
entityTypes: annotation.entityTypes ?? []
|
|
10654
10702
|
});
|
|
10655
10703
|
}
|
|
10656
10704
|
if (annotationData.length === 0) return;
|
|
10657
10705
|
const allEmbeddings = await this.embeddingProvider.embedBatch(
|
|
10658
10706
|
annotationData.map((a) => a.exactText)
|
|
10659
10707
|
);
|
|
10708
|
+
const model = this.embeddingProvider.model();
|
|
10709
|
+
const dimensions = this.embeddingProvider.dimensions();
|
|
10660
10710
|
for (let i = 0; i < annotationData.length; i++) {
|
|
10661
|
-
const { rid, aid, exactText,
|
|
10711
|
+
const { rid, aid, exactText, motivation, entityTypes } = annotationData[i];
|
|
10662
10712
|
const embedding = allEmbeddings[i];
|
|
10663
|
-
this.
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
|
|
10667
|
-
|
|
10713
|
+
await this.embeddingStore.writeAnnotationEmbedding(
|
|
10714
|
+
aid,
|
|
10715
|
+
rid,
|
|
10716
|
+
model,
|
|
10717
|
+
dimensions,
|
|
10718
|
+
exactText,
|
|
10668
10719
|
embedding,
|
|
10669
|
-
|
|
10670
|
-
|
|
10671
|
-
|
|
10720
|
+
motivation,
|
|
10721
|
+
entityTypes
|
|
10722
|
+
);
|
|
10672
10723
|
const payload = {
|
|
10673
10724
|
annotationId: aid,
|
|
10674
10725
|
resourceId: rid,
|
|
10675
|
-
motivation
|
|
10676
|
-
entityTypes
|
|
10726
|
+
motivation,
|
|
10727
|
+
entityTypes,
|
|
10677
10728
|
exactText
|
|
10678
10729
|
};
|
|
10679
10730
|
await this.vectorStore.upsertAnnotationVector(aid, embedding, payload);
|
|
@@ -10696,19 +10747,24 @@ var Smelter = class _Smelter {
|
|
|
10696
10747
|
}
|
|
10697
10748
|
}
|
|
10698
10749
|
async processEvent(storedEvent) {
|
|
10699
|
-
|
|
10700
|
-
switch (event.type) {
|
|
10750
|
+
switch (storedEvent.type) {
|
|
10701
10751
|
case "yield:created":
|
|
10702
|
-
await this.handleResourceCreated(
|
|
10752
|
+
await this.handleResourceCreated(storedEvent);
|
|
10753
|
+
break;
|
|
10754
|
+
case "yield:updated":
|
|
10755
|
+
await this.handleResourceUpdated(storedEvent);
|
|
10756
|
+
break;
|
|
10757
|
+
case "yield:representation-added":
|
|
10758
|
+
await this.handleRepresentationAdded(storedEvent);
|
|
10703
10759
|
break;
|
|
10704
10760
|
case "mark:archived":
|
|
10705
|
-
await this.handleResourceArchived(
|
|
10761
|
+
await this.handleResourceArchived(storedEvent);
|
|
10706
10762
|
break;
|
|
10707
10763
|
case "mark:added":
|
|
10708
|
-
await this.handleAnnotationAdded(
|
|
10764
|
+
await this.handleAnnotationAdded(storedEvent);
|
|
10709
10765
|
break;
|
|
10710
10766
|
case "mark:removed":
|
|
10711
|
-
await this.handleAnnotationRemoved(
|
|
10767
|
+
await this.handleAnnotationRemoved(storedEvent);
|
|
10712
10768
|
break;
|
|
10713
10769
|
}
|
|
10714
10770
|
}
|
|
@@ -10743,18 +10799,13 @@ var Smelter = class _Smelter {
|
|
|
10743
10799
|
dimensions,
|
|
10744
10800
|
heapMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
|
|
10745
10801
|
});
|
|
10746
|
-
const embeddingChunks = chunks.map((text2, i) => {
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
dimensions
|
|
10754
|
-
});
|
|
10755
|
-
return { chunkIndex: i, text: text2, embedding: embeddings[i] };
|
|
10756
|
-
});
|
|
10757
|
-
this.logger.info("Smelter emitted events", {
|
|
10802
|
+
const embeddingChunks = chunks.map((text2, i) => ({
|
|
10803
|
+
chunkIndex: i,
|
|
10804
|
+
text: text2,
|
|
10805
|
+
embedding: embeddings[i]
|
|
10806
|
+
}));
|
|
10807
|
+
await this.embeddingStore.writeResourceChunks(rid, model, dimensions, embeddingChunks);
|
|
10808
|
+
this.logger.info("Smelter wrote resource embeddings to store", {
|
|
10758
10809
|
resourceId: String(rid),
|
|
10759
10810
|
chunkCount: embeddingChunks.length,
|
|
10760
10811
|
heapMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
|
|
@@ -10766,13 +10817,51 @@ var Smelter = class _Smelter {
|
|
|
10766
10817
|
heapMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
|
|
10767
10818
|
});
|
|
10768
10819
|
}
|
|
10820
|
+
/**
|
|
10821
|
+
* Re-embed a resource whose content has changed in-place.
|
|
10822
|
+
*
|
|
10823
|
+
* Used by yield:updated and yield:representation-added handlers. Reads the
|
|
10824
|
+
* current storageUri from the materialized view (which is updated before the
|
|
10825
|
+
* EventBus fires), deletes stale Qdrant vectors, and overwrites the
|
|
10826
|
+
* EmbeddingStore file with fresh chunks.
|
|
10827
|
+
*/
|
|
10828
|
+
async reembedResource(rid) {
|
|
10829
|
+
const view = await this.viewStorage.get(rid);
|
|
10830
|
+
const storageUri = view?.resource.storageUri;
|
|
10831
|
+
if (!storageUri) return;
|
|
10832
|
+
const content = await this.contentStore.retrieve(storageUri);
|
|
10833
|
+
if (!content) return;
|
|
10834
|
+
const text = new TextDecoder().decode(content);
|
|
10835
|
+
if (!text.trim()) return;
|
|
10836
|
+
const chunks = chunkText(text, this.chunkingConfig);
|
|
10837
|
+
if (chunks.length === 0) return;
|
|
10838
|
+
const embeddings = await this.embeddingProvider.embedBatch(chunks);
|
|
10839
|
+
const model = this.embeddingProvider.model();
|
|
10840
|
+
const dimensions = this.embeddingProvider.dimensions();
|
|
10841
|
+
const embeddingChunks = chunks.map((chunkText2, i) => ({
|
|
10842
|
+
chunkIndex: i,
|
|
10843
|
+
text: chunkText2,
|
|
10844
|
+
embedding: embeddings[i]
|
|
10845
|
+
}));
|
|
10846
|
+
await this.embeddingStore.writeResourceChunks(rid, model, dimensions, embeddingChunks);
|
|
10847
|
+
await this.vectorStore.deleteResourceVectors(rid);
|
|
10848
|
+
await this.vectorStore.upsertResourceVectors(rid, embeddingChunks);
|
|
10849
|
+
this.logger.debug("Smelter re-embedded resource", {
|
|
10850
|
+
resourceId: String(rid),
|
|
10851
|
+
chunks: embeddingChunks.length
|
|
10852
|
+
});
|
|
10853
|
+
}
|
|
10854
|
+
async handleResourceUpdated(event) {
|
|
10855
|
+
await this.reembedResource(makeResourceId2(event.resourceId));
|
|
10856
|
+
}
|
|
10857
|
+
async handleRepresentationAdded(event) {
|
|
10858
|
+
await this.reembedResource(makeResourceId2(event.resourceId));
|
|
10859
|
+
}
|
|
10769
10860
|
async handleResourceArchived(event) {
|
|
10770
10861
|
const rid = makeResourceId2(event.resourceId);
|
|
10771
10862
|
await this.vectorStore.deleteResourceVectors(rid);
|
|
10772
|
-
this.
|
|
10773
|
-
this.logger.debug("Smelter deleted resource vectors", {
|
|
10774
|
-
resourceId: String(rid)
|
|
10775
|
-
});
|
|
10863
|
+
await this.embeddingStore.deleteResourceEmbeddings(rid);
|
|
10864
|
+
this.logger.debug("Smelter deleted resource vectors", { resourceId: String(rid) });
|
|
10776
10865
|
}
|
|
10777
10866
|
async handleAnnotationAdded(event) {
|
|
10778
10867
|
await new Promise((resolve2) => setTimeout(resolve2, 0));
|
|
@@ -10790,20 +10879,25 @@ var Smelter = class _Smelter {
|
|
|
10790
10879
|
heapMB: Math.round(process.memoryUsage().heapUsed / 1024 / 1024)
|
|
10791
10880
|
});
|
|
10792
10881
|
const embedding = await this.embeddingProvider.embed(exactText);
|
|
10793
|
-
this.
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
|
|
10882
|
+
const model = this.embeddingProvider.model();
|
|
10883
|
+
const dimensions = this.embeddingProvider.dimensions();
|
|
10884
|
+
const motivation = annotation.motivation ?? "";
|
|
10885
|
+
const entityTypes = annotation.entityTypes ?? [];
|
|
10886
|
+
await this.embeddingStore.writeAnnotationEmbedding(
|
|
10887
|
+
aid,
|
|
10888
|
+
rid,
|
|
10889
|
+
model,
|
|
10890
|
+
dimensions,
|
|
10891
|
+
exactText,
|
|
10798
10892
|
embedding,
|
|
10799
|
-
|
|
10800
|
-
|
|
10801
|
-
|
|
10893
|
+
motivation,
|
|
10894
|
+
entityTypes
|
|
10895
|
+
);
|
|
10802
10896
|
const payload = {
|
|
10803
10897
|
annotationId: aid,
|
|
10804
10898
|
resourceId: rid,
|
|
10805
|
-
motivation
|
|
10806
|
-
entityTypes
|
|
10899
|
+
motivation,
|
|
10900
|
+
entityTypes,
|
|
10807
10901
|
exactText
|
|
10808
10902
|
};
|
|
10809
10903
|
await this.vectorStore.upsertAnnotationVector(aid, embedding, payload);
|
|
@@ -10815,16 +10909,134 @@ var Smelter = class _Smelter {
|
|
|
10815
10909
|
async handleAnnotationRemoved(event) {
|
|
10816
10910
|
const annotationId3 = String(event.payload.annotationId);
|
|
10817
10911
|
if (!annotationId3) return;
|
|
10818
|
-
const rid = makeResourceId2(event.resourceId);
|
|
10819
10912
|
const aid = makeAnnotationId2(annotationId3);
|
|
10820
10913
|
await this.vectorStore.deleteAnnotationVector(aid);
|
|
10821
|
-
this.
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
10914
|
+
await this.embeddingStore.deleteAnnotationEmbedding(aid);
|
|
10915
|
+
this.logger.debug("Smelter deleted annotation vector", { annotationId: String(aid) });
|
|
10916
|
+
}
|
|
10917
|
+
};
|
|
10918
|
+
|
|
10919
|
+
// src/embedding-store.ts
|
|
10920
|
+
import { promises as fs } from "fs";
|
|
10921
|
+
import * as path from "path";
|
|
10922
|
+
import { getShardPath } from "@semiont/event-sourcing";
|
|
10923
|
+
var EmbeddingStore = class {
|
|
10924
|
+
constructor(project) {
|
|
10925
|
+
this.project = project;
|
|
10926
|
+
}
|
|
10927
|
+
// ── Path helpers ────────────────────────────────────────────────────────────
|
|
10928
|
+
resourceFilePath(resourceId7) {
|
|
10929
|
+
const [ab, cd] = getShardPath(String(resourceId7));
|
|
10930
|
+
return path.join(this.project.embeddingsDir, ab, cd, `${String(resourceId7)}.jsonl`);
|
|
10931
|
+
}
|
|
10932
|
+
annotationFilePath(annotationId3) {
|
|
10933
|
+
const [ab, cd] = getShardPath(String(annotationId3));
|
|
10934
|
+
return path.join(this.project.embeddingsDir, ab, cd, `${String(annotationId3)}.json`);
|
|
10935
|
+
}
|
|
10936
|
+
// ── Resource embeddings ─────────────────────────────────────────────────────
|
|
10937
|
+
async writeResourceChunks(resourceId7, model, dimensions, chunks) {
|
|
10938
|
+
const filePath = this.resourceFilePath(resourceId7);
|
|
10939
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
10940
|
+
const header = JSON.stringify({ model, dimensions });
|
|
10941
|
+
const lines = chunks.map(
|
|
10942
|
+
(c) => JSON.stringify({ chunkIndex: c.chunkIndex, text: c.text, embedding: c.embedding })
|
|
10943
|
+
);
|
|
10944
|
+
await fs.writeFile(filePath, [header, ...lines].join("\n") + "\n", "utf-8");
|
|
10945
|
+
}
|
|
10946
|
+
async readResourceEmbeddings(resourceId7) {
|
|
10947
|
+
const filePath = this.resourceFilePath(resourceId7);
|
|
10948
|
+
try {
|
|
10949
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
10950
|
+
const lines = content.trim().split("\n").filter((l) => l.trim());
|
|
10951
|
+
if (lines.length === 0) return null;
|
|
10952
|
+
const header = JSON.parse(lines[0]);
|
|
10953
|
+
const chunks = lines.slice(1).map((l) => JSON.parse(l));
|
|
10954
|
+
return { model: header.model, dimensions: header.dimensions, chunks };
|
|
10955
|
+
} catch (err) {
|
|
10956
|
+
if (err.code === "ENOENT") return null;
|
|
10957
|
+
throw err;
|
|
10958
|
+
}
|
|
10959
|
+
}
|
|
10960
|
+
async deleteResourceEmbeddings(resourceId7) {
|
|
10961
|
+
const filePath = this.resourceFilePath(resourceId7);
|
|
10962
|
+
try {
|
|
10963
|
+
await fs.unlink(filePath);
|
|
10964
|
+
} catch (err) {
|
|
10965
|
+
if (err.code !== "ENOENT") throw err;
|
|
10966
|
+
}
|
|
10967
|
+
}
|
|
10968
|
+
// ── Annotation embeddings ───────────────────────────────────────────────────
|
|
10969
|
+
async writeAnnotationEmbedding(annotationId3, resourceId7, model, dimensions, text, embedding, motivation, entityTypes) {
|
|
10970
|
+
const filePath = this.annotationFilePath(annotationId3);
|
|
10971
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
10972
|
+
const data = {
|
|
10973
|
+
model,
|
|
10974
|
+
dimensions,
|
|
10975
|
+
resourceId: String(resourceId7),
|
|
10976
|
+
text,
|
|
10977
|
+
embedding,
|
|
10978
|
+
motivation,
|
|
10979
|
+
entityTypes
|
|
10980
|
+
};
|
|
10981
|
+
await fs.writeFile(filePath, JSON.stringify(data), "utf-8");
|
|
10982
|
+
}
|
|
10983
|
+
async readAnnotationEmbedding(annotationId3) {
|
|
10984
|
+
const filePath = this.annotationFilePath(annotationId3);
|
|
10985
|
+
try {
|
|
10986
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
10987
|
+
return JSON.parse(content);
|
|
10988
|
+
} catch (err) {
|
|
10989
|
+
if (err.code === "ENOENT") return null;
|
|
10990
|
+
throw err;
|
|
10991
|
+
}
|
|
10992
|
+
}
|
|
10993
|
+
async deleteAnnotationEmbedding(annotationId3) {
|
|
10994
|
+
const filePath = this.annotationFilePath(annotationId3);
|
|
10995
|
+
try {
|
|
10996
|
+
await fs.unlink(filePath);
|
|
10997
|
+
} catch (err) {
|
|
10998
|
+
if (err.code !== "ENOENT") throw err;
|
|
10999
|
+
}
|
|
11000
|
+
}
|
|
11001
|
+
// ── Scan ────────────────────────────────────────────────────────────────────
|
|
11002
|
+
/**
|
|
11003
|
+
* Scan embeddings directory and return all resource IDs (from *.jsonl files).
|
|
11004
|
+
*/
|
|
11005
|
+
async getAllResourceIds() {
|
|
11006
|
+
return this.scanIds((name) => name.endsWith(".jsonl"), ".jsonl");
|
|
11007
|
+
}
|
|
11008
|
+
/**
|
|
11009
|
+
* Scan embeddings directory and return all annotation IDs (from *.json files).
|
|
11010
|
+
*/
|
|
11011
|
+
async getAllAnnotationIds() {
|
|
11012
|
+
return this.scanIds((name) => name.endsWith(".json"), ".json");
|
|
11013
|
+
}
|
|
11014
|
+
async scanIds(filter, ext) {
|
|
11015
|
+
const base = this.project.embeddingsDir;
|
|
11016
|
+
try {
|
|
11017
|
+
await fs.access(base);
|
|
11018
|
+
} catch {
|
|
11019
|
+
return [];
|
|
11020
|
+
}
|
|
11021
|
+
const results = [];
|
|
11022
|
+
const scan = async (dir) => {
|
|
11023
|
+
let entries;
|
|
11024
|
+
try {
|
|
11025
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
11026
|
+
} catch {
|
|
11027
|
+
return;
|
|
11028
|
+
}
|
|
11029
|
+
for (const entry of entries) {
|
|
11030
|
+
const full = path.join(dir, entry.name);
|
|
11031
|
+
if (entry.isDirectory()) {
|
|
11032
|
+
await scan(full);
|
|
11033
|
+
} else if (filter(entry.name)) {
|
|
11034
|
+
results.push(entry.name.slice(0, -ext.length));
|
|
11035
|
+
}
|
|
11036
|
+
}
|
|
11037
|
+
};
|
|
11038
|
+
await scan(base);
|
|
11039
|
+
return results;
|
|
10828
11040
|
}
|
|
10829
11041
|
};
|
|
10830
11042
|
|
|
@@ -10856,12 +11068,15 @@ async function createKnowledgeBase(eventStore, project, graphDb, eventBus, logge
|
|
|
10856
11068
|
};
|
|
10857
11069
|
if (options?.vectorStore && options?.embeddingProvider) {
|
|
10858
11070
|
kb.vectors = options.vectorStore;
|
|
11071
|
+
const embeddingStore = new EmbeddingStore(project);
|
|
10859
11072
|
kb.smelter = new Smelter(
|
|
10860
11073
|
eventStore,
|
|
10861
11074
|
eventBus,
|
|
10862
11075
|
options.vectorStore,
|
|
10863
11076
|
options.embeddingProvider,
|
|
10864
11077
|
content,
|
|
11078
|
+
embeddingStore,
|
|
11079
|
+
views,
|
|
10865
11080
|
logger.child({ component: "smelter" }),
|
|
10866
11081
|
options.chunkingConfig
|
|
10867
11082
|
);
|
|
@@ -10876,7 +11091,7 @@ async function createKnowledgeBase(eventStore, project, graphDb, eventBus, logge
|
|
|
10876
11091
|
// src/gatherer.ts
|
|
10877
11092
|
var import_rxjs3 = __toESM(require_cjs(), 1);
|
|
10878
11093
|
var import_operators3 = __toESM(require_operators(), 1);
|
|
10879
|
-
import { annotationId as makeAnnotationId3, resourceId } from "@semiont/core";
|
|
11094
|
+
import { annotationId as makeAnnotationId3, resourceId, errField as errField3 } from "@semiont/core";
|
|
10880
11095
|
|
|
10881
11096
|
// src/generation/resource-generation.ts
|
|
10882
11097
|
async function generateResourceSummary(resourceName, content, entityTypes, client) {
|
|
@@ -11664,7 +11879,7 @@ var Gatherer = class {
|
|
|
11664
11879
|
} catch (error) {
|
|
11665
11880
|
this.logger.error("Gather annotation context failed", {
|
|
11666
11881
|
annotationId: event.annotationId,
|
|
11667
|
-
error
|
|
11882
|
+
error: errField3(error)
|
|
11668
11883
|
});
|
|
11669
11884
|
resultBus.get("gather:failed").next({
|
|
11670
11885
|
correlationId: event.correlationId,
|
|
@@ -11693,7 +11908,7 @@ var Gatherer = class {
|
|
|
11693
11908
|
} catch (error) {
|
|
11694
11909
|
this.logger.error("Gather resource context failed", {
|
|
11695
11910
|
resourceId: event.resourceId,
|
|
11696
|
-
error
|
|
11911
|
+
error: errField3(error)
|
|
11697
11912
|
});
|
|
11698
11913
|
resultBus.get("gather:resource-failed").next({
|
|
11699
11914
|
correlationId: event.correlationId,
|
|
@@ -11722,7 +11937,7 @@ var Gatherer = class {
|
|
|
11722
11937
|
// src/matcher.ts
|
|
11723
11938
|
var import_rxjs4 = __toESM(require_cjs(), 1);
|
|
11724
11939
|
var import_operators4 = __toESM(require_operators(), 1);
|
|
11725
|
-
import { resourceId as resourceId2 } from "@semiont/core";
|
|
11940
|
+
import { resourceId as resourceId2, errField as errField4 } from "@semiont/core";
|
|
11726
11941
|
import { getResourceId as getResourceId4, getResourceEntityTypes as getResourceEntityTypes4 } from "@semiont/api-client";
|
|
11727
11942
|
var Matcher = class {
|
|
11728
11943
|
constructor(kb, eventBus, logger, inferenceClient, embeddingProvider) {
|
|
@@ -11771,7 +11986,7 @@ var Matcher = class {
|
|
|
11771
11986
|
} catch (error) {
|
|
11772
11987
|
this.logger.error("Bind search failed", {
|
|
11773
11988
|
referenceId: event.referenceId,
|
|
11774
|
-
error
|
|
11989
|
+
error: errField4(error)
|
|
11775
11990
|
});
|
|
11776
11991
|
this.eventBus.scope(event.resourceId).get("match:search-failed").next({
|
|
11777
11992
|
correlationId: event.correlationId,
|
|
@@ -12041,7 +12256,7 @@ For each candidate, output a line with the number and score, like:
|
|
|
12041
12256
|
// src/stower.ts
|
|
12042
12257
|
var import_rxjs5 = __toESM(require_cjs(), 1);
|
|
12043
12258
|
var import_operators5 = __toESM(require_operators(), 1);
|
|
12044
|
-
import { promises as
|
|
12259
|
+
import { promises as fs2 } from "fs";
|
|
12045
12260
|
import { resourceId as resourceId3, userId as makeUserId, annotationId as makeAnnotationId4, CREATION_METHODS, generateUuid } from "@semiont/core";
|
|
12046
12261
|
import { resolveStorageUri } from "@semiont/event-sourcing";
|
|
12047
12262
|
var Stower = class {
|
|
@@ -12069,9 +12284,7 @@ var Stower = class {
|
|
|
12069
12284
|
pipe("job:start", (e) => this.handleJobStart(e)),
|
|
12070
12285
|
pipe("job:report-progress", (e) => this.handleJobReportProgress(e)),
|
|
12071
12286
|
pipe("job:complete", (e) => this.handleJobComplete(e)),
|
|
12072
|
-
pipe("job:fail", (e) => this.handleJobFail(e))
|
|
12073
|
-
pipe("embedding:compute", (e) => this.handleEmbeddingComputed(e)),
|
|
12074
|
-
pipe("embedding:delete", (e) => this.handleEmbeddingDeleted(e))
|
|
12287
|
+
pipe("job:fail", (e) => this.handleJobFail(e))
|
|
12075
12288
|
).subscribe({
|
|
12076
12289
|
error: (err) => this.logger.error("Stower pipeline error", { error: err })
|
|
12077
12290
|
});
|
|
@@ -12275,7 +12488,7 @@ var Stower = class {
|
|
|
12275
12488
|
if (event.storageUri) {
|
|
12276
12489
|
const absPath = this.kb.content.resolveUri(event.storageUri);
|
|
12277
12490
|
try {
|
|
12278
|
-
await
|
|
12491
|
+
await fs2.access(absPath);
|
|
12279
12492
|
} catch {
|
|
12280
12493
|
this.logger.warn("Unarchive failed: file not found at storageUri", { storageUri: event.storageUri });
|
|
12281
12494
|
return;
|
|
@@ -12375,33 +12588,6 @@ var Stower = class {
|
|
|
12375
12588
|
}
|
|
12376
12589
|
});
|
|
12377
12590
|
}
|
|
12378
|
-
async handleEmbeddingComputed(event) {
|
|
12379
|
-
await this.kb.eventStore.appendEvent({
|
|
12380
|
-
type: "embedding:computed",
|
|
12381
|
-
resourceId: resourceId3(event.resourceId),
|
|
12382
|
-
userId: makeUserId("did:web:system:smelter"),
|
|
12383
|
-
version: 1,
|
|
12384
|
-
payload: {
|
|
12385
|
-
annotationId: event.annotationId,
|
|
12386
|
-
chunkIndex: event.chunkIndex,
|
|
12387
|
-
chunkText: event.chunkText,
|
|
12388
|
-
embedding: event.embedding,
|
|
12389
|
-
model: event.model,
|
|
12390
|
-
dimensions: event.dimensions
|
|
12391
|
-
}
|
|
12392
|
-
});
|
|
12393
|
-
}
|
|
12394
|
-
async handleEmbeddingDeleted(event) {
|
|
12395
|
-
await this.kb.eventStore.appendEvent({
|
|
12396
|
-
type: "embedding:deleted",
|
|
12397
|
-
resourceId: resourceId3(event.resourceId),
|
|
12398
|
-
userId: makeUserId("did:web:system:smelter"),
|
|
12399
|
-
version: 1,
|
|
12400
|
-
payload: {
|
|
12401
|
-
annotationId: event.annotationId
|
|
12402
|
-
}
|
|
12403
|
-
});
|
|
12404
|
-
}
|
|
12405
12591
|
async stop() {
|
|
12406
12592
|
this.subscription?.unsubscribe();
|
|
12407
12593
|
this.subscription = null;
|
|
@@ -12412,25 +12598,25 @@ var Stower = class {
|
|
|
12412
12598
|
// src/browser.ts
|
|
12413
12599
|
var import_rxjs6 = __toESM(require_cjs(), 1);
|
|
12414
12600
|
var import_operators6 = __toESM(require_operators(), 1);
|
|
12415
|
-
import { promises as
|
|
12416
|
-
import * as
|
|
12417
|
-
import { resourceId as resourceId4, annotationId } from "@semiont/core";
|
|
12601
|
+
import { promises as fs4 } from "fs";
|
|
12602
|
+
import * as path3 from "path";
|
|
12603
|
+
import { resourceId as resourceId4, annotationId, errField as errField5 } from "@semiont/core";
|
|
12418
12604
|
import { getExactText as getExactText2, getTargetSource as getTargetSource2, getTargetSelector as getTargetSelector3, getResourceEntityTypes as getResourceEntityTypes5, getBodySource as getBodySource2 } from "@semiont/api-client";
|
|
12419
|
-
import { EventQuery as
|
|
12605
|
+
import { EventQuery as EventQuery2 } from "@semiont/event-sourcing";
|
|
12420
12606
|
import { getEntityTypes as getEntityTypes2 } from "@semiont/ontology";
|
|
12421
12607
|
|
|
12422
12608
|
// src/views/entity-types-reader.ts
|
|
12423
|
-
import { promises as
|
|
12424
|
-
import * as
|
|
12609
|
+
import { promises as fs3 } from "fs";
|
|
12610
|
+
import * as path2 from "path";
|
|
12425
12611
|
async function readEntityTypesProjection(project) {
|
|
12426
|
-
const entityTypesPath =
|
|
12612
|
+
const entityTypesPath = path2.join(
|
|
12427
12613
|
project.stateDir,
|
|
12428
12614
|
"projections",
|
|
12429
12615
|
"__system__",
|
|
12430
12616
|
"entitytypes.json"
|
|
12431
12617
|
);
|
|
12432
12618
|
try {
|
|
12433
|
-
const content = await
|
|
12619
|
+
const content = await fs3.readFile(entityTypesPath, "utf-8");
|
|
12434
12620
|
const projection = JSON.parse(content);
|
|
12435
12621
|
return projection.entityTypes || [];
|
|
12436
12622
|
} catch (error) {
|
|
@@ -12473,7 +12659,7 @@ var Browser = class {
|
|
|
12473
12659
|
// ========================================================================
|
|
12474
12660
|
async handleBrowseResource(event) {
|
|
12475
12661
|
try {
|
|
12476
|
-
const eventQuery = new
|
|
12662
|
+
const eventQuery = new EventQuery2(this.kb.eventStore.log.storage);
|
|
12477
12663
|
const events = await eventQuery.getResourceEvents(resourceId4(event.resourceId));
|
|
12478
12664
|
const stored = await this.kb.eventStore.views.materializer.materialize(events, resourceId4(event.resourceId));
|
|
12479
12665
|
if (!stored) {
|
|
@@ -12497,7 +12683,7 @@ var Browser = class {
|
|
|
12497
12683
|
}
|
|
12498
12684
|
});
|
|
12499
12685
|
} catch (error) {
|
|
12500
|
-
this.logger.error("Browse resource failed", { resourceId: event.resourceId, error });
|
|
12686
|
+
this.logger.error("Browse resource failed", { resourceId: event.resourceId, error: errField5(error) });
|
|
12501
12687
|
this.eventBus.get("browse:resource-failed").next({
|
|
12502
12688
|
correlationId: event.correlationId,
|
|
12503
12689
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -12527,7 +12713,7 @@ var Browser = class {
|
|
|
12527
12713
|
}
|
|
12528
12714
|
});
|
|
12529
12715
|
} catch (error) {
|
|
12530
|
-
this.logger.error("Browse resources failed", { error });
|
|
12716
|
+
this.logger.error("Browse resources failed", { error: errField5(error) });
|
|
12531
12717
|
this.eventBus.get("browse:resources-failed").next({
|
|
12532
12718
|
correlationId: event.correlationId,
|
|
12533
12719
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -12545,7 +12731,7 @@ var Browser = class {
|
|
|
12545
12731
|
}
|
|
12546
12732
|
});
|
|
12547
12733
|
} catch (error) {
|
|
12548
|
-
this.logger.error("Browse annotations failed", { resourceId: event.resourceId, error });
|
|
12734
|
+
this.logger.error("Browse annotations failed", { resourceId: event.resourceId, error: errField5(error) });
|
|
12549
12735
|
this.eventBus.get("browse:annotations-failed").next({
|
|
12550
12736
|
correlationId: event.correlationId,
|
|
12551
12737
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -12577,7 +12763,7 @@ var Browser = class {
|
|
|
12577
12763
|
}
|
|
12578
12764
|
});
|
|
12579
12765
|
} catch (error) {
|
|
12580
|
-
this.logger.error("Browse annotation failed", { resourceId: event.resourceId, annotationId: event.annotationId, error });
|
|
12766
|
+
this.logger.error("Browse annotation failed", { resourceId: event.resourceId, annotationId: event.annotationId, error: errField5(error) });
|
|
12581
12767
|
this.eventBus.get("browse:annotation-failed").next({
|
|
12582
12768
|
correlationId: event.correlationId,
|
|
12583
12769
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -12586,7 +12772,7 @@ var Browser = class {
|
|
|
12586
12772
|
}
|
|
12587
12773
|
async handleBrowseEvents(event) {
|
|
12588
12774
|
try {
|
|
12589
|
-
const eventQuery = new
|
|
12775
|
+
const eventQuery = new EventQuery2(this.kb.eventStore.log.storage);
|
|
12590
12776
|
const filters = {
|
|
12591
12777
|
resourceId: resourceId4(event.resourceId)
|
|
12592
12778
|
};
|
|
@@ -12609,7 +12795,7 @@ var Browser = class {
|
|
|
12609
12795
|
}
|
|
12610
12796
|
});
|
|
12611
12797
|
} catch (error) {
|
|
12612
|
-
this.logger.error("Browse events failed", { resourceId: event.resourceId, error });
|
|
12798
|
+
this.logger.error("Browse events failed", { resourceId: event.resourceId, error: errField5(error) });
|
|
12613
12799
|
this.eventBus.get("browse:events-failed").next({
|
|
12614
12800
|
correlationId: event.correlationId,
|
|
12615
12801
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -12626,7 +12812,7 @@ var Browser = class {
|
|
|
12626
12812
|
});
|
|
12627
12813
|
return;
|
|
12628
12814
|
}
|
|
12629
|
-
const eventQuery = new
|
|
12815
|
+
const eventQuery = new EventQuery2(this.kb.eventStore.log.storage);
|
|
12630
12816
|
const allEvents = await eventQuery.queryEvents({ resourceId: resourceId4(event.resourceId) });
|
|
12631
12817
|
const annotationEvents = allEvents.filter((stored) => {
|
|
12632
12818
|
const p = stored.payload;
|
|
@@ -12645,7 +12831,7 @@ var Browser = class {
|
|
|
12645
12831
|
}
|
|
12646
12832
|
});
|
|
12647
12833
|
} catch (error) {
|
|
12648
|
-
this.logger.error("Browse annotation history failed", { resourceId: event.resourceId, annotationId: event.annotationId, error });
|
|
12834
|
+
this.logger.error("Browse annotation history failed", { resourceId: event.resourceId, annotationId: event.annotationId, error: errField5(error) });
|
|
12649
12835
|
this.eventBus.get("browse:annotation-history-failed").next({
|
|
12650
12836
|
correlationId: event.correlationId,
|
|
12651
12837
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -12687,7 +12873,7 @@ var Browser = class {
|
|
|
12687
12873
|
response: { referencedBy }
|
|
12688
12874
|
});
|
|
12689
12875
|
} catch (error) {
|
|
12690
|
-
this.logger.error("Referenced-by query failed", { resourceId: event.resourceId, error });
|
|
12876
|
+
this.logger.error("Referenced-by query failed", { resourceId: event.resourceId, error: errField5(error) });
|
|
12691
12877
|
this.eventBus.get("browse:referenced-by-failed").next({
|
|
12692
12878
|
correlationId: event.correlationId,
|
|
12693
12879
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -12702,7 +12888,7 @@ var Browser = class {
|
|
|
12702
12888
|
response: { entityTypes }
|
|
12703
12889
|
});
|
|
12704
12890
|
} catch (error) {
|
|
12705
|
-
this.logger.error("Entity types read failed", { error });
|
|
12891
|
+
this.logger.error("Entity types read failed", { error: errField5(error) });
|
|
12706
12892
|
this.eventBus.get("browse:entity-types-failed").next({
|
|
12707
12893
|
correlationId: event.correlationId,
|
|
12708
12894
|
message: error instanceof Error ? error.message : String(error)
|
|
@@ -12715,8 +12901,8 @@ var Browser = class {
|
|
|
12715
12901
|
async handleBrowseDirectory(event) {
|
|
12716
12902
|
const { correlationId, path: reqPath, sort = "name" } = event;
|
|
12717
12903
|
const projectRoot = this.project.root;
|
|
12718
|
-
const resolved =
|
|
12719
|
-
if (!resolved.startsWith(projectRoot +
|
|
12904
|
+
const resolved = path3.resolve(projectRoot, reqPath);
|
|
12905
|
+
if (!resolved.startsWith(projectRoot + path3.sep) && resolved !== projectRoot) {
|
|
12720
12906
|
this.eventBus.get("browse:directory-failed").next({
|
|
12721
12907
|
correlationId,
|
|
12722
12908
|
path: reqPath,
|
|
@@ -12726,7 +12912,7 @@ var Browser = class {
|
|
|
12726
12912
|
}
|
|
12727
12913
|
let dirents;
|
|
12728
12914
|
try {
|
|
12729
|
-
dirents = await
|
|
12915
|
+
dirents = await fs4.readdir(resolved, { withFileTypes: true, encoding: "utf8" });
|
|
12730
12916
|
} catch (err) {
|
|
12731
12917
|
const msg = err.code === "ENOENT" ? "path not found" : String(err);
|
|
12732
12918
|
this.eventBus.get("browse:directory-failed").next({
|
|
@@ -12740,16 +12926,16 @@ var Browser = class {
|
|
|
12740
12926
|
const allViews = await this.views.getAll();
|
|
12741
12927
|
const prefix = `file://${resolved}`;
|
|
12742
12928
|
const viewsByUri = new Map(
|
|
12743
|
-
allViews.filter((v) => v.resource.storageUri?.startsWith(prefix + "/") || v.resource.storageUri?.startsWith(prefix +
|
|
12929
|
+
allViews.filter((v) => v.resource.storageUri?.startsWith(prefix + "/") || v.resource.storageUri?.startsWith(prefix + path3.sep)).map((v) => [v.resource.storageUri, v])
|
|
12744
12930
|
);
|
|
12745
12931
|
const entries = [];
|
|
12746
12932
|
for (const dirent of visible) {
|
|
12747
|
-
const entryPath =
|
|
12748
|
-
const relPath =
|
|
12933
|
+
const entryPath = path3.join(resolved, dirent.name);
|
|
12934
|
+
const relPath = path3.relative(projectRoot, entryPath);
|
|
12749
12935
|
if (dirent.isDirectory()) {
|
|
12750
12936
|
let mtime = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
12751
12937
|
try {
|
|
12752
|
-
const stat = await
|
|
12938
|
+
const stat = await fs4.stat(entryPath);
|
|
12753
12939
|
mtime = stat.mtime.toISOString();
|
|
12754
12940
|
} catch {
|
|
12755
12941
|
}
|
|
@@ -12759,7 +12945,7 @@ var Browser = class {
|
|
|
12759
12945
|
let size = 0;
|
|
12760
12946
|
let mtime = (/* @__PURE__ */ new Date(0)).toISOString();
|
|
12761
12947
|
try {
|
|
12762
|
-
const stat = await
|
|
12948
|
+
const stat = await fs4.stat(entryPath);
|
|
12763
12949
|
size = stat.size;
|
|
12764
12950
|
mtime = stat.mtime.toISOString();
|
|
12765
12951
|
} catch {
|
|
@@ -13430,9 +13616,7 @@ async function exportBackup(options, output) {
|
|
|
13430
13616
|
for (const [streamId, events] of streamData) {
|
|
13431
13617
|
streamSummaries.push({
|
|
13432
13618
|
stream: streamId,
|
|
13433
|
-
eventCount: events.length
|
|
13434
|
-
firstChecksum: events[0].metadata.checksum || "",
|
|
13435
|
-
lastChecksum: events[events.length - 1].metadata.checksum || ""
|
|
13619
|
+
eventCount: events.length
|
|
13436
13620
|
});
|
|
13437
13621
|
}
|
|
13438
13622
|
const manifestHeader = {
|
|
@@ -13501,26 +13685,11 @@ async function replayEventStream(jsonl, eventBus, resolveBlob, contentStore, log
|
|
|
13501
13685
|
annotationsCreated: 0,
|
|
13502
13686
|
entityTypesAdded: 0
|
|
13503
13687
|
};
|
|
13504
|
-
let hashChainValid = true;
|
|
13505
|
-
for (let i = 1; i < storedEvents.length; i++) {
|
|
13506
|
-
const prev = storedEvents[i - 1];
|
|
13507
|
-
const curr = storedEvents[i];
|
|
13508
|
-
if (curr.metadata.prevEventHash && prev.metadata.checksum) {
|
|
13509
|
-
if (curr.metadata.prevEventHash !== prev.metadata.checksum) {
|
|
13510
|
-
logger?.warn("Hash chain break", {
|
|
13511
|
-
index: i,
|
|
13512
|
-
expected: prev.metadata.checksum,
|
|
13513
|
-
got: curr.metadata.prevEventHash
|
|
13514
|
-
});
|
|
13515
|
-
hashChainValid = false;
|
|
13516
|
-
}
|
|
13517
|
-
}
|
|
13518
|
-
}
|
|
13519
13688
|
for (const stored of storedEvents) {
|
|
13520
13689
|
await replayEvent(stored, eventBus, resolveBlob, contentStore, stats, logger);
|
|
13521
13690
|
stats.eventsReplayed++;
|
|
13522
13691
|
}
|
|
13523
|
-
return { stats
|
|
13692
|
+
return { stats };
|
|
13524
13693
|
}
|
|
13525
13694
|
async function replayEvent(event, eventBus, resolveBlob, contentStore, stats, logger) {
|
|
13526
13695
|
switch (event.type) {
|
|
@@ -13749,7 +13918,6 @@ async function importBackup(archive, options) {
|
|
|
13749
13918
|
const resolveBlob = buildBlobResolver(entries);
|
|
13750
13919
|
const systemData = entries.get(".semiont/events/__system__.jsonl");
|
|
13751
13920
|
let stats = { eventsReplayed: 0, resourcesCreated: 0, annotationsCreated: 0, entityTypesAdded: 0 };
|
|
13752
|
-
let hashChainValid = true;
|
|
13753
13921
|
if (systemData) {
|
|
13754
13922
|
const result = await replayEventStream(
|
|
13755
13923
|
systemData.toString("utf8"),
|
|
@@ -13759,7 +13927,6 @@ async function importBackup(archive, options) {
|
|
|
13759
13927
|
logger
|
|
13760
13928
|
);
|
|
13761
13929
|
stats = mergeStats(stats, result.stats);
|
|
13762
|
-
if (!result.hashChainValid) hashChainValid = false;
|
|
13763
13930
|
}
|
|
13764
13931
|
for (const summary of streamSummaries) {
|
|
13765
13932
|
if (summary.stream === "__system__") continue;
|
|
@@ -13776,10 +13943,9 @@ async function importBackup(archive, options) {
|
|
|
13776
13943
|
logger
|
|
13777
13944
|
);
|
|
13778
13945
|
stats = mergeStats(stats, result.stats);
|
|
13779
|
-
if (!result.hashChainValid) hashChainValid = false;
|
|
13780
13946
|
}
|
|
13781
|
-
logger?.info("Backup import complete", { ...stats
|
|
13782
|
-
return { manifest: header, stats
|
|
13947
|
+
logger?.info("Backup import complete", { ...stats });
|
|
13948
|
+
return { manifest: header, stats };
|
|
13783
13949
|
}
|
|
13784
13950
|
function mergeStats(a, b) {
|
|
13785
13951
|
return {
|