@vibesdotdev/runtime-client 0.0.1
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 +97 -0
- package/SPEC.md +44 -0
- package/dist/base.d.ts +49 -0
- package/dist/base.d.ts.map +1 -0
- package/dist/base.js +86 -0
- package/dist/base.js.map +1 -0
- package/dist/contract.d.ts +23 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +2 -0
- package/dist/contract.js.map +1 -0
- package/dist/docs/runtime-client.api.docs.descriptor.d.ts +8 -0
- package/dist/docs/runtime-client.api.docs.descriptor.d.ts.map +1 -0
- package/dist/docs/runtime-client.api.docs.descriptor.js +344 -0
- package/dist/docs/runtime-client.api.docs.descriptor.js.map +1 -0
- package/dist/docs/runtime-client.helpers.docs.descriptor.d.ts +8 -0
- package/dist/docs/runtime-client.helpers.docs.descriptor.d.ts.map +1 -0
- package/dist/docs/runtime-client.helpers.docs.descriptor.js +352 -0
- package/dist/docs/runtime-client.helpers.docs.descriptor.js.map +1 -0
- package/dist/docs/runtime-client.surface.docs.descriptor.d.ts +8 -0
- package/dist/docs/runtime-client.surface.docs.descriptor.d.ts.map +1 -0
- package/dist/docs/runtime-client.surface.docs.descriptor.js +464 -0
- package/dist/docs/runtime-client.surface.docs.descriptor.js.map +1 -0
- package/dist/docs/types.d.ts +19 -0
- package/dist/docs/types.d.ts.map +1 -0
- package/dist/docs/types.js +2 -0
- package/dist/docs/types.js.map +1 -0
- package/dist/helper.d.ts +14 -0
- package/dist/helper.d.ts.map +1 -0
- package/dist/helper.js +27 -0
- package/dist/helper.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/kind.d.ts +10 -0
- package/dist/kind.d.ts.map +1 -0
- package/dist/kind.js +12 -0
- package/dist/kind.js.map +1 -0
- package/dist/plugin.d.ts +10 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +17 -0
- package/dist/plugin.js.map +1 -0
- package/dist/runtime-client.plugin.d.ts +13 -0
- package/dist/runtime-client.plugin.d.ts.map +1 -0
- package/dist/runtime-client.plugin.js +27 -0
- package/dist/runtime-client.plugin.js.map +1 -0
- package/dist/schema.d.ts +32 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +8 -0
- package/dist/schema.js.map +1 -0
- package/package.json +61 -0
- package/src/base.ts +100 -0
- package/src/contract.ts +23 -0
- package/src/docs/runtime-client.api.docs.descriptor.ts +346 -0
- package/src/docs/runtime-client.helpers.docs.descriptor.ts +354 -0
- package/src/docs/runtime-client.surface.docs.descriptor.ts +466 -0
- package/src/docs/types.ts +18 -0
- package/src/helper.ts +32 -0
- package/src/index.ts +11 -0
- package/src/kind.ts +14 -0
- package/src/plugin.ts +19 -0
- package/src/runtime-client.plugin.ts +32 -0
- package/src/schema.ts +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @vibesdotdev/runtime-client
|
|
2
|
+
|
|
3
|
+
The `runtime/client` kind and `BaseRuntimeClient`. Every module that exposes
|
|
4
|
+
functionality across the monorepo does so through exactly one client registered
|
|
5
|
+
under this kind.
|
|
6
|
+
|
|
7
|
+
## Authoring a new client
|
|
8
|
+
|
|
9
|
+
Mechanical recipe. No variation.
|
|
10
|
+
|
|
11
|
+
### 1. Define the client class
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// <module>/src/lib/client/runtime-client.ts
|
|
15
|
+
import { BaseRuntimeClient, type RuntimeClientDescriptor } from '@vibesdotdev/runtime-client';
|
|
16
|
+
import type { VibesRuntime } from '@vibesdotdev/runtime';
|
|
17
|
+
|
|
18
|
+
export class MyModuleClient extends BaseRuntimeClient {
|
|
19
|
+
constructor(
|
|
20
|
+
descriptor: RuntimeClientDescriptor = { id: 'my-module', kind: 'runtime/client' },
|
|
21
|
+
context?: unknown,
|
|
22
|
+
runtime?: VibesRuntime,
|
|
23
|
+
) {
|
|
24
|
+
super(descriptor, context, runtime);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async doSomething(/* … */) {
|
|
28
|
+
// resolve other kinds via this.runtime.query(...)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Register in the module's plugin
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
export default createRuntimePlugin({
|
|
37
|
+
id: 'my-module',
|
|
38
|
+
dependencies: ['runtime-client', /* … */],
|
|
39
|
+
onRegister(runtime) {
|
|
40
|
+
runtime.registerDescriptor('runtime/client', {
|
|
41
|
+
id: 'my-module',
|
|
42
|
+
kind: 'runtime/client',
|
|
43
|
+
description: 'Canonical MyModule client',
|
|
44
|
+
});
|
|
45
|
+
runtime.registerLoader('runtime/client', 'my-module', async () => {
|
|
46
|
+
const { MyModuleClient } = await import('./client/runtime-client.js');
|
|
47
|
+
return { impl: MyModuleClient };
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. Export the ambient helper
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// <module>/src/lib/client/helper.ts
|
|
57
|
+
import { getVibesClient } from '@vibesdotdev/runtime-client';
|
|
58
|
+
import type { MyModuleClient } from './runtime-client';
|
|
59
|
+
|
|
60
|
+
export async function getVibesMyModuleClient(): Promise<MyModuleClient> {
|
|
61
|
+
return getVibesClient<MyModuleClient>('my-module');
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 4. Expose via module barrel + `package.json` subpath
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
// <module>/src/lib/client/index.ts
|
|
69
|
+
export { MyModuleClient } from './runtime-client';
|
|
70
|
+
export { getVibesMyModuleClient } from './helper';
|
|
71
|
+
export type * from './contracts';
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Add `"./client"` to the module's `package.json#exports`.
|
|
75
|
+
|
|
76
|
+
## Consuming another module's client
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { getVibesToolsClient } from '@vibesdotdev/tools/client';
|
|
80
|
+
const tools = await getVibesToolsClient();
|
|
81
|
+
const agent = await tools.getAgent('assistant');
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If the other module exposes only kinds (no client), use `runtime.query('<kind>').…`
|
|
85
|
+
directly. Never deep-import another module's internals.
|
|
86
|
+
|
|
87
|
+
## Test
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
bun test src/__tests__/
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Docs
|
|
94
|
+
|
|
95
|
+
- [SPEC.md](./SPEC.md) — package contract, owned surfaces, hard rules
|
|
96
|
+
- [runtime](../runtime/SPEC.md) — registry/query layer this builds on
|
|
97
|
+
- [client](../client/SPEC.md) — sister `api/client` kind for HTTP clients
|
package/SPEC.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# @vibesdotdev/runtime-client
|
|
2
|
+
|
|
3
|
+
The `runtime/client` kind + the shared base every module-level client extends. One client per module, runtime-resolved.
|
|
4
|
+
|
|
5
|
+
## Owns
|
|
6
|
+
|
|
7
|
+
- `runtime/client` kind (registered via `./plugin`)
|
|
8
|
+
- `BaseRuntimeClient` abstract class — ambient runtime acquisition, idempotent `load()`/`ensureLoaded()`, optional `config/manifest` auto-load via `descriptor.configManifestId`, `onLoad`/`onDispose` hooks, `(descriptor, context?, runtime?)` constructor signature
|
|
9
|
+
- `RuntimeClient` interface (`./contract`)
|
|
10
|
+
- `RuntimeClientDescriptor` zod schema (`./schema`)
|
|
11
|
+
- `getVibesClient<T>(id)` ambient helper
|
|
12
|
+
|
|
13
|
+
## Does not own
|
|
14
|
+
|
|
15
|
+
- HTTP abstraction → [`@vibesdotdev/client`](../client/SPEC.md) (`api/client` kind)
|
|
16
|
+
- Config manager → [`@vibesdotdev/config`](../config/SPEC.md) (`config/manifest` kind)
|
|
17
|
+
- Registry / kind resolution → [`@vibesdotdev/runtime`](../runtime/SPEC.md)
|
|
18
|
+
- Any module's domain methods — those live on each module's subclass
|
|
19
|
+
|
|
20
|
+
## Hard rules
|
|
21
|
+
|
|
22
|
+
- **One client per module.** No split HTTP-vs-in-process clients. No module-specific factories competing with the canonical one.
|
|
23
|
+
- **All module clients extend `BaseRuntimeClient`.** They do not reimplement lifecycle, config-load, or runtime acquisition.
|
|
24
|
+
- **Scope selection lives inside the client**, never in consumers. Consumers call `client.foo()` and never branch on hardware/connection mode.
|
|
25
|
+
- **Cross-module access goes through (1) the other module's client, or (2) direct `runtime.query('<kind>')` for primitives.** Never deep-import another module's internals. Never duplicate another module's types.
|
|
26
|
+
- **Two sanctioned client flavors only:** `runtime/client` (this package) and `api/client` ([`@vibesdotdev/client`](../client/SPEC.md)). New flavors require a SPEC update.
|
|
27
|
+
- This package depends only on `@vibesdotdev/runtime` and `zod`. It does not import any module's domain code.
|
|
28
|
+
|
|
29
|
+
## Public entrypoints
|
|
30
|
+
|
|
31
|
+
- `.` — `BaseRuntimeClient`, `getVibesClient`, `RuntimeClient` type, descriptor schema (barrel)
|
|
32
|
+
- `./plugin` — `runtimeClientPlugin` (registers the kind)
|
|
33
|
+
- `./contract` — `RuntimeClient` (type-only)
|
|
34
|
+
- `./schema` — `RuntimeClientDescriptor` zod schema
|
|
35
|
+
- `./base` — `BaseRuntimeClient`
|
|
36
|
+
|
|
37
|
+
## Verification
|
|
38
|
+
|
|
39
|
+
`bun test src/__tests__/`. Covers kind registration, base lifecycle, `getVibesClient` resolution, descriptor schema.
|
|
40
|
+
|
|
41
|
+
## Links
|
|
42
|
+
|
|
43
|
+
- [runtime/SPEC.md](../runtime/SPEC.md)
|
|
44
|
+
- [client/SPEC.md](../client/SPEC.md) — sister `api/client` kind
|
package/dist/base.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type VibesRuntime } from '@vibesdotdev/runtime';
|
|
2
|
+
import type { RuntimeClient } from './contract.ts';
|
|
3
|
+
import type { RuntimeClientDescriptor } from './schema.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Shared base for module-level clients.
|
|
6
|
+
*
|
|
7
|
+
* Handles:
|
|
8
|
+
* - ambient runtime acquisition (via `getVibesRuntime()`)
|
|
9
|
+
* - idempotent lazy init (`ensureLoaded()`)
|
|
10
|
+
* - `config/manifest` auto-loading when `descriptor.configManifestId` is set
|
|
11
|
+
* - lifecycle hooks (`onLoad`, `onDispose`) for subclasses
|
|
12
|
+
*
|
|
13
|
+
* Subclasses (AIClient, ToolsClient, …) add their domain methods and call
|
|
14
|
+
* `this.ensureLoaded()` at method entry points when their behavior depends
|
|
15
|
+
* on loaded config.
|
|
16
|
+
*
|
|
17
|
+
* Constructor signature matches the runtime's kind-instantiation contract:
|
|
18
|
+
* `(descriptor, context?)`. Context is not currently consumed — runtime
|
|
19
|
+
* access goes through the ambient singleton — but remains a parameter for
|
|
20
|
+
* forward compatibility with kind contexts that carry scope metadata.
|
|
21
|
+
*/
|
|
22
|
+
export declare abstract class BaseRuntimeClient implements RuntimeClient {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
readonly runtime: VibesRuntime;
|
|
25
|
+
protected readonly descriptor: RuntimeClientDescriptor;
|
|
26
|
+
protected configValues: unknown | null;
|
|
27
|
+
private loadPromise?;
|
|
28
|
+
constructor(descriptor: RuntimeClientDescriptor, _context?: unknown, runtime?: VibesRuntime);
|
|
29
|
+
/**
|
|
30
|
+
* Idempotent lazy init. First call drives `onLoad()`; subsequent calls
|
|
31
|
+
* await the same promise. Subclasses call this at method entry points
|
|
32
|
+
* when they need config loaded.
|
|
33
|
+
*/
|
|
34
|
+
ensureLoaded(): Promise<void>;
|
|
35
|
+
/** Public `load()` matching the `RuntimeClient` contract. Alias of `ensureLoaded()`. */
|
|
36
|
+
load(): Promise<void>;
|
|
37
|
+
dispose(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Override to perform module-specific initialization. Default behavior:
|
|
40
|
+
* if `descriptor.configManifestId` is set, resolve the corresponding
|
|
41
|
+
* `config/manifest` and load its values into `this.configValues`.
|
|
42
|
+
*/
|
|
43
|
+
protected onLoad(): Promise<void>;
|
|
44
|
+
protected onDispose(): void;
|
|
45
|
+
/** Subclass accessor for loaded config values (null if load hasn't run or failed). */
|
|
46
|
+
protected getConfigValues<T = unknown>(): T | null;
|
|
47
|
+
private runLoad;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,8BAAsB,iBAAkB,YAAW,aAAa;IAC/D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAE/B,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,uBAAuB,CAAC;IACvD,SAAS,CAAC,YAAY,EAAE,OAAO,GAAG,IAAI,CAAQ;IAE9C,OAAO,CAAC,WAAW,CAAC,CAAgB;gBAGnC,UAAU,EAAE,uBAAuB,EACnC,QAAQ,CAAC,EAAE,OAAO,EAClB,OAAO,CAAC,EAAE,YAAY;IAUvB;;;;OAIG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC,wFAAwF;IAClF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,OAAO,IAAI,IAAI;IAMf;;;;OAIG;cACa,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBvC,SAAS,CAAC,SAAS,IAAI,IAAI;IAE3B,sFAAsF;IACtF,SAAS,CAAC,eAAe,CAAC,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,IAAI;YAIpC,OAAO;CAGrB"}
|
package/dist/base.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { getVibesRuntime } from '@vibesdotdev/runtime';
|
|
2
|
+
/**
|
|
3
|
+
* Shared base for module-level clients.
|
|
4
|
+
*
|
|
5
|
+
* Handles:
|
|
6
|
+
* - ambient runtime acquisition (via `getVibesRuntime()`)
|
|
7
|
+
* - idempotent lazy init (`ensureLoaded()`)
|
|
8
|
+
* - `config/manifest` auto-loading when `descriptor.configManifestId` is set
|
|
9
|
+
* - lifecycle hooks (`onLoad`, `onDispose`) for subclasses
|
|
10
|
+
*
|
|
11
|
+
* Subclasses (AIClient, ToolsClient, …) add their domain methods and call
|
|
12
|
+
* `this.ensureLoaded()` at method entry points when their behavior depends
|
|
13
|
+
* on loaded config.
|
|
14
|
+
*
|
|
15
|
+
* Constructor signature matches the runtime's kind-instantiation contract:
|
|
16
|
+
* `(descriptor, context?)`. Context is not currently consumed — runtime
|
|
17
|
+
* access goes through the ambient singleton — but remains a parameter for
|
|
18
|
+
* forward compatibility with kind contexts that carry scope metadata.
|
|
19
|
+
*/
|
|
20
|
+
export class BaseRuntimeClient {
|
|
21
|
+
id;
|
|
22
|
+
runtime;
|
|
23
|
+
descriptor;
|
|
24
|
+
configValues = null;
|
|
25
|
+
loadPromise;
|
|
26
|
+
constructor(descriptor, _context, runtime) {
|
|
27
|
+
this.descriptor = descriptor;
|
|
28
|
+
this.id = descriptor.id;
|
|
29
|
+
// Ambient runtime is the default path (matches `getVibesClient<T>(id)`).
|
|
30
|
+
// Explicit runtime override is available for legacy factory callers and
|
|
31
|
+
// advanced scenarios (e.g. multi-runtime test harnesses).
|
|
32
|
+
this.runtime = runtime ?? getVibesRuntime();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Idempotent lazy init. First call drives `onLoad()`; subsequent calls
|
|
36
|
+
* await the same promise. Subclasses call this at method entry points
|
|
37
|
+
* when they need config loaded.
|
|
38
|
+
*/
|
|
39
|
+
async ensureLoaded() {
|
|
40
|
+
if (!this.loadPromise) {
|
|
41
|
+
this.loadPromise = this.runLoad();
|
|
42
|
+
}
|
|
43
|
+
return this.loadPromise;
|
|
44
|
+
}
|
|
45
|
+
/** Public `load()` matching the `RuntimeClient` contract. Alias of `ensureLoaded()`. */
|
|
46
|
+
async load() {
|
|
47
|
+
return this.ensureLoaded();
|
|
48
|
+
}
|
|
49
|
+
dispose() {
|
|
50
|
+
this.loadPromise = undefined;
|
|
51
|
+
this.configValues = null;
|
|
52
|
+
this.onDispose();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Override to perform module-specific initialization. Default behavior:
|
|
56
|
+
* if `descriptor.configManifestId` is set, resolve the corresponding
|
|
57
|
+
* `config/manifest` and load its values into `this.configValues`.
|
|
58
|
+
*/
|
|
59
|
+
async onLoad() {
|
|
60
|
+
const manifestId = this.descriptor.configManifestId;
|
|
61
|
+
if (!manifestId)
|
|
62
|
+
return;
|
|
63
|
+
try {
|
|
64
|
+
const manifest = (await this.runtime
|
|
65
|
+
.query('config/manifest')
|
|
66
|
+
.withId(manifestId)
|
|
67
|
+
.resolve());
|
|
68
|
+
if (manifest?.load) {
|
|
69
|
+
this.configValues = await manifest.load();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Config is best-effort at the base layer. Subclasses handle required/missing config.
|
|
74
|
+
this.configValues = null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
onDispose() { }
|
|
78
|
+
/** Subclass accessor for loaded config values (null if load hasn't run or failed). */
|
|
79
|
+
getConfigValues() {
|
|
80
|
+
return this.configValues;
|
|
81
|
+
}
|
|
82
|
+
async runLoad() {
|
|
83
|
+
await this.onLoad();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=base.js.map
|
package/dist/base.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAqB,MAAM,sBAAsB,CAAC;AAI1E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAgB,iBAAiB;IAC7B,EAAE,CAAS;IACX,OAAO,CAAe;IAEZ,UAAU,CAA0B;IAC7C,YAAY,GAAmB,IAAI,CAAC;IAEtC,WAAW,CAAiB;IAEpC,YACC,UAAmC,EACnC,QAAkB,EAClB,OAAsB;QAEtB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC;QACxB,yEAAyE;QACzE,wEAAwE;QACxE,0DAA0D;QAC1D,IAAI,CAAC,OAAO,GAAG,OAAO,IAAI,eAAe,EAAE,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY;QACjB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACvB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QACnC,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC;IAED,wFAAwF;IACxF,KAAK,CAAC,IAAI;QACT,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAED,OAAO;QACN,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,SAAS,EAAE,CAAC;IAClB,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,MAAM;QACrB,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;QACpD,IAAI,CAAC,UAAU;YAAE,OAAO;QACxB,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO;iBAClC,KAAK,CAAC,iBAAiB,CAAC;iBACxB,MAAM,CAAC,UAAU,CAAC;iBAClB,OAAO,EAAE,CAAkD,CAAC;YAC9D,IAAI,QAAQ,EAAE,IAAI,EAAE,CAAC;gBACpB,IAAI,CAAC,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3C,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,sFAAsF;YACtF,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC1B,CAAC;IACF,CAAC;IAES,SAAS,KAAU,CAAC;IAE9B,sFAAsF;IAC5E,eAAe;QACxB,OAAO,IAAI,CAAC,YAAwB,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,OAAO;QACpB,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;CACD"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { VibesRuntime } from '@vibesdotdev/runtime';
|
|
2
|
+
/**
|
|
3
|
+
* Base contract every module-level client satisfies.
|
|
4
|
+
*
|
|
5
|
+
* Module-specific clients extend this with domain methods:
|
|
6
|
+
* AIClient adds `generate`, `getProvider`, `listModels`, …
|
|
7
|
+
* ToolsClient adds `listTools`, `runTool`, …
|
|
8
|
+
* KnowledgeClient adds `search`, `ingest`, …
|
|
9
|
+
*
|
|
10
|
+
* All clients share the same shape for lifecycle + runtime access so that
|
|
11
|
+
* consumers, tests, and tooling can treat them uniformly.
|
|
12
|
+
*/
|
|
13
|
+
export interface RuntimeClient {
|
|
14
|
+
/** The descriptor id this client was registered with. */
|
|
15
|
+
readonly id: string;
|
|
16
|
+
/** Runtime reference the client uses for internal resolution. */
|
|
17
|
+
readonly runtime: VibesRuntime;
|
|
18
|
+
/** Idempotent load. Safe to call repeatedly; internal state cached. */
|
|
19
|
+
load(): Promise<void>;
|
|
20
|
+
/** Release any client-held resources (subscriptions, caches, etc.). */
|
|
21
|
+
dispose(): void;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,uEAAuE;IACvE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,uEAAuE;IACvE,OAAO,IAAI,IAAI,CAAC;CAChB"}
|
package/dist/contract.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DocsTopicDescriptor } from './types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Descriptor for runtime-client.api
|
|
4
|
+
* BaseRuntimeClient class, client patterns, how to extend
|
|
5
|
+
*/
|
|
6
|
+
declare const descriptor: DocsTopicDescriptor;
|
|
7
|
+
export default descriptor;
|
|
8
|
+
//# sourceMappingURL=runtime-client.api.docs.descriptor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-client.api.docs.descriptor.d.ts","sourceRoot":"","sources":["../../src/docs/runtime-client.api.docs.descriptor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD;;;GAGG;AACH,QAAA,MAAM,UAAU,EAAE,mBAiVjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Descriptor for runtime-client.api
|
|
3
|
+
* BaseRuntimeClient class, client patterns, how to extend
|
|
4
|
+
*/
|
|
5
|
+
const descriptor = {
|
|
6
|
+
kind: 'docs/topic',
|
|
7
|
+
id: 'runtime-client.api',
|
|
8
|
+
title: 'Runtime Client API',
|
|
9
|
+
summary: 'BaseRuntimeClient base class and patterns for extending module-level clients',
|
|
10
|
+
body: {
|
|
11
|
+
type: 'markdown',
|
|
12
|
+
sourceType: 'raw',
|
|
13
|
+
source: `---
|
|
14
|
+
title: Runtime Client API
|
|
15
|
+
summary: BaseRuntimeClient base class and patterns for extending module-level clients
|
|
16
|
+
tags: [runtime-client, base-class, extension, api, patterns]
|
|
17
|
+
parent: runtime-client
|
|
18
|
+
order: 1
|
|
19
|
+
surfaces: [cli, web, in-app]
|
|
20
|
+
hardware: [consumer, cloud]
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Runtime Client API
|
|
24
|
+
|
|
25
|
+
The \`BaseRuntimeClient\` class provides a shared foundation for module-level clients (AIClient, ToolsClient, KnowledgeClient, etc.). It handles runtime acquisition, idempotent lazy initialization, config loading, and lifecycle management.
|
|
26
|
+
|
|
27
|
+
## Architecture
|
|
28
|
+
|
|
29
|
+
Module clients follow a **one-client-per-module** pattern:
|
|
30
|
+
|
|
31
|
+
\`\`\`
|
|
32
|
+
┌─────────────────────────────────────────────────────────┐
|
|
33
|
+
│ Module Plugin (ai, tools, knowledge, etc.) │
|
|
34
|
+
│ - Registers runtime/client descriptor │
|
|
35
|
+
│ - Provides implementation class via loader │
|
|
36
|
+
└─────────────────────────────────────────────────────────┘
|
|
37
|
+
│
|
|
38
|
+
▼
|
|
39
|
+
┌─────────────────────────────────────────────────────────┐
|
|
40
|
+
│ RuntimeClient Implementation (extends BaseRuntimeClient)│
|
|
41
|
+
│ - Domain methods (generate, listTools, search, etc.) │
|
|
42
|
+
│ - Config access via this.getConfigValues<T>() │
|
|
43
|
+
│ - Runtime access via this.runtime │
|
|
44
|
+
└─────────────────────────────────────────────────────────┘
|
|
45
|
+
│
|
|
46
|
+
▼
|
|
47
|
+
┌─────────────────────────────────────────────────────────┐
|
|
48
|
+
│ BaseRuntimeClient (shared base) │
|
|
49
|
+
│ - Ambient runtime acquisition │
|
|
50
|
+
│ - Idempotent lazy init (ensureLoaded()) │
|
|
51
|
+
│ - Config manifest auto-loading │
|
|
52
|
+
│ - Lifecycle hooks (onLoad, onDispose) │
|
|
53
|
+
└─────────────────────────────────────────────────────────┘
|
|
54
|
+
\`\`\`
|
|
55
|
+
|
|
56
|
+
## BaseRuntimeClient
|
|
57
|
+
|
|
58
|
+
### Constructor
|
|
59
|
+
|
|
60
|
+
\`\`\`ts
|
|
61
|
+
constructor(
|
|
62
|
+
descriptor: RuntimeClientDescriptor,
|
|
63
|
+
_context?: unknown,
|
|
64
|
+
runtime?: VibesRuntime
|
|
65
|
+
)
|
|
66
|
+
\`\`\`
|
|
67
|
+
|
|
68
|
+
**Parameters:**
|
|
69
|
+
- \`descriptor\` — The \`runtime/client\` descriptor this client represents
|
|
70
|
+
- \`_context\` — Reserved for future scope metadata (not currently used)
|
|
71
|
+
- \`runtime\` — Optional explicit runtime override (defaults to \`getVibesRuntime()\`)
|
|
72
|
+
|
|
73
|
+
### Properties
|
|
74
|
+
|
|
75
|
+
\`\`\`ts
|
|
76
|
+
readonly id: string; // From descriptor.id
|
|
77
|
+
readonly runtime: VibesRuntime; // Ambient runtime singleton
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
### Lifecycle Methods
|
|
81
|
+
|
|
82
|
+
#### ensureLoaded() / load()
|
|
83
|
+
|
|
84
|
+
Idempotent lazy initialization. First call drives \`onLoad()\`; subsequent calls await the same promise.
|
|
85
|
+
|
|
86
|
+
\`\`\`ts
|
|
87
|
+
async ensureLoaded(): Promise<void>
|
|
88
|
+
async load(): Promise<void> // Alias of ensureLoaded()
|
|
89
|
+
\`\`\`
|
|
90
|
+
|
|
91
|
+
**When to call:** At method entry points when your client depends on loaded config.
|
|
92
|
+
|
|
93
|
+
\`\`\`ts
|
|
94
|
+
export class AIClient extends BaseRuntimeClient {
|
|
95
|
+
async generate(prompt: string): Promise<GenerationResponse> {
|
|
96
|
+
await this.ensureLoaded(); // Ensure config is loaded
|
|
97
|
+
|
|
98
|
+
const config = this.getConfigValues<AIConfig>();
|
|
99
|
+
const provider = await this.runtime.query('ai/provider')
|
|
100
|
+
.withId(config?.defaultProvider ?? 'anthropic')
|
|
101
|
+
.resolve();
|
|
102
|
+
|
|
103
|
+
return provider.generate({ prompt });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
\`\`\`
|
|
107
|
+
|
|
108
|
+
#### dispose()
|
|
109
|
+
|
|
110
|
+
Releases client-held resources:
|
|
111
|
+
|
|
112
|
+
\`\`\`ts
|
|
113
|
+
dispose(): void {
|
|
114
|
+
this.loadPromise = undefined;
|
|
115
|
+
this.configValues = null;
|
|
116
|
+
this.onDispose(); // Subclass hook
|
|
117
|
+
}
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
Call when shutting down the client (e.g., test teardown, hot reload).
|
|
121
|
+
|
|
122
|
+
### Protected Hooks for Subclasses
|
|
123
|
+
|
|
124
|
+
#### onLoad()
|
|
125
|
+
|
|
126
|
+
Override to perform module-specific initialization. Default behavior: if \`descriptor.configManifestId\` is set, resolves the corresponding \`config/manifest\` and loads its values.
|
|
127
|
+
|
|
128
|
+
\`\`\`ts
|
|
129
|
+
protected async onLoad(): Promise<void> {
|
|
130
|
+
// Default: load config manifest if specified
|
|
131
|
+
const manifestId = this.descriptor.configManifestId;
|
|
132
|
+
if (!manifestId) return;
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const manifest = await this.runtime
|
|
136
|
+
.query('config/manifest')
|
|
137
|
+
.withId(manifestId)
|
|
138
|
+
.resolve();
|
|
139
|
+
|
|
140
|
+
if (manifest?.load) {
|
|
141
|
+
this.configValues = await manifest.load();
|
|
142
|
+
}
|
|
143
|
+
} catch {
|
|
144
|
+
// Config is best-effort at base layer
|
|
145
|
+
this.configValues = null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Subclasses can extend:
|
|
149
|
+
// - Initialize domain-specific caches
|
|
150
|
+
// - Validate required config
|
|
151
|
+
// - Establish connections
|
|
152
|
+
}
|
|
153
|
+
\`\`\`
|
|
154
|
+
|
|
155
|
+
#### onDispose()
|
|
156
|
+
|
|
157
|
+
Override to release resources:
|
|
158
|
+
|
|
159
|
+
\`\`\`ts
|
|
160
|
+
protected onDispose(): void {
|
|
161
|
+
// Close connections, clear caches, cancel subscriptions
|
|
162
|
+
}
|
|
163
|
+
\`\`\`
|
|
164
|
+
|
|
165
|
+
#### getConfigValues<T>()
|
|
166
|
+
|
|
167
|
+
Accessor for loaded config values (null if load hasn't run or failed):
|
|
168
|
+
|
|
169
|
+
\`\`\`ts
|
|
170
|
+
protected getConfigValues<T = unknown>(): T | null
|
|
171
|
+
\`\`\`
|
|
172
|
+
|
|
173
|
+
## Extending BaseRuntimeClient
|
|
174
|
+
|
|
175
|
+
### Minimal Example
|
|
176
|
+
|
|
177
|
+
\`\`\`ts
|
|
178
|
+
// packages/my-module/src/client.ts
|
|
179
|
+
import { BaseRuntimeClient, type RuntimeClientDescriptor } from '@vibesdotdev/runtime-client';
|
|
180
|
+
|
|
181
|
+
export interface MyModuleDescriptor extends RuntimeClientDescriptor {
|
|
182
|
+
kind: 'runtime/client';
|
|
183
|
+
id: 'my-module';
|
|
184
|
+
configManifestId?: string;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export class MyModuleClient extends BaseRuntimeClient {
|
|
188
|
+
constructor(descriptor: MyModuleDescriptor) {
|
|
189
|
+
super(descriptor);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async doSomething(input: string): Promise<string> {
|
|
193
|
+
await this.ensureLoaded();
|
|
194
|
+
|
|
195
|
+
const runtime = this.runtime;
|
|
196
|
+
// Use runtime APIs...
|
|
197
|
+
return \`Processed: \${input}\`;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
\`\`\`
|
|
201
|
+
|
|
202
|
+
### Full Example with Config
|
|
203
|
+
|
|
204
|
+
\`\`\`ts
|
|
205
|
+
// packages/ai/src/client/ai-client.ts
|
|
206
|
+
import { BaseRuntimeClient, type RuntimeClientDescriptor } from '@vibesdotdev/runtime-client';
|
|
207
|
+
|
|
208
|
+
interface AIConfig {
|
|
209
|
+
defaultProvider: string;
|
|
210
|
+
maxTokens: number;
|
|
211
|
+
temperature: number;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export class AIClient extends BaseRuntimeClient {
|
|
215
|
+
constructor(descriptor: RuntimeClientDescriptor) {
|
|
216
|
+
super(descriptor);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
async generate(options: {
|
|
220
|
+
prompt: string;
|
|
221
|
+
model?: string;
|
|
222
|
+
maxTokens?: number;
|
|
223
|
+
}): Promise<string> {
|
|
224
|
+
await this.ensureLoaded();
|
|
225
|
+
|
|
226
|
+
const config = this.getConfigValues<AIConfig>();
|
|
227
|
+
if (!config) {
|
|
228
|
+
throw new Error('AI config not loaded');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const provider = await this.runtime
|
|
232
|
+
.query('ai/provider')
|
|
233
|
+
.withId(config.defaultProvider)
|
|
234
|
+
.resolve();
|
|
235
|
+
|
|
236
|
+
const response = await provider.generate({
|
|
237
|
+
prompt: options.prompt,
|
|
238
|
+
model: options.model,
|
|
239
|
+
maxTokens: options.maxTokens ?? config.maxTokens,
|
|
240
|
+
temperature: config.temperature
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return response.text;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async listModels(): Promise<string[]> {
|
|
247
|
+
await this.ensureLoaded();
|
|
248
|
+
|
|
249
|
+
const models = await this.runtime
|
|
250
|
+
.query('ai/model')
|
|
251
|
+
.descriptors();
|
|
252
|
+
|
|
253
|
+
return models.map(m => m.id);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
protected async onLoad(): Promise<void> {
|
|
257
|
+
await super.onLoad(); // Load config manifest
|
|
258
|
+
|
|
259
|
+
// Additional AI-specific initialization
|
|
260
|
+
// e.g., warm provider caches, validate API keys
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
protected onDispose(): void {
|
|
264
|
+
// Cancel pending generations, clear caches
|
|
265
|
+
super.onDispose();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
\`\`\`
|
|
269
|
+
|
|
270
|
+
### Registering the Client
|
|
271
|
+
|
|
272
|
+
\`\`\`ts
|
|
273
|
+
// packages/ai/src/ai.plugin.ts
|
|
274
|
+
import { createRuntimePlugin } from '@vibesdotdev/runtime';
|
|
275
|
+
import { AIClient } from './client/ai-client';
|
|
276
|
+
|
|
277
|
+
export const aiPlugin = createRuntimePlugin({
|
|
278
|
+
id: 'ai',
|
|
279
|
+
name: 'AI Module',
|
|
280
|
+
onRegister(runtime) {
|
|
281
|
+
// Register per-id loader for runtime/client kind
|
|
282
|
+
runtime.registerLoader('runtime/client', 'ai', async () => {
|
|
283
|
+
return new AIClient({
|
|
284
|
+
kind: 'runtime/client',
|
|
285
|
+
id: 'ai',
|
|
286
|
+
configManifestId: 'ai/config'
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
\`\`\`
|
|
292
|
+
|
|
293
|
+
## WRONG patterns
|
|
294
|
+
|
|
295
|
+
:::card{title="Anti-patterns"}
|
|
296
|
+
- ❌ **Direct runtime instantiation** — Don't \`new VibesRuntime()\`; use ambient \`this.runtime\`
|
|
297
|
+
- ❌ **Storing runtime references** — Call \`getVibesRuntime()\` at construction, store as \`this.runtime\`
|
|
298
|
+
- ❌ **Skipping ensureLoaded()** — Always call at method entry if you need config
|
|
299
|
+
- ❌ **Multiple config loads** — Base class handles idempotent loading; don't re-implement
|
|
300
|
+
- ❌ **Throwing on missing config** — Config is best-effort; validate in subclass if required
|
|
301
|
+
- ❌ **Direct config manifest resolution** — Use base class \`onLoad()\` pattern
|
|
302
|
+
:::
|
|
303
|
+
|
|
304
|
+
## Code paths
|
|
305
|
+
|
|
306
|
+
- Base class: [\`packages/runtime-client/src/base.ts\`](https://github.com/vibesdotdev/monorepo/tree/main/packages/runtime-client/src/base.ts)
|
|
307
|
+
- Contract: [\`packages/runtime-client/src/contract.ts\`](https://github.com/vibesdotdev/monorepo/tree/main/packages/runtime-client/src/contract.ts)
|
|
308
|
+
- Schema: [\`packages/runtime-client/src/schema.ts\`](https://github.com/vibesdotdev/monorepo/tree/main/packages/runtime-client/src/schema.ts)
|
|
309
|
+
- Kind: [\`packages/runtime-client/src/kind.ts\`](https://github.com/vibesdotdev/monorepo/tree/main/packages/runtime-client/src/kind.ts)
|
|
310
|
+
|
|
311
|
+
:::card{title="See also"}
|
|
312
|
+
- [\`runtime-client.helpers\`](runtime-client.helpers) — \`getVibesClient()\` helper functions
|
|
313
|
+
- [\`runtime-client.surface\`](runtime-client.surface) — Surface initialization patterns
|
|
314
|
+
- [\`runtime.query\`](runtime.query) — Runtime query API for resolving clients
|
|
315
|
+
- [\`runtime.plugins\`](runtime.plugins) — Plugin registration and loaders
|
|
316
|
+
:::
|
|
317
|
+
`
|
|
318
|
+
},
|
|
319
|
+
parent: 'runtime-client',
|
|
320
|
+
order: 1,
|
|
321
|
+
tags: ['runtime-client', 'base-class', 'extension', 'api', 'patterns'],
|
|
322
|
+
surfaces: ['cli', 'web', 'in-app'],
|
|
323
|
+
hardware: ['consumer', 'cloud'],
|
|
324
|
+
enabled: true,
|
|
325
|
+
man: {
|
|
326
|
+
name: 'runtime-client.api — BaseRuntimeClient and extension patterns',
|
|
327
|
+
section: 1,
|
|
328
|
+
synopsis: 'vibes man runtime-client.api',
|
|
329
|
+
options: [],
|
|
330
|
+
examples: [
|
|
331
|
+
{
|
|
332
|
+
description: 'Extend BaseRuntimeClient',
|
|
333
|
+
command: 'class MyClient extends BaseRuntimeClient { ... }'
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
description: 'Load config in onLoad()',
|
|
337
|
+
command: 'protected async onLoad() { await super.onLoad(); ... }'
|
|
338
|
+
}
|
|
339
|
+
],
|
|
340
|
+
seeAlso: ['runtime-client.helpers', 'runtime-client.surface', 'runtime.query']
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
export default descriptor;
|
|
344
|
+
//# sourceMappingURL=runtime-client.api.docs.descriptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-client.api.docs.descriptor.js","sourceRoot":"","sources":["../../src/docs/runtime-client.api.docs.descriptor.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,GAAwB;IACtC,IAAI,EAAE,YAAY;IAClB,EAAE,EAAE,oBAAoB;IACxB,KAAK,EAAE,oBAAoB;IAC3B,OAAO,EAAE,8EAA8E;IACvF,IAAI,EAAE;QACJ,IAAI,EAAE,UAAU;QAChB,UAAU,EAAE,KAAK;QACjB,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgTX;KACE;IACD,MAAM,EAAE,gBAAgB;IACxB,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC;IACtE,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC;IAClC,QAAQ,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC;IAC/B,OAAO,EAAE,IAAI;IACb,GAAG,EAAE;QACH,IAAI,EAAE,+DAA+D;QACrE,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,8BAA8B;QACxC,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE;YACR;gBACE,WAAW,EAAE,0BAA0B;gBACvC,OAAO,EAAE,kDAAkD;aAC5D;YACD;gBACE,WAAW,EAAE,yBAAyB;gBACtC,OAAO,EAAE,wDAAwD;aAClE;SACF;QACD,OAAO,EAAE,CAAC,wBAAwB,EAAE,wBAAwB,EAAE,eAAe,CAAC;KAC/E;CACF,CAAC;AAEF,eAAe,UAAU,CAAC"}
|