@agentick/sandbox 0.2.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 ADDED
@@ -0,0 +1,251 @@
1
+ # @agentick/sandbox
2
+
3
+ Sandbox primitive layer for Agentick. Provides types, React context, a `<Sandbox>` JSX component, and pre-built tools (Shell, ReadFile, WriteFile, EditFile) for sandboxed code execution.
4
+
5
+ Provider adapters (`@agentick/sandbox-local`, `@agentick/sandbox-docker`, etc.) implement `SandboxProvider` and plug in via the `provider` prop.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pnpm add @agentick/sandbox
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```tsx
16
+ import { Sandbox, Shell, ReadFile, WriteFile, EditFile } from "@agentick/sandbox";
17
+ import { localProvider } from "@agentick/sandbox-local";
18
+
19
+ function CodingAgent() {
20
+ return (
21
+ <Sandbox provider={localProvider()} workspace="/tmp/project">
22
+ <Shell />
23
+ <ReadFile />
24
+ <WriteFile />
25
+ <EditFile />
26
+ <System>You are a coding assistant with sandbox access.</System>
27
+ </Sandbox>
28
+ );
29
+ }
30
+ ```
31
+
32
+ ## Component
33
+
34
+ ### `<Sandbox>`
35
+
36
+ Creates a sandbox instance and provides it to children via React context.
37
+
38
+ ```tsx
39
+ <Sandbox
40
+ provider={localProvider()} // Required — SandboxProvider implementation
41
+ workspace="/tmp/project" // Path or true for auto temp dir (default: true)
42
+ mounts={[{ host: "./src", sandbox: "/app/src", mode: "rw" }]}
43
+ allow={{ fs: true, net: false }} // Advisory permissions
44
+ env={{ NODE_ENV: "development" }} // Env vars (string or () => string)
45
+ limits={{ memory: 512_000_000 }} // Resource constraints
46
+ setup={async (sb) => {
47
+ // Post-creation setup
48
+ await sb.exec("npm install");
49
+ }}
50
+ >
51
+ {children}
52
+ </Sandbox>
53
+ ```
54
+
55
+ Uses `useData` for async initialization and `useOnUnmount` for cleanup.
56
+
57
+ ## Hook
58
+
59
+ ### `useSandbox()`
60
+
61
+ Access the nearest `Sandbox` from the component tree. Throws if no provider is found.
62
+
63
+ ```tsx
64
+ import { useSandbox } from "@agentick/sandbox";
65
+
66
+ const sandbox = useSandbox();
67
+ const result = await sandbox.exec("ls -la");
68
+ ```
69
+
70
+ Primary use: the `use()` hook on `createTool` for tree-scoped sandbox access.
71
+
72
+ ```tsx
73
+ const MyTool = createTool({
74
+ name: "my_tool",
75
+ description: "Custom sandbox tool",
76
+ input: z.object({ query: z.string() }),
77
+ use: () => ({ sandbox: useSandbox() }),
78
+ handler: async ({ query }, deps) => {
79
+ const result = await deps!.sandbox.exec(`grep -r "${query}" .`);
80
+ return [{ type: "text", text: result.stdout }];
81
+ },
82
+ });
83
+ ```
84
+
85
+ ## Tools
86
+
87
+ Four pre-built tools, all using `use()` + `useSandbox()` for tree-scoped access:
88
+
89
+ | Tool | Name | Description |
90
+ | ----------- | ------------ | ------------------------------ |
91
+ | `Shell` | `shell` | Execute a shell command |
92
+ | `ReadFile` | `read_file` | Read file contents |
93
+ | `WriteFile` | `write_file` | Write content to a file |
94
+ | `EditFile` | `edit_file` | Apply surgical edits to a file |
95
+
96
+ ```tsx
97
+ import { Shell, ReadFile, WriteFile, EditFile } from "@agentick/sandbox";
98
+
99
+ // Include all tools
100
+ <Sandbox provider={provider}>
101
+ <Shell />
102
+ <ReadFile />
103
+ <WriteFile />
104
+ <EditFile />
105
+ <MyAgent />
106
+ </Sandbox>
107
+
108
+ // Or pick specific tools
109
+ <Sandbox provider={provider}>
110
+ <Shell />
111
+ <ReadFile />
112
+ <MyAgent />
113
+ </Sandbox>
114
+ ```
115
+
116
+ ### Tree Scoping
117
+
118
+ Multiple sandboxes in the same tree work naturally. Each tool accesses its nearest `<Sandbox>` provider:
119
+
120
+ ```tsx
121
+ <Sandbox provider={localProvider()}>
122
+ <Shell /> {/* Uses local sandbox */}
123
+ <ReadFile />
124
+ </Sandbox>
125
+ <Sandbox provider={dockerProvider()}>
126
+ <Shell /> {/* Uses Docker sandbox */}
127
+ <WriteFile />
128
+ </Sandbox>
129
+ ```
130
+
131
+ ## Edit Utilities
132
+
133
+ Surgical code editing with 3-level matching that recovers from trailing whitespace, indentation mismatch, and CRLF/LF differences.
134
+
135
+ ### `applyEdits(source, edits)`
136
+
137
+ Pure transform, no I/O. Matching strategy per edit (in order):
138
+
139
+ 1. Exact byte match
140
+ 2. Line-normalized (trailing whitespace stripped)
141
+ 3. Indent-adjusted (leading whitespace baseline stripped)
142
+
143
+ ```typescript
144
+ import { applyEdits } from "@agentick/sandbox";
145
+
146
+ const result = applyEdits(source, [
147
+ { old: "return 1;", new: "return 2;" },
148
+ { old: "oldName", new: "newName", all: true },
149
+ ]);
150
+ // result.content, result.applied, result.changes
151
+ ```
152
+
153
+ ### `editFile(path, edits)`
154
+
155
+ File wrapper. Reads, applies edits, writes atomically (temp + rename).
156
+
157
+ ```typescript
158
+ import { editFile } from "@agentick/sandbox";
159
+
160
+ await editFile("/path/to/file.ts", [{ old: "const x = 1;", new: "const x = 42;" }]);
161
+ ```
162
+
163
+ ## Types
164
+
165
+ ```typescript
166
+ import type {
167
+ // Core types
168
+ SandboxHandle, // Runtime handle: exec, readFile, writeFile, editFile, destroy
169
+ SandboxProvider, // Factory: name, create, restore?, destroy?
170
+ SandboxCreateOptions, // Passed to provider.create()
171
+ SandboxConfig, // Component-level config
172
+ SandboxSnapshot, // Serializable state for persistence
173
+
174
+ // Execution
175
+ ExecOptions, // Per-command: cwd, env, timeout
176
+ ExecResult, // Output: stdout, stderr, exitCode
177
+ OutputChunk, // Streaming: stream, data
178
+
179
+ // Configuration
180
+ Mount, // Host<->sandbox path mapping
181
+ Permissions, // Advisory: fs, net, childProcess, inheritEnv
182
+ ResourceLimits, // Constraints: memory, cpu, timeout, disk, maxProcesses
183
+
184
+ // Edit
185
+ Edit, // { old, new, all? }
186
+ EditResult, // { content, applied, changes }
187
+ EditChange, // { line, removed, added }
188
+ } from "@agentick/sandbox";
189
+ ```
190
+
191
+ ## Implementing a Provider
192
+
193
+ Provider adapters implement `SandboxProvider`:
194
+
195
+ ```typescript
196
+ import type { SandboxProvider, SandboxHandle, SandboxCreateOptions } from "@agentick/sandbox";
197
+ import { applyEdits } from "@agentick/sandbox";
198
+
199
+ export function myProvider(): SandboxProvider {
200
+ return {
201
+ name: "my-provider",
202
+ async create(options: SandboxCreateOptions): Promise<SandboxHandle> {
203
+ // Set up sandbox environment...
204
+ return {
205
+ id: crypto.randomUUID(),
206
+ workspacePath: "/sandbox/workspace",
207
+ async exec(command, opts) {
208
+ /* ... */
209
+ },
210
+ async readFile(path) {
211
+ /* ... */
212
+ },
213
+ async writeFile(path, content) {
214
+ /* ... */
215
+ },
216
+ async editFile(path, edits) {
217
+ const source = await this.readFile(path);
218
+ const result = applyEdits(source, edits);
219
+ if (result.applied > 0) await this.writeFile(path, result.content);
220
+ return result;
221
+ },
222
+ async destroy() {
223
+ /* ... */
224
+ },
225
+ };
226
+ },
227
+ };
228
+ }
229
+ ```
230
+
231
+ ## Testing
232
+
233
+ Import test utilities from `@agentick/sandbox/testing`:
234
+
235
+ ```typescript
236
+ import { createMockSandbox, createMockProvider } from "@agentick/sandbox/testing";
237
+
238
+ const sandbox = createMockSandbox({
239
+ exec: vi.fn().mockResolvedValue({ stdout: "hello", stderr: "", exitCode: 0 }),
240
+ });
241
+
242
+ const provider = createMockProvider({
243
+ create: vi.fn().mockResolvedValue(sandbox),
244
+ });
245
+ ```
246
+
247
+ Both return objects with `vi.fn()` stubs and sensible defaults. Override any method via the options parameter.
248
+
249
+ ## License
250
+
251
+ MIT
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Sandbox Component
3
+ *
4
+ * JSX component that creates and provides a Sandbox instance to its children.
5
+ * Uses useData for async initialization and useOnUnmount for cleanup.
6
+ */
7
+ import type React from "react";
8
+ import type { SandboxProvider, Mount, Permissions, ResourceLimits, Sandbox as SandboxHandle } from "./types";
9
+ export interface SandboxProps {
10
+ /** The sandbox provider to use (e.g. localProvider()). */
11
+ provider: SandboxProvider;
12
+ /** Workspace path, or true for auto temp directory. Default: true. */
13
+ workspace?: string | true;
14
+ /** Host↔sandbox path mappings. */
15
+ mounts?: Mount[];
16
+ /** Advisory permissions. */
17
+ allow?: Permissions;
18
+ /** Environment variables. Functions are resolved at creation time. */
19
+ env?: Record<string, string | (() => string)>;
20
+ /** Post-creation setup callback. */
21
+ setup?: (sandbox: SandboxHandle) => Promise<void>;
22
+ /** Resource constraints. */
23
+ limits?: ResourceLimits;
24
+ /** Whether to persist sandbox state in snapshots. Default: false. */
25
+ persist?: boolean;
26
+ children: React.ReactNode;
27
+ }
28
+ /**
29
+ * Creates a sandbox instance and provides it to children via context.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * <Sandbox provider={localProvider()}>
34
+ * <Shell />
35
+ * <ReadFile />
36
+ * <WriteFile />
37
+ * <EditFile />
38
+ * <MyAgent />
39
+ * </Sandbox>
40
+ * ```
41
+ */
42
+ export declare function Sandbox({ provider, workspace, mounts, allow, env, setup, limits, children, }: SandboxProps): React.ReactElement;
43
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EACV,eAAe,EAEf,KAAK,EACL,WAAW,EACX,cAAc,EACd,OAAO,IAAI,aAAa,EACzB,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,YAAY;IAC3B,0DAA0D;IAC1D,QAAQ,EAAE,eAAe,CAAC;IAE1B,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B,kCAAkC;IAClC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IAEjB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,WAAW,CAAC;IAEpB,sEAAsE;IACtE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC;IAE9C,oCAAoC;IACpC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD,4BAA4B;IAC5B,MAAM,CAAC,EAAE,cAAc,CAAC;IAExB,qEAAqE;IACrE,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,EACtB,QAAQ,EACR,SAAgB,EAChB,MAAM,EACN,KAAK,EACL,GAAG,EACH,KAAK,EACL,MAAM,EACN,QAAQ,GACT,EAAE,YAAY,GAAG,KAAK,CAAC,YAAY,CA2BnC"}
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useData, useOnUnmount } from "@agentick/core";
3
+ import { SandboxContext } from "./context";
4
+ /**
5
+ * Creates a sandbox instance and provides it to children via context.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * <Sandbox provider={localProvider()}>
10
+ * <Shell />
11
+ * <ReadFile />
12
+ * <WriteFile />
13
+ * <EditFile />
14
+ * <MyAgent />
15
+ * </Sandbox>
16
+ * ```
17
+ */
18
+ export function Sandbox({ provider, workspace = true, mounts, allow, env, setup, limits, children, }) {
19
+ // Resolve env functions to plain strings
20
+ const resolvedEnv = env
21
+ ? Object.fromEntries(Object.entries(env).map(([k, v]) => [k, typeof v === "function" ? v() : v]))
22
+ : undefined;
23
+ const options = {
24
+ workspace,
25
+ mounts,
26
+ permissions: allow,
27
+ env: resolvedEnv,
28
+ limits,
29
+ };
30
+ const sandbox = useData("sandbox", async () => {
31
+ const sb = await provider.create(options);
32
+ if (setup)
33
+ await setup(sb);
34
+ return sb;
35
+ });
36
+ useOnUnmount(() => {
37
+ sandbox.destroy();
38
+ });
39
+ return _jsx(SandboxContext.Provider, { value: sandbox, children: children });
40
+ }
41
+ //# sourceMappingURL=component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.tsx"],"names":[],"mappings":";AAQA,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAsC3C;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,OAAO,CAAC,EACtB,QAAQ,EACR,SAAS,GAAG,IAAI,EAChB,MAAM,EACN,KAAK,EACL,GAAG,EACH,KAAK,EACL,MAAM,EACN,QAAQ,GACK;IACb,yCAAyC;IACzC,MAAM,WAAW,GAAG,GAAG;QACrB,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC5E;QACH,CAAC,CAAC,SAAS,CAAC;IAEd,MAAM,OAAO,GAAyB;QACpC,SAAS;QACT,MAAM;QACN,WAAW,EAAE,KAAK;QAClB,GAAG,EAAE,WAAW;QAChB,MAAM;KACP,CAAC;IAEF,MAAM,OAAO,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,KAAK;YAAE,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,YAAY,CAAC,GAAG,EAAE;QAChB,OAAO,CAAC,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,OAAO,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,OAAO,YAAG,QAAQ,GAA2B,CAAC;AACvF,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Sandbox Context
3
+ *
4
+ * React context and hook for accessing the nearest Sandbox in the component tree.
5
+ */
6
+ import type { Sandbox } from "./types";
7
+ export declare const SandboxContext: import("react").Context<Sandbox | null>;
8
+ /**
9
+ * Access the nearest Sandbox from the component tree.
10
+ *
11
+ * @throws Error if no `<Sandbox>` provider is found in the tree.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const Shell = createTool({
16
+ * name: 'shell',
17
+ * use: () => ({ sandbox: useSandbox() }),
18
+ * handler: async ({ command }, deps) => {
19
+ * const result = await deps!.sandbox.exec(command);
20
+ * return [{ type: 'text', text: result.stdout }];
21
+ * },
22
+ * });
23
+ * ```
24
+ */
25
+ export declare function useSandbox(): Sandbox;
26
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,eAAO,MAAM,cAAc,yCAAsC,CAAC;AAElE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAQpC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Sandbox Context
3
+ *
4
+ * React context and hook for accessing the nearest Sandbox in the component tree.
5
+ */
6
+ import { createContext, useContext } from "react";
7
+ export const SandboxContext = createContext(null);
8
+ /**
9
+ * Access the nearest Sandbox from the component tree.
10
+ *
11
+ * @throws Error if no `<Sandbox>` provider is found in the tree.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const Shell = createTool({
16
+ * name: 'shell',
17
+ * use: () => ({ sandbox: useSandbox() }),
18
+ * handler: async ({ command }, deps) => {
19
+ * const result = await deps!.sandbox.exec(command);
20
+ * return [{ type: 'text', text: result.stdout }];
21
+ * },
22
+ * });
23
+ * ```
24
+ */
25
+ export function useSandbox() {
26
+ const sandbox = useContext(SandboxContext);
27
+ if (!sandbox) {
28
+ throw new Error("useSandbox(): No sandbox found. Wrap your component tree with <Sandbox provider={...}>.");
29
+ }
30
+ return sandbox;
31
+ }
32
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAGlD,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAiB,IAAI,CAAC,CAAC;AAElE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,OAAO,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/edit.d.ts ADDED
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Surgical Code Editing
3
+ *
4
+ * LLM-driven code editing with layered matching that recovers from
5
+ * trailing whitespace, indentation mismatch, and CRLF/LF differences.
6
+ *
7
+ * Pure transform (`applyEdits`) + file wrapper (`editFile`) with atomic writes.
8
+ */
9
+ export interface Edit {
10
+ /** Exact string to find in the source. */
11
+ old: string;
12
+ /** Replacement string. Empty string deletes the match. */
13
+ new: string;
14
+ /** Replace ALL occurrences. Default false — requires unique match. */
15
+ all?: boolean;
16
+ }
17
+ export interface EditChange {
18
+ /** 1-based line where the change starts. */
19
+ line: number;
20
+ /** Lines removed. */
21
+ removed: number;
22
+ /** Lines added. */
23
+ added: number;
24
+ }
25
+ export interface EditResult {
26
+ /** Resulting content after edits. */
27
+ content: string;
28
+ /** Total number of replacements applied. */
29
+ applied: number;
30
+ /** Per-replacement details in document order. */
31
+ changes: EditChange[];
32
+ }
33
+ export declare class EditError extends Error {
34
+ readonly editIndex: number;
35
+ readonly detail?: {
36
+ closest?: string;
37
+ line?: number;
38
+ } | undefined;
39
+ constructor(message: string, editIndex: number, detail?: {
40
+ closest?: string;
41
+ line?: number;
42
+ } | undefined);
43
+ }
44
+ /**
45
+ * Apply edits to a source string. Pure function, no I/O.
46
+ *
47
+ * Matching strategy per edit (in order):
48
+ * 1. Exact byte match
49
+ * 2. Line-normalized (trailing whitespace stripped)
50
+ * 3. Indent-adjusted (leading whitespace baseline stripped, new indentation adjusted)
51
+ *
52
+ * Multi-edit: all matches resolved against original source,
53
+ * validated for overlap, applied bottom-to-top.
54
+ *
55
+ * @throws EditError on match failure or overlapping edits
56
+ */
57
+ export declare function applyEdits(source: string, edits: Edit[]): EditResult;
58
+ /**
59
+ * Edit a file on disk. Reads, applies edits, writes atomically (temp + rename).
60
+ */
61
+ export declare function editFile(path: string, edits: Edit[]): Promise<EditResult>;
62
+ //# sourceMappingURL=edit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../src/edit.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,MAAM,WAAW,IAAI;IACnB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED,qBAAa,SAAU,SAAQ,KAAK;aAGhB,SAAS,EAAE,MAAM;aACjB,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;gBAF5D,OAAO,EAAE,MAAM,EACC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,YAAA;CAK/D;AAyHD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,UAAU,CAsJpE;AAID;;GAEG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAmB/E"}