@semiont/api-client 0.4.21 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,15 +1,11 @@
1
- import { components, UserDID, paths, ResourceId, AnnotationId, GraphConnection, UpdateResourceInput, Motivation, BodyOperation, GatheredContext, JobId, EventBus, AccessToken, BaseUrl, Logger, EventMap, Email, RefreshToken, GoogleCredential, ContentFormat, SearchQuery, CloneToken, EntityType, Selector } from '@semiont/core';
2
- export { Logger, Selector, getFragmentSelector, getSvgSelector, getTextPositionSelector, validateSvgMarkup } from '@semiont/core';
3
- import { Observable, BehaviorSubject, Subject } from 'rxjs';
4
- export { BoundingBox, ContentCache, FragmentSelector, JWTTokenSchema, LOCALES, LocaleInfo, MatchQuality, Point, SvgSelector, TextPosition, TextPositionSelector, TextQuoteSelector, ValidatedAnnotation, ValidationFailure, ValidationResult, ValidationSuccess, buildContentCache, createCircleSvg, createPolygonSvg, createRectangleSvg, decodeRepresentation, decodeWithCharset, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findTextWithContext, formatLocaleDisplay, getAllLocaleCodes, getAnnotationExactText, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getTargetSelector, getTargetSource, getTextQuoteSelector, hasTargetSelector, isArchived, isAssessment, isBodyResolved, isComment, isDraft, isHighlight, isReference, isResolvedReference, isStubReference, isTag, isValidEmail, normalizeCoordinates, normalizeText, parseSvgSelector, scaleSvgToNative, validateAndCorrectOffsets, validateData, verifyPosition } from './utils/index.js';
1
+ import { KyInstance } from 'ky';
2
+ import { Observable, BehaviorSubject } from 'rxjs';
3
+ import { ConnectionState, ITransport, BaseUrl, AccessToken, Logger, EventMap, ResourceId, EventBus, Email, components, GoogleCredential, RefreshToken, UserResponse, ListUsersResponse, UserDID, UpdateUserRequest, UpdateUserResponse, ProgressCallback, ProgressEvent, HealthCheckResponse, StatusResponse, IContentTransport, PutBinaryRequest, ContentFormat } from '@semiont/core';
5
4
 
5
+ /** Minimal ViewModel surface — anything with a `dispose()` method. */
6
6
  interface ViewModel {
7
7
  dispose(): void;
8
8
  }
9
- declare function createDisposer(): {
10
- add(vm: ViewModel | (() => void)): void;
11
- dispose(): void;
12
- };
13
9
 
14
10
  interface BusEvent {
15
11
  channel: string;
@@ -23,23 +19,6 @@ interface ActorVMOptions {
23
19
  scope?: string;
24
20
  reconnectMs?: number;
25
21
  }
26
- /**
27
- * Connection state exposed by the SSE bus actor.
28
- *
29
- * initial ─ before start() has been called
30
- * connecting ─ fetch() in flight, no bytes yet
31
- * open ─ SSE stream live, first byte seen
32
- * reconnecting ─ open → dropped, retrying; may be transient
33
- * degraded ─ has been reconnecting for > DEGRADED_THRESHOLD_MS;
34
- * UI banner threshold; distinguishes brief mount-
35
- * churn cycles from sustained disconnection
36
- * closed ─ stop()/dispose() called; terminal
37
- *
38
- * Transition rules are enforced by a helper that throws on invalid
39
- * transitions — catches bugs in the reconnect loop that would
40
- * otherwise strand the observable in a lying value.
41
- */
42
- type ConnectionState = 'initial' | 'connecting' | 'open' | 'reconnecting' | 'degraded' | 'closed';
43
22
  /** Time in the `reconnecting` state before transitioning to `degraded`. */
44
23
  declare const DEGRADED_THRESHOLD_MS = 3000;
45
24
  interface ActorVM extends ViewModel {
@@ -54,672 +33,31 @@ interface ActorVM extends ViewModel {
54
33
  declare function createActorVM(options: ActorVMOptions): ActorVM;
55
34
 
56
35
  /**
57
- * Verb Namespace Interfaces
58
- *
59
- * These interfaces define the public API of the Semiont api-client,
60
- * organized by the 7 domain flows (Browse, Mark, Bind, Gather, Match,
61
- * Yield, Beckon) plus infrastructure namespaces (Job, Auth, Admin).
62
- *
63
- * Each namespace maps 1:1 to a flow. Each flow maps to a clear actor
64
- * on the backend. The frontend calls `client.mark.annotation()` and the
65
- * proxy handles HTTP, auth, SSE, and caching internally.
66
- *
67
- * Return type conventions:
68
- * - Browse live queries → Observable (bus gateway driven, cached)
69
- * - Browse one-shot reads → Promise (fetch once, no cache)
70
- * - Commands (mark, bind, yield.resource) → Promise (fire-and-forget)
71
- * - Long-running ops (gather, match, yield.fromAnnotation, mark.assist) → Observable (progress + result)
72
- * - Ephemeral signals (beckon) → void
73
- */
74
-
75
- type Annotation$2 = components['schemas']['Annotation'];
76
- type ResourceDescriptor$5 = components['schemas']['ResourceDescriptor'];
77
- type StoredEventResponse$2 = components['schemas']['StoredEventResponse'];
78
- type GatherProgress = components['schemas']['GatherProgress'];
79
- type MatchSearchResult = components['schemas']['MatchSearchResult'];
80
- type JobProgress$2 = components['schemas']['JobProgress'];
81
- type YieldProgress$1 = JobProgress$2;
82
- type GatherAnnotationComplete = components['schemas']['GatherAnnotationComplete'];
83
- type JobStatusResponse$1 = components['schemas']['JobStatusResponse'];
84
- type AuthResponse$1 = components['schemas']['AuthResponse'];
85
- type OAuthConfigResponse$1 = components['schemas']['OAuthConfigResponse'];
86
- type AdminUserStatsResponse$1 = components['schemas']['AdminUserStatsResponse'];
87
- type ResponseContent$1<T> = T extends {
88
- responses: {
89
- 200: {
90
- content: {
91
- 'application/json': infer R;
92
- };
93
- };
94
- };
95
- } ? R : T extends {
96
- responses: {
97
- 201: {
98
- content: {
99
- 'application/json': infer R;
100
- };
101
- };
102
- };
103
- } ? R : T extends {
104
- responses: {
105
- 202: {
106
- content: {
107
- 'application/json': infer R;
108
- };
109
- };
110
- };
111
- } ? R : never;
112
- type RequestContent$1<T> = T extends {
113
- requestBody?: {
114
- content: {
115
- 'application/json': infer R;
116
- };
117
- };
118
- } ? R : never;
119
- /** Input for creating an annotation via mark.annotation() */
120
- type CreateAnnotationInput = components['schemas']['CreateAnnotationRequest'];
121
- /** Input for creating a resource via yield.resource() */
122
- interface CreateResourceInput {
123
- name: string;
124
- file: File | Buffer;
125
- format: string;
126
- entityTypes?: string[];
127
- language?: string;
128
- creationMethod?: string;
129
- sourceAnnotationId?: string;
130
- sourceResourceId?: string;
131
- storageUri: string;
132
- /** Prompt that drove AI generation (for AI-generated resources). */
133
- generationPrompt?: string;
134
- /** Agent(s) that generated the content (for AI-generated resources). */
135
- generator?: components['schemas']['Agent'] | components['schemas']['Agent'][];
136
- isDraft?: boolean;
137
- }
138
- /** Options for yield.fromAnnotation() */
139
- interface GenerationOptions {
140
- title: string;
141
- storageUri: string;
142
- context: GatheredContext;
143
- prompt?: string;
144
- language?: string;
145
- temperature?: number;
146
- maxTokens?: number;
147
- }
148
- /** Options for mark.assist() */
149
- interface MarkAssistOptions {
150
- entityTypes?: string[];
151
- includeDescriptiveReferences?: boolean;
152
- instructions?: string;
153
- density?: number;
154
- tone?: string;
155
- language?: string;
156
- schemaId?: string;
157
- categories?: string[];
158
- }
159
- /** Options for yield.createFromToken() */
160
- type CreateFromTokenOptions = {
161
- token: string;
162
- name: string;
163
- content: string;
164
- archiveOriginal?: boolean;
165
- };
166
- /** Referenced-by entry from browse.referencedBy() */
167
- type ReferencedByEntry = components['schemas']['GetReferencedByResponse']['referencedBy'][number];
168
- /** Annotation history from browse.annotationHistory() */
169
- type AnnotationHistoryResponse = components['schemas']['GetAnnotationHistoryResponse'];
170
- /** User object from auth/admin responses */
171
- type User = AuthResponse$1['user'];
172
- /**
173
- * Progress emitted by gather.annotation() Observable.
174
- * Emits GatherProgress during assembly, then GatherAnnotationComplete on finish.
175
- */
176
- type GatherAnnotationProgress = GatherProgress | GatherAnnotationComplete;
177
- /**
178
- * Progress emitted by match.search() Observable.
179
- * Emits the final MatchSearchResult (no intermediate progress events currently).
180
- */
181
- type MatchSearchProgress = MatchSearchResult;
182
- /**
183
- * Progress emitted by mark.assist() Observable.
184
- * Each emission is a JobProgress snapshot (unified job lifecycle). The
185
- * Observable completes on `job:complete`; errors on `job:fail`.
186
- */
187
- type MarkAssistProgress = JobProgress$2;
188
- /**
189
- * Browse — reads from materialized views
190
- *
191
- * Live queries return Observables that emit initial state and re-emit
192
- * on bus gateway updates. One-shot reads return Promises.
193
- *
194
- * Backend actor: Browser (context classes)
195
- * Event prefix: browse:*
196
- */
197
- interface BrowseNamespace$1 {
198
- resource(resourceId: ResourceId): Observable<ResourceDescriptor$5 | undefined>;
199
- resources(filters?: {
200
- limit?: number;
201
- archived?: boolean;
202
- search?: string;
203
- }): Observable<ResourceDescriptor$5[] | undefined>;
204
- annotations(resourceId: ResourceId): Observable<Annotation$2[] | undefined>;
205
- annotation(resourceId: ResourceId, annotationId: AnnotationId): Observable<Annotation$2 | undefined>;
206
- entityTypes(): Observable<string[] | undefined>;
207
- referencedBy(resourceId: ResourceId): Observable<ReferencedByEntry[] | undefined>;
208
- events(resourceId: ResourceId): Observable<StoredEventResponse$2[] | undefined>;
209
- resourceContent(resourceId: ResourceId): Promise<string>;
210
- resourceRepresentation(resourceId: ResourceId, options?: {
211
- accept?: string;
212
- }): Promise<{
213
- data: ArrayBuffer;
214
- contentType: string;
215
- }>;
216
- resourceRepresentationStream(resourceId: ResourceId, options?: {
217
- accept?: string;
218
- }): Promise<{
219
- stream: ReadableStream<Uint8Array>;
220
- contentType: string;
221
- }>;
222
- resourceEvents(resourceId: ResourceId): Promise<StoredEventResponse$2[]>;
223
- annotationHistory(resourceId: ResourceId, annotationId: AnnotationId): Promise<AnnotationHistoryResponse>;
224
- connections(resourceId: ResourceId): Promise<GraphConnection[]>;
225
- backlinks(resourceId: ResourceId): Promise<Annotation$2[]>;
226
- resourcesByName(query: string, limit?: number): Promise<ResourceDescriptor$5[]>;
227
- files(dirPath?: string, sort?: 'name' | 'mtime' | 'annotationCount'): Promise<components['schemas']['BrowseFilesResponse']>;
228
- }
229
- /**
230
- * Mark — annotation CRUD, entity types, AI assist
231
- *
232
- * Commands return Promises that resolve on HTTP acceptance (202).
233
- * Results appear on browse Observables via bus gateway.
234
- * assist() returns an Observable for long-running progress.
235
- *
236
- * Backend actor: Stower
237
- * Event prefix: mark:*
238
- */
239
- interface MarkNamespace$1 {
240
- annotation(resourceId: ResourceId, input: CreateAnnotationInput): Promise<{
241
- annotationId: string;
242
- }>;
243
- delete(resourceId: ResourceId, annotationId: AnnotationId): Promise<void>;
244
- entityType(type: string): Promise<void>;
245
- entityTypes(types: string[]): Promise<void>;
246
- updateResource(resourceId: ResourceId, data: UpdateResourceInput): Promise<void>;
247
- archive(resourceId: ResourceId): Promise<void>;
248
- unarchive(resourceId: ResourceId): Promise<void>;
249
- assist(resourceId: ResourceId, motivation: Motivation, options: MarkAssistOptions): Observable<MarkAssistProgress>;
250
- }
251
- /**
252
- * Bind — reference linking
253
- *
254
- * The simplest namespace. One method. The result (updated annotation
255
- * with resolved reference) arrives on browse.annotations() via the
256
- * enriched mark:body-updated event.
257
- *
258
- * Backend actor: Stower (via mark:update-body)
259
- * Event prefix: mark:body-updated (shares mark event pipeline)
260
- */
261
- interface BindNamespace$1 {
262
- body(resourceId: ResourceId, annotationId: AnnotationId, operations: BodyOperation[]): Promise<void>;
263
- }
264
- /**
265
- * Gather — context assembly
266
- *
267
- * Long-running (LLM calls + graph traversal). Returns Observables
268
- * that emit progress then the gathered context.
269
- *
270
- * Backend actor: Gatherer
271
- * Event prefix: gather:*
272
- */
273
- interface GatherNamespace$1 {
274
- annotation(annotationId: AnnotationId, resourceId: ResourceId, options?: {
275
- contextWindow?: number;
276
- }): Observable<GatherAnnotationProgress>;
277
- resource(resourceId: ResourceId, options?: {
278
- contextWindow?: number;
279
- }): Observable<GatherAnnotationProgress>;
280
- }
281
- /**
282
- * Match — search and ranking
283
- *
284
- * Long-running (semantic search, optional LLM scoring). Returns
285
- * Observable with progress then results.
286
- *
287
- * Backend actor: Matcher
288
- * Event prefix: match:*
289
- */
290
- interface MatchNamespace$1 {
291
- search(resourceId: ResourceId, referenceId: string, context: GatheredContext, options?: {
292
- limit?: number;
293
- useSemanticScoring?: boolean;
294
- }): Observable<MatchSearchProgress>;
295
- }
296
- /**
297
- * Yield — resource creation
298
- *
299
- * resource() is synchronous file upload (Promise).
300
- * fromAnnotation() is long-running LLM generation (Observable).
301
- *
302
- * Backend actor: Stower + generation worker
303
- * Event prefix: yield:*
304
- */
305
- interface YieldNamespace$1 {
306
- resource(data: CreateResourceInput): Promise<{
307
- resourceId: string;
308
- }>;
309
- fromAnnotation(resourceId: ResourceId, annotationId: AnnotationId, options: GenerationOptions): Observable<YieldProgress$1>;
310
- cloneToken(resourceId: ResourceId): Promise<{
311
- token: string;
312
- expiresAt: string;
313
- }>;
314
- fromToken(token: string): Promise<ResourceDescriptor$5>;
315
- createFromToken(options: CreateFromTokenOptions): Promise<{
316
- resourceId: string;
317
- }>;
318
- }
319
- /**
320
- * Beckon — attention coordination
36
+ * HttpTransport the HTTP/SSE implementation of ITransport.
321
37
  *
322
- * Fire-and-forget. Ephemeral presence signal delivered via the
323
- * attention-stream to other participants.
38
+ * Phase 1 of TRANSPORT-ABSTRACTION. Owns everything that crosses the wire
39
+ * in remote mode: the bus actor (SSE + POST /bus/emit), auth/admin/exchange/
40
+ * system HTTP endpoints, and connection-state plumbing.
324
41
  *
325
- * Backend actor: (frontend relay via attention-stream)
326
- * Event prefix: beckon:*
327
- */
328
- interface BeckonNamespace$1 {
329
- attention(annotationId: AnnotationId, resourceId: ResourceId): void;
330
- }
331
- /**
332
- * Job — worker lifecycle
333
- */
334
- interface JobNamespace$1 {
335
- status(jobId: JobId): Promise<JobStatusResponse$1>;
336
- pollUntilComplete(jobId: JobId, options?: {
337
- interval?: number;
338
- timeout?: number;
339
- onProgress?: (status: JobStatusResponse$1) => void;
340
- }): Promise<JobStatusResponse$1>;
341
- cancel(jobId: JobId, type: string): Promise<void>;
342
- }
343
- /**
344
- * Auth — authentication
345
- */
346
- interface AuthNamespace$1 {
347
- password(email: string, password: string): Promise<AuthResponse$1>;
348
- google(credential: string): Promise<AuthResponse$1>;
349
- refresh(token: string): Promise<AuthResponse$1>;
350
- logout(): Promise<void>;
351
- me(): Promise<User>;
352
- acceptTerms(): Promise<void>;
353
- mcpToken(): Promise<{
354
- token: string;
355
- }>;
356
- mediaToken(resourceId: ResourceId): Promise<{
357
- token: string;
358
- }>;
359
- }
360
- /**
361
- * Admin — administration
362
- */
363
- interface AdminNamespace$1 {
364
- users(): Promise<User[]>;
365
- userStats(): Promise<AdminUserStatsResponse$1>;
366
- updateUser(userId: UserDID, data: RequestContent$1<paths['/api/admin/users/{id}']['patch']>): Promise<User>;
367
- oauthConfig(): Promise<OAuthConfigResponse$1>;
368
- healthCheck(): Promise<ResponseContent$1<paths['/api/health']['get']>>;
369
- status(): Promise<ResponseContent$1<paths['/api/status']['get']>>;
370
- backup(): Promise<Response>;
371
- restore(file: File, onProgress?: (event: {
372
- phase: string;
373
- message?: string;
374
- result?: Record<string, unknown>;
375
- }) => void): Promise<{
376
- phase: string;
377
- message?: string;
378
- result?: Record<string, unknown>;
379
- }>;
380
- exportKnowledgeBase(params?: {
381
- includeArchived?: boolean;
382
- }): Promise<Response>;
383
- importKnowledgeBase(file: File, onProgress?: (event: {
384
- phase: string;
385
- message?: string;
386
- result?: Record<string, unknown>;
387
- }) => void): Promise<{
388
- phase: string;
389
- message?: string;
390
- result?: Record<string, unknown>;
391
- }>;
392
- }
393
-
394
- type Annotation$1 = components['schemas']['Annotation'];
395
- type ResourceDescriptor$4 = components['schemas']['ResourceDescriptor'];
396
- type StoredEventResponse$1 = components['schemas']['StoredEventResponse'];
397
- type TokenGetter$4 = () => AccessToken | undefined;
398
- type ResourceListFilters = {
399
- limit?: number;
400
- archived?: boolean;
401
- search?: string;
402
- };
403
- declare class BrowseNamespace implements BrowseNamespace$1 {
404
- private readonly http;
405
- private readonly eventBus;
406
- private readonly resourceCache;
407
- private readonly resourceListCache;
408
- private readonly annotationListCache;
409
- /**
410
- * Annotation-detail cache keyed by `annotationId` only — the resourceId
411
- * is a routing hint for the backend fetch, not an identity component.
412
- * We track the most recent resourceId per annotationId in a side-map
413
- * so `mark:delete-ok` (which carries only `annotationId`) can reach
414
- * the right cache entry. Aligns with the pre-refactor semantics.
415
- */
416
- private readonly annotationDetailCache;
417
- private readonly annotationResources;
418
- private readonly entityTypesCache;
419
- private readonly referencedByCache;
420
- private readonly resourceEventsCache;
421
- /** Filter-blob memory so `invalidateResourceLists` can replay per-key. */
422
- private readonly resourceListFilters;
423
- /**
424
- * Per-key memo for `annotations()` observables. The cache stores the
425
- * full `AnnotationsListResponse`; the public shape is just the inner
426
- * `Annotation[]`. Without this memo, every call to `annotations(rId)`
427
- * would produce a fresh `.pipe(map(...))` observable, violating B4
428
- * (per-key observable stability). Consumers that compare observable
429
- * identity — React hooks depending on the observable reference,
430
- * `distinctUntilChanged` at a higher level — would misbehave.
431
- */
432
- private readonly annotationListObs;
433
- private readonly getToken;
434
- private readonly actor;
435
- constructor(http: SemiontApiClient, eventBus: EventBus, getToken: TokenGetter$4, actor: ActorVM);
436
- resource(resourceId: ResourceId): Observable<ResourceDescriptor$4 | undefined>;
437
- resources(filters?: ResourceListFilters): Observable<ResourceDescriptor$4[] | undefined>;
438
- annotations(resourceId: ResourceId): Observable<Annotation$1[] | undefined>;
439
- annotation(resourceId: ResourceId, annotationId: AnnotationId): Observable<Annotation$1 | undefined>;
440
- entityTypes(): Observable<string[] | undefined>;
441
- referencedBy(resourceId: ResourceId): Observable<ReferencedByEntry[] | undefined>;
442
- events(resourceId: ResourceId): Observable<StoredEventResponse$1[] | undefined>;
443
- resourceContent(resourceId: ResourceId): Promise<string>;
444
- resourceRepresentation(resourceId: ResourceId, options?: {
445
- accept?: string;
446
- }): Promise<{
447
- data: ArrayBuffer;
448
- contentType: string;
449
- }>;
450
- resourceRepresentationStream(resourceId: ResourceId, options?: {
451
- accept?: string;
452
- }): Promise<{
453
- stream: ReadableStream<Uint8Array>;
454
- contentType: string;
455
- }>;
456
- resourceEvents(resourceId: ResourceId): Promise<StoredEventResponse$1[]>;
457
- annotationHistory(resourceId: ResourceId, annotationId: AnnotationId): Promise<AnnotationHistoryResponse>;
458
- connections(_resourceId: ResourceId): Promise<GraphConnection[]>;
459
- backlinks(_resourceId: ResourceId): Promise<Annotation$1[]>;
460
- resourcesByName(_query: string, _limit?: number): Promise<ResourceDescriptor$4[]>;
461
- files(dirPath?: string, sort?: 'name' | 'mtime' | 'annotationCount'): Promise<components['schemas']['BrowseFilesResponse']>;
462
- invalidateAnnotationList(resourceId: ResourceId): void;
463
- removeAnnotationDetail(annotationId: AnnotationId): void;
464
- invalidateResourceDetail(id: ResourceId): void;
465
- invalidateResourceLists(): void;
466
- invalidateEntityTypes(): void;
467
- invalidateReferencedBy(resourceId: ResourceId): void;
468
- invalidateResourceEvents(resourceId: ResourceId): void;
469
- updateAnnotationInPlace(resourceId: ResourceId, annotation: Annotation$1): void;
470
- /**
471
- * Typed shorthand for `eventBus.get(channel).subscribe(handler)`.
472
- * Preserves per-channel payload typing so handlers read
473
- * `EventMap[K]` without any casts.
474
- */
475
- private on;
476
- /**
477
- * Handler shared by `mark:entity-tag-added` and `mark:entity-tag-removed`.
478
- * Both events carry the same effect: the annotation list, the
479
- * resource descriptor, and the event log for that resource all may
480
- * now reflect different entity tagging, so invalidate all three.
481
- */
482
- private onEntityTagChanged;
483
- /**
484
- * Handler shared by `mark:archived` and `mark:unarchived`. Both
485
- * change a resource's archived flag, which is stored on the resource
486
- * descriptor and affects the resource-list filter.
487
- */
488
- private onArchiveToggled;
489
- /**
490
- * Handler shared by `yield:create-ok` and `yield:update-ok`. Both
491
- * report a resource mutation with the resourceId as a string (not
492
- * yet branded), so we brand and apply the same effect as
493
- * `onArchiveToggled`.
494
- */
495
- private onYieldResourceMutated;
496
- private subscribeToEvents;
497
- }
498
-
499
- type TokenGetter$3 = () => AccessToken | undefined;
500
- declare class MarkNamespace implements MarkNamespace$1 {
501
- private readonly http;
502
- private readonly eventBus;
503
- private readonly getToken;
504
- private readonly actor;
505
- constructor(http: SemiontApiClient, eventBus: EventBus, getToken: TokenGetter$3, actor: ActorVM);
506
- annotation(resourceId: ResourceId, input: CreateAnnotationInput): Promise<{
507
- annotationId: string;
508
- }>;
509
- delete(resourceId: ResourceId, annotationId: AnnotationId): Promise<void>;
510
- entityType(type: string): Promise<void>;
511
- entityTypes(types: string[]): Promise<void>;
512
- updateResource(resourceId: ResourceId, data: UpdateResourceInput): Promise<void>;
513
- archive(resourceId: ResourceId): Promise<void>;
514
- unarchive(resourceId: ResourceId): Promise<void>;
515
- assist(resourceId: ResourceId, motivation: Motivation, options: MarkAssistOptions): Observable<MarkAssistProgress>;
516
- private dispatchAssist;
517
- }
518
-
519
- declare class BindNamespace implements BindNamespace$1 {
520
- private readonly actor;
521
- constructor(actor: ActorVM);
522
- body(resourceId: ResourceId, annotationId: AnnotationId, operations: BodyOperation[]): Promise<void>;
523
- }
524
-
525
- declare class GatherNamespace implements GatherNamespace$1 {
526
- private readonly eventBus;
527
- private readonly actor;
528
- constructor(eventBus: EventBus, actor: ActorVM);
529
- annotation(annotationId: AnnotationId, resourceId: ResourceId, options?: {
530
- contextWindow?: number;
531
- }): Observable<GatherAnnotationProgress>;
532
- resource(_resourceId: ResourceId, _options?: {
533
- contextWindow?: number;
534
- }): Observable<GatherAnnotationProgress>;
535
- }
536
-
537
- declare class MatchNamespace implements MatchNamespace$1 {
538
- private readonly eventBus;
539
- private readonly actor;
540
- constructor(eventBus: EventBus, actor: ActorVM);
541
- search(resourceId: ResourceId, referenceId: string, context: GatheredContext, options?: {
542
- limit?: number;
543
- useSemanticScoring?: boolean;
544
- }): Observable<MatchSearchProgress>;
545
- }
546
-
547
- type YieldProgress = components['schemas']['JobProgress'];
548
-
549
- type ResourceDescriptor$3 = components['schemas']['ResourceDescriptor'];
550
- type TokenGetter$2 = () => AccessToken | undefined;
551
- declare class YieldNamespace implements YieldNamespace$1 {
552
- private readonly http;
553
- private readonly eventBus;
554
- private readonly getToken;
555
- private readonly actor;
556
- constructor(http: SemiontApiClient, eventBus: EventBus, getToken: TokenGetter$2, actor: ActorVM);
557
- resource(data: CreateResourceInput): Promise<{
558
- resourceId: string;
559
- }>;
560
- fromAnnotation(resourceId: ResourceId, annotationId: AnnotationId, options: GenerationOptions): Observable<YieldProgress>;
561
- cloneToken(resourceId: ResourceId): Promise<{
562
- token: string;
563
- expiresAt: string;
564
- }>;
565
- fromToken(token: string): Promise<ResourceDescriptor$3>;
566
- createFromToken(options: CreateFromTokenOptions): Promise<{
567
- resourceId: string;
568
- }>;
569
- }
570
-
571
- declare class BeckonNamespace implements BeckonNamespace$1 {
572
- private readonly actor;
573
- constructor(actor: ActorVM);
574
- attention(annotationId: AnnotationId, resourceId: ResourceId): void;
575
- }
576
-
577
- type JobStatusResponse = components['schemas']['JobStatusResponse'];
578
- declare class JobNamespace implements JobNamespace$1 {
579
- private readonly actor;
580
- constructor(actor: ActorVM);
581
- status(jobId: JobId): Promise<JobStatusResponse>;
582
- pollUntilComplete(jobId: JobId, options?: {
583
- interval?: number;
584
- timeout?: number;
585
- onProgress?: (status: JobStatusResponse) => void;
586
- }): Promise<JobStatusResponse>;
587
- cancel(jobId: JobId, type: string): Promise<void>;
588
- }
589
-
590
- /**
591
- * AuthNamespace — authentication
42
+ * Does NOT own the local coordination bus — that lives on `SemiontClient`.
43
+ * `bridgeInto(bus)` wires SSE-received events into the caller-supplied bus
44
+ * once at construction.
592
45
  */
593
46
 
594
47
  type AuthResponse = components['schemas']['AuthResponse'];
595
- type TokenGetter$1 = () => AccessToken | undefined;
596
- declare class AuthNamespace implements AuthNamespace$1 {
597
- private readonly http;
598
- private readonly getToken;
599
- constructor(http: SemiontApiClient, getToken: TokenGetter$1);
600
- password(emailStr: string, passwordStr: string): Promise<AuthResponse>;
601
- google(credential: string): Promise<AuthResponse>;
602
- refresh(token: string): Promise<AuthResponse>;
603
- logout(): Promise<void>;
604
- me(): Promise<User>;
605
- acceptTerms(): Promise<void>;
606
- mcpToken(): Promise<{
607
- token: string;
608
- }>;
609
- mediaToken(resourceId: ResourceId): Promise<{
610
- token: string;
611
- }>;
612
- }
613
-
614
- /**
615
- * AdminNamespace — administration
616
- */
617
-
48
+ type TokenRefreshResponse = components['schemas']['TokenRefreshResponse'];
618
49
  type AdminUserStatsResponse = components['schemas']['AdminUserStatsResponse'];
619
50
  type OAuthConfigResponse = components['schemas']['OAuthConfigResponse'];
620
- type TokenGetter = () => AccessToken | undefined;
621
- declare class AdminNamespace implements AdminNamespace$1 {
622
- private readonly http;
623
- private readonly getToken;
624
- constructor(http: SemiontApiClient, getToken: TokenGetter);
625
- users(): Promise<User[]>;
626
- userStats(): Promise<AdminUserStatsResponse>;
627
- updateUser(userId: UserDID, data: RequestContent$1<paths['/api/admin/users/{id}']['patch']>): Promise<User>;
628
- oauthConfig(): Promise<OAuthConfigResponse>;
629
- healthCheck(): Promise<ResponseContent$1<paths['/api/health']['get']>>;
630
- status(): Promise<ResponseContent$1<paths['/api/status']['get']>>;
631
- backup(): Promise<Response>;
632
- restore(file: File, onProgress?: (event: {
633
- phase: string;
634
- message?: string;
635
- result?: Record<string, unknown>;
636
- }) => void): Promise<{
637
- phase: string;
638
- message?: string;
639
- result?: Record<string, unknown>;
640
- }>;
641
- exportKnowledgeBase(params?: {
642
- includeArchived?: boolean;
643
- }): Promise<Response>;
644
- importKnowledgeBase(file: File, onProgress?: (event: {
645
- phase: string;
646
- message?: string;
647
- result?: Record<string, unknown>;
648
- }) => void): Promise<{
649
- phase: string;
650
- message?: string;
651
- result?: Record<string, unknown>;
652
- }>;
653
- }
654
-
655
- /**
656
- * Common API client for Semiont backend
657
- *
658
- * This client can be used by:
659
- * - MCP server (Node.js)
660
- * - Demo scripts (Node.js)
661
- * - Frontend (Next.js/React - can wrap with hooks)
662
- *
663
- * Uses ky for HTTP requests with built-in retry, timeout, and error handling.
664
- */
665
-
666
- type ResponseContent<T> = T extends {
667
- responses: {
668
- 200: {
669
- content: {
670
- 'application/json': infer R;
671
- };
672
- };
673
- };
674
- } ? R : T extends {
675
- responses: {
676
- 201: {
677
- content: {
678
- 'application/json': infer R;
679
- };
680
- };
681
- };
682
- } ? R : T extends {
683
- responses: {
684
- 202: {
685
- content: {
686
- 'application/json': infer R;
687
- };
688
- };
689
- };
690
- } ? R : never;
691
- type RequestContent<T> = T extends {
692
- requestBody?: {
693
- content: {
694
- 'application/json': infer R;
695
- };
696
- };
697
- } ? R : never;
698
51
  declare class APIError extends Error {
699
52
  status: number;
700
53
  statusText: string;
701
54
  details?: unknown | undefined;
702
55
  constructor(message: string, status: number, statusText: string, details?: unknown | undefined);
703
56
  }
704
- /**
705
- * Optional callback invoked when a request fails with HTTP 401. If it
706
- * resolves to a non-null token, the failed request is retried once with
707
- * the new Bearer token. If it resolves to null (or throws), the original
708
- * 401 propagates as an APIError.
709
- *
710
- * Implementations must dedupe concurrent calls so that simultaneous 401s
711
- * don't fire multiple parallel refresh requests. `SemiontSession.refresh()`
712
- * satisfies this via an in-flight Promise map keyed by KB id.
713
- */
714
57
  type TokenRefresher = () => Promise<string | null>;
715
- interface SemiontApiClientConfig {
58
+ interface HttpTransportConfig {
716
59
  baseUrl: BaseUrl;
717
- /**
718
- * Observable access token. All auth (HTTP + bus) reads the current value.
719
- * Update by calling `.next(newToken)` on the BehaviorSubject. The bus actor
720
- * auto-starts when the value transitions from null to a real token.
721
- * If omitted, the client operates unauthenticated (public endpoints only).
722
- */
60
+ /** Observable token source; headers read the current value. */
723
61
  token$?: BehaviorSubject<AccessToken | null>;
724
62
  timeout?: number;
725
63
  retry?: number;
@@ -727,1325 +65,109 @@ interface SemiontApiClientConfig {
727
65
  /** Optional 401-recovery hook. See {@link TokenRefresher}. */
728
66
  tokenRefresher?: TokenRefresher;
729
67
  }
730
- /**
731
- * Options for individual API requests
732
- */
733
- interface RequestOptions {
734
- /** Access token for this request */
735
- auth?: AccessToken;
736
- }
737
- /**
738
- * Semiont API Client
739
- *
740
- * Provides type-safe methods for all Semiont backend API endpoints.
741
- * This client is fully stateless - authentication must be provided per request.
742
- */
743
- declare class SemiontApiClient {
744
- private http;
68
+ declare class HttpTransport implements ITransport {
745
69
  readonly baseUrl: BaseUrl;
746
- /**
747
- * Workspace-scoped EventBus — owned by the client, constructed
748
- * internally, never accepted from config. Private: all bus access
749
- * goes through `client.emit` / `client.on` / `client.stream`.
750
- */
751
- private readonly eventBus;
752
- private logger?;
753
- /**
754
- * Observable token source. All auth reads from this.
755
- */
70
+ private readonly http;
756
71
  private readonly token$;
72
+ private readonly logger?;
757
73
  private _actor;
758
- readonly browse: BrowseNamespace;
759
- readonly mark: MarkNamespace;
760
- readonly bind: BindNamespace;
761
- readonly gather: GatherNamespace;
762
- readonly match: MatchNamespace;
763
- readonly yield: YieldNamespace;
764
- readonly beckon: BeckonNamespace;
765
- readonly job: JobNamespace;
766
- readonly auth: AuthNamespace;
767
- readonly admin: AdminNamespace;
768
- constructor(config: SemiontApiClientConfig);
769
74
  private _actorStarted;
770
- get actor(): ActorVM;
75
+ private disposed;
771
76
  private activeResource;
77
+ /** Buses we've been asked to bridge wire events into. */
78
+ private readonly bridges;
79
+ constructor(config: HttpTransportConfig);
80
+ get actor(): ActorVM;
81
+ emit<K extends keyof EventMap>(channel: K, payload: EventMap[K], resourceScope?: ResourceId): Promise<void>;
82
+ on<K extends keyof EventMap>(channel: K, handler: (payload: EventMap[K]) => void): () => void;
83
+ stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;
772
84
  /**
773
- * Subscribe the bus actor to the resource-scoped SSE stream for a single
774
- * resource and bridge incoming scoped events into the workspace event bus.
775
- *
776
- * **One distinct scope at a time**: the client supports subscriptions
777
- * to a single resource scope concurrently. Multiple calls with the
778
- * **same** resourceId are ref-counted — each returns an independent
779
- * unsubscribe; the underlying SSE scope is torn down only when the
780
- * last unsubscribe fires. Calling with a **different** resourceId
781
- * while a subscription is live throws. Widening this to multiple
782
- * concurrent scopes is deferred until a product requirement (e.g.
783
- * split-pane viewer, headless fleet-watcher) forces the design.
784
- *
785
- * @returns a disposer that decrements the ref count (and tears down
786
- * the SSE scope + bridges when it reaches zero).
85
+ * Wire this transport's SSE fan-in into the given bus. Every channel
86
+ * in `BRIDGED_CHANNELS` (and subsequently per-resource scoped channels
87
+ * opened by `subscribeToResource`) is published on the bus. Safe to
88
+ * call multiple times each bus is added to the fan-out list.
787
89
  */
90
+ bridgeInto(bus: EventBus): void;
788
91
  subscribeToResource(resourceId: ResourceId): () => void;
789
92
  private makeUnsubscriber;
93
+ get state$(): Observable<ConnectionState>;
790
94
  dispose(): void;
791
- /** Emit an event on the internal bus. */
792
- emit<K extends keyof EventMap>(channel: K, payload: EventMap[K]): void;
793
- /** Subscribe to an event on the internal bus; returns unsubscribe. */
794
- on<K extends keyof EventMap>(channel: K, handler: (payload: EventMap[K]) => void): () => void;
795
- /** Read-only observable for a bus channel. Consumers `.pipe(...)` over this. */
796
- stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;
797
- /**
798
- * Build the `Authorization: Bearer <token>` header. If the caller passed
799
- * an explicit `{ auth }` it wins (used by session-internal throwaway
800
- * clients that need to run a validation request with a specific token).
801
- * Otherwise the current value of `this.token$` is used, so external
802
- * callers never have to plumb the token themselves.
803
- */
804
95
  private authHeaders;
805
- authenticatePassword(email: Email, password: string, options?: RequestOptions): Promise<ResponseContent<paths['/api/tokens/password']['post']>>;
806
- refreshToken(token: RefreshToken, options?: RequestOptions): Promise<ResponseContent<paths['/api/tokens/refresh']['post']>>;
807
- authenticateGoogle(credential: GoogleCredential, options?: RequestOptions): Promise<ResponseContent<paths['/api/tokens/google']['post']>>;
808
- generateMCPToken(options?: RequestOptions): Promise<ResponseContent<paths['/api/tokens/mcp-generate']['post']>>;
809
- getMediaToken(resourceId: ResourceId, options?: RequestOptions): Promise<{
96
+ authenticatePassword(email: Email, password: string): Promise<AuthResponse>;
97
+ authenticateGoogle(credential: GoogleCredential): Promise<AuthResponse>;
98
+ refreshAccessToken(token: RefreshToken): Promise<TokenRefreshResponse>;
99
+ logout(): Promise<void>;
100
+ acceptTerms(): Promise<void>;
101
+ getCurrentUser(): Promise<UserResponse>;
102
+ generateMcpToken(): Promise<{
810
103
  token: string;
811
104
  }>;
812
- getMe(options?: RequestOptions): Promise<ResponseContent<paths['/api/users/me']['get']>>;
813
- acceptTerms(options?: RequestOptions): Promise<ResponseContent<paths['/api/users/accept-terms']['post']>>;
814
- logout(options?: RequestOptions): Promise<ResponseContent<paths['/api/users/logout']['post']>>;
815
- /**
816
- * Create a new resource with binary content support
817
- *
818
- * @param data - Resource creation data
819
- * @param data.name - Resource name
820
- * @param data.file - File object or Buffer with binary content
821
- * @param data.format - MIME type (e.g., 'text/markdown', 'image/png')
822
- * @param data.entityTypes - Optional array of entity types
823
- * @param data.language - Optional ISO 639-1 language code
824
- * @param data.creationMethod - Optional creation method
825
- * @param data.sourceAnnotationId - Optional source annotation ID
826
- * @param data.sourceResourceId - Optional source resource ID
827
- * @param data.generationPrompt - Optional prompt that drove AI generation
828
- * @param data.generator - Optional Agent(s) that generated the content
829
- * @param options - Request options including auth
830
- */
831
- yieldResource(data: {
832
- name: string;
833
- file: File | Buffer;
834
- format: string;
835
- entityTypes?: string[];
836
- language?: string;
837
- creationMethod?: string;
838
- sourceAnnotationId?: string;
839
- sourceResourceId?: string;
840
- storageUri: string;
841
- generationPrompt?: string;
842
- generator?: components['schemas']['Agent'] | components['schemas']['Agent'][];
843
- isDraft?: boolean;
844
- }, options?: RequestOptions): Promise<ResponseContent<paths['/resources']['post']>>;
845
- browseResource(id: ResourceId, _options?: RequestOptions): Promise<components['schemas']['GetResourceResponse']>;
846
- /**
847
- * Get resource representation using W3C content negotiation
848
- * Returns raw binary content (images, PDFs, text, etc.) with content type
849
- *
850
- * @param resourceUri - Full resource URI
851
- * @param options - Options including Accept header for content negotiation and auth
852
- * @returns Object with data (ArrayBuffer) and contentType (string)
853
- *
854
- * @example
855
- * ```typescript
856
- * // Get markdown representation
857
- * const { data, contentType } = await client.getResourceRepresentation(rUri, { accept: 'text/markdown', auth: token });
858
- * const markdown = new TextDecoder().decode(data);
859
- *
860
- * // Get image representation
861
- * const { data, contentType } = await client.getResourceRepresentation(rUri, { accept: 'image/png', auth: token });
862
- * const blob = new Blob([data], { type: contentType });
863
- *
864
- * // Get PDF representation
865
- * const { data, contentType } = await client.getResourceRepresentation(rUri, { accept: 'application/pdf', auth: token });
866
- * ```
867
- */
868
- getResourceRepresentation(id: ResourceId, options?: {
869
- accept?: ContentFormat;
870
- auth?: AccessToken;
871
- }): Promise<{
872
- data: ArrayBuffer;
873
- contentType: string;
874
- }>;
875
- /**
876
- * Get resource representation as a stream using W3C content negotiation
877
- * Returns streaming binary content (for large files: videos, large PDFs, etc.)
878
- *
879
- * Use this for large files to avoid loading entire content into memory.
880
- * The stream is consumed incrementally and the backend connection stays open
881
- * until the stream is fully consumed or closed.
882
- *
883
- * @param resourceUri - Full resource URI
884
- * @param options - Options including Accept header for content negotiation and auth
885
- * @returns Object with stream (ReadableStream) and contentType (string)
886
- *
887
- * @example
888
- * ```typescript
889
- * // Stream large file
890
- * const { stream, contentType } = await client.getResourceRepresentationStream(rUri, {
891
- * accept: 'video/mp4',
892
- * auth: token
893
- * });
894
- *
895
- * // Consume stream chunk by chunk (never loads entire file into memory)
896
- * for await (const chunk of stream) {
897
- * // Process chunk
898
- * console.log(`Received ${chunk.length} bytes`);
899
- * }
900
- *
901
- * // Or pipe to a file in Node.js
902
- * const fileStream = fs.createWriteStream('output.mp4');
903
- * const reader = stream.getReader();
904
- * while (true) {
905
- * const { done, value } = await reader.read();
906
- * if (done) break;
907
- * fileStream.write(value);
908
- * }
909
- * ```
910
- */
911
- getResourceRepresentationStream(id: ResourceId, options?: {
912
- accept?: ContentFormat;
913
- auth?: AccessToken;
914
- }): Promise<{
915
- stream: ReadableStream<Uint8Array>;
916
- contentType: string;
917
- }>;
918
- browseResources(limit?: number, archived?: boolean, query?: SearchQuery, _options?: RequestOptions): Promise<components['schemas']['ListResourcesResponse']>;
919
- updateResource(id: ResourceId, data: {
920
- archived?: boolean;
921
- entityTypes?: string[];
922
- }, options?: RequestOptions): Promise<void>;
923
- getResourceEvents(id: ResourceId, _options?: RequestOptions): Promise<components['schemas']['GetEventsResponse']>;
924
- browseReferences(id: ResourceId, _options?: RequestOptions): Promise<components['schemas']['GetReferencedByResponse']>;
925
- generateCloneToken(id: ResourceId, _options?: RequestOptions): Promise<components['schemas']['CloneResourceWithTokenResponse']>;
926
- getResourceByToken(token: CloneToken, _options?: RequestOptions): Promise<components['schemas']['GetResourceByTokenResponse']>;
927
- createResourceFromToken(data: {
105
+ getMediaToken(resourceId: ResourceId): Promise<{
928
106
  token: string;
929
- name: string;
930
- content: string;
931
- archiveOriginal?: boolean;
932
- }, _options?: RequestOptions): Promise<{
933
- resourceId: string;
934
- }>;
935
- markAnnotation(id: ResourceId, data: components['schemas']['CreateAnnotationRequest'], _options?: RequestOptions): Promise<{
936
- annotationId: string;
937
- }>;
938
- getAnnotation(id: AnnotationId, _options?: RequestOptions): Promise<components['schemas']['GetAnnotationResponse']>;
939
- browseAnnotation(resourceId: ResourceId, annotationId: AnnotationId, _options?: RequestOptions): Promise<components['schemas']['GetAnnotationResponse']>;
940
- browseAnnotations(id: ResourceId, _motivation?: Motivation, _options?: RequestOptions): Promise<components['schemas']['GetAnnotationsResponse']>;
941
- deleteAnnotation(resourceId: ResourceId, annotationId: AnnotationId, _options?: RequestOptions): Promise<void>;
942
- bindAnnotation(resourceId: ResourceId, annotationId: AnnotationId, data: {
943
- operations: BodyOperation[];
944
- }, _options?: RequestOptions): Promise<{
945
- correlationId: string;
946
- }>;
947
- getAnnotationHistory(resourceId: ResourceId, annotationId: AnnotationId, _options?: RequestOptions): Promise<components['schemas']['GetAnnotationHistoryResponse']>;
948
- annotateReferences(resourceId: ResourceId, data: {
949
- entityTypes: string[];
950
- includeDescriptiveReferences?: boolean;
951
- }, _options?: RequestOptions): Promise<{
952
- correlationId: string;
953
- jobId: string;
954
107
  }>;
955
- annotateHighlights(resourceId: ResourceId, data: {
956
- instructions?: string;
957
- density?: number;
958
- }, _options?: RequestOptions): Promise<{
959
- correlationId: string;
960
- jobId: string;
961
- }>;
962
- annotateAssessments(resourceId: ResourceId, data: {
963
- instructions?: string;
964
- tone?: string;
965
- density?: number;
966
- language?: string;
967
- }, _options?: RequestOptions): Promise<{
968
- correlationId: string;
969
- jobId: string;
970
- }>;
971
- annotateComments(resourceId: ResourceId, data: {
972
- instructions?: string;
973
- tone?: string;
974
- density?: number;
975
- language?: string;
976
- }, _options?: RequestOptions): Promise<{
977
- correlationId: string;
978
- jobId: string;
979
- }>;
980
- annotateTags(resourceId: ResourceId, data: {
981
- schemaId: string;
982
- categories: string[];
983
- }, _options?: RequestOptions): Promise<{
984
- correlationId: string;
985
- jobId: string;
986
- }>;
987
- yieldResourceFromAnnotation(resourceId: ResourceId, annotationId: AnnotationId, data: {
988
- title: string;
989
- storageUri: string;
990
- context: unknown;
991
- prompt?: string;
992
- language?: string;
993
- temperature?: number;
994
- maxTokens?: number;
995
- }, _options?: RequestOptions): Promise<{
996
- correlationId: string;
997
- jobId: string;
998
- }>;
999
- gatherAnnotationContext(resourceId: ResourceId, annotationId: AnnotationId, data: {
1000
- correlationId: string;
1001
- contextWindow?: number;
1002
- }, _options?: RequestOptions): Promise<{
1003
- correlationId: string;
1004
- }>;
1005
- matchSearch(resourceId: ResourceId, data: {
1006
- correlationId: string;
1007
- referenceId: string;
1008
- context: unknown;
1009
- limit?: number;
1010
- useSemanticScoring?: boolean;
1011
- }, _options?: RequestOptions): Promise<{
1012
- correlationId: string;
1013
- }>;
1014
- addEntityType(type: EntityType, _options?: RequestOptions): Promise<void>;
1015
- addEntityTypesBulk(types: EntityType[], _options?: RequestOptions): Promise<void>;
1016
- listEntityTypes(_options?: RequestOptions): Promise<components['schemas']['GetEntityTypesResponse']>;
1017
- beckonAttention(_participantId: string, data: {
1018
- annotationId?: string;
1019
- resourceId: string;
1020
- message?: string;
1021
- }, _options?: RequestOptions): Promise<components['schemas']['BeckonResponse']>;
1022
- listUsers(options?: RequestOptions): Promise<ResponseContent<paths['/api/admin/users']['get']>>;
1023
- getUserStats(options?: RequestOptions): Promise<ResponseContent<paths['/api/admin/users/stats']['get']>>;
1024
- /**
1025
- * Update a user by ID
1026
- * Note: Users use DID identifiers (did:web:domain:users:id), not HTTP URIs.
1027
- */
1028
- updateUser(id: UserDID, data: RequestContent<paths['/api/admin/users/{id}']['patch']>, options?: RequestOptions): Promise<ResponseContent<paths['/api/admin/users/{id}']['patch']>>;
1029
- getOAuthConfig(options?: RequestOptions): Promise<ResponseContent<paths['/api/admin/oauth/config']['get']>>;
1030
- /**
1031
- * Create a backup of the knowledge base. Returns raw Response for streaming download.
1032
- * Caller should use response.blob() to trigger a file download.
1033
- */
1034
- backupKnowledgeBase(options?: RequestOptions): Promise<Response>;
1035
- /**
1036
- * Restore knowledge base from a backup file. Parses SSE progress events and calls onProgress.
1037
- * Returns the final SSE event (phase: 'complete' or 'error').
1038
- */
1039
- restoreKnowledgeBase(file: File, options?: RequestOptions & {
1040
- onProgress?: (event: {
1041
- phase: string;
1042
- message?: string;
1043
- result?: Record<string, unknown>;
1044
- }) => void;
1045
- }): Promise<{
1046
- phase: string;
1047
- message?: string;
1048
- result?: Record<string, unknown>;
1049
- }>;
1050
- /**
1051
- * Export the knowledge base as a JSON-LD Linked Data archive. Returns raw Response for streaming download.
1052
- * Caller should use response.blob() to trigger a file download.
1053
- */
108
+ listUsers(): Promise<ListUsersResponse>;
109
+ getUserStats(): Promise<AdminUserStatsResponse>;
110
+ updateUser(id: UserDID, data: UpdateUserRequest): Promise<UpdateUserResponse>;
111
+ getOAuthConfig(): Promise<OAuthConfigResponse>;
112
+ backupKnowledgeBase(): Promise<Response>;
113
+ restoreKnowledgeBase(file: File, onProgress?: ProgressCallback): Promise<ProgressEvent>;
1054
114
  exportKnowledgeBase(params?: {
1055
115
  includeArchived?: boolean;
1056
- }, options?: RequestOptions): Promise<Response>;
1057
- /**
1058
- * Import a JSON-LD Linked Data archive into the knowledge base. Parses SSE progress events and calls onProgress.
1059
- * Returns the final SSE event (phase: 'complete' or 'error').
1060
- */
1061
- importKnowledgeBase(file: File, options?: RequestOptions & {
1062
- onProgress?: (event: {
1063
- phase: string;
1064
- message?: string;
1065
- result?: Record<string, unknown>;
1066
- }) => void;
1067
- }): Promise<{
1068
- phase: string;
1069
- message?: string;
1070
- result?: Record<string, unknown>;
1071
- }>;
116
+ }): Promise<Response>;
117
+ importKnowledgeBase(file: File, onProgress?: ProgressCallback): Promise<ProgressEvent>;
1072
118
  private parseSSEStream;
1073
- getJobStatus(id: JobId, _options?: RequestOptions): Promise<components['schemas']['JobStatusResponse']>;
1074
- /**
1075
- * Poll a job until it completes or fails
1076
- * @param id - The job ID to poll
1077
- * @param options - Polling options
1078
- * @returns The final job status
1079
- */
1080
- pollJobUntilComplete(id: JobId, options?: {
1081
- interval?: number;
1082
- timeout?: number;
1083
- onProgress?: (status: components['schemas']['JobStatusResponse']) => void;
1084
- auth?: AccessToken;
1085
- }): Promise<components['schemas']['JobStatusResponse']>;
1086
- healthCheck(options?: RequestOptions): Promise<ResponseContent<paths['/api/health']['get']>>;
1087
- getStatus(options?: RequestOptions): Promise<ResponseContent<paths['/api/status']['get']>>;
1088
- browseFiles(dirPath?: string, sort?: 'name' | 'mtime' | 'annotationCount', _options?: RequestOptions): Promise<components['schemas']['BrowseFilesResponse']>;
1089
- }
1090
-
1091
- declare class BusRequestError extends Error {
1092
- constructor(message: string);
1093
- }
1094
- declare function busRequest<TResult>(actor: ActorVM, emitChannel: string, payload: Record<string, unknown>, resultChannel: string, failureChannel: string, timeoutMs?: number): Promise<TResult>;
1095
-
1096
- /**
1097
- * RxJS-native read-through cache primitive.
1098
- *
1099
- * Behavioral contract: packages/api-client/docs/CACHE-SEMANTICS.md (B1–B13).
1100
- *
1101
- * Framework-agnostic: no React, no dependency on any namespace. Used by
1102
- * `BrowseNamespace` to back its per-key stores, but equally usable from
1103
- * CLI, MCP, or worker code.
1104
- *
1105
- * Shape:
1106
- * - `observe(key)`: returns an Observable<V | undefined> that triggers
1107
- * a fetch on first subscription for a missing key, dedup-joins any
1108
- * concurrent fetch, and emits the stored value thereafter.
1109
- * - `invalidate(key)`: stale-while-revalidate — keeps the current
1110
- * value visible to observers, clears the in-flight guard, starts a
1111
- * fresh fetch. If the previous fetch was orphaned (SSE torn down,
1112
- * response lost), this is how the cache recovers.
1113
- * - `remove(key)`: drops the cache entry entirely. Used for entity
1114
- * deletions (B13a). No refetch.
1115
- * - `set(key, value)`: writes through without a fetch. Used when a
1116
- * bus event carries the new value inline (B13b).
1117
- * - `invalidateAll()`: per-key SWR refetch of every currently-cached
1118
- * entry. Used by gap-detection paths.
1119
- * - `dispose()`: completes the store so observers unsubscribe.
1120
- *
1121
- * What's deliberately out:
1122
- * - No subscriber ref-counting / GC of unobserved keys. The per-key
1123
- * observable memo grows with the set of observed keys for the cache's
1124
- * lifetime (B11). Acceptable given cache lifetime == client lifetime.
1125
- * - No TTL / cacheTime. Entries are evicted only by explicit remove.
1126
- * - No retry / backoff. A failing fetch leaves the cache unchanged
1127
- * (B6); the caller drives retry via invalidate.
1128
- */
1129
-
1130
- interface Cache<K, V> {
1131
- /** Observable stream of the value at `key`. Triggers a fetch if not cached. */
1132
- observe(key: K): Observable<V | undefined>;
1133
- /** Synchronous snapshot of the current value, without triggering a fetch. */
1134
- get(key: K): V | undefined;
1135
- /** Iterator of currently-cached keys. For invalidateAll and diagnostics. */
1136
- keys(): K[];
1137
- /**
1138
- * Mark the entry stale and refetch. Keeps the previous value visible
1139
- * to observers during the refetch (stale-while-revalidate).
1140
- */
1141
- invalidate(key: K): void;
1142
- /** Drop the entry from the cache. No refetch. */
1143
- remove(key: K): void;
1144
- /** Write-through: set the value directly without a fetch. */
1145
- set(key: K, value: V): void;
1146
- /** Per-key SWR refetch of every currently-cached entry. */
1147
- invalidateAll(): void;
1148
- /** Release the underlying subject. Observers complete. */
1149
- dispose(): void;
1150
- }
1151
- declare function createCache<K, V>(fetchFn: (key: K) => Promise<V>): Cache<K, V>;
1152
-
1153
- /**
1154
- * KnowledgeBase — a connection to a Semiont backend instance.
1155
- *
1156
- * Each KB has its own JWT, its own API base URL, and its own session.
1157
- * The user is "authenticated against KB X" — never globally authenticated.
1158
- */
1159
- interface KnowledgeBase {
1160
- id: string;
1161
- label: string;
1162
- host: string;
1163
- port: number;
1164
- protocol: 'http' | 'https';
1165
- email: string;
1166
- gitBranch?: string;
1167
- }
1168
- /**
1169
- * Input shape for adding a new KB. The id is generated by the provider.
1170
- */
1171
- type NewKnowledgeBase = Omit<KnowledgeBase, 'id'>;
1172
- /**
1173
- * Status of the locally-stored credential for a KB. Derived from the
1174
- * presence and validity of the JWT in session storage.
1175
- */
1176
- type KbSessionStatus = 'authenticated' | 'expired' | 'signed-out' | 'unreachable';
1177
-
1178
- /**
1179
- * Session-level error surface. Emitted on `SemiontBrowser.error$` for
1180
- * failures that make the session itself unusable (auth failed, actor
1181
- * couldn't start, token refresh terminally exhausted). Per-request
1182
- * errors stay with the caller as normal Promise rejections.
1183
- */
1184
- type SemiontErrorCode = 'session.construct-failed' | 'session.auth-failed' | 'session.refresh-exhausted' | 'browser.sign-in-failed';
1185
- declare class SemiontError extends Error {
1186
- readonly code: SemiontErrorCode;
1187
- readonly kbId: string | null;
1188
- constructor(code: SemiontErrorCode, message: string, kbId?: string | null);
1189
- }
1190
-
1191
- /**
1192
- * SessionStorage — environment-agnostic persistence adapter for the
1193
- * Semiont session layer. Decouples `SemiontSession` / `SemiontBrowser`
1194
- * from `localStorage` / `window` so the same classes can run in a
1195
- * browser, a CLI process, or tests without environment guards.
1196
- *
1197
- * Implementations shipped here:
1198
- * - `InMemorySessionStorage` — map-backed, for tests.
1199
- *
1200
- * Browser-backed (`WebBrowserStorage`) lives in `@semiont/react-ui`
1201
- * because it touches browser-only globals.
1202
- */
1203
- /** String key/value store with optional cross-context change subscription. */
1204
- interface SessionStorage {
1205
- /** Read a string value; null if absent. */
1206
- get(key: string): string | null;
1207
- /** Write a string value. */
1208
- set(key: string, value: string): void;
1209
- /** Remove a key. No-op if absent. */
1210
- delete(key: string): void;
1211
- /**
1212
- * Optional: subscribe to external changes (cross-tab, cross-process).
1213
- * Browser implements via the `storage` event; filesystem would use
1214
- * fs.watch; in-memory omits this method. Returns an unsubscribe
1215
- * callback. If omitted, cross-context sync simply isn't available
1216
- * in that environment — the session still works correctly within a
1217
- * single process.
1218
- */
1219
- subscribe?(handler: (key: string, newValue: string | null) => void): () => void;
1220
- }
1221
- /**
1222
- * Map-backed `SessionStorage`. Cross-context sync is not implemented;
1223
- * tests that need it can drive it manually.
1224
- */
1225
- declare class InMemorySessionStorage implements SessionStorage {
1226
- private readonly map;
1227
- get(key: string): string | null;
1228
- set(key: string, value: string): void;
1229
- delete(key: string): void;
1230
- }
1231
-
1232
- /**
1233
- * SemiontSession — per-backend session lifetime object. Owns the
1234
- * SemiontApiClient, the access token BehaviorSubject, and optionally
1235
- * an authenticated user. One SemiontSession exists per active backend
1236
- * connection; lifetime is decoupled from React mount lifetime.
1237
- *
1238
- * Headless by design. Runs in browsers, CLIs, workers, and tests.
1239
- * UI-specific state (session-expired/permission-denied modals) lives
1240
- * in `FrontendSessionSignals`, which wraps a session — the session
1241
- * itself has no modal observables, no user-facing notifications.
1242
- *
1243
- * Auth is parameterized via callbacks passed at construction:
1244
- *
1245
- * - `refresh()` — invoked on 401 / proactive re-auth. Returns the
1246
- * new access token, or null on failure. The frontend passes a
1247
- * closure that runs the refresh-token flow; the worker passes
1248
- * one that exchanges the shared secret.
1249
- *
1250
- * - `validate(token)` — optional. If provided, the session calls
1251
- * it once at startup with the stored token to confirm it's
1252
- * still good and populate `user$`. Frontend passes `getMe`;
1253
- * worker omits this (service principals have no user record).
1254
- *
1255
- * - `onAuthFailed(message)` — optional. Invoked when refresh
1256
- * terminally fails (expired token, no recovery possible). The
1257
- * frontend wires this to `FrontendSessionSignals.notifySessionExpired`
1258
- * so the modal surfaces; headless consumers typically just log.
1259
- *
1260
- * Persistence goes through a `SessionStorage` adapter provided at
1261
- * construction — the session never touches `localStorage` or `window`
1262
- * directly.
1263
- */
1264
-
1265
- type UserInfo = components['schemas']['UserResponse'];
1266
- interface SemiontSessionConfig {
1267
- kb: KnowledgeBase;
1268
- /** Persistence adapter. Reads/writes tokens via this. */
1269
- storage: SessionStorage;
1270
- /**
1271
- * Re-authenticate after expiry / 401. Returns a new access token
1272
- * (no "Bearer " prefix) on success, or null if recovery is
1273
- * impossible (user needs to sign in again, or the service secret
1274
- * is missing). Callers must dedupe concurrent invocations if the
1275
- * underlying auth call isn't itself idempotent.
1276
- */
1277
- refresh: () => Promise<string | null>;
1278
- /**
1279
- * Validate the stored token at startup and populate `user$`. Omit
1280
- * for service-principal sessions (worker, CLI tools) where there
1281
- * is no user record to fetch.
1282
- */
1283
- validate?: (token: AccessToken) => Promise<UserInfo | null>;
1284
- /**
1285
- * Invoked when refresh terminally fails. Frontend consumers wire
1286
- * this to a UI signal that surfaces the session-expired modal.
1287
- */
1288
- onAuthFailed?: (message: string | null) => void;
1289
- /** Called for session-level failures (auth, refresh exhaustion). */
1290
- onError?: (err: SemiontError) => void;
1291
- }
1292
- declare class SemiontSession {
1293
- readonly kb: KnowledgeBase;
1294
- readonly client: SemiontApiClient;
1295
- readonly token$: BehaviorSubject<AccessToken | null>;
1296
- readonly user$: BehaviorSubject<UserInfo | null>;
1297
- readonly streamState$: Observable<ConnectionState>;
1298
- /** Resolves after the initial validation round-trip completes (success or failure). */
1299
- readonly ready: Promise<void>;
1300
- private readonly storage;
1301
- private readonly doRefresh;
1302
- private readonly doValidate?;
1303
- private readonly onAuthFailed;
1304
- private readonly onError;
1305
- private refreshTimer;
1306
- private unsubscribeStorage;
1307
- private disposed;
1308
- constructor(config: SemiontSessionConfig);
1309
- /**
1310
- * Run the initial mount-time validation. If a stored access token is
1311
- * present and unexpired, call the configured `validate` with it to
1312
- * confirm it still works and populate `user$`. If expired, try
1313
- * refresh first. On 401 from validate, try refresh once. Surfaces
1314
- * auth-failed on terminal failure.
1315
- *
1316
- * When no `validate` callback is provided (service principals), this
1317
- * still runs through the refresh-if-expired step so the stored
1318
- * token is current — it just skips the user-validation round trip.
1319
- */
1320
- private validate;
1321
- /**
1322
- * Refresh the access token via the configured `refresh` callback.
1323
- * On success, pushes the new token into `token$` and schedules the
1324
- * next proactive refresh. On failure, clears persisted state and
1325
- * fires `onAuthFailed` — the frontend's wiring of that callback is
1326
- * what surfaces the session-expired modal.
1327
- */
1328
- refresh(): Promise<AccessToken | null>;
1329
- private scheduleProactiveRefresh;
1330
- private clearRefreshTimer;
119
+ healthCheck(): Promise<HealthCheckResponse>;
120
+ getStatus(): Promise<StatusResponse>;
1331
121
  /**
1332
- * Cross-context sync: another tab/process refreshed or signed out this
1333
- * KB. Mirror the change into our in-memory state.
122
+ * Temporary escape hatch for the ongoing transport migration: namespaces
123
+ * that still need to issue ad-hoc HTTP calls (e.g. legacy browse/mark
124
+ * HTTP fallbacks) can borrow the configured `ky` instance here. Will be
125
+ * deleted once all namespaces route through bus channels or through
126
+ * typed methods on this transport.
1334
127
  */
1335
- private handleStorageChange;
1336
- get expiresAt(): Date | null;
1337
- dispose(): Promise<void>;
1338
- }
1339
-
1340
- /**
1341
- * OpenResource — a single entry in the open-resources list (tabs).
1342
- *
1343
- * The list itself lives on `SemiontBrowser.openResources$`. The CRUD
1344
- * methods (`addOpenResource`, `removeOpenResource`, `updateOpenResourceName`,
1345
- * `reorderOpenResources`) live on `SemiontBrowser` too.
1346
- */
1347
- interface OpenResource {
1348
- /** Unique identifier for the resource */
1349
- id: string;
1350
- /** Display name of the resource */
1351
- name: string;
1352
- /** Timestamp when the resource was opened */
1353
- openedAt: number;
1354
- /** Order/position for manual sorting (optional for backward compatibility) */
1355
- order?: number;
1356
- /** Media type for icon display (e.g., 'application/pdf', 'text/plain') */
1357
- mediaType?: string;
1358
- /** Working-tree URI (e.g. "file://docs/overview.md") — used as tooltip in navigation */
1359
- storageUri?: string;
1360
- }
1361
-
1362
- /**
1363
- * FrontendSessionSignals — modal state that belongs to the UI, not
1364
- * the session itself.
1365
- *
1366
- * `SemiontSession` is a headless per-backend client + token + user
1367
- * holder. It can run in any process: browser, worker, CLI, test. But
1368
- * the session-expired / permission-denied *modals* only make sense
1369
- * in a UI context. Keeping those observables on `SemiontSession`
1370
- * meant workers and CLIs carried four dead BehaviorSubjects that
1371
- * nothing would ever fire.
1372
- *
1373
- * `FrontendSessionSignals` owns the modal state and has no hard
1374
- * reference to a session. `SemiontBrowser` constructs one alongside
1375
- * every frontend session and wires:
1376
- *
1377
- * - `session.onAuthFailed` → `signals.notifySessionExpired` so
1378
- * proactive-refresh failures surface as modals
1379
- * - `notify` module handlers → the active signals' methods so
1380
- * external callers (e.g. React Query's QueryCache.onError) can
1381
- * trigger the modals without touching the session
1382
- *
1383
- * React consumers that need modal state subscribe here; consumers
1384
- * that need bus/HTTP access continue to subscribe to the session.
1385
- *
1386
- * Session auth-state cleanup (clearing token, clearing storage) is
1387
- * the session's own responsibility inside `refresh()` — by the time
1388
- * `notifySessionExpired` runs, the session has already torn down.
1389
- * Signals only surfaces the modal.
1390
- */
1391
-
1392
- declare class FrontendSessionSignals {
1393
- readonly sessionExpiredAt$: BehaviorSubject<number | null>;
1394
- readonly sessionExpiredMessage$: BehaviorSubject<string | null>;
1395
- readonly permissionDeniedAt$: BehaviorSubject<number | null>;
1396
- readonly permissionDeniedMessage$: BehaviorSubject<string | null>;
1397
- constructor();
1398
- notifySessionExpired(message: string | null): void;
1399
- notifyPermissionDenied(message: string | null): void;
1400
- acknowledgeSessionExpired(): void;
1401
- acknowledgePermissionDenied(): void;
1402
- dispose(): void;
1403
- }
1404
-
1405
- /**
1406
- * SemiontBrowser — top-level app-facing container for non-KB state.
1407
- *
1408
- * Holds the list of configured KBs, the active KB selection, the active
1409
- * SemiontSession, the identity token, the open-resources list, and a
1410
- * session-level error stream. Module-scoped singleton — survives every
1411
- * React re-render, remount, and route change. `SemiontProvider` hands
1412
- * the singleton to the React tree; `useSemiont()` returns it.
1413
- *
1414
- * Persistence goes through a `SessionStorage` adapter provided at
1415
- * construction — the browser never touches `localStorage` or `window`
1416
- * directly.
1417
- */
1418
-
1419
- interface SemiontBrowserConfig {
1420
- /** Persistence adapter. The browser reads/writes all persisted state via this. */
1421
- storage: SessionStorage;
1422
- }
1423
- declare class SemiontBrowser {
1424
- readonly kbs$: BehaviorSubject<KnowledgeBase[]>;
1425
- readonly activeKbId$: BehaviorSubject<string | null>;
1426
- readonly activeSession$: BehaviorSubject<SemiontSession | null>;
1427
- /**
1428
- * Modal signals (session-expired / permission-denied) for the
1429
- * currently-active session. Parallels `activeSession$` — always
1430
- * non-null when `activeSession$` is non-null, always null when it
1431
- * is. Extracted from the session itself so headless sessions
1432
- * (workers, CLIs, tests) don't carry dead modal observables.
1433
- * See [FrontendSessionSignals](./frontend-session-signals.ts).
1434
- */
1435
- readonly activeSignals$: BehaviorSubject<FrontendSessionSignals | null>;
1436
- /**
1437
- * True while a session is actively being constructed (setActiveKb /
1438
- * signIn in flight, awaiting `session.ready`). Distinguishes the
1439
- * "session about to arrive" intermediate state from "session
1440
- * intentionally null" (after signOut, or when the active KB has no
1441
- * stored credentials). UIs that want a loading spinner should gate
1442
- * on this; otherwise they get stuck spinning after every signOut.
1443
- */
1444
- readonly sessionActivating$: BehaviorSubject<boolean>;
1445
- readonly openResources$: BehaviorSubject<OpenResource[]>;
1446
- readonly error$: Subject<SemiontError>;
1447
- readonly identityToken$: BehaviorSubject<string | null>;
1448
- private readonly storage;
1449
- /**
1450
- * App-scoped EventBus. Hosts UI-shell events that must work regardless
1451
- * of whether a KB session is active: panel toggles, sidebar state,
1452
- * tab reorders, routing, settings, etc. Disjoint from the per-session
1453
- * bus inside `SemiontApiClient`, which carries KB-content events
1454
- * (mark:*, beckon:*, gather:*, match:*, bind:*, yield:*, browse:click).
1455
- */
1456
- private readonly eventBus;
1457
- private unregisterNotify;
1458
- private unsubscribeStorage;
1459
- private disposed;
1460
- private activating;
1461
- /**
1462
- * Per-KB in-flight refresh dedup. Simultaneous 401s for the same
1463
- * KB converge on a single `/api/tokens/refresh` network call.
1464
- * Was previously module-scoped in `refresh.ts`; moved here when
1465
- * that file was deleted — SemiontBrowser is a singleton so the
1466
- * scoping is equivalent.
1467
- */
1468
- private readonly inFlightRefreshes;
1469
- constructor(config: SemiontBrowserConfig);
1470
- /** Emit an event on the browser's app-scoped bus. */
1471
- emit<K extends keyof EventMap>(channel: K, payload: EventMap[K]): void;
1472
- /** Subscribe to an event; returns unsubscribe. */
1473
- on<K extends keyof EventMap>(channel: K, handler: (payload: EventMap[K]) => void): () => void;
1474
- /** Read-only observable for an app-scoped channel. */
1475
- stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;
1476
- /**
1477
- * Set the app-level identity token (from NextAuth's useSession).
1478
- * Called at the root layout via a single `useEffect`. No other site
1479
- * in the codebase should call this.
1480
- */
1481
- setIdentityToken(token: string | null): void;
1482
- addKb(input: NewKnowledgeBase, access: string, refresh: string): KnowledgeBase;
1483
- removeKb(id: string): void;
1484
- updateKb(id: string, updates: Partial<KnowledgeBase>): void;
128
+ get rawHttp(): KyInstance;
1485
129
  /**
1486
- * Read the locally-stored credential status for a KB. Pure / synchronous —
1487
- * does not subscribe to context changes. Used by KB-list UI to color status
1488
- * dots without requiring re-renders on every tick.
130
+ * Current access token (synchronously read from the BehaviorSubject).
131
+ * Used by content-transport and legacy namespace HTTP fallbacks that
132
+ * need to pass `auth: token` through some code paths.
1489
133
  */
1490
- getKbSessionStatus(kbId: string): KbSessionStatus;
1491
- /**
1492
- * Switch the active KB. Follows the D2 disposal contract:
1493
- * 1. Synchronously announce the new id on `activeKbId$` and null out
1494
- * `activeSession$` so views see a safe empty state first.
1495
- * 2. Serialize overlapping calls — if an activation is in flight, wait
1496
- * for it before proceeding.
1497
- * 3. Dispose whatever session is currently live.
1498
- * 4. Construct the next session and await `session.ready`.
1499
- * 5. Before emitting, re-check `activeKbId$` — if a newer call superseded
1500
- * us while we waited, dispose our session and skip the emit.
1501
- * 6. Emit the new session.
1502
- */
1503
- setActiveKb(id: string | null): Promise<void>;
1504
- /**
1505
- * Sign in to an existing KB: store the tokens and (re)activate the
1506
- * session. If the KB is already active, the current session is disposed
1507
- * and replaced so the new tokens take effect.
1508
- */
1509
- signIn(id: string, access: string, refresh: string): Promise<void>;
1510
- /**
1511
- * Sign out of a KB: clear stored tokens. If the KB is active, dispose
1512
- * its session + signals and emit null for both.
1513
- */
1514
- signOut(id: string): Promise<void>;
1515
- addOpenResource(id: string, name: string, mediaType?: string, storageUri?: string): void;
1516
- removeOpenResource(id: string): void;
1517
- updateOpenResourceName(id: string, name: string): void;
1518
- reorderOpenResources(oldIndex: number, newIndex: number): void;
1519
- /**
1520
- * Refresh the active KB's access token. Returns the new token on
1521
- * success, null on failure. Concurrent calls for the same KB
1522
- * dedupe through `inFlightRefreshes`, so simultaneous 401s trigger
1523
- * only one `/api/tokens/refresh` round trip.
1524
- *
1525
- * Uses a throwaway `SemiontApiClient` with no `tokenRefresher` —
1526
- * a refresh call returning 401 would otherwise re-enter this
1527
- * function infinitely.
1528
- */
1529
- private performRefresh;
1530
- /**
1531
- * Validate an access token by calling `getMe` on a throwaway
1532
- * client. The session uses this once at startup to populate
1533
- * `user$`; 401 triggers a refresh-then-retry inside the session.
1534
- */
1535
- private performValidate;
1536
- dispose(): Promise<void>;
1537
- }
1538
-
1539
- /**
1540
- * Module-scoped singleton for SemiontBrowser. Constructed lazily on first
1541
- * `getBrowser()` call, survives every React re-render, remount, and route
1542
- * change.
1543
- *
1544
- * The caller provides a `SessionStorage` implementation — there is no
1545
- * default here because storage-backend selection is environment-specific
1546
- * (browsers use `WebBrowserStorage`, CLI uses a filesystem adapter,
1547
- * tests use `InMemorySessionStorage`). The first call to `getBrowser`
1548
- * wins; subsequent calls return the cached instance regardless of the
1549
- * storage passed.
1550
- */
1551
-
1552
- interface GetBrowserOptions {
1553
- /** Persistence adapter used to construct the singleton on first call. */
1554
- storage: SessionStorage;
134
+ getToken(): AccessToken | undefined;
1555
135
  }
1556
- declare function getBrowser(options: GetBrowserOptions): SemiontBrowser;
1557
136
 
1558
137
  /**
1559
- * Pure helpers and storage-adapter-driven loaders for the Semiont
1560
- * session layer.
138
+ * HttpContentTransport binary I/O over HTTP.
1561
139
  *
1562
- * Contains:
1563
- * - Storage key shape (constants, `sessionKey(kbId)`)
1564
- * - JWT expiry parsing and "is expired" check
1565
- * - URL/protocol helpers for KB instances
1566
- * - Loaders/savers that take a `SessionStorage` and operate over it
1567
- * (no direct `localStorage` access)
1568
- *
1569
- * No React imports, no module-scoped state, no side effects beyond
1570
- * whatever the passed-in `SessionStorage` does.
140
+ * Phase 1 of TRANSPORT-ABSTRACTION. Narrow by design because binary has
141
+ * different backpressure and streaming characteristics than typed command
142
+ * payloads. Uses the HttpTransport's underlying ky instance + token, so
143
+ * retries, logging, and auth behave identically to the rest of the wire.
1571
144
  */
1572
145
 
1573
- /** The shape persisted per KB. */
1574
- interface StoredSession {
1575
- access: string;
1576
- refresh: string;
1577
- }
1578
- declare function setStoredSession(storage: SessionStorage, kbId: string, session: StoredSession): void;
1579
- declare function defaultProtocol(host: string): 'http' | 'https';
1580
- declare function isValidHostname(host: string): boolean;
1581
- declare function kbBackendUrl(kb: KnowledgeBase): string;
1582
-
1583
- declare function notifySessionExpired(message?: string): void;
1584
- declare function notifyPermissionDenied(message?: string): void;
1585
-
1586
- /**
1587
- * createSearchPipeline
1588
- *
1589
- * A debounced-search RxJS pipeline factory. Combines an input Subject with a
1590
- * downstream fetch function and emits typed `{ results, isSearching }` state.
1591
- *
1592
- * Designed to be created once per component instance via React's
1593
- * `useState(() => createSearchPipeline(...))` lazy initializer, then consumed
1594
- * via `useObservable(pipeline.state$)`. The pipeline holds no React state and
1595
- * has no React imports — it's pure RxJS, unit-testable without a renderer.
1596
- *
1597
- * The fetch function is expected to return `Observable<T[] | undefined>`,
1598
- * matching the cache-miss-then-data shape of `BrowseNamespace` Observables:
1599
- * `undefined` means "fetch in flight, no value yet"; an array means "data
1600
- * available (possibly empty)".
1601
- */
1602
-
1603
- interface SearchState<T> {
1604
- results: T[];
1605
- isSearching: boolean;
1606
- }
1607
- interface SearchPipeline<T> {
1608
- /** Latest query string. Bind to a controlled input via `useObservable`. */
1609
- query$: Observable<string>;
1610
- /** Latest search state — results plus a loading flag. */
1611
- state$: Observable<SearchState<T>>;
1612
- /** Push a new query value. Triggers the debounced fetch. */
1613
- setQuery(value: string): void;
1614
- /** Tear down the input Subject. Call from `useEffect` cleanup. */
1615
- dispose(): void;
1616
- }
1617
- interface SearchPipelineOptions {
1618
- /** Milliseconds to wait after the last keystroke before fetching. Default 250. */
1619
- debounceMs?: number;
1620
- /** Initial query value. Useful for modals that open with a pre-filled term. */
1621
- initialQuery?: string;
1622
- }
1623
- declare function createSearchPipeline<T>(fetch: (query: string) => Observable<T[] | undefined>, options?: SearchPipelineOptions): SearchPipeline<T>;
1624
-
1625
- interface BeckonVM extends ViewModel {
1626
- hoveredAnnotationId$: Observable<string | null>;
1627
- hover(annotationId: string | null): void;
1628
- focus(annotationId: string): void;
1629
- sparkle(annotationId: string): void;
1630
- }
1631
- declare function createBeckonVM(client: SemiontApiClient): BeckonVM;
1632
- /** Default milliseconds the mouse must dwell before beckon:hover is emitted. */
1633
- declare const HOVER_DELAY_MS = 150;
1634
- type EmitHover = (annotationId: string | null) => void;
1635
- interface HoverHandlers {
1636
- handleMouseEnter: (annotationId: string) => void;
1637
- handleMouseLeave: () => void;
1638
- cleanup: () => void;
1639
- }
1640
- declare function createHoverHandlers(emit: EmitHover, delayMs: number): HoverHandlers;
1641
-
1642
- /**
1643
- * ShellVM — app-shell state: which toolbar panel is open, tab-bar
1644
- * coordination helpers, scroll-to-annotation signals. Lives on
1645
- * `SemiontBrowser`'s app-scoped bus (not the per-session client bus)
1646
- * because panel toggles and shell chrome must work regardless of
1647
- * whether a KB session is active.
1648
- *
1649
- * Channels: `panel:toggle`, `panel:open`, `panel:close`.
1650
- */
1651
-
1652
- type ToolbarPanelType = 'history' | 'info' | 'annotations' | 'settings' | 'collaboration' | 'user' | 'jsonld' | 'knowledge-base';
1653
- declare const COMMON_PANELS: readonly ToolbarPanelType[];
1654
- declare const RESOURCE_PANELS: readonly ToolbarPanelType[];
1655
- interface ShellVM extends ViewModel {
1656
- activePanel$: Observable<ToolbarPanelType | null>;
1657
- scrollToAnnotationId$: Observable<string | null>;
1658
- panelInitialTab$: Observable<{
1659
- tab: string;
1660
- generation: number;
1661
- } | null>;
1662
- openPanel(panel: string): void;
1663
- closePanel(): void;
1664
- togglePanel(panel: string): void;
1665
- onScrollCompleted(): void;
1666
- }
1667
- interface ShellVMOptions {
1668
- initialPanel?: ToolbarPanelType | null;
1669
- onPanelChange?: (panel: ToolbarPanelType | null) => void;
1670
- }
1671
- declare function createShellVM(browser: SemiontBrowser, options?: ShellVMOptions): ShellVM;
1672
-
1673
- interface GatherVM extends ViewModel {
1674
- context$: Observable<GatheredContext | null>;
1675
- loading$: Observable<boolean>;
1676
- error$: Observable<Error | null>;
1677
- annotationId$: Observable<AnnotationId | null>;
1678
- }
1679
- declare function createGatherVM(client: SemiontApiClient, resourceId: ResourceId): GatherVM;
1680
-
1681
- interface MatchVM extends ViewModel {
1682
- }
1683
- declare function createMatchVM(client: SemiontApiClient, _resourceId: ResourceId): MatchVM;
1684
-
1685
- type JobProgress$1 = components['schemas']['JobProgress'];
1686
- interface GenerateDocumentOptions {
1687
- title: string;
1688
- storageUri: string;
1689
- prompt?: string;
1690
- language?: string;
1691
- temperature?: number;
1692
- maxTokens?: number;
1693
- context: GatheredContext;
1694
- }
1695
- interface YieldVM extends ViewModel {
1696
- isGenerating$: Observable<boolean>;
1697
- progress$: Observable<JobProgress$1 | null>;
1698
- generate(referenceId: string, options: GenerateDocumentOptions): void;
1699
- }
1700
- declare function createYieldVM(client: SemiontApiClient, resourceId: ResourceId, locale: string): YieldVM;
1701
-
1702
- type JobProgress = components['schemas']['JobProgress'];
1703
- interface PendingAnnotation {
1704
- selector: Selector | Selector[];
1705
- motivation: Motivation;
1706
- }
1707
- interface MarkVM extends ViewModel {
1708
- pendingAnnotation$: Observable<PendingAnnotation | null>;
1709
- assistingMotivation$: Observable<Motivation | null>;
1710
- progress$: Observable<JobProgress | null>;
1711
- }
1712
- declare function createMarkVM(client: SemiontApiClient, resourceId: ResourceId): MarkVM;
1713
-
1714
- type ResourceDescriptor$2 = components['schemas']['ResourceDescriptor'];
1715
- interface DiscoverVM extends ViewModel {
1716
- browse: ShellVM;
1717
- search: SearchPipeline<ResourceDescriptor$2>;
1718
- recentResources$: Observable<ResourceDescriptor$2[]>;
1719
- entityTypes$: Observable<string[]>;
1720
- isLoadingRecent$: Observable<boolean>;
1721
- }
1722
- declare function createDiscoverVM(client: SemiontApiClient, browse: ShellVM): DiscoverVM;
1723
-
1724
- interface EntityTagsVM extends ViewModel {
1725
- browse: ShellVM;
1726
- entityTypes$: Observable<string[]>;
1727
- isLoading$: Observable<boolean>;
1728
- newTag$: Observable<string>;
1729
- error$: Observable<string>;
1730
- isAdding$: Observable<boolean>;
1731
- setNewTag(value: string): void;
1732
- addTag(): Promise<void>;
1733
- }
1734
- declare function createEntityTagsVM(client: SemiontApiClient, browse: ShellVM): EntityTagsVM;
1735
-
1736
- interface ImportPreview {
1737
- format: string;
1738
- version: number;
1739
- sourceUrl: string;
1740
- stats: Record<string, number>;
1741
- }
1742
- interface ExchangeVM extends ViewModel {
1743
- browse: ShellVM;
1744
- selectedFile$: Observable<File | null>;
1745
- preview$: Observable<ImportPreview | null>;
1746
- importPhase$: Observable<string | null>;
1747
- importMessage$: Observable<string | undefined>;
1748
- importResult$: Observable<Record<string, unknown> | undefined>;
1749
- isExporting$: Observable<boolean>;
1750
- isImporting$: Observable<boolean>;
1751
- selectFile(file: File): void;
1752
- cancelImport(): void;
1753
- doExport(): Promise<{
1754
- blob: Blob;
1755
- filename: string;
146
+ declare class HttpContentTransport implements IContentTransport {
147
+ private readonly transport;
148
+ constructor(transport: HttpTransport);
149
+ putBinary(request: PutBinaryRequest, options?: {
150
+ auth?: AccessToken;
151
+ }): Promise<{
152
+ resourceId: ResourceId;
1756
153
  }>;
1757
- doImport(): Promise<void>;
1758
- }
1759
- declare function createExchangeVM(browse: ShellVM, exportFn: (params?: {
1760
- includeArchived?: boolean;
1761
- }) => Promise<Response>, importFn: (file: File, options?: {
1762
- onProgress?: (event: {
1763
- phase: string;
1764
- message?: string;
1765
- result?: Record<string, unknown>;
1766
- }) => void;
1767
- }) => Promise<{
1768
- phase: string;
1769
- message?: string;
1770
- result?: Record<string, unknown>;
1771
- }>): ExchangeVM;
1772
-
1773
- interface AdminUsersVM extends ViewModel {
1774
- browse: ShellVM;
1775
- users$: Observable<unknown[]>;
1776
- stats$: Observable<unknown | null>;
1777
- usersLoading$: Observable<boolean>;
1778
- statsLoading$: Observable<boolean>;
1779
- updateUser(id: string, data: {
1780
- isAdmin?: boolean;
1781
- isActive?: boolean;
1782
- }): Promise<void>;
1783
- }
1784
- declare function createAdminUsersVM(client: SemiontApiClient, browse: ShellVM): AdminUsersVM;
1785
-
1786
- interface AdminSecurityVM extends ViewModel {
1787
- browse: ShellVM;
1788
- providers$: Observable<unknown[]>;
1789
- allowedDomains$: Observable<string[]>;
1790
- isLoading$: Observable<boolean>;
1791
- }
1792
- declare function createAdminSecurityVM(client: SemiontApiClient, browse: ShellVM): AdminSecurityVM;
1793
-
1794
- interface WelcomeVM extends ViewModel {
1795
- userData$: Observable<{
1796
- termsAcceptedAt?: string;
1797
- } | null>;
1798
- isProcessing$: Observable<boolean>;
1799
- acceptTerms(): Promise<void>;
1800
- }
1801
- declare function createWelcomeVM(client: SemiontApiClient): WelcomeVM;
1802
-
1803
- type ResourceDescriptor$1 = components['schemas']['ResourceDescriptor'];
1804
- interface ResourceLoaderVM extends ViewModel {
1805
- resource$: Observable<ResourceDescriptor$1 | undefined>;
1806
- isLoading$: Observable<boolean>;
1807
- invalidate(): void;
1808
- }
1809
- declare function createResourceLoaderVM(client: SemiontApiClient, resourceId: ResourceId): ResourceLoaderVM;
1810
-
1811
- interface SessionVM extends ViewModel {
1812
- isLoggingOut$: Observable<boolean>;
1813
- logout(): Promise<void>;
1814
- }
1815
- declare function createSessionVM(client: SemiontApiClient): SessionVM;
1816
-
1817
- interface SmelterEvent {
1818
- type: string;
1819
- resourceId?: string;
1820
- payload: Record<string, unknown>;
1821
- }
1822
- interface SmelterActorVMOptions {
1823
- baseUrl: string;
1824
- token: string;
1825
- reconnectMs?: number;
1826
- }
1827
- interface SmelterActorVM extends ViewModel {
1828
- events$: Observable<SmelterEvent>;
1829
- state$: Observable<ConnectionState>;
1830
- emit(channel: string, payload: Record<string, unknown>): Promise<void>;
1831
- start(): void;
1832
- stop(): void;
1833
- }
1834
- declare function createSmelterActorVM(options: SmelterActorVMOptions): SmelterActorVM;
1835
-
1836
- /**
1837
- * Job Claim Adapter — worker-side job lifecycle glue on top of a
1838
- * shared `ActorVM`.
1839
- *
1840
- * Replaces the old `WorkerVM`, which owned its own actor and
1841
- * duplicated the SSE connection that `SemiontApiClient` already held.
1842
- * Workers now construct a `SemiontSession` normally (one actor, one
1843
- * SSE connection) and use this adapter to attach job-claim behaviour
1844
- * on top of `session.client.actor`.
1845
- *
1846
- * The adapter is intentionally thin: it subscribes to `job:queued`
1847
- * on the actor, claims jobs via the existing request-response
1848
- * protocol (`job:claim` → `job:claimed` / `job:claim-failed`), and
1849
- * exposes observables for job orchestration. It does **not** own
1850
- * the actor, has no HTTP concerns, and has no modal state.
1851
- */
1852
-
1853
- interface JobAssignment {
1854
- jobId: string;
1855
- type: string;
1856
- resourceId: string;
1857
- }
1858
- interface ActiveJob {
1859
- jobId: string;
1860
- type: string;
1861
- resourceId: string;
1862
- userId: string;
1863
- params: Record<string, unknown>;
1864
- }
1865
- interface JobClaimAdapterOptions {
1866
- /** Shared actor (typically `session.client.actor`). */
1867
- actor: ActorVM;
1868
- /**
1869
- * Job types this worker can process. Jobs of other types that
1870
- * arrive on `job:queued` are ignored. Empty array = accept any.
1871
- */
1872
- jobTypes: string[];
1873
- }
1874
- interface JobClaimAdapter {
1875
- /** Currently-claimed job, or null when idle. */
1876
- readonly activeJob$: Observable<ActiveJob | null>;
1877
- /** True while a claim is in flight or a job is being processed. */
1878
- readonly isProcessing$: Observable<boolean>;
1879
- /** Monotonically-incrementing count of successfully-completed jobs. */
1880
- readonly jobsCompleted$: Observable<number>;
1881
- /** Stream of job failures (including claim-failed and processing errors). */
1882
- readonly errors$: Observable<{
1883
- jobId: string;
1884
- error: string;
154
+ getBinary(resourceId: ResourceId, options?: {
155
+ accept?: ContentFormat | string;
156
+ auth?: AccessToken;
157
+ }): Promise<{
158
+ data: ArrayBuffer;
159
+ contentType: string;
160
+ }>;
161
+ getBinaryStream(resourceId: ResourceId, options?: {
162
+ accept?: ContentFormat | string;
163
+ auth?: AccessToken;
164
+ }): Promise<{
165
+ stream: ReadableStream<Uint8Array>;
166
+ contentType: string;
1885
167
  }>;
1886
- /**
1887
- * Subscribe to `job:queued` events (adding the channel to the actor
1888
- * if not already subscribed) and begin claiming matching jobs.
1889
- * Idempotent — calling `start()` twice is a no-op.
1890
- */
1891
- start(): void;
1892
- /** Stop claiming new jobs. Does not cancel an in-flight job. */
1893
- stop(): void;
1894
- /** Signal successful completion of `activeJob$`. */
1895
- completeJob(): void;
1896
- /** Signal failure of `activeJob$`. Emits on `errors$`. */
1897
- failJob(jobId: string, error: string): void;
1898
- /** Release observables. Does not dispose the shared actor. */
1899
168
  dispose(): void;
169
+ /** Auth header + W3C trace propagation for the active span. */
170
+ private requestHeaders;
1900
171
  }
1901
- /**
1902
- * Attach job-claim behaviour to a shared `ActorVM`.
1903
- */
1904
- declare function createJobClaimAdapter(options: JobClaimAdapterOptions): JobClaimAdapter;
1905
-
1906
- interface Job {
1907
- jobId: string;
1908
- type: string;
1909
- status: string;
1910
- resourceId: string;
1911
- userId: string;
1912
- created: string;
1913
- startedAt?: string;
1914
- completedAt?: string;
1915
- error?: string;
1916
- progress?: Record<string, unknown>;
1917
- result?: Record<string, unknown>;
1918
- }
1919
- interface JobQueueVM extends ViewModel {
1920
- jobs$: Observable<Job[]>;
1921
- pendingByType$: Observable<Map<string, number>>;
1922
- runningJobs$: Observable<Job[]>;
1923
- jobCreated$: Observable<Job>;
1924
- jobCompleted$: Observable<Job>;
1925
- jobFailed$: Observable<Job>;
1926
- }
1927
- declare function createJobQueueVM(client: SemiontApiClient): JobQueueVM;
1928
-
1929
- type Annotation = components['schemas']['Annotation'];
1930
- interface AnnotationGroups {
1931
- highlights: Annotation[];
1932
- comments: Annotation[];
1933
- assessments: Annotation[];
1934
- references: Annotation[];
1935
- tags: Annotation[];
1936
- }
1937
- type StoredEventResponse = components['schemas']['StoredEventResponse'];
1938
- interface WizardState {
1939
- open: boolean;
1940
- annotationId: string | null;
1941
- resourceId: string | null;
1942
- defaultTitle: string;
1943
- entityTypes: string[];
1944
- }
1945
- interface ResourceViewerPageVM extends ViewModel {
1946
- beckon: BeckonVM;
1947
- browse: ShellVM;
1948
- mark: MarkVM;
1949
- gather: GatherVM;
1950
- yield: YieldVM;
1951
- annotations$: Observable<Annotation[]>;
1952
- annotationGroups$: Observable<AnnotationGroups>;
1953
- entityTypes$: Observable<string[]>;
1954
- events$: Observable<StoredEventResponse[]>;
1955
- referencedBy$: Observable<ReferencedByEntry[]>;
1956
- content$: Observable<string>;
1957
- contentLoading$: Observable<boolean>;
1958
- mediaToken$: Observable<string | null>;
1959
- wizard$: Observable<WizardState>;
1960
- closeWizard(): void;
1961
- }
1962
- declare function createResourceViewerPageVM(client: SemiontApiClient, resourceId: ResourceId, locale: string, browse: ShellVM, options?: {
1963
- mediaType?: string;
1964
- }): ResourceViewerPageVM;
1965
-
1966
- type ResourceDescriptor = components['schemas']['ResourceDescriptor'];
1967
- type ComposeMode = 'new' | 'clone' | 'reference';
1968
- interface ComposeParams {
1969
- mode?: string | undefined;
1970
- token?: string | undefined;
1971
- annotationUri?: string | undefined;
1972
- sourceDocumentId?: string | undefined;
1973
- name?: string | undefined;
1974
- entityTypes?: string | undefined;
1975
- storedContext?: string | undefined;
1976
- }
1977
- interface CloneData {
1978
- sourceResource: ResourceDescriptor;
1979
- sourceContent: string;
1980
- }
1981
- interface ReferenceData {
1982
- annotationUri: string;
1983
- sourceDocumentId: string;
1984
- name: string;
1985
- entityTypes: string[];
1986
- }
1987
- interface SaveResourceParams {
1988
- mode: ComposeMode;
1989
- name: string;
1990
- storageUri: string;
1991
- content?: string;
1992
- file?: File;
1993
- format?: string;
1994
- charset?: string;
1995
- entityTypes?: string[];
1996
- language: string;
1997
- archiveOriginal?: boolean;
1998
- annotationUri?: string;
1999
- sourceDocumentId?: string;
2000
- }
2001
- interface ComposePageVM extends ViewModel {
2002
- browse: ShellVM;
2003
- mode$: Observable<ComposeMode>;
2004
- loading$: Observable<boolean>;
2005
- cloneData$: Observable<CloneData | null>;
2006
- referenceData$: Observable<ReferenceData | null>;
2007
- gatheredContext$: Observable<GatheredContext | null>;
2008
- entityTypes$: Observable<string[]>;
2009
- save(params: SaveResourceParams): Promise<string>;
2010
- }
2011
- declare function createComposePageVM(client: SemiontApiClient, browse: ShellVM, params: ComposeParams, auth?: AccessToken): ComposePageVM;
2012
-
2013
- /**
2014
- * MIME type utilities for Semiont
2015
- *
2016
- * Initial support for:
2017
- * - text/plain
2018
- * - text/markdown
2019
- * - image/png
2020
- * - image/jpeg
2021
- * - application/pdf
2022
- */
2023
- /**
2024
- * Map MIME type to file extension
2025
- */
2026
- declare function getExtensionForMimeType(mimeType: string): string;
2027
- /**
2028
- * Detect if MIME type is an image (png or jpeg only for now)
2029
- */
2030
- declare function isImageMimeType(mimeType: string): boolean;
2031
- /**
2032
- * Detect if MIME type is text-based (plain or markdown only for now)
2033
- */
2034
- declare function isTextMimeType(mimeType: string): boolean;
2035
- /**
2036
- * Detect if MIME type is PDF
2037
- */
2038
- declare function isPdfMimeType(mimeType: string): boolean;
2039
- /**
2040
- * Get category for MIME type (for routing to appropriate viewer)
2041
- *
2042
- * Categories represent annotation models, not file formats:
2043
- * - 'text': Text-based annotations (TextPositionSelector, TextQuoteSelector)
2044
- * - 'image': Spatial coordinate annotations (SvgSelector, FragmentSelector)
2045
- *
2046
- * PDFs use spatial coordinates for annotations, so they belong to 'image' category.
2047
- */
2048
- type MimeCategory = 'text' | 'image' | 'unsupported';
2049
- declare function getMimeCategory(mimeType: string): MimeCategory;
2050
172
 
2051
- export { APIError, type ActiveJob, type ActorVM, type ActorVMOptions, AdminNamespace, type AdminSecurityVM, type AdminUsersVM, type AnnotationGroups, type AnnotationHistoryResponse, AuthNamespace, BeckonNamespace, type BeckonVM, BindNamespace, BrowseNamespace, type BusEvent, BusRequestError, COMMON_PANELS, type Cache, type CloneData, type ComposeMode, type ComposePageVM, type ComposeParams, type ConnectionState, type CreateAnnotationInput, type CreateFromTokenOptions, type CreateResourceInput, DEGRADED_THRESHOLD_MS, type DiscoverVM, type EntityTagsVM, type ExchangeVM, FrontendSessionSignals, type GatherAnnotationProgress, GatherNamespace, type GatherVM, type GenerateDocumentOptions, type GenerationOptions, type GetBrowserOptions, HOVER_DELAY_MS, type HoverHandlers, type ImportPreview, InMemorySessionStorage, type Job, type JobAssignment, type JobClaimAdapter, type JobClaimAdapterOptions, JobNamespace, type JobQueueVM, type KbSessionStatus, type KnowledgeBase, type MarkAssistOptions, type MarkAssistProgress, MarkNamespace, type MarkVM, MatchNamespace, type MatchSearchProgress, type MatchVM, type MimeCategory, type NewKnowledgeBase, type OpenResource, type PendingAnnotation, RESOURCE_PANELS, type ReferenceData, type ReferencedByEntry, type RequestContent$1 as RequestContent, type RequestOptions, type ResourceLoaderVM, type ResourceViewerPageVM, type ResponseContent$1 as ResponseContent, type SaveResourceParams, type SearchPipeline, type SearchPipelineOptions, type SearchState, SemiontApiClient, type SemiontApiClientConfig, SemiontBrowser, type SemiontBrowserConfig, SemiontError, type SemiontErrorCode, SemiontSession, type SemiontSessionConfig, type SessionStorage, type SessionVM, type ShellVM, type ShellVMOptions, type SmelterActorVM, type SmelterActorVMOptions, type SmelterEvent, type StoredSession, type TokenRefresher, type ToolbarPanelType, type User, type UserInfo, type ViewModel, type WelcomeVM, type WizardState, YieldNamespace, type YieldVM, busRequest, createActorVM, createAdminSecurityVM, createAdminUsersVM, createBeckonVM, createCache, createComposePageVM, createDiscoverVM, createDisposer, createEntityTagsVM, createExchangeVM, createGatherVM, createHoverHandlers, createJobClaimAdapter, createJobQueueVM, createMarkVM, createMatchVM, createResourceLoaderVM, createResourceViewerPageVM, createSearchPipeline, createSessionVM, createShellVM, createSmelterActorVM, createWelcomeVM, createYieldVM, defaultProtocol, getBrowser, getExtensionForMimeType, getMimeCategory, isImageMimeType, isPdfMimeType, isTextMimeType, isValidHostname, kbBackendUrl, notifyPermissionDenied, notifySessionExpired, setStoredSession };
173
+ export { APIError, type ActorVM, type ActorVMOptions, type BusEvent, DEGRADED_THRESHOLD_MS, HttpContentTransport, HttpTransport, type HttpTransportConfig, type TokenRefresher, createActorVM };