@grosspoetrysystems/oompf 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 +21 -0
- package/README.md +171 -0
- package/dist/index.d.mts +179 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +8463 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +58 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gross Poetry Systems
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# oompf
|
|
2
|
+
|
|
3
|
+
`oompf` publishes, inspects, searches, and installs OMP (Oh My Pi) agent
|
|
4
|
+
profiles through the OOMPF index at [oompf.run](https://oompf.run).
|
|
5
|
+
|
|
6
|
+
A local profile becomes a public GitHub Gist, its metadata is registered in the
|
|
7
|
+
index, and anyone can reinstall it as a native OMP profile:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
oompf publish <profile> → public Gist → indexed → https://oompf.run/p/<id>
|
|
11
|
+
oompf add <url> → installs a native OMP profile
|
|
12
|
+
omp --profile <name> → run it
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The canonical profile artifact always stays at its public Gist; OOMPF persists
|
|
16
|
+
and serves **metadata only**.
|
|
17
|
+
|
|
18
|
+
## Requirements
|
|
19
|
+
|
|
20
|
+
- **Node >= 22 or Bun.** The CLI uses `Promise.withResolvers`, which requires
|
|
21
|
+
Node 22+ (or any Bun release).
|
|
22
|
+
- **GitHub CLI (`gh`), authenticated** — required for `publish`, which creates a
|
|
23
|
+
public Gist with your `gh` account. Verify with `gh auth status`; run
|
|
24
|
+
`gh auth login` first if needed.
|
|
25
|
+
- **OMP CLI (`omp`) on `PATH`** — required for `publish` (resolves the local
|
|
26
|
+
profile's config path) and `add` (resolves the install directory). OOMPF asks
|
|
27
|
+
OMP where a profile lives rather than hardcoding a home path. `omp` is itself
|
|
28
|
+
a Bun program.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
bunx @grosspoetrysystems/oompf@latest --help
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or keep it on `PATH`:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g @grosspoetrysystems/oompf
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The package is scoped; the binary is plain `oompf`. Examples below use the
|
|
43
|
+
binary name.
|
|
44
|
+
|
|
45
|
+
Working in a clone of the repository? Run it from source with
|
|
46
|
+
`bun apps/cli/src/index.ts <command>`.
|
|
47
|
+
|
|
48
|
+
## Commands
|
|
49
|
+
|
|
50
|
+
Every command prints human-readable output by default and structured JSON with
|
|
51
|
+
`--json`. On failure, every command exits non-zero and prints a stable error
|
|
52
|
+
envelope: a machine-readable `code`, a human `message`, and optional
|
|
53
|
+
value-free `details`.
|
|
54
|
+
|
|
55
|
+
All commands target `https://oompf.run` by default. Set `OOMPF_BASE_URL` to point
|
|
56
|
+
elsewhere, for example at a local instance:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
OOMPF_BASE_URL=http://localhost:4321 oompf search anthropic
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### `oompf publish [profile]`
|
|
63
|
+
|
|
64
|
+
Resolve a local OMP profile (pass the name, or omit it when exactly one profile
|
|
65
|
+
is unambiguous), validate and secret-scan its `config.yml`, create a public
|
|
66
|
+
one-file Gist, and register its metadata with the index.
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
oompf publish work
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Output: the `githubUrl`, the canonical `oompfUrl` (`https://oompf.run/p/<id>`),
|
|
73
|
+
a copyable `addCommand`, the artifact `hash`, the structural verdict, and any
|
|
74
|
+
warnings.
|
|
75
|
+
|
|
76
|
+
Failure modes:
|
|
77
|
+
|
|
78
|
+
- `no_profile` — no OMP profiles were found; pass an explicit name.
|
|
79
|
+
- `ambiguous_profile` — more than one profile exists; pass the one to publish.
|
|
80
|
+
- `missing_config` — the profile has no `config.yml` / `config.yaml`.
|
|
81
|
+
- `invalid_artifact` — the profile failed structural validation.
|
|
82
|
+
- `blocking_secrets` — high-confidence secrets were detected in the config;
|
|
83
|
+
nothing is published. Remove them and retry.
|
|
84
|
+
- GitHub authentication or Gist-creation failure (e.g. `gh` not installed or
|
|
85
|
+
not authenticated), or registration failure against the index
|
|
86
|
+
(`network_error`, or the server's own code such as `validation_failed`).
|
|
87
|
+
|
|
88
|
+
Nothing is registered if local validation fails.
|
|
89
|
+
|
|
90
|
+
### `oompf add <ref> [--name <name>]`
|
|
91
|
+
|
|
92
|
+
Install a shared profile as a native OMP profile. The reference may be an OOMPF
|
|
93
|
+
URL or id, a public Gist URL, or a bare Gist id.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
oompf add https://oompf.run/p/prof_1b7c9e0a4d2f3a5b6c8d9e0f1a2b3c4d
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The canonical YAML is fetched and re-validated before anything is written. The
|
|
100
|
+
local name defaults to `<owner>-<profile>` and overrides with `--name`. The
|
|
101
|
+
install directory is resolved by asking OMP itself. An existing config is
|
|
102
|
+
refused outright — there is no overwrite and no `--force`.
|
|
103
|
+
|
|
104
|
+
Output: the installed `name`, the `path` written, the artifact `hash`, the
|
|
105
|
+
`command` to run it, and any warnings.
|
|
106
|
+
|
|
107
|
+
Failure modes:
|
|
108
|
+
|
|
109
|
+
- `invalid_artifact` — the fetched artifact failed structural validation.
|
|
110
|
+
- `invalid_name` — the derived (or `--name`) profile name violates OMP's naming
|
|
111
|
+
rules; pass an explicit valid `--name`.
|
|
112
|
+
- `target_exists` — a profile with that name already has a config; OOMPF refuses
|
|
113
|
+
to overwrite it.
|
|
114
|
+
- `network_error` — the index or Gist source could not be reached.
|
|
115
|
+
- The Gist is missing or private, or the reference is not a supported Gist/URL.
|
|
116
|
+
|
|
117
|
+
### `oompf inspect <ref>`
|
|
118
|
+
|
|
119
|
+
Show a shared profile's metadata without installing it.
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
oompf inspect https://oompf.run/p/prof_1b7c9e0a4d2f3a5b6c8d9e0f1a2b3c4d
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
An OOMPF reference is answered from the index; a Gist reference is fetched and
|
|
126
|
+
validated live. Output is metadata only — models, providers, aliases, the
|
|
127
|
+
structural verdict, provenance, and the install command. The canonical artifact
|
|
128
|
+
content is never emitted.
|
|
129
|
+
|
|
130
|
+
Failure modes: `not_found` for an unknown indexed id; `network_error` when the
|
|
131
|
+
index is unreachable; Gist fetch errors when the source is missing, private, or
|
|
132
|
+
unsupported.
|
|
133
|
+
|
|
134
|
+
### `oompf search [query]`
|
|
135
|
+
|
|
136
|
+
Free-text search over the index. Omitting the query lists all indexed profiles.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
oompf search anthropic
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Output: the normalized `query`, the result `count`, and one compact metadata-only
|
|
143
|
+
record per match (id, name, owner, models, providers, revision, structural
|
|
144
|
+
verdict, source, and canonical URL).
|
|
145
|
+
|
|
146
|
+
Failure mode: `network_error` when the index is unreachable.
|
|
147
|
+
|
|
148
|
+
## JSON output and errors
|
|
149
|
+
|
|
150
|
+
- `--json` on any command returns the same data the human output renders,
|
|
151
|
+
machine-readable.
|
|
152
|
+
- Failures use a stable envelope with a machine-readable `code` — see the codes
|
|
153
|
+
listed per command above. Network failures map to `network_error`; unexpected
|
|
154
|
+
errors fall back to the generic code `error`. Server errors surface the
|
|
155
|
+
server's own code (for example `not_found`, `validation_failed`,
|
|
156
|
+
`internal_error`).
|
|
157
|
+
|
|
158
|
+
## Safety
|
|
159
|
+
|
|
160
|
+
- **Secrets are scanned before publish.** High-confidence findings block the
|
|
161
|
+
publish with `blocking_secrets`; nothing leaves your machine.
|
|
162
|
+
- **Installs never overwrite.** An existing target raises `target_exists`; there
|
|
163
|
+
is no `--force`.
|
|
164
|
+
- **Metadata only.** OOMPF indexes metadata and validation results; the canonical
|
|
165
|
+
artifact stays at its public Gist.
|
|
166
|
+
|
|
167
|
+
## Links
|
|
168
|
+
|
|
169
|
+
- Documentation: [https://oompf.run/docs/](https://oompf.run/docs/)
|
|
170
|
+
- Repository: [grosspoetrysystems/oompf](https://github.com/grosspoetrysystems/oompf)
|
|
171
|
+
- Issues: [https://github.com/grosspoetrysystems/oompf/issues](https://github.com/grosspoetrysystems/oompf/issues)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { Cli } from "incur";
|
|
2
|
+
//#region ../../packages/core/dist/omp-profile.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Portable OMP profile discovery and path resolution.
|
|
5
|
+
*
|
|
6
|
+
* OOMPF never hardcodes `~/.omp`. Instead it treats the OMP CLI as the single
|
|
7
|
+
* source of truth for where a profile's agent directory lives, invoking
|
|
8
|
+
* `omp --profile <name> config path` (and the profile-less `omp config path`)
|
|
9
|
+
* with the current environment propagated. This honours `PI_CONFIG_DIR`,
|
|
10
|
+
* `PI_CODING_AGENT_DIR`, XDG base directories, and OMP's own profile
|
|
11
|
+
* resolution without OOMPF having to re-implement any of it.
|
|
12
|
+
*
|
|
13
|
+
* OMP is always invoked as an argv array (never a shell string), so profile
|
|
14
|
+
* names — even hostile ones — are passed as opaque arguments with no shell
|
|
15
|
+
* interpolation.
|
|
16
|
+
*/
|
|
17
|
+
/** A profile found on disk under OMP's resolved profiles directory. */
|
|
18
|
+
interface DiscoveredProfile {
|
|
19
|
+
/** Absolute path to the profile's agent directory. */
|
|
20
|
+
readonly agentDir: string;
|
|
21
|
+
/** Absolute path to `config.yml`/`config.yaml`, or `null` if neither exists. */
|
|
22
|
+
readonly configPath: string | null;
|
|
23
|
+
/** The profile name (directory basename), already OMP-valid. */
|
|
24
|
+
readonly name: string;
|
|
25
|
+
}
|
|
26
|
+
/** The fully resolved configuration for a single existing profile. */
|
|
27
|
+
interface ResolvedProfileConfig {
|
|
28
|
+
/** Absolute path to the profile's agent directory (verified to exist). */
|
|
29
|
+
readonly agentDir: string;
|
|
30
|
+
/** Absolute path to the loaded config file, or `null` when none is present. */
|
|
31
|
+
readonly configPath: string | null;
|
|
32
|
+
/** Parsed config document (mapping root), or `null` when no config exists. */
|
|
33
|
+
readonly document: Record<string, unknown> | null;
|
|
34
|
+
/** The profile name that was resolved. */
|
|
35
|
+
readonly profile: string;
|
|
36
|
+
}
|
|
37
|
+
/** Options accepted by every resolver; `ompCommand` overrides the binary. */
|
|
38
|
+
interface OmpProfileOptions {
|
|
39
|
+
/** Executable used to invoke OMP. Defaults to `"omp"` on `PATH`. */
|
|
40
|
+
readonly ompCommand?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Resolve the agent directory OMP would use to install a profile named `name`.
|
|
44
|
+
*
|
|
45
|
+
* Validates the name first, then asks OMP for the path. Succeeds for a profile
|
|
46
|
+
* that does not yet exist — the returned directory is an install target, so it
|
|
47
|
+
* is not required to be present on disk.
|
|
48
|
+
*/
|
|
49
|
+
declare function resolveInstallTarget(name: string, options?: OmpProfileOptions): Promise<string>;
|
|
50
|
+
/**
|
|
51
|
+
* Resolve the full configuration for an existing profile.
|
|
52
|
+
*
|
|
53
|
+
* Validates the name, resolves the agent directory via OMP (which MUST exist),
|
|
54
|
+
* then loads `config.yml`/`config.yaml` if present. Rejects when the profile's
|
|
55
|
+
* agent directory is missing.
|
|
56
|
+
*/
|
|
57
|
+
declare function resolveProfileConfig(profile: string, options?: OmpProfileOptions): Promise<ResolvedProfileConfig>;
|
|
58
|
+
/**
|
|
59
|
+
* Discover every profile present under OMP's resolved profiles directory.
|
|
60
|
+
*
|
|
61
|
+
* The profiles root is derived from OMP's own default agent path (`omp config
|
|
62
|
+
* path`), so it follows whatever `PI_CONFIG_DIR`/XDG/etc. resolution OMP
|
|
63
|
+
* applies. Directory entries whose names are not OMP-valid, and profiles whose
|
|
64
|
+
* agent directory is absent, are skipped. Results are sorted by name.
|
|
65
|
+
*/
|
|
66
|
+
declare function discoverProfiles(options?: OmpProfileOptions): Promise<DiscoveredProfile[]>;
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region ../../packages/github/dist/gh.d.ts
|
|
69
|
+
/**
|
|
70
|
+
* CLI-side `gh` (GitHub CLI) integration for OOMPF.
|
|
71
|
+
*
|
|
72
|
+
* This module shells out to the `gh` binary to read the authenticated identity
|
|
73
|
+
* and to publish public Gists. It MUST only ever be imported by CLI-side code:
|
|
74
|
+
* it spawns child processes and therefore cannot run inside a Cloudflare
|
|
75
|
+
* Worker. Every invocation passes an explicit argument array to the runner —
|
|
76
|
+
* there is no shell string and no interpolation, so profile names,
|
|
77
|
+
* descriptions, and file contents can never be reinterpreted as shell syntax.
|
|
78
|
+
*
|
|
79
|
+
* All process spawning is funnelled through an injectable {@link CommandRunner}
|
|
80
|
+
* seam so tests can exercise identity resolution and Gist publishing
|
|
81
|
+
* hermetically, without a real `gh` binary and without creating real Gists.
|
|
82
|
+
*/
|
|
83
|
+
/** Outcome of running a single command. */
|
|
84
|
+
interface CommandResult {
|
|
85
|
+
/** Process exit code; `null` when the process was terminated by a signal. */
|
|
86
|
+
readonly exitCode: number | null;
|
|
87
|
+
readonly stderr: string;
|
|
88
|
+
readonly stdout: string;
|
|
89
|
+
}
|
|
90
|
+
/** A single command invocation: an executable plus a literal argument array. */
|
|
91
|
+
interface CommandInput {
|
|
92
|
+
/** Arguments passed verbatim; never concatenated into a shell command. */
|
|
93
|
+
readonly args: readonly string[];
|
|
94
|
+
/** Executable to run (e.g. `"gh"`). Never a shell string. */
|
|
95
|
+
readonly command: string;
|
|
96
|
+
/** Optional UTF-8 text piped to the process stdin. */
|
|
97
|
+
readonly stdin?: string;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Injectable command seam. Implementations MUST NOT invoke a shell; they run
|
|
101
|
+
* `input.command` with `input.args` as discrete argv entries.
|
|
102
|
+
*
|
|
103
|
+
* A missing executable MUST reject (e.g. an `ENOENT` error) rather than
|
|
104
|
+
* resolve with a non-zero exit code, so callers can distinguish "not
|
|
105
|
+
* installed" from "ran and failed".
|
|
106
|
+
*/
|
|
107
|
+
type CommandRunner = (input: CommandInput) => Promise<CommandResult>;
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region ../../packages/github/dist/gists.d.ts
|
|
110
|
+
/** Minimal structural view of a `fetch` response used by this module. */
|
|
111
|
+
interface GistFetchResponse {
|
|
112
|
+
readonly ok: boolean;
|
|
113
|
+
readonly status: number;
|
|
114
|
+
text(): Promise<string>;
|
|
115
|
+
}
|
|
116
|
+
/** Injectable `fetch` seam so tests never hit the network. */
|
|
117
|
+
type GistFetch = (url: string, init?: {
|
|
118
|
+
readonly headers?: Record<string, string>;
|
|
119
|
+
}) => Promise<GistFetchResponse>;
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/deps.d.ts
|
|
122
|
+
/** Minimal structural view of an HTTP response the API client consumes. */
|
|
123
|
+
interface HttpResponse {
|
|
124
|
+
readonly ok: boolean;
|
|
125
|
+
readonly status: number;
|
|
126
|
+
text(): Promise<string>;
|
|
127
|
+
}
|
|
128
|
+
/** Injectable HTTP seam for the OOMPF web API (register/search/metadata). */
|
|
129
|
+
type HttpFetch = (url: string, init?: {
|
|
130
|
+
readonly method?: string;
|
|
131
|
+
readonly headers?: Record<string, string>;
|
|
132
|
+
readonly body?: string;
|
|
133
|
+
}) => Promise<HttpResponse>;
|
|
134
|
+
/** Injectable filesystem seam for reading and atomically installing configs. */
|
|
135
|
+
interface FsSeam {
|
|
136
|
+
/** True when a path exists (file or directory). */
|
|
137
|
+
exists(path: string): Promise<boolean>;
|
|
138
|
+
/** Recursively create a directory with the given octal permission mode. */
|
|
139
|
+
mkdir(path: string, mode: number): Promise<void>;
|
|
140
|
+
/** Read a UTF-8 text file. */
|
|
141
|
+
readFile(path: string): Promise<string>;
|
|
142
|
+
/** Write a UTF-8 text file with the given octal permission mode. */
|
|
143
|
+
writeFile(path: string, data: string, mode: number): Promise<void>;
|
|
144
|
+
}
|
|
145
|
+
/** Every seam a command may need, each optional and defaulted at the boundary. */
|
|
146
|
+
interface CliDeps {
|
|
147
|
+
/** Profile discovery seam (publish default-profile derivation). */
|
|
148
|
+
readonly discoverProfiles?: typeof discoverProfiles;
|
|
149
|
+
/** Filesystem seam. */
|
|
150
|
+
readonly fs?: FsSeam;
|
|
151
|
+
/** `gh` executable name; defaults to `"gh"`. */
|
|
152
|
+
readonly ghCommand?: string;
|
|
153
|
+
/** Gist raw-fetch seam; defaults to the global `fetch`. */
|
|
154
|
+
readonly gistFetch?: GistFetch;
|
|
155
|
+
/** OOMPF web API HTTP seam; defaults to the global `fetch`. */
|
|
156
|
+
readonly httpFetch?: HttpFetch;
|
|
157
|
+
/** `omp` executable name; defaults to `"omp"`. */
|
|
158
|
+
readonly ompCommand?: string;
|
|
159
|
+
/** Install-target resolver seam (add). */
|
|
160
|
+
readonly resolveInstallTarget?: typeof resolveInstallTarget;
|
|
161
|
+
/** Existing-profile resolver seam (publish). */
|
|
162
|
+
readonly resolveProfileConfig?: typeof resolveProfileConfig;
|
|
163
|
+
/** `gh` command runner seam (auth check + Gist creation). */
|
|
164
|
+
readonly runner?: CommandRunner;
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/index.d.ts
|
|
168
|
+
/**
|
|
169
|
+
* OOMPF CLI version, surfaced by `oompf --version`.
|
|
170
|
+
*
|
|
171
|
+
* Must match `package.json`; `index.test.ts` asserts it, because a published
|
|
172
|
+
* binary reporting the wrong version makes every bug report ambiguous.
|
|
173
|
+
*/
|
|
174
|
+
declare const CLI_VERSION = "0.1.0";
|
|
175
|
+
/** Build the OOMPF CLI with the given (optional) injectable seams. */
|
|
176
|
+
declare function createCli(deps?: CliDeps): Cli.Cli<{}, undefined, undefined, undefined>;
|
|
177
|
+
//#endregion
|
|
178
|
+
export { CLI_VERSION, createCli };
|
|
179
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../../packages/core/dist/omp-profile.d.ts","../../../packages/github/dist/gh.d.ts","../../../packages/github/dist/gists.d.ts","../src/deps.ts","../src/index.ts"],"mappings":";;;;;;;;;;;;;;;;;UAeiB;;WAEJ;;WAEA;;WAEA;;;UAGI;;WAEJ;;WAEA;;WAEA,UAAU;;WAEV;;;UAGI;;WAEJ;;;;;;;;;iBASW,qBAAqB,cAAc,UAAU,oBAAoB;;;;;;;;iBAQjE,qBAAqB,iBAAiB,UAAU,oBAAoB,QAAQ;;;;;;;;;iBAS5E,iBAAiB,UAAU,oBAAoB,QAAQ;;;;;;;;;;;;;;;;;;UChD9D;;WAEJ;WACA;WACA;;;UAGI;;WAEJ;;WAEA;;WAEA;;;;;;;;;;KAUD,iBAAiB,OAAO,iBAAiB,QAAQ;;;;UCG5C;WACJ;WACA;EACT,QAAQ;;;KAGA,aAAa,aAAa;WACzB,UAAU;MACjB,QAAQ;;;;UC3BG;WACN;WACA;EACT,QAAQ;;;KAIE,aACV,aACA;WACW;WACA,UAAU;WACV;MAER,QAAQ;;UAGI;;EAEf,OAAO,eAAe;;EAEtB,MAAM,cAAc,eAAe;;EAEnC,SAAS,eAAe;;EAExB,UAAU,cAAc,cAAc,eAAe;;;UAoCtC;;WAEN,0BAA0B;;WAE1B,KAAK;;WAEL;;WAEA,YAAY;;WAEZ,YAAY;;WAEZ;;WAEA,8BAA8B;;WAE9B,8BAA8B;;WAE9B,SAAS;;;;;;;;;;cC5EP;;iBAGG,UAAU,OAAM,UAAY,IAAA"}
|