agenticros 0.1.12 → 0.1.14

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.
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Safe read/write helper for the OpenClaw gateway config file.
3
+ *
4
+ * The OpenClaw config (default: `~/.openclaw/openclaw.json`) is the source of
5
+ * truth for the AgenticROS *plugin*'s skill configuration —
6
+ * `plugins.entries.agenticros.config.skillPaths` and `.skillPackages` decide
7
+ * which skill packages the plugin loads at gateway start. The MCP server and
8
+ * the Gemini CLI read their config from `~/.agenticros/config.json` instead;
9
+ * neither currently loads skills.
10
+ *
11
+ * This module exists so the rest of the CLI can mutate that nested
12
+ * `plugins.entries.agenticros.config` slice without round-tripping the entire
13
+ * JSON document or accidentally clobbering unrelated keys (gateway auth,
14
+ * other plugins, etc). Every write goes through the full JSON parse → mutate
15
+ * → stringify cycle to keep the file valid; comments are not supported in the
16
+ * source JSON either way.
17
+ */
18
+ /** Default location of the OpenClaw config. Overridable via `$OPENCLAW_CONFIG`. */
19
+ export declare function openclawConfigPath(): string;
20
+ export declare function openclawConfigExists(): boolean;
21
+ /**
22
+ * Read the OpenClaw config or return `undefined` if it doesn't exist / is
23
+ * not valid JSON. We never throw — callers can decide how loudly to fail.
24
+ */
25
+ export declare function readOpenclawConfig(): Record<string, unknown> | undefined;
26
+ /** Write the config back, pretty-printed (2-space indent), with a trailing newline. */
27
+ export declare function writeOpenclawConfig(cfg: Record<string, unknown>): void;
28
+ /**
29
+ * Locate (and lazily create) the `plugins.entries.agenticros.config` subtree.
30
+ * Mutates `cfg` in place and returns the inner config object so callers can
31
+ * read/modify its `skillPaths`, `skillPackages`, `skills`, etc.
32
+ */
33
+ export declare function getAgenticrosPluginConfig(cfg: Record<string, unknown>): Record<string, unknown>;
34
+ /**
35
+ * Ensure `obj[key]` is an array of strings and return it (creating an empty
36
+ * array if needed). Non-string entries in an existing array are preserved so
37
+ * we don't silently drop opaque values, but lookups still operate on strings.
38
+ */
39
+ export declare function ensureStringArray(obj: Record<string, unknown>, key: string): unknown[];
40
+ /**
41
+ * Locate the AgenticROS plugin manifest whose `contracts.tools` the CLI
42
+ * should treat as canonical.
43
+ *
44
+ * Order:
45
+ * 1. The in-repo source manifest at
46
+ * `<installRoot>/packages/agenticros/openclaw.plugin.json`. This is
47
+ * the "future-proof" list — anything `sync-skill-tools.mjs` adds for
48
+ * a new skill lands here first, and the next `setup_gateway_plugin.sh`
49
+ * run propagates it into the deploy. Stamping `alsoAllow` from this
50
+ * file means the chat agent picks up the new tools the moment the
51
+ * gateway restarts, with no second sync round-trip.
52
+ * 2. The deploy dir produced by `setup_gateway_plugin.sh`
53
+ * (`~/.agenticros/plugin-deploy/openclaw.plugin.json`) — used when
54
+ * the CLI runs without a workspace checkout (npx-from-tarball).
55
+ *
56
+ * `installRoot` is the agenticros workspace root (`getCliPaths().repoRoot`).
57
+ * Returns `undefined` if neither file exists yet — callers should treat that
58
+ * as "plugin not installed yet, skip the sync step".
59
+ */
60
+ export declare function findAgenticrosPluginManifest(installRoot?: string): string | undefined;
61
+ /**
62
+ * Read `contracts.tools` from the AgenticROS plugin manifest, or `undefined`
63
+ * if we can't find / parse it. This is the canonical list the CLI uses when
64
+ * stamping `tools.alsoAllow` in the OpenClaw config.
65
+ */
66
+ export declare function readAgenticrosContractTools(installRoot?: string): string[] | undefined;
67
+ export interface AlsoAllowSyncResult {
68
+ /** Tools that were already in `alsoAllow` before we ran. */
69
+ preExisting: string[];
70
+ /** Tools we appended this run (anything from `tools` that wasn't already allowed). */
71
+ added: string[];
72
+ /** Full `alsoAllow` after the update — useful for logging. */
73
+ final: string[];
74
+ /** True when the on-disk config was modified. */
75
+ changed: boolean;
76
+ }
77
+ /**
78
+ * Make sure every tool id in `tools` is reachable from the chat agent's tool
79
+ * picker by appending missing entries to `cfg.tools.alsoAllow`.
80
+ *
81
+ * Why this exists: OpenClaw 2026.6+ ships a `tools.profile` ("coding",
82
+ * "standard", …) that is a *strict* allowlist applied before plugin-registered
83
+ * tools are merged in. Plugins like AgenticROS can register tools all day, but
84
+ * the chat agent will never see them unless the user opts each one in via
85
+ * `tools.alsoAllow`. The gateway logs this as "Browser is configured, but the
86
+ * current tool profile does not include the browser tool…" for built-ins; for
87
+ * plugin tools you instead just see the agent claim "I don't have those tools"
88
+ * in chat. We keep the user out of that footgun by syncing `alsoAllow` to the
89
+ * plugin's `contracts.tools` whenever the CLI knows the canonical list.
90
+ *
91
+ * Idempotent. Never removes entries (other plugins may have added their own).
92
+ * Returns a result rather than mutating cfg in-place + writing, because
93
+ * callers sometimes want to combine this with other config mutations and
94
+ * write once at the end. This function still writes when run standalone
95
+ * (when `write` is true, the default) so simple callers stay one-liners.
96
+ */
97
+ export declare function ensureToolsAlsoAllow(tools: string[], opts?: {
98
+ write?: boolean;
99
+ cfg?: Record<string, unknown>;
100
+ }): AlsoAllowSyncResult | undefined;
101
+ //# sourceMappingURL=openclaw-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-config.d.ts","sourceRoot":"","sources":["../../src/util/openclaw-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,mFAAmF;AACnF,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAYxE;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAItE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAK/F;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,GAAG,EAAE,MAAM,GACV,OAAO,EAAE,CAMX;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQrF;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAatF;AAED,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,sFAAsF;IACtF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,8DAA8D;IAC9D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAO,GAC5D,mBAAmB,GAAG,SAAS,CAiBjC"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Safe read/write helper for the OpenClaw gateway config file.
3
+ *
4
+ * The OpenClaw config (default: `~/.openclaw/openclaw.json`) is the source of
5
+ * truth for the AgenticROS *plugin*'s skill configuration —
6
+ * `plugins.entries.agenticros.config.skillPaths` and `.skillPackages` decide
7
+ * which skill packages the plugin loads at gateway start. The MCP server and
8
+ * the Gemini CLI read their config from `~/.agenticros/config.json` instead;
9
+ * neither currently loads skills.
10
+ *
11
+ * This module exists so the rest of the CLI can mutate that nested
12
+ * `plugins.entries.agenticros.config` slice without round-tripping the entire
13
+ * JSON document or accidentally clobbering unrelated keys (gateway auth,
14
+ * other plugins, etc). Every write goes through the full JSON parse → mutate
15
+ * → stringify cycle to keep the file valid; comments are not supported in the
16
+ * source JSON either way.
17
+ */
18
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
19
+ import { dirname, join } from "node:path";
20
+ import { homedir } from "node:os";
21
+ /** Default location of the OpenClaw config. Overridable via `$OPENCLAW_CONFIG`. */
22
+ export function openclawConfigPath() {
23
+ const env = process.env["OPENCLAW_CONFIG"];
24
+ if (env && env.trim().length > 0)
25
+ return env;
26
+ return join(homedir(), ".openclaw", "openclaw.json");
27
+ }
28
+ export function openclawConfigExists() {
29
+ return existsSync(openclawConfigPath());
30
+ }
31
+ /**
32
+ * Read the OpenClaw config or return `undefined` if it doesn't exist / is
33
+ * not valid JSON. We never throw — callers can decide how loudly to fail.
34
+ */
35
+ export function readOpenclawConfig() {
36
+ const p = openclawConfigPath();
37
+ if (!existsSync(p))
38
+ return undefined;
39
+ try {
40
+ const parsed = JSON.parse(readFileSync(p, "utf8"));
41
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
42
+ return parsed;
43
+ }
44
+ return undefined;
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ }
50
+ /** Write the config back, pretty-printed (2-space indent), with a trailing newline. */
51
+ export function writeOpenclawConfig(cfg) {
52
+ const p = openclawConfigPath();
53
+ mkdirSync(dirname(p), { recursive: true });
54
+ writeFileSync(p, `${JSON.stringify(cfg, null, 2)}\n`);
55
+ }
56
+ /**
57
+ * Locate (and lazily create) the `plugins.entries.agenticros.config` subtree.
58
+ * Mutates `cfg` in place and returns the inner config object so callers can
59
+ * read/modify its `skillPaths`, `skillPackages`, `skills`, etc.
60
+ */
61
+ export function getAgenticrosPluginConfig(cfg) {
62
+ const plugins = asObject(cfg, "plugins");
63
+ const entries = asObject(plugins, "entries");
64
+ const agenticros = asObject(entries, "agenticros");
65
+ return asObject(agenticros, "config");
66
+ }
67
+ function asObject(parent, key) {
68
+ const cur = parent[key];
69
+ if (cur && typeof cur === "object" && !Array.isArray(cur)) {
70
+ return cur;
71
+ }
72
+ const fresh = {};
73
+ parent[key] = fresh;
74
+ return fresh;
75
+ }
76
+ /**
77
+ * Ensure `obj[key]` is an array of strings and return it (creating an empty
78
+ * array if needed). Non-string entries in an existing array are preserved so
79
+ * we don't silently drop opaque values, but lookups still operate on strings.
80
+ */
81
+ export function ensureStringArray(obj, key) {
82
+ const cur = obj[key];
83
+ if (Array.isArray(cur))
84
+ return cur;
85
+ const fresh = [];
86
+ obj[key] = fresh;
87
+ return fresh;
88
+ }
89
+ /**
90
+ * Locate the AgenticROS plugin manifest whose `contracts.tools` the CLI
91
+ * should treat as canonical.
92
+ *
93
+ * Order:
94
+ * 1. The in-repo source manifest at
95
+ * `<installRoot>/packages/agenticros/openclaw.plugin.json`. This is
96
+ * the "future-proof" list — anything `sync-skill-tools.mjs` adds for
97
+ * a new skill lands here first, and the next `setup_gateway_plugin.sh`
98
+ * run propagates it into the deploy. Stamping `alsoAllow` from this
99
+ * file means the chat agent picks up the new tools the moment the
100
+ * gateway restarts, with no second sync round-trip.
101
+ * 2. The deploy dir produced by `setup_gateway_plugin.sh`
102
+ * (`~/.agenticros/plugin-deploy/openclaw.plugin.json`) — used when
103
+ * the CLI runs without a workspace checkout (npx-from-tarball).
104
+ *
105
+ * `installRoot` is the agenticros workspace root (`getCliPaths().repoRoot`).
106
+ * Returns `undefined` if neither file exists yet — callers should treat that
107
+ * as "plugin not installed yet, skip the sync step".
108
+ */
109
+ export function findAgenticrosPluginManifest(installRoot) {
110
+ if (installRoot) {
111
+ const inRepo = join(installRoot, "packages", "agenticros", "openclaw.plugin.json");
112
+ if (existsSync(inRepo))
113
+ return inRepo;
114
+ }
115
+ const deployed = join(homedir(), ".agenticros", "plugin-deploy", "openclaw.plugin.json");
116
+ if (existsSync(deployed))
117
+ return deployed;
118
+ return undefined;
119
+ }
120
+ /**
121
+ * Read `contracts.tools` from the AgenticROS plugin manifest, or `undefined`
122
+ * if we can't find / parse it. This is the canonical list the CLI uses when
123
+ * stamping `tools.alsoAllow` in the OpenClaw config.
124
+ */
125
+ export function readAgenticrosContractTools(installRoot) {
126
+ const manifestPath = findAgenticrosPluginManifest(installRoot);
127
+ if (!manifestPath)
128
+ return undefined;
129
+ try {
130
+ const m = JSON.parse(readFileSync(manifestPath, "utf8"));
131
+ const tools = m.contracts?.tools;
132
+ if (!Array.isArray(tools))
133
+ return undefined;
134
+ return tools.filter((t) => typeof t === "string");
135
+ }
136
+ catch {
137
+ return undefined;
138
+ }
139
+ }
140
+ /**
141
+ * Make sure every tool id in `tools` is reachable from the chat agent's tool
142
+ * picker by appending missing entries to `cfg.tools.alsoAllow`.
143
+ *
144
+ * Why this exists: OpenClaw 2026.6+ ships a `tools.profile` ("coding",
145
+ * "standard", …) that is a *strict* allowlist applied before plugin-registered
146
+ * tools are merged in. Plugins like AgenticROS can register tools all day, but
147
+ * the chat agent will never see them unless the user opts each one in via
148
+ * `tools.alsoAllow`. The gateway logs this as "Browser is configured, but the
149
+ * current tool profile does not include the browser tool…" for built-ins; for
150
+ * plugin tools you instead just see the agent claim "I don't have those tools"
151
+ * in chat. We keep the user out of that footgun by syncing `alsoAllow` to the
152
+ * plugin's `contracts.tools` whenever the CLI knows the canonical list.
153
+ *
154
+ * Idempotent. Never removes entries (other plugins may have added their own).
155
+ * Returns a result rather than mutating cfg in-place + writing, because
156
+ * callers sometimes want to combine this with other config mutations and
157
+ * write once at the end. This function still writes when run standalone
158
+ * (when `write` is true, the default) so simple callers stay one-liners.
159
+ */
160
+ export function ensureToolsAlsoAllow(tools, opts = {}) {
161
+ const cfg = opts.cfg ?? readOpenclawConfig();
162
+ if (!cfg)
163
+ return undefined;
164
+ const toolsBlock = asObject(cfg, "tools");
165
+ const rawAlso = ensureStringArray(toolsBlock, "alsoAllow");
166
+ const preExisting = rawAlso.filter((x) => typeof x === "string");
167
+ const added = [];
168
+ for (const t of tools) {
169
+ if (typeof t !== "string" || t.length === 0)
170
+ continue;
171
+ if (preExisting.includes(t) || added.includes(t))
172
+ continue;
173
+ rawAlso.push(t);
174
+ added.push(t);
175
+ }
176
+ const final = [...preExisting, ...added];
177
+ const changed = added.length > 0;
178
+ if (opts.write !== false && changed)
179
+ writeOpenclawConfig(cfg);
180
+ return { preExisting, added, final, changed };
181
+ }
182
+ //# sourceMappingURL=openclaw-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-config.js","sourceRoot":"","sources":["../../src/util/openclaw-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Skill discovery, validation, and config-file mutation primitives.
3
+ *
4
+ * An AgenticROS skill is a Node package whose `package.json` carries
5
+ * `"agenticrosSkill": true` and exports a `registerSkill(api, config, context)`
6
+ * function from its `main` entry. The OpenClaw AgenticROS plugin loads them
7
+ * at gateway start by walking two arrays in its config:
8
+ *
9
+ * - `skillPaths[]` — absolute directories to scan (validate `package.json`)
10
+ * - `skillPackages[]` — npm-resolvable names (e.g. `agenticros-skill-find`)
11
+ *
12
+ * This module is the single place the CLI talks to those arrays. It also
13
+ * encapsulates discovery (where on disk users typically clone skill repos)
14
+ * and the `deriveSkillId` convention shared with `@agenticros/agenticros`'s
15
+ * skill-loader so menu / list output uses the same short ids the plugin
16
+ * surfaces (e.g. `followme`, `find`).
17
+ */
18
+ export interface SkillRef {
19
+ /** Short id (matches what the OpenClaw plugin uses for `config.skills.<id>`). */
20
+ id: string;
21
+ /** npm package name (from `package.json.name`). */
22
+ packageName: string;
23
+ /** Absolute directory containing `package.json`, when known. */
24
+ dir?: string;
25
+ /** Where the skill is currently registered with the gateway. */
26
+ registeredAs: ("path" | "package")[];
27
+ /**
28
+ * Absolute path the skill's `package.json` declares as its entry (`main`),
29
+ * resolved against `dir`. Only set when we inspected the directory.
30
+ */
31
+ entry?: string;
32
+ /** True when `entry` exists on disk; false when the skill needs `pnpm build`. */
33
+ built?: boolean;
34
+ }
35
+ /**
36
+ * Apply the same short-id transform the OpenClaw plugin's skill-loader uses,
37
+ * so menu output and the plugin's `config.skills.<id>` keys line up exactly.
38
+ * `agenticros-skill-followme` → `followme`; scoped packages drop the scope.
39
+ */
40
+ export declare function deriveSkillId(packageName: string): string;
41
+ /**
42
+ * Inspect a directory and decide whether it's a valid AgenticROS skill clone.
43
+ * Returns a partial `SkillRef` (no `registeredAs`) or `undefined` when the
44
+ * directory is missing, lacks `package.json`, or doesn't opt in via the
45
+ * `agenticrosSkill: true` flag.
46
+ */
47
+ export declare function inspectSkillDir(dir: string): Omit<SkillRef, "registeredAs"> | undefined;
48
+ /**
49
+ * Return a deduped list of "places we should look for skill clones" — the
50
+ * directories whose children the CLI scans on `agenticros skills discover`.
51
+ *
52
+ * We include both the parent of the active repo / install dir (so siblings
53
+ * of `agenticros/` work, e.g. `../agenticros-skill-find`) and `$HOME` /
54
+ * `$HOME/Projects/` / `$HOME/Code/` so a vanilla clone-into-Projects flow
55
+ * is found without configuration.
56
+ */
57
+ export declare function discoveryRoots(extra?: string[]): string[];
58
+ /**
59
+ * Walk every directory in `roots`, returning a `SkillRef` for each child
60
+ * directory that passes `inspectSkillDir`. Used by both `discover` and
61
+ * `list` (which uses it to render orphaned-but-cloned skills).
62
+ */
63
+ export declare function scanForSkills(extra?: string[]): SkillRef[];
64
+ export interface SkillsListing {
65
+ /** Skills currently registered in the OpenClaw config (path-loaded or package-loaded). */
66
+ registered: SkillRef[];
67
+ /** Skill clones that exist on disk in known discovery roots but aren't registered. */
68
+ available: SkillRef[];
69
+ /** `skillPaths` entries that refer to a directory that no longer exists. */
70
+ brokenPaths: string[];
71
+ }
72
+ /**
73
+ * Build a snapshot of the user's current skill state: what's registered,
74
+ * what's available-but-not-registered, and what registrations are broken.
75
+ * The single source of truth for the `agenticros skills` (list) view.
76
+ */
77
+ export declare function listSkills(): SkillsListing;
78
+ export interface AddResult {
79
+ ok: boolean;
80
+ /** Human-readable summary of what changed (or why nothing changed). */
81
+ message: string;
82
+ skill?: SkillRef;
83
+ }
84
+ /**
85
+ * Add a skill to the OpenClaw plugin config by absolute directory path.
86
+ * Idempotent: re-adding an existing entry is a no-op and returns `ok: true`
87
+ * with an explanatory message. The directory must contain a valid
88
+ * `package.json` with `agenticrosSkill: true`.
89
+ */
90
+ export declare function addSkillByPath(dir: string): AddResult;
91
+ /**
92
+ * Add a skill by npm package name (must be resolvable on the gateway's
93
+ * Node search path). Mainly intended for skills published to a registry —
94
+ * for local clones, prefer `addSkillByPath` so the absolute directory is
95
+ * recorded.
96
+ */
97
+ export declare function addSkillByPackage(name: string): AddResult;
98
+ export interface RemoveResult {
99
+ ok: boolean;
100
+ message: string;
101
+ removedPaths: string[];
102
+ removedPackages: string[];
103
+ }
104
+ /**
105
+ * Remove every registration that matches `idOrName` — either a derived skill
106
+ * id (e.g. `find`), a full package name (e.g. `agenticros-skill-find`), or an
107
+ * absolute path that appears in `skillPaths`. Both `skillPaths` (matched by
108
+ * resolving each path back through `inspectSkillDir`) and `skillPackages`
109
+ * are cleaned in a single pass.
110
+ */
111
+ export declare function removeSkill(idOrName: string): RemoveResult;
112
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/util/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAgBH,MAAM,WAAW,QAAQ;IACvB,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,YAAY,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IACrC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,GAAG,SAAS,CA6BvF;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CAuB7D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,MAAM,EAAO,GAAG,QAAQ,EAAE,CAqB9D;AA0BD,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,sFAAsF;IACtF,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAyC1C;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAuCrD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CA6BzD;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CA+D1D"}