@semiont/sdk 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -15
- package/dist/awaitable.d.ts +103 -0
- package/dist/awaitable.d.ts.map +1 -0
- package/dist/bus-request.d.ts +18 -0
- package/dist/bus-request.d.ts.map +1 -0
- package/dist/cache.d.ts +57 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/client.d.ts +138 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/index.d.ts +52 -1733
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -1
- package/dist/index.js.map +1 -1
- package/dist/namespaces/admin.d.ts +27 -0
- package/dist/namespaces/admin.d.ts.map +1 -0
- package/dist/namespaces/auth.d.ts +26 -0
- package/dist/namespaces/auth.d.ts.map +1 -0
- package/dist/namespaces/beckon.d.ts +12 -0
- package/dist/namespaces/beckon.d.ts.map +1 -0
- package/dist/namespaces/bind.d.ts +11 -0
- package/dist/namespaces/bind.d.ts.map +1 -0
- package/dist/namespaces/browse.d.ts +111 -0
- package/dist/namespaces/browse.d.ts.map +1 -0
- package/dist/namespaces/frame.d.ts +29 -0
- package/dist/namespaces/frame.d.ts.map +1 -0
- package/dist/namespaces/gather.d.ts +16 -0
- package/dist/namespaces/gather.d.ts.map +1 -0
- package/dist/namespaces/job.d.ts +32 -0
- package/dist/namespaces/job.d.ts.map +1 -0
- package/dist/namespaces/mark.d.ts +27 -0
- package/dist/namespaces/mark.d.ts.map +1 -0
- package/dist/namespaces/match.d.ts +15 -0
- package/dist/namespaces/match.d.ts.map +1 -0
- package/dist/namespaces/types.d.ts +438 -0
- package/dist/namespaces/types.d.ts.map +1 -0
- package/dist/namespaces/yield.d.ts +23 -0
- package/dist/namespaces/yield.d.ts.map +1 -0
- package/dist/session/errors.d.ts +18 -0
- package/dist/session/errors.d.ts.map +1 -0
- package/dist/session/http-session-factory.d.ts +15 -0
- package/dist/session/http-session-factory.d.ts.map +1 -0
- package/dist/session/knowledge-base.d.ts +95 -0
- package/dist/session/knowledge-base.d.ts.map +1 -0
- package/dist/session/open-resource.d.ts +22 -0
- package/dist/session/open-resource.d.ts.map +1 -0
- package/dist/session/registry.d.ts +31 -0
- package/dist/session/registry.d.ts.map +1 -0
- package/dist/session/semiont-browser.d.ts +141 -0
- package/dist/session/semiont-browser.d.ts.map +1 -0
- package/dist/session/semiont-session.d.ts +210 -0
- package/dist/session/semiont-session.d.ts.map +1 -0
- package/dist/session/session-factory.d.ts +31 -0
- package/dist/session/session-factory.d.ts.map +1 -0
- package/dist/session/session-signals.d.ts +40 -0
- package/dist/session/session-signals.d.ts.map +1 -0
- package/dist/session/session-storage.d.ts +41 -0
- package/dist/session/session-storage.d.ts.map +1 -0
- package/dist/session/storage.d.ts +52 -0
- package/dist/session/storage.d.ts.map +1 -0
- package/dist/session/testing.d.ts +7 -0
- package/dist/session/testing.d.ts.map +1 -0
- package/dist/state/flows/beckon-state-unit.d.ts +22 -0
- package/dist/state/flows/beckon-state-unit.d.ts.map +1 -0
- package/dist/state/flows/gather-state-unit.d.ts +12 -0
- package/dist/state/flows/gather-state-unit.d.ts.map +1 -0
- package/dist/state/flows/mark-state-unit.d.ts +17 -0
- package/dist/state/flows/mark-state-unit.d.ts.map +1 -0
- package/dist/state/flows/match-state-unit.d.ts +7 -0
- package/dist/state/flows/match-state-unit.d.ts.map +1 -0
- package/dist/state/flows/yield-state-unit.d.ts +25 -0
- package/dist/state/flows/yield-state-unit.d.ts.map +1 -0
- package/dist/state/index.d.ts +10 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/lib/search-pipeline.d.ts +38 -0
- package/dist/state/lib/search-pipeline.d.ts.map +1 -0
- package/dist/state/lib/state-unit.d.ts +33 -0
- package/dist/state/lib/state-unit.d.ts.map +1 -0
- package/dist/state/lib/worker-bus.d.ts +21 -0
- package/dist/state/lib/worker-bus.d.ts.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -14,9 +14,9 @@ The SDK is **transport-agnostic**: it consumes the `ITransport` and `IContentTra
|
|
|
14
14
|
|
|
15
15
|
> **Where this doc fits.** This README is the *typed-surface reference* — what's in `@semiont/sdk`, how the namespaces are organized, what return shapes to expect. For the *protocol-level architectural framing* (the eight flows, the three programmable surfaces — CLI, SDK, Skills — the core tenets, the per-flow contracts), start with [`docs/protocol/README.md`](https://github.com/The-AI-Alliance/semiont/blob/main/docs/protocol/README.md). Daemon authors stitching multiple packages together also want the [skill packs](https://github.com/The-AI-Alliance/semiont/tree/main/docs/protocol/skills) — `semiont-session` for watcher daemons, `semiont-worker` for job-claim daemons, `semiont-wiki` for the end-to-end annotation pipeline.
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Four ideas that hold the surface together
|
|
18
18
|
|
|
19
|
-
The SDK is wider than a typical client library because the domain is — collaborative knowledge work over a shared corpus, with humans and AI agents as peers.
|
|
19
|
+
The SDK is wider than a typical client library because the domain is — collaborative knowledge work over a shared corpus, with humans and AI agents as peers. Four framings make the API tractable; once you've seen them, the rest is predictable.
|
|
20
20
|
|
|
21
21
|
### 1. Eight verbs
|
|
22
22
|
|
|
@@ -24,38 +24,62 @@ Every operation in the SDK belongs to one of eight *flows* — verbs that descri
|
|
|
24
24
|
|
|
25
25
|
| Verb | What it does | Example methods |
|
|
26
26
|
|---|---|---|
|
|
27
|
-
| **frame** | Define and evolve the schema vocabulary (entity types,
|
|
27
|
+
| **frame** | Define and evolve the schema vocabulary (entity types, tag schemas, future relation types) | `frame.addEntityType`, `frame.addEntityTypes`, `frame.addTagSchema` |
|
|
28
28
|
| **yield** | Introduce new resources into the system | `yield.resource`, `yield.fromAnnotation`, `yield.cloneToken` |
|
|
29
29
|
| **mark** | Add structured metadata to resources | `mark.annotation`, `mark.assist`, `mark.archive` |
|
|
30
30
|
| **match** | Search the corpus for candidate resources | `match.search` |
|
|
31
31
|
| **bind** | Resolve ambiguous references to specific resources | `bind.body`, `bind.initiate` |
|
|
32
32
|
| **gather** | Assemble related context around an annotation | `gather.annotation` |
|
|
33
|
-
| **browse** | Navigate, read, and observe | `browse.resource`, `browse.annotations`, `browse.click` |
|
|
33
|
+
| **browse** | Navigate, read, and observe | `browse.resource`, `browse.annotations`, `browse.entityTypes`, `browse.tagSchemas`, `browse.click` |
|
|
34
34
|
| **beckon** | Coordinate attention across participants | `beckon.hover`, `beckon.attention`, `beckon.sparkle` |
|
|
35
35
|
|
|
36
36
|
Each flow is a namespace on `SemiontClient` (`client.mark.X(...)`, `client.gather.X(...)`, ...). The verb is the unit of mental model — a method call belongs to a flow, not to a noun. Frame is the schema-layer flow — content flows operate within the vocabulary Frame manages. Per-flow contracts live in [`docs/protocol/flows`](https://github.com/The-AI-Alliance/semiont/tree/main/docs/protocol/flows).
|
|
37
37
|
|
|
38
|
-
### 2.
|
|
38
|
+
### 2. One call, two ways to consume
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
Most data-fetching libraries make you choose between Promise-shaped and Observable-shaped at the import line. The SDK doesn't. Every long-lived value comes back as an `Observable` that *also* implements `PromiseLike<T>` — `await` it for the final value, `.subscribe(...)` it for progress events or live updates, from the same call.
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
```ts
|
|
43
|
+
// One-shot consumer — never imports rxjs
|
|
44
|
+
const resource = await client.browse.resource(rId);
|
|
45
|
+
const result = await client.match.search(rId, refId, ctx);
|
|
46
|
+
|
|
47
|
+
// Reactive consumer — same call, .subscribe instead of await
|
|
48
|
+
client.browse.resource(rId).subscribe((r) => {
|
|
49
|
+
if (r === undefined) showSkeleton();
|
|
50
|
+
else render(r);
|
|
51
|
+
});
|
|
52
|
+
client.match.search(rId, refId, ctx).subscribe((event) => {
|
|
53
|
+
if (event.kind === 'progress') updateProgress(event.data);
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
A script that just wants the final value never imports anything from `rxjs`. A browser app rendering loading state subscribes to the same shape. The reactive substrate is preserved as a load-bearing architectural choice; the user-facing surface looks Promise-shaped when that's all the caller needs.
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
Methods return one of: `Promise<T>` (atomic backend ops), an awaitable `Observable<T>` subclass (`StreamObservable<T>` for bounded progress streams, `CacheObservable<T>` for live queries with stale-while-revalidate), or `void` (collaboration signals — see #3). Per-method assignments and the typing discipline are in [`docs/REACTIVE-MODEL.md`](https://github.com/The-AI-Alliance/semiont/blob/main/packages/sdk/docs/REACTIVE-MODEL.md).
|
|
50
60
|
|
|
51
61
|
### 3. Collaboration primitives
|
|
52
62
|
|
|
53
|
-
The
|
|
63
|
+
The `void`-returning third category — collaboration signals — is the SDK's distinctive contribution to multi-participant coordination. They look fire-and-forget at the call site; on the bus they fan out across every participant.
|
|
54
64
|
|
|
55
65
|
A human in a browser hovers an annotation (`beckon.hover(annotationId)`); an AI agent at the other end of the bus sees `beckon:hover` and reacts. An agent emits a sparkle (`beckon.sparkle(annotationId)`); the human's UI lights up the indicated annotation. A frontend state unit emits `mark.changeShape('rectangle')`; a different participant subscribed to `mark:shape-changed` reacts.
|
|
56
66
|
|
|
57
67
|
This is *protocol-level* coordination — not browser-app fluff, not bolted-on presence — and it sits on the same typed namespace surface as data operations. Observers reach the same signals via `session.subscribe(channel, handler)` or `client.bus.get(channel)`. Three legitimate paths to the bus are documented in [`docs/REACTIVE-MODEL.md`](https://github.com/The-AI-Alliance/semiont/blob/main/packages/sdk/docs/REACTIVE-MODEL.md#three-paths-to-the-bus).
|
|
58
68
|
|
|
69
|
+
### 4. Transport agnosticism
|
|
70
|
+
|
|
71
|
+
`SemiontClient` is constructed against the `ITransport` and `IContentTransport` interfaces from `@semiont/core` — not against any particular wire. The same SDK surface runs over HTTP, in-process, or any future transport that satisfies the interface. None of the eight verb namespaces or the flow state machines reach for transport-specific features.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
// HTTP — connect to a remote backend
|
|
75
|
+
const client = await SemiontClient.signInHttp({ baseUrl, email, password });
|
|
76
|
+
|
|
77
|
+
// In-process — same surface, no network
|
|
78
|
+
const client = new SemiontClient(localTransport, localContentTransport);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`KnowledgeBase` carries a uniform shape regardless of transport (only the nested `endpoint` varies — `{ kind: 'http', host, port, protocol }` or `{ kind: 'local', kbId }`). Code that doesn't *construct* transports — your scripts, the verb namespaces, the flow state machines — never inspects which kind it has. Tests can run against an in-process transport for speed; daemons can embed the backend; the same domain code drives both.
|
|
82
|
+
|
|
59
83
|
## What's in the box
|
|
60
84
|
|
|
61
85
|
- **`SemiontClient`** — the verb-oriented coordinator over a wire transport.
|
|
@@ -166,7 +190,7 @@ Same `SemiontClient`, same verb namespaces — no network involved. There is no
|
|
|
166
190
|
|
|
167
191
|
## Worked examples
|
|
168
192
|
|
|
169
|
-
The eight verb namespaces hang off `SemiontClient`, plus three infrastructure namespaces (`auth`, `admin`, `job`) when the client was constructed with backend operations. Each example below uses one of the
|
|
193
|
+
The eight verb namespaces hang off `SemiontClient`, plus three infrastructure namespaces (`auth`, `admin`, `job`) when the client was constructed with backend operations. Each example below uses one of the return shapes mentioned above; the per-method assignment table is in [`docs/REACTIVE-MODEL.md`](https://github.com/The-AI-Alliance/semiont/blob/main/packages/sdk/docs/REACTIVE-MODEL.md#method-by-method-assignment).
|
|
170
194
|
|
|
171
195
|
```ts
|
|
172
196
|
// Browse — live queries; await yields the loaded value, subscribe yields
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thenable Observable subclasses.
|
|
3
|
+
*
|
|
4
|
+
* Two thin Observable subclasses that also implement `PromiseLike<T>`. Used as
|
|
5
|
+
* the public return type of namespace methods that emit streams (job
|
|
6
|
+
* lifecycle, generation progress) and cache reads (Browse live queries).
|
|
7
|
+
*
|
|
8
|
+
* The point: scripts can `await` the call directly without `lastValueFrom` /
|
|
9
|
+
* `firstValueFrom` wrappers; reactive consumers keep using `.subscribe(...)`
|
|
10
|
+
* and `.pipe(...)` exactly as before.
|
|
11
|
+
*
|
|
12
|
+
* The asymmetric `.then()` semantics — last-value-on-completion for streams,
|
|
13
|
+
* first-non-undefined-value for caches — is encoded by the subclass name. The
|
|
14
|
+
* docstring on the namespace method tells the consumer which one applies.
|
|
15
|
+
*
|
|
16
|
+
* `.pipe(...)` returns a plain `Observable<T>` (RxJS doesn't propagate
|
|
17
|
+
* subclasses through `pipe`). Once you compose, you've explicitly entered
|
|
18
|
+
* RxJS land; `lastValueFrom` from `rxjs` is the right bridge there.
|
|
19
|
+
*/
|
|
20
|
+
import { Observable } from 'rxjs';
|
|
21
|
+
import type { ResourceId } from '@semiont/core';
|
|
22
|
+
/**
|
|
23
|
+
* Bounded Observable stream — emits zero-or-more progress values, then a
|
|
24
|
+
* final value on completion. Used by job-lifecycle methods like
|
|
25
|
+
* `mark.assist`, `gather.annotation`, `match.search`, `yield.fromAnnotation`.
|
|
26
|
+
*
|
|
27
|
+
* Awaiting resolves to the **last** emitted value (via `lastValueFrom`).
|
|
28
|
+
* Subscribing yields every emission, ending in `complete`.
|
|
29
|
+
*/
|
|
30
|
+
export declare class StreamObservable<T> extends Observable<T> implements PromiseLike<T> {
|
|
31
|
+
then<R1 = T, R2 = never>(onfulfilled?: ((v: T) => R1 | PromiseLike<R1>) | null, onrejected?: ((e: unknown) => R2 | PromiseLike<R2>) | null): PromiseLike<R1 | R2>;
|
|
32
|
+
/** Wrap an existing Observable's subscribe behavior in a StreamObservable. */
|
|
33
|
+
static from<T>(source: Observable<T>): StreamObservable<T>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Multicast cache observable — emits `undefined` while the underlying value
|
|
37
|
+
* is loading, then the value, then re-emits when bus events invalidate the
|
|
38
|
+
* cache entry. Used by Browse live-query methods (`browse.resource`,
|
|
39
|
+
* `browse.annotations`, etc.).
|
|
40
|
+
*
|
|
41
|
+
* Awaiting resolves to the **first non-undefined** value (waits past the
|
|
42
|
+
* loading state). Subscribing yields the full sequence including the
|
|
43
|
+
* initial `undefined`, so reactive consumers can render a loading state.
|
|
44
|
+
*
|
|
45
|
+
* The class is parameterized as `CacheObservable<T>` even though the
|
|
46
|
+
* stream's element type is `T | undefined` — `T` is what the consumer
|
|
47
|
+
* gets from `await`, and that's the contract we want to advertise. The
|
|
48
|
+
* `Observable<T | undefined>` shape leaks through `.subscribe` and
|
|
49
|
+
* `.pipe` in the natural way.
|
|
50
|
+
*/
|
|
51
|
+
export declare class CacheObservable<T> extends Observable<T | undefined> implements PromiseLike<T> {
|
|
52
|
+
then<R1 = T, R2 = never>(onfulfilled?: ((v: T) => R1 | PromiseLike<R1>) | null, onrejected?: ((e: unknown) => R2 | PromiseLike<R2>) | null): PromiseLike<R1 | R2>;
|
|
53
|
+
/**
|
|
54
|
+
* Wrap an existing Observable's subscribe behavior in a `CacheObservable`.
|
|
55
|
+
*
|
|
56
|
+
* Memoizes on source identity: passing the same `source` returns the same
|
|
57
|
+
* wrapper instance. The Browse cache primitive already returns a stable
|
|
58
|
+
* Observable per key (its B4 contract), so this preserves that contract
|
|
59
|
+
* through the awaitable wrapping. Without the memo, every public-method
|
|
60
|
+
* call would produce a fresh wrapper and break referential-equality
|
|
61
|
+
* guarantees that hook-style reactive consumers depend on.
|
|
62
|
+
*
|
|
63
|
+
* Backed by a `WeakMap`, so wrappers are GC'd when their source is.
|
|
64
|
+
*/
|
|
65
|
+
static from<T>(source: Observable<T | undefined>): CacheObservable<T>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Discriminated phases of an upload's lifecycle.
|
|
69
|
+
*
|
|
70
|
+
* - `started` — emitted immediately on `yield.resource(...)` invocation, before any bytes flow.
|
|
71
|
+
* - `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.
|
|
72
|
+
* - `finished` — emitted on backend acknowledgement, carries the assigned `resourceId`.
|
|
73
|
+
*
|
|
74
|
+
* 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.
|
|
75
|
+
*/
|
|
76
|
+
export type UploadProgress = {
|
|
77
|
+
phase: 'started';
|
|
78
|
+
totalBytes: number;
|
|
79
|
+
} | {
|
|
80
|
+
phase: 'progress';
|
|
81
|
+
bytesUploaded: number;
|
|
82
|
+
totalBytes: number;
|
|
83
|
+
} | {
|
|
84
|
+
phase: 'finished';
|
|
85
|
+
resourceId: ResourceId;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Specialized `StreamObservable` for `yield.resource`. Subscribers see the
|
|
89
|
+
* full `UploadProgress` event sequence (started → optional progress → finished).
|
|
90
|
+
* Awaiting resolves specifically to `{ resourceId }` extracted from the
|
|
91
|
+
* `'finished'` event — preserving the pre-Phase-18 awaited shape so existing
|
|
92
|
+
* `await client.yield.resource(...)` callers don't need to narrow the union.
|
|
93
|
+
*/
|
|
94
|
+
export declare class UploadObservable extends Observable<UploadProgress> implements PromiseLike<{
|
|
95
|
+
resourceId: ResourceId;
|
|
96
|
+
}> {
|
|
97
|
+
then<R1 = {
|
|
98
|
+
resourceId: ResourceId;
|
|
99
|
+
}, R2 = never>(onfulfilled?: ((v: {
|
|
100
|
+
resourceId: ResourceId;
|
|
101
|
+
}) => R1 | PromiseLike<R1>) | null, onrejected?: ((e: unknown) => R2 | PromiseLike<R2>) | null): PromiseLike<R1 | R2>;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=awaitable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"awaitable.d.ts","sourceRoot":"","sources":["../src/awaitable.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,UAAU,EAAiC,MAAM,MAAM,CAAC;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;GAOG;AACH,qBAAa,gBAAgB,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;IAC9E,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,KAAK,EACrB,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EACrD,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,GACzD,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;IAIvB,8EAA8E;IAC9E,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC;CAG3D;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,eAAe,CAAC,CAAC,CAAE,SAAQ,UAAU,CAAC,CAAC,GAAG,SAAS,CAAE,YAAW,WAAW,CAAC,CAAC,CAAC;IACzF,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,KAAK,EACrB,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EACrD,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,GACzD,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;IAKvB;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC;CAQtE;AAID;;;;;;;;GAQG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAChE;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC;AAElD;;;;;;GAMG;AACH,qBAAa,gBAAiB,SAAQ,UAAU,CAAC,cAAc,CAAE,YAAW,WAAW,CAAC;IAAE,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC;IACjH,IAAI,CAAC,EAAE,GAAG;QAAE,UAAU,EAAE,UAAU,CAAA;KAAE,EAAE,EAAE,GAAG,KAAK,EAC9C,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;QAAE,UAAU,EAAE,UAAU,CAAA;KAAE,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,EAC9E,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,GACzD,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC;CASxB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { SemiontError, type EventMap } from '@semiont/core';
|
|
3
|
+
export type BusRequestErrorCode = 'bus.timeout' | 'bus.rejected' | 'bus.bad-payload' | 'bus.unauthorized' | 'bus.forbidden' | 'bus.not-found';
|
|
4
|
+
export declare class BusRequestError extends SemiontError {
|
|
5
|
+
code: BusRequestErrorCode;
|
|
6
|
+
constructor(message: string, code: BusRequestErrorCode, details?: Record<string, unknown>);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Subset of ITransport that `busRequest` needs: a way to send a command and
|
|
10
|
+
* a way to observe channels. Generic enough that an in-process transport
|
|
11
|
+
* can satisfy it without round-tripping through HTTP.
|
|
12
|
+
*/
|
|
13
|
+
export interface BusRequestPrimitive {
|
|
14
|
+
emit<K extends keyof EventMap>(channel: K, payload: EventMap[K]): Promise<void>;
|
|
15
|
+
stream<K extends keyof EventMap>(channel: K): Observable<EventMap[K]>;
|
|
16
|
+
}
|
|
17
|
+
export declare function busRequest<TResult>(bus: BusRequestPrimitive, emitChannel: string, payload: Record<string, unknown>, resultChannel: string, failureChannel: string, timeoutMs?: number): Promise<TResult>;
|
|
18
|
+
//# sourceMappingURL=bus-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus-request.d.ts","sourceRoot":"","sources":["../src/bus-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmD,MAAM,MAAM,CAAC;AAEnF,OAAO,EAAE,YAAY,EAAE,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE5D,MAAM,MAAM,mBAAmB,GAC3B,aAAa,GACb,cAAc,GACd,iBAAiB,GACjB,kBAAkB,GAClB,eAAe,GACf,eAAe,CAAC;AAEpB,qBAAa,eAAgB,SAAQ,YAAY;IACvC,IAAI,EAAE,mBAAmB,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAI1F;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,MAAM,CAAC,CAAC,SAAS,MAAM,QAAQ,EAAE,OAAO,EAAE,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;CACvE;AAED,wBAAsB,UAAU,CAAC,OAAO,EACtC,GAAG,EAAE,mBAAmB,EACxB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,SAAS,SAAS,GACjB,OAAO,CAAC,OAAO,CAAC,CA+ClB"}
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RxJS-native read-through cache primitive.
|
|
3
|
+
*
|
|
4
|
+
* Behavioral contract: packages/sdk/docs/CACHE-SEMANTICS.md (B1–B13).
|
|
5
|
+
*
|
|
6
|
+
* Framework-agnostic: no React, no dependency on any namespace. Used by
|
|
7
|
+
* `BrowseNamespace` to back its per-key stores, but equally usable from
|
|
8
|
+
* CLI, MCP, or worker code.
|
|
9
|
+
*
|
|
10
|
+
* Shape:
|
|
11
|
+
* - `observe(key)`: returns an Observable<V | undefined> that triggers
|
|
12
|
+
* a fetch on first subscription for a missing key, dedup-joins any
|
|
13
|
+
* concurrent fetch, and emits the stored value thereafter.
|
|
14
|
+
* - `invalidate(key)`: stale-while-revalidate — keeps the current
|
|
15
|
+
* value visible to observers, clears the in-flight guard, starts a
|
|
16
|
+
* fresh fetch. If the previous fetch was orphaned (SSE torn down,
|
|
17
|
+
* response lost), this is how the cache recovers.
|
|
18
|
+
* - `remove(key)`: drops the cache entry entirely. Used for entity
|
|
19
|
+
* deletions (B13a). No refetch.
|
|
20
|
+
* - `set(key, value)`: writes through without a fetch. Used when a
|
|
21
|
+
* bus event carries the new value inline (B13b).
|
|
22
|
+
* - `invalidateAll()`: per-key SWR refetch of every currently-cached
|
|
23
|
+
* entry. Used by gap-detection paths.
|
|
24
|
+
* - `dispose()`: completes the store so observers unsubscribe.
|
|
25
|
+
*
|
|
26
|
+
* What's deliberately out:
|
|
27
|
+
* - No subscriber ref-counting / GC of unobserved keys. The per-key
|
|
28
|
+
* observable memo grows with the set of observed keys for the cache's
|
|
29
|
+
* lifetime (B11). Acceptable given cache lifetime == client lifetime.
|
|
30
|
+
* - No TTL / cacheTime. Entries are evicted only by explicit remove.
|
|
31
|
+
* - No retry / backoff. A failing fetch leaves the cache unchanged
|
|
32
|
+
* (B6); the caller drives retry via invalidate.
|
|
33
|
+
*/
|
|
34
|
+
import { Observable } from 'rxjs';
|
|
35
|
+
export interface Cache<K, V> {
|
|
36
|
+
/** Observable stream of the value at `key`. Triggers a fetch if not cached. */
|
|
37
|
+
observe(key: K): Observable<V | undefined>;
|
|
38
|
+
/** Synchronous snapshot of the current value, without triggering a fetch. */
|
|
39
|
+
get(key: K): V | undefined;
|
|
40
|
+
/** Iterator of currently-cached keys. For invalidateAll and diagnostics. */
|
|
41
|
+
keys(): K[];
|
|
42
|
+
/**
|
|
43
|
+
* Mark the entry stale and refetch. Keeps the previous value visible
|
|
44
|
+
* to observers during the refetch (stale-while-revalidate).
|
|
45
|
+
*/
|
|
46
|
+
invalidate(key: K): void;
|
|
47
|
+
/** Drop the entry from the cache. No refetch. */
|
|
48
|
+
remove(key: K): void;
|
|
49
|
+
/** Write-through: set the value directly without a fetch. */
|
|
50
|
+
set(key: K, value: V): void;
|
|
51
|
+
/** Per-key SWR refetch of every currently-cached entry. */
|
|
52
|
+
invalidateAll(): void;
|
|
53
|
+
/** Release the underlying subject. Observers complete. */
|
|
54
|
+
dispose(): void;
|
|
55
|
+
}
|
|
56
|
+
export declare function createCache<K, V>(fetchFn: (key: K) => Promise<V>): Cache<K, V>;
|
|
57
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAmB,UAAU,EAA6B,MAAM,MAAM,CAAC;AAE9E,MAAM,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;IACzB,+EAA+E;IAC/E,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAE3C,6EAA6E;IAC7E,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;IAE3B,4EAA4E;IAC5E,IAAI,IAAI,CAAC,EAAE,CAAC;IAEZ;;;OAGG;IACH,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;IAEzB,iDAAiD;IACjD,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;IAErB,6DAA6D;IAC7D,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IAE5B,2DAA2D;IAC3D,aAAa,IAAI,IAAI,CAAC;IAEtB,0DAA0D;IAC1D,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CA0F9E"}
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SemiontClient — the verb-oriented namespace surface.
|
|
3
|
+
*
|
|
4
|
+
* Thin coordinator over an injected transport pair. Owns a local
|
|
5
|
+
* `EventBus` (`bus`) for UI-signal channels and bridges wire events into
|
|
6
|
+
* it via `transport.bridgeInto(bus)`. Namespaces receive `(transport,
|
|
7
|
+
* bus)` (and `content` for binary-I/O namespaces) and choose internally
|
|
8
|
+
* whether each method goes over the wire or stays local.
|
|
9
|
+
*
|
|
10
|
+
* No public `emit`/`on`/`stream` shortcuts: consumers call typed
|
|
11
|
+
* namespace methods. The single sanctioned channel-by-name escape hatch
|
|
12
|
+
* is `SemiontSession.subscribe(channel, handler)`, which reads from
|
|
13
|
+
* `client.bus`.
|
|
14
|
+
*/
|
|
15
|
+
import type { ResourceId, BaseUrl, AccessToken } from '@semiont/core';
|
|
16
|
+
import { EventBus } from '@semiont/core';
|
|
17
|
+
import { BrowseNamespace } from './namespaces/browse';
|
|
18
|
+
import { MarkNamespace } from './namespaces/mark';
|
|
19
|
+
import { BindNamespace } from './namespaces/bind';
|
|
20
|
+
import { GatherNamespace } from './namespaces/gather';
|
|
21
|
+
import { MatchNamespace } from './namespaces/match';
|
|
22
|
+
import { YieldNamespace } from './namespaces/yield';
|
|
23
|
+
import { BeckonNamespace } from './namespaces/beckon';
|
|
24
|
+
import { FrameNamespace } from './namespaces/frame';
|
|
25
|
+
import { JobNamespace } from './namespaces/job';
|
|
26
|
+
import { AuthNamespace } from './namespaces/auth';
|
|
27
|
+
import { AdminNamespace } from './namespaces/admin';
|
|
28
|
+
import type { IBackendOperations, IContentTransport, ITransport } from '@semiont/core';
|
|
29
|
+
export { APIError, type TokenRefresher, HttpTransport, type HttpTransportConfig, HttpContentTransport, } from '@semiont/api-client';
|
|
30
|
+
export declare class SemiontClient {
|
|
31
|
+
/**
|
|
32
|
+
* The wire-facing transport. Owns bus actor, HTTP, auth, admin, exchange,
|
|
33
|
+
* system. Exposed for advanced consumers (workers, custom job adapters)
|
|
34
|
+
* that need raw `transport.emit(channel, payload, scope)` access. Ordinary
|
|
35
|
+
* consumers go through typed namespace methods.
|
|
36
|
+
*/
|
|
37
|
+
readonly transport: ITransport;
|
|
38
|
+
/** Binary I/O transport. */
|
|
39
|
+
private readonly content;
|
|
40
|
+
/**
|
|
41
|
+
* Per-client local EventBus. Wire events flow in via the transport
|
|
42
|
+
* bridge. Read-only public so `SemiontSession.subscribe(channel, …)`
|
|
43
|
+
* can wire arbitrary-channel subscriptions; everything else uses
|
|
44
|
+
* typed namespace methods.
|
|
45
|
+
*/
|
|
46
|
+
readonly bus: EventBus;
|
|
47
|
+
readonly baseUrl: BaseUrl;
|
|
48
|
+
readonly frame: FrameNamespace;
|
|
49
|
+
readonly browse: BrowseNamespace;
|
|
50
|
+
readonly mark: MarkNamespace;
|
|
51
|
+
readonly bind: BindNamespace;
|
|
52
|
+
readonly gather: GatherNamespace;
|
|
53
|
+
readonly match: MatchNamespace;
|
|
54
|
+
readonly yield: YieldNamespace;
|
|
55
|
+
readonly beckon: BeckonNamespace;
|
|
56
|
+
readonly job: JobNamespace;
|
|
57
|
+
readonly auth: AuthNamespace | undefined;
|
|
58
|
+
readonly admin: AdminNamespace | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* The client *owns* its bus. The constructor creates a fresh `EventBus`
|
|
61
|
+
* and hands it to the transport via `transport.bridgeInto(this.bus)`.
|
|
62
|
+
* The reference flows client → transport, never the other way:
|
|
63
|
+
* the transport stores the reference and publishes the events it
|
|
64
|
+
* receives onto that bus. `HttpTransport` does so for every channel
|
|
65
|
+
* delivered on its SSE wire; in-process transports adapt their
|
|
66
|
+
* internal source.
|
|
67
|
+
*
|
|
68
|
+
* Callers do not pass a bus in. If they need to interact with the bus
|
|
69
|
+
* (e.g. for tests or to subscribe to arbitrary channels), they read it
|
|
70
|
+
* back via `client.bus`.
|
|
71
|
+
*
|
|
72
|
+
* `backend` is optional. When provided, the `auth` and `admin`
|
|
73
|
+
* namespaces are constructed against it; when omitted, they're
|
|
74
|
+
* `undefined`. For HTTP setups this is conventionally the same
|
|
75
|
+
* `HttpTransport` instance that's also passed as `transport` (HTTP
|
|
76
|
+
* implements both `ITransport` and `IBackendOperations`).
|
|
77
|
+
*/
|
|
78
|
+
constructor(transport: ITransport, content: IContentTransport, backend?: IBackendOperations);
|
|
79
|
+
/** Transport-level connection state. HTTP reflects SSE health; local is always 'connected'. */
|
|
80
|
+
get state$(): import("rxjs").Observable<import("@semiont/core").ConnectionState>;
|
|
81
|
+
subscribeToResource(resourceId: ResourceId): () => void;
|
|
82
|
+
dispose(): void;
|
|
83
|
+
/**
|
|
84
|
+
* Convenience factory for the default HTTP setup. Constructs a
|
|
85
|
+
* `BehaviorSubject<AccessToken | null>` internally, plus an
|
|
86
|
+
* `HttpTransport` and `HttpContentTransport`, and returns the wired
|
|
87
|
+
* `SemiontClient`.
|
|
88
|
+
*
|
|
89
|
+
* Use this for one-shot scripts, CLI commands, or any consumer that
|
|
90
|
+
* doesn't need to drive the token from outside (no manual refresh,
|
|
91
|
+
* no cross-tab sync). For long-running scripts that need refresh,
|
|
92
|
+
* use `SemiontSession.fromHttp(...)` (with a token already on hand)
|
|
93
|
+
* or `SemiontSession.signInHttp(...)` (credentials-first) instead —
|
|
94
|
+
* either owns the same transport/client wiring plus the
|
|
95
|
+
* proactive-refresh + storage machinery.
|
|
96
|
+
*
|
|
97
|
+
* Strings are accepted for `baseUrl` and `token`; they are branded
|
|
98
|
+
* via `baseUrl()` / `accessToken()` from `@semiont/core` automatically.
|
|
99
|
+
* Pass the already-branded values if you have them.
|
|
100
|
+
*
|
|
101
|
+
* Omit `token` for unauthenticated usage (public endpoints only).
|
|
102
|
+
*/
|
|
103
|
+
static fromHttp(opts: {
|
|
104
|
+
baseUrl: BaseUrl | string;
|
|
105
|
+
token?: AccessToken | string | null;
|
|
106
|
+
}): SemiontClient;
|
|
107
|
+
/**
|
|
108
|
+
* Async factory for the credentials-first script case. Builds a
|
|
109
|
+
* transient HTTP transport, calls `auth.password(email, password)`
|
|
110
|
+
* to acquire an access token, and returns the wired client with
|
|
111
|
+
* the token populated.
|
|
112
|
+
*
|
|
113
|
+
* This is the right entry point for skills, CLI scripts, and any
|
|
114
|
+
* consumer that starts with email + password rather than a JWT
|
|
115
|
+
* already on hand. For consumers that already hold a token (CLI
|
|
116
|
+
* cached-token path, env-var token, embedded auth flow), use
|
|
117
|
+
* `fromHttp({ baseUrl, token })` instead.
|
|
118
|
+
*
|
|
119
|
+
* For long-running scripts that need refresh, use
|
|
120
|
+
* `SemiontSession.signInHttp(...)` — same credentials shape, plus
|
|
121
|
+
* the session machinery for proactive refresh and persistence.
|
|
122
|
+
*
|
|
123
|
+
* Named `signInHttp` because email+password authentication is
|
|
124
|
+
* inherently an HTTP-shaped operation in the current backend; an
|
|
125
|
+
* in-process `LocalTransport` doesn't have a credentials login
|
|
126
|
+
* path. Non-HTTP transports construct the client directly from
|
|
127
|
+
* their package's transport instance.
|
|
128
|
+
*
|
|
129
|
+
* Throws if authentication fails. The transient client is disposed
|
|
130
|
+
* before the throw, so no resources leak on failure.
|
|
131
|
+
*/
|
|
132
|
+
static signInHttp(opts: {
|
|
133
|
+
baseUrl: BaseUrl | string;
|
|
134
|
+
email: string;
|
|
135
|
+
password: string;
|
|
136
|
+
}): Promise<SemiontClient>;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAwB,MAAM,eAAe,CAAC;AAE/D,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAevF,OAAO,EACL,QAAQ,EACR,KAAK,cAAc,EACnB,aAAa,EACb,KAAK,mBAAmB,EACxB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,aAAa;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,4BAA4B;IAC5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAW1B,SAAgB,KAAK,EAAE,cAAc,CAAC;IACtC,SAAgB,MAAM,EAAE,eAAe,CAAC;IACxC,SAAgB,IAAI,EAAE,aAAa,CAAC;IACpC,SAAgB,IAAI,EAAE,aAAa,CAAC;IACpC,SAAgB,MAAM,EAAE,eAAe,CAAC;IACxC,SAAgB,KAAK,EAAE,cAAc,CAAC;IACtC,SAAgB,KAAK,EAAE,cAAc,CAAC;IACtC,SAAgB,MAAM,EAAE,eAAe,CAAC;IACxC,SAAgB,GAAG,EAAE,YAAY,CAAC;IAClC,SAAgB,IAAI,EAAE,aAAa,GAAG,SAAS,CAAC;IAChD,SAAgB,KAAK,EAAE,cAAc,GAAG,SAAS,CAAC;IAElD;;;;;;;;;;;;;;;;;;OAkBG;gBACS,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,kBAAkB;IAqB3F,+FAA+F;IAC/F,IAAI,MAAM,uEAET;IAED,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,IAAI;IAIvD,OAAO,IAAI,IAAI;IAKf;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QACpB,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;QAC1B,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC;KACrC,GAAG,aAAa;IAajB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;WACU,UAAU,CAAC,IAAI,EAAE;QAC5B,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC;QAC1B,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,aAAa,CAAC;CAgB3B"}
|