@semiont/make-meaning 0.5.29 → 0.5.31
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 +23 -10
- package/dist/archivist-main.js +241 -150
- package/dist/archivist-main.js.map +1 -1
- package/dist/index.d.ts +26 -38
- package/dist/index.js +124 -76
- package/dist/index.js.map +1 -1
- package/dist/librarian-main.js +118 -50
- package/dist/librarian-main.js.map +1 -1
- package/dist/smelter-main.js +151 -42
- package/dist/smelter-main.js.map +1 -1
- package/dist/weaver-main.js +162 -51
- package/dist/weaver-main.js.map +1 -1
- package/package.json +13 -13
package/dist/smelter-main.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { archivistContentReads, createAnchoredTextStore,
|
|
2
|
-
import { createTomlConfigLoader, accessToken, baseUrl as baseUrl$1, retryWithBackoff, isTransientFetchError, STARTUP_FETCH_RETRY, burstBuffer, errField, resourceId,
|
|
1
|
+
import { archivistContentReads, createAnchoredTextStore, derivingExtractorFor, calculateChecksum } from '@semiont/content';
|
|
2
|
+
import { replyChannelsFor, createTomlConfigLoader, accessToken, baseUrl as baseUrl$1, retryWithBackoff, isTransientFetchError, STARTUP_FETCH_RETRY, burstBuffer, errField, resourceId, textSourceOf, decodeRepresentation, busRequest, getResourceEntityTypes, chunkText, getTargetSelector, getExactText, annotationId, getPrimaryMediaType, yieldsGeometryOf, getPrimaryRepresentation } from '@semiont/core';
|
|
3
3
|
import { registerVectorIndexSizeProvider, withActorSpan } from '@semiont/observability';
|
|
4
|
-
import
|
|
4
|
+
import '@semiont/ontology';
|
|
5
|
+
import '@semiont/graph';
|
|
5
6
|
import { createEmbeddingProvider, createVectorStore } from '@semiont/vectors';
|
|
7
|
+
import '@semiont/event-sourcing';
|
|
8
|
+
import { HttpTransport } from '@semiont/http-transport';
|
|
6
9
|
import { createServer } from 'http';
|
|
7
10
|
import { existsSync, readFileSync } from 'fs';
|
|
8
11
|
import { homedir } from 'os';
|
|
@@ -10057,8 +10060,8 @@ var Smelter = class _Smelter {
|
|
|
10057
10060
|
if (!rid) return;
|
|
10058
10061
|
const { data, contentType } = await this.content.getBinary(resourceId(rid));
|
|
10059
10062
|
const bytes = Buffer.from(data);
|
|
10060
|
-
const extractor =
|
|
10061
|
-
if (!extractor
|
|
10063
|
+
const extractor = derivingExtractorFor(contentType);
|
|
10064
|
+
if (!extractor) {
|
|
10062
10065
|
this.logger.info("Re-anchor found no geometry-capable extractor", { resourceId: rid, contentType });
|
|
10063
10066
|
return;
|
|
10064
10067
|
}
|
|
@@ -10092,41 +10095,38 @@ var Smelter = class _Smelter {
|
|
|
10092
10095
|
* null (logged) when the resource doesn't decode as text, is unavailable,
|
|
10093
10096
|
* or is empty — callers skip it.
|
|
10094
10097
|
*/
|
|
10095
|
-
async fetchEmbeddableText(
|
|
10098
|
+
async fetchEmbeddableText(resourceId6) {
|
|
10096
10099
|
try {
|
|
10097
|
-
const { data, contentType } = await this.content.getBinary(resourceId(
|
|
10100
|
+
const { data, contentType } = await this.content.getBinary(resourceId(resourceId6));
|
|
10098
10101
|
const bytes = Buffer.from(data);
|
|
10099
10102
|
const checksum = calculateChecksum(bytes);
|
|
10100
|
-
const extractor =
|
|
10101
|
-
if (!extractor) {
|
|
10102
|
-
this.logger.debug("Skipping resource with no
|
|
10103
|
+
const extractor = derivingExtractorFor(contentType);
|
|
10104
|
+
if (!extractor && textSourceOf(contentType) === "none") {
|
|
10105
|
+
this.logger.debug("Skipping resource with no way to read its media type", { resourceId: resourceId6, contentType });
|
|
10103
10106
|
return { kind: "skipped", checksum, reason: "no-extractor" };
|
|
10104
10107
|
}
|
|
10105
|
-
const extracted = await extractor.extract(bytes, contentType, {
|
|
10106
|
-
key: checksum,
|
|
10107
|
-
store: this.anchoredStore
|
|
10108
|
-
});
|
|
10108
|
+
const extracted = extractor ? await extractor.extract(bytes, contentType, { key: checksum, store: this.anchoredStore }) : { kind: "extracted", text: decodeRepresentation(bytes, contentType), method: "text-passthrough" };
|
|
10109
10109
|
if (extracted.kind === "declined") {
|
|
10110
|
-
this.logger.debug("Extractor declined", { resourceId:
|
|
10110
|
+
this.logger.debug("Extractor declined", { resourceId: resourceId6, contentType, reason: extracted.declined });
|
|
10111
10111
|
return { kind: "skipped", checksum, reason: extracted.declined };
|
|
10112
10112
|
}
|
|
10113
10113
|
if (extracted.ocrConfidence && extracted.ocrConfidence.lowConfidenceWords > 0) {
|
|
10114
10114
|
this.logger.info("OCR read words it was unsure of", {
|
|
10115
|
-
resourceId:
|
|
10115
|
+
resourceId: resourceId6,
|
|
10116
10116
|
contentType,
|
|
10117
10117
|
...extracted.ocrConfidence
|
|
10118
10118
|
});
|
|
10119
10119
|
}
|
|
10120
10120
|
if (extracted.unreadPages?.length) {
|
|
10121
10121
|
this.logger.info("Partial extraction coverage", {
|
|
10122
|
-
resourceId:
|
|
10122
|
+
resourceId: resourceId6,
|
|
10123
10123
|
contentType,
|
|
10124
10124
|
unreadPages: extracted.unreadPages
|
|
10125
10125
|
});
|
|
10126
10126
|
}
|
|
10127
10127
|
return extracted.text.trim() ? { kind: "text", text: extracted.text, checksum, machineRead: extracted.method === "ocr" } : { kind: "skipped", checksum, reason: "empty" };
|
|
10128
10128
|
} catch (error) {
|
|
10129
|
-
this.logger.warn("Content unavailable for embedding", { resourceId:
|
|
10129
|
+
this.logger.warn("Content unavailable for embedding", { resourceId: resourceId6, error: errField(error) });
|
|
10130
10130
|
return { kind: "unavailable" };
|
|
10131
10131
|
}
|
|
10132
10132
|
}
|
|
@@ -10136,11 +10136,11 @@ var Smelter = class _Smelter {
|
|
|
10136
10136
|
* fold. Best-effort — waiters degrade to their bounded timeout; a signal
|
|
10137
10137
|
* failure must never fail the embed.
|
|
10138
10138
|
*/
|
|
10139
|
-
async emitSettled(
|
|
10139
|
+
async emitSettled(resourceId6, contentChecksum, outcome, reason) {
|
|
10140
10140
|
try {
|
|
10141
|
-
await this.bus.emit("smelt:settled", { resourceId, contentChecksum, outcome, ...reason ? { reason } : {} });
|
|
10141
|
+
await this.bus.emit("smelt:settled", { resourceId: resourceId6, contentChecksum, outcome, ...reason ? { reason } : {} });
|
|
10142
10142
|
} catch (error) {
|
|
10143
|
-
this.logger.warn("Failed to emit smelt:settled", { resourceId, outcome, error: errField(error) });
|
|
10143
|
+
this.logger.warn("Failed to emit smelt:settled", { resourceId: resourceId6, outcome, error: errField(error) });
|
|
10144
10144
|
}
|
|
10145
10145
|
}
|
|
10146
10146
|
/**
|
|
@@ -10152,11 +10152,11 @@ var Smelter = class _Smelter {
|
|
|
10152
10152
|
* propagates to the pipeline's per-resource error handler (reconcile heals),
|
|
10153
10153
|
* rather than silently stamping `[]` and letting the resource leak into recall.
|
|
10154
10154
|
*/
|
|
10155
|
-
async resolveEntityTypes(
|
|
10155
|
+
async resolveEntityTypes(resourceId6) {
|
|
10156
10156
|
const { resource } = await busRequest(
|
|
10157
10157
|
this.bus,
|
|
10158
10158
|
"browse:resource-requested",
|
|
10159
|
-
{ resourceId }
|
|
10159
|
+
{ resourceId: resourceId6 }
|
|
10160
10160
|
);
|
|
10161
10161
|
return getResourceEntityTypes(resource);
|
|
10162
10162
|
}
|
|
@@ -10240,11 +10240,11 @@ var Smelter = class _Smelter {
|
|
|
10240
10240
|
this.logger.info("Indexed annotation", { annotationId: String(aid) });
|
|
10241
10241
|
}
|
|
10242
10242
|
async handleAnnotationRemoved(event) {
|
|
10243
|
-
const
|
|
10244
|
-
if (!
|
|
10245
|
-
const aid = annotationId(
|
|
10243
|
+
const annotationId3 = event.payload.annotationId;
|
|
10244
|
+
if (!annotationId3) return;
|
|
10245
|
+
const aid = annotationId(annotationId3);
|
|
10246
10246
|
await this.vectorStore.deleteAnnotationVector(aid);
|
|
10247
|
-
this.logger.info("Deleted annotation vector", { annotationId:
|
|
10247
|
+
this.logger.info("Deleted annotation vector", { annotationId: annotationId3 });
|
|
10248
10248
|
}
|
|
10249
10249
|
/**
|
|
10250
10250
|
* Batch-embed chunks from multiple yield:created events in a single
|
|
@@ -10483,16 +10483,16 @@ var Smelter = class _Smelter {
|
|
|
10483
10483
|
* resource (S1/S2).
|
|
10484
10484
|
*/
|
|
10485
10485
|
async rebuildAnchors(command) {
|
|
10486
|
-
const { correlationId, resourceId } = command;
|
|
10486
|
+
const { correlationId, resourceId: resourceId6 } = command;
|
|
10487
10487
|
try {
|
|
10488
10488
|
let work;
|
|
10489
|
-
if (
|
|
10490
|
-
work = [{ type: "smelt:reanchor", resourceId, payload: {} }];
|
|
10489
|
+
if (resourceId6) {
|
|
10490
|
+
work = [{ type: "smelt:reanchor", resourceId: resourceId6, payload: {} }];
|
|
10491
10491
|
} else {
|
|
10492
10492
|
const resources = await this.listAllResources();
|
|
10493
10493
|
work = [...this.classifyEmbeddable(resources)].filter(([, catalog]) => catalog.yieldsGeometry).map(([rid]) => ({ type: "smelt:reanchor", resourceId: rid, payload: {} }));
|
|
10494
10494
|
}
|
|
10495
|
-
this.logger.info("Anchored-text rebuild started", { scoped:
|
|
10495
|
+
this.logger.info("Anchored-text rebuild started", { scoped: resourceId6 ?? null, resources: work.length });
|
|
10496
10496
|
const failed = await this.drain(work);
|
|
10497
10497
|
if (failed > 0) {
|
|
10498
10498
|
await this.bus.emit("smelt:rebuild-anchors-failed", {
|
|
@@ -10502,7 +10502,7 @@ var Smelter = class _Smelter {
|
|
|
10502
10502
|
return;
|
|
10503
10503
|
}
|
|
10504
10504
|
await this.bus.emit("smelt:rebuild-anchors-ok", correlationId ? { correlationId } : {});
|
|
10505
|
-
this.logger.info("Anchored-text rebuild complete", { scoped:
|
|
10505
|
+
this.logger.info("Anchored-text rebuild complete", { scoped: resourceId6 ?? null, resources: work.length });
|
|
10506
10506
|
} catch (error) {
|
|
10507
10507
|
this.logger.error("Anchored-text rebuild failed", { error: errField(error) });
|
|
10508
10508
|
try {
|
|
@@ -10520,22 +10520,24 @@ var Smelter = class _Smelter {
|
|
|
10520
10520
|
* representation's checksum (the bytes the smelter would read), the
|
|
10521
10521
|
* current entity-type set (the discriminator the stamps must carry), and
|
|
10522
10522
|
* whether the media type's extractor derives geometry (whether an
|
|
10523
|
-
* anchored-text artifact should exist).
|
|
10524
|
-
*
|
|
10525
|
-
*
|
|
10526
|
-
*
|
|
10523
|
+
* anchored-text artifact should exist). Both answers are core's, keyed by the
|
|
10524
|
+
* media type's strategy: embeddable ⇔ the type has any text-reading strategy
|
|
10525
|
+
* at all, and geometry ⇔ that strategy derives it. Until READ-VS-EXTRACT P2
|
|
10526
|
+
* embeddability was asked as `EXTRACTORS[strategy] !== null` — true, but a
|
|
10527
|
+
* second statement of `strategy !== 'none'`, answered by resolving an
|
|
10528
|
+
* implementation to learn a fact about a media type.
|
|
10527
10529
|
* Shared by `reconcile()` and the `smelt:rebuild-anchors` planner.
|
|
10528
10530
|
*/
|
|
10529
10531
|
classifyEmbeddable(resources) {
|
|
10530
10532
|
const embeddable = /* @__PURE__ */ new Map();
|
|
10531
10533
|
for (const resource of resources) {
|
|
10532
10534
|
const mediaType = getPrimaryMediaType(resource);
|
|
10533
|
-
const
|
|
10534
|
-
if (resource["@id"] &&
|
|
10535
|
+
const readable = mediaType !== void 0 && textSourceOf(mediaType) !== "none";
|
|
10536
|
+
if (resource["@id"] && mediaType && readable) {
|
|
10535
10537
|
embeddable.set(resource["@id"], {
|
|
10536
10538
|
checksum: getPrimaryRepresentation(resource)?.checksum,
|
|
10537
10539
|
entityTypes: getResourceEntityTypes(resource),
|
|
10538
|
-
yieldsGeometry:
|
|
10540
|
+
yieldsGeometry: yieldsGeometryOf(mediaType)
|
|
10539
10541
|
});
|
|
10540
10542
|
}
|
|
10541
10543
|
}
|
|
@@ -10555,6 +10557,108 @@ var Smelter = class _Smelter {
|
|
|
10555
10557
|
}
|
|
10556
10558
|
}
|
|
10557
10559
|
};
|
|
10560
|
+
var MATCHER_CHANNELS = [
|
|
10561
|
+
"match:search-requested"
|
|
10562
|
+
];
|
|
10563
|
+
|
|
10564
|
+
// src/gatherer.ts
|
|
10565
|
+
var GATHERER_CHANNELS = [
|
|
10566
|
+
"gather:requested",
|
|
10567
|
+
"gather:resource-requested"
|
|
10568
|
+
];
|
|
10569
|
+
var STOWER_CHANNELS = [
|
|
10570
|
+
"yield:create",
|
|
10571
|
+
"yield:clone-persist",
|
|
10572
|
+
"yield:update",
|
|
10573
|
+
"yield:mv",
|
|
10574
|
+
"mark:create",
|
|
10575
|
+
"mark:commit",
|
|
10576
|
+
"mark:delete",
|
|
10577
|
+
"mark:update-body",
|
|
10578
|
+
"frame:add-entity-type",
|
|
10579
|
+
"frame:add-tag-schema",
|
|
10580
|
+
"mark:archive",
|
|
10581
|
+
"mark:unarchive",
|
|
10582
|
+
"mark:update-entity-types",
|
|
10583
|
+
"job:start",
|
|
10584
|
+
"job:complete",
|
|
10585
|
+
"job:fail"
|
|
10586
|
+
];
|
|
10587
|
+
|
|
10588
|
+
// src/browser.ts
|
|
10589
|
+
var BROWSER_CHANNELS = [
|
|
10590
|
+
"browse:resource-requested",
|
|
10591
|
+
"browse:anchored-text-requested",
|
|
10592
|
+
"browse:resources-requested",
|
|
10593
|
+
"browse:annotations-requested",
|
|
10594
|
+
"browse:annotation-requested",
|
|
10595
|
+
"browse:events-requested",
|
|
10596
|
+
"browse:annotation-history-requested",
|
|
10597
|
+
"browse:referenced-by-requested",
|
|
10598
|
+
"browse:entity-types-requested",
|
|
10599
|
+
"browse:tag-schemas-requested",
|
|
10600
|
+
"browse:agents-requested",
|
|
10601
|
+
"browse:directory-requested"
|
|
10602
|
+
];
|
|
10603
|
+
|
|
10604
|
+
// src/clone-token-manager.ts
|
|
10605
|
+
var CLONE_TOKEN_CHANNELS = [
|
|
10606
|
+
"yield:clone-token-requested",
|
|
10607
|
+
"yield:clone-resource-requested",
|
|
10608
|
+
"yield:clone-create"
|
|
10609
|
+
];
|
|
10610
|
+
|
|
10611
|
+
// src/service-channels.ts
|
|
10612
|
+
var SMELTER_AWAITED_OPERATIONS = [
|
|
10613
|
+
"browse:resource-requested",
|
|
10614
|
+
"browse:annotations-requested",
|
|
10615
|
+
"browse:resources-requested"
|
|
10616
|
+
];
|
|
10617
|
+
var SMELTER_REPLY_CHANNELS = replyChannelsFor(SMELTER_AWAITED_OPERATIONS);
|
|
10618
|
+
var WEAVER_AWAITED_OPERATIONS = [
|
|
10619
|
+
"browse:resources-requested",
|
|
10620
|
+
"browse:events-requested",
|
|
10621
|
+
"browse:annotations-requested"
|
|
10622
|
+
];
|
|
10623
|
+
replyChannelsFor(WEAVER_AWAITED_OPERATIONS);
|
|
10624
|
+
var LIBRARIAN_INBOUND_CHANNELS = [
|
|
10625
|
+
...MATCHER_CHANNELS,
|
|
10626
|
+
...GATHERER_CHANNELS,
|
|
10627
|
+
"gather:summary-requested",
|
|
10628
|
+
"weave:applied",
|
|
10629
|
+
"smelt:settled"
|
|
10630
|
+
];
|
|
10631
|
+
replyChannelsFor(LIBRARIAN_INBOUND_CHANNELS);
|
|
10632
|
+
var ARCHIVIST_INBOUND_CHANNELS = [
|
|
10633
|
+
...STOWER_CHANNELS,
|
|
10634
|
+
...BROWSER_CHANNELS,
|
|
10635
|
+
...CLONE_TOKEN_CHANNELS,
|
|
10636
|
+
"mark:create-request",
|
|
10637
|
+
"smelt:settled",
|
|
10638
|
+
// The annotation-context read moved here with the bytes (SINGLE-KB-MOUNT D5).
|
|
10639
|
+
"browse:annotation-context-requested"
|
|
10640
|
+
];
|
|
10641
|
+
var ARCHIVIST_OUTBOUND_STRAYS = [
|
|
10642
|
+
"mark:body-update-failed",
|
|
10643
|
+
// op keyed 'bind:update-body' (gateway handler re-emits mark:update-body)
|
|
10644
|
+
"yield:move-failed"
|
|
10645
|
+
// yield:mv has no registered operation; failure is direct-subscribed
|
|
10646
|
+
];
|
|
10647
|
+
[
|
|
10648
|
+
...ARCHIVIST_OUTBOUND_STRAYS,
|
|
10649
|
+
...replyChannelsFor(ARCHIVIST_INBOUND_CHANNELS)
|
|
10650
|
+
];
|
|
10651
|
+
async function runBootPass(pass, run, logger2, onState) {
|
|
10652
|
+
try {
|
|
10653
|
+
const summary = await run();
|
|
10654
|
+
onState?.({ phase: "done", summary });
|
|
10655
|
+
} catch (error) {
|
|
10656
|
+
logger2.error(`Boot pass '${pass}' failed \u2014 continuing with a store that may be behind`, {
|
|
10657
|
+
pass,
|
|
10658
|
+
error: errField(error)
|
|
10659
|
+
});
|
|
10660
|
+
}
|
|
10661
|
+
}
|
|
10558
10662
|
var configPath = join(homedir(), ".semiontconfig");
|
|
10559
10663
|
var tomlReader = {
|
|
10560
10664
|
readIfExists: (p) => existsSync(p) ? readFileSync(p, "utf-8") : null
|
|
@@ -10590,7 +10694,7 @@ var chunkingConfig = {
|
|
|
10590
10694
|
overlap: embedding.chunking?.overlap ?? 64
|
|
10591
10695
|
};
|
|
10592
10696
|
var workerSecret = process.env.SEMIONT_WORKER_SECRET ?? "";
|
|
10593
|
-
var healthPort =
|
|
10697
|
+
var healthPort = 24101;
|
|
10594
10698
|
var logger = createProcessLogger("smelter");
|
|
10595
10699
|
async function authenticate() {
|
|
10596
10700
|
if (!workerSecret) {
|
|
@@ -10661,7 +10765,12 @@ async function main() {
|
|
|
10661
10765
|
const httpTransport = new HttpTransport({
|
|
10662
10766
|
baseUrl: baseUrl$1(baseUrl),
|
|
10663
10767
|
token$: tokenSubject,
|
|
10664
|
-
tokenRefresher: refreshToken
|
|
10768
|
+
tokenRefresher: refreshToken,
|
|
10769
|
+
// Only the reply channels this process awaits — not the full bridged
|
|
10770
|
+
// set, whose global reply fan-out is the worker-OOM failure mode. See
|
|
10771
|
+
// SMELTER_AWAITED_OPERATIONS. The domain-event channels are added by
|
|
10772
|
+
// the actor state unit's start() below.
|
|
10773
|
+
channels: SMELTER_REPLY_CHANNELS
|
|
10665
10774
|
});
|
|
10666
10775
|
const actorStateUnit = createSmelterActorStateUnit({
|
|
10667
10776
|
bus: httpTransport.actor
|
|
@@ -10715,7 +10824,7 @@ async function main() {
|
|
|
10715
10824
|
};
|
|
10716
10825
|
process.on("SIGTERM", shutdown);
|
|
10717
10826
|
process.on("SIGINT", shutdown);
|
|
10718
|
-
await smelter.reconcile();
|
|
10827
|
+
await runBootPass("reconcile", () => smelter.reconcile(), logger);
|
|
10719
10828
|
}
|
|
10720
10829
|
main().catch((error) => {
|
|
10721
10830
|
logger.error("Fatal", { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : void 0 });
|