@semiont/core 0.5.21 → 0.5.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1265,32 +1265,28 @@ interface paths {
1265
1265
  path?: never;
1266
1266
  cookie?: never;
1267
1267
  };
1268
+ get?: never;
1269
+ put?: never;
1268
1270
  /**
1269
1271
  * Subscribe to the Semiont event bus (SSE)
1270
- * @description Opens a long-lived Server-Sent Events stream over which the bus delivers events matching the requested channels and scopes.
1272
+ * @description Opens a long-lived Server-Sent Events stream over which the bus delivers events matching the requested subscription matrix. The JSON body names unscoped `global` channels plus any number of `scoped` entries — one per resource scope — so a single connection can hold live subscriptions to many resources at once (MULTI-RESOURCE-SCOPE).
1271
1273
  *
1272
- * Each SSE frame has `event: bus-event`, a JSON-encoded `data` of the form `{ channel, payload, scope? }`, and an `id` (either a persisted event id, `scope:seq`, for domain events; or an ephemeral id for job-lifecycle / result channels).
1274
+ * Each SSE frame has `event: bus-event`, a JSON-encoded `data` of the form `{ channel, payload, scope? }` (scoped events carry their originating scope), and an `id` (a persisted event id `p-<scope>-<seq>` for domain events; an ephemeral `e-*` id for job-lifecycle / correlated-reply channels).
1273
1275
  *
1274
- * Pass the last-received id as `Last-Event-ID` to resume — the server replays missed persisted events and emits a `bus:resume-gap` synthetic event when the gap exceeds the replay window.
1276
+ * Resumption is per scope: pass each scope's last-received persisted id as `lastEventId` on its scoped entry — the server replays that scope's missed persisted events and emits a scoped `bus:resume-gap` synthetic event when the gap cannot be covered.
1275
1277
  */
1276
- get: {
1278
+ post: {
1277
1279
  parameters: {
1278
- query?: {
1279
- /** @description Unscoped channels to subscribe to. Repeat the parameter for multiple channels. At least one of `channel` or `scoped` is required. */
1280
- channel?: string[];
1281
- /** @description Resource-scoped channels to subscribe to (requires `scope`). Repeat for multiple. */
1282
- scoped?: string[];
1283
- /** @description Resource scope for scoped channels (typically a resourceId). */
1284
- scope?: string;
1285
- };
1286
- header?: {
1287
- /** @description Id of the last event the client received. On reconnect, the server replays persisted events after this id and emits `bus:resume-gap` if the gap exceeds the replay cap. */
1288
- "Last-Event-ID"?: string;
1289
- };
1280
+ query?: never;
1281
+ header?: never;
1290
1282
  path?: never;
1291
1283
  cookie?: never;
1292
1284
  };
1293
- requestBody?: never;
1285
+ requestBody: {
1286
+ content: {
1287
+ "application/json": components["schemas"]["BusSubscribeRequest"];
1288
+ };
1289
+ };
1294
1290
  responses: {
1295
1291
  /** @description SSE stream opened */
1296
1292
  200: {
@@ -1301,7 +1297,7 @@ interface paths {
1301
1297
  "text/event-stream": components["schemas"]["EventStreamResponse"];
1302
1298
  };
1303
1299
  };
1304
- /** @description No channels requested (at least one `channel` or `scoped` parameter required) */
1300
+ /** @description Malformed body, no channels requested, duplicate scopes, malformed scoped entry, or scope count above the per-connection cap */
1305
1301
  400: {
1306
1302
  headers: {
1307
1303
  [name: string]: unknown;
@@ -1321,8 +1317,6 @@ interface paths {
1321
1317
  };
1322
1318
  };
1323
1319
  };
1324
- put?: never;
1325
- post?: never;
1326
1320
  delete?: never;
1327
1321
  options?: never;
1328
1322
  head?: never;
@@ -2124,6 +2118,22 @@ interface components {
2124
2118
  /** @description Optional resource scope for broadcast channels (e.g. resourceId). Publishers only — frontends must never set this. */
2125
2119
  scope?: string;
2126
2120
  };
2121
+ /** @description Subscription matrix for the bus SSE stream (MULTI-RESOURCE-SCOPE). `global` channels are delivered unscoped; each `scoped` entry subscribes the connection to one resource scope's channels, optionally resuming replay from that scope's last-seen persisted event id. At least one global channel or one scoped entry is required. */
2122
+ BusSubscribeRequest: {
2123
+ /** @description Unscoped channels to subscribe to. */
2124
+ global?: string[];
2125
+ /** @description Correlation ids of busRequest replies this client still awaits (BUS-RESUMPTION Phase 2). The server replays any matching replies from its bounded retention buffer (TTL 60s) as normal frames with their deterministic `e-<channel>:<cid>` ids, so a reply that ALSO arrived live dedups client-side. At most 256 entries. */
2126
+ pendingReplies?: string[];
2127
+ /** @description Per-resource-scope subscriptions. Scopes must be unique across entries. */
2128
+ scoped?: {
2129
+ /** @description Resource scope (a resourceId). */
2130
+ scope: string;
2131
+ /** @description Channels to subscribe within this scope. */
2132
+ channels: string[];
2133
+ /** @description This scope's last-seen persisted event id (`p-<scope>-<seq>`). The server replays this scope's persisted events after it before joining the live tail, and emits a scoped `bus:resume-gap` when it cannot cover the gap (unparseable or mismatched id, retention exceeded, or query error). */
2134
+ lastEventId?: string;
2135
+ }[];
2136
+ };
2127
2137
  CloneResourceWithTokenResponse: {
2128
2138
  /** @description Generated clone token */
2129
2139
  token: string;
@@ -2243,8 +2253,8 @@ interface components {
2243
2253
  placement: "local" | "codespace";
2244
2254
  /** @description owner/name GitHub slug — present for codespace placements, where the repo is the stack's identity */
2245
2255
  repo?: string;
2246
- /** @description The KB's did:web identifier as recorded from its committed .semiont/config — the permanent identity stamped into its event log. Prefer this as a merge key: ports are reallocated across restarts; the did follows the KB. */
2247
- did?: string;
2256
+ /** @description The KB's did:web identifier, from its committed .semiont/config — "did:web:" + the [site] domain, verbatim. REQUIRED: a KB that declares no domain has no identity to publish, and the launcher refuses to start it rather than inventing or defaulting one. NOT unique within a document: a did names the knowledge base, not a running copy of it, so a local clone and a codespace of the same repo legitimately share one and both are published. host:port is the unique field (at most one entry per address), so consumers look up by ADDRESS and use the did to VERIFY that the copy they reached is the KB they meant — an address alone cannot say which KB is which, and an identity alone cannot say which copy. */
2257
+ did: string;
2248
2258
  /** @description Human-readable site name from the KB's .semiont/config, for display */
2249
2259
  siteName?: string;
2250
2260
  /** @description The agent that owns this entry's lifecycle (the launcher writes "semiont-launcher"). Consumers treat managed entries as authoritative for themselves — upsert on appearance, remove on disappearance — and never touch entries they did not write. */
@@ -3251,6 +3261,8 @@ interface components {
3251
3261
  projectName?: string;
3252
3262
  /** @description Current git branch of the knowledge base repository */
3253
3263
  gitBranch?: string;
3264
+ /** @description The knowledge base's did:web identity — 'did:web:' + the committed [site] domain, byte-identical to the string the launcher publishes in its discovery document. REQUIRED: a KB that declares no domain does not run (the launcher refuses to start it, and the backend refuses to boot), so a response without this field means the caller reached something that bypassed both. Identifies WHICH knowledge base this is; it does NOT identify which running copy — one KB reachable at two addresses (a local clone and a codespace of one repo) reports the same did at both. Use it to verify what you connected to, not to select among discovered entries. */
3265
+ did: string;
3254
3266
  };
3255
3267
  /** @description A persisted domain event with metadata. Flat shape — event fields and metadata are peers. */
3256
3268
  StoredEventResponse: {
@@ -5387,8 +5399,9 @@ interface ITransport {
5387
5399
  * SDK-internal: this is the scope primitive the SDK's resource-scoped
5388
5400
  * `browse.*` live queries drive on subscribe/teardown (freshness follows
5389
5401
  * observation; #847) — it is not part of the application-facing surface.
5390
- * Single-scope at a time; multi-scope is deferred
5391
- * (`.plans/MULTI-RESOURCE-SCOPE.md`).
5402
+ * Distinct resources COMPOSE (`.plans/MULTI-RESOURCE-SCOPE.md`): each
5403
+ * resource's subscriptions are ref-counted independently, and one client
5404
+ * may hold many resource scopes at once on its single connection.
5392
5405
  */
5393
5406
  subscribeToResource(resourceId: ResourceId): () => void;
5394
5407
  /**
@@ -5404,8 +5417,24 @@ interface ITransport {
5404
5417
  * Transport-level connection state. For HTTP, reflects the SSE
5405
5418
  * connection's health; for in-process transports, typically `'open'`
5406
5419
  * from construction onward (no connection to lose).
5420
+ *
5421
+ * Load-bearing beyond UI: `busRequest` gates its emit on this
5422
+ * (`BusRequestPrimitive.state$`, .plans/BUS-ATTACH-GATE.md) — no
5423
+ * correlated emit before the reply path exists. Implementers back it
5424
+ * with a `BehaviorSubject` so the current state arrives synchronously
5425
+ * on subscribe.
5407
5426
  */
5408
5427
  readonly state$: Observable<ConnectionState>;
5428
+ /**
5429
+ * Correlated-reply retention, client side (BUS-RESUMPTION Phase 2 /
5430
+ * SDK-DEBT S1). `busRequest` registers its correlationId here before
5431
+ * emitting and releases on settle; a wire transport includes the
5432
+ * tracked set as `pendingReplies` on each subscribe body so a reply
5433
+ * published while the connection was down replays from the server's
5434
+ * retention buffer. OPTIONAL: in-process transports that cannot lose
5435
+ * replies omit it.
5436
+ */
5437
+ trackReply?(correlationId: string): () => void;
5409
5438
  /**
5410
5439
  * Stream of transport-level errors surfaced from typed-wire methods or
5411
5440
  * other transport-mediated round-trips, just before they're thrown to
@@ -5534,6 +5563,33 @@ interface IContentTransport {
5534
5563
  dispose(): void;
5535
5564
  }
5536
5565
 
5566
+ /**
5567
+ * BUS_OPERATIONS — the request/reply operations registry (Tier 1).
5568
+ *
5569
+ * Each entry declares ONE operation as the triple that was previously three
5570
+ * loose, independently-maintained facts spread across call sites:
5571
+ * - the request channel (the key — an `EmittableChannel`),
5572
+ * - the `result` channel (success reply),
5573
+ * - the `failure` channel,
5574
+ * - and, for a streaming op, an optional `progress` channel.
5575
+ *
5576
+ * `BridgedChannel` / `BRIDGED_CHANNELS` are DERIVED from this map
5577
+ * (bridged-channels.ts): every reply lands in the bridged fan-in set by
5578
+ * construction, so "a reply channel forgotten from BRIDGED_CHANNELS" — the
5579
+ * recurring bug class (gather:resource-complete, frame:*-add-failed) — is no
5580
+ * longer representable. See .plans/BUS-OPERATIONS-REGISTRY.md.
5581
+ *
5582
+ * `Partial<Record<EmittableChannel, …>>` enforces that every key is a real
5583
+ * emittable request. `result`/`failure`/`progress` stay `EventName` rather than
5584
+ * `BridgedChannel` to avoid a circular reference (BridgedChannel derives from
5585
+ * this map); the derivation closes the loop instead.
5586
+ */
5587
+ interface BusOperationSpec {
5588
+ result: EventName;
5589
+ failure: EventName;
5590
+ /** Streaming ops only: an intermediate channel that also bridges. */
5591
+ progress?: EventName;
5592
+ }
5537
5593
  declare const BUS_OPERATIONS: {
5538
5594
  readonly 'bind:update-body': {
5539
5595
  readonly result: "bind:body-updated";
@@ -5742,6 +5798,26 @@ declare class BusRequestError extends SemiontError {
5742
5798
  interface BusRequestPrimitive {
5743
5799
  emit<K extends keyof EventMap>(channel: K, payload: EventMap[K]): Promise<void>;
5744
5800
  stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;
5801
+ /**
5802
+ * Connection state of the stream that carries replies. Required, not
5803
+ * optional (.plans/BUS-ATTACH-GATE.md D2): `busRequest` gates its emit on
5804
+ * this — no correlated emit before the reply path exists. Implementers back
5805
+ * it with a `BehaviorSubject`, so the current state arrives synchronously
5806
+ * on subscribe; a transport that cannot lose replies (in-process) reports
5807
+ * `'open'` until disposal.
5808
+ */
5809
+ state$: Observable<ConnectionState>;
5810
+ /**
5811
+ * Correlated-reply retention, client side (.plans/BUS-RESUMPTION.md
5812
+ * Phase 2 / SDK-DEBT S1). `busRequest` registers its correlationId here
5813
+ * BEFORE emitting and calls the returned disposer on every settle path;
5814
+ * a wire transport includes the currently-tracked ids as
5815
+ * `pendingReplies` in each subscribe body, so a reply published while
5816
+ * the connection was down is replayed from the server's retention
5817
+ * buffer on reconnect. OPTIONAL: an in-process transport that cannot
5818
+ * lose replies omits the surface and `busRequest` behaves as before.
5819
+ */
5820
+ trackReply?(correlationId: string): () => void;
5745
5821
  }
5746
5822
  /**
5747
5823
  * Request/reply over the bus, keyed by the operation's request channel.
@@ -6503,8 +6579,12 @@ declare function isDefined<T>(value: T | null | undefined): value is T;
6503
6579
  *
6504
6580
  * DID:WEB shapes used in Semiont:
6505
6581
  *
6506
- * Person: did:web:<host>:users:<email%40host>
6507
- * Software: did:web:<host>:agents:<provider>:<model>
6582
+ * Knowledge base: did:web:<domain>
6583
+ * Person: did:web:<domain>:users:<email%40host>
6584
+ * Software: did:web:<domain>:agents:<provider>:<model>
6585
+ *
6586
+ * `<domain>` is the KB's committed `[site] domain` — one identity, with its
6587
+ * people and software peers named beneath it.
6508
6588
  *
6509
6589
  * `didToAgent` is the inverse: parse the DID, recognize whether the
6510
6590
  * subject is a person or a software peer, and return a typed Agent.
@@ -6516,6 +6596,23 @@ declare function isDefined<T>(value: T | null | undefined): value is T;
6516
6596
  */
6517
6597
 
6518
6598
  type Agent = components['schemas']['Agent'];
6599
+ /**
6600
+ * The knowledge base's own did:web identity, from its committed
6601
+ * `[site] domain` (`SemiontProject.siteDomain()`).
6602
+ *
6603
+ * Format: `did:web:<domain>` — the domain **verbatim, never encoded**. The
6604
+ * config already stores it in did:web colon-path form
6605
+ * (`the-ai-alliance.github.io:semiont-caselaw-kb`), so encoding those colons
6606
+ * would mint a string nothing else in the system produces. The launcher
6607
+ * mints the identical string in Go (`kbconfig.go` `didWeb()`), and the two
6608
+ * MUST agree byte-for-byte: the Browser joins discovered KBs to connected
6609
+ * ones on this value, and a mismatch fails silently — looking implemented
6610
+ * while never matching (.plans/KB-IDENTITY-VS-ADDRESS.md).
6611
+ *
6612
+ * A KB has no did when it declares no domain; identity is declared, never
6613
+ * defaulted or inferred from an address.
6614
+ */
6615
+ declare function kbDid(domain: string): string;
6519
6616
  /**
6520
6617
  * Convert a user object to a DID:WEB identifier.
6521
6618
  *
@@ -7178,18 +7275,19 @@ type TomlFileReader = {
7178
7275
  * Parse ~/.semiontconfig and .semiont/config and return EnvironmentConfig.
7179
7276
  *
7180
7277
  * @param projectRoot - Path to the project root (contains .semiont/config)
7181
- * @param environment - Environment name (e.g. 'local', 'production')
7278
+ * @param environment - Environment name (e.g. 'local', 'production'); when
7279
+ * undefined, resolved from SEMIONT_ENV, then `[defaults] environment`
7182
7280
  * @param globalConfigPath - Path to ~/.semiontconfig (caller resolves ~ expansion)
7183
7281
  * @param reader - File reader abstraction
7184
7282
  * @param env - Environment variables for ${VAR} resolution
7185
7283
  */
7186
- declare function loadTomlConfig(projectRoot: string | null, environment: string, globalConfigPath: string, reader: TomlFileReader, env: Record<string, string | undefined>): EnvironmentConfig;
7284
+ declare function loadTomlConfig(projectRoot: string | null, environment: string | undefined, globalConfigPath: string, reader: TomlFileReader, env: Record<string, string | undefined>): EnvironmentConfig;
7187
7285
  /**
7188
7286
  * Create a TOML config loader backed by a file reader.
7189
7287
  * Drop-in replacement for createConfigLoader that reads TOML instead of JSON.
7190
7288
  * The caller must resolve globalConfigPath (e.g. expand '~' using process.env.HOME).
7191
7289
  */
7192
- declare function createTomlConfigLoader(reader: TomlFileReader, globalConfigPath: string, env: Record<string, string | undefined>): (projectRoot: string | null, environment: string) => EnvironmentConfig;
7290
+ declare function createTomlConfigLoader(reader: TomlFileReader, globalConfigPath: string, env: Record<string, string | undefined>): (projectRoot: string | null, environment?: string) => EnvironmentConfig;
7193
7291
 
7194
7292
  /**
7195
7293
  * Environment validation utilities
@@ -7349,5 +7447,5 @@ declare function retryWithBackoff<T>(fn: () => Promise<T>, isRetryable: (error:
7349
7447
  */
7350
7448
  declare const DISCOVERY_URL_PATH = "/discovery/kbs.json";
7351
7449
 
7352
- export { AUTHORABLE_MEDIA_TYPES, BRIDGED_CHANNELS, BusRequestError, CHANNEL_SCHEMAS, CONTEXT_FULL_WEIGHT, CONTEXT_PARTIAL_WEIGHT, ConfigurationError, ConflictError, DISCOVERY_URL_PATH, EMBEDDABLE_MEDIA_TYPES, EventBus, JWTTokenSchema, LOCALES, MEDIA_TYPES, NotFoundError, PERSISTED_EVENT_TYPES, POSITION_WEIGHT_MAX, POSITION_WINDOW, RESOURCE_BROADCAST_TYPES, STARTUP_FETCH_RETRY, ScopedEventBus, ScriptError, SemiontError, UnauthorizedError, ValidationError, accessToken, agentToDid, anchorAnnotation, annotationId, annotationUri, applyBodyOperations, assembleAnnotation, authCode, baseMediaType, baseUrl, buildContentCache, burstBuffer, busLog, busLogEnabled, busRequest, capabilitiesOf, cloneToken, createCircleSvg, createFragmentSelector, createPolygonSvg, createRectangleSvg, createTomlConfigLoader, decodeRepresentation, decodeWithCharset, deriveViews, didToAgent, email, entityType, errField, extensionForMediaType, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findBodyItem, formatLocaleDisplay, generateUuid, getAllLocaleCodes, getAllPlatformTypes, getAnnotationExactText, getAnnotationUriFromEvent, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getFragmentSelector, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPageFromFragment, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getSvgSelector, getTargetSelector, getTargetSource, getTextPositionSelector, getTextQuoteSelector, googleCredential, hasTargetSelector, isAnnotationId, isArchived, isArray, isAssessment, isBodyResolved, isBoolean, isComment, isDefined, isDraft, isEventRelatedToAnnotation, isFunction, isHighlight, isNull, isNullish, isNumber, isObject, isReference, isResolvedReference, isResourceId, isStoredEvent, isString, isStubReference, isSupportedMediaType, isTag, isTransientFetchError, isUndefined, isValidEmail, isValidPlatformType, jobId, loadTomlConfig, mcpToken, mediaTypeForExtension, normalizeCoordinates, normalizeText, parseEnvironment, parseFragmentSelector, parseSvgSelector, reconcileSelector, refreshToken, resourceAnnotationUri, resourceId, resourceUri, retryWithBackoff, scaleSvgToNative, searchQuery, serializePerKey, setBusLogTraceIdProvider, softwareToAgent, textExtractionOf, userDID, userId, userToAgent, userToDid, validateData, validateEnvironment, validateSvgMarkup, verifyPosition };
7353
- export type { AccessToken, AnchorConfidence, AnchorMethod, AnchorRect, AnchorSelectors, AnchorStrategy, AnchoringModel, Annotation, AnnotationCategory, AnnotationId, AnnotationUri, AnthropicProviderConfig, AppConfig, AssembledAnnotation, AuthCode, BackendDownload, BackendServiceConfig, BaseUrl, BodyItem, BodyItemIdentity, BodyOperation, BoundingBox, Brand, BridgedChannel, BurstBufferOptions, BusOp, BusRequestErrorCode, BusRequestPrimitive, CloneToken, CollaboratorEntry, ConnectionState, ContentCache, ContentFormat, CreateAnnotationInternal, DatabaseServiceConfig, DiscoveredKB, DiscoveryDocument, Email, EmbeddingServiceConfig, EmittableChannel, EntityType, EntityTypeStats, Environment, EnvironmentConfig, EventBase, EventInput, EventMap, EventMetadata, EventName, EventOfType, EventQuery, EventSignature, FragmentSelector, FrontendServiceConfig, GatheredContext, GoogleAuthRequest, GoogleCredential, GraphConnection, GraphDatabaseType, GraphPath, GraphServiceConfig, GraphViews, HealthCheckResponse, IBackendOperations, IContentTransport, ITransport, InferenceProvidersConfig, JobId, JobType, ListUsersResponse, LlmSelectorInput, LocaleInfo, Logger, MCPToken, MatchQuality, McpServiceConfig, MediaTypeCapabilities, Motivation, OllamaProviderConfig, PdfCoordinate, PersistedEvent, PersistedEventType, PlatformType, Point, ProgressCallback, ProgressEvent, PutBinaryOptions, PutBinaryProgress, PutBinaryRequest, ReconciledSelector, RefreshToken, RenderMode, RenderedAnchor, ResourceAnnotationUri, ResourceAnnotations, ResourceBroadcastType, ResourceDescriptor, ResourceFilter, ResourceId, ResourceUri, RetryAttemptInfo, RetryPolicy, SearchQuery, SelectionData, Selector, SemiontConfig, ServicePlatformConfig, ServicesConfig, SiteConfig, StateUnit, StatusResponse, StoredEvent, StoredEventLike, SupportedMediaType, SvgSelector, TagCategory, TagSchema, TextExtraction, TextPosition, TextPositionSelector, TextQuoteSelector, ActorInferenceConfig as TomlActorInferenceConfig, TomlFileReader, InferenceConfig as TomlInferenceConfig, WorkerInferenceConfig as TomlWorkerInferenceConfig, TransportErrorCode, UpdateResourceInput, UpdateUserRequest, UpdateUserResponse, UserDID, UserId, UserResponse, ValidationFailure, ValidationResult, ValidationSuccess, VectorsServiceConfig, components, operations, paths };
7450
+ export { AUTHORABLE_MEDIA_TYPES, BRIDGED_CHANNELS, BUS_OPERATIONS, BusRequestError, CHANNEL_SCHEMAS, CONTEXT_FULL_WEIGHT, CONTEXT_PARTIAL_WEIGHT, ConfigurationError, ConflictError, DISCOVERY_URL_PATH, EMBEDDABLE_MEDIA_TYPES, EventBus, JWTTokenSchema, LOCALES, MEDIA_TYPES, NotFoundError, PERSISTED_EVENT_TYPES, POSITION_WEIGHT_MAX, POSITION_WINDOW, RESOURCE_BROADCAST_TYPES, STARTUP_FETCH_RETRY, ScopedEventBus, ScriptError, SemiontError, UnauthorizedError, ValidationError, accessToken, agentToDid, anchorAnnotation, annotationId, annotationUri, applyBodyOperations, assembleAnnotation, authCode, baseMediaType, baseUrl, buildContentCache, burstBuffer, busLog, busLogEnabled, busRequest, capabilitiesOf, cloneToken, createCircleSvg, createFragmentSelector, createPolygonSvg, createRectangleSvg, createTomlConfigLoader, decodeRepresentation, decodeWithCharset, deriveViews, didToAgent, email, entityType, errField, extensionForMediaType, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findBodyItem, formatLocaleDisplay, generateUuid, getAllLocaleCodes, getAllPlatformTypes, getAnnotationExactText, getAnnotationUriFromEvent, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getFragmentSelector, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPageFromFragment, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getSvgSelector, getTargetSelector, getTargetSource, getTextPositionSelector, getTextQuoteSelector, googleCredential, hasTargetSelector, isAnnotationId, isArchived, isArray, isAssessment, isBodyResolved, isBoolean, isComment, isDefined, isDraft, isEventRelatedToAnnotation, isFunction, isHighlight, isNull, isNullish, isNumber, isObject, isReference, isResolvedReference, isResourceId, isStoredEvent, isString, isStubReference, isSupportedMediaType, isTag, isTransientFetchError, isUndefined, isValidEmail, isValidPlatformType, jobId, kbDid, loadTomlConfig, mcpToken, mediaTypeForExtension, normalizeCoordinates, normalizeText, parseEnvironment, parseFragmentSelector, parseSvgSelector, reconcileSelector, refreshToken, resourceAnnotationUri, resourceId, resourceUri, retryWithBackoff, scaleSvgToNative, searchQuery, serializePerKey, setBusLogTraceIdProvider, softwareToAgent, textExtractionOf, userDID, userId, userToAgent, userToDid, validateData, validateEnvironment, validateSvgMarkup, verifyPosition };
7451
+ export type { AccessToken, AnchorConfidence, AnchorMethod, AnchorRect, AnchorSelectors, AnchorStrategy, AnchoringModel, Annotation, AnnotationCategory, AnnotationId, AnnotationUri, AnthropicProviderConfig, AppConfig, AssembledAnnotation, AuthCode, BackendDownload, BackendServiceConfig, BaseUrl, BodyItem, BodyItemIdentity, BodyOperation, BoundingBox, Brand, BridgedChannel, BurstBufferOptions, BusOp, BusOperationKey, BusOperationSpec, BusRequestErrorCode, BusRequestPrimitive, CloneToken, CollaboratorEntry, ConnectionState, ContentCache, ContentFormat, CreateAnnotationInternal, DatabaseServiceConfig, DiscoveredKB, DiscoveryDocument, Email, EmbeddingServiceConfig, EmittableChannel, EntityType, EntityTypeStats, Environment, EnvironmentConfig, EventBase, EventInput, EventMap, EventMetadata, EventName, EventOfType, EventQuery, EventSignature, FragmentSelector, FrontendServiceConfig, GatheredContext, GoogleAuthRequest, GoogleCredential, GraphConnection, GraphDatabaseType, GraphPath, GraphServiceConfig, GraphViews, HealthCheckResponse, IBackendOperations, IContentTransport, ITransport, InferenceProvidersConfig, JobId, JobType, ListUsersResponse, LlmSelectorInput, LocaleInfo, Logger, MCPToken, MatchQuality, McpServiceConfig, MediaTypeCapabilities, Motivation, OllamaProviderConfig, PdfCoordinate, PersistedEvent, PersistedEventType, PlatformType, Point, ProgressCallback, ProgressEvent, PutBinaryOptions, PutBinaryProgress, PutBinaryRequest, ReconciledSelector, RefreshToken, RenderMode, RenderedAnchor, ResourceAnnotationUri, ResourceAnnotations, ResourceBroadcastType, ResourceDescriptor, ResourceFilter, ResourceId, ResourceUri, RetryAttemptInfo, RetryPolicy, SearchQuery, SelectionData, Selector, SemiontConfig, ServicePlatformConfig, ServicesConfig, SiteConfig, StateUnit, StatusResponse, StoredEvent, StoredEventLike, SupportedMediaType, SvgSelector, TagCategory, TagSchema, TextExtraction, TextPosition, TextPositionSelector, TextQuoteSelector, ActorInferenceConfig as TomlActorInferenceConfig, TomlFileReader, InferenceConfig as TomlInferenceConfig, WorkerInferenceConfig as TomlWorkerInferenceConfig, TransportErrorCode, UpdateResourceInput, UpdateUserRequest, UpdateUserResponse, UserDID, UserId, UserResponse, ValidationFailure, ValidationResult, ValidationSuccess, VectorsServiceConfig, components, operations, paths };
package/dist/index.js CHANGED
@@ -1223,18 +1223,69 @@ async function busRequest(bus, operation, payload, timeoutMs = 3e4) {
1223
1223
  })
1224
1224
  );
1225
1225
  const resultPromise = firstValueFrom(result$);
1226
- try {
1227
- await bus.emit(operation, fullPayload);
1228
- } catch (emitError) {
1226
+ const closedBeforeEmit = () => {
1229
1227
  resultPromise.catch(() => {
1230
1228
  });
1231
- throw emitError;
1229
+ return new BusRequestError(`Bus closed before emit on ${operation}`, "bus.closed", {
1230
+ channel: operation,
1231
+ correlationId
1232
+ });
1233
+ };
1234
+ let currentState;
1235
+ bus.state$.subscribe((s) => {
1236
+ currentState = s;
1237
+ }).unsubscribe();
1238
+ if (currentState === "closed") {
1239
+ throw closedBeforeEmit();
1240
+ }
1241
+ let emitAllowed = currentState === "open";
1242
+ if (!emitAllowed) {
1243
+ const gate = firstValueFrom(
1244
+ bus.state$.pipe(
1245
+ filter((s) => s === "open" || s === "closed"),
1246
+ take(1),
1247
+ // `state$` completed without ever attaching: treat as closed.
1248
+ defaultIfEmpty("closed")
1249
+ )
1250
+ );
1251
+ const outcome = await Promise.race([
1252
+ gate,
1253
+ // Either settlement of the reply machinery means "stop waiting, never
1254
+ // emit": its timeout rejecting `bus.timeout` at `timeoutMs` (the same
1255
+ // moment it would fire today — D4), or its streams completing into the
1256
+ // `bus.closed` default above. The shared tail below carries it.
1257
+ resultPromise.then(
1258
+ () => "settled",
1259
+ () => "settled"
1260
+ )
1261
+ ]);
1262
+ if (outcome === "closed") {
1263
+ throw closedBeforeEmit();
1264
+ }
1265
+ emitAllowed = outcome === "open";
1232
1266
  }
1233
- const result = await resultPromise;
1234
- if (!result.ok) {
1235
- throw result.error;
1267
+ let releaseTracking;
1268
+ if (emitAllowed) {
1269
+ releaseTracking = bus.trackReply?.(correlationId);
1270
+ try {
1271
+ await bus.emit(operation, fullPayload);
1272
+ } catch (emitError) {
1273
+ releaseTracking?.();
1274
+ releaseTracking = void 0;
1275
+ resultPromise.catch(() => {
1276
+ });
1277
+ throw emitError;
1278
+ }
1279
+ }
1280
+ try {
1281
+ const result = await resultPromise;
1282
+ if (!result.ok) {
1283
+ throw result.error;
1284
+ }
1285
+ return result.response;
1286
+ } finally {
1287
+ releaseTracking?.();
1236
1288
  }
1237
- return result.response;
1238
1289
  }
1239
1290
 
1240
1291
  // src/fuzzy-anchor.ts
@@ -2002,6 +2053,9 @@ function isDefined(value) {
2002
2053
  }
2003
2054
 
2004
2055
  // src/did-utils.ts
2056
+ function kbDid(domain) {
2057
+ return `did:web:${domain}`;
2058
+ }
2005
2059
  function userToDid(user) {
2006
2060
  return `did:web:${user.domain}:users:${encodeURIComponent(user.email)}`;
2007
2061
  }
@@ -2103,20 +2157,27 @@ function requirePlatform(value, serviceName) {
2103
2157
  }
2104
2158
  function loadTomlConfig(projectRoot, environment, globalConfigPath, reader, env) {
2105
2159
  const projectConfigContent = projectRoot ? reader.readIfExists(`${projectRoot}/.semiont/config`) : null;
2106
- let projectName = "semiont-project";
2107
- let projectVersion;
2108
- let projectSite;
2109
- let projectEnvSection = {};
2110
- if (projectConfigContent) {
2111
- const projectConfig = parse(projectConfigContent);
2112
- projectName = projectConfig.project?.name ?? projectName;
2113
- projectVersion = projectConfig.project?.version;
2114
- projectSite = projectConfig.site;
2115
- projectEnvSection = projectConfig.environments?.[environment] ?? {};
2116
- }
2160
+ const projectConfig = projectConfigContent ? parse(projectConfigContent) : void 0;
2161
+ const projectName = projectConfig?.project?.name ?? "semiont-project";
2162
+ const projectVersion = projectConfig?.project?.version;
2163
+ const projectSite = projectConfig?.site;
2117
2164
  const globalContent = reader.readIfExists(globalConfigPath);
2118
2165
  const raw = globalContent ? parse(globalContent) : {};
2119
- const userEnvSection = raw.environments?.[environment] ?? {};
2166
+ const resolvedEnvironment = environment ?? env.SEMIONT_ENV ?? raw.defaults?.environment;
2167
+ if (!resolvedEnvironment) {
2168
+ throw new Error(
2169
+ "No environment selected: pass one explicitly, set SEMIONT_ENV, or declare `[defaults] environment` in ~/.semiontconfig."
2170
+ );
2171
+ }
2172
+ const projectHasSection = projectConfig?.environments != null && resolvedEnvironment in projectConfig.environments;
2173
+ const globalHasSection = raw.environments != null && resolvedEnvironment in raw.environments;
2174
+ if (!projectHasSection && !globalHasSection) {
2175
+ throw new Error(
2176
+ `Environment "${resolvedEnvironment}" is selected but no [environments.${resolvedEnvironment}] section exists in the project (.semiont/config) or global (~/.semiontconfig) config. Declare the section, or select an environment that exists.`
2177
+ );
2178
+ }
2179
+ const projectEnvSection = projectConfig?.environments?.[resolvedEnvironment] ?? {};
2180
+ const userEnvSection = raw.environments?.[resolvedEnvironment] ?? {};
2120
2181
  const envSection = deepMerge(
2121
2182
  projectEnvSection,
2122
2183
  userEnvSection
@@ -2139,7 +2200,7 @@ function loadTomlConfig(projectRoot, environment, globalConfigPath, reader, env)
2139
2200
  } else {
2140
2201
  if (!flatInference.type) {
2141
2202
  throw new Error(
2142
- `[environments.${environment}.inference] is missing 'type'. Add type = "anthropic" or use [inference.anthropic] sub-section.`
2203
+ `[environments.${resolvedEnvironment}.inference] is missing 'type'. Add type = "anthropic" or use [inference.anthropic] sub-section.`
2143
2204
  );
2144
2205
  }
2145
2206
  providerDefaults.apiKey = flatInference.apiKey;
@@ -2152,7 +2213,7 @@ function loadTomlConfig(projectRoot, environment, globalConfigPath, reader, env)
2152
2213
  } else {
2153
2214
  if (!flatInference.type) {
2154
2215
  throw new Error(
2155
- `[environments.${environment}.inference] is missing 'type'. Add type = "ollama" or use [inference.ollama] sub-section.`
2216
+ `[environments.${resolvedEnvironment}.inference] is missing 'type'. Add type = "ollama" or use [inference.ollama] sub-section.`
2156
2217
  );
2157
2218
  }
2158
2219
  providerDefaults.baseURL = flatInference.baseURL;
@@ -2318,7 +2379,7 @@ function loadTomlConfig(projectRoot, environment, globalConfigPath, reader, env)
2318
2379
  } : void 0,
2319
2380
  logLevel: resolved.logLevel,
2320
2381
  _metadata: {
2321
- environment,
2382
+ environment: resolvedEnvironment,
2322
2383
  projectRoot,
2323
2384
  projectName,
2324
2385
  projectVersion,
@@ -2462,6 +2523,6 @@ async function retryWithBackoff(fn, isRetryable, policy, onRetry) {
2462
2523
  // src/discovery.ts
2463
2524
  var DISCOVERY_URL_PATH = "/discovery/kbs.json";
2464
2525
 
2465
- export { AUTHORABLE_MEDIA_TYPES, BRIDGED_CHANNELS, BusRequestError, CHANNEL_SCHEMAS, CONTEXT_FULL_WEIGHT, CONTEXT_PARTIAL_WEIGHT, ConfigurationError, ConflictError, DISCOVERY_URL_PATH, EMBEDDABLE_MEDIA_TYPES, EventBus, JWTTokenSchema, LOCALES, MEDIA_TYPES, NotFoundError, PERSISTED_EVENT_TYPES, POSITION_WEIGHT_MAX, POSITION_WINDOW, RESOURCE_BROADCAST_TYPES, STARTUP_FETCH_RETRY, ScopedEventBus, ScriptError, SemiontError, UnauthorizedError, ValidationError, accessToken, agentToDid, anchorAnnotation, annotationId, annotationUri, applyBodyOperations, assembleAnnotation, authCode, baseMediaType, baseUrl, buildContentCache, burstBuffer, busLog, busLogEnabled, busRequest, capabilitiesOf, cloneToken, createCircleSvg, createFragmentSelector, createPolygonSvg, createRectangleSvg, createTomlConfigLoader, decodeRepresentation, decodeWithCharset, deriveViews, didToAgent, email, entityType, errField, extensionForMediaType, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findBodyItem, formatLocaleDisplay, generateUuid, getAllLocaleCodes, getAllPlatformTypes, getAnnotationExactText, getAnnotationUriFromEvent, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getFragmentSelector, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPageFromFragment, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getSvgSelector, getTargetSelector, getTargetSource, getTextPositionSelector, getTextQuoteSelector, googleCredential, hasTargetSelector, isAnnotationId, isArchived, isArray, isAssessment, isBodyResolved, isBoolean, isComment, isDefined, isDraft, isEventRelatedToAnnotation, isFunction, isHighlight, isNull, isNullish, isNumber, isObject, isReference, isResolvedReference, isResourceId, isStoredEvent, isString, isStubReference, isSupportedMediaType, isTag, isTransientFetchError, isUndefined, isValidEmail, isValidPlatformType, jobId, loadTomlConfig, mcpToken, mediaTypeForExtension, normalizeCoordinates, normalizeText, parseEnvironment, parseFragmentSelector, parseSvgSelector, reconcileSelector, refreshToken, resourceAnnotationUri, resourceId, resourceUri, retryWithBackoff, scaleSvgToNative, searchQuery, serializePerKey, setBusLogTraceIdProvider, softwareToAgent, textExtractionOf, userDID, userId, userToAgent, userToDid, validateData, validateEnvironment, validateSvgMarkup, verifyPosition };
2526
+ export { AUTHORABLE_MEDIA_TYPES, BRIDGED_CHANNELS, BUS_OPERATIONS, BusRequestError, CHANNEL_SCHEMAS, CONTEXT_FULL_WEIGHT, CONTEXT_PARTIAL_WEIGHT, ConfigurationError, ConflictError, DISCOVERY_URL_PATH, EMBEDDABLE_MEDIA_TYPES, EventBus, JWTTokenSchema, LOCALES, MEDIA_TYPES, NotFoundError, PERSISTED_EVENT_TYPES, POSITION_WEIGHT_MAX, POSITION_WINDOW, RESOURCE_BROADCAST_TYPES, STARTUP_FETCH_RETRY, ScopedEventBus, ScriptError, SemiontError, UnauthorizedError, ValidationError, accessToken, agentToDid, anchorAnnotation, annotationId, annotationUri, applyBodyOperations, assembleAnnotation, authCode, baseMediaType, baseUrl, buildContentCache, burstBuffer, busLog, busLogEnabled, busRequest, capabilitiesOf, cloneToken, createCircleSvg, createFragmentSelector, createPolygonSvg, createRectangleSvg, createTomlConfigLoader, decodeRepresentation, decodeWithCharset, deriveViews, didToAgent, email, entityType, errField, extensionForMediaType, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findBodyItem, formatLocaleDisplay, generateUuid, getAllLocaleCodes, getAllPlatformTypes, getAnnotationExactText, getAnnotationUriFromEvent, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getFragmentSelector, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPageFromFragment, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getSvgSelector, getTargetSelector, getTargetSource, getTextPositionSelector, getTextQuoteSelector, googleCredential, hasTargetSelector, isAnnotationId, isArchived, isArray, isAssessment, isBodyResolved, isBoolean, isComment, isDefined, isDraft, isEventRelatedToAnnotation, isFunction, isHighlight, isNull, isNullish, isNumber, isObject, isReference, isResolvedReference, isResourceId, isStoredEvent, isString, isStubReference, isSupportedMediaType, isTag, isTransientFetchError, isUndefined, isValidEmail, isValidPlatformType, jobId, kbDid, loadTomlConfig, mcpToken, mediaTypeForExtension, normalizeCoordinates, normalizeText, parseEnvironment, parseFragmentSelector, parseSvgSelector, reconcileSelector, refreshToken, resourceAnnotationUri, resourceId, resourceUri, retryWithBackoff, scaleSvgToNative, searchQuery, serializePerKey, setBusLogTraceIdProvider, softwareToAgent, textExtractionOf, userDID, userId, userToAgent, userToDid, validateData, validateEnvironment, validateSvgMarkup, verifyPosition };
2466
2527
  //# sourceMappingURL=index.js.map
2467
2528
  //# sourceMappingURL=index.js.map