@downcity/shell 0.1.4
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/bin/Shell.d.ts +55 -0
- package/bin/Shell.d.ts.map +1 -0
- package/bin/Shell.js +171 -0
- package/bin/Shell.js.map +1 -0
- package/bin/approval/ShellApprovalRuntime.d.ts +62 -0
- package/bin/approval/ShellApprovalRuntime.d.ts.map +1 -0
- package/bin/approval/ShellApprovalRuntime.js +214 -0
- package/bin/approval/ShellApprovalRuntime.js.map +1 -0
- package/bin/index.d.ts +27 -0
- package/bin/index.d.ts.map +1 -0
- package/bin/index.js +26 -0
- package/bin/index.js.map +1 -0
- package/bin/sandbox/LinuxBubblewrapSandbox.d.ts +19 -0
- package/bin/sandbox/LinuxBubblewrapSandbox.d.ts.map +1 -0
- package/bin/sandbox/LinuxBubblewrapSandbox.js +186 -0
- package/bin/sandbox/LinuxBubblewrapSandbox.js.map +1 -0
- package/bin/sandbox/MacOsSeatbeltSandbox.d.ts +16 -0
- package/bin/sandbox/MacOsSeatbeltSandbox.d.ts.map +1 -0
- package/bin/sandbox/MacOsSeatbeltSandbox.js +154 -0
- package/bin/sandbox/MacOsSeatbeltSandbox.js.map +1 -0
- package/bin/sandbox/SandboxConfigResolver.d.ts +37 -0
- package/bin/sandbox/SandboxConfigResolver.d.ts.map +1 -0
- package/bin/sandbox/SandboxConfigResolver.js +130 -0
- package/bin/sandbox/SandboxConfigResolver.js.map +1 -0
- package/bin/sandbox/SandboxPreflight.d.ts +73 -0
- package/bin/sandbox/SandboxPreflight.d.ts.map +1 -0
- package/bin/sandbox/SandboxPreflight.js +122 -0
- package/bin/sandbox/SandboxPreflight.js.map +1 -0
- package/bin/sandbox/SandboxRunner.d.ts +61 -0
- package/bin/sandbox/SandboxRunner.d.ts.map +1 -0
- package/bin/sandbox/SandboxRunner.js +107 -0
- package/bin/sandbox/SandboxRunner.js.map +1 -0
- package/bin/sandbox/UnrestrictedSandbox.d.ts +16 -0
- package/bin/sandbox/UnrestrictedSandbox.d.ts.map +1 -0
- package/bin/sandbox/UnrestrictedSandbox.js +39 -0
- package/bin/sandbox/UnrestrictedSandbox.js.map +1 -0
- package/bin/sandbox/types/Sandbox.d.ts +130 -0
- package/bin/sandbox/types/Sandbox.d.ts.map +1 -0
- package/bin/sandbox/types/Sandbox.js +10 -0
- package/bin/sandbox/types/Sandbox.js.map +1 -0
- package/bin/sandbox/types/SandboxRuntime.d.ts +370 -0
- package/bin/sandbox/types/SandboxRuntime.d.ts.map +1 -0
- package/bin/sandbox/types/SandboxRuntime.js +10 -0
- package/bin/sandbox/types/SandboxRuntime.js.map +1 -0
- package/bin/session/Paths.d.ts +12 -0
- package/bin/session/Paths.d.ts.map +1 -0
- package/bin/session/Paths.js +21 -0
- package/bin/session/Paths.js.map +1 -0
- package/bin/session/ShellActionResponse.d.ts +52 -0
- package/bin/session/ShellActionResponse.d.ts.map +1 -0
- package/bin/session/ShellActionResponse.js +73 -0
- package/bin/session/ShellActionResponse.js.map +1 -0
- package/bin/session/ShellActionRuntime.d.ts +15 -0
- package/bin/session/ShellActionRuntime.d.ts.map +1 -0
- package/bin/session/ShellActionRuntime.js +15 -0
- package/bin/session/ShellActionRuntime.js.map +1 -0
- package/bin/session/ShellActionRuntimeSupport.d.ts +88 -0
- package/bin/session/ShellActionRuntimeSupport.d.ts.map +1 -0
- package/bin/session/ShellActionRuntimeSupport.js +305 -0
- package/bin/session/ShellActionRuntimeSupport.js.map +1 -0
- package/bin/session/ShellProcessEvents.d.ts +22 -0
- package/bin/session/ShellProcessEvents.d.ts.map +1 -0
- package/bin/session/ShellProcessEvents.js +41 -0
- package/bin/session/ShellProcessEvents.js.map +1 -0
- package/bin/session/ShellRunScope.d.ts +43 -0
- package/bin/session/ShellRunScope.d.ts.map +1 -0
- package/bin/session/ShellRunScope.js +29 -0
- package/bin/session/ShellRunScope.js.map +1 -0
- package/bin/session/ShellRuntimeEnvironment.d.ts +21 -0
- package/bin/session/ShellRuntimeEnvironment.d.ts.map +1 -0
- package/bin/session/ShellRuntimeEnvironment.js +69 -0
- package/bin/session/ShellRuntimeEnvironment.js.map +1 -0
- package/bin/session/ShellRuntimeTypes.d.ts +160 -0
- package/bin/session/ShellRuntimeTypes.d.ts.map +1 -0
- package/bin/session/ShellRuntimeTypes.js +10 -0
- package/bin/session/ShellRuntimeTypes.js.map +1 -0
- package/bin/session/actions/ShellActionShared.d.ts +76 -0
- package/bin/session/actions/ShellActionShared.d.ts.map +1 -0
- package/bin/session/actions/ShellActionShared.js +100 -0
- package/bin/session/actions/ShellActionShared.js.map +1 -0
- package/bin/session/actions/ShellApprovalActions.d.ts +34 -0
- package/bin/session/actions/ShellApprovalActions.d.ts.map +1 -0
- package/bin/session/actions/ShellApprovalActions.js +37 -0
- package/bin/session/actions/ShellApprovalActions.js.map +1 -0
- package/bin/session/actions/ShellExecActions.d.ts +15 -0
- package/bin/session/actions/ShellExecActions.d.ts.map +1 -0
- package/bin/session/actions/ShellExecActions.js +117 -0
- package/bin/session/actions/ShellExecActions.js.map +1 -0
- package/bin/session/actions/ShellLifecycleActions.d.ts +18 -0
- package/bin/session/actions/ShellLifecycleActions.d.ts.map +1 -0
- package/bin/session/actions/ShellLifecycleActions.js +53 -0
- package/bin/session/actions/ShellLifecycleActions.js.map +1 -0
- package/bin/session/actions/ShellQueryActions.d.ts +27 -0
- package/bin/session/actions/ShellQueryActions.d.ts.map +1 -0
- package/bin/session/actions/ShellQueryActions.js +151 -0
- package/bin/session/actions/ShellQueryActions.js.map +1 -0
- package/bin/session/actions/ShellStartActions.d.ts +15 -0
- package/bin/session/actions/ShellStartActions.d.ts.map +1 -0
- package/bin/session/actions/ShellStartActions.js +167 -0
- package/bin/session/actions/ShellStartActions.js.map +1 -0
- package/bin/session/actions/ShellWriteActions.d.ts +15 -0
- package/bin/session/actions/ShellWriteActions.d.ts.map +1 -0
- package/bin/session/actions/ShellWriteActions.js +85 -0
- package/bin/session/actions/ShellWriteActions.js.map +1 -0
- package/bin/tool/ShellToolFormatting.d.ts +12 -0
- package/bin/tool/ShellToolFormatting.d.ts.map +1 -0
- package/bin/tool/ShellToolFormatting.js +31 -0
- package/bin/tool/ShellToolFormatting.js.map +1 -0
- package/bin/tool/ShellToolSchemas.d.ts +61 -0
- package/bin/tool/ShellToolSchemas.d.ts.map +1 -0
- package/bin/tool/ShellToolSchemas.js +130 -0
- package/bin/tool/ShellToolSchemas.js.map +1 -0
- package/bin/tool/ShellTools.d.ts +32 -0
- package/bin/tool/ShellTools.d.ts.map +1 -0
- package/bin/tool/ShellTools.js +296 -0
- package/bin/tool/ShellTools.js.map +1 -0
- package/bin/types/Shell.d.ts +115 -0
- package/bin/types/Shell.d.ts.map +1 -0
- package/bin/types/Shell.js +9 -0
- package/bin/types/Shell.js.map +1 -0
- package/bin/types/ShellAction.d.ts +258 -0
- package/bin/types/ShellAction.d.ts.map +1 -0
- package/bin/types/ShellAction.js +9 -0
- package/bin/types/ShellAction.js.map +1 -0
- package/bin/types/ShellHostContext.d.ts +78 -0
- package/bin/types/ShellHostContext.d.ts.map +1 -0
- package/bin/types/ShellHostContext.js +9 -0
- package/bin/types/ShellHostContext.js.map +1 -0
- package/bin/types/ShellRuntime.d.ts +128 -0
- package/bin/types/ShellRuntime.d.ts.map +1 -0
- package/bin/types/ShellRuntime.js +9 -0
- package/bin/types/ShellRuntime.js.map +1 -0
- package/bin/types/ShellRuntimeOptions.d.ts +103 -0
- package/bin/types/ShellRuntimeOptions.d.ts.map +1 -0
- package/bin/types/ShellRuntimeOptions.js +10 -0
- package/bin/types/ShellRuntimeOptions.js.map +1 -0
- package/bin/utils/Id.d.ts +11 -0
- package/bin/utils/Id.d.ts.map +1 -0
- package/bin/utils/Id.js +14 -0
- package/bin/utils/Id.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linux Bubblewrap sandbox backend。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 基于 `bwrap` 提供 Linux 本机 shell sandbox。
|
|
6
|
+
* - 继续保持“shell 命令必须进入 sandbox”的安全语义,不提供宿主机裸跑回退。
|
|
7
|
+
* - 边界与 macOS backend 对齐:路径、环境变量、网络、agent 级共享 HOME/TMPDIR/cache。
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import fs from "fs-extra";
|
|
12
|
+
const DEFAULT_PATH_VALUE = "/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin";
|
|
13
|
+
function dedupeExistingPaths(values) {
|
|
14
|
+
const seen = new Set();
|
|
15
|
+
const result = [];
|
|
16
|
+
for (const value of values) {
|
|
17
|
+
const normalized = path.resolve(String(value || "").trim());
|
|
18
|
+
if (!normalized || seen.has(normalized))
|
|
19
|
+
continue;
|
|
20
|
+
if (!fs.existsSync(normalized))
|
|
21
|
+
continue;
|
|
22
|
+
seen.add(normalized);
|
|
23
|
+
result.push(normalized);
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
}
|
|
27
|
+
function buildReadablePaths(params) {
|
|
28
|
+
return dedupeExistingPaths([
|
|
29
|
+
"/usr",
|
|
30
|
+
"/bin",
|
|
31
|
+
"/sbin",
|
|
32
|
+
"/lib",
|
|
33
|
+
"/lib64",
|
|
34
|
+
"/etc",
|
|
35
|
+
params.rootPath,
|
|
36
|
+
params.sandboxDir,
|
|
37
|
+
params.tmpDir,
|
|
38
|
+
params.cacheDir,
|
|
39
|
+
path.dirname(params.shellPath),
|
|
40
|
+
]);
|
|
41
|
+
}
|
|
42
|
+
function buildWritablePaths(params) {
|
|
43
|
+
return dedupeExistingPaths([
|
|
44
|
+
...params.config.writablePaths,
|
|
45
|
+
params.executionDir,
|
|
46
|
+
params.config.sandboxDir,
|
|
47
|
+
params.config.tmpDir,
|
|
48
|
+
params.config.cacheDir,
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
function isPathCoveredBy(paths, targetPath) {
|
|
52
|
+
const normalizedTarget = path.resolve(targetPath);
|
|
53
|
+
return paths.some((value) => {
|
|
54
|
+
const normalizedValue = path.resolve(value);
|
|
55
|
+
if (normalizedValue === normalizedTarget)
|
|
56
|
+
return true;
|
|
57
|
+
const relative = path.relative(normalizedValue, normalizedTarget);
|
|
58
|
+
return Boolean(relative) && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function buildSandboxEnv(params) {
|
|
62
|
+
const env = {};
|
|
63
|
+
for (const key of params.config.envAllowlist) {
|
|
64
|
+
const value = params.baseEnv[key];
|
|
65
|
+
if (typeof value !== "string" || !value.trim())
|
|
66
|
+
continue;
|
|
67
|
+
env[key] = value;
|
|
68
|
+
}
|
|
69
|
+
for (const [key, value] of Object.entries(params.baseEnv)) {
|
|
70
|
+
if (!key.startsWith("DC_"))
|
|
71
|
+
continue;
|
|
72
|
+
if (typeof value !== "string" || !value.trim())
|
|
73
|
+
continue;
|
|
74
|
+
env[key] = value;
|
|
75
|
+
}
|
|
76
|
+
env.PATH = String(env.PATH || params.baseEnv.PATH || DEFAULT_PATH_VALUE);
|
|
77
|
+
env.HOME = params.config.homeDir;
|
|
78
|
+
env.TMPDIR = params.config.tmpDir;
|
|
79
|
+
env.XDG_CACHE_HOME = params.config.cacheDir;
|
|
80
|
+
env.DC_SANDBOX = "1";
|
|
81
|
+
env.DC_SANDBOX_DIR = params.config.sandboxDir;
|
|
82
|
+
env.DC_SANDBOX_HOME = params.config.homeDir;
|
|
83
|
+
env.DC_SANDBOX_CACHE = params.config.cacheDir;
|
|
84
|
+
env.SHELL = params.shellPath;
|
|
85
|
+
return env;
|
|
86
|
+
}
|
|
87
|
+
function addReadOnlyBind(args, sourcePath) {
|
|
88
|
+
args.push("--ro-bind", sourcePath, sourcePath);
|
|
89
|
+
}
|
|
90
|
+
function addWritableBind(args, sourcePath) {
|
|
91
|
+
args.push("--bind", sourcePath, sourcePath);
|
|
92
|
+
}
|
|
93
|
+
function addParentDirs(args, targetPath, createdDirs) {
|
|
94
|
+
const parts = path.resolve(targetPath).split(path.sep).filter(Boolean);
|
|
95
|
+
let current = "";
|
|
96
|
+
for (let index = 0; index < parts.length - 1; index += 1) {
|
|
97
|
+
current = `${current}/${parts[index]}`;
|
|
98
|
+
if (createdDirs.has(current))
|
|
99
|
+
continue;
|
|
100
|
+
createdDirs.add(current);
|
|
101
|
+
args.push("--dir", current);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function buildLinuxBubblewrapArgs(params) {
|
|
105
|
+
const readablePaths = buildReadablePaths({
|
|
106
|
+
rootPath: params.config.rootPath,
|
|
107
|
+
shellPath: params.shellPath,
|
|
108
|
+
sandboxDir: params.config.sandboxDir,
|
|
109
|
+
tmpDir: params.config.tmpDir,
|
|
110
|
+
cacheDir: params.config.cacheDir,
|
|
111
|
+
});
|
|
112
|
+
const writablePaths = buildWritablePaths(params);
|
|
113
|
+
const writableSet = new Set(writablePaths);
|
|
114
|
+
const createdDirs = new Set();
|
|
115
|
+
const mountedPaths = [];
|
|
116
|
+
const args = [
|
|
117
|
+
"--die-with-parent",
|
|
118
|
+
"--unshare-pid",
|
|
119
|
+
"--proc",
|
|
120
|
+
"/proc",
|
|
121
|
+
"--dev",
|
|
122
|
+
"/dev",
|
|
123
|
+
];
|
|
124
|
+
if (params.config.networkMode === "off") {
|
|
125
|
+
args.push("--unshare-net");
|
|
126
|
+
}
|
|
127
|
+
for (const readablePath of readablePaths) {
|
|
128
|
+
if (writableSet.has(readablePath))
|
|
129
|
+
continue;
|
|
130
|
+
if (!isPathCoveredBy(mountedPaths, readablePath)) {
|
|
131
|
+
addParentDirs(args, readablePath, createdDirs);
|
|
132
|
+
}
|
|
133
|
+
addReadOnlyBind(args, readablePath);
|
|
134
|
+
mountedPaths.push(readablePath);
|
|
135
|
+
}
|
|
136
|
+
for (const writablePath of writablePaths) {
|
|
137
|
+
if (isPathCoveredBy(mountedPaths, writablePath))
|
|
138
|
+
continue;
|
|
139
|
+
addParentDirs(args, writablePath, createdDirs);
|
|
140
|
+
addWritableBind(args, writablePath);
|
|
141
|
+
mountedPaths.push(writablePath);
|
|
142
|
+
}
|
|
143
|
+
if (!isPathCoveredBy(readablePaths, params.actualCwd) &&
|
|
144
|
+
!isPathCoveredBy(writablePaths, params.actualCwd)) {
|
|
145
|
+
if (!isPathCoveredBy(mountedPaths, params.actualCwd)) {
|
|
146
|
+
addParentDirs(args, params.actualCwd, createdDirs);
|
|
147
|
+
}
|
|
148
|
+
addReadOnlyBind(args, params.actualCwd);
|
|
149
|
+
}
|
|
150
|
+
args.push("--chdir", params.actualCwd, params.shellPath, params.login ? "-lc" : "-c", params.cmd);
|
|
151
|
+
return args;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 在 Linux bubblewrap sandbox 中启动 shell 子进程。
|
|
155
|
+
*/
|
|
156
|
+
export async function spawnLinuxBubblewrapSandbox(params) {
|
|
157
|
+
await fs.ensureDir(params.config.sandboxDir);
|
|
158
|
+
await fs.ensureDir(params.config.tmpDir);
|
|
159
|
+
await fs.ensureDir(params.config.cacheDir);
|
|
160
|
+
await fs.ensureDir(params.executionDir);
|
|
161
|
+
for (const writablePath of params.config.writablePaths) {
|
|
162
|
+
await fs.ensureDir(writablePath);
|
|
163
|
+
}
|
|
164
|
+
const child = spawn("bwrap", buildLinuxBubblewrapArgs({
|
|
165
|
+
...params,
|
|
166
|
+
}), {
|
|
167
|
+
cwd: params.actualCwd,
|
|
168
|
+
stdio: "pipe",
|
|
169
|
+
env: buildSandboxEnv(params),
|
|
170
|
+
});
|
|
171
|
+
child.stdout.setEncoding("utf8");
|
|
172
|
+
child.stderr.setEncoding("utf8");
|
|
173
|
+
return {
|
|
174
|
+
child,
|
|
175
|
+
cwd: params.actualCwd,
|
|
176
|
+
sandboxed: true,
|
|
177
|
+
sandboxMode: "safe",
|
|
178
|
+
backend: "linux-bubblewrap",
|
|
179
|
+
networkMode: params.config.networkMode,
|
|
180
|
+
sandboxDir: params.config.sandboxDir,
|
|
181
|
+
homeDir: params.config.homeDir,
|
|
182
|
+
tmpDir: params.config.tmpDir,
|
|
183
|
+
cacheDir: params.config.cacheDir,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=LinuxBubblewrapSandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LinuxBubblewrapSandbox.js","sourceRoot":"","sources":["../../src/sandbox/LinuxBubblewrapSandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* macOS Seatbelt sandbox backend。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 当前最小实现直接基于系统自带 `sandbox-exec`。
|
|
6
|
+
* - 目标不是抽象完整 provider 体系,而是先把 shell 命令从“宿主机直跑”收敛成“带边界执行”。
|
|
7
|
+
* - 边界只保留四类:路径、环境变量、网络、agent 级共享 HOME/TMPDIR/cache。
|
|
8
|
+
*/
|
|
9
|
+
import type { SandboxSpawnParams, SandboxSpawnResult } from "../sandbox/types/SandboxRuntime.js";
|
|
10
|
+
/**
|
|
11
|
+
* 在 macOS seatbelt sandbox 中启动 shell 子进程。
|
|
12
|
+
*/
|
|
13
|
+
export declare function spawnMacOsSeatbeltSandbox(params: SandboxSpawnParams & {
|
|
14
|
+
actualCwd: string;
|
|
15
|
+
}): Promise<SandboxSpawnResult>;
|
|
16
|
+
//# sourceMappingURL=MacOsSeatbeltSandbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MacOsSeatbeltSandbox.d.ts","sourceRoot":"","sources":["../../src/sandbox/MacOsSeatbeltSandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,mCAAmC,CAAC;AA8H3C;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,kBAAkB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,GACjD,OAAO,CAAC,kBAAkB,CAAC,CA4C7B"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* macOS Seatbelt sandbox backend。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 当前最小实现直接基于系统自带 `sandbox-exec`。
|
|
6
|
+
* - 目标不是抽象完整 provider 体系,而是先把 shell 命令从“宿主机直跑”收敛成“带边界执行”。
|
|
7
|
+
* - 边界只保留四类:路径、环境变量、网络、agent 级共享 HOME/TMPDIR/cache。
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import fs from "fs-extra";
|
|
12
|
+
const DEFAULT_PATH_VALUE = "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
|
|
13
|
+
function escapeSeatbeltString(value) {
|
|
14
|
+
return String(value || "").replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
15
|
+
}
|
|
16
|
+
function dedupePaths(values) {
|
|
17
|
+
const seen = new Set();
|
|
18
|
+
const result = [];
|
|
19
|
+
for (const value of values) {
|
|
20
|
+
const normalized = path.resolve(String(value || "").trim());
|
|
21
|
+
if (!normalized || seen.has(normalized))
|
|
22
|
+
continue;
|
|
23
|
+
seen.add(normalized);
|
|
24
|
+
result.push(normalized);
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
function buildReadablePaths(params) {
|
|
29
|
+
return dedupePaths([
|
|
30
|
+
"/bin",
|
|
31
|
+
"/usr",
|
|
32
|
+
"/System",
|
|
33
|
+
"/etc",
|
|
34
|
+
"/dev",
|
|
35
|
+
"/Library",
|
|
36
|
+
"/opt/homebrew",
|
|
37
|
+
"/usr/local",
|
|
38
|
+
params.rootPath,
|
|
39
|
+
params.sandboxDir,
|
|
40
|
+
params.tmpDir,
|
|
41
|
+
params.cacheDir,
|
|
42
|
+
path.dirname(params.shellPath),
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
function buildWritablePaths(params) {
|
|
46
|
+
return dedupePaths([
|
|
47
|
+
...params.config.writablePaths,
|
|
48
|
+
params.executionDir,
|
|
49
|
+
params.config.sandboxDir,
|
|
50
|
+
params.config.tmpDir,
|
|
51
|
+
params.config.cacheDir,
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
function buildNetworkRules(networkMode) {
|
|
55
|
+
if (networkMode === "restricted" || networkMode === "full") {
|
|
56
|
+
return ["(allow network-outbound)", "(allow network-inbound)"];
|
|
57
|
+
}
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
function buildSeatbeltProfile(params) {
|
|
61
|
+
const readablePaths = buildReadablePaths({
|
|
62
|
+
rootPath: params.config.rootPath,
|
|
63
|
+
shellPath: params.shellPath,
|
|
64
|
+
sandboxDir: params.config.sandboxDir,
|
|
65
|
+
tmpDir: params.config.tmpDir,
|
|
66
|
+
cacheDir: params.config.cacheDir,
|
|
67
|
+
});
|
|
68
|
+
const writablePaths = buildWritablePaths(params);
|
|
69
|
+
const lines = [
|
|
70
|
+
"(version 1)",
|
|
71
|
+
"(deny default)",
|
|
72
|
+
'(import "system.sb")',
|
|
73
|
+
"(allow process*)",
|
|
74
|
+
"(allow sysctl-read)",
|
|
75
|
+
"(allow file-read-metadata)",
|
|
76
|
+
...readablePaths.map((value) => `(allow file-read* (subpath "${escapeSeatbeltString(value)}"))`),
|
|
77
|
+
...writablePaths.map((value) => `(allow file-write* (subpath "${escapeSeatbeltString(value)}"))`),
|
|
78
|
+
...buildNetworkRules(params.config.networkMode),
|
|
79
|
+
];
|
|
80
|
+
// 关键点(中文)
|
|
81
|
+
// - `cwd` 需要显式出现在读集合里,否则很多命令刚启动时就会因为工作目录不可见而失败。
|
|
82
|
+
// - 这里单独追加,避免未来 rootPath 与 cwd 的关系变化时被遗漏。
|
|
83
|
+
if (!readablePaths.includes(params.actualCwd)) {
|
|
84
|
+
lines.push(`(allow file-read* (subpath "${escapeSeatbeltString(params.actualCwd)}"))`);
|
|
85
|
+
}
|
|
86
|
+
return `${lines.join("\n")}\n`;
|
|
87
|
+
}
|
|
88
|
+
function buildSandboxEnv(params) {
|
|
89
|
+
const env = {};
|
|
90
|
+
for (const key of params.config.envAllowlist) {
|
|
91
|
+
const value = params.baseEnv[key];
|
|
92
|
+
if (typeof value !== "string" || !value.trim())
|
|
93
|
+
continue;
|
|
94
|
+
env[key] = value;
|
|
95
|
+
}
|
|
96
|
+
for (const [key, value] of Object.entries(params.baseEnv)) {
|
|
97
|
+
if (!key.startsWith("DC_"))
|
|
98
|
+
continue;
|
|
99
|
+
if (typeof value !== "string" || !value.trim())
|
|
100
|
+
continue;
|
|
101
|
+
env[key] = value;
|
|
102
|
+
}
|
|
103
|
+
env.PATH = String(env.PATH || params.baseEnv.PATH || DEFAULT_PATH_VALUE);
|
|
104
|
+
env.HOME = params.config.homeDir;
|
|
105
|
+
env.ZDOTDIR = params.config.homeDir;
|
|
106
|
+
env.TMPDIR = params.config.tmpDir;
|
|
107
|
+
env.XDG_CACHE_HOME = params.config.cacheDir;
|
|
108
|
+
env.DC_SANDBOX = "1";
|
|
109
|
+
env.DC_SANDBOX_DIR = params.config.sandboxDir;
|
|
110
|
+
env.DC_SANDBOX_HOME = params.config.homeDir;
|
|
111
|
+
env.DC_SANDBOX_CACHE = params.config.cacheDir;
|
|
112
|
+
env.SHELL = params.shellPath;
|
|
113
|
+
return env;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 在 macOS seatbelt sandbox 中启动 shell 子进程。
|
|
117
|
+
*/
|
|
118
|
+
export async function spawnMacOsSeatbeltSandbox(params) {
|
|
119
|
+
const profilePath = path.join(params.executionDir, "sandbox-profile.sb");
|
|
120
|
+
await fs.ensureDir(params.config.sandboxDir);
|
|
121
|
+
await fs.ensureDir(params.config.tmpDir);
|
|
122
|
+
await fs.ensureDir(params.config.cacheDir);
|
|
123
|
+
await fs.ensureDir(params.executionDir);
|
|
124
|
+
const profile = buildSeatbeltProfile({
|
|
125
|
+
...params,
|
|
126
|
+
});
|
|
127
|
+
await fs.writeFile(profilePath, profile, "utf-8");
|
|
128
|
+
const child = spawn("sandbox-exec", [
|
|
129
|
+
"-f",
|
|
130
|
+
profilePath,
|
|
131
|
+
params.shellPath,
|
|
132
|
+
params.login ? "-lc" : "-c",
|
|
133
|
+
params.cmd,
|
|
134
|
+
], {
|
|
135
|
+
cwd: params.actualCwd,
|
|
136
|
+
stdio: "pipe",
|
|
137
|
+
env: buildSandboxEnv(params),
|
|
138
|
+
});
|
|
139
|
+
child.stdout.setEncoding("utf8");
|
|
140
|
+
child.stderr.setEncoding("utf8");
|
|
141
|
+
return {
|
|
142
|
+
child,
|
|
143
|
+
cwd: params.actualCwd,
|
|
144
|
+
sandboxed: true,
|
|
145
|
+
sandboxMode: "safe",
|
|
146
|
+
backend: "macos-seatbelt",
|
|
147
|
+
networkMode: params.config.networkMode,
|
|
148
|
+
sandboxDir: params.config.sandboxDir,
|
|
149
|
+
homeDir: params.config.homeDir,
|
|
150
|
+
tmpDir: params.config.tmpDir,
|
|
151
|
+
cacheDir: params.config.cacheDir,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=MacOsSeatbeltSandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MacOsSeatbeltSandbox.js","sourceRoot":"","sources":["../../src/sandbox/MacOsSeatbeltSandbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox 配置解析器。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 这里负责把 `downcity.json` 中面向用户的最小配置,收敛成运行时可直接执行的绝对路径配置。
|
|
6
|
+
* - sandbox 是 agent 项目级能力,持久目录固定为 `<project>/.downcity/sandbox`。
|
|
7
|
+
* - 当前版本只服务 shell / CLI 这条命令执行链,不引入审批、profile 绑定或用户权限系统。
|
|
8
|
+
* - 解析结果只回答一个问题:这次命令执行的 sandbox 边界是什么。
|
|
9
|
+
*/
|
|
10
|
+
import type { ShellHostContext } from "../types/ShellHostContext.js";
|
|
11
|
+
import type { SandboxBackend } from "../sandbox/types/SandboxRuntime.js";
|
|
12
|
+
import type { ResolvedSandboxConfig } from "../sandbox/types/SandboxRuntime.js";
|
|
13
|
+
/**
|
|
14
|
+
* 判断目标路径是否位于根目录内,或与根目录本身相同。
|
|
15
|
+
*/
|
|
16
|
+
export declare function isPathInsideRoot(rootPath: string, targetPath: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* 根据宿主平台解析当前 sandbox backend。
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveSandboxBackend(): SandboxBackend;
|
|
21
|
+
/**
|
|
22
|
+
* 解析当前请求最终使用的 sandbox 配置。
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveSandboxConfig(context: ShellHostContext): ResolvedSandboxConfig;
|
|
25
|
+
/**
|
|
26
|
+
* 归一化 sandbox 内实际使用的工作目录。
|
|
27
|
+
*
|
|
28
|
+
* 说明(中文)
|
|
29
|
+
* - sandbox 启用时,工作目录必须收敛在 `rootPath` 范围内。
|
|
30
|
+
* - 超出项目根目录的 `cwd` 会被强制拉回 `rootPath`,避免宿主目录通过 `cwd` 泄漏回去。
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveSandboxCwd(params: {
|
|
33
|
+
rootPath: string;
|
|
34
|
+
requestedCwd: string;
|
|
35
|
+
context: ShellHostContext;
|
|
36
|
+
}): string;
|
|
37
|
+
//# sourceMappingURL=SandboxConfigResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SandboxConfigResolver.d.ts","sourceRoot":"","sources":["../../src/sandbox/SandboxConfigResolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AA4B/E;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAM9E;AAyCD;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,cAAc,CAMtD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,gBAAgB,GAAG,qBAAqB,CAuBrF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,gBAAgB,CAAC;CAC3B,GAAG,MAAM,CAUT"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sandbox 配置解析器。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 这里负责把 `downcity.json` 中面向用户的最小配置,收敛成运行时可直接执行的绝对路径配置。
|
|
6
|
+
* - sandbox 是 agent 项目级能力,持久目录固定为 `<project>/.downcity/sandbox`。
|
|
7
|
+
* - 当前版本只服务 shell / CLI 这条命令执行链,不引入审批、profile 绑定或用户权限系统。
|
|
8
|
+
* - 解析结果只回答一个问题:这次命令执行的 sandbox 边界是什么。
|
|
9
|
+
*/
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
const DEFAULT_ENV_ALLOWLIST = [
|
|
12
|
+
"PATH",
|
|
13
|
+
"LANG",
|
|
14
|
+
"TERM",
|
|
15
|
+
"COLORTERM",
|
|
16
|
+
"LC_ALL",
|
|
17
|
+
"LC_CTYPE",
|
|
18
|
+
"SHELL",
|
|
19
|
+
"USER",
|
|
20
|
+
"LOGNAME",
|
|
21
|
+
];
|
|
22
|
+
const SANDBOX_RELATIVE_DIR = path.join(".downcity", "sandbox");
|
|
23
|
+
function normalizeEnvAllowlist(values) {
|
|
24
|
+
const seen = new Set();
|
|
25
|
+
const result = [];
|
|
26
|
+
for (const value of values || DEFAULT_ENV_ALLOWLIST) {
|
|
27
|
+
const normalized = String(value || "").trim();
|
|
28
|
+
if (!normalized || seen.has(normalized))
|
|
29
|
+
continue;
|
|
30
|
+
seen.add(normalized);
|
|
31
|
+
result.push(normalized);
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 判断目标路径是否位于根目录内,或与根目录本身相同。
|
|
37
|
+
*/
|
|
38
|
+
export function isPathInsideRoot(rootPath, targetPath) {
|
|
39
|
+
const normalizedRoot = path.resolve(rootPath);
|
|
40
|
+
const normalizedTarget = path.resolve(targetPath);
|
|
41
|
+
if (normalizedRoot === normalizedTarget)
|
|
42
|
+
return true;
|
|
43
|
+
const relative = path.relative(normalizedRoot, normalizedTarget);
|
|
44
|
+
return Boolean(relative) && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
45
|
+
}
|
|
46
|
+
function normalizeWritablePaths(params) {
|
|
47
|
+
const { rootPath, sandboxDir, writablePaths, context } = params;
|
|
48
|
+
const rawValues = Array.isArray(writablePaths) && writablePaths.length > 0
|
|
49
|
+
? [rootPath, sandboxDir, ...writablePaths]
|
|
50
|
+
: [rootPath, sandboxDir];
|
|
51
|
+
const seen = new Set();
|
|
52
|
+
const result = [];
|
|
53
|
+
for (const rawValue of rawValues) {
|
|
54
|
+
const normalizedValue = String(rawValue || "").trim();
|
|
55
|
+
if (!normalizedValue)
|
|
56
|
+
continue;
|
|
57
|
+
const resolvedPath = path.resolve(path.isAbsolute(normalizedValue) ? normalizedValue : path.join(rootPath, normalizedValue));
|
|
58
|
+
if (!isPathInsideRoot(rootPath, resolvedPath)) {
|
|
59
|
+
context.logger?.warn("[sandbox] writable path ignored because it escapes project root", {
|
|
60
|
+
rootPath,
|
|
61
|
+
ignoredPath: normalizedValue,
|
|
62
|
+
resolvedPath,
|
|
63
|
+
});
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (seen.has(resolvedPath))
|
|
67
|
+
continue;
|
|
68
|
+
seen.add(resolvedPath);
|
|
69
|
+
result.push(resolvedPath);
|
|
70
|
+
}
|
|
71
|
+
if (result.length === 0) {
|
|
72
|
+
result.push(path.resolve(rootPath));
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 根据宿主平台解析当前 sandbox backend。
|
|
78
|
+
*/
|
|
79
|
+
export function resolveSandboxBackend() {
|
|
80
|
+
if (process.platform === "darwin")
|
|
81
|
+
return "macos-seatbelt";
|
|
82
|
+
if (process.platform === "linux")
|
|
83
|
+
return "linux-bubblewrap";
|
|
84
|
+
throw new Error(`sandbox backend is required for shell execution, but current platform is unsupported: ${process.platform}`);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 解析当前请求最终使用的 sandbox 配置。
|
|
88
|
+
*/
|
|
89
|
+
export function resolveSandboxConfig(context) {
|
|
90
|
+
const rootPath = path.resolve(context.rootPath);
|
|
91
|
+
const projectConfig = context.config?.sandbox;
|
|
92
|
+
const sandboxDir = path.join(rootPath, SANDBOX_RELATIVE_DIR);
|
|
93
|
+
const tmpDir = path.join(sandboxDir, "tmp");
|
|
94
|
+
const cacheDir = path.join(sandboxDir, ".cache");
|
|
95
|
+
return {
|
|
96
|
+
backend: resolveSandboxBackend(),
|
|
97
|
+
rootPath,
|
|
98
|
+
sandboxDir,
|
|
99
|
+
homeDir: sandboxDir,
|
|
100
|
+
tmpDir,
|
|
101
|
+
cacheDir,
|
|
102
|
+
envAllowlist: normalizeEnvAllowlist(projectConfig?.envAllowlist),
|
|
103
|
+
writablePaths: normalizeWritablePaths({
|
|
104
|
+
rootPath,
|
|
105
|
+
sandboxDir,
|
|
106
|
+
writablePaths: projectConfig?.writablePaths,
|
|
107
|
+
context,
|
|
108
|
+
}),
|
|
109
|
+
networkMode: projectConfig?.networkMode || "full",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* 归一化 sandbox 内实际使用的工作目录。
|
|
114
|
+
*
|
|
115
|
+
* 说明(中文)
|
|
116
|
+
* - sandbox 启用时,工作目录必须收敛在 `rootPath` 范围内。
|
|
117
|
+
* - 超出项目根目录的 `cwd` 会被强制拉回 `rootPath`,避免宿主目录通过 `cwd` 泄漏回去。
|
|
118
|
+
*/
|
|
119
|
+
export function resolveSandboxCwd(params) {
|
|
120
|
+
const normalizedCwd = path.resolve(params.requestedCwd);
|
|
121
|
+
if (isPathInsideRoot(params.rootPath, normalizedCwd)) {
|
|
122
|
+
return normalizedCwd;
|
|
123
|
+
}
|
|
124
|
+
params.context.logger?.warn("[sandbox] cwd escapes project root and was reset to rootPath", {
|
|
125
|
+
rootPath: params.rootPath,
|
|
126
|
+
requestedCwd: normalizedCwd,
|
|
127
|
+
});
|
|
128
|
+
return params.rootPath;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=SandboxConfigResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SandboxConfigResolver.js","sourceRoot":"","sources":["../../src/sandbox/SandboxConfigResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SandboxPreflight:本机 shell sandbox 依赖预检。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - shell 命令必须进入 sandbox;这里提前检查 backend 依赖,避免启动后首次 shell 执行才失败。
|
|
6
|
+
* - Linux backend 基于 bubblewrap,本质使用 Linux namespaces / bind mount 等内核能力。
|
|
7
|
+
* - 本模块只诊断并给出修复建议,不自动安装软件,也不修改宿主机 sysctl。
|
|
8
|
+
*/
|
|
9
|
+
import type { SandboxBackend } from "../sandbox/types/SandboxRuntime.js";
|
|
10
|
+
/**
|
|
11
|
+
* sandbox 预检失败原因。
|
|
12
|
+
*/
|
|
13
|
+
export type SandboxPreflightIssueCode = "unsupported-platform" | "missing-command" | "userns-disabled";
|
|
14
|
+
/**
|
|
15
|
+
* 单条 sandbox 预检失败。
|
|
16
|
+
*/
|
|
17
|
+
export interface SandboxPreflightIssue {
|
|
18
|
+
/**
|
|
19
|
+
* 机器可读的失败原因。
|
|
20
|
+
*/
|
|
21
|
+
code: SandboxPreflightIssueCode;
|
|
22
|
+
/**
|
|
23
|
+
* 人类可读的失败说明。
|
|
24
|
+
*/
|
|
25
|
+
message: string;
|
|
26
|
+
/**
|
|
27
|
+
* 可复制的修复建议列表。
|
|
28
|
+
*/
|
|
29
|
+
fixes: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* sandbox 预检结果。
|
|
33
|
+
*/
|
|
34
|
+
export interface SandboxPreflightResult {
|
|
35
|
+
/**
|
|
36
|
+
* 当前平台是否满足 shell sandbox 启动要求。
|
|
37
|
+
*/
|
|
38
|
+
ok: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* 当前宿主平台。
|
|
41
|
+
*/
|
|
42
|
+
platform: NodeJS.Platform;
|
|
43
|
+
/**
|
|
44
|
+
* 当前平台对应的 sandbox backend。
|
|
45
|
+
*/
|
|
46
|
+
backend?: SandboxBackend;
|
|
47
|
+
/**
|
|
48
|
+
* 失败原因集合。
|
|
49
|
+
*/
|
|
50
|
+
issues: SandboxPreflightIssue[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* sandbox 预检宿主探测依赖。
|
|
54
|
+
*/
|
|
55
|
+
export interface ShellSandboxPreflightProbe {
|
|
56
|
+
/**
|
|
57
|
+
* 判断命令是否存在于 PATH 中。
|
|
58
|
+
*/
|
|
59
|
+
commandExists(command: string): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* 读取 `/proc` 下整数配置。
|
|
62
|
+
*/
|
|
63
|
+
readProcInt(filePath: string): Promise<number | null>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* 检查当前宿主是否满足 shell sandbox 运行要求。
|
|
67
|
+
*/
|
|
68
|
+
export declare function checkShellSandboxPreflight(): Promise<SandboxPreflightResult>;
|
|
69
|
+
/**
|
|
70
|
+
* 使用注入探针检查当前宿主是否满足 shell sandbox 运行要求。
|
|
71
|
+
*/
|
|
72
|
+
export declare function checkShellSandboxPreflightWithProbe(probe: ShellSandboxPreflightProbe): Promise<SandboxPreflightResult>;
|
|
73
|
+
//# sourceMappingURL=SandboxPreflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SandboxPreflight.d.ts","sourceRoot":"","sources":["../../src/sandbox/SandboxPreflight.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAExE;;GAEG;AACH,MAAM,MAAM,yBAAyB,GACjC,sBAAsB,GACtB,iBAAiB,GACjB,iBAAiB,CAAC;AAEtB;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,IAAI,EAAE,yBAAyB,CAAC;IAEhC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,EAAE,EAAE,OAAO,CAAC;IAEZ;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAE1B;;OAEG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IAEzB;;OAEG;IACH,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjD;;OAEG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvD;AAyCD;;GAEG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAKlF;AAED;;GAEG;AACH,wBAAsB,mCAAmC,CACvD,KAAK,EAAE,0BAA0B,GAChC,OAAO,CAAC,sBAAsB,CAAC,CAoEjC"}
|