@herdctl/core 1.3.0 → 2.0.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 (181) hide show
  1. package/dist/config/__tests__/agent.test.js +12 -12
  2. package/dist/config/__tests__/agent.test.js.map +1 -1
  3. package/dist/config/__tests__/loader.test.js +201 -4
  4. package/dist/config/__tests__/loader.test.js.map +1 -1
  5. package/dist/config/__tests__/merge.test.js +29 -4
  6. package/dist/config/__tests__/merge.test.js.map +1 -1
  7. package/dist/config/__tests__/parser.test.js +13 -13
  8. package/dist/config/__tests__/parser.test.js.map +1 -1
  9. package/dist/config/__tests__/schema.test.js +10 -10
  10. package/dist/config/__tests__/schema.test.js.map +1 -1
  11. package/dist/config/index.d.ts +1 -1
  12. package/dist/config/index.d.ts.map +1 -1
  13. package/dist/config/index.js +2 -2
  14. package/dist/config/index.js.map +1 -1
  15. package/dist/config/loader.d.ts.map +1 -1
  16. package/dist/config/loader.js +71 -0
  17. package/dist/config/loader.js.map +1 -1
  18. package/dist/config/merge.d.ts +4 -1
  19. package/dist/config/merge.d.ts.map +1 -1
  20. package/dist/config/merge.js +16 -0
  21. package/dist/config/merge.js.map +1 -1
  22. package/dist/config/schema.d.ts +906 -89
  23. package/dist/config/schema.d.ts.map +1 -1
  24. package/dist/config/schema.js +109 -7
  25. package/dist/config/schema.js.map +1 -1
  26. package/dist/fleet-manager/__tests__/coverage.test.js +25 -24
  27. package/dist/fleet-manager/__tests__/coverage.test.js.map +1 -1
  28. package/dist/fleet-manager/__tests__/discord-manager.test.js +9 -2
  29. package/dist/fleet-manager/__tests__/discord-manager.test.js.map +1 -1
  30. package/dist/fleet-manager/__tests__/integration.test.js +27 -0
  31. package/dist/fleet-manager/__tests__/integration.test.js.map +1 -1
  32. package/dist/fleet-manager/__tests__/job-control.test.js +66 -0
  33. package/dist/fleet-manager/__tests__/job-control.test.js.map +1 -1
  34. package/dist/fleet-manager/__tests__/status-queries.test.js +12 -11
  35. package/dist/fleet-manager/__tests__/status-queries.test.js.map +1 -1
  36. package/dist/fleet-manager/config-reload.js +9 -9
  37. package/dist/fleet-manager/config-reload.js.map +1 -1
  38. package/dist/fleet-manager/discord-manager.d.ts.map +1 -1
  39. package/dist/fleet-manager/discord-manager.js +27 -4
  40. package/dist/fleet-manager/discord-manager.js.map +1 -1
  41. package/dist/fleet-manager/fleet-manager.d.ts +11 -0
  42. package/dist/fleet-manager/fleet-manager.d.ts.map +1 -1
  43. package/dist/fleet-manager/fleet-manager.js +27 -0
  44. package/dist/fleet-manager/fleet-manager.js.map +1 -1
  45. package/dist/fleet-manager/job-control.d.ts +1 -1
  46. package/dist/fleet-manager/job-control.d.ts.map +1 -1
  47. package/dist/fleet-manager/job-control.js +36 -14
  48. package/dist/fleet-manager/job-control.js.map +1 -1
  49. package/dist/fleet-manager/schedule-executor.d.ts +1 -1
  50. package/dist/fleet-manager/schedule-executor.d.ts.map +1 -1
  51. package/dist/fleet-manager/schedule-executor.js +11 -14
  52. package/dist/fleet-manager/schedule-executor.js.map +1 -1
  53. package/dist/fleet-manager/status-queries.js +7 -7
  54. package/dist/fleet-manager/status-queries.js.map +1 -1
  55. package/dist/fleet-manager/types.d.ts +10 -2
  56. package/dist/fleet-manager/types.d.ts.map +1 -1
  57. package/dist/fleet-manager/working-directory-helper.d.ts +29 -0
  58. package/dist/fleet-manager/working-directory-helper.d.ts.map +1 -0
  59. package/dist/fleet-manager/working-directory-helper.js +36 -0
  60. package/dist/fleet-manager/working-directory-helper.js.map +1 -0
  61. package/dist/index.d.ts +2 -1
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +4 -1
  64. package/dist/index.js.map +1 -1
  65. package/dist/runner/__tests__/job-executor.test.js +449 -118
  66. package/dist/runner/__tests__/job-executor.test.js.map +1 -1
  67. package/dist/runner/__tests__/sdk-adapter.test.js +147 -23
  68. package/dist/runner/__tests__/sdk-adapter.test.js.map +1 -1
  69. package/dist/runner/index.d.ts +2 -0
  70. package/dist/runner/index.d.ts.map +1 -1
  71. package/dist/runner/index.js +1 -0
  72. package/dist/runner/index.js.map +1 -1
  73. package/dist/runner/job-executor.d.ts +12 -8
  74. package/dist/runner/job-executor.d.ts.map +1 -1
  75. package/dist/runner/job-executor.js +257 -126
  76. package/dist/runner/job-executor.js.map +1 -1
  77. package/dist/runner/runtime/__tests__/cli-session-path.test.d.ts +2 -0
  78. package/dist/runner/runtime/__tests__/cli-session-path.test.d.ts.map +1 -0
  79. package/dist/runner/runtime/__tests__/cli-session-path.test.js +150 -0
  80. package/dist/runner/runtime/__tests__/cli-session-path.test.js.map +1 -0
  81. package/dist/runner/runtime/__tests__/docker-config.test.d.ts +2 -0
  82. package/dist/runner/runtime/__tests__/docker-config.test.d.ts.map +1 -0
  83. package/dist/runner/runtime/__tests__/docker-config.test.js +352 -0
  84. package/dist/runner/runtime/__tests__/docker-config.test.js.map +1 -0
  85. package/dist/runner/runtime/__tests__/docker-security.test.d.ts +2 -0
  86. package/dist/runner/runtime/__tests__/docker-security.test.d.ts.map +1 -0
  87. package/dist/runner/runtime/__tests__/docker-security.test.js +384 -0
  88. package/dist/runner/runtime/__tests__/docker-security.test.js.map +1 -0
  89. package/dist/runner/runtime/__tests__/factory.test.d.ts +2 -0
  90. package/dist/runner/runtime/__tests__/factory.test.d.ts.map +1 -0
  91. package/dist/runner/runtime/__tests__/factory.test.js +149 -0
  92. package/dist/runner/runtime/__tests__/factory.test.js.map +1 -0
  93. package/dist/runner/runtime/__tests__/integration.test.d.ts +2 -0
  94. package/dist/runner/runtime/__tests__/integration.test.d.ts.map +1 -0
  95. package/dist/runner/runtime/__tests__/integration.test.js +274 -0
  96. package/dist/runner/runtime/__tests__/integration.test.js.map +1 -0
  97. package/dist/runner/runtime/cli-runtime.d.ts +107 -0
  98. package/dist/runner/runtime/cli-runtime.d.ts.map +1 -0
  99. package/dist/runner/runtime/cli-runtime.js +335 -0
  100. package/dist/runner/runtime/cli-runtime.js.map +1 -0
  101. package/dist/runner/runtime/cli-session-path.d.ts +108 -0
  102. package/dist/runner/runtime/cli-session-path.d.ts.map +1 -0
  103. package/dist/runner/runtime/cli-session-path.js +173 -0
  104. package/dist/runner/runtime/cli-session-path.js.map +1 -0
  105. package/dist/runner/runtime/cli-session-watcher.d.ts +55 -0
  106. package/dist/runner/runtime/cli-session-watcher.d.ts.map +1 -0
  107. package/dist/runner/runtime/cli-session-watcher.js +187 -0
  108. package/dist/runner/runtime/cli-session-watcher.js.map +1 -0
  109. package/dist/runner/runtime/container-manager.d.ts +76 -0
  110. package/dist/runner/runtime/container-manager.d.ts.map +1 -0
  111. package/dist/runner/runtime/container-manager.js +229 -0
  112. package/dist/runner/runtime/container-manager.js.map +1 -0
  113. package/dist/runner/runtime/container-runner.d.ts +62 -0
  114. package/dist/runner/runtime/container-runner.d.ts.map +1 -0
  115. package/dist/runner/runtime/container-runner.js +235 -0
  116. package/dist/runner/runtime/container-runner.js.map +1 -0
  117. package/dist/runner/runtime/docker-config.d.ts +100 -0
  118. package/dist/runner/runtime/docker-config.d.ts.map +1 -0
  119. package/dist/runner/runtime/docker-config.js +98 -0
  120. package/dist/runner/runtime/docker-config.js.map +1 -0
  121. package/dist/runner/runtime/factory.d.ts +63 -0
  122. package/dist/runner/runtime/factory.d.ts.map +1 -0
  123. package/dist/runner/runtime/factory.js +68 -0
  124. package/dist/runner/runtime/factory.js.map +1 -0
  125. package/dist/runner/runtime/index.d.ts +20 -0
  126. package/dist/runner/runtime/index.d.ts.map +1 -0
  127. package/dist/runner/runtime/index.js +21 -0
  128. package/dist/runner/runtime/index.js.map +1 -0
  129. package/dist/runner/runtime/interface.d.ts +59 -0
  130. package/dist/runner/runtime/interface.d.ts.map +1 -0
  131. package/dist/runner/runtime/interface.js +12 -0
  132. package/dist/runner/runtime/interface.js.map +1 -0
  133. package/dist/runner/runtime/sdk-runtime.d.ts +46 -0
  134. package/dist/runner/runtime/sdk-runtime.d.ts.map +1 -0
  135. package/dist/runner/runtime/sdk-runtime.js +63 -0
  136. package/dist/runner/runtime/sdk-runtime.js.map +1 -0
  137. package/dist/runner/sdk-adapter.d.ts +4 -0
  138. package/dist/runner/sdk-adapter.d.ts.map +1 -1
  139. package/dist/runner/sdk-adapter.js +35 -16
  140. package/dist/runner/sdk-adapter.js.map +1 -1
  141. package/dist/runner/types.d.ts +12 -6
  142. package/dist/runner/types.d.ts.map +1 -1
  143. package/dist/scheduler/__tests__/schedule-runner.test.js +61 -50
  144. package/dist/scheduler/__tests__/schedule-runner.test.js.map +1 -1
  145. package/dist/scheduler/schedule-runner.d.ts +1 -4
  146. package/dist/scheduler/schedule-runner.d.ts.map +1 -1
  147. package/dist/scheduler/schedule-runner.js +40 -8
  148. package/dist/scheduler/schedule-runner.js.map +1 -1
  149. package/dist/state/__tests__/session-schema.test.js +4 -0
  150. package/dist/state/__tests__/session-schema.test.js.map +1 -1
  151. package/dist/state/__tests__/session-validation.test.d.ts +2 -0
  152. package/dist/state/__tests__/session-validation.test.d.ts.map +1 -0
  153. package/dist/state/__tests__/session-validation.test.js +446 -0
  154. package/dist/state/__tests__/session-validation.test.js.map +1 -0
  155. package/dist/state/__tests__/session.test.js +68 -0
  156. package/dist/state/__tests__/session.test.js.map +1 -1
  157. package/dist/state/__tests__/working-directory-validation.test.d.ts +5 -0
  158. package/dist/state/__tests__/working-directory-validation.test.d.ts.map +1 -0
  159. package/dist/state/__tests__/working-directory-validation.test.js +101 -0
  160. package/dist/state/__tests__/working-directory-validation.test.js.map +1 -0
  161. package/dist/state/index.d.ts +2 -0
  162. package/dist/state/index.d.ts.map +1 -1
  163. package/dist/state/index.js +4 -0
  164. package/dist/state/index.js.map +1 -1
  165. package/dist/state/schemas/session-info.d.ts +32 -0
  166. package/dist/state/schemas/session-info.d.ts.map +1 -1
  167. package/dist/state/schemas/session-info.js +22 -0
  168. package/dist/state/schemas/session-info.js.map +1 -1
  169. package/dist/state/session-validation.d.ts +202 -0
  170. package/dist/state/session-validation.d.ts.map +1 -0
  171. package/dist/state/session-validation.js +407 -0
  172. package/dist/state/session-validation.js.map +1 -0
  173. package/dist/state/session.d.ts +23 -3
  174. package/dist/state/session.d.ts.map +1 -1
  175. package/dist/state/session.js +41 -6
  176. package/dist/state/session.js.map +1 -1
  177. package/dist/state/working-directory-validation.d.ts +52 -0
  178. package/dist/state/working-directory-validation.d.ts.map +1 -0
  179. package/dist/state/working-directory-validation.js +81 -0
  180. package/dist/state/working-directory-validation.js.map +1 -0
  181. package/package.json +7 -2
@@ -0,0 +1,235 @@
1
+ /**
2
+ * ContainerRunner - Docker container decorator for RuntimeInterface
3
+ *
4
+ * Wraps any runtime (SDK or CLI) and transparently executes inside Docker containers.
5
+ * Handles path translation, mount configuration, and container lifecycle.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * const baseRuntime = new CLIRuntime();
10
+ * const dockerRuntime = new ContainerRunner(baseRuntime, dockerConfig);
11
+ *
12
+ * // Execution happens inside Docker container
13
+ * for await (const message of dockerRuntime.execute(options)) {
14
+ * console.log(message);
15
+ * }
16
+ * ```
17
+ */
18
+ import { execa } from "execa";
19
+ import * as path from "node:path";
20
+ import * as fs from "node:fs/promises";
21
+ import { PassThrough } from "node:stream";
22
+ import { createInterface } from "node:readline";
23
+ import { ContainerManager, buildContainerMounts, buildContainerEnv, } from "./container-manager.js";
24
+ import { CLIRuntime } from "./cli-runtime.js";
25
+ import { SDKRuntime } from "./sdk-runtime.js";
26
+ import { toSDKOptions } from "../sdk-adapter.js";
27
+ import Dockerode from "dockerode";
28
+ /**
29
+ * Container runtime decorator
30
+ *
31
+ * Decorates any RuntimeInterface to execute inside Docker containers.
32
+ * The wrapped runtime's execute logic runs via `docker exec` inside the container.
33
+ */
34
+ export class ContainerRunner {
35
+ wrapped;
36
+ config;
37
+ manager;
38
+ stateDir;
39
+ /**
40
+ * Create a new ContainerRunner
41
+ *
42
+ * @param wrapped - The underlying runtime to execute inside containers
43
+ * @param config - Docker configuration
44
+ * @param stateDir - herdctl state directory (.herdctl/)
45
+ * @param docker - Optional Docker client for testing
46
+ */
47
+ constructor(wrapped, config, stateDir, docker) {
48
+ this.wrapped = wrapped;
49
+ this.config = config;
50
+ this.manager = new ContainerManager(docker);
51
+ this.stateDir = stateDir;
52
+ }
53
+ /**
54
+ * Execute agent inside Docker container
55
+ *
56
+ * Creates or reuses container, then executes based on runtime type:
57
+ * - CLI runtime: docker exec claude, watch session files on host
58
+ * - SDK runtime: docker exec wrapper script, stream JSONL from stdout
59
+ */
60
+ async *execute(options) {
61
+ const { agent } = options;
62
+ // Ensure docker-sessions directory exists on host (for CLI runtime)
63
+ const dockerSessionsDir = path.join(this.stateDir, "docker-sessions");
64
+ await fs.mkdir(dockerSessionsDir, { recursive: true });
65
+ // Build mounts and environment
66
+ const mounts = buildContainerMounts(agent, this.config, this.stateDir);
67
+ const env = buildContainerEnv(agent, this.config);
68
+ // Get or create container
69
+ const container = await this.manager.getOrCreateContainer(agent.name, this.config, mounts, env);
70
+ try {
71
+ // Get container ID for docker exec
72
+ const containerInfo = await container.inspect();
73
+ const containerId = containerInfo.Id;
74
+ // Handle CLI runtime with session file watching
75
+ if (this.wrapped instanceof CLIRuntime) {
76
+ yield* this.executeCLIRuntime(containerId, dockerSessionsDir, options);
77
+ }
78
+ // Handle SDK runtime with wrapper script
79
+ else if (this.wrapped instanceof SDKRuntime) {
80
+ yield* this.executeSDKRuntime(container, options);
81
+ }
82
+ // Unknown runtime type
83
+ else {
84
+ throw new Error(`Unsupported runtime type for Docker execution: ${this.wrapped.constructor.name}`);
85
+ }
86
+ }
87
+ catch (error) {
88
+ const errorMessage = error instanceof Error ? error.message : String(error);
89
+ yield {
90
+ type: "error",
91
+ message: `Docker execution failed: ${errorMessage}`,
92
+ };
93
+ // Container cleanup happens in finally block
94
+ }
95
+ finally {
96
+ // For ephemeral containers, stop immediately after execution
97
+ // This triggers AutoRemove so the container is cleaned up automatically
98
+ if (this.config.ephemeral) {
99
+ try {
100
+ await this.manager.stopContainer(container);
101
+ }
102
+ catch (stopError) {
103
+ // Log but don't fail - container might already be stopped
104
+ console.error('[ContainerRunner] Failed to stop ephemeral container:', stopError);
105
+ }
106
+ }
107
+ // Always cleanup old containers, regardless of success/failure
108
+ // This prevents container accumulation from failed executions
109
+ try {
110
+ await this.manager.cleanupOldContainers(agent.name, this.config.maxContainers);
111
+ }
112
+ catch (cleanupError) {
113
+ // Log cleanup errors but don't fail the execution
114
+ console.error('[ContainerRunner] Failed to cleanup old containers:', cleanupError);
115
+ }
116
+ }
117
+ }
118
+ /**
119
+ * Execute CLI runtime inside Docker container
120
+ *
121
+ * Spawns claude CLI via docker exec and watches session files on host.
122
+ */
123
+ async *executeCLIRuntime(containerId, dockerSessionsDir, options) {
124
+ // Create CLI runtime with Docker-specific spawner
125
+ const cliRuntime = new CLIRuntime({
126
+ processSpawner: (args, _cwd, prompt, signal) => {
127
+ // Build docker exec command with prompt piped to stdin
128
+ // Uses printf to avoid issues with newlines and special chars in prompt
129
+ // Command: docker exec <container> sh -c 'cd /workspace && printf %s "prompt" | claude <args>'
130
+ const escapedPrompt = prompt.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
131
+ const claudeArgs = args.map(arg => {
132
+ // Escape single quotes in arguments
133
+ return `'${arg.replace(/'/g, "'\\''")}'`;
134
+ }).join(" ");
135
+ const claudeCommand = `cd /workspace && printf %s "${escapedPrompt}" | claude ${claudeArgs}`;
136
+ console.log("[ContainerRunner] Executing docker command:", "docker", ["exec", containerId, "sh", "-c", claudeCommand]);
137
+ console.log("[ContainerRunner] Prompt length:", prompt.length);
138
+ // execa returns Subprocess directly (which is promise-like)
139
+ return execa("docker", ["exec", containerId, "sh", "-c", claudeCommand], {
140
+ cancelSignal: signal,
141
+ });
142
+ },
143
+ // Session files are written inside container but mounted to host
144
+ sessionDirOverride: dockerSessionsDir,
145
+ });
146
+ // Delegate to CLI runtime - it handles session watching, timeout, errors
147
+ yield* cliRuntime.execute(options);
148
+ }
149
+ /**
150
+ * Execute SDK runtime inside Docker container
151
+ *
152
+ * Runs docker-sdk-wrapper.js script which imports SDK and streams messages as JSONL.
153
+ */
154
+ async *executeSDKRuntime(container, options) {
155
+ // Build SDK options
156
+ const sdkOptions = toSDKOptions(options.agent, {
157
+ resume: options.resume,
158
+ fork: options.fork,
159
+ });
160
+ // Override cwd for Docker - workspace is always mounted at /workspace
161
+ sdkOptions.cwd = "/workspace";
162
+ // Prepare options JSON for wrapper script
163
+ const wrapperOptions = {
164
+ prompt: options.prompt,
165
+ sdkOptions,
166
+ };
167
+ // Create exec with environment variable
168
+ // Use bash login shell to get full environment including PATH
169
+ const optionsJson = JSON.stringify(wrapperOptions).replace(/'/g, "'\\''");
170
+ const command = `export HERDCTL_SDK_OPTIONS='${optionsJson}' && node /usr/local/lib/docker-sdk-wrapper.js`;
171
+ console.log("[ContainerRunner] SDK exec command:", command);
172
+ console.log("[ContainerRunner] Options JSON length:", optionsJson.length);
173
+ const exec = await container.exec({
174
+ Cmd: [
175
+ "bash",
176
+ "-l",
177
+ "-c",
178
+ command,
179
+ ],
180
+ AttachStdout: true,
181
+ AttachStderr: true,
182
+ AttachStdin: false,
183
+ Tty: false,
184
+ WorkingDir: "/workspace",
185
+ });
186
+ // Start exec and get stream
187
+ const stream = await exec.start({ hijack: true, stdin: false });
188
+ // Demultiplex stdout/stderr
189
+ const stdout = new PassThrough();
190
+ const stderr = new PassThrough();
191
+ const modem = new Dockerode().modem;
192
+ modem.demuxStream(stream, stdout, stderr);
193
+ // Collect stderr for error diagnosis
194
+ const stderrLines = [];
195
+ const stderrRl = createInterface({
196
+ input: stderr,
197
+ crlfDelay: Infinity,
198
+ });
199
+ stderrRl.on("line", (line) => {
200
+ const trimmed = line.trim();
201
+ if (trimmed) {
202
+ console.error("[ContainerRunner] SDK stderr:", trimmed);
203
+ stderrLines.push(trimmed);
204
+ }
205
+ });
206
+ // Parse stdout line-by-line as JSONL
207
+ const rl = createInterface({
208
+ input: stdout,
209
+ crlfDelay: Infinity,
210
+ });
211
+ for await (const line of rl) {
212
+ const trimmed = line.trim();
213
+ if (!trimmed)
214
+ continue;
215
+ try {
216
+ const message = JSON.parse(trimmed);
217
+ yield message;
218
+ }
219
+ catch (error) {
220
+ console.warn(`[ContainerRunner] Failed to parse SDK output: ${error instanceof Error ? error.message : String(error)}`);
221
+ }
222
+ }
223
+ // Check exec exit code
224
+ const inspectData = await exec.inspect();
225
+ const exitCode = inspectData.ExitCode ?? 0;
226
+ if (exitCode !== 0) {
227
+ const stderr = stderrLines.join("\n");
228
+ yield {
229
+ type: "error",
230
+ message: `SDK wrapper exited with code ${exitCode}${stderr ? `\n\nStderr:\n${stderr}` : ""}`,
231
+ };
232
+ }
233
+ }
234
+ }
235
+ //# sourceMappingURL=container-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-runner.js","sourceRoot":"","sources":["../../../src/runner/runtime/container-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Docker configuration types and utilities
3
+ *
4
+ * This module provides TypeScript types for Docker container configuration
5
+ * and utility functions for path mapping and container management.
6
+ */
7
+ import type { DockerInput } from "../../config/schema.js";
8
+ /**
9
+ * Network isolation modes for Docker containers
10
+ */
11
+ export type NetworkMode = "none" | "bridge" | "host";
12
+ /**
13
+ * Volume mount mode
14
+ */
15
+ export type VolumeMode = "ro" | "rw";
16
+ /**
17
+ * Path mapping between host and container
18
+ */
19
+ export interface PathMapping {
20
+ /** Absolute path on the host system */
21
+ hostPath: string;
22
+ /** Path inside the container */
23
+ containerPath: string;
24
+ /** Mount mode: read-only or read-write */
25
+ mode: VolumeMode;
26
+ }
27
+ /**
28
+ * Resolved Docker configuration with defaults applied
29
+ */
30
+ export interface DockerConfig {
31
+ /** Whether Docker is enabled */
32
+ enabled: boolean;
33
+ /** Use ephemeral containers (fresh per job) vs persistent (reuse across jobs) */
34
+ ephemeral: boolean;
35
+ /** Docker image to use */
36
+ image: string;
37
+ /** Network isolation mode */
38
+ network: NetworkMode;
39
+ /** Memory limit in bytes */
40
+ memoryBytes: number;
41
+ /** CPU shares (relative weight) */
42
+ cpuShares?: number;
43
+ /** Container user as "UID:GID" string */
44
+ user: string;
45
+ /** Maximum containers to keep per agent */
46
+ maxContainers: number;
47
+ /** Additional volume mounts */
48
+ volumes: PathMapping[];
49
+ /** Workspace mount mode */
50
+ workspaceMode: VolumeMode;
51
+ /** Environment variables to pass to the container */
52
+ env: Record<string, string>;
53
+ }
54
+ /**
55
+ * Default Docker image for Claude Code containers
56
+ *
57
+ * Users must build this image locally using the Dockerfile in the repository root:
58
+ * docker build -t herdctl/runtime:latest .
59
+ */
60
+ export declare const DEFAULT_DOCKER_IMAGE = "herdctl/runtime:latest";
61
+ /**
62
+ * Default memory limit (2GB)
63
+ */
64
+ export declare const DEFAULT_MEMORY_LIMIT = "2g";
65
+ /**
66
+ * Default max containers to keep per agent
67
+ */
68
+ export declare const DEFAULT_MAX_CONTAINERS = 5;
69
+ /**
70
+ * Parse memory string (e.g., "2g", "512m") to bytes
71
+ *
72
+ * @param memory - Memory string with unit suffix
73
+ * @returns Memory in bytes
74
+ * @throws Error if format is invalid
75
+ */
76
+ export declare function parseMemoryToBytes(memory: string): number;
77
+ /**
78
+ * Parse volume mount string to PathMapping
79
+ *
80
+ * @param volume - Volume mount string in format "host:container" or "host:container:mode"
81
+ * @returns PathMapping object
82
+ * @throws Error if format is invalid
83
+ */
84
+ export declare function parseVolumeMount(volume: string): PathMapping;
85
+ /**
86
+ * Get the current user's UID:GID for container user mapping
87
+ *
88
+ * @returns User string in "UID:GID" format
89
+ */
90
+ export declare function getHostUser(): string;
91
+ /**
92
+ * Resolve Docker config from agent configuration
93
+ *
94
+ * Applies defaults and parses string values to typed equivalents.
95
+ *
96
+ * @param docker - Docker configuration from agent config (may be partial)
97
+ * @returns Fully resolved DockerConfig
98
+ */
99
+ export declare function resolveDockerConfig(docker?: DockerInput): DockerConfig;
100
+ //# sourceMappingURL=docker-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-config.d.ts","sourceRoot":"","sources":["../../../src/runner/runtime/docker-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAU,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,gCAAgC;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,2BAA2B;IAC3B,aAAa,EAAE,UAAU,CAAC;IAC1B,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC7B;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,oBAAoB,OAAO,CAAC;AAEzC;;GAEG;AACH,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAoBzD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CAoB5D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAKpC;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,YAAY,CActE"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Docker configuration types and utilities
3
+ *
4
+ * This module provides TypeScript types for Docker container configuration
5
+ * and utility functions for path mapping and container management.
6
+ */
7
+ /**
8
+ * Default Docker image for Claude Code containers
9
+ *
10
+ * Users must build this image locally using the Dockerfile in the repository root:
11
+ * docker build -t herdctl/runtime:latest .
12
+ */
13
+ export const DEFAULT_DOCKER_IMAGE = "herdctl/runtime:latest";
14
+ /**
15
+ * Default memory limit (2GB)
16
+ */
17
+ export const DEFAULT_MEMORY_LIMIT = "2g";
18
+ /**
19
+ * Default max containers to keep per agent
20
+ */
21
+ export const DEFAULT_MAX_CONTAINERS = 5;
22
+ /**
23
+ * Parse memory string (e.g., "2g", "512m") to bytes
24
+ *
25
+ * @param memory - Memory string with unit suffix
26
+ * @returns Memory in bytes
27
+ * @throws Error if format is invalid
28
+ */
29
+ export function parseMemoryToBytes(memory) {
30
+ const match = memory.toLowerCase().match(/^(\d+(?:\.\d+)?)\s*([kmgt]?)b?$/i);
31
+ if (!match) {
32
+ throw new Error(`Invalid memory format: "${memory}". Use format like "2g", "512m", "1024k", or "2048" (bytes).`);
33
+ }
34
+ const value = parseFloat(match[1]);
35
+ const unit = match[2]?.toLowerCase() ?? "";
36
+ const multipliers = {
37
+ "": 1,
38
+ k: 1024,
39
+ m: 1024 * 1024,
40
+ g: 1024 * 1024 * 1024,
41
+ t: 1024 * 1024 * 1024 * 1024,
42
+ };
43
+ return Math.floor(value * multipliers[unit]);
44
+ }
45
+ /**
46
+ * Parse volume mount string to PathMapping
47
+ *
48
+ * @param volume - Volume mount string in format "host:container" or "host:container:mode"
49
+ * @returns PathMapping object
50
+ * @throws Error if format is invalid
51
+ */
52
+ export function parseVolumeMount(volume) {
53
+ const parts = volume.split(":");
54
+ if (parts.length < 2 || parts.length > 3) {
55
+ throw new Error(`Invalid volume format: "${volume}". Use "host:container" or "host:container:ro|rw".`);
56
+ }
57
+ const [hostPath, containerPath, modeStr] = parts;
58
+ const mode = modeStr === "ro" ? "ro" : modeStr === "rw" || !modeStr ? "rw" : "rw";
59
+ if (modeStr && modeStr !== "ro" && modeStr !== "rw") {
60
+ throw new Error(`Invalid volume mode: "${modeStr}". Use "ro" (read-only) or "rw" (read-write).`);
61
+ }
62
+ return { hostPath, containerPath, mode };
63
+ }
64
+ /**
65
+ * Get the current user's UID:GID for container user mapping
66
+ *
67
+ * @returns User string in "UID:GID" format
68
+ */
69
+ export function getHostUser() {
70
+ // process.getuid() and process.getgid() are available on POSIX systems
71
+ const uid = process.getuid?.() ?? 1000;
72
+ const gid = process.getgid?.() ?? 1000;
73
+ return `${uid}:${gid}`;
74
+ }
75
+ /**
76
+ * Resolve Docker config from agent configuration
77
+ *
78
+ * Applies defaults and parses string values to typed equivalents.
79
+ *
80
+ * @param docker - Docker configuration from agent config (may be partial)
81
+ * @returns Fully resolved DockerConfig
82
+ */
83
+ export function resolveDockerConfig(docker) {
84
+ return {
85
+ enabled: docker?.enabled ?? false,
86
+ ephemeral: docker?.ephemeral ?? true,
87
+ image: docker?.image ?? docker?.base_image ?? DEFAULT_DOCKER_IMAGE,
88
+ network: docker?.network ?? "bridge",
89
+ memoryBytes: parseMemoryToBytes(docker?.memory ?? DEFAULT_MEMORY_LIMIT),
90
+ cpuShares: docker?.cpu_shares,
91
+ user: docker?.user ?? getHostUser(),
92
+ maxContainers: docker?.max_containers ?? DEFAULT_MAX_CONTAINERS,
93
+ volumes: docker?.volumes?.map(parseVolumeMount) ?? [],
94
+ workspaceMode: docker?.workspace_mode ?? "rw",
95
+ env: docker?.env ?? {},
96
+ };
97
+ }
98
+ //# sourceMappingURL=docker-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker-config.js","sourceRoot":"","sources":["../../../src/runner/runtime/docker-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Runtime factory for creating runtime instances
3
+ *
4
+ * Creates appropriate runtime implementations based on agent configuration.
5
+ * Supports SDK runtime, CLI runtime, and optional Docker containerization.
6
+ */
7
+ import type { ResolvedAgent } from "../../config/index.js";
8
+ import type { RuntimeInterface } from "./interface.js";
9
+ /**
10
+ * Runtime type identifier
11
+ *
12
+ * - 'sdk': Claude Agent SDK runtime (default, standard pricing)
13
+ * - 'cli': Claude CLI runtime (Max plan pricing)
14
+ */
15
+ export type RuntimeType = "sdk" | "cli";
16
+ /**
17
+ * Options for runtime factory
18
+ */
19
+ export interface RuntimeFactoryOptions {
20
+ /**
21
+ * herdctl state directory (.herdctl/)
22
+ *
23
+ * Required when Docker is enabled to locate docker-sessions directory.
24
+ * If not provided, defaults to '.herdctl' in current working directory.
25
+ */
26
+ stateDir?: string;
27
+ }
28
+ /**
29
+ * Runtime factory for creating runtime instances
30
+ *
31
+ * This factory creates the appropriate runtime implementation based on
32
+ * agent configuration. It provides a centralized point for runtime
33
+ * instantiation and validation.
34
+ *
35
+ * When docker.enabled is true, the base runtime is wrapped with
36
+ * ContainerRunner for Docker containerization.
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * // SDK runtime (default)
41
+ * const runtime = RuntimeFactory.create(resolvedAgent);
42
+ *
43
+ * // CLI runtime with Docker
44
+ * const dockerRuntime = RuntimeFactory.create(dockerAgent, {
45
+ * stateDir: '/path/to/.herdctl'
46
+ * });
47
+ * ```
48
+ */
49
+ export declare class RuntimeFactory {
50
+ /**
51
+ * Create a runtime instance based on agent configuration
52
+ *
53
+ * Determines the runtime type from agent.runtime (defaults to 'sdk')
54
+ * and wraps with ContainerRunner if agent.docker.enabled is true.
55
+ *
56
+ * @param agent - Resolved agent configuration
57
+ * @param options - Factory options including stateDir for Docker
58
+ * @returns Runtime implementation (possibly wrapped with ContainerRunner)
59
+ * @throws Error if runtime type is unsupported or invalid
60
+ */
61
+ static create(agent: ResolvedAgent, options?: RuntimeFactoryOptions): RuntimeInterface;
62
+ }
63
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/runner/runtime/factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAMvD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,KAAK,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,cAAc;IACzB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,CACX,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,qBAA0B,GAClC,gBAAgB;CAgCpB"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Runtime factory for creating runtime instances
3
+ *
4
+ * Creates appropriate runtime implementations based on agent configuration.
5
+ * Supports SDK runtime, CLI runtime, and optional Docker containerization.
6
+ */
7
+ import { SDKRuntime } from "./sdk-runtime.js";
8
+ import { CLIRuntime } from "./cli-runtime.js";
9
+ import { ContainerRunner } from "./container-runner.js";
10
+ import { resolveDockerConfig } from "./docker-config.js";
11
+ /**
12
+ * Runtime factory for creating runtime instances
13
+ *
14
+ * This factory creates the appropriate runtime implementation based on
15
+ * agent configuration. It provides a centralized point for runtime
16
+ * instantiation and validation.
17
+ *
18
+ * When docker.enabled is true, the base runtime is wrapped with
19
+ * ContainerRunner for Docker containerization.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // SDK runtime (default)
24
+ * const runtime = RuntimeFactory.create(resolvedAgent);
25
+ *
26
+ * // CLI runtime with Docker
27
+ * const dockerRuntime = RuntimeFactory.create(dockerAgent, {
28
+ * stateDir: '/path/to/.herdctl'
29
+ * });
30
+ * ```
31
+ */
32
+ export class RuntimeFactory {
33
+ /**
34
+ * Create a runtime instance based on agent configuration
35
+ *
36
+ * Determines the runtime type from agent.runtime (defaults to 'sdk')
37
+ * and wraps with ContainerRunner if agent.docker.enabled is true.
38
+ *
39
+ * @param agent - Resolved agent configuration
40
+ * @param options - Factory options including stateDir for Docker
41
+ * @returns Runtime implementation (possibly wrapped with ContainerRunner)
42
+ * @throws Error if runtime type is unsupported or invalid
43
+ */
44
+ static create(agent, options = {}) {
45
+ // Determine runtime type from agent config (default to SDK)
46
+ const runtimeType = agent.runtime ?? "sdk";
47
+ let runtime;
48
+ switch (runtimeType) {
49
+ case "sdk":
50
+ runtime = new SDKRuntime();
51
+ break;
52
+ case "cli":
53
+ runtime = new CLIRuntime();
54
+ break;
55
+ default:
56
+ throw new Error(`Unknown runtime type: ${runtimeType}. ` +
57
+ "Supported types: 'sdk' (default), 'cli'");
58
+ }
59
+ // Wrap with ContainerRunner if Docker is enabled
60
+ if (agent.docker?.enabled) {
61
+ const dockerConfig = resolveDockerConfig(agent.docker);
62
+ const stateDir = options.stateDir ?? process.cwd() + "/.herdctl";
63
+ runtime = new ContainerRunner(runtime, dockerConfig, stateDir);
64
+ }
65
+ return runtime;
66
+ }
67
+ }
68
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../src/runner/runtime/factory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAuBzD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,cAAc;IACzB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,CACX,KAAoB,EACpB,UAAiC,EAAE;QAEnC,4DAA4D;QAC5D,MAAM,WAAW,GAAiB,KAAK,CAAC,OAAuB,IAAI,KAAK,CAAC;QAEzE,IAAI,OAAyB,CAAC;QAE9B,QAAQ,WAAW,EAAE,CAAC;YACpB,KAAK,KAAK;gBACR,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC3B,MAAM;YAER,KAAK,KAAK;gBACR,OAAO,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC3B,MAAM;YAER;gBACE,MAAM,IAAI,KAAK,CACb,yBAAyB,WAAW,IAAI;oBACtC,yCAAyC,CAC5C,CAAC;QACN,CAAC;QAED,iDAAiD;QACjD,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC1B,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC;YAEjE,OAAO,GAAG,IAAI,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;QACjE,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Runtime module barrel export
3
+ *
4
+ * Exports all public runtime types and classes for easy importing:
5
+ * - RuntimeInterface and RuntimeExecuteOptions types
6
+ * - SDKRuntime and CLIRuntime implementations
7
+ * - RuntimeFactory for runtime instantiation
8
+ * - RuntimeType for type identification
9
+ * - CLI session path utilities
10
+ */
11
+ export type { RuntimeInterface, RuntimeExecuteOptions } from "./interface.js";
12
+ export { SDKRuntime } from "./sdk-runtime.js";
13
+ export { CLIRuntime } from "./cli-runtime.js";
14
+ export { RuntimeFactory, type RuntimeType } from "./factory.js";
15
+ export { encodePathForCli, getCliSessionDir, getCliSessionFile, } from "./cli-session-path.js";
16
+ export { CLISessionWatcher, watchSessionFile, } from "./cli-session-watcher.js";
17
+ export { type DockerConfig, type PathMapping, type NetworkMode, type VolumeMode, parseMemoryToBytes, parseVolumeMount, getHostUser, resolveDockerConfig, DEFAULT_DOCKER_IMAGE, DEFAULT_MEMORY_LIMIT, DEFAULT_MAX_CONTAINERS, } from "./docker-config.js";
18
+ export { ContainerRunner } from "./container-runner.js";
19
+ export { ContainerManager, buildContainerMounts, buildContainerEnv, } from "./container-manager.js";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runner/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Runtime module barrel export
3
+ *
4
+ * Exports all public runtime types and classes for easy importing:
5
+ * - RuntimeInterface and RuntimeExecuteOptions types
6
+ * - SDKRuntime and CLIRuntime implementations
7
+ * - RuntimeFactory for runtime instantiation
8
+ * - RuntimeType for type identification
9
+ * - CLI session path utilities
10
+ */
11
+ export { SDKRuntime } from "./sdk-runtime.js";
12
+ export { CLIRuntime } from "./cli-runtime.js";
13
+ export { RuntimeFactory } from "./factory.js";
14
+ export { encodePathForCli, getCliSessionDir, getCliSessionFile, } from "./cli-session-path.js";
15
+ export { CLISessionWatcher, watchSessionFile, } from "./cli-session-watcher.js";
16
+ // Docker configuration
17
+ export { parseMemoryToBytes, parseVolumeMount, getHostUser, resolveDockerConfig, DEFAULT_DOCKER_IMAGE, DEFAULT_MEMORY_LIMIT, DEFAULT_MAX_CONTAINERS, } from "./docker-config.js";
18
+ // Container execution
19
+ export { ContainerRunner } from "./container-runner.js";
20
+ export { ContainerManager, buildContainerMounts, buildContainerEnv, } from "./container-manager.js";
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runner/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAoB,MAAM,cAAc,CAAC;AAChE,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAElC,uBAAuB;AACvB,OAAO,EAKL,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAE5B,sBAAsB;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC"}