@run402/sdk 4.39.0 → 4.40.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.
Files changed (36) hide show
  1. package/dist/namespaces/gitvault.crypto.d.ts +10 -0
  2. package/dist/namespaces/gitvault.crypto.d.ts.map +1 -1
  3. package/dist/namespaces/gitvault.crypto.js +10 -0
  4. package/dist/namespaces/gitvault.crypto.js.map +1 -1
  5. package/dist/namespaces/gitvault.d.ts +141 -4
  6. package/dist/namespaces/gitvault.d.ts.map +1 -1
  7. package/dist/namespaces/gitvault.js +226 -3
  8. package/dist/namespaces/gitvault.js.map +1 -1
  9. package/dist/node/gitvault-keystore.d.ts +11 -1
  10. package/dist/node/gitvault-keystore.d.ts.map +1 -1
  11. package/dist/node/gitvault-keystore.js.map +1 -1
  12. package/dist/node/gitvault-mirror-backend.d.ts +88 -0
  13. package/dist/node/gitvault-mirror-backend.d.ts.map +1 -0
  14. package/dist/node/gitvault-mirror-backend.js +374 -0
  15. package/dist/node/gitvault-mirror-backend.js.map +1 -0
  16. package/dist/node/gitvault-mirror-config.d.ts +53 -0
  17. package/dist/node/gitvault-mirror-config.d.ts.map +1 -0
  18. package/dist/node/gitvault-mirror-config.js +112 -0
  19. package/dist/node/gitvault-mirror-config.js.map +1 -0
  20. package/dist/node/gitvault-mirror.d.ts +120 -0
  21. package/dist/node/gitvault-mirror.d.ts.map +1 -0
  22. package/dist/node/gitvault-mirror.js +464 -0
  23. package/dist/node/gitvault-mirror.js.map +1 -0
  24. package/dist/node/gitvault-publication.d.ts +131 -0
  25. package/dist/node/gitvault-publication.d.ts.map +1 -1
  26. package/dist/node/gitvault-publication.js +145 -1
  27. package/dist/node/gitvault-publication.js.map +1 -1
  28. package/dist/node/gitvault-recover.d.ts +136 -0
  29. package/dist/node/gitvault-recover.d.ts.map +1 -0
  30. package/dist/node/gitvault-recover.js +412 -0
  31. package/dist/node/gitvault-recover.js.map +1 -0
  32. package/dist/node/gitvault-snapshot.d.ts +8 -0
  33. package/dist/node/gitvault-snapshot.d.ts.map +1 -1
  34. package/dist/node/gitvault-snapshot.js +11 -0
  35. package/dist/node/gitvault-snapshot.js.map +1 -1
  36. package/package.json +1 -1
@@ -0,0 +1,53 @@
1
+ import { GitvaultKeystore } from "./gitvault-keystore.js";
2
+ /** Where the mirror writes objects. Directory is a plain local (or network-mounted) path; S3 is `s3://<bucket>/<prefix>`. */
3
+ export type GitvaultMirrorDestination = {
4
+ kind: "directory";
5
+ path: string;
6
+ } | {
7
+ kind: "s3";
8
+ bucket: string;
9
+ prefix: string;
10
+ region: string;
11
+ endpoint?: string;
12
+ };
13
+ /** How the S3 destination authenticates. Never a raw key — see the module doc. */
14
+ export type GitvaultMirrorCredential = {
15
+ kind: "profile";
16
+ profile: string;
17
+ } | {
18
+ kind: "ambient";
19
+ };
20
+ /** `mirrors/<repo_id>.json` — the ONLY thing this file persists: where, and which named credential to resolve at use time. */
21
+ export interface GitvaultMirrorConfig {
22
+ version: 1;
23
+ repo_id: string;
24
+ destination: GitvaultMirrorDestination;
25
+ /** Present only for an `s3` destination — a directory destination needs no credential. */
26
+ credential?: GitvaultMirrorCredential;
27
+ created_at: string;
28
+ updated_at: string;
29
+ }
30
+ export declare function mirrorsDir(keystore: GitvaultKeystore): string;
31
+ export declare function mirrorConfigPath(keystore: GitvaultKeystore, repoId: string): string;
32
+ /** Read the mirror config for one vault, or `null` when none is configured. */
33
+ export declare function readMirrorConfig(keystore: GitvaultKeystore, repoId: string): GitvaultMirrorConfig | null;
34
+ /** Every repo id with a mirror configured on this machine. */
35
+ export declare function listMirroredRepoIds(keystore: GitvaultKeystore): string[];
36
+ /** Set (create or replace) the mirror destination for one vault. */
37
+ export declare function saveMirrorConfig(keystore: GitvaultKeystore, input: {
38
+ repo_id: string;
39
+ destination: GitvaultMirrorDestination;
40
+ credential?: GitvaultMirrorCredential;
41
+ }, now?: () => Date): GitvaultMirrorConfig;
42
+ /** Remove the mirror config for one vault. Never touches the mirror's own bytes — this only stops future pushes/syncs from targeting it. */
43
+ export declare function removeMirrorConfig(keystore: GitvaultKeystore, repoId: string): {
44
+ removed: boolean;
45
+ };
46
+ /** Parse `s3://<bucket>/<prefix>` or a plain filesystem path into a {@link GitvaultMirrorDestination}. */
47
+ export declare function parseMirrorDestinationUrl(url: string, options?: {
48
+ region?: string;
49
+ endpoint?: string;
50
+ }): GitvaultMirrorDestination;
51
+ /** Render a destination back to the address form a human typed (for `status`/errors). */
52
+ export declare function formatMirrorDestination(destination: GitvaultMirrorDestination): string;
53
+ //# sourceMappingURL=gitvault-mirror-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-mirror-config.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-mirror-config.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,gBAAgB,EAAyC,MAAM,wBAAwB,CAAC;AAMjG,6HAA6H;AAC7H,MAAM,MAAM,yBAAyB,GACjC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtF,kFAAkF;AAClF,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,8HAA8H;AAC9H,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,yBAAyB,CAAC;IACvC,0FAA0F;IAC1F,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAE7D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGnF;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAaxG;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAQxE;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,yBAAyB,CAAC;IAAC,UAAU,CAAC,EAAE,wBAAwB,CAAA;CAAE,EAAE,GAAG,GAAE,MAAM,IAAuB,GAAG,oBAAoB,CAehO;AAED,4IAA4I;AAC5I,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CASnG;AAED,0GAA0G;AAC1G,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,yBAAyB,CAYtI;AAED,yFAAyF;AACzF,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,yBAAyB,GAAG,MAAM,CAEtF"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * gitvault-mirror-and-recover — mirror destination config (design D1/D2,
3
+ * task 2.1).
4
+ *
5
+ * Per-vault mirror configuration lives BESIDE the keystore, in its own
6
+ * sibling directory (`<keystore root>/mirrors/<repo_id>.json`) — never in
7
+ * `run402.config.json` (that file is committed to the repository, and a
8
+ * mirror destination is a per-machine operational fact, not something to
9
+ * share with every clone) and never containing a raw secret value. The
10
+ * credential field names an AWS profile OR selects the ambient environment
11
+ * chain (`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`/`AWS_SESSION_TOKEN`) —
12
+ * resolved at USE time by {@link ../node/gitvault-mirror-backend.js}, never
13
+ * read or cached here. D1 is the reason this file exists at all: run402
14
+ * never holds a credential to the customer's bucket, so the credential must
15
+ * live somewhere run402 code never uploads or transmits — this config file,
16
+ * read only by the client's own machine.
17
+ */
18
+ import { existsSync, readdirSync, unlinkSync } from "node:fs";
19
+ import { join } from "node:path";
20
+ import { LocalError } from "../errors.js";
21
+ import { GITVAULT_SRC_RE } from "../namespaces/gitvault.crypto.js";
22
+ import { readFileNoFollow, writeFileAtomic0600 } from "./gitvault-keystore.js";
23
+ function fail(code, message, context, details, nextActions) {
24
+ throw new LocalError(message, context, { code, details, ...(nextActions ? { next_actions: nextActions } : {}) });
25
+ }
26
+ export function mirrorsDir(keystore) {
27
+ return join(keystore.rootDir, "mirrors");
28
+ }
29
+ export function mirrorConfigPath(keystore, repoId) {
30
+ if (!GITVAULT_SRC_RE.test(repoId))
31
+ fail("GITVAULT_BAD_REPO_ID", `not a src_ id: ${repoId}`, "resolving gitvault mirror config path");
32
+ return join(mirrorsDir(keystore), `${repoId}.json`);
33
+ }
34
+ /** Read the mirror config for one vault, or `null` when none is configured. */
35
+ export function readMirrorConfig(keystore, repoId) {
36
+ const text = readFileNoFollow(mirrorConfigPath(keystore, repoId));
37
+ if (!text)
38
+ return null;
39
+ let parsed;
40
+ try {
41
+ parsed = JSON.parse(text);
42
+ }
43
+ catch (e) {
44
+ fail("GITVAULT_MIRROR_CONFIG_CORRUPT", `mirror config for ${repoId} is not valid JSON: ${e.message}`, "reading gitvault mirror config", { repo_id: repoId });
45
+ }
46
+ if (parsed.version !== 1 || parsed.repo_id !== repoId || !parsed.destination) {
47
+ fail("GITVAULT_MIRROR_CONFIG_CORRUPT", `mirror config for ${repoId} is not a version-1 gitvault mirror config`, "reading gitvault mirror config", { repo_id: repoId });
48
+ }
49
+ return parsed;
50
+ }
51
+ /** Every repo id with a mirror configured on this machine. */
52
+ export function listMirroredRepoIds(keystore) {
53
+ const dir = mirrorsDir(keystore);
54
+ if (!existsSync(dir))
55
+ return [];
56
+ return readdirSync(dir)
57
+ .filter((n) => n.endsWith(".json"))
58
+ .map((n) => n.slice(0, -5))
59
+ .filter((id) => GITVAULT_SRC_RE.test(id))
60
+ .sort();
61
+ }
62
+ /** Set (create or replace) the mirror destination for one vault. */
63
+ export function saveMirrorConfig(keystore, input, now = () => new Date()) {
64
+ if (input.destination.kind === "s3" && !input.credential) {
65
+ fail("GITVAULT_MIRROR_CREDENTIAL_REQUIRED", "an s3 mirror destination needs a credential — pass --profile <name> or --ambient", "configuring gitvault mirror");
66
+ }
67
+ const existing = readMirrorConfig(keystore, input.repo_id);
68
+ const full = {
69
+ version: 1,
70
+ repo_id: input.repo_id,
71
+ destination: input.destination,
72
+ ...(input.credential ? { credential: input.credential } : {}),
73
+ created_at: existing?.created_at ?? now().toISOString(),
74
+ updated_at: now().toISOString(),
75
+ };
76
+ writeFileAtomic0600(mirrorConfigPath(keystore, input.repo_id), JSON.stringify(full, null, 2));
77
+ return full;
78
+ }
79
+ /** Remove the mirror config for one vault. Never touches the mirror's own bytes — this only stops future pushes/syncs from targeting it. */
80
+ export function removeMirrorConfig(keystore, repoId) {
81
+ const path = mirrorConfigPath(keystore, repoId);
82
+ if (!existsSync(path))
83
+ return { removed: false };
84
+ try {
85
+ unlinkSync(path);
86
+ }
87
+ catch (e) {
88
+ fail("GITVAULT_MIRROR_CONFIG_REMOVE_FAILED", `could not remove mirror config for ${repoId}: ${e.message}`, "removing gitvault mirror config", { repo_id: repoId });
89
+ }
90
+ return { removed: true };
91
+ }
92
+ /** Parse `s3://<bucket>/<prefix>` or a plain filesystem path into a {@link GitvaultMirrorDestination}. */
93
+ export function parseMirrorDestinationUrl(url, options = {}) {
94
+ if (url.startsWith("s3://")) {
95
+ const rest = url.slice("s3://".length);
96
+ const slash = rest.indexOf("/");
97
+ const bucket = slash === -1 ? rest : rest.slice(0, slash);
98
+ const prefix = slash === -1 ? "" : rest.slice(slash + 1).replace(/\/+$/, "");
99
+ if (!bucket)
100
+ fail("GITVAULT_MIRROR_DESTINATION_INVALID", `${url} names no bucket`, "parsing gitvault mirror destination", { url });
101
+ const region = options.region ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION;
102
+ if (!region)
103
+ fail("GITVAULT_MIRROR_REGION_REQUIRED", `an s3 destination needs a region — pass --region or set AWS_REGION`, "parsing gitvault mirror destination", { url });
104
+ return { kind: "s3", bucket, prefix, region, ...(options.endpoint ? { endpoint: options.endpoint } : {}) };
105
+ }
106
+ return { kind: "directory", path: url };
107
+ }
108
+ /** Render a destination back to the address form a human typed (for `status`/errors). */
109
+ export function formatMirrorDestination(destination) {
110
+ return destination.kind === "s3" ? `s3://${destination.bucket}/${destination.prefix}` : destination.path;
111
+ }
112
+ //# sourceMappingURL=gitvault-mirror-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-mirror-config.js","sourceRoot":"","sources":["../../src/node/gitvault-mirror-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import type { Client } from "../kernel.js";
2
+ import { GITVAULT_MIRROR_KEYSTORE_STILL_REQUIRED_STATEMENT, GITVAULT_MIRROR_VALIDITY_NOT_FRESHNESS_STATEMENT } from "../namespaces/gitvault.crypto.js";
3
+ import { GitvaultKeystore } from "./gitvault-keystore.js";
4
+ import { type GitvaultMirrorBackend } from "./gitvault-mirror-backend.js";
5
+ /**
6
+ * REPO-RELATIVE — the `source/<repo_id>/` prefix has already been stripped
7
+ * (see the module doc's mirror-layout mapping). This is the shape every
8
+ * OTHER function in this module, `gitvault-recover.ts`, and the mirror
9
+ * backend interface all consume; nothing here ever sees the raw wire key
10
+ * except `listGitvaultObjectsAll` itself.
11
+ *
12
+ * `size_bytes` is an exact decimal string for EVERY kind, including the two
13
+ * generation-addressed chain kinds (`head`/`vault_genesis` at generation
14
+ * zero, `admission_record`) — never `null`.
15
+ */
16
+ export interface GitvaultObjectEntry {
17
+ key: string;
18
+ object_kind: string;
19
+ sha256: string;
20
+ size_bytes: string;
21
+ }
22
+ /** Page through `GET /gitvault/v1/vaults/:vault_id/objects`, collecting every entry, stripped to repo-relative keys. Store-and-echo cursor per D3a — never parsed here either. */
23
+ export declare function listGitvaultObjectsAll(client: Client, repoId: string): Promise<GitvaultObjectEntry[]>;
24
+ /** Read one object's bytes by key, using the same wire identity every stored kind already carries (§3 layout). `null` when the gateway reports the object absent. */
25
+ export declare function readGitvaultObjectBytes(client: Client, repoId: string, entry: GitvaultObjectEntry): Promise<Uint8Array | null>;
26
+ /** Exported for the key-shape conformance test (`gitvault-mirror-recover.test.ts`) — never called for its own sake outside this module. */
27
+ export declare function generationRouteForKey(key: string): {
28
+ route: "heads" | "admissions";
29
+ generation: string;
30
+ } | null;
31
+ /**
32
+ * `key_envelope` is path-addressed by `(epoch, recipient_fingerprint)`, not a
33
+ * plain object_id — every other kind uses its object_id, read straight from
34
+ * the key's own filename via an ANCHORED, kind-specific pattern (never a
35
+ * loose, unanchored fallback — see {@link NON_GENERATION_KEY_SPECS}).
36
+ * Exported for the key-shape conformance test.
37
+ */
38
+ export declare function objectReadRequestForEntry(entry: GitvaultObjectEntry): {
39
+ object_kind: string;
40
+ object_id?: string;
41
+ epoch?: string;
42
+ recipient_fingerprint?: string;
43
+ };
44
+ export interface GitvaultMirrorWritePlan {
45
+ /** Every non-head, non-admission entry, in listing order — write these FIRST, in any order among themselves. */
46
+ objects: GitvaultObjectEntry[];
47
+ /** Then admission records and heads, interleaved, strictly ascending by generation (admission before its own head). */
48
+ admissionsAndHeads: GitvaultObjectEntry[];
49
+ }
50
+ /** Sort a flat listing into the admission-order write plan (module doc above). */
51
+ export declare function planMirrorWrite(entries: readonly GitvaultObjectEntry[]): GitvaultMirrorWritePlan;
52
+ export interface GitvaultMirrorCopyResult {
53
+ key: string;
54
+ outcome: "copied" | "already_present" | "skipped_foreign_recipient" | "failed";
55
+ size_bytes?: string;
56
+ error?: string;
57
+ }
58
+ export interface GitvaultMirrorSyncSummary {
59
+ repo_id: string;
60
+ destination: string;
61
+ /** Faithful counts of what ACTUALLY happened this call — never an estimate (design D3a rider (e)). */
62
+ objects_listed: number;
63
+ objects_copied: number;
64
+ objects_already_present: number;
65
+ /**
66
+ * Task 5.3 follow-up: a `key_envelope` wrapped for a DIFFERENT recipient
67
+ * than this machine's own identity — EXPECTED, not a problem. The
68
+ * recipient-only read gate means a mirror can only ever hold envelopes
69
+ * addressed to the local identity; a multi-recipient vault
70
+ * (gitvault-human-envelopes) makes this the norm. Never counted toward
71
+ * `objects_failed`, and never causes `mirror sync` to report anything but
72
+ * success — named per-key in `skipped_foreign_recipient_keys` so a reader
73
+ * can tell "expected skip" from "silent gap" without cross-referencing.
74
+ */
75
+ objects_skipped_foreign_recipient: number;
76
+ skipped_foreign_recipient_keys: string[];
77
+ objects_failed: number;
78
+ bytes_copied: string;
79
+ errors: Array<{
80
+ key: string;
81
+ error: string;
82
+ }>;
83
+ validity_not_freshness: typeof GITVAULT_MIRROR_VALIDITY_NOT_FRESHNESS_STATEMENT;
84
+ keystore_still_required: typeof GITVAULT_MIRROR_KEYSTORE_STILL_REQUIRED_STATEMENT;
85
+ }
86
+ export interface GitvaultMirrorSyncOptions {
87
+ keystore?: GitvaultKeystore;
88
+ /** Test/advanced hook: an already-opened backend, bypassing config resolution. */
89
+ backend?: GitvaultMirrorBackend;
90
+ }
91
+ /**
92
+ * `run402 gitvault mirror sync` (task 2.3): list the vault's stored objects,
93
+ * diff against the mirror by key+size, fetch and hash-verify what's missing,
94
+ * write it in admission order. Resumable and idempotent — running it twice in
95
+ * a row with nothing new copies nothing the second time.
96
+ */
97
+ export declare function mirrorSync(client: Client, repoId: string, options?: GitvaultMirrorSyncOptions): Promise<GitvaultMirrorSyncSummary>;
98
+ export interface GitvaultMirrorPushResult {
99
+ attempted: boolean;
100
+ outcome: "pushed" | "skipped_no_mirror" | "failed";
101
+ summary?: GitvaultMirrorSyncSummary;
102
+ error?: string;
103
+ }
104
+ /**
105
+ * Fires after an ordinary vault push/deploy produces a new generation. NEVER
106
+ * throws and NEVER alters the caller's deploy/push outcome (design D6) — a
107
+ * mirror is strictly extra durability, and its failure is reported BESIDE the
108
+ * vault result as a distinct line, not folded into it. Fires only when a
109
+ * mirror is configured for this vault; a vault with no mirror gets
110
+ * `skipped_no_mirror` (not an error) so callers can log it uniformly without
111
+ * branching on whether mirroring was ever opted into.
112
+ *
113
+ * Implemented as a full (but INCREMENTAL, idempotent) sync rather than a
114
+ * push-scoped upload: the objects listing + diff-by-size machinery already
115
+ * makes an all-caught-up sync cheap (one listing page, zero copies), and this
116
+ * keeps the admission-order write discipline in exactly one place instead of
117
+ * a second, push-scoped code path that could drift from it.
118
+ */
119
+ export declare function mirrorPushForGeneration(client: Client, repoId: string, options?: GitvaultMirrorSyncOptions): Promise<GitvaultMirrorPushResult>;
120
+ //# sourceMappingURL=gitvault-mirror.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitvault-mirror.d.ts","sourceRoot":"","sources":["../../src/node/gitvault-mirror.ts"],"names":[],"mappings":"AAuFA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAEL,iDAAiD,EACjD,gDAAgD,EACjD,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE1D,OAAO,EAAuD,KAAK,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAY/H;;;;;;;;;;GAUG;AACH,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AA4CD,kLAAkL;AAClL,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAe3G;AAED,qKAAqK;AACrK,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA0CpI;AAED,2IAA2I;AAC3I,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,OAAO,GAAG,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAM/G;AAmCD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,mBAAmB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAAE,CAwBjK;AA2BD,MAAM,WAAW,uBAAuB;IACtC,gHAAgH;IAChH,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,uHAAuH;IACvH,kBAAkB,EAAE,mBAAmB,EAAE,CAAC;CAC3C;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,GAAG,uBAAuB,CAsBhG;AAID,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,QAAQ,GAAG,iBAAiB,GAAG,2BAA2B,GAAG,QAAQ,CAAC;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,sGAAsG;IACtG,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;IAChC;;;;;;;;;OASG;IACH,iCAAiC,EAAE,MAAM,CAAC;IAC1C,8BAA8B,EAAE,MAAM,EAAE,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9C,sBAAsB,EAAE,OAAO,gDAAgD,CAAC;IAChF,uBAAuB,EAAE,OAAO,iDAAiD,CAAC;CACnF;AAsDD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,kFAAkF;IAClF,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAgD5I;AAgBD,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,QAAQ,GAAG,mBAAmB,GAAG,QAAQ,CAAC;IACnD,OAAO,CAAC,EAAE,yBAAyB,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAgBxJ"}