@semiont/sdk 0.5.3 → 0.5.4

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.
Files changed (79) hide show
  1. package/dist/awaitable.d.ts +103 -0
  2. package/dist/awaitable.d.ts.map +1 -0
  3. package/dist/bus-request.d.ts +18 -0
  4. package/dist/bus-request.d.ts.map +1 -0
  5. package/dist/cache.d.ts +57 -0
  6. package/dist/cache.d.ts.map +1 -0
  7. package/dist/client.d.ts +138 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/index.d.ts +52 -1750
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +0 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/namespaces/admin.d.ts +27 -0
  14. package/dist/namespaces/admin.d.ts.map +1 -0
  15. package/dist/namespaces/auth.d.ts +26 -0
  16. package/dist/namespaces/auth.d.ts.map +1 -0
  17. package/dist/namespaces/beckon.d.ts +12 -0
  18. package/dist/namespaces/beckon.d.ts.map +1 -0
  19. package/dist/namespaces/bind.d.ts +11 -0
  20. package/dist/namespaces/bind.d.ts.map +1 -0
  21. package/dist/namespaces/browse.d.ts +111 -0
  22. package/dist/namespaces/browse.d.ts.map +1 -0
  23. package/dist/namespaces/frame.d.ts +29 -0
  24. package/dist/namespaces/frame.d.ts.map +1 -0
  25. package/dist/namespaces/gather.d.ts +16 -0
  26. package/dist/namespaces/gather.d.ts.map +1 -0
  27. package/dist/namespaces/job.d.ts +32 -0
  28. package/dist/namespaces/job.d.ts.map +1 -0
  29. package/dist/namespaces/mark.d.ts +27 -0
  30. package/dist/namespaces/mark.d.ts.map +1 -0
  31. package/dist/namespaces/match.d.ts +15 -0
  32. package/dist/namespaces/match.d.ts.map +1 -0
  33. package/dist/namespaces/types.d.ts +438 -0
  34. package/dist/namespaces/types.d.ts.map +1 -0
  35. package/dist/namespaces/yield.d.ts +23 -0
  36. package/dist/namespaces/yield.d.ts.map +1 -0
  37. package/dist/session/errors.d.ts +18 -0
  38. package/dist/session/errors.d.ts.map +1 -0
  39. package/dist/session/http-session-factory.d.ts +15 -0
  40. package/dist/session/http-session-factory.d.ts.map +1 -0
  41. package/dist/session/knowledge-base.d.ts +95 -0
  42. package/dist/session/knowledge-base.d.ts.map +1 -0
  43. package/dist/session/open-resource.d.ts +22 -0
  44. package/dist/session/open-resource.d.ts.map +1 -0
  45. package/dist/session/registry.d.ts +31 -0
  46. package/dist/session/registry.d.ts.map +1 -0
  47. package/dist/session/semiont-browser.d.ts +141 -0
  48. package/dist/session/semiont-browser.d.ts.map +1 -0
  49. package/dist/session/semiont-session.d.ts +210 -0
  50. package/dist/session/semiont-session.d.ts.map +1 -0
  51. package/dist/session/session-factory.d.ts +31 -0
  52. package/dist/session/session-factory.d.ts.map +1 -0
  53. package/dist/session/session-signals.d.ts +40 -0
  54. package/dist/session/session-signals.d.ts.map +1 -0
  55. package/dist/session/session-storage.d.ts +41 -0
  56. package/dist/session/session-storage.d.ts.map +1 -0
  57. package/dist/session/storage.d.ts +52 -0
  58. package/dist/session/storage.d.ts.map +1 -0
  59. package/dist/session/testing.d.ts +7 -0
  60. package/dist/session/testing.d.ts.map +1 -0
  61. package/dist/state/flows/beckon-state-unit.d.ts +22 -0
  62. package/dist/state/flows/beckon-state-unit.d.ts.map +1 -0
  63. package/dist/state/flows/gather-state-unit.d.ts +12 -0
  64. package/dist/state/flows/gather-state-unit.d.ts.map +1 -0
  65. package/dist/state/flows/mark-state-unit.d.ts +17 -0
  66. package/dist/state/flows/mark-state-unit.d.ts.map +1 -0
  67. package/dist/state/flows/match-state-unit.d.ts +7 -0
  68. package/dist/state/flows/match-state-unit.d.ts.map +1 -0
  69. package/dist/state/flows/yield-state-unit.d.ts +25 -0
  70. package/dist/state/flows/yield-state-unit.d.ts.map +1 -0
  71. package/dist/state/index.d.ts +10 -0
  72. package/dist/state/index.d.ts.map +1 -0
  73. package/dist/state/lib/search-pipeline.d.ts +38 -0
  74. package/dist/state/lib/search-pipeline.d.ts.map +1 -0
  75. package/dist/state/lib/state-unit.d.ts +33 -0
  76. package/dist/state/lib/state-unit.d.ts.map +1 -0
  77. package/dist/state/lib/worker-bus.d.ts +21 -0
  78. package/dist/state/lib/worker-bus.d.ts.map +1 -0
  79. package/package.json +3 -3
package/dist/index.d.ts CHANGED
@@ -1,1759 +1,61 @@
1
- import * as rxjs from 'rxjs';
2
- import { Observable, BehaviorSubject, Subject } from 'rxjs';
3
- export { firstValueFrom, lastValueFrom } from 'rxjs';
4
- import * as _semiont_core from '@semiont/core';
5
- import { ResourceId, components, UserDID, paths, BackendDownload, ProgressEvent, AnnotationId, BodyOperation, EventMap, ResourceDescriptor, Annotation, TagSchema, GraphConnection, Motivation, GatheredContext, JobId, ITransport, EventBus, IContentTransport, IBackendOperations, BaseUrl, AccessToken, SemiontError, ConnectionState, Selector } from '@semiont/core';
6
- export { AccessToken, Annotation, AnnotationId, BaseUrl, BodyItem, BodyOperation, ConnectionState, EntityType, EventMap, GatheredContext, IContentTransport, ITransport, Logger, Motivation, RefreshToken, ResourceDescriptor, ResourceId, SemiontError, TagCategory, TagSchema, UserId, accessToken, annotationId, baseUrl, entityType, refreshToken, resourceId, userId } from '@semiont/core';
7
- export { APIError, HttpContentTransport, HttpTransport, HttpTransportConfig, TokenRefresher } from '@semiont/api-client';
8
-
9
- /**
10
- * Thenable Observable subclasses.
11
- *
12
- * Two thin Observable subclasses that also implement `PromiseLike<T>`. Used as
13
- * the public return type of namespace methods that emit streams (job
14
- * lifecycle, generation progress) and cache reads (Browse live queries).
15
- *
16
- * The point: scripts can `await` the call directly without `lastValueFrom` /
17
- * `firstValueFrom` wrappers; reactive consumers keep using `.subscribe(...)`
18
- * and `.pipe(...)` exactly as before.
19
- *
20
- * The asymmetric `.then()` semantics — last-value-on-completion for streams,
21
- * first-non-undefined-value for caches — is encoded by the subclass name. The
22
- * docstring on the namespace method tells the consumer which one applies.
23
- *
24
- * `.pipe(...)` returns a plain `Observable<T>` (RxJS doesn't propagate
25
- * subclasses through `pipe`). Once you compose, you've explicitly entered
26
- * RxJS land; `lastValueFrom` from `rxjs` is the right bridge there.
27
- */
28
-
29
- /**
30
- * Bounded Observable stream — emits zero-or-more progress values, then a
31
- * final value on completion. Used by job-lifecycle methods like
32
- * `mark.assist`, `gather.annotation`, `match.search`, `yield.fromAnnotation`.
33
- *
34
- * Awaiting resolves to the **last** emitted value (via `lastValueFrom`).
35
- * Subscribing yields every emission, ending in `complete`.
36
- */
37
- declare class StreamObservable<T> extends Observable<T> implements PromiseLike<T> {
38
- then<R1 = T, R2 = never>(onfulfilled?: ((v: T) => R1 | PromiseLike<R1>) | null, onrejected?: ((e: unknown) => R2 | PromiseLike<R2>) | null): PromiseLike<R1 | R2>;
39
- /** Wrap an existing Observable's subscribe behavior in a StreamObservable. */
40
- static from<T>(source: Observable<T>): StreamObservable<T>;
41
- }
42
- /**
43
- * Multicast cache observable — emits `undefined` while the underlying value
44
- * is loading, then the value, then re-emits when bus events invalidate the
45
- * cache entry. Used by Browse live-query methods (`browse.resource`,
46
- * `browse.annotations`, etc.).
47
- *
48
- * Awaiting resolves to the **first non-undefined** value (waits past the
49
- * loading state). Subscribing yields the full sequence including the
50
- * initial `undefined`, so reactive consumers can render a loading state.
51
- *
52
- * The class is parameterized as `CacheObservable<T>` even though the
53
- * stream's element type is `T | undefined` — `T` is what the consumer
54
- * gets from `await`, and that's the contract we want to advertise. The
55
- * `Observable<T | undefined>` shape leaks through `.subscribe` and
56
- * `.pipe` in the natural way.
57
- */
58
- declare class CacheObservable<T> extends Observable<T | undefined> implements PromiseLike<T> {
59
- then<R1 = T, R2 = never>(onfulfilled?: ((v: T) => R1 | PromiseLike<R1>) | null, onrejected?: ((e: unknown) => R2 | PromiseLike<R2>) | null): PromiseLike<R1 | R2>;
60
- /**
61
- * Wrap an existing Observable's subscribe behavior in a `CacheObservable`.
62
- *
63
- * Memoizes on source identity: passing the same `source` returns the same
64
- * wrapper instance. The Browse cache primitive already returns a stable
65
- * Observable per key (its B4 contract), so this preserves that contract
66
- * through the awaitable wrapping. Without the memo, every public-method
67
- * call would produce a fresh wrapper and break referential-equality
68
- * guarantees that hook-style reactive consumers depend on.
69
- *
70
- * Backed by a `WeakMap`, so wrappers are GC'd when their source is.
71
- */
72
- static from<T>(source: Observable<T | undefined>): CacheObservable<T>;
73
- }
74
- /**
75
- * Discriminated phases of an upload's lifecycle.
76
- *
77
- * - `started` — emitted immediately on `yield.resource(...)` invocation, before any bytes flow.
78
- * - `progress` — emitted as bytes flow over the wire. Wired by `HttpContentTransport`'s XHR path when a caller passes `onProgress` (or, transitively, when `yield.resource` is the caller — it always wires the hook so subscribers see byte counts). `bytesUploaded` and `totalBytes` carry the running counts; `totalBytes` may be 0 when the transport can't determine the total (rare, e.g. chunked encoding) — UI consumers should render an indeterminate state in that case.
79
- * - `finished` — emitted on backend acknowledgement, carries the assigned `resourceId`.
80
- *
81
- * Failures surface as `Observable.error(...)` (typically an `APIError` from the transport's `errors$` Subject), not as a `phase: 'failed'` event — `subscribe`'s error callback handles them. Cancellation is honored: unsubscribing before `finished` aborts the in-flight HTTP request on the XHR path.
82
- */
83
- type UploadProgress = {
84
- phase: 'started';
85
- totalBytes: number;
86
- } | {
87
- phase: 'progress';
88
- bytesUploaded: number;
89
- totalBytes: number;
90
- } | {
91
- phase: 'finished';
92
- resourceId: ResourceId;
93
- };
94
- /**
95
- * Specialized `StreamObservable` for `yield.resource`. Subscribers see the
96
- * full `UploadProgress` event sequence (started → optional progress → finished).
97
- * Awaiting resolves specifically to `{ resourceId }` extracted from the
98
- * `'finished'` event — preserving the pre-Phase-18 awaited shape so existing
99
- * `await client.yield.resource(...)` callers don't need to narrow the union.
100
- */
101
- declare class UploadObservable extends Observable<UploadProgress> implements PromiseLike<{
102
- resourceId: ResourceId;
103
- }> {
104
- then<R1 = {
105
- resourceId: ResourceId;
106
- }, R2 = never>(onfulfilled?: ((v: {
107
- resourceId: ResourceId;
108
- }) => R1 | PromiseLike<R1>) | null, onrejected?: ((e: unknown) => R2 | PromiseLike<R2>) | null): PromiseLike<R1 | R2>;
109
- }
110
-
111
- /**
112
- * Verb Namespace Interfaces
113
- *
114
- * These interfaces define the public API of `@semiont/sdk`, organized by
115
- * the 7 domain flows (Browse, Mark, Bind, Gather, Match, Yield, Beckon)
116
- * plus infrastructure namespaces (Job, Auth, Admin).
117
- *
118
- * Each namespace maps 1:1 to a flow. Each flow maps to a clear actor on
119
- * the backend. The frontend calls `client.mark.annotation()` and the
120
- * client handles HTTP, auth, SSE, and caching internally.
121
- *
122
- * Return type conventions:
123
- * - Browse live queries → `CacheObservable<T>` (bus-driven, cached;
124
- * subscribe yields `T | undefined`, await yields `T` after first load)
125
- * - Browse one-shot reads → `Promise<T>` (fetch once, no cache)
126
- * - Commands (mark, bind, yield.resource) → `Promise<T>` (atomic ops)
127
- * - Long-running ops (gather, match, yield.fromAnnotation, mark.assist)
128
- * → `StreamObservable<T>` (progress + result; subscribe yields every
129
- * emit, await yields the last one)
130
- * - Ephemeral signals (beckon) → `void`
131
- *
132
- * `StreamObservable` and `CacheObservable` are `Observable` subclasses
133
- * that also implement `PromiseLike<T>` — `await client.X.Y(...)` works
134
- * directly without `lastValueFrom`/`firstValueFrom` wrappers.
135
- * `.pipe(...)` returns a plain `Observable<T>` (the thenable subclass
136
- * does not propagate through pipe — by design).
137
- */
138
-
139
- type StoredEventResponse$1 = components['schemas']['StoredEventResponse'];
140
- type GatherProgress = components['schemas']['GatherProgress'];
141
- type MatchSearchResult = components['schemas']['MatchSearchResult'];
142
- type JobProgress$2 = components['schemas']['JobProgress'];
143
- type GatherAnnotationComplete = components['schemas']['GatherAnnotationComplete'];
144
- type JobStatusResponse$1 = components['schemas']['JobStatusResponse'];
145
- type AuthResponse$1 = components['schemas']['AuthResponse'];
146
- type TokenRefreshResponse$1 = components['schemas']['TokenRefreshResponse'];
147
- type OAuthConfigResponse$1 = components['schemas']['OAuthConfigResponse'];
148
- type AdminUserStatsResponse$1 = components['schemas']['AdminUserStatsResponse'];
149
- type ResponseContent<T> = T extends {
150
- responses: {
151
- 200: {
152
- content: {
153
- 'application/json': infer R;
154
- };
155
- };
156
- };
157
- } ? R : T extends {
158
- responses: {
159
- 201: {
160
- content: {
161
- 'application/json': infer R;
162
- };
163
- };
164
- };
165
- } ? R : T extends {
166
- responses: {
167
- 202: {
168
- content: {
169
- 'application/json': infer R;
170
- };
171
- };
172
- };
173
- } ? R : never;
174
- type RequestContent<T> = T extends {
175
- requestBody?: {
176
- content: {
177
- 'application/json': infer R;
178
- };
179
- };
180
- } ? R : never;
181
- /** Input for creating an annotation via mark.annotation() */
182
- type CreateAnnotationInput = components['schemas']['CreateAnnotationRequest'];
183
- /** Input for creating a resource via yield.resource() */
184
- interface CreateResourceInput {
185
- name: string;
186
- file: File | Buffer;
187
- format: string;
188
- entityTypes?: string[];
189
- language?: string;
190
- creationMethod?: string;
191
- sourceAnnotationId?: string;
192
- sourceResourceId?: string;
193
- storageUri: string;
194
- /** Prompt that drove AI generation (for AI-generated resources). */
195
- generationPrompt?: string;
196
- /** Agent(s) that generated the content (for AI-generated resources). */
197
- generator?: components['schemas']['Agent'] | components['schemas']['Agent'][];
198
- isDraft?: boolean;
199
- }
200
- /** Options for yield.fromAnnotation() */
201
- interface GenerationOptions {
202
- title: string;
203
- storageUri: string;
204
- context: GatheredContext;
205
- prompt?: string;
206
- /** Entity-type tags to stamp on the synthesized resource. Used both as a prompt bias for the generation worker and as the `entityTypes` set on the resulting resource (so `browse.resources({ entityType: ... })` queries can find it). */
207
- entityTypes?: string[];
208
- /** Annotation/resource body locale — language the generated resource is written in (typically the user's UI locale). */
209
- language?: string;
210
- /** Source-resource locale — language of the resource the annotation lives on, used in the prompt so the LLM understands embedded source-context snippets. BCP-47. */
211
- sourceLanguage?: string;
212
- temperature?: number;
213
- maxTokens?: number;
214
- }
215
- /** Options for mark.assist() */
216
- interface MarkAssistOptions {
217
- entityTypes?: string[];
218
- includeDescriptiveReferences?: boolean;
219
- instructions?: string;
220
- density?: number;
221
- tone?: string;
222
- /** Annotation body locale — language the LLM should write generated body text in (comment text, assessment text, tag/reference body language stamp). BCP-47. */
223
- language?: string;
224
- /** Source-resource locale — language of the content being analyzed, used in the prompt so the LLM analyzes non-English source correctly. BCP-47. */
225
- sourceLanguage?: string;
226
- schemaId?: string;
227
- categories?: string[];
228
- }
229
- /** Options for yield.createFromToken() */
230
- type CreateFromTokenOptions = {
231
- token: string;
232
- name: string;
233
- content: string;
234
- archiveOriginal?: boolean;
235
- };
236
- /** Referenced-by entry from browse.referencedBy() */
237
- type ReferencedByEntry = components['schemas']['GetReferencedByResponse']['referencedBy'][number];
238
- /** Annotation history from browse.annotationHistory() */
239
- type AnnotationHistoryResponse = components['schemas']['GetAnnotationHistoryResponse'];
240
- /** User object from auth/admin responses */
241
- type User = AuthResponse$1['user'];
242
- /**
243
- * Progress emitted by gather.annotation() Observable.
244
- * Emits GatherProgress during assembly, then GatherAnnotationComplete on finish.
245
- */
246
- type GatherAnnotationProgress = GatherProgress | GatherAnnotationComplete;
247
- /**
248
- * Progress emitted by match.search() Observable.
249
- * Emits the final MatchSearchResult (no intermediate progress events currently).
250
- */
251
- type MatchSearchProgress = MatchSearchResult;
252
- /**
253
- * Progress payload emitted by mark.assist() and yield.fromAnnotation()
254
- * Observables. Each progress emission carries a JobProgress snapshot
255
- * (unified job lifecycle).
256
- */
257
- type MarkAssistProgress = JobProgress$2;
258
- /**
259
- * Discriminated event yielded by the `mark.assist()` Observable. Progress
260
- * events stream while the worker runs; the final value before the
261
- * Observable completes is a `complete` event carrying the `JobCompleteCommand`
262
- * payload (with `result`, `jobId`, `jobType`, etc.). The Observable errors
263
- * on `job:fail`.
264
- */
265
- type MarkAssistEvent = {
266
- kind: 'progress';
267
- data: MarkAssistProgress;
268
- } | {
269
- kind: 'complete';
270
- data: components['schemas']['JobCompleteCommand'];
271
- };
272
- /**
273
- * Discriminated event yielded by the `yield.fromAnnotation()` Observable.
274
- * Same shape and semantics as `MarkAssistEvent`.
275
- */
276
- type YieldGenerationEvent = {
277
- kind: 'progress';
278
- data: JobProgress$2;
279
- } | {
280
- kind: 'complete';
281
- data: components['schemas']['JobCompleteCommand'];
282
- };
283
- /**
284
- * Browse — reads from materialized views
285
- *
286
- * Live queries return Observables that emit initial state and re-emit
287
- * on bus gateway updates. One-shot reads return Promises.
288
- *
289
- * Backend actor: Browser (context classes)
290
- * Event prefix: browse:*
291
- */
292
- interface BrowseNamespace$1 {
293
- resource(resourceId: ResourceId): CacheObservable<ResourceDescriptor>;
294
- resources(filters?: {
295
- limit?: number;
296
- archived?: boolean;
297
- search?: string;
298
- }): CacheObservable<ResourceDescriptor[]>;
299
- annotations(resourceId: ResourceId): CacheObservable<Annotation[]>;
300
- annotation(resourceId: ResourceId, annotationId: AnnotationId): CacheObservable<Annotation>;
301
- entityTypes(): CacheObservable<string[]>;
302
- tagSchemas(): CacheObservable<TagSchema[]>;
303
- referencedBy(resourceId: ResourceId): CacheObservable<ReferencedByEntry[]>;
304
- events(resourceId: ResourceId): CacheObservable<StoredEventResponse$1[]>;
305
- resourceContent(resourceId: ResourceId): Promise<string>;
306
- resourceRepresentation(resourceId: ResourceId, options?: {
307
- accept?: string;
308
- }): Promise<{
309
- data: ArrayBuffer;
310
- contentType: string;
311
- }>;
312
- resourceRepresentationStream(resourceId: ResourceId, options?: {
313
- accept?: string;
314
- }): Promise<{
315
- stream: ReadableStream<Uint8Array>;
316
- contentType: string;
317
- }>;
318
- resourceEvents(resourceId: ResourceId): Promise<StoredEventResponse$1[]>;
319
- annotationHistory(resourceId: ResourceId, annotationId: AnnotationId): Promise<AnnotationHistoryResponse>;
320
- connections(resourceId: ResourceId): Promise<GraphConnection[]>;
321
- backlinks(resourceId: ResourceId): Promise<Annotation[]>;
322
- resourcesByName(query: string, limit?: number): Promise<ResourceDescriptor[]>;
323
- files(dirPath?: string, sort?: 'name' | 'mtime' | 'annotationCount'): Promise<components['schemas']['BrowseFilesResponse']>;
324
- click(annotationId: AnnotationId, motivation: Motivation): void;
325
- navigateReference(resourceId: ResourceId): void;
326
- }
327
- /**
328
- * Frame — schema-layer flow (the eighth flow).
329
- *
330
- * Frame operates on the KB's conceptual vocabulary — what *kinds* of
331
- * things exist (entity types) and, in the future, what taxonomies are
332
- * recognized (tag schemas), what relations are typed (predicate types),
333
- * and how schemas are imported (ontology I/O). The other seven flows
334
- * (yield, mark, match, bind, gather, browse, beckon) operate on
335
- * content; Frame operates on the schema layer that content is expressed
336
- * in.
337
- *
338
- * MVP scope is small: entity-type vocabulary writes only. Live reads of
339
- * the entity-type vocabulary stay on Browse (`browse.entityTypes()` is
340
- * a `CacheObservable<string[]>` consumed by 8+ call sites). Frame owns
341
- * writes; Browse owns reads — the same asymmetry that already holds for
342
- * resources and annotations.
343
- *
344
- * Backend actor: Stower
345
- * Event prefix: frame:*
346
- */
347
- interface FrameNamespace$1 {
348
- /** Add a single entity type to the KB's vocabulary. Idempotent — adding an existing type is a no-op. */
349
- addEntityType(type: string): Promise<void>;
350
- /** Add multiple entity types in one call. Convenience over a loop of `addEntityType`. */
351
- addEntityTypes(types: string[]): Promise<void>;
352
- /**
353
- * Register a tag schema with the KB's runtime registry.
354
- *
355
- * Most-recent registration of a given `schema.id` wins; identical
356
- * re-registrations are silent, differing content overwrites the
357
- * existing entry and logs a warning. KBs typically call this at
358
- * session/skill startup so the schema is available for `mark.assist`
359
- * with motivation `tagging` and surfaces in `browse.tagSchemas()`.
360
- */
361
- addTagSchema(schema: TagSchema): Promise<void>;
362
- }
363
- /**
364
- * Mark — annotation CRUD, AI assist, resource lifecycle
365
- *
366
- * Commands return Promises that resolve on HTTP acceptance (202).
367
- * Results appear on browse Observables via bus gateway.
368
- * assist() returns an Observable for long-running progress.
369
- *
370
- * Backend actor: Stower
371
- * Event prefix: mark:*
372
- */
373
- interface MarkNamespace$1 {
374
- annotation(input: CreateAnnotationInput): Promise<{
375
- annotationId: AnnotationId;
376
- }>;
377
- delete(resourceId: ResourceId, annotationId: AnnotationId): Promise<void>;
378
- archive(resourceId: ResourceId): Promise<void>;
379
- unarchive(resourceId: ResourceId): Promise<void>;
380
- assist(resourceId: ResourceId, motivation: Motivation, options: MarkAssistOptions): StreamObservable<MarkAssistEvent>;
381
- request(selector: components['schemas']['MarkRequestedEvent']['selector'], motivation: Motivation): void;
382
- /** Fire-and-forget variant of `assist` — mark-state-unit orchestrates the call and its progress Observable. */
383
- requestAssist(motivation: Motivation, options: MarkAssistOptions, correlationId?: string): void;
384
- /** Submit the currently pending annotation with its selector and optional body. */
385
- submit(input: components['schemas']['MarkSubmitEvent']): void;
386
- /** Cancel the currently pending annotation (if any). */
387
- cancelPending(): void;
388
- /** Dismiss the in-progress AI-assist widget. */
389
- dismissProgress(): void;
390
- changeSelection(motivation: Motivation | null): void;
391
- changeClick(action: string): void;
392
- changeShape(shape: string): void;
393
- toggleMode(): void;
394
- }
395
- /**
396
- * Bind — reference linking
397
- *
398
- * The simplest namespace. One method. The result (updated annotation
399
- * with resolved reference) arrives on browse.annotations() via the
400
- * enriched mark:body-updated event.
401
- *
402
- * Backend actor: Stower (via mark:update-body)
403
- * Event prefix: mark:body-updated (shares mark event pipeline)
404
- */
405
- interface BindNamespace$1 {
406
- body(resourceId: ResourceId, annotationId: AnnotationId, operations: BodyOperation[]): Promise<void>;
407
- /** UI signal: a reference-binding flow is requested for an annotation. */
408
- initiate(input: EventMap['bind:initiate']): void;
409
- }
410
- /**
411
- * Gather — context assembly
412
- *
413
- * Long-running (LLM calls + graph traversal). Returns Observables
414
- * that emit progress then the gathered context.
415
- *
416
- * Backend actor: Gatherer
417
- * Event prefix: gather:*
418
- */
419
- interface GatherNamespace$1 {
420
- annotation(resourceId: ResourceId, annotationId: AnnotationId, options?: {
421
- contextWindow?: number;
422
- }): StreamObservable<GatherAnnotationProgress>;
423
- resource(resourceId: ResourceId, options?: {
424
- contextWindow?: number;
425
- }): StreamObservable<GatherAnnotationProgress>;
426
- }
427
- /**
428
- * Match — search and ranking
429
- *
430
- * Long-running (semantic search, optional LLM scoring). Returns
431
- * Observable with progress then results.
432
- *
433
- * Backend actor: Matcher
434
- * Event prefix: match:*
435
- */
436
- interface MatchNamespace$1 {
437
- search(resourceId: ResourceId, referenceId: AnnotationId, context: GatheredContext, options?: {
438
- limit?: number;
439
- useSemanticScoring?: boolean;
440
- }): StreamObservable<MatchSearchProgress>;
441
- /** Fire-and-forget variant: match-state-unit orchestrates the call and its result Observable. */
442
- requestSearch(input: components['schemas']['MatchSearchRequest']): void;
443
- }
444
- /**
445
- * Yield — resource creation
446
- *
447
- * resource() is synchronous file upload (Promise).
448
- * fromAnnotation() is long-running LLM generation (Observable).
449
- *
450
- * Backend actor: Stower + generation worker
451
- * Event prefix: yield:*
452
- */
453
- interface YieldNamespace$1 {
454
- resource(data: CreateResourceInput): UploadObservable;
455
- fromAnnotation(resourceId: ResourceId, annotationId: AnnotationId, options: GenerationOptions): StreamObservable<YieldGenerationEvent>;
456
- cloneToken(resourceId: ResourceId): Promise<{
457
- token: string;
458
- expiresAt: string;
459
- }>;
460
- fromToken(token: string): Promise<ResourceDescriptor>;
461
- createFromToken(options: CreateFromTokenOptions): Promise<{
462
- resourceId: ResourceId;
463
- }>;
464
- /** UI signal: user invoked the clone action from the resource-info panel. */
465
- clone(): void;
466
- }
467
- /**
468
- * Beckon — attention coordination
469
- *
470
- * Fire-and-forget. Ephemeral presence signal delivered via the
471
- * attention-stream to other participants.
472
- *
473
- * Backend actor: (frontend relay via attention-stream)
474
- * Event prefix: beckon:*
475
- */
476
- interface BeckonNamespace$1 {
477
- attention(resourceId: ResourceId, annotationId: AnnotationId): void;
478
- hover(annotationId: AnnotationId | null): void;
479
- sparkle(annotationId: AnnotationId): void;
480
- }
481
- /**
482
- * Job — worker lifecycle
483
- */
484
- interface JobNamespace$1 {
485
- /** Live stream of `job:queued` events from the bus. */
486
- readonly queued$: Observable<EventMap['job:queued']>;
487
- /** Live stream of `job:report-progress` events from the bus. */
488
- readonly progress$: Observable<EventMap['job:report-progress']>;
489
- /** Live stream of `job:complete` events from the bus. */
490
- readonly complete$: Observable<EventMap['job:complete']>;
491
- /** Live stream of `job:fail` events from the bus. */
492
- readonly fail$: Observable<EventMap['job:fail']>;
493
- status(jobId: JobId): Promise<JobStatusResponse$1>;
494
- pollUntilComplete(jobId: JobId, options?: {
495
- interval?: number;
496
- timeout?: number;
497
- onProgress?: (status: JobStatusResponse$1) => void;
498
- }): Promise<JobStatusResponse$1>;
499
- cancelByType(jobType: 'annotation' | 'generation'): Promise<void>;
500
- /** UI signal: cancel all active jobs of a given type (e.g. "annotation"). */
501
- cancelRequest(jobType: 'annotation' | 'generation'): void;
502
- }
503
- /**
504
- * Auth — authentication
505
- */
506
- interface AuthNamespace$1 {
507
- password(email: string, password: string): Promise<AuthResponse$1>;
508
- google(credential: string): Promise<AuthResponse$1>;
509
- refresh(token: string): Promise<TokenRefreshResponse$1>;
510
- logout(): Promise<void>;
511
- me(): Promise<User>;
512
- acceptTerms(): Promise<void>;
513
- mcpToken(): Promise<{
514
- token: string;
515
- }>;
516
- mediaToken(resourceId: ResourceId): Promise<{
517
- token: string;
518
- }>;
519
- }
520
- /**
521
- * Admin — administration
522
- */
523
- interface AdminNamespace$1 {
524
- users(): Promise<User[]>;
525
- userStats(): Promise<AdminUserStatsResponse$1>;
526
- updateUser(userId: UserDID, data: RequestContent<paths['/api/admin/users/{id}']['patch']>): Promise<User>;
527
- oauthConfig(): Promise<OAuthConfigResponse$1>;
528
- healthCheck(): Promise<ResponseContent<paths['/api/health']['get']>>;
529
- status(): Promise<ResponseContent<paths['/api/status']['get']>>;
530
- backup(): Promise<BackendDownload>;
531
- /**
532
- * Restore from a backup archive. Returns a `StreamObservable` that
533
- * emits each `ProgressEvent` as the operation runs (`'started'`,
534
- * `'parsing'`, `'importing'`, ..., `'complete'`). Subscribers see
535
- * every step; awaiters get the final event via the PromiseLike sugar.
536
- */
537
- restore(file: File): StreamObservable<ProgressEvent>;
538
- exportKnowledgeBase(params?: {
539
- includeArchived?: boolean;
540
- }): Promise<BackendDownload>;
541
- importKnowledgeBase(file: File): StreamObservable<ProgressEvent>;
542
- }
543
-
544
- type StoredEventResponse = components['schemas']['StoredEventResponse'];
545
- type ResourceListFilters = {
546
- limit?: number;
547
- archived?: boolean;
548
- search?: string;
549
- };
550
- declare class BrowseNamespace implements BrowseNamespace$1 {
551
- private readonly transport;
552
- private readonly bus;
553
- private readonly content;
554
- private readonly resourceCache;
555
- private readonly resourceListCache;
556
- private readonly annotationListCache;
557
- /**
558
- * Annotation-detail cache keyed by `annotationId` only — the resourceId
559
- * is a routing hint for the backend fetch, not an identity component.
560
- * We track the most recent resourceId per annotationId in a side-map
561
- * so `mark:delete-ok` (which carries only `annotationId`) can reach
562
- * the right cache entry. Aligns with the pre-refactor semantics.
563
- */
564
- private readonly annotationDetailCache;
565
- private readonly annotationResources;
566
- private readonly entityTypesCache;
567
- private readonly tagSchemasCache;
568
- private readonly referencedByCache;
569
- private readonly resourceEventsCache;
570
- /** Filter-blob memory so `invalidateResourceLists` can replay per-key. */
571
- private readonly resourceListFilters;
572
- /**
573
- * Per-key memo for `annotations()` observables. The cache stores the
574
- * full `AnnotationsListResponse`; the public shape is just the inner
575
- * `Annotation[]`. Without this memo, every call to `annotations(rId)`
576
- * would produce a fresh `.pipe(map(...))` observable, violating B4
577
- * (per-key observable stability). Consumers that compare observable
578
- * identity — React hooks depending on the observable reference,
579
- * `distinctUntilChanged` at a higher level — would misbehave.
580
- */
581
- private readonly annotationListObs;
582
- constructor(transport: ITransport, bus: EventBus, content: IContentTransport);
583
- resource(resourceId: ResourceId): CacheObservable<ResourceDescriptor>;
584
- resources(filters?: ResourceListFilters): CacheObservable<ResourceDescriptor[]>;
585
- annotations(resourceId: ResourceId): CacheObservable<Annotation[]>;
586
- annotation(resourceId: ResourceId, annotationId: AnnotationId): CacheObservable<Annotation>;
587
- entityTypes(): CacheObservable<string[]>;
588
- tagSchemas(): CacheObservable<TagSchema[]>;
589
- referencedBy(resourceId: ResourceId): CacheObservable<ReferencedByEntry[]>;
590
- events(resourceId: ResourceId): CacheObservable<StoredEventResponse[]>;
591
- resourceContent(resourceId: ResourceId): Promise<string>;
592
- resourceRepresentation(resourceId: ResourceId, options?: {
593
- accept?: string;
594
- }): Promise<{
595
- data: ArrayBuffer;
596
- contentType: string;
597
- }>;
598
- resourceRepresentationStream(resourceId: ResourceId, options?: {
599
- accept?: string;
600
- }): Promise<{
601
- stream: ReadableStream<Uint8Array>;
602
- contentType: string;
603
- }>;
604
- resourceEvents(resourceId: ResourceId): Promise<StoredEventResponse[]>;
605
- annotationHistory(resourceId: ResourceId, annotationId: AnnotationId): Promise<AnnotationHistoryResponse>;
606
- connections(_resourceId: ResourceId): Promise<GraphConnection[]>;
607
- backlinks(_resourceId: ResourceId): Promise<Annotation[]>;
608
- resourcesByName(_query: string, _limit?: number): Promise<ResourceDescriptor[]>;
609
- files(dirPath?: string, sort?: 'name' | 'mtime' | 'annotationCount'): Promise<components['schemas']['BrowseFilesResponse']>;
610
- click(annotationId: AnnotationId, motivation: Motivation): void;
611
- navigateReference(resourceId: ResourceId): void;
612
- invalidateAnnotationList(resourceId: ResourceId): void;
613
- removeAnnotationDetail(annotationId: AnnotationId): void;
614
- invalidateResourceDetail(id: ResourceId): void;
615
- invalidateResourceLists(): void;
616
- invalidateEntityTypes(): void;
617
- invalidateTagSchemas(): void;
618
- invalidateReferencedBy(resourceId: ResourceId): void;
619
- invalidateResourceEvents(resourceId: ResourceId): void;
620
- updateAnnotationInPlace(resourceId: ResourceId, annotation: Annotation): void;
621
- /**
622
- * Typed shorthand for `eventBus.get(channel).subscribe(handler)`.
623
- * Preserves per-channel payload typing so handlers read
624
- * `EventMap[K]` without any casts.
625
- */
626
- private on;
627
- /**
628
- * Handler shared by `mark:entity-tag-added` and `mark:entity-tag-removed`.
629
- * Both events carry the same effect: the annotation list, the
630
- * resource descriptor, and the event log for that resource all may
631
- * now reflect different entity tagging, so invalidate all three.
632
- */
633
- private onEntityTagChanged;
634
- /**
635
- * Handler shared by `mark:archived` and `mark:unarchived`. Both
636
- * change a resource's archived flag, which is stored on the resource
637
- * descriptor and affects the resource-list filter.
638
- */
639
- private onArchiveToggled;
640
- /**
641
- * Handler shared by `yield:create-ok` and `yield:update-ok`. Both
642
- * report a resource mutation with the resourceId as a string (not
643
- * yet branded), so we brand and apply the same effect as
644
- * `onArchiveToggled`.
645
- */
646
- private onYieldResourceMutated;
647
- private subscribeToEvents;
648
- }
649
-
650
- declare class MarkNamespace implements MarkNamespace$1 {
651
- private readonly transport;
652
- private readonly bus;
653
- constructor(transport: ITransport, bus: EventBus);
654
- annotation(input: CreateAnnotationInput): Promise<{
655
- annotationId: AnnotationId;
656
- }>;
657
- delete(resourceId: ResourceId, annotationId: AnnotationId): Promise<void>;
658
- archive(resourceId: ResourceId): Promise<void>;
659
- unarchive(resourceId: ResourceId): Promise<void>;
660
- assist(resourceId: ResourceId, motivation: Motivation, options: MarkAssistOptions): StreamObservable<MarkAssistEvent>;
661
- request(selector: components['schemas']['MarkRequestedEvent']['selector'], motivation: Motivation): void;
662
- requestAssist(motivation: Motivation, options: MarkAssistOptions, correlationId?: string): void;
663
- submit(input: components['schemas']['MarkSubmitEvent']): void;
664
- cancelPending(): void;
665
- dismissProgress(): void;
666
- changeSelection(motivation: Motivation | null): void;
667
- changeClick(action: string): void;
668
- changeShape(shape: string): void;
669
- toggleMode(): void;
670
- private dispatchAssist;
671
- }
672
-
673
- declare class BindNamespace implements BindNamespace$1 {
674
- private readonly transport;
675
- private readonly bus;
676
- constructor(transport: ITransport, bus: EventBus);
677
- body(resourceId: ResourceId, annotationId: AnnotationId, operations: BodyOperation[]): Promise<void>;
678
- initiate(input: EventMap['bind:initiate']): void;
679
- }
680
-
681
- declare class GatherNamespace implements GatherNamespace$1 {
682
- private readonly transport;
683
- private readonly bus;
684
- constructor(transport: ITransport, bus: EventBus);
685
- annotation(resourceId: ResourceId, annotationId: AnnotationId, options?: {
686
- contextWindow?: number;
687
- }): StreamObservable<GatherAnnotationProgress>;
688
- resource(_resourceId: ResourceId, _options?: {
689
- contextWindow?: number;
690
- }): StreamObservable<GatherAnnotationProgress>;
691
- }
692
-
693
- declare class MatchNamespace implements MatchNamespace$1 {
694
- private readonly transport;
695
- private readonly bus;
696
- constructor(transport: ITransport, bus: EventBus);
697
- requestSearch(input: components['schemas']['MatchSearchRequest']): void;
698
- search(resourceId: ResourceId, referenceId: AnnotationId, context: GatheredContext, options?: {
699
- limit?: number;
700
- useSemanticScoring?: boolean;
701
- }): StreamObservable<MatchSearchProgress>;
702
- }
703
-
704
- declare class YieldNamespace implements YieldNamespace$1 {
705
- private readonly transport;
706
- private readonly bus;
707
- private readonly content;
708
- constructor(transport: ITransport, bus: EventBus, content: IContentTransport);
709
- resource(data: CreateResourceInput): UploadObservable;
710
- fromAnnotation(resourceId: ResourceId, annotationId: AnnotationId, options: GenerationOptions): StreamObservable<YieldGenerationEvent>;
711
- cloneToken(resourceId: ResourceId): Promise<{
712
- token: string;
713
- expiresAt: string;
714
- }>;
715
- fromToken(token: string): Promise<ResourceDescriptor>;
716
- createFromToken(options: CreateFromTokenOptions): Promise<{
717
- resourceId: ResourceId;
718
- }>;
719
- clone(): void;
720
- }
721
-
722
- declare class BeckonNamespace implements BeckonNamespace$1 {
723
- private readonly transport;
724
- private readonly bus;
725
- constructor(transport: ITransport, bus: EventBus);
726
- attention(resourceId: ResourceId, annotationId: AnnotationId): void;
727
- hover(annotationId: AnnotationId | null): void;
728
- sparkle(annotationId: AnnotationId): void;
729
- }
730
-
731
- /**
732
- * FrameNamespace — the eighth flow's surface.
733
- *
734
- * Frame operates on the KB's **schema layer** — the conceptual vocabulary
735
- * the other seven flows are expressed in. Where yield/mark/match/bind/
736
- * gather/browse/beckon act on content (resources, annotations, references,
737
- * attention), Frame acts on what *kinds* of things exist: entity types,
738
- * eventually tag schemas, relation/predicate types, ontology imports.
739
- *
740
- * The MVP owns a single primitive — entity-type vocabulary writes on the
741
- * `frame:add-entity-type` channel. See `docs/protocol/flows/FRAME.md`
742
- * for the per-flow contract.
743
- *
744
- * Live reads of the entity-type vocabulary stay on Browse
745
- * (`browse.entityTypes()` is a `CacheObservable<string[]>`). Frame owns
746
- * writes; Browse owns reads. The asymmetry is intentional — re-implementing
747
- * Browse's cache primitives on Frame for a single read would duplicate
748
- * machinery without benefit.
749
- */
750
-
751
- declare class FrameNamespace implements FrameNamespace$1 {
752
- private readonly transport;
753
- constructor(transport: ITransport);
754
- addEntityType(type: string): Promise<void>;
755
- addEntityTypes(types: string[]): Promise<void>;
756
- addTagSchema(schema: TagSchema): Promise<void>;
757
- }
758
-
759
- type JobStatusResponse = components['schemas']['JobStatusResponse'];
760
- declare class JobNamespace implements JobNamespace$1 {
761
- private readonly transport;
762
- private readonly bus;
763
- constructor(transport: ITransport, bus: EventBus);
764
- /**
765
- * Live stream of `job:queued` events. Surfaces a typed view onto the
766
- * underlying bus channel for consumers (CLIs, MCP handlers, widgets)
767
- * that orchestrate jobs and need to react to lifecycle transitions.
768
- */
769
- get queued$(): Observable<EventMap['job:queued']>;
770
- /** Live stream of `job:report-progress` events. */
771
- get progress$(): Observable<EventMap['job:report-progress']>;
772
- /** Live stream of `job:complete` events. */
773
- get complete$(): Observable<EventMap['job:complete']>;
774
- /** Live stream of `job:fail` events. */
775
- get fail$(): Observable<EventMap['job:fail']>;
776
- status(jobId: JobId): Promise<JobStatusResponse>;
777
- pollUntilComplete(jobId: JobId, options?: {
778
- interval?: number;
779
- timeout?: number;
780
- onProgress?: (status: JobStatusResponse) => void;
781
- }): Promise<JobStatusResponse>;
782
- cancelByType(jobType: 'annotation' | 'generation'): Promise<void>;
783
- cancelRequest(jobType: 'annotation' | 'generation'): void;
784
- }
785
-
786
- /**
787
- * AuthNamespace — authentication. Backend ops only; no bus.
788
- */
789
-
790
- type AuthResponse = components['schemas']['AuthResponse'];
791
- type TokenRefreshResponse = components['schemas']['TokenRefreshResponse'];
792
- declare class AuthNamespace implements AuthNamespace$1 {
793
- private readonly backend;
794
- constructor(backend: IBackendOperations);
795
- password(emailStr: string, passwordStr: string): Promise<AuthResponse>;
796
- google(credential: string): Promise<AuthResponse>;
797
- refresh(token: string): Promise<TokenRefreshResponse>;
798
- logout(): Promise<void>;
799
- me(): Promise<User>;
800
- acceptTerms(): Promise<void>;
801
- mcpToken(): Promise<{
802
- token: string;
803
- }>;
804
- mediaToken(resourceId: ResourceId): Promise<{
805
- token: string;
806
- }>;
807
- }
808
-
809
1
  /**
810
- * AdminNamespace — administration. Backend ops only; no bus.
811
- */
812
-
813
- type AdminUserStatsResponse = components['schemas']['AdminUserStatsResponse'];
814
- type OAuthConfigResponse = components['schemas']['OAuthConfigResponse'];
815
- declare class AdminNamespace implements AdminNamespace$1 {
816
- private readonly backend;
817
- constructor(backend: IBackendOperations);
818
- users(): Promise<User[]>;
819
- userStats(): Promise<AdminUserStatsResponse>;
820
- updateUser(userId: UserDID, data: RequestContent<paths['/api/admin/users/{id}']['patch']>): Promise<User>;
821
- oauthConfig(): Promise<OAuthConfigResponse>;
822
- healthCheck(): Promise<ResponseContent<paths['/api/health']['get']>>;
823
- status(): Promise<ResponseContent<paths['/api/status']['get']>>;
824
- backup(): Promise<BackendDownload>;
825
- restore(file: File): StreamObservable<ProgressEvent>;
826
- exportKnowledgeBase(params?: {
827
- includeArchived?: boolean;
828
- }): Promise<BackendDownload>;
829
- importKnowledgeBase(file: File): StreamObservable<ProgressEvent>;
830
- }
831
-
832
- declare class SemiontClient {
833
- /**
834
- * The wire-facing transport. Owns bus actor, HTTP, auth, admin, exchange,
835
- * system. Exposed for advanced consumers (workers, custom job adapters)
836
- * that need raw `transport.emit(channel, payload, scope)` access. Ordinary
837
- * consumers go through typed namespace methods.
838
- */
839
- readonly transport: ITransport;
840
- /** Binary I/O transport. */
841
- private readonly content;
842
- /**
843
- * Per-client local EventBus. Wire events flow in via the transport
844
- * bridge. Read-only public so `SemiontSession.subscribe(channel, …)`
845
- * can wire arbitrary-channel subscriptions; everything else uses
846
- * typed namespace methods.
847
- */
848
- readonly bus: EventBus;
849
- readonly baseUrl: BaseUrl;
850
- readonly frame: FrameNamespace;
851
- readonly browse: BrowseNamespace;
852
- readonly mark: MarkNamespace;
853
- readonly bind: BindNamespace;
854
- readonly gather: GatherNamespace;
855
- readonly match: MatchNamespace;
856
- readonly yield: YieldNamespace;
857
- readonly beckon: BeckonNamespace;
858
- readonly job: JobNamespace;
859
- readonly auth: AuthNamespace | undefined;
860
- readonly admin: AdminNamespace | undefined;
861
- /**
862
- * The client *owns* its bus. The constructor creates a fresh `EventBus`
863
- * and hands it to the transport via `transport.bridgeInto(this.bus)`.
864
- * The reference flows client → transport, never the other way:
865
- * the transport stores the reference and publishes the events it
866
- * receives onto that bus. `HttpTransport` does so for every channel
867
- * delivered on its SSE wire; in-process transports adapt their
868
- * internal source.
869
- *
870
- * Callers do not pass a bus in. If they need to interact with the bus
871
- * (e.g. for tests or to subscribe to arbitrary channels), they read it
872
- * back via `client.bus`.
873
- *
874
- * `backend` is optional. When provided, the `auth` and `admin`
875
- * namespaces are constructed against it; when omitted, they're
876
- * `undefined`. For HTTP setups this is conventionally the same
877
- * `HttpTransport` instance that's also passed as `transport` (HTTP
878
- * implements both `ITransport` and `IBackendOperations`).
879
- */
880
- constructor(transport: ITransport, content: IContentTransport, backend?: IBackendOperations);
881
- /** Transport-level connection state. HTTP reflects SSE health; local is always 'connected'. */
882
- get state$(): rxjs.Observable<_semiont_core.ConnectionState>;
883
- subscribeToResource(resourceId: ResourceId): () => void;
884
- dispose(): void;
885
- /**
886
- * Convenience factory for the default HTTP setup. Constructs a
887
- * `BehaviorSubject<AccessToken | null>` internally, plus an
888
- * `HttpTransport` and `HttpContentTransport`, and returns the wired
889
- * `SemiontClient`.
890
- *
891
- * Use this for one-shot scripts, CLI commands, or any consumer that
892
- * doesn't need to drive the token from outside (no manual refresh,
893
- * no cross-tab sync). For long-running scripts that need refresh,
894
- * use `SemiontSession.fromHttp(...)` (with a token already on hand)
895
- * or `SemiontSession.signInHttp(...)` (credentials-first) instead —
896
- * either owns the same transport/client wiring plus the
897
- * proactive-refresh + storage machinery.
898
- *
899
- * Strings are accepted for `baseUrl` and `token`; they are branded
900
- * via `baseUrl()` / `accessToken()` from `@semiont/core` automatically.
901
- * Pass the already-branded values if you have them.
902
- *
903
- * Omit `token` for unauthenticated usage (public endpoints only).
904
- */
905
- static fromHttp(opts: {
906
- baseUrl: BaseUrl | string;
907
- token?: AccessToken | string | null;
908
- }): SemiontClient;
909
- /**
910
- * Async factory for the credentials-first script case. Builds a
911
- * transient HTTP transport, calls `auth.password(email, password)`
912
- * to acquire an access token, and returns the wired client with
913
- * the token populated.
914
- *
915
- * This is the right entry point for skills, CLI scripts, and any
916
- * consumer that starts with email + password rather than a JWT
917
- * already on hand. For consumers that already hold a token (CLI
918
- * cached-token path, env-var token, embedded auth flow), use
919
- * `fromHttp({ baseUrl, token })` instead.
920
- *
921
- * For long-running scripts that need refresh, use
922
- * `SemiontSession.signInHttp(...)` — same credentials shape, plus
923
- * the session machinery for proactive refresh and persistence.
924
- *
925
- * Named `signInHttp` because email+password authentication is
926
- * inherently an HTTP-shaped operation in the current backend; an
927
- * in-process `LocalTransport` doesn't have a credentials login
928
- * path. Non-HTTP transports construct the client directly from
929
- * their package's transport instance.
930
- *
931
- * Throws if authentication fails. The transient client is disposed
932
- * before the throw, so no resources leak on failure.
933
- */
934
- static signInHttp(opts: {
935
- baseUrl: BaseUrl | string;
936
- email: string;
937
- password: string;
938
- }): Promise<SemiontClient>;
939
- }
940
-
941
- type BusRequestErrorCode = 'bus.timeout' | 'bus.rejected' | 'bus.bad-payload' | 'bus.unauthorized' | 'bus.forbidden' | 'bus.not-found';
942
- declare class BusRequestError extends SemiontError {
943
- code: BusRequestErrorCode;
944
- constructor(message: string, code: BusRequestErrorCode, details?: Record<string, unknown>);
945
- }
946
- /**
947
- * Subset of ITransport that `busRequest` needs: a way to send a command and
948
- * a way to observe channels. Generic enough that an in-process transport
949
- * can satisfy it without round-tripping through HTTP.
950
- */
951
- interface BusRequestPrimitive {
952
- emit<K extends keyof EventMap>(channel: K, payload: EventMap[K]): Promise<void>;
953
- stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;
954
- }
955
- declare function busRequest<TResult>(bus: BusRequestPrimitive, emitChannel: string, payload: Record<string, unknown>, resultChannel: string, failureChannel: string, timeoutMs?: number): Promise<TResult>;
956
-
957
- /**
958
- * KnowledgeBase — a connection to a Semiont knowledge system.
959
- *
960
- * The KB type itself is uniform. The transport-shape variation lives in
961
- * the nested `endpoint` field, which is a discriminated union:
2
+ * @semiont/sdk
962
3
  *
963
- * - `endpoint.kind === 'http'` a remote backend reached over HTTP+SSE.
964
- * Carries `host`/`port`/`protocol`.
965
- * - `endpoint.kind === 'local'` an in-process knowledge system reached
966
- * via `LocalTransport` from
967
- * `@semiont/make-meaning`. Carries an
968
- * opaque `kbId` identifying the local
969
- * instance to the host process.
4
+ * The Semiont SDK `SemiontClient`, the verb-oriented namespaces, the
5
+ * per-tab session layer, the flow state machines and worker adapters,
6
+ * and the supporting helpers (`bus-request`, `cache`).
970
7
  *
971
- * Code that doesn't know how to make a transport (`SemiontSession`,
972
- * `SemiontBrowser`, the frontend KB list UI) treats `KnowledgeBase` as
973
- * uniform and never inspects `endpoint`. Code that *does* construct
974
- * transports (the transport-factory passed to `SemiontBrowser`,
975
- * `kbBackendUrl` for HTTP URL construction) inspects `endpoint.kind`
976
- * and dispatches.
8
+ * Transport-agnostic: `SemiontClient` consumes the `ITransport` /
9
+ * `IContentTransport` contracts from `@semiont/core`. The HTTP adapters
10
+ * (`HttpTransport`, `HttpContentTransport`) are re-exported here for
11
+ * convenience so the common case is a single import; non-HTTP transports
12
+ * (e.g. `LocalTransport` from `@semiont/make-meaning`) are constructed
13
+ * by the caller from their own package.
977
14
  *
978
- * Each KB has its own session, its own credentials (where applicable),
979
- * and its own JWT (HTTP only). The user is "authenticated against KB X" —
980
- * never globally authenticated.
981
- */
982
- /** Fields shared by every KB regardless of endpoint kind. */
983
- interface KnowledgeBase {
984
- id: string;
985
- label: string;
986
- email: string;
987
- gitBranch?: string;
988
- endpoint: KbEndpoint;
989
- }
990
- type KbEndpoint = HttpEndpoint | LocalEndpoint;
991
- interface HttpEndpoint {
992
- kind: 'http';
993
- host: string;
994
- port: number;
995
- protocol: 'http' | 'https';
996
- }
997
- interface LocalEndpoint {
998
- kind: 'local';
999
- /** Opaque identifier for the in-process KB instance the host has loaded. */
1000
- kbId: string;
1001
- }
1002
- /**
1003
- * Input shape for adding a new KB. The id is generated by the provider.
1004
- */
1005
- type NewKnowledgeBase = Omit<KnowledgeBase, 'id'>;
1006
- /**
1007
- * Status of the locally-stored credential for a KB. Derived from the
1008
- * presence and validity of the JWT in session storage.
1009
- */
1010
- type KbSessionStatus = 'authenticated' | 'expired' | 'signed-out' | 'unreachable';
1011
- /**
1012
- * Construct a `KnowledgeBase` for an HTTP-backed Semiont backend without
1013
- * spelling out the nested `endpoint` literal. Convenience for tests,
1014
- * worker bootstraps, and one-off scripts.
15
+ * Transport-specific error classes (`APIError` from `@semiont/api-client`)
16
+ * are NOT re-exported. Catch on `SemiontError` (exported below) and route
17
+ * on `err.code`; reach for the transport-specific class only when you're
18
+ * already in HTTP-aware code and import it from `@semiont/api-client`
19
+ * directly.
1015
20
  *
1016
21
  * ```ts
1017
- * const kb = httpKb({
1018
- * id: 'my-watcher',
1019
- * label: 'My Watcher',
1020
- * email: 'me@example.com',
1021
- * host: 'localhost',
1022
- * port: 4000,
1023
- * protocol: 'http',
1024
- * });
1025
- * ```
1026
- *
1027
- * Equivalent to:
22
+ * import { SemiontClient, HttpTransport, HttpContentTransport } from '@semiont/sdk';
23
+ * import { baseUrl } from '@semiont/core';
1028
24
  *
1029
- * ```ts
1030
- * const kb: KnowledgeBase = {
1031
- * id, label, email,
1032
- * endpoint: { kind: 'http', host, port, protocol },
1033
- * };
25
+ * const transport = new HttpTransport({ baseUrl: baseUrl('https://kb.example/') });
26
+ * // HttpTransport implements both ITransport and IBackendOperations;
27
+ * // passing it as the third arg wires `client.auth` and `client.admin`.
28
+ * const client = new SemiontClient(transport, new HttpContentTransport(transport), transport);
1034
29
  * ```
1035
- *
1036
- * UI hosts that have a structured form (host / port / protocol pickers)
1037
- * already construct the literal directly — they don't need this helper.
1038
- * Local-endpoint KBs construct the literal directly too; the local
1039
- * endpoint shape (`{ kind: 'local', kbId }`) is one line and doesn't
1040
- * earn a helper.
1041
- */
1042
- declare function httpKb(opts: {
1043
- id: string;
1044
- label: string;
1045
- email: string;
1046
- host: string;
1047
- port: number;
1048
- protocol: 'http' | 'https';
1049
- gitBranch?: string;
1050
- }): KnowledgeBase;
1051
-
1052
- /**
1053
- * Session-level error surface. Emitted on `SemiontBrowser.error$` for
1054
- * failures that make the session itself unusable (auth failed, actor
1055
- * couldn't start, token refresh terminally exhausted). Per-request
1056
- * errors stay with the caller as normal Promise rejections.
1057
- *
1058
- * `SemiontSessionError` extends `SemiontError` (the unified Semiont base)
1059
- * so consumers can catch with `instanceof SemiontError` for any error
1060
- * surfaced through the SDK.
1061
- */
1062
-
1063
- type SemiontSessionErrorCode = 'session.construct-failed' | 'session.auth-failed' | 'session.refresh-exhausted' | 'browser.sign-in-failed';
1064
- declare class SemiontSessionError extends SemiontError {
1065
- code: SemiontSessionErrorCode;
1066
- readonly kbId: string | null;
1067
- constructor(code: SemiontSessionErrorCode, message: string, kbId?: string | null);
1068
- }
1069
-
1070
- /**
1071
- * SessionStorage — environment-agnostic persistence adapter for the
1072
- * Semiont session layer. Decouples `SemiontSession` / `SemiontBrowser`
1073
- * from `localStorage` / `window` so the same classes can run in a
1074
- * browser, a CLI process, or tests without environment guards.
1075
- *
1076
- * Implementations shipped here:
1077
- * - `InMemorySessionStorage` — map-backed, for tests.
1078
- *
1079
- * Browser-backed (`WebBrowserStorage`) lives in `@semiont/react-ui`
1080
- * because it touches browser-only globals.
1081
- */
1082
- /** String key/value store with optional cross-context change subscription. */
1083
- interface SessionStorage {
1084
- /** Read a string value; null if absent. */
1085
- get(key: string): string | null;
1086
- /** Write a string value. */
1087
- set(key: string, value: string): void;
1088
- /** Remove a key. No-op if absent. */
1089
- delete(key: string): void;
1090
- /**
1091
- * Optional: subscribe to external changes (cross-tab, cross-process).
1092
- * Browser implements via the `storage` event; filesystem would use
1093
- * fs.watch; in-memory omits this method. Returns an unsubscribe
1094
- * callback. If omitted, cross-context sync simply isn't available
1095
- * in that environment — the session still works correctly within a
1096
- * single process.
1097
- */
1098
- subscribe?(handler: (key: string, newValue: string | null) => void): () => void;
1099
- }
1100
- /**
1101
- * Map-backed `SessionStorage`. Cross-context sync is not implemented;
1102
- * tests that need it can drive it manually.
1103
- */
1104
- declare class InMemorySessionStorage implements SessionStorage {
1105
- private readonly map;
1106
- get(key: string): string | null;
1107
- set(key: string, value: string): void;
1108
- delete(key: string): void;
1109
- }
1110
-
1111
- /**
1112
- * SemiontSession — per-backend session lifetime object. Owns the
1113
- * SemiontClient, the access token BehaviorSubject, and optionally
1114
- * an authenticated user. One SemiontSession exists per active backend
1115
- * connection; lifetime is decoupled from React mount lifetime.
1116
- *
1117
- * Headless by design. Runs in browsers, CLIs, workers, and tests.
1118
- * UI-specific state (session-expired/permission-denied modals) lives
1119
- * in `SessionSignals`, which wraps a session — the session
1120
- * itself has no modal observables, no user-facing notifications.
1121
- *
1122
- * Auth is parameterized via callbacks passed at construction:
1123
- *
1124
- * - `refresh()` — invoked on 401 / proactive re-auth. Returns the
1125
- * new access token, or null on failure. The frontend passes a
1126
- * closure that runs the refresh-token flow; the worker passes
1127
- * one that exchanges the shared secret.
1128
- *
1129
- * - `validate(token)` — optional. If provided, the session calls
1130
- * it once at startup with the stored token to confirm it's
1131
- * still good and populate `user$`. Frontend passes `getMe`;
1132
- * worker omits this (service principals have no user record).
1133
- *
1134
- * - `onAuthFailed(message)` — optional. Invoked when refresh
1135
- * terminally fails (expired token, no recovery possible). UI hosts
1136
- * typically wire this to `SessionSignals.notifySessionExpired` so a
1137
- * modal surfaces; headless consumers typically just log.
1138
- *
1139
- * Persistence goes through a `SessionStorage` adapter provided at
1140
- * construction — the session never touches `localStorage` or `window`
1141
- * directly.
1142
- */
1143
-
1144
- type UserInfo = components['schemas']['UserResponse'];
1145
- interface SemiontSessionConfig {
1146
- kb: KnowledgeBase;
1147
- /** Persistence adapter. Reads/writes tokens via this. */
1148
- storage: SessionStorage;
1149
- /**
1150
- * Pre-built api client. The session does not construct it — caller
1151
- * builds the transport stack and passes the client in. This is the
1152
- * seam where consumers swap one `ITransport` implementation for
1153
- * another (HTTP, in-process, etc.).
1154
- */
1155
- client: SemiontClient;
1156
- /**
1157
- * Token observable shared with the transport. Caller must pass the
1158
- * SAME instance to both the transport (via `HttpTransport` config)
1159
- * and the session. The session writes refreshed tokens here; the
1160
- * transport reads from here.
1161
- */
1162
- token$: BehaviorSubject<AccessToken | null>;
1163
- /**
1164
- * Re-authenticate after expiry / 401. Returns a new access token
1165
- * (no "Bearer " prefix) on success, or null if recovery is
1166
- * impossible. Omit for transports where tokens don't apply.
1167
- */
1168
- refresh?: () => Promise<string | null>;
1169
- /**
1170
- * Validate the stored token at startup and populate `user$`. Omit
1171
- * for service-principal sessions (worker, CLI tools) where there
1172
- * is no user record to fetch.
1173
- */
1174
- validate?: (token: AccessToken) => Promise<UserInfo | null>;
1175
- /**
1176
- * Invoked when refresh terminally fails. Frontend consumers wire
1177
- * this to a UI signal that surfaces the session-expired modal.
1178
- */
1179
- onAuthFailed?: (message: string | null) => void;
1180
- /** Called for session-level failures (auth, refresh exhaustion). */
1181
- onError?: (err: SemiontSessionError) => void;
1182
- }
1183
- declare class SemiontSession {
1184
- readonly kb: KnowledgeBase;
1185
- readonly client: SemiontClient;
1186
- readonly token$: BehaviorSubject<AccessToken | null>;
1187
- readonly user$: BehaviorSubject<UserInfo | null>;
1188
- readonly streamState$: Observable<ConnectionState>;
1189
- /**
1190
- * Stream of `SemiontError` instances surfaced by the underlying transport
1191
- * just before they're thrown to the caller. For `HttpTransport` this is
1192
- * an `APIError` (status-coded); other transports emit their own subclass.
1193
- * Surfaced here so a host layer (e.g. `SemiontBrowser`) can route by
1194
- * `err.code` to global notifications without every call site handling
1195
- * errors itself. Headless consumers can subscribe for logging.
1196
- *
1197
- * Re-published from `client.transport.errors$` per the `ITransport`
1198
- * contract — the session is purely a passthrough.
1199
- */
1200
- readonly errors$: Observable<SemiontError>;
1201
- /** Resolves after the initial validation round-trip completes (success or failure). */
1202
- readonly ready: Promise<void>;
1203
- private readonly storage;
1204
- private readonly doRefresh?;
1205
- private readonly doValidate?;
1206
- private readonly onAuthFailed;
1207
- private readonly onError;
1208
- private refreshTimer;
1209
- private unsubscribeStorage;
1210
- private disposed;
1211
- constructor(config: SemiontSessionConfig);
1212
- /**
1213
- * Run the initial mount-time validation. If a stored access token is
1214
- * present and unexpired, call the configured `validate` with it to
1215
- * confirm it still works and populate `user$`. If expired, try
1216
- * refresh first. On 401 from validate, try refresh once. Surfaces
1217
- * auth-failed on terminal failure.
1218
- *
1219
- * When no `validate` callback is provided (service principals), this
1220
- * still runs through the refresh-if-expired step so the stored
1221
- * token is current — it just skips the user-validation round trip.
1222
- */
1223
- private validate;
1224
- /**
1225
- * Refresh the access token via the configured `refresh` callback.
1226
- * On success, pushes the new token into `token$` and schedules the
1227
- * next proactive refresh. On failure, clears persisted state and
1228
- * fires `onAuthFailed` — the frontend's wiring of that callback is
1229
- * what surfaces the session-expired modal.
1230
- */
1231
- refresh(): Promise<AccessToken | null>;
1232
- private scheduleProactiveRefresh;
1233
- private clearRefreshTimer;
1234
- /**
1235
- * Cross-context sync: another tab/process refreshed or signed out this
1236
- * KB. Mirror the change into our in-memory state.
1237
- */
1238
- private handleStorageChange;
1239
- get expiresAt(): Date | null;
1240
- /**
1241
- * Subscribe to a session-bus channel. The single sanctioned escape hatch
1242
- * for generic-channel subscription (the case `useEventSubscription` needs
1243
- * — channel name is a hook parameter, not known statically). All other
1244
- * consumers must call typed namespace methods (e.g. `session.client.mark.archive(...)`).
1245
- *
1246
- * @returns disposer that unsubscribes the handler.
1247
- */
1248
- subscribe<K extends keyof EventMap>(channel: K, handler: (payload: EventMap[K]) => void): () => void;
1249
- dispose(): Promise<void>;
1250
- /**
1251
- * Convenience factory for the default HTTP setup. Constructs the
1252
- * shared `BehaviorSubject<AccessToken | null>`, an `HttpTransport`,
1253
- * an `HttpContentTransport`, and a `SemiontClient`, then wires
1254
- * the session over them. Removes the load-bearing
1255
- * "same-token$-instance" invariant from the caller's hands.
1256
- *
1257
- * Strings are accepted for `baseUrl` and `token`; they are branded
1258
- * via `baseUrl()` / `accessToken()` from `@semiont/core` automatically.
1259
- *
1260
- * The remaining options (`refresh`, `validate`, `onAuthFailed`,
1261
- * `onError`) match `SemiontSessionConfig` exactly.
1262
- */
1263
- static fromHttp(opts: {
1264
- kb: KnowledgeBase;
1265
- storage: SessionStorage;
1266
- baseUrl: BaseUrl | string;
1267
- token?: AccessToken | string | null;
1268
- refresh?: () => Promise<string | null>;
1269
- validate?: (token: AccessToken) => Promise<UserInfo | null>;
1270
- onAuthFailed?: (message: string | null) => void;
1271
- onError?: (err: SemiontSessionError) => void;
1272
- }): SemiontSession;
1273
- /**
1274
- * Async factory for the credentials-first long-running script case.
1275
- * Builds the HTTP transport stack, calls `auth.password(email,
1276
- * password)` to acquire access + refresh tokens, persists them via
1277
- * the storage adapter, wires a default `refresh` callback that
1278
- * exchanges the refresh token via `auth.refresh(...)`, and returns
1279
- * the ready session.
1280
- *
1281
- * The consumer-supplied `refresh` callback becomes optional — only
1282
- * needed for non-standard refresh flows (worker-pool shared secret,
1283
- * OAuth refresh-token grant, interactive re-prompt). The default
1284
- * uses the refresh token returned by `auth.password`.
1285
- *
1286
- * `kb` is required and must be a full `KnowledgeBase`. The `id` field
1287
- * is the storage key for this session — distinct scripts sharing the
1288
- * same `SessionStorage` instance must use distinct ids to avoid
1289
- * trampling each other's tokens. The factory does not synthesize a
1290
- * default; the consumer makes the choice.
1291
- *
1292
- * Named `signInHttp` because email+password authentication is
1293
- * inherently an HTTP-shaped operation in the current backend; an
1294
- * in-process `LocalTransport` doesn't have a credentials login
1295
- * path. Non-HTTP transports construct the session directly from
1296
- * their package's transport instance.
1297
- *
1298
- * Throws on auth failure with no resources leaked. On success, the
1299
- * returned session's `ready` promise has already resolved.
1300
- */
1301
- static signInHttp(opts: {
1302
- kb: KnowledgeBase;
1303
- storage: SessionStorage;
1304
- baseUrl: BaseUrl | string;
1305
- email: string;
1306
- password: string;
1307
- validate?: (token: AccessToken) => Promise<UserInfo | null>;
1308
- onAuthFailed?: (message: string | null) => void;
1309
- onError?: (err: SemiontSessionError) => void;
1310
- }): Promise<SemiontSession>;
1311
- }
1312
-
1313
- /**
1314
- * OpenResource — a single entry in the open-resources list (tabs).
1315
- *
1316
- * The list itself lives on `SemiontBrowser.openResources$`. The CRUD
1317
- * methods (`addOpenResource`, `removeOpenResource`, `updateOpenResourceName`,
1318
- * `reorderOpenResources`) live on `SemiontBrowser` too.
1319
- */
1320
- interface OpenResource {
1321
- /** Unique identifier for the resource */
1322
- id: string;
1323
- /** Display name of the resource */
1324
- name: string;
1325
- /** Timestamp when the resource was opened */
1326
- openedAt: number;
1327
- /** Order/position for manual sorting (optional for backward compatibility) */
1328
- order?: number;
1329
- /** Media type for icon display (e.g., 'application/pdf', 'text/plain') */
1330
- mediaType?: string;
1331
- /** Working-tree URI (e.g. "file://docs/overview.md") — used as tooltip in navigation */
1332
- storageUri?: string;
1333
- }
1334
-
1335
- /**
1336
- * SessionSignals — UI-facing notification state that belongs to the host
1337
- * surface, not to the session itself.
1338
- *
1339
- * `SemiontSession` is a headless per-backend client + token + user
1340
- * holder. It can run in any process: browser, worker, CLI, test. But
1341
- * the session-expired / permission-denied *notifications* are inherently
1342
- * a UI-host concern. Keeping those observables on `SemiontSession` meant
1343
- * workers and CLIs carried four dead BehaviorSubjects that nothing would
1344
- * ever fire.
1345
- *
1346
- * `SessionSignals` owns the notification state and has no hard reference
1347
- * to a session. A UI host (e.g. `SemiontBrowser`) constructs one alongside
1348
- * every active session and wires:
1349
- *
1350
- * - `session.onAuthFailed` → `signals.notifySessionExpired` so
1351
- * proactive-refresh failures surface as a notification
1352
- *
1353
- * UI consumers that need to render modal/banner state subscribe here;
1354
- * consumers that need bus/HTTP access continue to subscribe to the session.
1355
- *
1356
- * Session auth-state cleanup (clearing token, clearing storage) is
1357
- * the session's own responsibility inside `refresh()` — by the time
1358
- * `notifySessionExpired` runs, the session has already torn down.
1359
- * Signals only surfaces the notification.
1360
30
  */
1361
-
1362
- declare class SessionSignals {
1363
- readonly sessionExpiredAt$: BehaviorSubject<number | null>;
1364
- readonly sessionExpiredMessage$: BehaviorSubject<string | null>;
1365
- readonly permissionDeniedAt$: BehaviorSubject<number | null>;
1366
- readonly permissionDeniedMessage$: BehaviorSubject<string | null>;
1367
- constructor();
1368
- notifySessionExpired(message: string | null): void;
1369
- notifyPermissionDenied(message: string | null): void;
1370
- acknowledgeSessionExpired(): void;
1371
- acknowledgePermissionDenied(): void;
1372
- dispose(): void;
1373
- }
1374
-
1375
- /**
1376
- * SessionFactory the injection point that lets `SemiontBrowser` stay
1377
- * transport-agnostic.
1378
- *
1379
- * The browser knows how to manage the *lifecycle* of an active session
1380
- * (track it in `activeSession$`, dispose on KB switch, serialize
1381
- * overlapping activations) but does not know how to *construct* one —
1382
- * because that's where transport choice lives. The construction step
1383
- * is parameterized via this factory.
1384
- *
1385
- * The HTTP factory is provided by `createHttpSessionFactory`. A
1386
- * future in-process variant from `@semiont/make-meaning` would expose
1387
- * its own factory.
1388
- */
1389
-
1390
- interface SessionFactoryOptions {
1391
- /** The KB the session is being constructed for. */
1392
- kb: KnowledgeBase;
1393
- /** Persistence adapter — same one the browser uses. */
1394
- storage: SessionStorage;
1395
- /** Modal-signal sink for auth-failed / permission-denied notifications. */
1396
- signals: SessionSignals;
1397
- /** Receives session-level errors (auth-failed, refresh-exhausted, ...). */
1398
- onError: (err: SemiontSessionError) => void;
1399
- }
1400
- type SessionFactory = (opts: SessionFactoryOptions) => SemiontSession;
1401
-
1402
- /**
1403
- * SemiontBrowser — top-level app-facing container for non-KB state.
1404
- *
1405
- * Holds the list of configured KBs, the active KB selection, the active
1406
- * SemiontSession, the identity token, the open-resources list, and a
1407
- * session-level error stream. Held as a process-wide instance for the
1408
- * host's lifetime — see `getBrowser()` in `registry.ts` for the canonical
1409
- * accessor.
1410
- *
1411
- * Transport-agnostic: the browser orchestrates session *lifecycle* but
1412
- * delegates session *construction* to a `SessionFactory` injected at
1413
- * construction. HTTP-backed apps pass `createHttpSessionFactory()` from
1414
- * `@semiont/sdk`; in-process apps pass their own factory.
1415
- *
1416
- * Persistence goes through a `SessionStorage` adapter provided at
1417
- * construction — the browser never touches `localStorage` or `window`
1418
- * directly.
1419
- */
1420
-
1421
- interface SemiontBrowserConfig {
1422
- /** Persistence adapter. The browser reads/writes all persisted state via this. */
1423
- storage: SessionStorage;
1424
- /**
1425
- * Builds a `SemiontSession` for a KB. The browser is transport-
1426
- * agnostic — every HTTP-vs-local construction concern lives in the
1427
- * factory. HTTP-backed apps pass `createHttpSessionFactory()` from
1428
- * `@semiont/sdk`; a future in-process variant from `@semiont/make-meaning`
1429
- * would expose its own factory.
1430
- */
1431
- sessionFactory: SessionFactory;
1432
- }
1433
- declare class SemiontBrowser {
1434
- readonly kbs$: BehaviorSubject<KnowledgeBase[]>;
1435
- readonly activeKbId$: BehaviorSubject<string | null>;
1436
- readonly activeSession$: BehaviorSubject<SemiontSession | null>;
1437
- /**
1438
- * Modal signals (session-expired / permission-denied) for the
1439
- * currently-active session. Parallels `activeSession$` — always
1440
- * non-null when `activeSession$` is non-null, always null when it
1441
- * is. Extracted from the session itself so headless sessions
1442
- * (workers, CLIs, tests) don't carry dead modal observables.
1443
- * See [SessionSignals](./session-signals.ts).
1444
- */
1445
- readonly activeSignals$: BehaviorSubject<SessionSignals | null>;
1446
- /**
1447
- * True while a session is actively being constructed (setActiveKb /
1448
- * signIn in flight, awaiting `session.ready`). Distinguishes the
1449
- * "session about to arrive" intermediate state from "session
1450
- * intentionally null" (after signOut, or when the active KB has no
1451
- * stored credentials). UIs that want a loading spinner should gate
1452
- * on this; otherwise they get stuck spinning after every signOut.
1453
- */
1454
- readonly sessionActivating$: BehaviorSubject<boolean>;
1455
- readonly openResources$: BehaviorSubject<OpenResource[]>;
1456
- readonly error$: Subject<SemiontSessionError>;
1457
- readonly identityToken$: BehaviorSubject<string | null>;
1458
- private readonly storage;
1459
- private readonly sessionFactory;
1460
- /**
1461
- * App-scoped EventBus. Hosts UI-shell events that must work regardless
1462
- * of whether a KB session is active: panel toggles, sidebar state,
1463
- * tab reorders, routing, settings, etc. Disjoint from the per-session
1464
- * bus inside `SemiontClient`, which carries KB-content events
1465
- * (mark:*, beckon:*, gather:*, match:*, bind:*, yield:*, browse:click).
1466
- */
1467
- private readonly eventBus;
1468
- private unsubscribeStorage;
1469
- private disposed;
1470
- private activating;
1471
- constructor(config: SemiontBrowserConfig);
1472
- /** Emit an event on the browser's app-scoped bus. */
1473
- emit<K extends keyof EventMap>(channel: K, payload: EventMap[K]): void;
1474
- /** Subscribe to an event; returns unsubscribe. */
1475
- on<K extends keyof EventMap>(channel: K, handler: (payload: EventMap[K]) => void): () => void;
1476
- /** Read-only observable for an app-scoped channel. */
1477
- stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;
1478
- /**
1479
- * Set the app-level identity token. Sourced from whatever the host
1480
- * environment uses for OAuth sessions (e.g. NextAuth in a browser app).
1481
- * Should be called once from the host's startup-and-on-change site;
1482
- * no other code should write to this slot.
1483
- */
1484
- setIdentityToken(token: string | null): void;
1485
- addKb(input: NewKnowledgeBase, access: string, refresh: string): KnowledgeBase;
1486
- removeKb(id: string): void;
1487
- /**
1488
- * Patch a KB in the list. Restricted to the common, endpoint-agnostic
1489
- * fields (`label`, `email`, `gitBranch`) — the `endpoint` shape isn't
1490
- * editable in place; remove and re-add to change the connection
1491
- * target.
1492
- */
1493
- updateKb(id: string, updates: {
1494
- label?: string;
1495
- email?: string;
1496
- gitBranch?: string;
1497
- }): void;
1498
- /**
1499
- * Read the locally-stored credential status for a KB. Pure / synchronous —
1500
- * does not subscribe to context changes. Used by KB-list UI to color status
1501
- * dots without requiring re-renders on every tick.
1502
- */
1503
- getKbSessionStatus(kbId: string): KbSessionStatus;
1504
- /**
1505
- * Switch the active KB. Follows the D2 disposal contract:
1506
- * 1. Synchronously announce the new id on `activeKbId$` and null out
1507
- * `activeSession$` so views see a safe empty state first.
1508
- * 2. Serialize overlapping calls — if an activation is in flight, wait
1509
- * for it before proceeding.
1510
- * 3. Dispose whatever session is currently live.
1511
- * 4. Construct the next session and await `session.ready`.
1512
- * 5. Before emitting, re-check `activeKbId$` — if a newer call superseded
1513
- * us while we waited, dispose our session and skip the emit.
1514
- * 6. Emit the new session.
1515
- */
1516
- setActiveKb(id: string | null): Promise<void>;
1517
- /**
1518
- * Sign in to an existing KB: store the tokens and (re)activate the
1519
- * session. If the KB is already active, the current session is disposed
1520
- * and replaced so the new tokens take effect.
1521
- */
1522
- signIn(id: string, access: string, refresh: string): Promise<void>;
1523
- /**
1524
- * Sign out of a KB: clear stored tokens. If the KB is active, dispose
1525
- * its session + signals and emit null for both.
1526
- */
1527
- signOut(id: string): Promise<void>;
1528
- addOpenResource(id: string, name: string, mediaType?: string, storageUri?: string): void;
1529
- removeOpenResource(id: string): void;
1530
- updateOpenResourceName(id: string, name: string): void;
1531
- reorderOpenResources(oldIndex: number, newIndex: number): void;
1532
- dispose(): Promise<void>;
1533
- }
1534
-
1535
- /**
1536
- * createHttpSessionFactory — the default `SessionFactory` for HTTP-backed
1537
- * KBs. Owns every HTTP-specific construction concern that used to live in
1538
- * `SemiontBrowser`: building `HttpTransport`/`HttpContentTransport`,
1539
- * wiring the `tokenRefresher` callback, deduplicating concurrent 401
1540
- * refresh round trips, and invoking the auth endpoints for token refresh
1541
- * and user-validate.
1542
- *
1543
- * Returned as a closure so a single `inFlightRefreshes` map is shared
1544
- * across every session this factory builds — the dedup is meaningful
1545
- * across concurrent session reactivations for the same KB id.
1546
- */
1547
-
1548
- declare function createHttpSessionFactory(): SessionFactory;
1549
-
1550
- /**
1551
- * Process-wide accessor for `SemiontBrowser`. Constructed lazily on the
1552
- * first `getBrowser()` call and held for the host's lifetime — a single
1553
- * instance owns the KB list, identity token, and active-session state,
1554
- * so callers throughout the host get the same view of "which KB am I
1555
- * talking to right now" regardless of where they pick it up.
1556
- *
1557
- * The caller provides a `SessionStorage` implementation and a
1558
- * `SessionFactory` — both are environment-specific (browsers use
1559
- * `WebBrowserStorage` + `createHttpSessionFactory()`, CLI/embedded
1560
- * hosts use a filesystem adapter and possibly a local-process
1561
- * factory, tests use `InMemorySessionStorage` and stubs). The first
1562
- * call to `getBrowser` wins; subsequent calls return the cached
1563
- * instance regardless of the options passed.
1564
- */
1565
-
1566
- interface GetBrowserOptions {
1567
- /** Persistence adapter used to construct the singleton on first call. */
1568
- storage: SessionStorage;
1569
- /** Session factory used to build a `SemiontSession` per active KB. */
1570
- sessionFactory: SessionFactory;
1571
- }
1572
- declare function getBrowser(options: GetBrowserOptions): SemiontBrowser;
1573
-
1574
- /**
1575
- * Pure helpers and storage-adapter-driven loaders for the Semiont
1576
- * session layer.
1577
- *
1578
- * Contains:
1579
- * - Storage key shape (constants, `sessionKey(kbId)`)
1580
- * - JWT expiry parsing and "is expired" check
1581
- * - URL/protocol helpers for KB instances
1582
- * - Loaders/savers that take a `SessionStorage` and operate over it
1583
- * (no direct `localStorage` access)
1584
- *
1585
- * No React imports, no module-scoped state, no side effects beyond
1586
- * whatever the passed-in `SessionStorage` does.
1587
- */
1588
-
1589
- /** The shape persisted per KB. */
1590
- interface StoredSession {
1591
- access: string;
1592
- refresh: string;
1593
- }
1594
- declare function setStoredSession(storage: SessionStorage, kbId: string, session: StoredSession): void;
1595
- declare function defaultProtocol(host: string): 'http' | 'https';
1596
- declare function isValidHostname(host: string): boolean;
1597
- /**
1598
- * Build the wire URL for an HTTP KB endpoint. HTTP-shaped helper —
1599
- * lives next to the KB list machinery because the frontend Panel needs
1600
- * it for the auth round-trip when adding a KB. Code that holds a
1601
- * uniform `KnowledgeBase` should not call this; it should hand the KB
1602
- * to a transport factory and let the factory inspect `endpoint.kind`.
1603
- */
1604
- declare function kbBackendUrl(endpoint: HttpEndpoint): string;
1605
-
1606
- /**
1607
- * Marker for the state-unit pattern: a stateful, lifecycled object with an
1608
- * RxJS-shaped public surface, constructed by a factory function
1609
- * (`createFooStateUnit`), with internal state held in a closure.
1610
- *
1611
- * The structural contract is `dispose()` — the rest of the pattern
1612
- * (closure-based identity, Observable public surface, internal Subjects
1613
- * exposed as `.asObservable()` views, no leaked subscriptions, composition
1614
- * by parameter rather than ownership) is convention enforced by review,
1615
- * not the type system.
1616
- *
1617
- * See `packages/sdk/docs/STATE-UNITS.md` for the full axioms and rationale.
1618
- */
1619
- interface StateUnit {
1620
- /**
1621
- * Idempotent, total teardown. Completes every Subject the unit owns,
1622
- * unsubscribes every internal subscription, releases timers / abort
1623
- * controllers / network handles. Safe to call multiple times — the
1624
- * second call is a no-op.
1625
- */
1626
- dispose(): void;
1627
- }
1628
- /**
1629
- * Compose multiple disposers into a single `dispose()` call. Accepts either
1630
- * a `StateUnit` (whose `dispose()` will be invoked) or a plain teardown
1631
- * function. The returned object is itself disposable; call its `dispose()`
1632
- * once to tear down everything that was added.
1633
- */
1634
- declare function createDisposer(): {
1635
- add(item: StateUnit | (() => void)): void;
1636
- dispose(): void;
1637
- };
1638
-
1639
- /**
1640
- * createSearchPipeline
1641
- *
1642
- * A debounced-search RxJS pipeline factory. Combines an input Subject with a
1643
- * downstream fetch function and emits typed `{ results, isSearching }` state.
1644
- *
1645
- * Designed to be created once per consumer instance and held for its lifetime
1646
- * (e.g. by a view layer's lazy initializer), then observed via `state$`. The
1647
- * pipeline is pure RxJS — unit-testable without any view-layer dependency.
1648
- *
1649
- * The fetch function is expected to return `Observable<T[] | undefined>`,
1650
- * matching the cache-miss-then-data shape of `BrowseNamespace` Observables:
1651
- * `undefined` means "fetch in flight, no value yet"; an array means "data
1652
- * available (possibly empty)".
1653
- */
1654
-
1655
- interface SearchState<T> {
1656
- results: T[];
1657
- isSearching: boolean;
1658
- }
1659
- interface SearchPipeline<T> {
1660
- /** Latest query string. Bind to a controlled input. */
1661
- query$: Observable<string>;
1662
- /** Latest search state — results plus a loading flag. */
1663
- state$: Observable<SearchState<T>>;
1664
- /** Push a new query value. Triggers the debounced fetch. */
1665
- setQuery(value: string): void;
1666
- /** Tear down the input Subject. Call from the consumer's cleanup hook. */
1667
- dispose(): void;
1668
- }
1669
- interface SearchPipelineOptions {
1670
- /** Milliseconds to wait after the last keystroke before fetching. Default 250. */
1671
- debounceMs?: number;
1672
- /** Initial query value. Useful for modals that open with a pre-filled term. */
1673
- initialQuery?: string;
1674
- }
1675
- declare function createSearchPipeline<T>(fetch: (query: string) => Observable<T[] | undefined>, options?: SearchPipelineOptions): SearchPipeline<T>;
1676
-
1677
- /**
1678
- * WorkerBus — minimal channel-bus surface that worker-side adapters
1679
- * (e.g. `JobClaimAdapter` in `@semiont/jobs`, `SmelterActorStateUnit` in
1680
- * `@semiont/make-meaning`) need.
1681
- *
1682
- * Transport-neutral by design. HTTP `ActorStateUnit` (from `@semiont/api-client`)
1683
- * satisfies it directly; an in-process worker can pass a small shim around
1684
- * an `EventBus` with a `() => Promise<void>` `emit` that calls into the
1685
- * actor system.
1686
- *
1687
- * `addChannels` is optional because in-process buses receive every emit
1688
- * implicitly — only HTTP needs to widen its SSE subscription set to
1689
- * include worker-only channels (`job:queued`, `yield:created`, etc.).
1690
- */
1691
-
1692
- interface WorkerBus {
1693
- on$<T = Record<string, unknown>>(channel: string): Observable<T>;
1694
- emit(channel: string, payload: Record<string, unknown>): Promise<void>;
1695
- addChannels?(channels: readonly string[]): void;
1696
- }
1697
-
1698
- interface BeckonStateUnit extends StateUnit {
1699
- hoveredAnnotationId$: Observable<AnnotationId | null>;
1700
- hover(annotationId: AnnotationId | null): void;
1701
- focus(annotationId: AnnotationId): void;
1702
- sparkle(annotationId: AnnotationId): void;
1703
- }
1704
- declare function createBeckonStateUnit(client: SemiontClient): BeckonStateUnit;
1705
- /** Default milliseconds the mouse must dwell before beckon:hover is emitted. */
1706
- declare const HOVER_DELAY_MS = 150;
1707
- type EmitHover = (annotationId: AnnotationId | null) => void;
1708
- interface HoverHandlers {
1709
- handleMouseEnter: (annotationId: AnnotationId) => void;
1710
- handleMouseLeave: () => void;
1711
- cleanup: () => void;
1712
- }
1713
- declare function createHoverHandlers(emit: EmitHover, delayMs: number): HoverHandlers;
1714
-
1715
- interface GatherStateUnit extends StateUnit {
1716
- context$: Observable<GatheredContext | null>;
1717
- loading$: Observable<boolean>;
1718
- error$: Observable<Error | null>;
1719
- annotationId$: Observable<AnnotationId | null>;
1720
- }
1721
- declare function createGatherStateUnit(client: SemiontClient, resourceId: ResourceId): GatherStateUnit;
1722
-
1723
- interface MatchStateUnit extends StateUnit {
1724
- }
1725
- declare function createMatchStateUnit(client: SemiontClient, _resourceId: ResourceId): MatchStateUnit;
1726
-
1727
- type JobProgress$1 = components['schemas']['JobProgress'];
1728
- interface GenerateDocumentOptions {
1729
- title: string;
1730
- storageUri: string;
1731
- prompt?: string;
1732
- /** Body locale — language the generated resource is written in. Falls back to the state unit's UI locale when unset. */
1733
- language?: string;
1734
- /** Source-resource locale — language of the resource the annotation lives on. Forwarded to the prompt for context-snippet awareness. BCP-47. */
1735
- sourceLanguage?: string;
1736
- temperature?: number;
1737
- maxTokens?: number;
1738
- context: GatheredContext;
1739
- }
1740
- interface YieldStateUnit extends StateUnit {
1741
- isGenerating$: Observable<boolean>;
1742
- progress$: Observable<JobProgress$1 | null>;
1743
- generate(referenceId: string, options: GenerateDocumentOptions): void;
1744
- }
1745
- declare function createYieldStateUnit(client: SemiontClient, resourceId: ResourceId, locale: string): YieldStateUnit;
1746
-
1747
- type JobProgress = components['schemas']['JobProgress'];
1748
- interface PendingAnnotation {
1749
- selector: Selector | Selector[];
1750
- motivation: Motivation;
1751
- }
1752
- interface MarkStateUnit extends StateUnit {
1753
- pendingAnnotation$: Observable<PendingAnnotation | null>;
1754
- assistingMotivation$: Observable<Motivation | null>;
1755
- progress$: Observable<JobProgress | null>;
1756
- }
1757
- declare function createMarkStateUnit(client: SemiontClient, resourceId: ResourceId): MarkStateUnit;
1758
-
1759
- export { AdminNamespace, type AnnotationHistoryResponse, AuthNamespace, BeckonNamespace, type BeckonStateUnit, BindNamespace, BrowseNamespace, BusRequestError, type BusRequestErrorCode, type BusRequestPrimitive, CacheObservable, type CreateAnnotationInput, type CreateFromTokenOptions, type CreateResourceInput, FrameNamespace, type GatherAnnotationProgress, GatherNamespace, type GatherStateUnit, type GenerateDocumentOptions, type GenerationOptions, type GetBrowserOptions, HOVER_DELAY_MS, type HoverHandlers, type HttpEndpoint, InMemorySessionStorage, JobNamespace, type KbEndpoint, type KbSessionStatus, type KnowledgeBase, type LocalEndpoint, type MarkAssistEvent, type MarkAssistOptions, type MarkAssistProgress, MarkNamespace, type MarkStateUnit, MatchNamespace, type MatchSearchProgress, type MatchStateUnit, type NewKnowledgeBase, type OpenResource, type PendingAnnotation, type ReferencedByEntry, type RequestContent, type ResponseContent, type SearchPipeline, type SearchPipelineOptions, type SearchState, SemiontBrowser, type SemiontBrowserConfig, SemiontClient, SemiontSession, type SemiontSessionConfig, SemiontSessionError, type SemiontSessionErrorCode, type SessionFactory, type SessionFactoryOptions, SessionSignals, type SessionStorage, type StateUnit, type StoredSession, StreamObservable, UploadObservable, type UploadProgress, type User, type UserInfo, type WorkerBus, type YieldGenerationEvent, YieldNamespace, type YieldStateUnit, busRequest, createBeckonStateUnit, createDisposer, createGatherStateUnit, createHoverHandlers, createHttpSessionFactory, createMarkStateUnit, createMatchStateUnit, createSearchPipeline, createYieldStateUnit, defaultProtocol, getBrowser, httpKb, isValidHostname, kbBackendUrl, setStoredSession };
31
+ export * from './client';
32
+ export { StreamObservable, CacheObservable, UploadObservable, type UploadProgress } from './awaitable';
33
+ export { busRequest, BusRequestError, type BusRequestErrorCode, type BusRequestPrimitive, } from './bus-request';
34
+ export { FrameNamespace } from './namespaces/frame';
35
+ export { BrowseNamespace } from './namespaces/browse';
36
+ export { MarkNamespace } from './namespaces/mark';
37
+ export { BindNamespace } from './namespaces/bind';
38
+ export { GatherNamespace } from './namespaces/gather';
39
+ export { MatchNamespace } from './namespaces/match';
40
+ export { YieldNamespace } from './namespaces/yield';
41
+ export { BeckonNamespace } from './namespaces/beckon';
42
+ export { JobNamespace } from './namespaces/job';
43
+ export { AuthNamespace } from './namespaces/auth';
44
+ export { AdminNamespace } from './namespaces/admin';
45
+ export type * from './namespaces/types';
46
+ export type { Logger, AccessToken, AnnotationId, BaseUrl, RefreshToken, ResourceId, UserId, Annotation, BodyItem, BodyOperation, EntityType, EventMap, GatheredContext, Motivation, ResourceDescriptor, TagCategory, TagSchema, ConnectionState, IContentTransport, ITransport, } from '@semiont/core';
47
+ export { accessToken, annotationId, baseUrl, entityType, refreshToken, resourceId, userId, SemiontError, } from '@semiont/core';
48
+ export { SemiontSession, type SemiontSessionConfig, type UserInfo } from './session/semiont-session';
49
+ export { SemiontBrowser, type SemiontBrowserConfig } from './session/semiont-browser';
50
+ export type { SessionFactory, SessionFactoryOptions } from './session/session-factory';
51
+ export { createHttpSessionFactory } from './session/http-session-factory';
52
+ export { SessionSignals } from './session/session-signals';
53
+ export { SemiontSessionError, type SemiontSessionErrorCode } from './session/errors';
54
+ export { getBrowser, type GetBrowserOptions } from './session/registry';
55
+ export { type SessionStorage, InMemorySessionStorage, } from './session/session-storage';
56
+ export { type KnowledgeBase, type KbEndpoint, type HttpEndpoint, type LocalEndpoint, type NewKnowledgeBase, type KbSessionStatus, httpKb, } from './session/knowledge-base';
57
+ export { type OpenResource } from './session/open-resource';
58
+ export { defaultProtocol, isValidHostname, kbBackendUrl, setStoredSession, type StoredSession, } from './session/storage';
59
+ export * from './state';
60
+ export { firstValueFrom, lastValueFrom } from 'rxjs';
61
+ //# sourceMappingURL=index.d.ts.map