@clawmasons/mason 0.1.1 → 0.1.2
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/dist/acp/bridge.d.ts +92 -0
- package/dist/acp/bridge.d.ts.map +1 -0
- package/dist/acp/bridge.js +266 -0
- package/dist/acp/bridge.js.map +1 -0
- package/dist/acp/logger.d.ts +18 -0
- package/dist/acp/logger.d.ts.map +1 -0
- package/dist/acp/logger.js +35 -0
- package/dist/acp/logger.js.map +1 -0
- package/dist/acp/matcher.d.ts +60 -0
- package/dist/acp/matcher.d.ts.map +1 -0
- package/dist/acp/matcher.js +101 -0
- package/dist/acp/matcher.js.map +1 -0
- package/dist/acp/rewriter.d.ts +35 -0
- package/dist/acp/rewriter.d.ts.map +1 -0
- package/dist/acp/rewriter.js +46 -0
- package/dist/acp/rewriter.js.map +1 -0
- package/dist/acp/session.d.ts +202 -0
- package/dist/acp/session.d.ts.map +1 -0
- package/dist/acp/session.js +444 -0
- package/dist/acp/session.js.map +1 -0
- package/dist/acp/warnings.d.ts +24 -0
- package/dist/acp/warnings.d.ts.map +1 -0
- package/dist/acp/warnings.js +32 -0
- package/dist/acp/warnings.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +4 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/build.d.ts +22 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +107 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/docker-utils.d.ts +16 -0
- package/dist/cli/commands/docker-utils.d.ts.map +1 -0
- package/dist/cli/commands/docker-utils.js +54 -0
- package/dist/cli/commands/docker-utils.js.map +1 -0
- package/dist/cli/commands/index.d.ts +11 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +89 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/list.d.ts +8 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +60 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/package.d.ts +15 -0
- package/dist/cli/commands/package.d.ts.map +1 -0
- package/dist/cli/commands/package.js +241 -0
- package/dist/cli/commands/package.js.map +1 -0
- package/dist/cli/commands/permissions.d.ts +8 -0
- package/dist/cli/commands/permissions.d.ts.map +1 -0
- package/dist/cli/commands/permissions.js +60 -0
- package/dist/cli/commands/permissions.js.map +1 -0
- package/dist/cli/commands/proxy.d.ts +12 -0
- package/dist/cli/commands/proxy.d.ts.map +1 -0
- package/dist/cli/commands/proxy.js +253 -0
- package/dist/cli/commands/proxy.js.map +1 -0
- package/dist/cli/commands/run-agent.d.ts +149 -0
- package/dist/cli/commands/run-agent.d.ts.map +1 -0
- package/dist/cli/commands/run-agent.js +1072 -0
- package/dist/cli/commands/run-agent.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +10 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +138 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +18 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/proxy-entry.d.ts +8 -0
- package/dist/cli/proxy-entry.d.ts.map +1 -0
- package/dist/cli/proxy-entry.js +25 -0
- package/dist/cli/proxy-entry.js.map +1 -0
- package/dist/generator/agent-dockerfile.d.ts +38 -0
- package/dist/generator/agent-dockerfile.d.ts.map +1 -0
- package/dist/generator/agent-dockerfile.js +120 -0
- package/dist/generator/agent-dockerfile.js.map +1 -0
- package/dist/generator/credential-service-dockerfile.d.ts +14 -0
- package/dist/generator/credential-service-dockerfile.d.ts.map +1 -0
- package/dist/generator/credential-service-dockerfile.js +44 -0
- package/dist/generator/credential-service-dockerfile.js.map +1 -0
- package/dist/generator/index.d.ts +6 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +6 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/mount-volumes.d.ts +30 -0
- package/dist/generator/mount-volumes.d.ts.map +1 -0
- package/dist/generator/mount-volumes.js +39 -0
- package/dist/generator/mount-volumes.js.map +1 -0
- package/dist/generator/proxy-dockerfile.d.ts +19 -0
- package/dist/generator/proxy-dockerfile.d.ts.map +1 -0
- package/dist/generator/proxy-dockerfile.js +59 -0
- package/dist/generator/proxy-dockerfile.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/materializer/common.d.ts +17 -0
- package/dist/materializer/common.d.ts.map +1 -0
- package/dist/materializer/common.js +37 -0
- package/dist/materializer/common.js.map +1 -0
- package/dist/materializer/docker-generator.d.ts +258 -0
- package/dist/materializer/docker-generator.d.ts.map +1 -0
- package/dist/materializer/docker-generator.js +529 -0
- package/dist/materializer/docker-generator.js.map +1 -0
- package/dist/materializer/index.d.ts +9 -0
- package/dist/materializer/index.d.ts.map +1 -0
- package/dist/materializer/index.js +7 -0
- package/dist/materializer/index.js.map +1 -0
- package/dist/materializer/proxy-dependencies.d.ts +43 -0
- package/dist/materializer/proxy-dependencies.d.ts.map +1 -0
- package/dist/materializer/proxy-dependencies.js +452 -0
- package/dist/materializer/proxy-dependencies.js.map +1 -0
- package/dist/materializer/role-materializer.d.ts +56 -0
- package/dist/materializer/role-materializer.d.ts.map +1 -0
- package/dist/materializer/role-materializer.js +119 -0
- package/dist/materializer/role-materializer.js.map +1 -0
- package/dist/materializer/types.d.ts +2 -0
- package/dist/materializer/types.d.ts.map +1 -0
- package/dist/materializer/types.js +2 -0
- package/dist/materializer/types.js.map +1 -0
- package/dist/resolver/discover.d.ts +7 -0
- package/dist/resolver/discover.d.ts.map +1 -0
- package/dist/resolver/discover.js +102 -0
- package/dist/resolver/discover.js.map +1 -0
- package/dist/resolver/errors.d.ts +35 -0
- package/dist/resolver/errors.d.ts.map +1 -0
- package/dist/resolver/errors.js +62 -0
- package/dist/resolver/errors.js.map +1 -0
- package/dist/resolver/index.d.ts +5 -0
- package/dist/resolver/index.d.ts.map +1 -0
- package/dist/resolver/index.js +4 -0
- package/dist/resolver/index.js.map +1 -0
- package/dist/resolver/resolve.d.ts +8 -0
- package/dist/resolver/resolve.d.ts.map +1 -0
- package/dist/resolver/resolve.js +177 -0
- package/dist/resolver/resolve.js.map +1 -0
- package/dist/runtime/gitignore.d.ts +16 -0
- package/dist/runtime/gitignore.d.ts.map +1 -0
- package/dist/runtime/gitignore.js +37 -0
- package/dist/runtime/gitignore.js.map +1 -0
- package/dist/validator/index.d.ts +3 -0
- package/dist/validator/index.d.ts.map +1 -0
- package/dist/validator/index.js +2 -0
- package/dist/validator/index.js.map +1 -0
- package/dist/validator/types.d.ts +48 -0
- package/dist/validator/types.d.ts.map +1 -0
- package/dist/validator/types.js +2 -0
- package/dist/validator/types.js.map +1 -0
- package/dist/validator/validate.d.ts +8 -0
- package/dist/validator/validate.d.ts.map +1 -0
- package/dist/validator/validate.js +217 -0
- package/dist/validator/validate.js.map +1 -0
- package/package.json +10 -9
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role-centric Docker build directory and session generation.
|
|
3
|
+
*
|
|
4
|
+
* Generates:
|
|
5
|
+
* 1. Docker build directories at `.mason/docker/<role-name>/` (PRD §7.1)
|
|
6
|
+
* 2. Volume masking for container.ignore.paths (PRD §7.3)
|
|
7
|
+
* 3. Sentinel empty file for file-level volume masking
|
|
8
|
+
* 4. Session directories with self-contained compose files (PRD §7.5)
|
|
9
|
+
*
|
|
10
|
+
* @module docker-generator
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from "node:fs";
|
|
13
|
+
import * as path from "node:path";
|
|
14
|
+
import * as crypto from "node:crypto";
|
|
15
|
+
import * as os from "node:os";
|
|
16
|
+
import { getAppShortName } from "@clawmasons/shared";
|
|
17
|
+
import { materializeForAgent, getMaterializer, getAgentFromRegistry } from "./role-materializer.js";
|
|
18
|
+
import { generateAgentDockerfile } from "../generator/agent-dockerfile.js";
|
|
19
|
+
import { generateProxyDockerfile } from "../generator/proxy-dockerfile.js";
|
|
20
|
+
import { adaptRoleToResolvedAgent } from "@clawmasons/shared";
|
|
21
|
+
import { resolveRoleMountVolumes } from "../generator/mount-volumes.js";
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Constants
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/** Path to sentinel empty file relative to project root. */
|
|
26
|
+
const SENTINEL_RELATIVE_PATH = ".mason/empty-file";
|
|
27
|
+
/** Container path where the project is mounted read-only. */
|
|
28
|
+
const PROJECT_MOUNT_PATH = "/home/mason/workspace/project";
|
|
29
|
+
/**
|
|
30
|
+
* Get the current host user's UID and GID.
|
|
31
|
+
* Returns string values suitable for Docker build args.
|
|
32
|
+
*/
|
|
33
|
+
export function getHostIds() {
|
|
34
|
+
const info = os.userInfo();
|
|
35
|
+
return { uid: String(info.uid), gid: String(info.gid) };
|
|
36
|
+
}
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Volume Masking
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
/**
|
|
41
|
+
* Sanitize a path into a valid Docker volume name.
|
|
42
|
+
*
|
|
43
|
+
* Replaces non-alphanumeric characters with hyphens, strips leading/trailing
|
|
44
|
+
* hyphens, and prefixes with "ignore-".
|
|
45
|
+
*/
|
|
46
|
+
export function sanitizeVolumeName(ignorePath) {
|
|
47
|
+
const cleaned = ignorePath
|
|
48
|
+
.replace(/[/\\]/g, "-")
|
|
49
|
+
.replace(/\./g, "")
|
|
50
|
+
.replace(/[^a-zA-Z0-9-]/g, "-")
|
|
51
|
+
.replace(/-+/g, "-")
|
|
52
|
+
.replace(/^-|-$/g, "");
|
|
53
|
+
return `ignore-${cleaned}`;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Sanitize a file entry name into a Docker Compose config name.
|
|
57
|
+
*
|
|
58
|
+
* E.g. `.mcp.json` → `overlay-mcp-json`, `AGENTS.md` → `overlay-agents-md`.
|
|
59
|
+
*/
|
|
60
|
+
function sanitizeOverlayConfigName(entry) {
|
|
61
|
+
const cleaned = entry
|
|
62
|
+
.toLowerCase()
|
|
63
|
+
.replace(/[/\\]/g, "-")
|
|
64
|
+
.replace(/\./g, "-")
|
|
65
|
+
.replace(/[^a-zA-Z0-9-]/g, "-")
|
|
66
|
+
.replace(/-+/g, "-")
|
|
67
|
+
.replace(/^-|-$/g, "");
|
|
68
|
+
return `overlay-${cleaned}`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Sanitize a file mask path into a Docker Compose config name.
|
|
72
|
+
*
|
|
73
|
+
* E.g. `.env` → `mask-env`, `.env.local` → `mask-env-local`.
|
|
74
|
+
*/
|
|
75
|
+
function sanitizeMaskConfigName(entry) {
|
|
76
|
+
const cleaned = entry
|
|
77
|
+
.toLowerCase()
|
|
78
|
+
.replace(/[/\\]/g, "-")
|
|
79
|
+
.replace(/\./g, "-")
|
|
80
|
+
.replace(/[^a-zA-Z0-9-]/g, "-")
|
|
81
|
+
.replace(/-+/g, "-")
|
|
82
|
+
.replace(/^-|-$/g, "");
|
|
83
|
+
return `mask-${cleaned}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Classify ignore paths and generate volume mask entries.
|
|
87
|
+
*
|
|
88
|
+
* - Paths ending with `/` are classified as directories (masked with named empty volumes).
|
|
89
|
+
* - Paths without trailing `/` are classified as files (masked with bind mount of sentinel file).
|
|
90
|
+
*
|
|
91
|
+
* All container paths target the project mount at `/home/mason/workspace/project/`.
|
|
92
|
+
*
|
|
93
|
+
* @param ignorePaths - Array of paths from container.ignore.paths
|
|
94
|
+
* @returns Array of VolumeMaskEntry objects
|
|
95
|
+
*/
|
|
96
|
+
export function generateVolumeMasks(ignorePaths) {
|
|
97
|
+
return ignorePaths.map((p) => {
|
|
98
|
+
const isDirectory = p.endsWith("/");
|
|
99
|
+
const cleanPath = p.replace(/\/+$/, ""); // strip trailing slash for path building
|
|
100
|
+
const containerPath = `${PROJECT_MOUNT_PATH}/${cleanPath}`;
|
|
101
|
+
if (isDirectory) {
|
|
102
|
+
return {
|
|
103
|
+
type: "directory",
|
|
104
|
+
hostPath: p,
|
|
105
|
+
containerPath,
|
|
106
|
+
volumeName: sanitizeVolumeName(cleanPath),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
return {
|
|
111
|
+
type: "file",
|
|
112
|
+
hostPath: p,
|
|
113
|
+
containerPath,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Sentinel File
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
/**
|
|
122
|
+
* Ensure the sentinel empty file exists at `.mason/empty-file`.
|
|
123
|
+
*
|
|
124
|
+
* The file is 0 bytes with permissions `0o444` (read-only for all).
|
|
125
|
+
* Idempotent — does nothing if the file already exists.
|
|
126
|
+
*
|
|
127
|
+
* @param projectDir - Absolute path to the project root
|
|
128
|
+
* @returns Absolute path to the sentinel file
|
|
129
|
+
*/
|
|
130
|
+
export function ensureSentinelFile(projectDir, fsDeps) {
|
|
131
|
+
const deps = {
|
|
132
|
+
existsSync: fsDeps?.existsSync ?? fs.existsSync,
|
|
133
|
+
mkdirSync: fsDeps?.mkdirSync ?? fs.mkdirSync,
|
|
134
|
+
writeFileSync: fsDeps?.writeFileSync ?? fs.writeFileSync,
|
|
135
|
+
chmodSync: fsDeps?.chmodSync ?? fs.chmodSync,
|
|
136
|
+
};
|
|
137
|
+
const sentinelPath = path.join(projectDir, SENTINEL_RELATIVE_PATH);
|
|
138
|
+
if (!deps.existsSync(sentinelPath)) {
|
|
139
|
+
deps.mkdirSync(path.dirname(sentinelPath), { recursive: true });
|
|
140
|
+
deps.writeFileSync(sentinelPath, "", { mode: 0o444 });
|
|
141
|
+
deps.chmodSync(sentinelPath, 0o444);
|
|
142
|
+
}
|
|
143
|
+
return sentinelPath;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Generate the role-centric Docker build directory at
|
|
147
|
+
* `.mason/docker/<role-name>/`.
|
|
148
|
+
*
|
|
149
|
+
* Structure (PRD §7.1):
|
|
150
|
+
* ```
|
|
151
|
+
* <role-name>/
|
|
152
|
+
* ├── <agent-type>/
|
|
153
|
+
* │ ├── Dockerfile
|
|
154
|
+
* │ └── workspace/
|
|
155
|
+
* │ └── (materialized files)
|
|
156
|
+
* ├── mcp-proxy/
|
|
157
|
+
* │ └── Dockerfile
|
|
158
|
+
* └── docker-compose.yaml
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
export function generateRoleDockerBuildDir(opts, fsDeps) {
|
|
162
|
+
const deps = {
|
|
163
|
+
mkdirSync: fsDeps?.mkdirSync ?? fs.mkdirSync,
|
|
164
|
+
writeFileSync: fsDeps?.writeFileSync ?? fs.writeFileSync,
|
|
165
|
+
};
|
|
166
|
+
const { role, agentType, projectDir, agentName, proxyEndpoint } = opts;
|
|
167
|
+
const roleName = getAppShortName(role.metadata.name);
|
|
168
|
+
const buildRoot = opts.dockerBuildRoot ?? path.join(projectDir, ".mason", "docker");
|
|
169
|
+
const buildDir = path.join(buildRoot, roleName);
|
|
170
|
+
// --- Agent subdirectory ---
|
|
171
|
+
const agentDir = path.join(buildDir, agentType);
|
|
172
|
+
deps.mkdirSync(agentDir, { recursive: true });
|
|
173
|
+
// Home directory materialization (if the materializer supports it)
|
|
174
|
+
// Skip when fsDeps is provided (test mode) since materializeHome uses real fs
|
|
175
|
+
const materializer = getMaterializer(agentType);
|
|
176
|
+
let hasHome = false;
|
|
177
|
+
if (!fsDeps && materializer?.materializeHome) {
|
|
178
|
+
const homePath = path.join(agentDir, "home");
|
|
179
|
+
materializer.materializeHome(projectDir, homePath);
|
|
180
|
+
hasHome = true;
|
|
181
|
+
}
|
|
182
|
+
// Agent Dockerfile
|
|
183
|
+
const resolvedAgent = adaptRoleToResolvedAgent(role, agentType);
|
|
184
|
+
const agentRole = resolvedAgent.roles[0];
|
|
185
|
+
if (!agentRole) {
|
|
186
|
+
throw new Error(`adaptRoleToResolvedAgent produced no roles for "${role.metadata.name}"`);
|
|
187
|
+
}
|
|
188
|
+
const isSupervisor = role.type === "supervisor";
|
|
189
|
+
const agentPkg = getAgentFromRegistry(agentType);
|
|
190
|
+
const agentDockerfile = generateAgentDockerfile(resolvedAgent, agentRole, {
|
|
191
|
+
hasHome: hasHome || isSupervisor,
|
|
192
|
+
dockerfileConfig: agentPkg?.dockerfile,
|
|
193
|
+
devContainerCustomizations: opts.devContainerCustomizations,
|
|
194
|
+
roleType: role.type,
|
|
195
|
+
});
|
|
196
|
+
deps.writeFileSync(path.join(agentDir, "Dockerfile"), agentDockerfile);
|
|
197
|
+
// Workspace files — split into output buckets:
|
|
198
|
+
// File routing:
|
|
199
|
+
// - agent-launch.json → {agentDir}/workspace/ (live-mounted to /home/mason/workspace/)
|
|
200
|
+
// - .mcp.json (supervisor) → {agentDir}/workspace/ (Claude Code reads from WORKDIR = /home/mason/workspace)
|
|
201
|
+
// - project role: everything else → {agentDir}/build/workspace/project/ (per-file overlay mounts)
|
|
202
|
+
// - supervisor role: everything else → {agentDir}/home/ (merged into home mount at /home/mason/)
|
|
203
|
+
const proxyEp = proxyEndpoint ?? `http://proxy-${roleName}:9090`;
|
|
204
|
+
const materializeOpts = (opts.agentConfigCredentials?.length || opts.agentArgs?.length)
|
|
205
|
+
? {
|
|
206
|
+
...(opts.agentConfigCredentials?.length ? { agentConfigCredentials: opts.agentConfigCredentials } : {}),
|
|
207
|
+
...(opts.agentArgs?.length ? { agentArgs: opts.agentArgs } : {}),
|
|
208
|
+
}
|
|
209
|
+
: undefined;
|
|
210
|
+
const workspace = (isSupervisor && materializer?.materializeSupervisor)
|
|
211
|
+
? materializer.materializeSupervisor(resolvedAgent, proxyEp, undefined, materializeOpts, !fsDeps ? path.join(agentDir, "home") : undefined)
|
|
212
|
+
: materializeForAgent(role, agentType, proxyEp, undefined, materializeOpts);
|
|
213
|
+
const workspaceDir = path.join(agentDir, "workspace");
|
|
214
|
+
const buildWorkspaceProjectDir = path.join(agentDir, "build", "workspace", "project");
|
|
215
|
+
const homeBuildDir = path.join(agentDir, "home");
|
|
216
|
+
for (const [filePath, content] of workspace) {
|
|
217
|
+
const targetDir = filePath === "agent-launch.json"
|
|
218
|
+
? workspaceDir
|
|
219
|
+
: isSupervisor ? homeBuildDir : buildWorkspaceProjectDir;
|
|
220
|
+
const fullPath = path.join(targetDir, filePath);
|
|
221
|
+
deps.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
222
|
+
deps.writeFileSync(fullPath, content);
|
|
223
|
+
}
|
|
224
|
+
// --- MCP Proxy subdirectory ---
|
|
225
|
+
const proxyDir = path.join(buildDir, "mcp-proxy");
|
|
226
|
+
deps.mkdirSync(proxyDir, { recursive: true });
|
|
227
|
+
const proxyDockerfile = generateProxyDockerfile(agentRole, agentName);
|
|
228
|
+
deps.writeFileSync(path.join(proxyDir, "Dockerfile"), proxyDockerfile);
|
|
229
|
+
// --- Reference docker-compose.yaml ---
|
|
230
|
+
const refCompose = generateReferenceBuildCompose(roleName, agentType);
|
|
231
|
+
deps.writeFileSync(path.join(buildDir, "docker-compose.yaml"), refCompose);
|
|
232
|
+
return {
|
|
233
|
+
buildDir,
|
|
234
|
+
agentDockerfilePath: `${agentType}/Dockerfile`,
|
|
235
|
+
proxyDockerfilePath: "mcp-proxy/Dockerfile",
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Generate a reference docker-compose.yaml for the build directory.
|
|
240
|
+
* This is informational — the runnable compose file lives in the session dir.
|
|
241
|
+
*/
|
|
242
|
+
function generateReferenceBuildCompose(roleName, agentType) {
|
|
243
|
+
return `# Reference docker-compose for role: ${roleName}
|
|
244
|
+
# This is for reference only. Runnable compose files are in session directories.
|
|
245
|
+
# See .mason/sessions/<session-id>/docker-compose.yaml
|
|
246
|
+
services:
|
|
247
|
+
proxy-${roleName}:
|
|
248
|
+
build:
|
|
249
|
+
context: ../../../docker
|
|
250
|
+
dockerfile: ../docker/${roleName}/mcp-proxy/Dockerfile
|
|
251
|
+
environment:
|
|
252
|
+
- CHAPTER_PROXY_TOKEN=\${CHAPTER_PROXY_TOKEN}
|
|
253
|
+
- CREDENTIAL_PROXY_TOKEN=\${CREDENTIAL_PROXY_TOKEN}
|
|
254
|
+
ports:
|
|
255
|
+
- "9090:9090"
|
|
256
|
+
|
|
257
|
+
agent-${roleName}:
|
|
258
|
+
build:
|
|
259
|
+
context: ..
|
|
260
|
+
dockerfile: ${roleName}/${agentType}/Dockerfile
|
|
261
|
+
depends_on:
|
|
262
|
+
- proxy-${roleName}
|
|
263
|
+
environment:
|
|
264
|
+
- MCP_PROXY_TOKEN=\${CHAPTER_PROXY_TOKEN}
|
|
265
|
+
`;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Generate a self-contained docker-compose.yaml for a session directory.
|
|
269
|
+
*
|
|
270
|
+
* All paths are relative to the session directory, making the session dir
|
|
271
|
+
* a fully functional Docker Compose project. Users can run:
|
|
272
|
+
* - `docker compose logs -f`
|
|
273
|
+
* - `docker compose ps`
|
|
274
|
+
* - `docker compose exec agent sh`
|
|
275
|
+
* - `docker compose down`
|
|
276
|
+
*
|
|
277
|
+
* from the session directory.
|
|
278
|
+
*/
|
|
279
|
+
export function generateSessionComposeYml(opts) {
|
|
280
|
+
const { projectDir, dockerBuildDir, dockerDir, roleName, agentType, proxyToken, credentialProxyToken, proxyPort = 9090, volumeMasks = [], roleMounts, credentialKeys, sessionType, acpCommand, sessionDir, logsDir, homePath, hostUid, hostGid, workspacePath, buildWorkspaceProjectPath, buildWorkspaceProjectFileEntries = [], buildWorkspaceProjectDirEntries = [], homeOverride, vscodeServerHostPath, bashMode, verbose, } = opts;
|
|
281
|
+
// Unique compose project name derived from project directory
|
|
282
|
+
const projectHash = crypto.createHash("sha256").update(projectDir).digest("hex").slice(0, 8);
|
|
283
|
+
const composeName = `mason-${projectHash}`;
|
|
284
|
+
// Compute relative paths from session directory.
|
|
285
|
+
// Prefix with ./ so Docker Compose treats them as bind mounts (not named volumes).
|
|
286
|
+
const rel = (to) => {
|
|
287
|
+
const r = path.relative(sessionDir, to);
|
|
288
|
+
return r.startsWith(".") ? r : `./${r}`;
|
|
289
|
+
};
|
|
290
|
+
const relDockerDir = rel(dockerDir);
|
|
291
|
+
const relProjectDir = rel(projectDir);
|
|
292
|
+
const relLogsDir = rel(logsDir);
|
|
293
|
+
const relSentinel = rel(path.join(projectDir, SENTINEL_RELATIVE_PATH));
|
|
294
|
+
const proxyServiceName = `proxy-${roleName}`;
|
|
295
|
+
const agentServiceName = `agent-${roleName}`;
|
|
296
|
+
// --- Proxy service ---
|
|
297
|
+
const proxyEnvLines = [
|
|
298
|
+
` - CHAPTER_PROXY_TOKEN=${proxyToken}`,
|
|
299
|
+
` - CREDENTIAL_PROXY_TOKEN=${credentialProxyToken}`,
|
|
300
|
+
` - PROJECT_DIR=${PROJECT_MOUNT_PATH}`,
|
|
301
|
+
];
|
|
302
|
+
if (sessionType) {
|
|
303
|
+
proxyEnvLines.push(` - CHAPTER_SESSION_TYPE=${sessionType}`);
|
|
304
|
+
}
|
|
305
|
+
if (credentialKeys && credentialKeys.length > 0) {
|
|
306
|
+
proxyEnvLines.push(` - CHAPTER_DECLARED_CREDENTIALS=${JSON.stringify(credentialKeys)}`);
|
|
307
|
+
}
|
|
308
|
+
// --- Agent volumes ---
|
|
309
|
+
const agentVolumeLines = [];
|
|
310
|
+
// Home override (user-specified --home path, before other mounts)
|
|
311
|
+
if (homeOverride) {
|
|
312
|
+
const relHomeOverride = rel(homeOverride);
|
|
313
|
+
agentVolumeLines.push(` - ${relHomeOverride}:/home/mason/`);
|
|
314
|
+
}
|
|
315
|
+
// Project mount (no :ro — agents need write access)
|
|
316
|
+
agentVolumeLines.push(` - ${relProjectDir}:${PROJECT_MOUNT_PATH}`);
|
|
317
|
+
// Volume masks: directories only (named volumes); file masks routed through configs below
|
|
318
|
+
for (const mask of volumeMasks) {
|
|
319
|
+
if (mask.type === "directory") {
|
|
320
|
+
agentVolumeLines.push(` - ${mask.volumeName}:${mask.containerPath}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// Role-declared extra mounts
|
|
324
|
+
for (const vol of resolveRoleMountVolumes(roleMounts)) {
|
|
325
|
+
agentVolumeLines.push(` - ${vol}`);
|
|
326
|
+
}
|
|
327
|
+
// Logs dir mount
|
|
328
|
+
agentVolumeLines.push(` - ${relLogsDir}:/logs`);
|
|
329
|
+
// Workspace directory mount (live bind mount for agent-launch.json)
|
|
330
|
+
if (workspacePath) {
|
|
331
|
+
const relWorkspacePath = rel(workspacePath);
|
|
332
|
+
agentVolumeLines.push(` - ${relWorkspacePath}:/home/mason/workspace`);
|
|
333
|
+
}
|
|
334
|
+
// Directory overlay mounts (bind mounts — VirtioFS-safe for directories)
|
|
335
|
+
if (buildWorkspaceProjectPath && buildWorkspaceProjectDirEntries.length > 0) {
|
|
336
|
+
for (const entry of buildWorkspaceProjectDirEntries) {
|
|
337
|
+
const hostEntryPath = path.join(buildWorkspaceProjectPath, entry);
|
|
338
|
+
const relEntryPath = rel(hostEntryPath);
|
|
339
|
+
agentVolumeLines.push(` - ${relEntryPath}:/home/mason/workspace/project/${entry}`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// VS Code server persistent mount (dev-container mode)
|
|
343
|
+
if (vscodeServerHostPath) {
|
|
344
|
+
const relVscodePath = rel(vscodeServerHostPath);
|
|
345
|
+
agentVolumeLines.push(` - ${relVscodePath}:/home/mason/.vscode-server`);
|
|
346
|
+
}
|
|
347
|
+
// Home directory mount (materialized host config from build dir)
|
|
348
|
+
if (homePath) {
|
|
349
|
+
const relHomePath = rel(homePath);
|
|
350
|
+
agentVolumeLines.push(` - ${relHomePath}:/home/mason`);
|
|
351
|
+
}
|
|
352
|
+
// --- File overlay & mask configs (Docker Compose configs — mounted as tmpfs, VirtioFS-safe) ---
|
|
353
|
+
const configEntries = [];
|
|
354
|
+
// Overlay file configs (materialized workspace files)
|
|
355
|
+
if (buildWorkspaceProjectPath && buildWorkspaceProjectFileEntries.length > 0) {
|
|
356
|
+
for (const entry of buildWorkspaceProjectFileEntries) {
|
|
357
|
+
configEntries.push({
|
|
358
|
+
name: sanitizeOverlayConfigName(entry),
|
|
359
|
+
relPath: rel(path.join(buildWorkspaceProjectPath, entry)),
|
|
360
|
+
target: `/home/mason/workspace/project/${entry}`,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
// File mask configs (sentinel empty file → container path, VirtioFS-safe)
|
|
365
|
+
for (const mask of volumeMasks) {
|
|
366
|
+
if (mask.type === "file") {
|
|
367
|
+
configEntries.push({
|
|
368
|
+
name: sanitizeMaskConfigName(mask.hostPath),
|
|
369
|
+
relPath: relSentinel,
|
|
370
|
+
target: mask.containerPath,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const serviceConfigsBlock = configEntries.length > 0
|
|
375
|
+
? ` configs:\n${configEntries.map((c) => ` - source: ${c.name}\n target: ${c.target}`).join("\n")}\n`
|
|
376
|
+
: "";
|
|
377
|
+
const topLevelConfigsSection = configEntries.length > 0
|
|
378
|
+
? `\nconfigs:\n${configEntries.map((c) => ` ${c.name}:\n file: ${c.relPath}`).join("\n")}\n`
|
|
379
|
+
: "";
|
|
380
|
+
// --- Agent environment ---
|
|
381
|
+
const agentEnvLines = [
|
|
382
|
+
` - MCP_PROXY_TOKEN=${proxyToken}`,
|
|
383
|
+
` - MCP_PROXY_URL=http://${proxyServiceName}:9090`,
|
|
384
|
+
];
|
|
385
|
+
if (credentialKeys && credentialKeys.length > 0) {
|
|
386
|
+
agentEnvLines.push(` - AGENT_CREDENTIALS=${JSON.stringify(credentialKeys)}`);
|
|
387
|
+
}
|
|
388
|
+
if (bashMode) {
|
|
389
|
+
agentEnvLines.push(` - AGENT_COMMAND_OVERRIDE=bash`);
|
|
390
|
+
}
|
|
391
|
+
if (verbose) {
|
|
392
|
+
agentEnvLines.push(` - AGENT_ENTRY_VERBOSE=1`);
|
|
393
|
+
}
|
|
394
|
+
// --- Command override ---
|
|
395
|
+
const commandLine = acpCommand
|
|
396
|
+
? `\n command: ${JSON.stringify(acpCommand)}`
|
|
397
|
+
: "";
|
|
398
|
+
// --- Named volumes declaration ---
|
|
399
|
+
const namedVolumes = volumeMasks.filter((m) => m.type === "directory");
|
|
400
|
+
const volumesSection = namedVolumes.length > 0
|
|
401
|
+
? `\nvolumes:\n${namedVolumes.map((v) => ` ${v.volumeName}:`).join("\n")}\n`
|
|
402
|
+
: "";
|
|
403
|
+
return `# Generated by clawmasons — session compose file
|
|
404
|
+
# Run docker compose commands from this directory:
|
|
405
|
+
# docker compose logs -f
|
|
406
|
+
# docker compose ps
|
|
407
|
+
# docker compose exec ${agentServiceName} sh
|
|
408
|
+
# docker compose down
|
|
409
|
+
name: ${composeName}
|
|
410
|
+
services:
|
|
411
|
+
${proxyServiceName}:
|
|
412
|
+
build:
|
|
413
|
+
context: ${relDockerDir}
|
|
414
|
+
dockerfile: ${path.relative(dockerDir, path.join(dockerBuildDir, "mcp-proxy", "Dockerfile"))}
|
|
415
|
+
volumes:
|
|
416
|
+
- ${relProjectDir}:${PROJECT_MOUNT_PATH}:ro
|
|
417
|
+
- ${relLogsDir}:/logs
|
|
418
|
+
- ${rel(path.join(dockerBuildDir, "mcp-proxy", ".cache"))}:/app/.cache
|
|
419
|
+
environment:
|
|
420
|
+
${proxyEnvLines.join("\n")}
|
|
421
|
+
ports:
|
|
422
|
+
- "${proxyPort}:9090"
|
|
423
|
+
restart: "no"
|
|
424
|
+
|
|
425
|
+
${agentServiceName}:
|
|
426
|
+
build:
|
|
427
|
+
context: ${relDockerDir}
|
|
428
|
+
dockerfile: ${path.relative(dockerDir, path.join(dockerBuildDir, agentType, "Dockerfile"))}
|
|
429
|
+
args:
|
|
430
|
+
HOST_UID: "${hostUid ?? "1000"}"
|
|
431
|
+
HOST_GID: "${hostGid ?? "1000"}"
|
|
432
|
+
volumes:
|
|
433
|
+
${agentVolumeLines.join("\n")}
|
|
434
|
+
${serviceConfigsBlock} depends_on:
|
|
435
|
+
- ${proxyServiceName}
|
|
436
|
+
environment:
|
|
437
|
+
${agentEnvLines.join("\n")}${commandLine}
|
|
438
|
+
stdin_open: true
|
|
439
|
+
tty: true
|
|
440
|
+
init: true
|
|
441
|
+
restart: "no"
|
|
442
|
+
${topLevelConfigsSection}${volumesSection}`;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Create a session directory with a self-contained docker-compose.yaml.
|
|
446
|
+
*
|
|
447
|
+
* @returns Session metadata including paths, tokens, and service names.
|
|
448
|
+
*/
|
|
449
|
+
export function createSessionDirectory(opts, fsDeps) {
|
|
450
|
+
const deps = {
|
|
451
|
+
mkdirSync: fsDeps?.mkdirSync ?? fs.mkdirSync,
|
|
452
|
+
writeFileSync: fsDeps?.writeFileSync ?? fs.writeFileSync,
|
|
453
|
+
randomBytes: fsDeps?.randomBytes ?? crypto.randomBytes,
|
|
454
|
+
};
|
|
455
|
+
const { role, projectDir } = opts;
|
|
456
|
+
const roleName = getAppShortName(role.metadata.name);
|
|
457
|
+
// Generate session ID
|
|
458
|
+
const sessionId = opts.sessionId ?? deps.randomBytes(4).toString("hex");
|
|
459
|
+
// Create session directory
|
|
460
|
+
const sessionDir = path.join(projectDir, ".mason", "sessions", sessionId);
|
|
461
|
+
deps.mkdirSync(sessionDir, { recursive: true });
|
|
462
|
+
// Create logs directory
|
|
463
|
+
const logsDir = path.join(sessionDir, "logs");
|
|
464
|
+
deps.mkdirSync(logsDir, { recursive: true });
|
|
465
|
+
// Ensure sentinel file exists
|
|
466
|
+
ensureSentinelFile(projectDir, fsDeps ? {
|
|
467
|
+
existsSync: () => false, // always create in test mode
|
|
468
|
+
mkdirSync: deps.mkdirSync,
|
|
469
|
+
writeFileSync: deps.writeFileSync,
|
|
470
|
+
chmodSync: () => { },
|
|
471
|
+
} : undefined);
|
|
472
|
+
// Generate tokens
|
|
473
|
+
const proxyToken = deps.randomBytes(32).toString("hex");
|
|
474
|
+
const credentialProxyToken = deps.randomBytes(32).toString("hex");
|
|
475
|
+
// Compute volume masks from role's container.ignore.paths
|
|
476
|
+
const ignorePaths = role.container?.ignore?.paths ?? [];
|
|
477
|
+
const volumeMasks = generateVolumeMasks(ignorePaths);
|
|
478
|
+
// Detect materialized home directory.
|
|
479
|
+
// Supervisor roles always populate home/ (role content merged there during generateRoleDockerBuildDir).
|
|
480
|
+
const homePath = path.join(opts.dockerBuildDir, opts.agentType, "home");
|
|
481
|
+
const homeExists = role.type === "supervisor" || (fsDeps ? false : fs.existsSync(homePath));
|
|
482
|
+
// Compute workspace and build overlay paths
|
|
483
|
+
const workspacePath = path.join(opts.dockerBuildDir, opts.agentType, "workspace");
|
|
484
|
+
const buildWorkspaceProjectPath = path.join(opts.dockerBuildDir, opts.agentType, "build", "workspace", "project");
|
|
485
|
+
// Enumerate and classify build workspace project entries (skip in test mode — fsDeps means no real FS)
|
|
486
|
+
const buildWorkspaceProjectFileEntries = [];
|
|
487
|
+
const buildWorkspaceProjectDirEntries = [];
|
|
488
|
+
if (!fsDeps && fs.existsSync(buildWorkspaceProjectPath)) {
|
|
489
|
+
for (const entry of fs.readdirSync(buildWorkspaceProjectPath)) {
|
|
490
|
+
const entryPath = path.join(buildWorkspaceProjectPath, entry);
|
|
491
|
+
if (fs.statSync(entryPath).isDirectory()) {
|
|
492
|
+
buildWorkspaceProjectDirEntries.push(entry);
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
buildWorkspaceProjectFileEntries.push(entry);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
// Generate compose file
|
|
500
|
+
const composeContent = generateSessionComposeYml({
|
|
501
|
+
...opts,
|
|
502
|
+
roleName,
|
|
503
|
+
proxyToken,
|
|
504
|
+
credentialProxyToken,
|
|
505
|
+
volumeMasks,
|
|
506
|
+
sessionDir,
|
|
507
|
+
logsDir,
|
|
508
|
+
homePath: homeExists ? homePath : undefined,
|
|
509
|
+
workspacePath,
|
|
510
|
+
buildWorkspaceProjectPath,
|
|
511
|
+
buildWorkspaceProjectFileEntries,
|
|
512
|
+
buildWorkspaceProjectDirEntries,
|
|
513
|
+
});
|
|
514
|
+
const composeFile = path.join(sessionDir, "docker-compose.yaml");
|
|
515
|
+
deps.writeFileSync(composeFile, composeContent);
|
|
516
|
+
const proxyServiceName = `proxy-${roleName}`;
|
|
517
|
+
const agentServiceName = `agent-${roleName}`;
|
|
518
|
+
return {
|
|
519
|
+
sessionId,
|
|
520
|
+
sessionDir,
|
|
521
|
+
composeFile,
|
|
522
|
+
logsDir,
|
|
523
|
+
proxyToken,
|
|
524
|
+
credentialProxyToken,
|
|
525
|
+
proxyServiceName,
|
|
526
|
+
agentServiceName,
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
//# sourceMappingURL=docker-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-generator.js","sourceRoot":"","sources":["../../src/materializer/docker-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACpG,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAkB,MAAM,+BAA+B,CAAC;AAGxF,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,4DAA4D;AAC5D,MAAM,sBAAsB,GAAG,mBAAmB,CAAC;AAEnD,6DAA6D;AAC7D,MAAM,kBAAkB,GAAG,+BAA+B,CAAC;AAE3D;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC3B,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC1D,CAAC;AAiBD,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB;IACnD,MAAM,OAAO,GAAG,UAAU;SACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;SAClB,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzB,OAAO,UAAU,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,SAAS,yBAAyB,CAAC,KAAa;IAC9C,MAAM,OAAO,GAAG,KAAK;SAClB,WAAW,EAAE;SACb,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzB,OAAO,WAAW,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,SAAS,sBAAsB,CAAC,KAAa;IAC3C,MAAM,OAAO,GAAG,KAAK;SAClB,WAAW,EAAE;SACb,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzB,OAAO,QAAQ,OAAO,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAqB;IACvD,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3B,MAAM,WAAW,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,yCAAyC;QAClF,MAAM,aAAa,GAAG,GAAG,kBAAkB,IAAI,SAAS,EAAE,CAAC;QAE3D,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO;gBACL,IAAI,EAAE,WAAoB;gBAC1B,QAAQ,EAAE,CAAC;gBACX,aAAa;gBACb,UAAU,EAAE,kBAAkB,CAAC,SAAS,CAAC;aAC1C,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO;gBACL,IAAI,EAAE,MAAe;gBACrB,QAAQ,EAAE,CAAC;gBACX,aAAa;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,MAKC;IAED,MAAM,IAAI,GAAG;QACX,UAAU,EAAE,MAAM,EAAE,UAAU,IAAI,EAAE,CAAC,UAAU;QAC/C,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC,SAAS;QAC5C,aAAa,EAAE,MAAM,EAAE,aAAa,IAAI,EAAE,CAAC,aAAa;QACxD,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC,SAAS;KAC7C,CAAC;IAEF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;IAEnE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAoCD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,0BAA0B,CACxC,IAA6B,EAC7B,MAGC;IAED,MAAM,IAAI,GAAG;QACX,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC,SAAS;QAC5C,aAAa,EAAE,MAAM,EAAE,aAAa,IAAI,EAAE,CAAC,aAAa;KACzD,CAAC;IAEF,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IACvE,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACpF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhD,6BAA6B;IAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAChD,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9C,mEAAmE;IACnE,8EAA8E;IAC9E,MAAM,YAAY,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAChD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,CAAC,MAAM,IAAI,YAAY,EAAE,eAAe,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7C,YAAY,CAAC,eAAe,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACnD,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,mBAAmB;IACnB,MAAM,aAAa,GAAG,wBAAwB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,mDAAmD,IAAI,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC;IAChD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,eAAe,GAAG,uBAAuB,CAAC,aAAa,EAAE,SAAS,EAAE;QACxE,OAAO,EAAE,OAAO,IAAI,YAAY;QAChC,gBAAgB,EAAE,QAAQ,EAAE,UAAU;QACtC,0BAA0B,EAAE,IAAI,CAAC,0BAA0B;QAC3D,QAAQ,EAAE,IAAI,CAAC,IAAI;KACpB,CAAC,CAAC;IACH,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,eAAe,CAAC,CAAC;IAEvE,+CAA+C;IAC/C,gBAAgB;IAChB,wGAAwG;IACxG,wHAAwH;IACxH,mGAAmG;IACnG,yGAAyG;IACzG,MAAM,OAAO,GAAG,aAAa,IAAI,gBAAgB,QAAQ,OAAO,CAAC;IACjE,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC;QACrF,CAAC,CAAC;YACE,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvG,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjE;QACH,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,SAAS,GAAG,CAAC,YAAY,IAAI,YAAY,EAAE,qBAAqB,CAAC;QACrE,CAAC,CAAC,YAAY,CAAC,qBAAqB,CAChC,aAAa,EACb,OAAO,EACP,SAAS,EACT,eAAe,EACf,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAClD;QACH,CAAC,CAAC,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IACtD,MAAM,wBAAwB,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IACtF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjD,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,QAAQ,KAAK,mBAAmB;YAChD,CAAC,CAAC,YAAY;YACd,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,wBAAwB,CAAC;QAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,iCAAiC;IACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAClD,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9C,MAAM,eAAe,GAAG,uBAAuB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACtE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,eAAe,CAAC,CAAC;IAEvE,wCAAwC;IACxC,MAAM,UAAU,GAAG,6BAA6B,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACtE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,qBAAqB,CAAC,EAAE,UAAU,CAAC,CAAC;IAE3E,OAAO;QACL,QAAQ;QACR,mBAAmB,EAAE,GAAG,SAAS,aAAa;QAC9C,mBAAmB,EAAE,sBAAsB;KAC5C,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,6BAA6B,CACpC,QAAgB,EAChB,SAAiB;IAEjB,OAAO,wCAAwC,QAAQ;;;;UAI/C,QAAQ;;;8BAGY,QAAQ;;;;;;;UAO5B,QAAQ;;;oBAGE,QAAQ,IAAI,SAAS;;gBAEzB,QAAQ;;;CAGvB,CAAC;AACF,CAAC;AA+DD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAA2B;IACnE,MAAM,EACJ,UAAU,EACV,cAAc,EACd,SAAS,EACT,QAAQ,EACR,SAAS,EACT,UAAU,EACV,oBAAoB,EACpB,SAAS,GAAG,IAAI,EAChB,WAAW,GAAG,EAAE,EAChB,UAAU,EACV,cAAc,EACd,WAAW,EACX,UAAU,EACV,UAAU,EACV,OAAO,EACP,QAAQ,EACR,OAAO,EACP,OAAO,EACP,aAAa,EACb,yBAAyB,EACzB,gCAAgC,GAAG,EAAE,EACrC,+BAA+B,GAAG,EAAE,EACpC,YAAY,EACZ,oBAAoB,EACpB,QAAQ,EACR,OAAO,GACR,GAAG,IAAI,CAAC;IAET,6DAA6D;IAC7D,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7F,MAAM,WAAW,GAAG,SAAS,WAAW,EAAE,CAAC;IAE3C,iDAAiD;IACjD,mFAAmF;IACnF,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,EAAE;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;IAC1C,CAAC,CAAC;IACF,MAAM,YAAY,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IACpC,MAAM,aAAa,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IAChC,MAAM,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAEvE,MAAM,gBAAgB,GAAG,SAAS,QAAQ,EAAE,CAAC;IAC7C,MAAM,gBAAgB,GAAG,SAAS,QAAQ,EAAE,CAAC;IAE7C,wBAAwB;IACxB,MAAM,aAAa,GAAG;QACpB,+BAA+B,UAAU,EAAE;QAC3C,kCAAkC,oBAAoB,EAAE;QACxD,uBAAuB,kBAAkB,EAAE;KAC5C,CAAC;IACF,IAAI,WAAW,EAAE,CAAC;QAChB,aAAa,CAAC,IAAI,CAAC,gCAAgC,WAAW,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,cAAc,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,aAAa,CAAC,IAAI,CAAC,wCAAwC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,wBAAwB;IACxB,MAAM,gBAAgB,GAAa,EAAE,CAAC;IAEtC,kEAAkE;IAClE,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,eAAe,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1C,gBAAgB,CAAC,IAAI,CAAC,WAAW,eAAe,eAAe,CAAC,CAAC;IACnE,CAAC;IAED,oDAAoD;IACpD,gBAAgB,CAAC,IAAI,CAAC,WAAW,aAAa,IAAI,kBAAkB,EAAE,CAAC,CAAC;IAExE,0FAA0F;IAC1F,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAC9B,gBAAgB,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,KAAK,MAAM,GAAG,IAAI,uBAAuB,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,gBAAgB,CAAC,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,iBAAiB;IACjB,gBAAgB,CAAC,IAAI,CAAC,WAAW,UAAU,QAAQ,CAAC,CAAC;IAErD,oEAAoE;IACpE,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,gBAAgB,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC;QAC5C,gBAAgB,CAAC,IAAI,CAAC,WAAW,gBAAgB,wBAAwB,CAAC,CAAC;IAC7E,CAAC;IAED,yEAAyE;IACzE,IAAI,yBAAyB,IAAI,+BAA+B,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5E,KAAK,MAAM,KAAK,IAAI,+BAA+B,EAAE,CAAC;YACpD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAClE,MAAM,YAAY,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC;YACxC,gBAAgB,CAAC,IAAI,CAAC,WAAW,YAAY,kCAAkC,KAAK,EAAE,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,IAAI,oBAAoB,EAAE,CAAC;QACzB,MAAM,aAAa,GAAG,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAChD,gBAAgB,CAAC,IAAI,CAAC,WAAW,aAAa,6BAA6B,CAAC,CAAC;IAC/E,CAAC;IAED,iEAAiE;IACjE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,gBAAgB,CAAC,IAAI,CAAC,WAAW,WAAW,cAAc,CAAC,CAAC;IAC9D,CAAC;IAED,iGAAiG;IACjG,MAAM,aAAa,GAA6D,EAAE,CAAC;IAEnF,sDAAsD;IACtD,IAAI,yBAAyB,IAAI,gCAAgC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7E,KAAK,MAAM,KAAK,IAAI,gCAAgC,EAAE,CAAC;YACrD,aAAa,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,yBAAyB,CAAC,KAAK,CAAC;gBACtC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;gBACzD,MAAM,EAAE,iCAAiC,KAAK,EAAE;aACjD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC;gBACjB,IAAI,EAAE,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAC3C,OAAO,EAAE,WAAW;gBACpB,MAAM,EAAE,IAAI,CAAC,aAAa;aAC3B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,mBAAmB,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC;QAClD,CAAC,CAAC,iBAAiB,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACvC,mBAAmB,CAAC,CAAC,IAAI,qBAAqB,CAAC,CAAC,MAAM,EAAE,CACzD,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QAClB,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,sBAAsB,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC;QACrD,CAAC,CAAC,eAAe,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QAChG,CAAC,CAAC,EAAE,CAAC;IAEP,4BAA4B;IAC5B,MAAM,aAAa,GAAG;QACpB,2BAA2B,UAAU,EAAE;QACvC,gCAAgC,gBAAgB,OAAO;KACxD,CAAC;IACF,IAAI,cAAc,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,aAAa,CAAC,IAAI,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,QAAQ,EAAE,CAAC;QACb,aAAa,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,aAAa,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IACtD,CAAC;IAED,2BAA2B;IAC3B,MAAM,WAAW,GAAG,UAAU;QAC5B,CAAC,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE;QAChD,CAAC,CAAC,EAAE,CAAC;IAEP,oCAAoC;IACpC,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IACvE,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC;QAC5C,CAAC,CAAC,eAAe,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QAC7E,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO;;;;0BAIiB,gBAAgB;;QAElC,WAAW;;IAEf,gBAAgB;;iBAEH,YAAY;oBACT,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC;;UAExF,aAAa,IAAI,kBAAkB;UACnC,UAAU;UACV,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;;EAE7D,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;;WAEf,SAAS;;;IAGhB,gBAAgB;;iBAEH,YAAY;oBACT,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;;qBAE3E,OAAO,IAAI,MAAM;qBACjB,OAAO,IAAI,MAAM;;EAEpC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;EAC3B,mBAAmB;UACX,gBAAgB;;EAExB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,WAAW;;;;;EAKtC,sBAAsB,GAAG,cAAc,EAAE,CAAC;AAC5C,CAAC;AAgED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA0B,EAC1B,MAIC;IAED,MAAM,IAAI,GAAG;QACX,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE,CAAC,SAAS;QAC5C,aAAa,EAAE,MAAM,EAAE,aAAa,IAAI,EAAE,CAAC,aAAa;QACxD,WAAW,EAAE,MAAM,EAAE,WAAW,IAAI,MAAM,CAAC,WAAW;KACvD,CAAC;IAEF,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAClC,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAErD,sBAAsB;IACtB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExE,2BAA2B;IAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC1E,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhD,wBAAwB;IACxB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,8BAA8B;IAC9B,kBAAkB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACtC,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,6BAA6B;QACtD,SAAS,EAAE,IAAI,CAAC,SAAgE;QAChF,aAAa,EAAE,IAAI,CAAC,aAA4E;QAChG,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;KACpB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEf,kBAAkB;IAClB,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxD,MAAM,oBAAoB,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAElE,0DAA0D;IAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;IACxD,MAAM,WAAW,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAErD,sCAAsC;IACtC,wGAAwG;IACxG,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACxE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE5F,4CAA4C;IAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAClF,MAAM,yBAAyB,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAElH,uGAAuG;IACvG,MAAM,gCAAgC,GAAa,EAAE,CAAC;IACtD,MAAM,+BAA+B,GAAa,EAAE,CAAC;IACrD,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,UAAU,CAAC,yBAAyB,CAAC,EAAE,CAAC;QACxD,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,yBAAyB,CAAC,EAAE,CAAC;YAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAC9D,IAAI,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACzC,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACN,gCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED,wBAAwB;IACxB,MAAM,cAAc,GAAG,yBAAyB,CAAC;QAC/C,GAAG,IAAI;QACP,QAAQ;QACR,UAAU;QACV,oBAAoB;QACpB,WAAW;QACX,UAAU;QACV,OAAO;QACP,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QAC3C,aAAa;QACb,yBAAyB;QACzB,gCAAgC;QAChC,+BAA+B;KAChC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;IACjE,IAAI,CAAC,aAAa,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAEhD,MAAM,gBAAgB,GAAG,SAAS,QAAQ,EAAE,CAAC;IAC7C,MAAM,gBAAgB,GAAG,SAAS,QAAQ,EAAE,CAAC;IAE7C,OAAO;QACL,SAAS;QACT,UAAU;QACV,WAAW;QACX,OAAO;QACP,UAAU;QACV,oBAAoB;QACpB,gBAAgB;QAChB,gBAAgB;KACjB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { claudeCodeMaterializer } from "@clawmasons/claude-code-agent";
|
|
2
|
+
export { piCodingAgentMaterializer } from "@clawmasons/pi-coding-agent";
|
|
3
|
+
export { mcpAgentMaterializer } from "@clawmasons/mcp-agent/agent-package";
|
|
4
|
+
export { PROVIDER_ENV_VARS, ACP_RUNTIME_COMMANDS } from "./common.js";
|
|
5
|
+
export { materializeForAgent, getMaterializer, getRegisteredAgentTypes, MaterializerError, } from "./role-materializer.js";
|
|
6
|
+
export type { RuntimeMaterializer, MaterializationResult, MaterializeOptions, } from "./types.js";
|
|
7
|
+
export { generateVolumeMasks, sanitizeVolumeName, ensureSentinelFile, generateRoleDockerBuildDir, generateSessionComposeYml, createSessionDirectory, } from "./docker-generator.js";
|
|
8
|
+
export type { VolumeMaskEntry, GenerateBuildDirOptions, BuildDirResult, SessionComposeOptions, CreateSessionOptions, SessionResult, } from "./docker-generator.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/materializer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,GACd,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { claudeCodeMaterializer } from "@clawmasons/claude-code-agent";
|
|
2
|
+
export { piCodingAgentMaterializer } from "@clawmasons/pi-coding-agent";
|
|
3
|
+
export { mcpAgentMaterializer } from "@clawmasons/mcp-agent/agent-package";
|
|
4
|
+
export { PROVIDER_ENV_VARS, ACP_RUNTIME_COMMANDS } from "./common.js";
|
|
5
|
+
export { materializeForAgent, getMaterializer, getRegisteredAgentTypes, MaterializerError, } from "./role-materializer.js";
|
|
6
|
+
export { generateVolumeMasks, sanitizeVolumeName, ensureSentinelFile, generateRoleDockerBuildDir, generateSessionComposeYml, createSessionDirectory, } from "./docker-generator.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/materializer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,wBAAwB,CAAC;AAMhC,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,EAC1B,yBAAyB,EACzB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Populates the proxy Docker build context with required node_modules.
|
|
3
|
+
*
|
|
4
|
+
* The proxy Dockerfile at `{role}/mcp-proxy/Dockerfile` expects `package.json`
|
|
5
|
+
* and `node_modules/` to be available in the Docker build context root
|
|
6
|
+
* (`.mason/docker/`).
|
|
7
|
+
*
|
|
8
|
+
* This module resolves framework packages and their transitive production
|
|
9
|
+
* dependencies from the host's node_modules, copies them into the Docker
|
|
10
|
+
* build directory, and creates `.bin/` symlinks.
|
|
11
|
+
*
|
|
12
|
+
* @module proxy-dependencies
|
|
13
|
+
*/
|
|
14
|
+
import type { Role } from "@clawmasons/shared";
|
|
15
|
+
/**
|
|
16
|
+
* Ensure the proxy Docker build context has all required node_modules.
|
|
17
|
+
*
|
|
18
|
+
* Populates `{dockerDir}/node_modules/` and `{dockerDir}/package.json`
|
|
19
|
+
* with framework packages and their transitive production dependencies.
|
|
20
|
+
*
|
|
21
|
+
* Idempotent: skips if `{dockerDir}/node_modules/@clawmasons/mason` already
|
|
22
|
+
* exists.
|
|
23
|
+
*
|
|
24
|
+
* @param dockerDir - The Docker build root directory (`.mason/docker/`).
|
|
25
|
+
* @param projectDir - The project root (used as a search path for packages).
|
|
26
|
+
*/
|
|
27
|
+
export declare function ensureProxyDependencies(dockerDir: string, projectDir?: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Synthesize npm packages from a Role's inline apps and role config
|
|
30
|
+
* into the Docker build node_modules.
|
|
31
|
+
*
|
|
32
|
+
* When roles define `mcp_servers` inline (native .claude format) instead of
|
|
33
|
+
* referencing npm workspace packages, the proxy inside Docker has no packages
|
|
34
|
+
* to discover. This function bridges the gap by writing synthetic package.json
|
|
35
|
+
* files that `discoverPackages` / `resolveRolePackage` can find at runtime.
|
|
36
|
+
*
|
|
37
|
+
* Idempotent — skips packages that already exist.
|
|
38
|
+
*
|
|
39
|
+
* @param role - The Role with inline app configs
|
|
40
|
+
* @param dockerDir - The Docker build root (`.mason/docker/`)
|
|
41
|
+
*/
|
|
42
|
+
export declare function synthesizeRolePackages(role: Role, dockerDir: string): void;
|
|
43
|
+
//# sourceMappingURL=proxy-dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-dependencies.d.ts","sourceRoot":"","sources":["../../src/materializer/proxy-dependencies.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AA0U/C;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI,CAkDN;AAkCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,GAChB,IAAI,CA+DN"}
|