@semiont/make-meaning 0.5.10 → 0.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,7 +13,7 @@ This package implements the actor model from [ACTOR-MODEL.md](../../docs/system/
13
13
  Five **access actors** mediate every read and write — the bus-facing interface of the Knowledge Base:
14
14
 
15
15
  - **Stower** (write) — the single write gateway to the Knowledge Base; handles all resource and annotation mutations and job lifecycle events
16
- - **Browser** (read) — handles all KB read queries: resources, annotations, events, annotation history, referenced-by lookups, entity type and tag-schema listing, and directory browse (merging filesystem listings with KB metadata)
16
+ - **Browser** (read) — handles all KB read queries: resources, annotations, events, annotation history, referenced-by lookups, entity type and tag-schema listing, the collaborator directory (the KB's declared software agents, derived from the workers/actors inference config), and directory browse (merging filesystem listings with KB metadata)
17
17
  - **Gatherer** (context assembly) — assembles gathered context for annotations (`gather:requested`) and resources (`gather:resource-requested`); searches vectors for semantically similar passages (adds `semanticContext` to `GatheredContext`)
18
18
  - **Matcher** (search/link) — context-driven candidate search with multi-source retrieval, composite structural scoring, and optional LLM semantic scoring
19
19
  - **CloneTokenManager** (yield) — manages clone token lifecycle for resource cloning
@@ -130,7 +130,7 @@ graph TB
130
130
  end
131
131
 
132
132
  BUS -->|"yield:create, yield:update, yield:mv<br/>mark:create, mark:delete, mark:update-body<br/>frame:add-entity-type, frame:add-tag-schema<br/>mark:archive, mark:unarchive, mark:update-entity-types<br/>job:start, job:complete, job:fail"| STOWER
133
- BUS -->|"browse:resource-requested, browse:resources-requested<br/>browse:annotations-requested, browse:annotation-requested<br/>browse:events-requested, browse:annotation-history-requested<br/>browse:referenced-by-requested, browse:entity-types-requested<br/>browse:tag-schemas-requested, browse:directory-requested"| BROWSER
133
+ BUS -->|"browse:resource-requested, browse:resources-requested<br/>browse:annotations-requested, browse:annotation-requested<br/>browse:events-requested, browse:annotation-history-requested<br/>browse:referenced-by-requested, browse:entity-types-requested<br/>browse:tag-schemas-requested, browse:agents-requested<br/>browse:directory-requested"| BROWSER
134
134
  BUS -->|"gather:requested<br/>gather:resource-requested"| GATHERER
135
135
  BUS -->|"match:search-requested"| MATCHER
136
136
  BUS -->|"domain events:<br/>yield:created, yield:updated<br/>yield:representation-added<br/>mark:added, mark:removed, mark:archived"| SMELTER
@@ -138,7 +138,7 @@ graph TB
138
138
  BUS -->|"yield:clone-token-requested<br/>yield:clone-resource-requested<br/>yield:clone-create"| CTM
139
139
 
140
140
  STOWER -->|"yield:create-ok, yield:update-ok, yield:move-ok<br/>mark:delete-ok, *-failed replies<br/>(domain events are republished onto the bus<br/>by the EventStore: yield:created, mark:added, ...)"| BUS
141
- BROWSER -->|"browse:resource-result, browse:resources-result<br/>browse:annotations-result, browse:annotation-result<br/>browse:events-result, browse:annotation-history-result<br/>browse:referenced-by-result, browse:entity-types-result<br/>browse:tag-schemas-result, browse:directory-result"| BUS
141
+ BROWSER -->|"browse:resource-result, browse:resources-result<br/>browse:annotations-result, browse:annotation-result<br/>browse:events-result, browse:annotation-history-result<br/>browse:referenced-by-result, browse:entity-types-result<br/>browse:tag-schemas-result, browse:agents-result<br/>browse:directory-result"| BUS
142
142
  GATHERER -->|"gather:complete, gather:failed<br/>gather:resource-complete, gather:resource-failed"| BUS
143
143
  MATCHER -->|"match:search-results, match:search-failed"| BUS
144
144
  CTM -->|"yield:clone-token-generated<br/>yield:clone-resource-result<br/>yield:clone-created"| BUS
package/dist/index.d.ts CHANGED
@@ -49,6 +49,16 @@ interface MakeMeaningConfig {
49
49
  vectors?: VectorsServiceConfig;
50
50
  embedding?: EmbeddingServiceConfig;
51
51
  };
52
+ /**
53
+ * The KB's canonical identity domain — the SAME value `/api/tokens/agent`
54
+ * mints agent DIDs from (backend `site.domain`). The agent roster consumes
55
+ * it verbatim, so directory DIDs and work-stamped `generator` DIDs are
56
+ * equal by construction; it is never derived from service topology
57
+ * (.plans/bugs/agent-did-host-skew.md).
58
+ */
59
+ site?: {
60
+ domain: string;
61
+ };
52
62
  /** Per-actor inference config */
53
63
  actors?: ActorInferenceConfig;
54
64
  /** Per-worker-type inference config */
@@ -235,9 +245,10 @@ interface CreateResourceResult {
235
245
  declare class Stower {
236
246
  private kb;
237
247
  private eventBus;
248
+ private project;
238
249
  private subscription;
239
250
  private readonly logger;
240
- constructor(kb: KnowledgeBase, eventBus: EventBus, logger: Logger);
251
+ constructor(kb: KnowledgeBase, eventBus: EventBus, project: SemiontProject, logger: Logger);
241
252
  initialize(): Promise<void>;
242
253
  private handleYieldCreate;
243
254
  private handleYieldUpdate;
@@ -374,6 +385,8 @@ declare class Matcher {
374
385
  * - browse:referenced-by-requested — find annotations in the KB graph that reference a resource
375
386
  * - browse:entity-types-requested — list entity types from the project projection
376
387
  * - browse:tag-schemas-requested — list tag schemas from the project projection
388
+ * - browse:agents-requested — the collaborator directory: the KB's declared software
389
+ * agents, derived from the workers + actors inference config (COLLABORATOR-DIRECTORY)
377
390
  * - browse:directory-requested — list a project directory, merging fs + ViewStorage
378
391
  */
379
392
 
@@ -382,9 +395,10 @@ declare class Browser {
382
395
  private kb;
383
396
  private eventBus;
384
397
  private project;
398
+ private config;
385
399
  private subscriptions;
386
400
  private readonly logger;
387
- constructor(views: ViewStorage, kb: KnowledgeBase, eventBus: EventBus, project: SemiontProject, logger: Logger);
401
+ constructor(views: ViewStorage, kb: KnowledgeBase, eventBus: EventBus, project: SemiontProject, config: MakeMeaningConfig, logger: Logger);
388
402
  initialize(): Promise<void>;
389
403
  private handleBrowseResource;
390
404
  private handleBrowseResources;
@@ -395,6 +409,7 @@ declare class Browser {
395
409
  private handleReferencedBy;
396
410
  private handleEntityTypes;
397
411
  private handleTagSchemas;
412
+ private handleBrowseAgents;
398
413
  private handleBrowseDirectory;
399
414
  stop(): Promise<void>;
400
415
  }
@@ -1023,6 +1038,8 @@ interface ReplayStats {
1023
1038
 
1024
1039
  interface BackupImporterOptions {
1025
1040
  eventBus: EventBus;
1041
+ /** Replay appends historical events directly (facts, not commands). */
1042
+ eventStore: EventStore;
1026
1043
  contentStore: WorkingTreeStore;
1027
1044
  logger?: Logger;
1028
1045
  }
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { FsJobQueue } from '@semiont/jobs';
2
2
  import { FilesystemViewStorage, resolveStorageUri, EventQuery, createEventStore } from '@semiont/event-sourcing';
3
- import { getPrimaryRepresentation, decodeRepresentation, getResourceEntityTypes, getResourceId, getTargetSource, resourceId, getBodySource, getTargetSelector, deriveViews, getTextPositionSelector, annotationId, errField, userId, generateUuid, getExactText, busRequest, cloneToken, baseMediaType, isSupportedMediaType, capabilitiesOf, didToAgent, assembleAnnotation, jobId, entityType, baseUrl, busLog, BRIDGED_CHANNELS, burstBuffer, textExtractionOf, getPrimaryMediaType, extensionForMediaType, applyBodyOperations, findBodyItem } from '@semiont/core';
3
+ import { getPrimaryRepresentation, decodeRepresentation, getResourceEntityTypes, getResourceId, getTargetSource, resourceId, getBodySource, getTargetSelector, deriveViews, getTextPositionSelector, annotationId, errField, userId, generateUuid, getExactText, busRequest, cloneToken, baseMediaType, isSupportedMediaType, capabilitiesOf, didToAgent, assembleAnnotation, jobId, entityType, baseUrl, busLog, BRIDGED_CHANNELS, burstBuffer, textExtractionOf, getPrimaryMediaType, extensionForMediaType, applyBodyOperations, findBodyItem, softwareToAgent } from '@semiont/core';
4
4
  import { withActorSpan, recordBusEmit, withSpan, SpanKind, registerJobQueueProvider, registerVectorIndexSizeProvider } from '@semiont/observability';
5
5
  import { createInferenceClient } from '@semiont/inference';
6
6
  import { getGraphDatabase } from '@semiont/graph';
@@ -9733,6 +9733,15 @@ function resolveActorInference(config, actor) {
9733
9733
  `No inference config found for actor '${actor}'. Set actors.${actor}.inference in your config.`
9734
9734
  );
9735
9735
  }
9736
+ function resolveWorkerInference(config, workerType) {
9737
+ const specific = config.workers?.[workerType];
9738
+ if (specific) return specific;
9739
+ const defaultWorker = config.workers?.default;
9740
+ if (defaultWorker) return defaultWorker;
9741
+ throw new Error(
9742
+ `No inference config found for worker '${workerType}'. Set workers.${workerType}.inference or workers.default.inference in your config.`
9743
+ );
9744
+ }
9736
9745
 
9737
9746
  // src/service.ts
9738
9747
  var import_rxjs7 = __toESM(require_cjs());
@@ -10055,7 +10064,7 @@ var GraphDBConsumer = class _GraphDBConsumer {
10055
10064
  {
10056
10065
  const rid = resourceId(event.resourceId);
10057
10066
  const doc = await graphDb.getResource(rid);
10058
- if (doc) {
10067
+ if (doc && !(doc.entityTypes || []).includes(event.payload.entityType)) {
10059
10068
  await graphDb.updateResource(rid, {
10060
10069
  entityTypes: [...doc.entityTypes || [], event.payload.entityType]
10061
10070
  });
@@ -11345,14 +11354,59 @@ For each candidate, output a line with the number and score, like:
11345
11354
  // src/stower.ts
11346
11355
  var import_rxjs4 = __toESM(require_cjs());
11347
11356
  var import_operators4 = __toESM(require_operators());
11357
+ async function readEntityTypesProjection(project) {
11358
+ const entityTypesPath = path3.join(
11359
+ project.stateDir,
11360
+ "projections",
11361
+ "__system__",
11362
+ "entitytypes.json"
11363
+ );
11364
+ try {
11365
+ const content = await promises.readFile(entityTypesPath, "utf-8");
11366
+ const projection = JSON.parse(content);
11367
+ return projection.entityTypes || [];
11368
+ } catch (error) {
11369
+ if (error.code === "ENOENT") {
11370
+ return [];
11371
+ }
11372
+ throw error;
11373
+ }
11374
+ }
11375
+
11376
+ // src/views/projection-validators.ts
11377
+ function resolveTagSchema(tagSchemas, schemaId) {
11378
+ if (typeof schemaId !== "string" || !schemaId) {
11379
+ return { error: "tag-annotation requires schemaId" };
11380
+ }
11381
+ const schema = tagSchemas.find((s) => s.id === schemaId);
11382
+ if (!schema) {
11383
+ return { error: `Tag schema not registered: ${schemaId}` };
11384
+ }
11385
+ return { schema };
11386
+ }
11387
+ function validateEntityTypes(registered, requested) {
11388
+ if (!requested || requested.length === 0) {
11389
+ return { ok: true };
11390
+ }
11391
+ const set = new Set(registered);
11392
+ const unknown = requested.filter((t) => !set.has(t));
11393
+ return unknown.length > 0 ? { ok: false, unknown } : { ok: true };
11394
+ }
11395
+ function entityTypesNotRegisteredMessage(unknown) {
11396
+ return `Entity type not registered: ${unknown.join(", ")}`;
11397
+ }
11398
+
11399
+ // src/stower.ts
11348
11400
  var Stower = class {
11349
- constructor(kb, eventBus, logger) {
11401
+ constructor(kb, eventBus, project, logger) {
11350
11402
  this.kb = kb;
11351
11403
  this.eventBus = eventBus;
11404
+ this.project = project;
11352
11405
  this.logger = logger;
11353
11406
  }
11354
11407
  kb;
11355
11408
  eventBus;
11409
+ project;
11356
11410
  subscription = null;
11357
11411
  logger;
11358
11412
  async initialize() {
@@ -11688,22 +11742,38 @@ var Stower = class {
11688
11742
  const uid = userId(event._userId);
11689
11743
  const added = event.updatedEntityTypes.filter((et) => !event.currentEntityTypes.includes(et));
11690
11744
  const removed = event.currentEntityTypes.filter((et) => !event.updatedEntityTypes.includes(et));
11691
- for (const entityType2 of added) {
11692
- await this.kb.eventStore.appendEvent({
11693
- type: "mark:entity-tag-added",
11694
- resourceId: resourceId(event.resourceId),
11695
- userId: uid,
11696
- version: 1,
11697
- payload: { entityType: entityType2 }
11698
- });
11699
- }
11700
- for (const entityType2 of removed) {
11701
- await this.kb.eventStore.appendEvent({
11702
- type: "mark:entity-tag-removed",
11703
- resourceId: resourceId(event.resourceId),
11704
- userId: uid,
11705
- version: 1,
11706
- payload: { entityType: entityType2 }
11745
+ try {
11746
+ if (added.length > 0) {
11747
+ const registered = await readEntityTypesProjection(this.project);
11748
+ const result = validateEntityTypes(registered, added);
11749
+ if (!result.ok) {
11750
+ throw new Error(entityTypesNotRegisteredMessage(result.unknown));
11751
+ }
11752
+ }
11753
+ for (const entityType2 of added) {
11754
+ await this.kb.eventStore.appendEvent({
11755
+ type: "mark:entity-tag-added",
11756
+ resourceId: resourceId(event.resourceId),
11757
+ userId: uid,
11758
+ version: 1,
11759
+ payload: { entityType: entityType2 }
11760
+ });
11761
+ }
11762
+ for (const entityType2 of removed) {
11763
+ await this.kb.eventStore.appendEvent({
11764
+ type: "mark:entity-tag-removed",
11765
+ resourceId: resourceId(event.resourceId),
11766
+ userId: uid,
11767
+ version: 1,
11768
+ payload: { entityType: entityType2 }
11769
+ });
11770
+ }
11771
+ this.eventBus.get("mark:update-entity-types-ok").next({ correlationId: event.correlationId });
11772
+ } catch (error) {
11773
+ this.logger.error("Failed to update entity types", { error: errField(error) });
11774
+ this.eventBus.get("mark:update-entity-types-failed").next({
11775
+ correlationId: event.correlationId,
11776
+ message: error instanceof Error ? error.message : String(error)
11707
11777
  });
11708
11778
  }
11709
11779
  }
@@ -11767,24 +11837,6 @@ var Stower = class {
11767
11837
  // src/browser.ts
11768
11838
  var import_rxjs5 = __toESM(require_cjs());
11769
11839
  var import_operators5 = __toESM(require_operators());
11770
- async function readEntityTypesProjection(project) {
11771
- const entityTypesPath = path3.join(
11772
- project.stateDir,
11773
- "projections",
11774
- "__system__",
11775
- "entitytypes.json"
11776
- );
11777
- try {
11778
- const content = await promises.readFile(entityTypesPath, "utf-8");
11779
- const projection = JSON.parse(content);
11780
- return projection.entityTypes || [];
11781
- } catch (error) {
11782
- if (error.code === "ENOENT") {
11783
- return [];
11784
- }
11785
- throw error;
11786
- }
11787
- }
11788
11840
  async function readTagSchemasProjection(project) {
11789
11841
  const tagSchemasPath = path3.join(
11790
11842
  project.stateDir,
@@ -11815,20 +11867,66 @@ async function assembleResourceGraph(kb, resourceId10) {
11815
11867
  });
11816
11868
  return { resource: stored.resource, annotations, entityReferences };
11817
11869
  }
11870
+ var JOB_TYPES = [
11871
+ "reference-annotation",
11872
+ "highlight-annotation",
11873
+ "assessment-annotation",
11874
+ "comment-annotation",
11875
+ "tag-annotation",
11876
+ "generation"
11877
+ ];
11878
+ function deriveAgentRoster(config) {
11879
+ const domain = config.site?.domain;
11880
+ if (!domain) {
11881
+ throw new Error(
11882
+ "site.domain is required to mint agent DIDs \u2014 the directory must use the same canonical domain /api/tokens/agent mints worker DIDs from (no topology fallback)"
11883
+ );
11884
+ }
11885
+ const roster = /* @__PURE__ */ new Map();
11886
+ const admit = (inference, jobType) => {
11887
+ const key = `${inference.type}\0${inference.model}`;
11888
+ let entry = roster.get(key);
11889
+ if (!entry) {
11890
+ entry = {
11891
+ agent: softwareToAgent({ domain, provider: inference.type, model: inference.model }),
11892
+ servesJobTypes: []
11893
+ };
11894
+ roster.set(key, entry);
11895
+ }
11896
+ if (jobType) entry.servesJobTypes.push(jobType);
11897
+ };
11898
+ for (const jobType of JOB_TYPES) {
11899
+ try {
11900
+ admit(resolveWorkerInference(config, jobType), jobType);
11901
+ } catch {
11902
+ }
11903
+ }
11904
+ for (const actor of ["gatherer", "matcher"]) {
11905
+ try {
11906
+ admit(resolveActorInference(config, actor));
11907
+ } catch {
11908
+ }
11909
+ }
11910
+ return [...roster.values()].map(
11911
+ ({ agent, servesJobTypes }) => servesJobTypes.length ? { agent, servesJobTypes } : { agent }
11912
+ );
11913
+ }
11818
11914
 
11819
11915
  // src/browser.ts
11820
11916
  var Browser = class {
11821
- constructor(views, kb, eventBus, project, logger) {
11917
+ constructor(views, kb, eventBus, project, config, logger) {
11822
11918
  this.views = views;
11823
11919
  this.kb = kb;
11824
11920
  this.eventBus = eventBus;
11825
11921
  this.project = project;
11922
+ this.config = config;
11826
11923
  this.logger = logger;
11827
11924
  }
11828
11925
  views;
11829
11926
  kb;
11830
11927
  eventBus;
11831
11928
  project;
11929
+ config;
11832
11930
  subscriptions = [];
11833
11931
  logger;
11834
11932
  async initialize() {
@@ -11861,6 +11959,7 @@ var Browser = class {
11861
11959
  pipe("browse:referenced-by-requested", (e) => this.handleReferencedBy(e)).subscribe({ error: errorHandler }),
11862
11960
  pipe("browse:entity-types-requested", (e) => this.handleEntityTypes(e)).subscribe({ error: errorHandler }),
11863
11961
  pipe("browse:tag-schemas-requested", (e) => this.handleTagSchemas(e)).subscribe({ error: errorHandler }),
11962
+ pipe("browse:agents-requested", (e) => this.handleBrowseAgents(e)).subscribe({ error: errorHandler }),
11864
11963
  pipe("browse:directory-requested", (e) => this.handleBrowseDirectory(e)).subscribe({ error: errorHandler })
11865
11964
  );
11866
11965
  }
@@ -12109,6 +12208,21 @@ var Browser = class {
12109
12208
  });
12110
12209
  }
12111
12210
  }
12211
+ async handleBrowseAgents(event) {
12212
+ try {
12213
+ const agents = deriveAgentRoster(this.config);
12214
+ this.eventBus.get("browse:agents-result").next({
12215
+ correlationId: event.correlationId,
12216
+ response: { agents }
12217
+ });
12218
+ } catch (error) {
12219
+ this.logger.error("Agent roster derivation failed", { error: errField(error) });
12220
+ this.eventBus.get("browse:agents-failed").next({
12221
+ correlationId: event.correlationId,
12222
+ message: error instanceof Error ? error.message : String(error)
12223
+ });
12224
+ }
12225
+ }
12112
12226
  // ========================================================================
12113
12227
  // Filesystem read handler
12114
12228
  // ========================================================================
@@ -12669,31 +12783,6 @@ function registerBindUpdateBodyHandler(eventBus, parentLogger) {
12669
12783
  logger.warn("Bind body-update failed after forwarding", { correlationId: cid, message });
12670
12784
  });
12671
12785
  }
12672
-
12673
- // src/views/projection-validators.ts
12674
- function resolveTagSchema(tagSchemas, schemaId) {
12675
- if (typeof schemaId !== "string" || !schemaId) {
12676
- return { error: "tag-annotation requires schemaId" };
12677
- }
12678
- const schema = tagSchemas.find((s) => s.id === schemaId);
12679
- if (!schema) {
12680
- return { error: `Tag schema not registered: ${schemaId}` };
12681
- }
12682
- return { schema };
12683
- }
12684
- function validateEntityTypes(registered, requested) {
12685
- if (!requested || requested.length === 0) {
12686
- return { ok: true };
12687
- }
12688
- const set = new Set(registered);
12689
- const unknown = requested.filter((t) => !set.has(t));
12690
- return unknown.length > 0 ? { ok: false, unknown } : { ok: true };
12691
- }
12692
- function entityTypesNotRegisteredMessage(unknown) {
12693
- return `Entity type not registered: ${unknown.join(", ")}`;
12694
- }
12695
-
12696
- // src/handlers/job-commands.ts
12697
12786
  function parseDidUser(did) {
12698
12787
  const parts = did.split(":");
12699
12788
  const usersIdx = parts.indexOf("users");
@@ -12944,7 +13033,7 @@ async function createKnowledgeSystemFromConfig(project, config, eventBus, logger
12944
13033
  if (annotation === null) return event;
12945
13034
  return { ...event, annotation };
12946
13035
  });
12947
- const stower = new Stower(kb, eventBus, logger.child({ component: "stower" }));
13036
+ const stower = new Stower(kb, eventBus, project, logger.child({ component: "stower" }));
12948
13037
  await stower.initialize();
12949
13038
  await bootstrapEntityTypes(eventBus, eventStore, logger.child({ component: "entity-types-bootstrap" }));
12950
13039
  const gatherer = new Gatherer(
@@ -12963,7 +13052,7 @@ async function createKnowledgeSystemFromConfig(project, config, eventBus, logger
12963
13052
  embeddingProvider
12964
13053
  );
12965
13054
  await matcher.initialize();
12966
- const browser = new Browser(kb.views, kb, eventBus, project, logger.child({ component: "browser" }));
13055
+ const browser = new Browser(kb.views, kb, eventBus, project, config, logger.child({ component: "browser" }));
12967
13056
  await browser.initialize();
12968
13057
  const cloneTokenManager = new CloneTokenManager(kb, eventBus, logger.child({ component: "clone-token-manager" }));
12969
13058
  await cloneTokenManager.initialize();
@@ -13875,7 +13964,7 @@ function awaitReply(eventBus, command, payload, okChannel, failedChannel, timeou
13875
13964
  return (0, import_rxjs11.firstValueFrom)(result$);
13876
13965
  }
13877
13966
  var REPLAY_TIMEOUT_MS = 3e4;
13878
- async function replayEventStream(jsonl, eventBus, resolveBlob, contentStore, logger) {
13967
+ async function replayEventStream(jsonl, eventBus, eventStore, resolveBlob, contentStore, logger) {
13879
13968
  const lines = jsonl.trim().split("\n").filter((l) => l.length > 0);
13880
13969
  const storedEvents = lines.map((line) => JSON.parse(line));
13881
13970
  const stats = {
@@ -13885,12 +13974,12 @@ async function replayEventStream(jsonl, eventBus, resolveBlob, contentStore, log
13885
13974
  entityTypesAdded: 0
13886
13975
  };
13887
13976
  for (const stored of storedEvents) {
13888
- await replayEvent(stored, eventBus, resolveBlob, contentStore, stats, logger);
13977
+ await replayEvent(stored, eventBus, eventStore, resolveBlob, contentStore, stats, logger);
13889
13978
  stats.eventsReplayed++;
13890
13979
  }
13891
13980
  return { stats };
13892
13981
  }
13893
- async function replayEvent(event, eventBus, resolveBlob, contentStore, stats, logger) {
13982
+ async function replayEvent(event, eventBus, eventStore, resolveBlob, contentStore, stats, logger) {
13894
13983
  switch (event.type) {
13895
13984
  case "frame:entity-type-added":
13896
13985
  await replayEntityTypeAdded(event, eventBus, logger);
@@ -13918,7 +14007,7 @@ async function replayEvent(event, eventBus, resolveBlob, contentStore, stats, lo
13918
14007
  break;
13919
14008
  case "mark:entity-tag-added":
13920
14009
  case "mark:entity-tag-removed":
13921
- await replayEntityTagChange(event, eventBus, logger);
14010
+ await replayEntityTagChange(event, eventStore, logger);
13922
14011
  break;
13923
14012
  // Job events are transient — skip during replay
13924
14013
  case "job:started":
@@ -14034,25 +14123,18 @@ async function replayResourceUnarchived(event, eventBus, logger) {
14034
14123
  });
14035
14124
  logger?.debug("Replayed resource.unarchived", { resourceId: event.resourceId });
14036
14125
  }
14037
- async function replayEntityTagChange(event, eventBus, logger) {
14038
- const resourceId10 = event.resourceId;
14039
- const entityType2 = event.payload.entityType;
14126
+ async function replayEntityTagChange(event, eventStore, logger) {
14127
+ const base = {
14128
+ resourceId: event.resourceId,
14129
+ userId: event.userId,
14130
+ version: event.version
14131
+ };
14040
14132
  if (event.type === "mark:entity-tag-added") {
14041
- eventBus.get("mark:update-entity-types").next({
14042
- resourceId: resourceId10,
14043
- _userId: event.userId,
14044
- currentEntityTypes: [],
14045
- updatedEntityTypes: [entityType2]
14046
- });
14133
+ await eventStore.appendEvent({ ...base, type: "mark:entity-tag-added", payload: event.payload });
14047
14134
  } else {
14048
- eventBus.get("mark:update-entity-types").next({
14049
- resourceId: resourceId10,
14050
- _userId: event.userId,
14051
- currentEntityTypes: [entityType2],
14052
- updatedEntityTypes: []
14053
- });
14135
+ await eventStore.appendEvent({ ...base, type: "mark:entity-tag-removed", payload: event.payload });
14054
14136
  }
14055
- logger?.debug("Replayed entity tag change", { type: event.type, entityType: entityType2 });
14137
+ logger?.debug("Replayed entity tag change", { type: event.type, entityType: event.payload.entityType });
14056
14138
  }
14057
14139
 
14058
14140
  // src/exchange/backup-importer.ts
@@ -14071,7 +14153,7 @@ function buildBlobResolver(entries) {
14071
14153
  };
14072
14154
  }
14073
14155
  async function importBackup(archive, options) {
14074
- const { eventBus, contentStore, logger } = options;
14156
+ const { eventBus, eventStore, contentStore, logger } = options;
14075
14157
  const entries = /* @__PURE__ */ new Map();
14076
14158
  for await (const entry of readTarGz(archive)) {
14077
14159
  entries.set(entry.name, entry.data);
@@ -14099,6 +14181,7 @@ async function importBackup(archive, options) {
14099
14181
  const result = await replayEventStream(
14100
14182
  systemData.toString("utf8"),
14101
14183
  eventBus,
14184
+ eventStore,
14102
14185
  resolveBlob,
14103
14186
  contentStore,
14104
14187
  logger
@@ -14115,6 +14198,7 @@ async function importBackup(archive, options) {
14115
14198
  const result = await replayEventStream(
14116
14199
  eventData.toString("utf8"),
14117
14200
  eventBus,
14201
+ eventStore,
14118
14202
  resolveBlob,
14119
14203
  contentStore,
14120
14204
  logger