@jini-ai/agentic 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/ag-ui.d.ts +82 -0
- package/dist/ag-ui.d.ts.map +1 -0
- package/dist/ag-ui.js +56 -0
- package/dist/ag-ui.js.map +1 -0
- package/dist/agui/encoder.d.ts +50 -0
- package/dist/agui/encoder.d.ts.map +1 -0
- package/dist/agui/encoder.js +97 -0
- package/dist/agui/encoder.js.map +1 -0
- package/dist/agui/events.d.ts +59 -0
- package/dist/agui/events.d.ts.map +1 -0
- package/dist/agui/events.js +15 -0
- package/dist/agui/events.js.map +1 -0
- package/dist/capability.d.ts +81 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +79 -0
- package/dist/capability.js.map +1 -0
- package/dist/dom/dom-page-driver.d.ts +29 -0
- package/dist/dom/dom-page-driver.d.ts.map +1 -0
- package/dist/dom/dom-page-driver.js +557 -0
- package/dist/dom/dom-page-driver.js.map +1 -0
- package/dist/dom/index.d.ts +17 -0
- package/dist/dom/index.d.ts.map +1 -0
- package/dist/dom/index.js +17 -0
- package/dist/dom/index.js.map +1 -0
- package/dist/dom/model-context.d.ts +54 -0
- package/dist/dom/model-context.d.ts.map +1 -0
- package/dist/dom/model-context.js +36 -0
- package/dist/dom/model-context.js.map +1 -0
- package/dist/element-handles.d.ts +99 -0
- package/dist/element-handles.d.ts.map +1 -0
- package/dist/element-handles.js +39 -0
- package/dist/element-handles.js.map +1 -0
- package/dist/gen-ui/encoder.d.ts +50 -0
- package/dist/gen-ui/encoder.d.ts.map +1 -0
- package/dist/gen-ui/encoder.js +97 -0
- package/dist/gen-ui/encoder.js.map +1 -0
- package/dist/gen-ui/events.d.ts +59 -0
- package/dist/gen-ui/events.d.ts.map +1 -0
- package/dist/gen-ui/events.js +15 -0
- package/dist/gen-ui/events.js.map +1 -0
- package/dist/gen-ui/index.d.ts +18 -0
- package/dist/gen-ui/index.d.ts.map +1 -0
- package/dist/gen-ui/index.js +17 -0
- package/dist/gen-ui/index.js.map +1 -0
- package/dist/guards.d.ts +91 -0
- package/dist/guards.d.ts.map +1 -0
- package/dist/guards.js +181 -0
- package/dist/guards.js.map +1 -0
- package/dist/handle.d.ts +41 -0
- package/dist/handle.d.ts.map +1 -0
- package/dist/handle.js +41 -0
- package/dist/handle.js.map +1 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-ui-apps.d.ts +133 -0
- package/dist/mcp-ui-apps.d.ts.map +1 -0
- package/dist/mcp-ui-apps.js +134 -0
- package/dist/mcp-ui-apps.js.map +1 -0
- package/dist/mcp-ui.d.ts +133 -0
- package/dist/mcp-ui.d.ts.map +1 -0
- package/dist/mcp-ui.js +134 -0
- package/dist/mcp-ui.js.map +1 -0
- package/dist/page-capabilities.d.ts +14 -0
- package/dist/page-capabilities.d.ts.map +1 -0
- package/dist/page-capabilities.js +129 -0
- package/dist/page-capabilities.js.map +1 -0
- package/dist/page-driver.d.ts +107 -0
- package/dist/page-driver.d.ts.map +1 -0
- package/dist/page-driver.js +2 -0
- package/dist/page-driver.js.map +1 -0
- package/dist/page-executor.d.ts +87 -0
- package/dist/page-executor.d.ts.map +1 -0
- package/dist/page-executor.js +288 -0
- package/dist/page-executor.js.map +1 -0
- package/dist/webmcp.d.ts +81 -0
- package/dist/webmcp.d.ts.map +1 -0
- package/dist/webmcp.js +67 -0
- package/dist/webmcp.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module capability
|
|
3
|
+
*
|
|
4
|
+
* The vocabulary every agent-drivable surface shares: what an outside caller may ask a
|
|
5
|
+
* frontend to do, described as pure data with no transport, DOM, or framework attached.
|
|
6
|
+
*
|
|
7
|
+
* One noun, deliberately: **capability**. The chat pane's first draft used `tool` in its
|
|
8
|
+
* type names and `capability` in its ids, which forked the vocabulary across four files.
|
|
9
|
+
* `tool` stays reserved for the engine's own `ToolRegistry`/`ToolExecutor` nouns; anything
|
|
10
|
+
* an outside caller asks a *frontend* to do is a capability. Transports may of course
|
|
11
|
+
* present capabilities as MCP tools — that is a projection, not a rename.
|
|
12
|
+
*/
|
|
13
|
+
/** How much damage a capability can do. `requiresConfirmation` is the enforcement; this is the label. */
|
|
14
|
+
export type CapabilityRisk = 'read' | 'write';
|
|
15
|
+
/**
|
|
16
|
+
* Whether a capability means anything without a live UI session attached.
|
|
17
|
+
*
|
|
18
|
+
* - `session` — needs a connected frontend. "Highlight this field" is meaningless with no
|
|
19
|
+
* tab open, and must fail closed with a distinct error rather than hanging on a timeout.
|
|
20
|
+
* - `server` — a product outcome the backend can satisfy headlessly. Sending a chat message
|
|
21
|
+
* is the same outcome whether a tab is open or not.
|
|
22
|
+
*
|
|
23
|
+
* This decides *availability*, so a caller can be told "no eligible frontend is connected"
|
|
24
|
+
* instead of waiting for a timeout that will never resolve.
|
|
25
|
+
*/
|
|
26
|
+
export type CapabilitySurface = 'session' | 'server';
|
|
27
|
+
export interface CapabilityInputSchema {
|
|
28
|
+
readonly type: 'object';
|
|
29
|
+
readonly properties: Record<string, {
|
|
30
|
+
type: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
enum?: readonly string[];
|
|
33
|
+
}>;
|
|
34
|
+
readonly required?: readonly string[];
|
|
35
|
+
readonly additionalProperties?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface CapabilityDef {
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly description: string;
|
|
40
|
+
readonly inputSchema: CapabilityInputSchema;
|
|
41
|
+
readonly risk: CapabilityRisk;
|
|
42
|
+
readonly surface: CapabilitySurface;
|
|
43
|
+
/**
|
|
44
|
+
* Destructive or otherwise irreversible — the caller must acknowledge before it runs. A host
|
|
45
|
+
* with a real confirmation gate (`@jini-ai/daemon`'s `ToolExecutor` has a resumable one) should
|
|
46
|
+
* enforce it there; surfaces without one enforce it in-band by requiring `confirm: true`, so
|
|
47
|
+
* no transport can execute it by accident.
|
|
48
|
+
*/
|
|
49
|
+
readonly requiresConfirmation?: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Looks a capability up by id.
|
|
53
|
+
*
|
|
54
|
+
* @param capabilities - The manifest to search.
|
|
55
|
+
* @param id - Capability id to resolve.
|
|
56
|
+
* @returns The definition, or `undefined` when the id is not in the manifest.
|
|
57
|
+
*/
|
|
58
|
+
export declare function findCapability(capabilities: readonly CapabilityDef[], id: string): CapabilityDef | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Checks caller input against a capability's declared schema.
|
|
61
|
+
*
|
|
62
|
+
* Manifests advertise `additionalProperties: false` and a `required` list, but nothing was
|
|
63
|
+
* enforcing either — handlers read the fields they knew about and ignored the rest, so a
|
|
64
|
+
* misnamed argument silently became a missing one. This closes that for any surface that calls
|
|
65
|
+
* it. Intentionally a shallow check, not a JSON Schema engine: these schemas are flat by
|
|
66
|
+
* construction, and a real validator is a dependency this package will not take.
|
|
67
|
+
*
|
|
68
|
+
* @param capability - The capability being invoked.
|
|
69
|
+
* @param input - Raw caller-supplied arguments.
|
|
70
|
+
* @returns An error message, or `null` when the input is acceptable.
|
|
71
|
+
*/
|
|
72
|
+
export declare function findCapabilityInputError(capability: CapabilityDef, input: Record<string, unknown>): string | null;
|
|
73
|
+
/**
|
|
74
|
+
* The capabilities a caller may use given what is currently connected.
|
|
75
|
+
*
|
|
76
|
+
* @param capabilities - The full manifest.
|
|
77
|
+
* @param hasSession - Whether a live frontend session is attached.
|
|
78
|
+
* @returns Only the capabilities that can actually be satisfied right now.
|
|
79
|
+
*/
|
|
80
|
+
export declare function availableCapabilities(capabilities: readonly CapabilityDef[], hasSession: boolean): readonly CapabilityDef[];
|
|
81
|
+
//# sourceMappingURL=capability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.d.ts","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,yGAAyG;AACzG,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9C;;;;;;;;;;GAUG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IACtG,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,qBAAqB,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,YAAY,EAAE,SAAS,aAAa,EAAE,EACtC,EAAE,EAAE,MAAM,GACT,aAAa,GAAG,SAAS,CAE3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,aAAa,EACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,GAAG,IAAI,CAiCf;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,SAAS,aAAa,EAAE,EACtC,UAAU,EAAE,OAAO,GAClB,SAAS,aAAa,EAAE,CAE1B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module capability
|
|
3
|
+
*
|
|
4
|
+
* The vocabulary every agent-drivable surface shares: what an outside caller may ask a
|
|
5
|
+
* frontend to do, described as pure data with no transport, DOM, or framework attached.
|
|
6
|
+
*
|
|
7
|
+
* One noun, deliberately: **capability**. The chat pane's first draft used `tool` in its
|
|
8
|
+
* type names and `capability` in its ids, which forked the vocabulary across four files.
|
|
9
|
+
* `tool` stays reserved for the engine's own `ToolRegistry`/`ToolExecutor` nouns; anything
|
|
10
|
+
* an outside caller asks a *frontend* to do is a capability. Transports may of course
|
|
11
|
+
* present capabilities as MCP tools — that is a projection, not a rename.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Looks a capability up by id.
|
|
15
|
+
*
|
|
16
|
+
* @param capabilities - The manifest to search.
|
|
17
|
+
* @param id - Capability id to resolve.
|
|
18
|
+
* @returns The definition, or `undefined` when the id is not in the manifest.
|
|
19
|
+
*/
|
|
20
|
+
export function findCapability(capabilities, id) {
|
|
21
|
+
return capabilities.find((capability) => capability.id === id);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Checks caller input against a capability's declared schema.
|
|
25
|
+
*
|
|
26
|
+
* Manifests advertise `additionalProperties: false` and a `required` list, but nothing was
|
|
27
|
+
* enforcing either — handlers read the fields they knew about and ignored the rest, so a
|
|
28
|
+
* misnamed argument silently became a missing one. This closes that for any surface that calls
|
|
29
|
+
* it. Intentionally a shallow check, not a JSON Schema engine: these schemas are flat by
|
|
30
|
+
* construction, and a real validator is a dependency this package will not take.
|
|
31
|
+
*
|
|
32
|
+
* @param capability - The capability being invoked.
|
|
33
|
+
* @param input - Raw caller-supplied arguments.
|
|
34
|
+
* @returns An error message, or `null` when the input is acceptable.
|
|
35
|
+
*/
|
|
36
|
+
export function findCapabilityInputError(capability, input) {
|
|
37
|
+
const { properties, required, additionalProperties } = capability.inputSchema;
|
|
38
|
+
for (const name of required ?? []) {
|
|
39
|
+
if (input[name] === undefined)
|
|
40
|
+
return `"${name}" is required`;
|
|
41
|
+
}
|
|
42
|
+
if (additionalProperties === false) {
|
|
43
|
+
// `key in properties` walks the whole prototype chain, so a key that happens to be inherited
|
|
44
|
+
// from Object.prototype (`__proto__`, `constructor`, `toString`, `valueOf`, …) reads as
|
|
45
|
+
// "known" regardless of whether the schema actually lists it — `'constructor' in {}` is
|
|
46
|
+
// true even on an empty object. `JSON.parse('{"__proto__":...}')` creates a real own data
|
|
47
|
+
// property (not the accessor), so this was a live way for such a key to escape the
|
|
48
|
+
// "unknown argument" refusal entirely. hasOwnProperty ignores the prototype chain, so only
|
|
49
|
+
// keys the schema actually declares count as known.
|
|
50
|
+
const unknown = Object.keys(input)
|
|
51
|
+
.filter((key) => !Object.prototype.hasOwnProperty.call(properties, key));
|
|
52
|
+
if (unknown.length > 0) {
|
|
53
|
+
return `unknown ${unknown.length === 1 ? 'argument' : 'arguments'}: ${unknown.sort().join(', ')}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
for (const [name, schema] of Object.entries(properties)) {
|
|
57
|
+
const value = input[name];
|
|
58
|
+
if (value === undefined)
|
|
59
|
+
continue;
|
|
60
|
+
const actual = Array.isArray(value) ? 'array' : typeof value;
|
|
61
|
+
if (actual !== schema.type)
|
|
62
|
+
return `"${name}" must be a ${schema.type}, received ${actual}`;
|
|
63
|
+
if (schema.enum !== undefined && !schema.enum.includes(value)) {
|
|
64
|
+
return `"${name}" must be one of: ${schema.enum.join(', ')}`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The capabilities a caller may use given what is currently connected.
|
|
71
|
+
*
|
|
72
|
+
* @param capabilities - The full manifest.
|
|
73
|
+
* @param hasSession - Whether a live frontend session is attached.
|
|
74
|
+
* @returns Only the capabilities that can actually be satisfied right now.
|
|
75
|
+
*/
|
|
76
|
+
export function availableCapabilities(capabilities, hasSession) {
|
|
77
|
+
return hasSession ? capabilities : capabilities.filter((c) => c.surface === 'server');
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=capability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability.js","sourceRoot":"","sources":["../src/capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAwCH;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,YAAsC,EACtC,EAAU;IAEV,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,wBAAwB,CACtC,UAAyB,EACzB,KAA8B;IAE9B,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,oBAAoB,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC;IAE9E,KAAK,MAAM,IAAI,IAAI,QAAQ,IAAI,EAAE,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,IAAI,IAAI,eAAe,CAAC;IAChE,CAAC;IAED,IAAI,oBAAoB,KAAK,KAAK,EAAE,CAAC;QACnC,6FAA6F;QAC7F,wFAAwF;QACxF,wFAAwF;QACxF,0FAA0F;QAC1F,mFAAmF;QACnF,2FAA2F;QAC3F,oDAAoD;QACpD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;aAC/B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,WAAW,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpG,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,KAAK,KAAK,SAAS;YAAE,SAAS;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC;QAC7D,IAAI,MAAM,KAAK,MAAM,CAAC,IAAI;YAAE,OAAO,IAAI,IAAI,eAAe,MAAM,CAAC,IAAI,cAAc,MAAM,EAAE,CAAC;QAC5F,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAe,CAAC,EAAE,CAAC;YACxE,OAAO,IAAI,IAAI,qBAAqB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,YAAsC,EACtC,UAAmB;IAEnB,OAAO,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC;AACxF,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PageDriver } from '../page-driver.js';
|
|
2
|
+
export interface DomPageDriverOptions {
|
|
3
|
+
/** The subtree to expose. Never pass `document`. */
|
|
4
|
+
readonly root: ParentNode & {
|
|
5
|
+
querySelector: Element['querySelector'];
|
|
6
|
+
};
|
|
7
|
+
/** Page ids this driver may navigate to, and how to get there. */
|
|
8
|
+
readonly pages: Readonly<Record<string, () => void>>;
|
|
9
|
+
/**
|
|
10
|
+
* The id of the page currently shown, reported on every element.
|
|
11
|
+
*
|
|
12
|
+
* Omit it in a single-page app that swaps views: the driver then reads `data-agent-page` from
|
|
13
|
+
* the live DOM on every call, so navigating actually changes what elements report. A value
|
|
14
|
+
* captured here is fixed for the driver's whole lifetime, which is right only for a surface that
|
|
15
|
+
* never changes view — and silently wrong for one that does, since the driver outlives any one
|
|
16
|
+
* view (it is bound to the connection, not the render).
|
|
17
|
+
*/
|
|
18
|
+
readonly currentPage?: string | undefined;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Builds a driver over `root`.
|
|
22
|
+
*
|
|
23
|
+
* @param options - The subtree, the navigable pages, and the current page id.
|
|
24
|
+
* @returns A driver ready to hand to `executePageCapability`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createDomPageDriver(options: DomPageDriverOptions): PageDriver;
|
|
27
|
+
/** Reads the current page's `data-agent-page`, for hosts that tag the body. */
|
|
28
|
+
export declare function currentAgentPage(root: ParentNode): string | undefined;
|
|
29
|
+
//# sourceMappingURL=dom-page-driver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-page-driver.d.ts","sourceRoot":"","sources":["../../src/dom/dom-page-driver.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAsB,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAoMxE,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG;QAAE,aAAa,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;KAAE,CAAC;IACxE,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;IACrD;;;;;;;;OAQG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,UAAU,CAwT7E;AAgDD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAGrE"}
|