experimental-agent 0.2.1 → 0.3.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 (71) hide show
  1. package/README.md +55 -254
  2. package/dist/adapter-BigchkkI.d.mts +201 -0
  3. package/dist/adapter-BigchkkI.d.ts +201 -0
  4. package/dist/chunk-BFFNCESS.mjs +302 -0
  5. package/dist/chunk-C4VSUEY2.mjs +72 -0
  6. package/dist/chunk-DOD4MC5D.mjs +196 -0
  7. package/dist/chunk-ELWIUJUK.mjs +96 -0
  8. package/dist/chunk-GKASMIBR.mjs +50 -0
  9. package/dist/chunk-JO3JDCH5.mjs +107 -0
  10. package/dist/chunk-MSWINCCM.mjs +128 -0
  11. package/dist/chunk-RT72C52I.mjs +324 -0
  12. package/dist/chunk-ZUFJJYC4.mjs +150 -0
  13. package/dist/{handler-FRUPZ4LX.mjs → docker-QPCLWLYR.mjs} +3 -4
  14. package/dist/entry-BmQ8FO-5.d.ts +36 -0
  15. package/dist/entry-CZd9aAwn.d.mts +36 -0
  16. package/dist/index.d.mts +415 -18
  17. package/dist/index.d.ts +415 -18
  18. package/dist/index.js +3036 -5494
  19. package/dist/index.mjs +3264 -1142
  20. package/dist/lifecycle-workflow-steps.d.mts +5 -0
  21. package/dist/lifecycle-workflow-steps.d.ts +5 -0
  22. package/dist/lifecycle-workflow-steps.js +263 -0
  23. package/dist/lifecycle-workflow-steps.mjs +9 -0
  24. package/dist/lifecycle-workflow.d.mts +6 -6
  25. package/dist/lifecycle-workflow.d.ts +6 -6
  26. package/dist/lifecycle-workflow.js +192 -905
  27. package/dist/lifecycle-workflow.mjs +3 -1
  28. package/dist/local-KJ3BSIFJ.mjs +8 -0
  29. package/dist/next/loader.d.mts +1 -0
  30. package/dist/next/loader.d.ts +1 -0
  31. package/dist/next/loader.js +44 -18
  32. package/dist/next/loader.mjs +18 -13
  33. package/dist/next.js +32 -9
  34. package/dist/next.mjs +6 -4
  35. package/dist/{process-manager-JDUJDYGU.mjs → process-manager-WQHAIVRB.mjs} +1 -1
  36. package/dist/sandbox.d.mts +6 -0
  37. package/dist/sandbox.d.ts +6 -0
  38. package/dist/sandbox.js +1070 -0
  39. package/dist/sandbox.mjs +19 -0
  40. package/dist/steps-BnkRQKlc.d.ts +173 -0
  41. package/dist/steps-u-mGDbP_.d.mts +173 -0
  42. package/dist/storage.d.mts +11 -0
  43. package/dist/storage.d.ts +11 -0
  44. package/dist/storage.js +234 -0
  45. package/dist/storage.mjs +12 -0
  46. package/dist/vercel-QZ6INPMV.mjs +11 -0
  47. package/package.json +26 -5
  48. package/dist/agent-workflow.d.mts +0 -30
  49. package/dist/agent-workflow.d.ts +0 -30
  50. package/dist/agent-workflow.js +0 -5433
  51. package/dist/agent-workflow.mjs +0 -14
  52. package/dist/chunk-AML2VCQS.mjs +0 -1287
  53. package/dist/chunk-FQ67QZOI.mjs +0 -75
  54. package/dist/chunk-NO7RHGTH.mjs +0 -2367
  55. package/dist/chunk-NXDVNJRS.mjs +0 -106
  56. package/dist/chunk-OZZVS6L5.mjs +0 -139
  57. package/dist/chunk-QRWGDFFY.mjs +0 -75
  58. package/dist/chunk-SJVFFE5D.mjs +0 -402
  59. package/dist/chunk-TAXLUVIC.mjs +0 -1
  60. package/dist/chunk-TGNVXSMX.mjs +0 -399
  61. package/dist/chunk-YRYXN7W4.mjs +0 -48
  62. package/dist/chunk-ZIAHPXOJ.mjs +0 -595
  63. package/dist/client-BKA7XBGW.mjs +0 -15
  64. package/dist/client-CEeSFGva.d.mts +0 -2376
  65. package/dist/client-CEeSFGva.d.ts +0 -2376
  66. package/dist/docker-FB2MJTHJ.mjs +0 -12
  67. package/dist/local-fs-handlers-SYOCKTPN.mjs +0 -447
  68. package/dist/sandbox-UENKQV3T.mjs +0 -21
  69. package/dist/storage-LSDMRW73.mjs +0 -20
  70. package/dist/vercel-SD3JTECG.mjs +0 -20
  71. package/dist/vercel-sdk-I6A4MVAN.mjs +0 -8
@@ -0,0 +1,201 @@
1
+ import { WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from '@workflow/serde';
2
+ import { NetworkPolicy } from '@vercel/sandbox';
3
+ import { UIMessage } from 'ai';
4
+
5
+ type Session = {
6
+ id: string;
7
+ createdAt: number;
8
+ updatedAt: number;
9
+ model: string | null;
10
+ system: string | null;
11
+ sandboxId: string | null;
12
+ lastMessageId: string | null;
13
+ activeTools: string[] | null;
14
+ skillsDir: string[] | null;
15
+ generation: {
16
+ maxSteps?: number;
17
+ temperature?: number;
18
+ topK?: number;
19
+ topP?: number;
20
+ frequencyPenalty?: number;
21
+ presencePenalty?: number;
22
+ maxOutputTokens?: number;
23
+ headers?: Record<string, string>;
24
+ } | null;
25
+ };
26
+ type Message = {
27
+ id: string;
28
+ sessionId: string;
29
+ role: "user" | "assistant" | "system";
30
+ createdAt: number;
31
+ startedAt: number | null;
32
+ completedAt: number | null;
33
+ interruptedAt: number | null;
34
+ interruptedLastPart: {
35
+ index: number;
36
+ part: unknown;
37
+ } | null;
38
+ usage: {
39
+ steps: {
40
+ stepIndex: number;
41
+ model: string;
42
+ inputTokens: number;
43
+ outputTokens: number;
44
+ totalTokens: number;
45
+ cacheReadTokens: number;
46
+ cacheWriteTokens: number;
47
+ reasoningTokens: number;
48
+ }[];
49
+ summary: {
50
+ model: string;
51
+ inputTokens: number;
52
+ outputTokens: number;
53
+ totalTokens: number;
54
+ cacheReadTokens: number;
55
+ cacheWriteTokens: number;
56
+ reasoningTokens: number;
57
+ stepCount: number;
58
+ };
59
+ } | null;
60
+ workflowRunId?: string | null;
61
+ };
62
+ type Part = {
63
+ id: string;
64
+ messageId: string;
65
+ sessionId: string;
66
+ index: number;
67
+ part: UIMessage["parts"][number];
68
+ };
69
+ type Sandbox = {
70
+ id: string;
71
+ setup: {
72
+ binding: string;
73
+ version: string | null;
74
+ completedAt: number | null;
75
+ metadata: Record<string, unknown> | null;
76
+ networkPolicy: NetworkPolicy | null;
77
+ };
78
+ createdAt: number | null;
79
+ lastActiveAt: number | null;
80
+ };
81
+ type Setup = {
82
+ version: string;
83
+ snapshotId: string | null;
84
+ createdAt: number;
85
+ lastUsedAt: number | null;
86
+ };
87
+ type SetupSnapshot = Setup;
88
+
89
+ type StorageHandlers = {
90
+ "session.get"(p: {
91
+ id: string;
92
+ }): Promise<Session | null>;
93
+ "session.set"(p: {
94
+ id: string;
95
+ value: Session;
96
+ }): Promise<void>;
97
+ "session.update"(p: {
98
+ id: string;
99
+ updates: Partial<Session>;
100
+ }): Promise<Session>;
101
+ "message.get"(p: {
102
+ id: string;
103
+ }): Promise<Message | null>;
104
+ "message.set"(p: {
105
+ id: string;
106
+ value: Message;
107
+ }): Promise<void>;
108
+ "message.update"(p: {
109
+ id: string;
110
+ updates: Partial<Message>;
111
+ }): Promise<Message>;
112
+ "message.listBySession"(p: {
113
+ sessionId: string;
114
+ }): Promise<Message[]>;
115
+ "part.get"(p: {
116
+ id: string;
117
+ }): Promise<Part | null>;
118
+ "part.set"(p: {
119
+ id: string;
120
+ value: Part;
121
+ }): Promise<void>;
122
+ "part.listBySession"(p: {
123
+ sessionId: string;
124
+ }): Promise<Part[]>;
125
+ "sandbox.get"(p: {
126
+ id: string;
127
+ }): Promise<Sandbox | null>;
128
+ "sandbox.set"(p: {
129
+ id: string;
130
+ value: Sandbox;
131
+ }): Promise<void>;
132
+ "sandbox.update"(p: {
133
+ id: string;
134
+ updates: Partial<Sandbox>;
135
+ }): Promise<Sandbox>;
136
+ "setup.get"(p: {
137
+ id: string;
138
+ }): Promise<Setup | null>;
139
+ "setup.set"(p: {
140
+ id: string;
141
+ value: Setup;
142
+ }): Promise<void>;
143
+ };
144
+ type StorageCall = {
145
+ [K in keyof StorageHandlers]: {
146
+ method: K;
147
+ } & Parameters<StorageHandlers[K]>[0];
148
+ }[keyof StorageHandlers];
149
+ declare class StorageStep {
150
+ event: StorageCall;
151
+ constructor(event: StorageCall);
152
+ static [WORKFLOW_SERIALIZE](instance: StorageStep): {
153
+ event: StorageCall;
154
+ };
155
+ static [WORKFLOW_DESERIALIZE](data: {
156
+ event: StorageCall;
157
+ }): StorageStep;
158
+ on(handlers: StorageHandlers): Promise<any>;
159
+ }
160
+ /**
161
+ * A single function that handles all storage operations. Intended to be
162
+ * marked with `"use step"` so that its body (and Node.js-dependent
163
+ * imports like database clients) is extracted by the workflow bundler
164
+ * and runs server-side.
165
+ *
166
+ * The step receives a `StorageStep` instance (serializable via
167
+ * `@workflow/serde`) and should call `step.handle({ ... })` with a
168
+ * `StorageHandlers` map.
169
+ */
170
+ type StorageStepFunction = (store: StorageStep) => Promise<any>;
171
+ interface Storage {
172
+ session: {
173
+ get(key: string): Promise<Session | null>;
174
+ set(key: string, value: Session): Promise<void>;
175
+ update(key: string, updates: Partial<Session>): Promise<Session>;
176
+ };
177
+ message: {
178
+ get(key: string): Promise<Message | null>;
179
+ set(key: string, value: Message): Promise<void>;
180
+ update(key: string, updates: Partial<Message>): Promise<Message>;
181
+ listBySession(sessionId: string): Promise<Message[]>;
182
+ };
183
+ part: {
184
+ get(key: string): Promise<Part | null>;
185
+ set(key: string, value: Part): Promise<void>;
186
+ listBySession(sessionId: string): Promise<Part[]>;
187
+ };
188
+ sandbox: {
189
+ get(key: string): Promise<Sandbox | null>;
190
+ set(key: string, value: Sandbox): Promise<void>;
191
+ update(key: string, updates: Partial<Sandbox>): Promise<Sandbox>;
192
+ };
193
+ setup: {
194
+ get(key: string): Promise<Setup | null>;
195
+ set(key: string, value: Setup): Promise<void>;
196
+ };
197
+ }
198
+ type StorageInput = StorageHandlers | StorageStepFunction;
199
+ declare function toStorage(h: StorageInput): Storage;
200
+
201
+ export { type Message as M, type Part as P, type StorageHandlers as S, type Sandbox as a, type Session as b, type Setup as c, type SetupSnapshot as d, type Storage as e, type StorageCall as f, StorageStep as g, type StorageStepFunction as h, type StorageInput as i, toStorage as t };
@@ -0,0 +1,302 @@
1
+ // src/sandbox/bindings/docker.ts
2
+ import { ulid } from "ulid";
3
+ async function execDocker(args, opts) {
4
+ const { spawn } = await import("child_process");
5
+ return new Promise((resolve, reject) => {
6
+ const child = spawn("docker", ["sandbox", ...args], {
7
+ signal: opts?.signal
8
+ });
9
+ let stdout = "";
10
+ let stderr = "";
11
+ child.stdout.on("data", (data) => {
12
+ stdout += data.toString();
13
+ });
14
+ child.stderr.on("data", (data) => {
15
+ stderr += data.toString();
16
+ });
17
+ const timeoutId = opts?.timeoutMs ? setTimeout(() => {
18
+ child.kill("SIGTERM");
19
+ reject(new Error(`docker sandbox ${args[0]} timed out`));
20
+ }, opts.timeoutMs) : void 0;
21
+ child.on("error", (err) => {
22
+ if (timeoutId) {
23
+ clearTimeout(timeoutId);
24
+ }
25
+ reject(err);
26
+ });
27
+ child.on("close", (code) => {
28
+ if (timeoutId) {
29
+ clearTimeout(timeoutId);
30
+ }
31
+ resolve({ stdout, stderr, exitCode: code ?? 0 });
32
+ });
33
+ });
34
+ }
35
+ var ensurePromises = /* @__PURE__ */ new Map();
36
+ var activeSandboxes = /* @__PURE__ */ new Set();
37
+ var cleanupRegistered = false;
38
+ var _execSync = null;
39
+ async function registerCleanup() {
40
+ if (cleanupRegistered) {
41
+ return;
42
+ }
43
+ cleanupRegistered = true;
44
+ const cp = await import("child_process");
45
+ _execSync = cp.execSync;
46
+ const cleanup = () => {
47
+ if (!_execSync) {
48
+ return;
49
+ }
50
+ for (const name of Array.from(activeSandboxes)) {
51
+ try {
52
+ _execSync(`docker sandbox stop ${name}`, {
53
+ timeout: 1e4,
54
+ stdio: "pipe"
55
+ });
56
+ } catch {
57
+ }
58
+ }
59
+ };
60
+ process.on("exit", cleanup);
61
+ process.on("SIGINT", () => {
62
+ cleanup();
63
+ process.exit(130);
64
+ });
65
+ process.on("SIGTERM", () => {
66
+ cleanup();
67
+ process.exit(143);
68
+ });
69
+ }
70
+ async function ensureSandbox(sandboxName) {
71
+ const existing = ensurePromises.get(sandboxName);
72
+ if (existing) {
73
+ return existing;
74
+ }
75
+ const promise = (async () => {
76
+ const ls = await execDocker(["ls", "-q"], { timeoutMs: 1e4 });
77
+ const existingNames = ls.exitCode === 0 ? ls.stdout.split("\n").map((s) => s.trim()).filter(Boolean) : [];
78
+ if (existingNames.includes(sandboxName)) {
79
+ activeSandboxes.add(sandboxName);
80
+ registerCleanup();
81
+ return;
82
+ }
83
+ const path = await import("path");
84
+ const os = await import("os");
85
+ const fs = await import("fs/promises");
86
+ const workspaceDir = path.join(
87
+ os.tmpdir(),
88
+ "agent-docker-sandbox",
89
+ sandboxName
90
+ );
91
+ await fs.mkdir(workspaceDir, { recursive: true });
92
+ const create = await execDocker(
93
+ ["create", "--name", sandboxName, "shell", workspaceDir],
94
+ { timeoutMs: 6e4 }
95
+ );
96
+ if (create.exitCode !== 0) {
97
+ if (create.stderr.includes("already exists")) {
98
+ activeSandboxes.add(sandboxName);
99
+ registerCleanup();
100
+ return;
101
+ }
102
+ throw new Error(
103
+ `Failed to create docker sandbox "${sandboxName}": ${create.stderr}`
104
+ );
105
+ }
106
+ activeSandboxes.add(sandboxName);
107
+ registerCleanup();
108
+ })();
109
+ ensurePromises.set(sandboxName, promise);
110
+ try {
111
+ await promise;
112
+ } catch (e) {
113
+ ensurePromises.delete(sandboxName);
114
+ throw e;
115
+ }
116
+ }
117
+ var DEFAULT_DOCKER_CWD = "/home/agent/workspace";
118
+ var DockerSandboxInstance = class {
119
+ cwd;
120
+ sandboxName;
121
+ processes = /* @__PURE__ */ new Map();
122
+ constructor(sandboxName, cwd) {
123
+ this.sandboxName = sandboxName;
124
+ this.cwd = cwd ?? DEFAULT_DOCKER_CWD;
125
+ }
126
+ async exec(opts) {
127
+ await ensureSandbox(this.sandboxName);
128
+ const { spawn } = await import("child_process");
129
+ const commandId = `command_${ulid()}`;
130
+ const envFlags = opts.env ? Object.entries(opts.env).flatMap(([k, v]) => ["-e", `${k}=${v}`]) : [];
131
+ const cwdFlags = opts.cwd ? ["-w", opts.cwd] : [];
132
+ const baseCmd = opts.sudo ? ["sudo", opts.command, ...opts.args ?? []] : opts.args ? [opts.command, ...opts.args] : [opts.command];
133
+ const fullCmd = baseCmd;
134
+ const child = spawn(
135
+ "docker",
136
+ [
137
+ "sandbox",
138
+ "exec",
139
+ ...envFlags,
140
+ ...cwdFlags,
141
+ this.sandboxName,
142
+ ...fullCmd
143
+ ],
144
+ { signal: opts.signal }
145
+ );
146
+ this.processes.set(commandId, child);
147
+ let stdout = "";
148
+ let stderr = "";
149
+ const logQueue = [];
150
+ let logResolve = null;
151
+ let closed = false;
152
+ child.stdout.on("data", (data) => {
153
+ const str = String(data);
154
+ stdout += str;
155
+ logQueue.push({ stream: "stdout", data: str });
156
+ logResolve?.();
157
+ });
158
+ child.stderr.on("data", (data) => {
159
+ const str = String(data);
160
+ stderr += str;
161
+ logQueue.push({ stream: "stderr", data: str });
162
+ logResolve?.();
163
+ });
164
+ const result = new Promise((resolve, reject) => {
165
+ child.on("error", (err) => {
166
+ this.processes.delete(commandId);
167
+ closed = true;
168
+ logResolve?.();
169
+ reject(err);
170
+ });
171
+ child.on("close", (code) => {
172
+ this.processes.delete(commandId);
173
+ closed = true;
174
+ logResolve?.();
175
+ resolve({ stdout, stderr, exitCode: code ?? 0 });
176
+ });
177
+ });
178
+ async function* logs() {
179
+ while (!closed || logQueue.length > 0) {
180
+ const entry = logQueue.shift();
181
+ if (entry) {
182
+ yield entry;
183
+ } else if (!closed) {
184
+ await new Promise((r) => {
185
+ logResolve = r;
186
+ });
187
+ logResolve = null;
188
+ }
189
+ }
190
+ }
191
+ return { commandId, logs, result };
192
+ }
193
+ async readFile(opts) {
194
+ await ensureSandbox(this.sandboxName);
195
+ const result = await execDocker(
196
+ [
197
+ "exec",
198
+ this.sandboxName,
199
+ "bash",
200
+ "-c",
201
+ `base64 '${opts.path.replace(/'/g, "'\\''")}'`
202
+ ],
203
+ { timeoutMs: 3e4, signal: opts.signal }
204
+ );
205
+ if (result.exitCode !== 0) {
206
+ if (result.stderr.includes("No such file") || result.stderr.includes("ENOENT")) {
207
+ return null;
208
+ }
209
+ throw new Error(`readFile failed: ${result.stderr}`);
210
+ }
211
+ return Buffer.from(result.stdout.trim(), "base64");
212
+ }
213
+ async writeFiles(opts) {
214
+ await ensureSandbox(this.sandboxName);
215
+ for (const file of opts.files) {
216
+ const fullPath = opts.destPath ? `${opts.destPath}/${file.path}` : file.path;
217
+ const parentDir = fullPath.substring(0, fullPath.lastIndexOf("/"));
218
+ if (parentDir) {
219
+ await execDocker(["exec", this.sandboxName, "mkdir", "-p", parentDir], {
220
+ signal: opts.signal
221
+ });
222
+ }
223
+ const b64 = typeof file.content === "string" ? Buffer.from(file.content).toString("base64") : file.content.toString("base64");
224
+ await execDocker(
225
+ [
226
+ "exec",
227
+ this.sandboxName,
228
+ "bash",
229
+ "-c",
230
+ `echo '${b64}' | base64 -d > '${fullPath.replace(/'/g, "'\\''")}'`
231
+ ],
232
+ { signal: opts.signal }
233
+ );
234
+ if (file.path.endsWith(".sh")) {
235
+ await execDocker(["exec", this.sandboxName, "chmod", "+x", fullPath], {
236
+ signal: opts.signal
237
+ });
238
+ }
239
+ }
240
+ }
241
+ // biome-ignore lint/suspicious/useAwait: .
242
+ async getDomain(opts) {
243
+ return `http://localhost:${opts.port}`;
244
+ }
245
+ // biome-ignore lint/suspicious/useAwait: .
246
+ async kill(opts) {
247
+ const child = this.processes.get(opts.commandId);
248
+ if (child) {
249
+ child.kill("SIGTERM");
250
+ this.processes.delete(opts.commandId);
251
+ }
252
+ }
253
+ // biome-ignore lint/suspicious/useAwait: .
254
+ async getStatus() {
255
+ return "running";
256
+ }
257
+ async start() {
258
+ await ensureSandbox(this.sandboxName);
259
+ }
260
+ async stop() {
261
+ await execDocker(["stop", this.sandboxName], { timeoutMs: 3e4 });
262
+ activeSandboxes.delete(this.sandboxName);
263
+ ensurePromises.delete(this.sandboxName);
264
+ }
265
+ // biome-ignore lint/suspicious/useAwait: .
266
+ async snapshot() {
267
+ throw new Error("snapshot is not supported for docker sandboxes");
268
+ }
269
+ // biome-ignore lint/suspicious/useAwait: .
270
+ async updateNetworkPolicy() {
271
+ throw new Error(
272
+ "updateNetworkPolicy is not supported for docker sandboxes"
273
+ );
274
+ }
275
+ };
276
+ function dockerSandbox() {
277
+ return {
278
+ type: "docker",
279
+ async create(opts) {
280
+ const sandboxName = `agent-${ulid()}`;
281
+ const cwd = opts.setup?.config?.cwd;
282
+ await ensureSandbox(sandboxName);
283
+ const instance = new DockerSandboxInstance(sandboxName, cwd);
284
+ if (opts.setup?.run) {
285
+ await opts.setup.run(instance);
286
+ }
287
+ return {
288
+ instance,
289
+ metadata: { sandboxName }
290
+ };
291
+ },
292
+ // biome-ignore lint/suspicious/useAwait: .
293
+ async connect(opts) {
294
+ return new DockerSandboxInstance(opts.metadata.sandboxName);
295
+ }
296
+ };
297
+ }
298
+
299
+ export {
300
+ dockerSandbox
301
+ };
302
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NhbmRib3gvYmluZGluZ3MvZG9ja2VyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyB1bGlkIH0gZnJvbSBcInVsaWRcIjtcbmltcG9ydCB0eXBlIHsgRXhlY1Jlc3VsdCwgU2FuZGJveEJpbmRpbmcsIFNhbmRib3hJbnN0YW5jZSB9IGZyb20gXCIuLi9hZGFwdGVyXCI7XG5cbmV4cG9ydCB0eXBlIERvY2tlckJpbmRpbmdDb25maWcgPSB7XG4gIGN3ZD86IHN0cmluZztcbn07XG5cbmV4cG9ydCB0eXBlIERvY2tlckJpbmRpbmdNZXRhZGF0YSA9IHtcbiAgc2FuZGJveE5hbWU6IHN0cmluZztcbn07XG5cbi8qKlxuICogUnVuIGEgYGRvY2tlciBzYW5kYm94YCBDTEkgY29tbWFuZCBhbmQgcmV0dXJuIGl0cyBvdXRwdXQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGV4ZWNEb2NrZXIoXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBvcHRzPzogeyB0aW1lb3V0TXM/OiBudW1iZXI7IHNpZ25hbD86IEFib3J0U2lnbmFsIH1cbik6IFByb21pc2U8eyBzdGRvdXQ6IHN0cmluZzsgc3RkZXJyOiBzdHJpbmc7IGV4aXRDb2RlOiBudW1iZXIgfT4ge1xuICBjb25zdCB7IHNwYXduIH0gPSBhd2FpdCBpbXBvcnQoXCJub2RlOmNoaWxkX3Byb2Nlc3NcIik7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgY2hpbGQgPSBzcGF3bihcImRvY2tlclwiLCBbXCJzYW5kYm94XCIsIC4uLmFyZ3NdLCB7XG4gICAgICBzaWduYWw6IG9wdHM/LnNpZ25hbCxcbiAgICB9KTtcblxuICAgIGxldCBzdGRvdXQgPSBcIlwiO1xuICAgIGxldCBzdGRlcnIgPSBcIlwiO1xuXG4gICAgY2hpbGQuc3Rkb3V0Lm9uKFwiZGF0YVwiLCAoZGF0YTogQnVmZmVyKSA9PiB7XG4gICAgICBzdGRvdXQgKz0gZGF0YS50b1N0cmluZygpO1xuICAgIH0pO1xuICAgIGNoaWxkLnN0ZGVyci5vbihcImRhdGFcIiwgKGRhdGE6IEJ1ZmZlcikgPT4ge1xuICAgICAgc3RkZXJyICs9IGRhdGEudG9TdHJpbmcoKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHRpbWVvdXRJZCA9IG9wdHM/LnRpbWVvdXRNc1xuICAgICAgPyBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBjaGlsZC5raWxsKFwiU0lHVEVSTVwiKTtcbiAgICAgICAgICByZWplY3QobmV3IEVycm9yKGBkb2NrZXIgc2FuZGJveCAke2FyZ3NbMF19IHRpbWVkIG91dGApKTtcbiAgICAgICAgfSwgb3B0cy50aW1lb3V0TXMpXG4gICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgaWYgKHRpbWVvdXRJZCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgIH1cbiAgICAgIHJlamVjdChlcnIpO1xuICAgIH0pO1xuXG4gICAgY2hpbGQub24oXCJjbG9zZVwiLCAoY29kZSkgPT4ge1xuICAgICAgaWYgKHRpbWVvdXRJZCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgIH1cbiAgICAgIHJlc29sdmUoeyBzdGRvdXQsIHN0ZGVyciwgZXhpdENvZGU6IGNvZGUgPz8gMCB9KTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbi8qKlxuICogVHJhY2sgd2hpY2ggc2FuZGJveGVzIGhhdmUgYmVlbiB2ZXJpZmllZCB0byBleGlzdCBpbiB0aGlzIHByb2Nlc3MuXG4gKiBNYXBzIHNhbmRib3ggbmFtZSAtPiBQcm9taXNlIHNvIGNvbmN1cnJlbnQgY2FsbGVycyB3YWl0IG9uIHRoZSBzYW1lIGNoZWNrLlxuICovXG5jb25zdCBlbnN1cmVQcm9taXNlcyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPHZvaWQ+PigpO1xuXG4vKipcbiAqIFNhbmRib3hlcyB0aGF0IHRoaXMgcHJvY2VzcyBoYXMgdXNlZC4gU3RvcHBlZCBvbiBwcm9jZXNzIGV4aXQuXG4gKi9cbmNvbnN0IGFjdGl2ZVNhbmRib3hlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG5sZXQgY2xlYW51cFJlZ2lzdGVyZWQgPSBmYWxzZTtcbmxldCBfZXhlY1N5bmM6IHR5cGVvZiBpbXBvcnQoXCJub2RlOmNoaWxkX3Byb2Nlc3NcIikuZXhlY1N5bmMgfCBudWxsID0gbnVsbDtcblxuYXN5bmMgZnVuY3Rpb24gcmVnaXN0ZXJDbGVhbnVwKCkge1xuICBpZiAoY2xlYW51cFJlZ2lzdGVyZWQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY2xlYW51cFJlZ2lzdGVyZWQgPSB0cnVlO1xuXG4gIC8vIFByZS1sb2FkIGV4ZWNTeW5jIHNvIHRoZSBzeW5jaHJvbm91cyBleGl0IGhhbmRsZXIgY2FuIHVzZSBpdC5cbiAgY29uc3QgY3AgPSBhd2FpdCBpbXBvcnQoXCJub2RlOmNoaWxkX3Byb2Nlc3NcIik7XG4gIF9leGVjU3luYyA9IGNwLmV4ZWNTeW5jO1xuXG4gIGNvbnN0IGNsZWFudXAgPSAoKSA9PiB7XG4gICAgaWYgKCFfZXhlY1N5bmMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCBuYW1lIG9mIEFycmF5LmZyb20oYWN0aXZlU2FuZGJveGVzKSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgX2V4ZWNTeW5jKGBkb2NrZXIgc2FuZGJveCBzdG9wICR7bmFtZX1gLCB7XG4gICAgICAgICAgdGltZW91dDogMTBfMDAwLFxuICAgICAgICAgIHN0ZGlvOiBcInBpcGVcIixcbiAgICAgICAgfSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gQmVzdC1lZmZvcnQgXHUyMDE0IHNhbmRib3ggbWF5IGFscmVhZHkgYmUgc3RvcHBlZFxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBwcm9jZXNzLm9uKFwiZXhpdFwiLCBjbGVhbnVwKTtcbiAgcHJvY2Vzcy5vbihcIlNJR0lOVFwiLCAoKSA9PiB7XG4gICAgY2xlYW51cCgpO1xuICAgIHByb2Nlc3MuZXhpdCgxMzApO1xuICB9KTtcbiAgcHJvY2Vzcy5vbihcIlNJR1RFUk1cIiwgKCkgPT4ge1xuICAgIGNsZWFudXAoKTtcbiAgICBwcm9jZXNzLmV4aXQoMTQzKTtcbiAgfSk7XG59XG5cbi8qKlxuICogRW5zdXJlIGEgRG9ja2VyIHNhbmRib3ggZXhpc3RzIGZvciB0aGUgZ2l2ZW4gbmFtZS5cbiAqIElmIGl0IGFscmVhZHkgZXhpc3RzIChmcm9tIGEgcHJldmlvdXMgcHJvY2VzcyksIHJldXNlcyBpdC5cbiAqIElmIGl0IGRvZXNuJ3QgZXhpc3QsIGNyZWF0ZXMgaXQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGVuc3VyZVNhbmRib3goc2FuZGJveE5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBleGlzdGluZyA9IGVuc3VyZVByb21pc2VzLmdldChzYW5kYm94TmFtZSk7XG4gIGlmIChleGlzdGluZykge1xuICAgIHJldHVybiBleGlzdGluZztcbiAgfVxuXG4gIGNvbnN0IHByb21pc2UgPSAoYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGxzID0gYXdhaXQgZXhlY0RvY2tlcihbXCJsc1wiLCBcIi1xXCJdLCB7IHRpbWVvdXRNczogMTBfMDAwIH0pO1xuICAgIGNvbnN0IGV4aXN0aW5nTmFtZXMgPVxuICAgICAgbHMuZXhpdENvZGUgPT09IDBcbiAgICAgICAgPyBscy5zdGRvdXRcbiAgICAgICAgICAgIC5zcGxpdChcIlxcblwiKVxuICAgICAgICAgICAgLm1hcCgocykgPT4gcy50cmltKCkpXG4gICAgICAgICAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgICAgIDogW107XG5cbiAgICBpZiAoZXhpc3RpbmdOYW1lcy5pbmNsdWRlcyhzYW5kYm94TmFtZSkpIHtcbiAgICAgIGFjdGl2ZVNhbmRib3hlcy5hZGQoc2FuZGJveE5hbWUpO1xuICAgICAgcmVnaXN0ZXJDbGVhbnVwKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcGF0aCA9IGF3YWl0IGltcG9ydChcIm5vZGU6cGF0aFwiKTtcbiAgICBjb25zdCBvcyA9IGF3YWl0IGltcG9ydChcIm5vZGU6b3NcIik7XG4gICAgY29uc3QgZnMgPSBhd2FpdCBpbXBvcnQoXCJub2RlOmZzL3Byb21pc2VzXCIpO1xuXG4gICAgY29uc3Qgd29ya3NwYWNlRGlyID0gcGF0aC5qb2luKFxuICAgICAgb3MudG1wZGlyKCksXG4gICAgICBcImFnZW50LWRvY2tlci1zYW5kYm94XCIsXG4gICAgICBzYW5kYm94TmFtZVxuICAgICk7XG4gICAgYXdhaXQgZnMubWtkaXIod29ya3NwYWNlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgIGNvbnN0IGNyZWF0ZSA9IGF3YWl0IGV4ZWNEb2NrZXIoXG4gICAgICBbXCJjcmVhdGVcIiwgXCItLW5hbWVcIiwgc2FuZGJveE5hbWUsIFwic2hlbGxcIiwgd29ya3NwYWNlRGlyXSxcbiAgICAgIHsgdGltZW91dE1zOiA2MF8wMDAgfVxuICAgICk7XG5cbiAgICBpZiAoY3JlYXRlLmV4aXRDb2RlICE9PSAwKSB7XG4gICAgICBpZiAoY3JlYXRlLnN0ZGVyci5pbmNsdWRlcyhcImFscmVhZHkgZXhpc3RzXCIpKSB7XG4gICAgICAgIGFjdGl2ZVNhbmRib3hlcy5hZGQoc2FuZGJveE5hbWUpO1xuICAgICAgICByZWdpc3RlckNsZWFudXAoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIGNyZWF0ZSBkb2NrZXIgc2FuZGJveCBcIiR7c2FuZGJveE5hbWV9XCI6ICR7Y3JlYXRlLnN0ZGVycn1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGFjdGl2ZVNhbmRib3hlcy5hZGQoc2FuZGJveE5hbWUpO1xuICAgIHJlZ2lzdGVyQ2xlYW51cCgpO1xuICB9KSgpO1xuXG4gIGVuc3VyZVByb21pc2VzLnNldChzYW5kYm94TmFtZSwgcHJvbWlzZSk7XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBwcm9taXNlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgZW5zdXJlUHJvbWlzZXMuZGVsZXRlKHNhbmRib3hOYW1lKTtcbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmNvbnN0IERFRkFVTFRfRE9DS0VSX0NXRCA9IFwiL2hvbWUvYWdlbnQvd29ya3NwYWNlXCI7XG5cbmNsYXNzIERvY2tlclNhbmRib3hJbnN0YW5jZSBpbXBsZW1lbnRzIFNhbmRib3hJbnN0YW5jZSB7XG4gIHJlYWRvbmx5IGN3ZDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHNhbmRib3hOYW1lOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvY2Vzc2VzID0gbmV3IE1hcDxcbiAgICBzdHJpbmcsXG4gICAgaW1wb3J0KFwibm9kZTpjaGlsZF9wcm9jZXNzXCIpLkNoaWxkUHJvY2Vzc1xuICA+KCk7XG5cbiAgY29uc3RydWN0b3Ioc2FuZGJveE5hbWU6IHN0cmluZywgY3dkPzogc3RyaW5nKSB7XG4gICAgdGhpcy5zYW5kYm94TmFtZSA9IHNhbmRib3hOYW1lO1xuICAgIHRoaXMuY3dkID0gY3dkID8/IERFRkFVTFRfRE9DS0VSX0NXRDtcbiAgfVxuXG4gIGFzeW5jIGV4ZWMob3B0czoge1xuICAgIGNvbW1hbmQ6IHN0cmluZztcbiAgICBhcmdzPzogc3RyaW5nW107XG4gICAgY3dkPzogc3RyaW5nO1xuICAgIGVudj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gICAgc3Vkbz86IGJvb2xlYW47XG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG4gIH0pOiBQcm9taXNlPEV4ZWNSZXN1bHQ+IHtcbiAgICBhd2FpdCBlbnN1cmVTYW5kYm94KHRoaXMuc2FuZGJveE5hbWUpO1xuXG4gICAgY29uc3QgeyBzcGF3biB9ID0gYXdhaXQgaW1wb3J0KFwibm9kZTpjaGlsZF9wcm9jZXNzXCIpO1xuICAgIGNvbnN0IGNvbW1hbmRJZCA9IGBjb21tYW5kXyR7dWxpZCgpfWA7XG4gICAgY29uc3QgZW52RmxhZ3MgPSBvcHRzLmVudlxuICAgICAgPyBPYmplY3QuZW50cmllcyhvcHRzLmVudikuZmxhdE1hcCgoW2ssIHZdKSA9PiBbXCItZVwiLCBgJHtrfT0ke3Z9YF0pXG4gICAgICA6IFtdO1xuICAgIGNvbnN0IGN3ZEZsYWdzID0gb3B0cy5jd2QgPyBbXCItd1wiLCBvcHRzLmN3ZF0gOiBbXTtcbiAgICBjb25zdCBiYXNlQ21kID0gb3B0cy5zdWRvXG4gICAgICA/IFtcInN1ZG9cIiwgb3B0cy5jb21tYW5kLCAuLi4ob3B0cy5hcmdzID8/IFtdKV1cbiAgICAgIDogb3B0cy5hcmdzXG4gICAgICAgID8gW29wdHMuY29tbWFuZCwgLi4ub3B0cy5hcmdzXVxuICAgICAgICA6IFtvcHRzLmNvbW1hbmRdO1xuICAgIGNvbnN0IGZ1bGxDbWQgPSBiYXNlQ21kO1xuXG4gICAgY29uc3QgY2hpbGQgPSBzcGF3bihcbiAgICAgIFwiZG9ja2VyXCIsXG4gICAgICBbXG4gICAgICAgIFwic2FuZGJveFwiLFxuICAgICAgICBcImV4ZWNcIixcbiAgICAgICAgLi4uZW52RmxhZ3MsXG4gICAgICAgIC4uLmN3ZEZsYWdzLFxuICAgICAgICB0aGlzLnNhbmRib3hOYW1lLFxuICAgICAgICAuLi5mdWxsQ21kLFxuICAgICAgXSxcbiAgICAgIHsgc2lnbmFsOiBvcHRzLnNpZ25hbCB9XG4gICAgKTtcblxuICAgIHRoaXMucHJvY2Vzc2VzLnNldChjb21tYW5kSWQsIGNoaWxkKTtcblxuICAgIGxldCBzdGRvdXQgPSBcIlwiO1xuICAgIGxldCBzdGRlcnIgPSBcIlwiO1xuICAgIGNvbnN0IGxvZ1F1ZXVlOiB7IHN0cmVhbTogXCJzdGRvdXRcIiB8IFwic3RkZXJyXCI7IGRhdGE6IHN0cmluZyB9W10gPSBbXTtcbiAgICBsZXQgbG9nUmVzb2x2ZTogKCgpID0+IHZvaWQpIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IGNsb3NlZCA9IGZhbHNlO1xuXG4gICAgY2hpbGQuc3Rkb3V0Lm9uKFwiZGF0YVwiLCAoZGF0YTogc3RyaW5nIHwgQnVmZmVyKSA9PiB7XG4gICAgICBjb25zdCBzdHIgPSBTdHJpbmcoZGF0YSk7XG4gICAgICBzdGRvdXQgKz0gc3RyO1xuICAgICAgbG9nUXVldWUucHVzaCh7IHN0cmVhbTogXCJzdGRvdXRcIiwgZGF0YTogc3RyIH0pO1xuICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgfSk7XG5cbiAgICBjaGlsZC5zdGRlcnIub24oXCJkYXRhXCIsIChkYXRhOiBzdHJpbmcgfCBCdWZmZXIpID0+IHtcbiAgICAgIGNvbnN0IHN0ciA9IFN0cmluZyhkYXRhKTtcbiAgICAgIHN0ZGVyciArPSBzdHI7XG4gICAgICBsb2dRdWV1ZS5wdXNoKHsgc3RyZWFtOiBcInN0ZGVyclwiLCBkYXRhOiBzdHIgfSk7XG4gICAgICBsb2dSZXNvbHZlPy4oKTtcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBQcm9taXNlPHtcbiAgICAgIHN0ZG91dDogc3RyaW5nO1xuICAgICAgc3RkZXJyOiBzdHJpbmc7XG4gICAgICBleGl0Q29kZTogbnVtYmVyO1xuICAgIH0+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNoaWxkLm9uKFwiZXJyb3JcIiwgKGVycikgPT4ge1xuICAgICAgICB0aGlzLnByb2Nlc3Nlcy5kZWxldGUoY29tbWFuZElkKTtcbiAgICAgICAgY2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgbG9nUmVzb2x2ZT8uKCk7XG4gICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgfSk7XG5cbiAgICAgIGNoaWxkLm9uKFwiY2xvc2VcIiwgKGNvZGU6IG51bWJlciB8IG51bGwpID0+IHtcbiAgICAgICAgdGhpcy5wcm9jZXNzZXMuZGVsZXRlKGNvbW1hbmRJZCk7XG4gICAgICAgIGNsb3NlZCA9IHRydWU7XG4gICAgICAgIGxvZ1Jlc29sdmU/LigpO1xuICAgICAgICByZXNvbHZlKHsgc3Rkb3V0LCBzdGRlcnIsIGV4aXRDb2RlOiBjb2RlID8/IDAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uKiBsb2dzKCk6IEFzeW5jSXRlcmFibGU8e1xuICAgICAgc3RyZWFtOiBcInN0ZG91dFwiIHwgXCJzdGRlcnJcIjtcbiAgICAgIGRhdGE6IHN0cmluZztcbiAgICB9PiB7XG4gICAgICB3aGlsZSAoIWNsb3NlZCB8fCBsb2dRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IGVudHJ5ID0gbG9nUXVldWUuc2hpZnQoKTtcbiAgICAgICAgaWYgKGVudHJ5KSB7XG4gICAgICAgICAgeWllbGQgZW50cnk7XG4gICAgICAgIH0gZWxzZSBpZiAoIWNsb3NlZCkge1xuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlPHZvaWQ+KChyKSA9PiB7XG4gICAgICAgICAgICBsb2dSZXNvbHZlID0gcjtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBsb2dSZXNvbHZlID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7IGNvbW1hbmRJZCwgbG9ncywgcmVzdWx0IH07XG4gIH1cblxuICBhc3luYyByZWFkRmlsZShvcHRzOiB7XG4gICAgcGF0aDogc3RyaW5nO1xuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICB9KTogUHJvbWlzZTxCdWZmZXIgfCBudWxsPiB7XG4gICAgYXdhaXQgZW5zdXJlU2FuZGJveCh0aGlzLnNhbmRib3hOYW1lKTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGV4ZWNEb2NrZXIoXG4gICAgICBbXG4gICAgICAgIFwiZXhlY1wiLFxuICAgICAgICB0aGlzLnNhbmRib3hOYW1lLFxuICAgICAgICBcImJhc2hcIixcbiAgICAgICAgXCItY1wiLFxuICAgICAgICBgYmFzZTY0ICcke29wdHMucGF0aC5yZXBsYWNlKC8nL2csIFwiJ1xcXFwnJ1wiKX0nYCxcbiAgICAgIF0sXG4gICAgICB7IHRpbWVvdXRNczogMzBfMDAwLCBzaWduYWw6IG9wdHMuc2lnbmFsIH1cbiAgICApO1xuXG4gICAgaWYgKHJlc3VsdC5leGl0Q29kZSAhPT0gMCkge1xuICAgICAgaWYgKFxuICAgICAgICByZXN1bHQuc3RkZXJyLmluY2x1ZGVzKFwiTm8gc3VjaCBmaWxlXCIpIHx8XG4gICAgICAgIHJlc3VsdC5zdGRlcnIuaW5jbHVkZXMoXCJFTk9FTlRcIilcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBFcnJvcihgcmVhZEZpbGUgZmFpbGVkOiAke3Jlc3VsdC5zdGRlcnJ9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKHJlc3VsdC5zdGRvdXQudHJpbSgpLCBcImJhc2U2NFwiKTtcbiAgfVxuXG4gIGFzeW5jIHdyaXRlRmlsZXMob3B0czoge1xuICAgIGZpbGVzOiB7IHBhdGg6IHN0cmluZzsgY29udGVudDogc3RyaW5nIHwgQnVmZmVyIH1bXTtcbiAgICBkZXN0UGF0aDogc3RyaW5nO1xuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgZW5zdXJlU2FuZGJveCh0aGlzLnNhbmRib3hOYW1lKTtcblxuICAgIGZvciAoY29uc3QgZmlsZSBvZiBvcHRzLmZpbGVzKSB7XG4gICAgICBjb25zdCBmdWxsUGF0aCA9IG9wdHMuZGVzdFBhdGhcbiAgICAgICAgPyBgJHtvcHRzLmRlc3RQYXRofS8ke2ZpbGUucGF0aH1gXG4gICAgICAgIDogZmlsZS5wYXRoO1xuXG4gICAgICAvLyBFbnN1cmUgcGFyZW50IGRpcmVjdG9yeSBleGlzdHNcbiAgICAgIGNvbnN0IHBhcmVudERpciA9IGZ1bGxQYXRoLnN1YnN0cmluZygwLCBmdWxsUGF0aC5sYXN0SW5kZXhPZihcIi9cIikpO1xuICAgICAgaWYgKHBhcmVudERpcikge1xuICAgICAgICBhd2FpdCBleGVjRG9ja2VyKFtcImV4ZWNcIiwgdGhpcy5zYW5kYm94TmFtZSwgXCJta2RpclwiLCBcIi1wXCIsIHBhcmVudERpcl0sIHtcbiAgICAgICAgICBzaWduYWw6IG9wdHMuc2lnbmFsLFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgLy8gV3JpdGUgdmlhIGJhc2U2NCB0byBoYW5kbGUgYm90aCB0ZXh0IGFuZCBiaW5hcnkgY29udGVudFxuICAgICAgY29uc3QgYjY0ID1cbiAgICAgICAgdHlwZW9mIGZpbGUuY29udGVudCA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgID8gQnVmZmVyLmZyb20oZmlsZS5jb250ZW50KS50b1N0cmluZyhcImJhc2U2NFwiKVxuICAgICAgICAgIDogZmlsZS5jb250ZW50LnRvU3RyaW5nKFwiYmFzZTY0XCIpO1xuXG4gICAgICBhd2FpdCBleGVjRG9ja2VyKFxuICAgICAgICBbXG4gICAgICAgICAgXCJleGVjXCIsXG4gICAgICAgICAgdGhpcy5zYW5kYm94TmFtZSxcbiAgICAgICAgICBcImJhc2hcIixcbiAgICAgICAgICBcIi1jXCIsXG4gICAgICAgICAgYGVjaG8gJyR7YjY0fScgfCBiYXNlNjQgLWQgPiAnJHtmdWxsUGF0aC5yZXBsYWNlKC8nL2csIFwiJ1xcXFwnJ1wiKX0nYCxcbiAgICAgICAgXSxcbiAgICAgICAgeyBzaWduYWw6IG9wdHMuc2lnbmFsIH1cbiAgICAgICk7XG5cbiAgICAgIGlmIChmaWxlLnBhdGguZW5kc1dpdGgoXCIuc2hcIikpIHtcbiAgICAgICAgYXdhaXQgZXhlY0RvY2tlcihbXCJleGVjXCIsIHRoaXMuc2FuZGJveE5hbWUsIFwiY2htb2RcIiwgXCIreFwiLCBmdWxsUGF0aF0sIHtcbiAgICAgICAgICBzaWduYWw6IG9wdHMuc2lnbmFsLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBiaW9tZS1pZ25vcmUgbGludC9zdXNwaWNpb3VzL3VzZUF3YWl0OiAuXG4gIGFzeW5jIGdldERvbWFpbihvcHRzOiB7XG4gICAgcG9ydDogbnVtYmVyO1xuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICB9KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gYGh0dHA6Ly9sb2NhbGhvc3Q6JHtvcHRzLnBvcnR9YDtcbiAgfVxuXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IC5cbiAgYXN5bmMga2lsbChvcHRzOiB7IGNvbW1hbmRJZDogc3RyaW5nOyBzaWduYWw/OiBBYm9ydFNpZ25hbCB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2hpbGQgPSB0aGlzLnByb2Nlc3Nlcy5nZXQob3B0cy5jb21tYW5kSWQpO1xuICAgIGlmIChjaGlsZCkge1xuICAgICAgY2hpbGQua2lsbChcIlNJR1RFUk1cIik7XG4gICAgICB0aGlzLnByb2Nlc3Nlcy5kZWxldGUob3B0cy5jb21tYW5kSWQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IC5cbiAgYXN5bmMgZ2V0U3RhdHVzKCk6IFByb21pc2U8XG4gICAgXCJwZW5kaW5nXCIgfCBcInJ1bm5pbmdcIiB8IFwic3RvcHBpbmdcIiB8IFwic3RvcHBlZFwiIHwgXCJmYWlsZWRcIlxuICA+IHtcbiAgICAvLyBkb2NrZXIgc2FuZGJveCBDTEkgZG9lc24ndCBleHBvc2Ugc3RhdHVzIFx1MjAxNCBhc3N1bWUgcnVubmluZyBpZiBlbnN1cmVkXG4gICAgcmV0dXJuIFwicnVubmluZ1wiO1xuICB9XG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgZW5zdXJlU2FuZGJveCh0aGlzLnNhbmRib3hOYW1lKTtcbiAgfVxuXG4gIGFzeW5jIHN0b3AoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgZXhlY0RvY2tlcihbXCJzdG9wXCIsIHRoaXMuc2FuZGJveE5hbWVdLCB7IHRpbWVvdXRNczogMzBfMDAwIH0pO1xuICAgIGFjdGl2ZVNhbmRib3hlcy5kZWxldGUodGhpcy5zYW5kYm94TmFtZSk7XG4gICAgZW5zdXJlUHJvbWlzZXMuZGVsZXRlKHRoaXMuc2FuZGJveE5hbWUpO1xuICB9XG5cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy91c2VBd2FpdDogLlxuICBhc3luYyBzbmFwc2hvdCgpOiBQcm9taXNlPHsgc25hcHNob3RJZDogc3RyaW5nIH0+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJzbmFwc2hvdCBpcyBub3Qgc3VwcG9ydGVkIGZvciBkb2NrZXIgc2FuZGJveGVzXCIpO1xuICB9XG5cbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvc3VzcGljaW91cy91c2VBd2FpdDogLlxuICBhc3luYyB1cGRhdGVOZXR3b3JrUG9saWN5KCk6IFByb21pc2U8bmV2ZXI+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBcInVwZGF0ZU5ldHdvcmtQb2xpY3kgaXMgbm90IHN1cHBvcnRlZCBmb3IgZG9ja2VyIHNhbmRib3hlc1wiXG4gICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZG9ja2VyU2FuZGJveCgpOiBTYW5kYm94QmluZGluZzxcbiAgXCJkb2NrZXJcIixcbiAgRG9ja2VyQmluZGluZ0NvbmZpZyxcbiAgRG9ja2VyQmluZGluZ01ldGFkYXRhXG4+IHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiBcImRvY2tlclwiLFxuICAgIGFzeW5jIGNyZWF0ZShvcHRzKSB7XG4gICAgICBjb25zdCBzYW5kYm94TmFtZSA9IGBhZ2VudC0ke3VsaWQoKX1gO1xuICAgICAgY29uc3QgY3dkID0gb3B0cy5zZXR1cD8uY29uZmlnPy5jd2Q7XG5cbiAgICAgIGF3YWl0IGVuc3VyZVNhbmRib3goc2FuZGJveE5hbWUpO1xuXG4gICAgICBjb25zdCBpbnN0YW5jZSA9IG5ldyBEb2NrZXJTYW5kYm94SW5zdGFuY2Uoc2FuZGJveE5hbWUsIGN3ZCk7XG5cbiAgICAgIGlmIChvcHRzLnNldHVwPy5ydW4pIHtcbiAgICAgICAgYXdhaXQgb3B0cy5zZXR1cC5ydW4oaW5zdGFuY2UpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBpbnN0YW5jZSxcbiAgICAgICAgbWV0YWRhdGE6IHsgc2FuZGJveE5hbWUgfSxcbiAgICAgIH07XG4gICAgfSxcblxuICAgIC8vIGJpb21lLWlnbm9yZSBsaW50L3N1c3BpY2lvdXMvdXNlQXdhaXQ6IC5cbiAgICBhc3luYyBjb25uZWN0KG9wdHMpIHtcbiAgICAgIHJldHVybiBuZXcgRG9ja2VyU2FuZGJveEluc3RhbmNlKG9wdHMubWV0YWRhdGEuc2FuZGJveE5hbWUpO1xuICAgIH0sXG4gIH07XG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQUEsU0FBUyxZQUFZO0FBY3JCLGVBQWUsV0FDYixNQUNBLE1BQytEO0FBQy9ELFFBQU0sRUFBRSxNQUFNLElBQUksTUFBTSxPQUFPLGVBQW9CO0FBQ25ELFNBQU8sSUFBSSxRQUFRLENBQUMsU0FBUyxXQUFXO0FBQ3RDLFVBQU0sUUFBUSxNQUFNLFVBQVUsQ0FBQyxXQUFXLEdBQUcsSUFBSSxHQUFHO0FBQUEsTUFDbEQsUUFBUSxNQUFNO0FBQUEsSUFDaEIsQ0FBQztBQUVELFFBQUksU0FBUztBQUNiLFFBQUksU0FBUztBQUViLFVBQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxTQUFpQjtBQUN4QyxnQkFBVSxLQUFLLFNBQVM7QUFBQSxJQUMxQixDQUFDO0FBQ0QsVUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLFNBQWlCO0FBQ3hDLGdCQUFVLEtBQUssU0FBUztBQUFBLElBQzFCLENBQUM7QUFFRCxVQUFNLFlBQVksTUFBTSxZQUNwQixXQUFXLE1BQU07QUFDZixZQUFNLEtBQUssU0FBUztBQUNwQixhQUFPLElBQUksTUFBTSxrQkFBa0IsS0FBSyxDQUFDLENBQUMsWUFBWSxDQUFDO0FBQUEsSUFDekQsR0FBRyxLQUFLLFNBQVMsSUFDakI7QUFFSixVQUFNLEdBQUcsU0FBUyxDQUFDLFFBQVE7QUFDekIsVUFBSSxXQUFXO0FBQ2IscUJBQWEsU0FBUztBQUFBLE1BQ3hCO0FBQ0EsYUFBTyxHQUFHO0FBQUEsSUFDWixDQUFDO0FBRUQsVUFBTSxHQUFHLFNBQVMsQ0FBQyxT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
@@ -0,0 +1,72 @@
1
+ // src/sandbox/process-manager.ts
2
+ var DEFAULT_WAIT_UNTIL = 2e3;
3
+ var createProcessManager = (opts) => {
4
+ const { sandbox } = opts;
5
+ const run = async (runOpts) => {
6
+ const { command, waitUntil = DEFAULT_WAIT_UNTIL } = runOpts;
7
+ const execResult = await sandbox.exec({
8
+ command: "sh",
9
+ args: ["-c", command]
10
+ });
11
+ if (waitUntil === 0) {
12
+ return {
13
+ commandId: execResult.commandId,
14
+ stdout: "",
15
+ stderr: "",
16
+ exitCode: -1,
17
+ status: "running",
18
+ outputDir: ""
19
+ };
20
+ }
21
+ const completed = await raceTimeout(execResult, waitUntil);
22
+ if (!completed) {
23
+ return {
24
+ commandId: execResult.commandId,
25
+ stdout: "",
26
+ stderr: "",
27
+ exitCode: -1,
28
+ status: "running",
29
+ outputDir: ""
30
+ };
31
+ }
32
+ const outputDir = `.agent/bash/${Date.now()}-${execResult.commandId}`;
33
+ writeOutputDir(sandbox, outputDir, completed, command);
34
+ return {
35
+ commandId: execResult.commandId,
36
+ stdout: completed.stdout,
37
+ stderr: completed.stderr,
38
+ exitCode: completed.exitCode,
39
+ status: completed.exitCode === 0 ? "completed" : "failed",
40
+ outputDir
41
+ };
42
+ };
43
+ return { run };
44
+ };
45
+ async function raceTimeout(execResult, timeoutMs) {
46
+ const TIMED_OUT = /* @__PURE__ */ Symbol("timeout");
47
+ const timer = new Promise(
48
+ (resolve) => setTimeout(() => resolve(TIMED_OUT), timeoutMs)
49
+ );
50
+ const winner = await Promise.race([execResult.result, timer]);
51
+ return winner === TIMED_OUT ? null : winner;
52
+ }
53
+ function writeOutputDir(sandbox, dir, result, command) {
54
+ const files = [
55
+ { path: "stdout.txt", content: result.stdout },
56
+ {
57
+ path: "metadata.json",
58
+ content: JSON.stringify({ exitCode: result.exitCode, command }, null, 2)
59
+ }
60
+ ];
61
+ if (result.stderr) {
62
+ files.push({ path: "stderr.txt", content: result.stderr });
63
+ }
64
+ sandbox.writeFiles({ files, destPath: dir }).catch(() => {
65
+ });
66
+ }
67
+
68
+ export {
69
+ DEFAULT_WAIT_UNTIL,
70
+ createProcessManager
71
+ };
72
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3NhbmRib3gvcHJvY2Vzcy1tYW5hZ2VyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgdHlwZSB7IEV4ZWNSZXN1bHQgfSBmcm9tIFwiLi9hZGFwdGVyXCI7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1dBSVRfVU5USUwgPSAyMDAwO1xuXG50eXBlIFNhbmRib3hIYW5kbGUgPSB7XG4gIGV4ZWM6IChvcHRzOiB7IGNvbW1hbmQ6IHN0cmluZzsgYXJncz86IHN0cmluZ1tdIH0pID0+IFByb21pc2U8RXhlY1Jlc3VsdD47XG4gIHdyaXRlRmlsZXM6IChvcHRzOiB7XG4gICAgZmlsZXM6IHsgcGF0aDogc3RyaW5nOyBjb250ZW50OiBzdHJpbmcgfVtdO1xuICAgIGRlc3RQYXRoOiBzdHJpbmc7XG4gIH0pID0+IFByb21pc2U8dm9pZD47XG59O1xuXG50eXBlIEJhc2hSZXN1bHQgPSB7XG4gIGNvbW1hbmRJZDogc3RyaW5nO1xuICBzdGRvdXQ6IHN0cmluZztcbiAgc3RkZXJyOiBzdHJpbmc7XG4gIGV4aXRDb2RlOiBudW1iZXI7XG4gIHN0YXR1czogXCJydW5uaW5nXCIgfCBcImNvbXBsZXRlZFwiIHwgXCJmYWlsZWRcIjtcbiAgb3V0cHV0RGlyOiBzdHJpbmc7XG59O1xuXG50eXBlIFJ1bk9wdGlvbnMgPSB7XG4gIGNvbW1hbmQ6IHN0cmluZztcbiAgd2FpdFVudGlsPzogbnVtYmVyO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVByb2Nlc3NNYW5hZ2VyID0gKG9wdHM6IHsgc2FuZGJveDogU2FuZGJveEhhbmRsZSB9KSA9PiB7XG4gIGNvbnN0IHsgc2FuZGJveCB9ID0gb3B0cztcblxuICBjb25zdCBydW4gPSBhc3luYyAocnVuT3B0czogUnVuT3B0aW9ucyk6IFByb21pc2U8QmFzaFJlc3VsdD4gPT4ge1xuICAgIGNvbnN0IHsgY29tbWFuZCwgd2FpdFVudGlsID0gREVGQVVMVF9XQUlUX1VOVElMIH0gPSBydW5PcHRzO1xuXG4gICAgY29uc3QgZXhlY1Jlc3VsdCA9IGF3YWl0IHNhbmRib3guZXhlYyh7XG4gICAgICBjb21tYW5kOiBcInNoXCIsXG4gICAgICBhcmdzOiBbXCItY1wiLCBjb21tYW5kXSxcbiAgICB9KTtcblxuICAgIGlmICh3YWl0VW50aWwgPT09IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbW1hbmRJZDogZXhlY1Jlc3VsdC5jb21tYW5kSWQsXG4gICAgICAgIHN0ZG91dDogXCJcIixcbiAgICAgICAgc3RkZXJyOiBcIlwiLFxuICAgICAgICBleGl0Q29kZTogLTEsXG4gICAgICAgIHN0YXR1czogXCJydW5uaW5nXCIsXG4gICAgICAgIG91dHB1dERpcjogXCJcIixcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgY29tcGxldGVkID0gYXdhaXQgcmFjZVRpbWVvdXQoZXhlY1Jlc3VsdCwgd2FpdFVudGlsKTtcblxuICAgIGlmICghY29tcGxldGVkKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb21tYW5kSWQ6IGV4ZWNSZXN1bHQuY29tbWFuZElkLFxuICAgICAgICBzdGRvdXQ6IFwiXCIsXG4gICAgICAgIHN0ZGVycjogXCJcIixcbiAgICAgICAgZXhpdENvZGU6IC0xLFxuICAgICAgICBzdGF0dXM6IFwicnVubmluZ1wiLFxuICAgICAgICBvdXRwdXREaXI6IFwiXCIsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IG91dHB1dERpciA9IGAuYWdlbnQvYmFzaC8ke0RhdGUubm93KCl9LSR7ZXhlY1Jlc3VsdC5jb21tYW5kSWR9YDtcbiAgICB3cml0ZU91dHB1dERpcihzYW5kYm94LCBvdXRwdXREaXIsIGNvbXBsZXRlZCwgY29tbWFuZCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgY29tbWFuZElkOiBleGVjUmVzdWx0LmNvbW1hbmRJZCxcbiAgICAgIHN0ZG91dDogY29tcGxldGVkLnN0ZG91dCxcbiAgICAgIHN0ZGVycjogY29tcGxldGVkLnN0ZGVycixcbiAgICAgIGV4aXRDb2RlOiBjb21wbGV0ZWQuZXhpdENvZGUsXG4gICAgICBzdGF0dXM6IGNvbXBsZXRlZC5leGl0Q29kZSA9PT0gMCA/IFwiY29tcGxldGVkXCIgOiBcImZhaWxlZFwiLFxuICAgICAgb3V0cHV0RGlyLFxuICAgIH07XG4gIH07XG5cbiAgcmV0dXJuIHsgcnVuIH07XG59O1xuXG5hc3luYyBmdW5jdGlvbiByYWNlVGltZW91dChcbiAgZXhlY1Jlc3VsdDogRXhlY1Jlc3VsdCxcbiAgdGltZW91dE1zOiBudW1iZXJcbik6IFByb21pc2U8eyBzdGRvdXQ6IHN0cmluZzsgc3RkZXJyOiBzdHJpbmc7IGV4aXRDb2RlOiBudW1iZXIgfSB8IG51bGw+IHtcbiAgY29uc3QgVElNRURfT1VUID0gU3ltYm9sKFwidGltZW91dFwiKTtcbiAgY29uc3QgdGltZXIgPSBuZXcgUHJvbWlzZTx0eXBlb2YgVElNRURfT1VUPigocmVzb2x2ZSkgPT5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHJlc29sdmUoVElNRURfT1VUKSwgdGltZW91dE1zKVxuICApO1xuICBjb25zdCB3aW5uZXIgPSBhd2FpdCBQcm9taXNlLnJhY2UoW2V4ZWNSZXN1bHQucmVzdWx0LCB0aW1lcl0pO1xuICByZXR1cm4gd2lubmVyID09PSBUSU1FRF9PVVQgPyBudWxsIDogd2lubmVyO1xufVxuXG5mdW5jdGlvbiB3cml0ZU91dHB1dERpcihcbiAgc2FuZGJveDogU2FuZGJveEhhbmRsZSxcbiAgZGlyOiBzdHJpbmcsXG4gIHJlc3VsdDogeyBzdGRvdXQ6IHN0cmluZzsgc3RkZXJyOiBzdHJpbmc7IGV4aXRDb2RlOiBudW1iZXIgfSxcbiAgY29tbWFuZDogc3RyaW5nXG4pOiB2b2lkIHtcbiAgY29uc3QgZmlsZXM6IHsgcGF0aDogc3RyaW5nOyBjb250ZW50OiBzdHJpbmcgfVtdID0gW1xuICAgIHsgcGF0aDogXCJzdGRvdXQudHh0XCIsIGNvbnRlbnQ6IHJlc3VsdC5zdGRvdXQgfSxcbiAgICB7XG4gICAgICBwYXRoOiBcIm1ldGFkYXRhLmpzb25cIixcbiAgICAgIGNvbnRlbnQ6IEpTT04uc3RyaW5naWZ5KHsgZXhpdENvZGU6IHJlc3VsdC5leGl0Q29kZSwgY29tbWFuZCB9LCBudWxsLCAyKSxcbiAgICB9LFxuICBdO1xuICBpZiAocmVzdWx0LnN0ZGVycikge1xuICAgIGZpbGVzLnB1c2goeyBwYXRoOiBcInN0ZGVyci50eHRcIiwgY29udGVudDogcmVzdWx0LnN0ZGVyciB9KTtcbiAgfVxuXG4gIHNhbmRib3gud3JpdGVGaWxlcyh7IGZpbGVzLCBkZXN0UGF0aDogZGlyIH0pLmNhdGNoKCgpID0+IHtcbiAgICAvLyBpbnRlbnRpb25hbCBuby1vcCBcdTIwMTQgb3V0cHV0IGZpbGUgd3JpdGUgaXMgYmVzdC1lZmZvcnRcbiAgfSk7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBRU8sSUFBTSxxQkFBcUI7QUF3QjNCLElBQU0sdUJBQXVCLENBQUMsU0FBcUM7QUFDeEUsUUFBTSxFQUFFLFFBQVEsSUFBSTtBQUVwQixRQUFNLE1BQU0sT0FBTyxZQUE2QztBQUM5RCxVQUFNLEVBQUUsU0FBUyxZQUFZLG1CQUFtQixJQUFJO0FBRXBELFVBQU0sYUFBYSxNQUFNLFFBQVEsS0FBSztBQUFBLE1BQ3BDLFNBQVM7QUFBQSxNQUNULE1BQU0sQ0FBQyxNQUFNLE9BQU87QUFBQSxJQUN0QixDQUFDO0FBRUQsUUFBSSxjQUFjLEdBQUc7QUFDbkIsYUFBTztBQUFBLFFBQ0wsV0FBVyxXQUFXO0FBQUEsUUFDdEIsUUFBUTtBQUFBLFFBQ1IsUUFBUTtBQUFBLFFBQ1IsVUFBVTtBQUFBLFFBQ1YsUUFBUTtBQUFBLFFBQ1IsV0FBVztBQUFBLE1BQ2I7QUFBQSxJQUNGO0FBRUEsVUFBTSxZQUFZLE1BQU0sWUFBWSxZQUFZLFNBQVM7QUFFekQsUUFBSSxDQUFDLFdBQVc7QUFDZCxhQUFPO0FBQUEsUUFDTCxXQUFXLFdBQVc7QUFBQSxRQUN0QixRQUFRO0FBQUEsUUFDUixRQUFRO0FBQUEsUUFDUixVQUFVO0FBQUEsUUFDVixRQUFRO0FBQUEsUUFDUixXQUFXO0FBQUEsTUFDYjtBQUFBLElBQ0Y7QUFFQSxVQUFNLFlBQVksZUFBZSxLQUFLLElBQUksQ0FBQyxJQUFJLFdBQVcsU0FBUztBQUNuRSxtQkFBZSxTQUFTLFdBQVcsV0FBVyxPQUFPO0FBRXJELFdBQU87QUFBQSxNQUNMLFdBQVcsV0FBVztBQUFBLE1BQ3RCLFFBQVEsVUFBVTtBQUFBLE1BQ2xCLFFBQVEsVUFBVTtBQUFBLE1BQ2xCLFVBQVUsVUFBVTtBQUFBLE1BQ3BCLFFBQVEsVUFBVSxhQUFhLElBQUksY0FBYztBQUFBLE1BQ2pEO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFFQSxTQUFPLEVBQUUsSUFBSTtBQUNmO0FBRUEsZUFBZSxZQUNiLFlBQ0EsV0FDc0U7QUFDdEUsUUFBTSxZQUFZLHVCQUFPLFNBQVM7QUFDbEMsUUFBTSxRQUFRLElBQUk7QUFBQSxJQUEwQixDQUFDLFlBQzNDLFdBQVcsTUFBTSxRQUFRLFNBQVMsR0FBRyxTQUFTO0FBQUEsRUFDaEQ7QUFDQSxRQUFNLFNBQVMsTUFBTSxRQUFRLEtBQUssQ0FBQyxXQUFXLFFBQVEsS0FBSyxDQUFDO0FBQzVELFNBQU8sV0FBVyxZQUFZLE9BQU87QUFDdkM7QUFFQSxTQUFTLGVBQ1AsU0FDQSxLQUNBLFFBQ0EsU0FDTTtBQUNOLFFBQU0sUUFBNkM7QUFBQSxJQUNqRCxFQUFFLE1BQU0sY0FBYyxTQUFTLE9BQU8sT0FBTztBQUFBLElBQzdDO0FBQUEsTUFDRSxNQUFNO0FBQUEsTUFDTixTQUFTLEtBQUssVUFBVSxFQUFFLFVBQVUsT0FBTyxVQUFVLFFBQVEsR0FBRyxNQUFNLENBQUM7QUFBQSxJQUN6RTtBQUFBLEVBQ0Y7QUFDQSxNQUFJLE9BQU8sUUFBUTtBQUNqQixVQUFNLEtBQUssRUFBRSxNQUFNLGNBQWMsU0FBUyxPQUFPLE9BQU8sQ0FBQztBQUFBLEVBQzNEO0FBRUEsVUFBUSxXQUFXLEVBQUUsT0FBTyxVQUFVLElBQUksQ0FBQyxFQUFFLE1BQU0sTUFBTTtBQUFBLEVBRXpELENBQUM7QUFDSDsiLAogICJuYW1lcyI6IFtdCn0K