@semiont/sdk 0.5.4 → 0.5.6

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