opencode-swarm 7.83.0 → 7.85.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.
- package/.opencode/skills/codebase-review-swarm/references/review-protocol-v8.2.md +4 -0
- package/.opencode/skills/council/SKILL.md +6 -1
- package/.opencode/skills/deep-dive/SKILL.md +2 -0
- package/.opencode/skills/deep-research/SKILL.md +6 -0
- package/.opencode/skills/swarm-pr-feedback/SKILL.md +6 -0
- package/.opencode/skills/swarm-pr-review/SKILL.md +4 -0
- package/README.md +3 -1
- package/dist/background/lane-output-store.d.ts +72 -0
- package/dist/background/pending-delegations.d.ts +6 -0
- package/dist/cli/capability-probe-jevmgwmf.js +18 -0
- package/dist/cli/config-doctor-zejarrr6.js +35 -0
- package/dist/cli/dispatch-k86d928w.js +477 -0
- package/dist/cli/evidence-summary-service-g2znnd33.js +320 -0
- package/dist/cli/explorer-gz70sm9b.js +16 -0
- package/dist/cli/gate-evidence-y8zn7fe2.js +29 -0
- package/dist/cli/guardrail-explain-w4txg349.js +30 -0
- package/dist/cli/guardrail-log-80116wmz.js +15 -0
- package/dist/cli/index-0sxvwjt0.js +1241 -0
- package/dist/cli/index-293f68mj.js +13538 -0
- package/dist/cli/index-5cb86007.js +110 -0
- package/dist/cli/index-a76rekgs.js +67 -0
- package/dist/cli/index-b9v501fr.js +371 -0
- package/dist/cli/index-bcp79s17.js +1673 -0
- package/dist/cli/index-ckntc5gf.js +91 -0
- package/dist/cli/index-d9fbxaqd.js +2314 -0
- package/dist/cli/index-e7h9bb6v.js +233 -0
- package/dist/cli/index-e8pk68cc.js +540 -0
- package/dist/cli/index-eb85wtx9.js +242 -0
- package/dist/cli/index-f8r50m3h.js +14505 -0
- package/dist/cli/index-fjwwrwr5.js +37 -0
- package/dist/cli/index-hw9b2xng.js +2046 -0
- package/dist/cli/index-hz59hg4h.js +452 -0
- package/dist/cli/index-jtqkh8jf.js +119 -0
- package/dist/cli/index-p0arc26j.js +28 -0
- package/dist/cli/index-p0ye10nd.js +222 -0
- package/dist/cli/index-qqabjns2.js +412 -0
- package/dist/cli/index-red8fm8p.js +2914 -0
- package/dist/cli/index-vq2321gg.js +2391 -0
- package/dist/cli/index-x7qck34v.js +583 -0
- package/dist/cli/index-yhqt45de.js +29027 -0
- package/dist/cli/index-yhsmmv2z.js +339 -0
- package/dist/cli/index-yx44zd0p.js +40 -0
- package/dist/cli/index-zfsbaaqh.js +29 -0
- package/dist/cli/index.js +73 -69708
- package/dist/cli/knowledge-store-n4x6zyk7.js +73 -0
- package/dist/cli/pending-delegations-rd40tv9s.js +261 -0
- package/dist/cli/pr-subscriptions-y1nn36e5.js +33 -0
- package/dist/cli/schema-8d32b2v6.js +168 -0
- package/dist/cli/skill-generator-a5ehggyg.js +55 -0
- package/dist/cli/task-envelope-qn0qtnh0.js +90 -0
- package/dist/cli/telemetry-9bbyxrvn.js +20 -0
- package/dist/cli/workspace-snapshot-w58jr2ga.js +90 -0
- package/dist/commands/guardrail-explain.d.ts +1 -0
- package/dist/commands/guardrail-log.d.ts +1 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/registry.d.ts +14 -0
- package/dist/hooks/guardrails/audit-log.d.ts +114 -0
- package/dist/index.js +4005 -2432
- package/dist/services/diagnose-service.d.ts +5 -0
- package/dist/services/guardrail-explain-service.d.ts +42 -0
- package/dist/services/guardrail-log-service.d.ts +10 -0
- package/dist/tools/dispatch-lanes.d.ts +14 -3
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/retrieve-lane-output.d.ts +2 -0
- package/dist/tools/tool-metadata.d.ts +4 -0
- package/package.json +2 -2
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
init_logger,
|
|
4
|
+
warn
|
|
5
|
+
} from "./index-yx44zd0p.js";
|
|
6
|
+
import {
|
|
7
|
+
__esm,
|
|
8
|
+
__export,
|
|
9
|
+
__toCommonJS
|
|
10
|
+
} from "./index-a76rekgs.js";
|
|
11
|
+
|
|
12
|
+
// src/sandbox/win32/runner-client.ts
|
|
13
|
+
var exports_runner_client = {};
|
|
14
|
+
__export(exports_runner_client, {
|
|
15
|
+
probe: () => probe,
|
|
16
|
+
execute: () => execute,
|
|
17
|
+
buildDefaultPolicy: () => buildDefaultPolicy,
|
|
18
|
+
_resetProbeCache: () => _resetProbeCache,
|
|
19
|
+
_internals: () => _internals,
|
|
20
|
+
RUNNER_EXIT_CODES: () => RUNNER_EXIT_CODES
|
|
21
|
+
});
|
|
22
|
+
import { spawn, spawnSync } from "child_process";
|
|
23
|
+
import * as fs from "fs";
|
|
24
|
+
import * as os from "os";
|
|
25
|
+
import * as path from "path";
|
|
26
|
+
import { fileURLToPath } from "url";
|
|
27
|
+
function findRunnerBinary() {
|
|
28
|
+
const arch = process.arch === "x64" ? "x64" : "arm64";
|
|
29
|
+
const platform = "win32";
|
|
30
|
+
const packagePaths = [
|
|
31
|
+
path.resolve(_runtimeDir, "..", "..", "..", "binaries", `${platform}-${arch}`, "swarm-sandbox-runner.exe"),
|
|
32
|
+
path.resolve(_runtimeDir, "..", "..", "..", "..", "binaries", `${platform}-${arch}`, "swarm-sandbox-runner.exe")
|
|
33
|
+
];
|
|
34
|
+
for (const p of packagePaths) {
|
|
35
|
+
try {
|
|
36
|
+
if (fs.existsSync(p)) {
|
|
37
|
+
return p;
|
|
38
|
+
}
|
|
39
|
+
} catch {}
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const result = spawnSync("where", ["swarm-sandbox-runner.exe"], {
|
|
43
|
+
windowsHide: true,
|
|
44
|
+
encoding: "utf-8",
|
|
45
|
+
timeout: 2000,
|
|
46
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
47
|
+
});
|
|
48
|
+
if (result.status === 0 && result.stdout?.trim()) {
|
|
49
|
+
return result.stdout.trim().split(`
|
|
50
|
+
`)[0]?.trim() ?? null;
|
|
51
|
+
}
|
|
52
|
+
} catch {}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
function probe() {
|
|
56
|
+
if (_cachedProbe !== undefined) {
|
|
57
|
+
return _cachedProbe;
|
|
58
|
+
}
|
|
59
|
+
if (process.platform !== "win32") {
|
|
60
|
+
_cachedProbe = {
|
|
61
|
+
available: false,
|
|
62
|
+
mode: "none",
|
|
63
|
+
capabilities: null,
|
|
64
|
+
error: "not Windows"
|
|
65
|
+
};
|
|
66
|
+
return _cachedProbe;
|
|
67
|
+
}
|
|
68
|
+
const binary = _internals.findRunnerBinary();
|
|
69
|
+
if (!binary) {
|
|
70
|
+
_cachedProbe = {
|
|
71
|
+
available: false,
|
|
72
|
+
mode: "none",
|
|
73
|
+
capabilities: null,
|
|
74
|
+
error: "runner binary not found"
|
|
75
|
+
};
|
|
76
|
+
warn("Sandbox runner binary not found \u2014 degrading to weak sandbox");
|
|
77
|
+
return _cachedProbe;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const result = _internals.spawnRunner(binary, ["--probe"], {
|
|
81
|
+
windowsHide: true,
|
|
82
|
+
encoding: "utf-8",
|
|
83
|
+
timeout: 2000,
|
|
84
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
85
|
+
cwd: os.tmpdir()
|
|
86
|
+
});
|
|
87
|
+
if (result.error) {
|
|
88
|
+
_cachedProbe = {
|
|
89
|
+
available: false,
|
|
90
|
+
mode: "none",
|
|
91
|
+
capabilities: null,
|
|
92
|
+
error: `probe spawn error: ${result.error.code ?? result.error.message}`
|
|
93
|
+
};
|
|
94
|
+
warn(`Sandbox runner probe failed: ${_cachedProbe.error}`);
|
|
95
|
+
return _cachedProbe;
|
|
96
|
+
}
|
|
97
|
+
if (result.status !== 0) {
|
|
98
|
+
_cachedProbe = {
|
|
99
|
+
available: false,
|
|
100
|
+
mode: "none",
|
|
101
|
+
capabilities: null,
|
|
102
|
+
error: `probe exited with code ${result.status}`
|
|
103
|
+
};
|
|
104
|
+
warn(`Sandbox runner probe failed: ${_cachedProbe.error}`);
|
|
105
|
+
return _cachedProbe;
|
|
106
|
+
}
|
|
107
|
+
const capabilities = JSON.parse(result.stdout?.trim() ?? "{}");
|
|
108
|
+
let mode = "none";
|
|
109
|
+
if (capabilities.app_container_available) {
|
|
110
|
+
mode = "app-container";
|
|
111
|
+
} else if (capabilities.restricted_token_available) {
|
|
112
|
+
mode = "restricted-token";
|
|
113
|
+
}
|
|
114
|
+
_cachedProbe = {
|
|
115
|
+
available: mode !== "none",
|
|
116
|
+
mode,
|
|
117
|
+
capabilities
|
|
118
|
+
};
|
|
119
|
+
return _cachedProbe;
|
|
120
|
+
} catch (err) {
|
|
121
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
122
|
+
_cachedProbe = {
|
|
123
|
+
available: false,
|
|
124
|
+
mode: "none",
|
|
125
|
+
capabilities: null,
|
|
126
|
+
error: `probe threw: ${msg}`
|
|
127
|
+
};
|
|
128
|
+
warn(`Sandbox runner probe threw: ${msg}`);
|
|
129
|
+
return _cachedProbe;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async function execute(command, policy, mode = "auto") {
|
|
133
|
+
const binary = _internals.findRunnerBinary();
|
|
134
|
+
if (!binary) {
|
|
135
|
+
throw new Error("runner binary not found");
|
|
136
|
+
}
|
|
137
|
+
const policyJson = JSON.stringify(policy);
|
|
138
|
+
const args = ["--policy-stdin", "--mode", mode, "--", ...command];
|
|
139
|
+
return new Promise((resolve2, reject) => {
|
|
140
|
+
let proc;
|
|
141
|
+
const timeout = setTimeout(() => {
|
|
142
|
+
proc?.kill();
|
|
143
|
+
reject(new Error("runner execution timeout"));
|
|
144
|
+
}, policy.wall_clock_timeout_ms + 5000);
|
|
145
|
+
const unref = timeout.unref;
|
|
146
|
+
if (typeof unref === "function") {
|
|
147
|
+
unref.call(timeout);
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
proc = _internals.spawnAsync(binary, args, {
|
|
151
|
+
windowsHide: true,
|
|
152
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
153
|
+
cwd: policy.workspace_roots[0] ?? os.tmpdir()
|
|
154
|
+
});
|
|
155
|
+
} catch (err) {
|
|
156
|
+
clearTimeout(timeout);
|
|
157
|
+
reject(err);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
proc.stdin?.write(policyJson);
|
|
161
|
+
proc.stdin?.end();
|
|
162
|
+
let stdout = "";
|
|
163
|
+
let stderr = "";
|
|
164
|
+
const events = [];
|
|
165
|
+
proc.stdout?.on("data", (chunk) => {
|
|
166
|
+
stdout += chunk.toString();
|
|
167
|
+
});
|
|
168
|
+
proc.stderr?.on("data", (chunk) => {
|
|
169
|
+
const lines = chunk.toString().split(`
|
|
170
|
+
`);
|
|
171
|
+
for (const line of lines) {
|
|
172
|
+
const trimmed = line.trim();
|
|
173
|
+
if (!trimmed)
|
|
174
|
+
continue;
|
|
175
|
+
try {
|
|
176
|
+
const event = JSON.parse(trimmed);
|
|
177
|
+
if (event.type) {
|
|
178
|
+
events.push(event);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
} catch {}
|
|
182
|
+
stderr += `${trimmed}
|
|
183
|
+
`;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
proc.on("error", (err) => {
|
|
187
|
+
clearTimeout(timeout);
|
|
188
|
+
reject(err);
|
|
189
|
+
});
|
|
190
|
+
proc.on("close", (code) => {
|
|
191
|
+
clearTimeout(timeout);
|
|
192
|
+
const startEvent = events.find((e) => e.type === "start");
|
|
193
|
+
const runnerMode = startEvent?.mode ?? mode;
|
|
194
|
+
resolve2({
|
|
195
|
+
exitCode: code ?? 1,
|
|
196
|
+
stdout,
|
|
197
|
+
stderr,
|
|
198
|
+
events,
|
|
199
|
+
mode: runnerMode
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function _resetProbeCache() {
|
|
205
|
+
_cachedProbe = undefined;
|
|
206
|
+
}
|
|
207
|
+
function buildDefaultPolicy(workspaceRoot, runId) {
|
|
208
|
+
const id = runId ?? `swarm-${crypto.randomUUID?.() ?? Date.now()}`;
|
|
209
|
+
const appData = process.env.LOCALAPPDATA ?? path.join(os.homedir(), "AppData", "Local");
|
|
210
|
+
const tempRoot = path.join(appData, "opencode-swarm", "sandbox", id, "temp");
|
|
211
|
+
return {
|
|
212
|
+
schema_version: 1,
|
|
213
|
+
run_id: id,
|
|
214
|
+
workspace_roots: [workspaceRoot],
|
|
215
|
+
writable_roots: [workspaceRoot],
|
|
216
|
+
read_only_subpaths: [".git", ".codex", ".agents", ".swarm"],
|
|
217
|
+
temp_root: tempRoot,
|
|
218
|
+
temp_cap_bytes: 524288000,
|
|
219
|
+
memory_cap_bytes: 2147483648,
|
|
220
|
+
child_process_cap: 16,
|
|
221
|
+
wall_clock_timeout_ms: 600000,
|
|
222
|
+
network_mode: "off",
|
|
223
|
+
env_allowlist: ["PATH", "TEMP", "TMP", "USERPROFILE", "SYSTEMROOT"],
|
|
224
|
+
env_overrides: {
|
|
225
|
+
HTTP_PROXY: "http://127.0.0.1:1",
|
|
226
|
+
HTTPS_PROXY: "http://127.0.0.1:1"
|
|
227
|
+
},
|
|
228
|
+
path_stubs: ["ssh.exe", "curl.exe", "wget.exe", "scp.exe", "sftp.exe"],
|
|
229
|
+
private_desktop: true,
|
|
230
|
+
deny_alternate_data_streams: true,
|
|
231
|
+
deny_unc_paths: true,
|
|
232
|
+
deny_device_paths: true,
|
|
233
|
+
deny_symlink_egress: true
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
var _runtimeDir, RUNNER_EXIT_CODES, _cachedProbe, _internals;
|
|
237
|
+
var init_runner_client = __esm(() => {
|
|
238
|
+
init_logger();
|
|
239
|
+
_runtimeDir = fileURLToPath(new URL(".", import.meta.url));
|
|
240
|
+
RUNNER_EXIT_CODES = {
|
|
241
|
+
SUCCESS: 0,
|
|
242
|
+
CHILD_NON_ZERO: 1,
|
|
243
|
+
POLICY_VIOLATION: 64,
|
|
244
|
+
QUOTA_EXCEEDED: 65,
|
|
245
|
+
WALL_CLOCK_TIMEOUT: 66,
|
|
246
|
+
LAUNCHER_MISCONFIG: 67,
|
|
247
|
+
OS_API_FAILURE: 68,
|
|
248
|
+
PROBE_FAILED: 69
|
|
249
|
+
};
|
|
250
|
+
_internals = {
|
|
251
|
+
findRunnerBinary,
|
|
252
|
+
spawnRunner: spawnSync,
|
|
253
|
+
spawnAsync: spawn
|
|
254
|
+
};
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// src/sandbox/capability-probe.ts
|
|
258
|
+
import { execFile, spawnSync as spawnSync2 } from "child_process";
|
|
259
|
+
import * as os2 from "os";
|
|
260
|
+
function withProbeTimeout(cmd, args, ms) {
|
|
261
|
+
return new Promise((resolve2, reject) => {
|
|
262
|
+
const controller = new AbortController;
|
|
263
|
+
const timer = setTimeout(() => {
|
|
264
|
+
controller.abort();
|
|
265
|
+
proc?.kill();
|
|
266
|
+
}, ms);
|
|
267
|
+
const unref = timer.unref;
|
|
268
|
+
if (typeof unref === "function") {
|
|
269
|
+
unref.call(timer);
|
|
270
|
+
}
|
|
271
|
+
let proc;
|
|
272
|
+
try {
|
|
273
|
+
proc = execFile(cmd, args, {
|
|
274
|
+
signal: controller.signal,
|
|
275
|
+
timeout: ms,
|
|
276
|
+
windowsHide: true,
|
|
277
|
+
cwd: os2.tmpdir()
|
|
278
|
+
}, (error, stdout, _stderr) => {
|
|
279
|
+
clearTimeout(timer);
|
|
280
|
+
if (error) {
|
|
281
|
+
const exc = error;
|
|
282
|
+
if (exc.code === "ENOENT" || exc.code === "ENOTFOUND") {
|
|
283
|
+
reject(new Error("binary not found"));
|
|
284
|
+
} else {
|
|
285
|
+
reject(error);
|
|
286
|
+
}
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
resolve2(stdout?.trim() ?? "");
|
|
290
|
+
});
|
|
291
|
+
} catch (spawnError) {
|
|
292
|
+
clearTimeout(timer);
|
|
293
|
+
reject(spawnError);
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
async function probeLinux() {
|
|
298
|
+
try {
|
|
299
|
+
const output = await withProbeTimeout("bwrap", ["--version"], 2000);
|
|
300
|
+
if (output.length > 0) {
|
|
301
|
+
return {
|
|
302
|
+
status: "enabled",
|
|
303
|
+
mechanism: "Bubblewrap",
|
|
304
|
+
platform: "linux"
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
return {
|
|
308
|
+
status: "disabled",
|
|
309
|
+
mechanism: "Bubblewrap",
|
|
310
|
+
platform: "linux",
|
|
311
|
+
error: "binary returned empty version"
|
|
312
|
+
};
|
|
313
|
+
} catch (err) {
|
|
314
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
315
|
+
if (msg === "binary not found") {
|
|
316
|
+
return {
|
|
317
|
+
status: "unsupported",
|
|
318
|
+
mechanism: "Bubblewrap",
|
|
319
|
+
platform: "linux",
|
|
320
|
+
error: msg
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
status: "disabled",
|
|
325
|
+
mechanism: "Bubblewrap",
|
|
326
|
+
platform: "linux",
|
|
327
|
+
error: msg
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
async function probeMacOS() {
|
|
332
|
+
try {
|
|
333
|
+
const output = await withProbeTimeout("sandbox-exec", ["--version"], 2000);
|
|
334
|
+
if (output.length > 0) {
|
|
335
|
+
return {
|
|
336
|
+
status: "enabled",
|
|
337
|
+
mechanism: "sandbox-exec",
|
|
338
|
+
platform: "darwin"
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
status: "disabled",
|
|
343
|
+
mechanism: "sandbox-exec",
|
|
344
|
+
platform: "darwin",
|
|
345
|
+
error: "binary returned empty version"
|
|
346
|
+
};
|
|
347
|
+
} catch (err) {
|
|
348
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
349
|
+
if (msg === "binary not found") {
|
|
350
|
+
return {
|
|
351
|
+
status: "unsupported",
|
|
352
|
+
mechanism: "sandbox-exec",
|
|
353
|
+
platform: "darwin",
|
|
354
|
+
error: msg
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
status: "disabled",
|
|
359
|
+
mechanism: "sandbox-exec",
|
|
360
|
+
platform: "darwin",
|
|
361
|
+
error: msg
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
function probeWindows() {
|
|
366
|
+
try {
|
|
367
|
+
const { probe: runnerProbe } = (init_runner_client(), __toCommonJS(exports_runner_client));
|
|
368
|
+
const result = runnerProbe();
|
|
369
|
+
if (result.available) {
|
|
370
|
+
return {
|
|
371
|
+
status: "enabled",
|
|
372
|
+
platform: "win32",
|
|
373
|
+
mechanism: `native-runner/${result.mode}`
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
} catch {}
|
|
377
|
+
try {
|
|
378
|
+
const result = spawnSync2("cmd", ["/c", "echo", "ok"], {
|
|
379
|
+
windowsHide: true,
|
|
380
|
+
encoding: "utf-8",
|
|
381
|
+
timeout: 5000,
|
|
382
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
383
|
+
});
|
|
384
|
+
if (result.error) {
|
|
385
|
+
return {
|
|
386
|
+
status: "disabled",
|
|
387
|
+
platform: "win32",
|
|
388
|
+
mechanism: "PowerShell wrapper",
|
|
389
|
+
error: `cmd.exe probe failed: ${result.error.code}`
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
return result.status === 0 ? {
|
|
393
|
+
status: "enabled",
|
|
394
|
+
platform: "win32",
|
|
395
|
+
mechanism: "PowerShell wrapper"
|
|
396
|
+
} : {
|
|
397
|
+
status: "disabled",
|
|
398
|
+
platform: "win32",
|
|
399
|
+
mechanism: "PowerShell wrapper",
|
|
400
|
+
error: "cmd.exe probe returned non-zero"
|
|
401
|
+
};
|
|
402
|
+
} catch (err) {
|
|
403
|
+
return {
|
|
404
|
+
status: "disabled",
|
|
405
|
+
platform: "win32",
|
|
406
|
+
mechanism: "PowerShell wrapper",
|
|
407
|
+
error: String(err)
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
function isBubblewrapAvailable() {
|
|
412
|
+
return _cached?.status === "enabled" && _cached?.platform === "linux";
|
|
413
|
+
}
|
|
414
|
+
function isSandboxExecAvailable() {
|
|
415
|
+
return _cached?.status === "enabled" && _cached?.platform === "darwin";
|
|
416
|
+
}
|
|
417
|
+
function isWindowsSandboxAvailable() {
|
|
418
|
+
return _cached?.status === "enabled" && _cached?.platform === "win32";
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
class SandboxCapabilityProbe {
|
|
422
|
+
async detect() {
|
|
423
|
+
if (_cached !== undefined) {
|
|
424
|
+
return _cached;
|
|
425
|
+
}
|
|
426
|
+
const platform = process.platform;
|
|
427
|
+
switch (platform) {
|
|
428
|
+
case "linux":
|
|
429
|
+
_cached = await probeLinux();
|
|
430
|
+
break;
|
|
431
|
+
case "darwin":
|
|
432
|
+
_cached = await probeMacOS();
|
|
433
|
+
break;
|
|
434
|
+
case "win32":
|
|
435
|
+
_cached = probeWindows();
|
|
436
|
+
break;
|
|
437
|
+
default: {
|
|
438
|
+
_cached = {
|
|
439
|
+
status: "unsupported",
|
|
440
|
+
mechanism: "unknown",
|
|
441
|
+
platform,
|
|
442
|
+
error: `unsupported platform: ${platform}`
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return _cached;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
var _cached;
|
|
450
|
+
var init_capability_probe = () => {};
|
|
451
|
+
|
|
452
|
+
export { _internals, probe, execute, buildDefaultPolicy, init_runner_client, isBubblewrapAvailable, isSandboxExecAvailable, isWindowsSandboxAvailable, SandboxCapabilityProbe, init_capability_probe };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/utils/swarm-artifact-cache.ts
|
|
3
|
+
import * as fs from "fs/promises";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
var MAX_CACHE_ENTRIES = 128;
|
|
6
|
+
var textCache = new Map;
|
|
7
|
+
var parsedCache = new Map;
|
|
8
|
+
var stats = {
|
|
9
|
+
textReadCount: 0,
|
|
10
|
+
textCacheHitCount: 0,
|
|
11
|
+
textCacheMissCount: 0,
|
|
12
|
+
parsedReadCount: 0,
|
|
13
|
+
parseCount: 0,
|
|
14
|
+
parsedCacheHitCount: 0,
|
|
15
|
+
parsedCacheMissCount: 0,
|
|
16
|
+
statFailureCount: 0,
|
|
17
|
+
evictionCount: 0,
|
|
18
|
+
textEvictionCount: 0,
|
|
19
|
+
parsedEvictionCount: 0,
|
|
20
|
+
cloneFallbackCount: 0,
|
|
21
|
+
textEntryCount: 0,
|
|
22
|
+
parsedEntryCount: 0
|
|
23
|
+
};
|
|
24
|
+
function sameStamp(a, b) {
|
|
25
|
+
return a.mtimeMs === b.mtimeMs && a.ctimeMs === b.ctimeMs && a.size === b.size;
|
|
26
|
+
}
|
|
27
|
+
async function getStamp(filePath) {
|
|
28
|
+
try {
|
|
29
|
+
const stat2 = await fs.stat(filePath);
|
|
30
|
+
if (!stat2.isFile())
|
|
31
|
+
return null;
|
|
32
|
+
return { mtimeMs: stat2.mtimeMs, ctimeMs: stat2.ctimeMs, size: stat2.size };
|
|
33
|
+
} catch {
|
|
34
|
+
stats.statFailureCount++;
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function canStoreRead(before, after) {
|
|
39
|
+
return after !== null && sameStamp(before, after);
|
|
40
|
+
}
|
|
41
|
+
function setBounded(cache, key, value, cacheKind) {
|
|
42
|
+
cache.set(key, value);
|
|
43
|
+
while (cache.size > MAX_CACHE_ENTRIES) {
|
|
44
|
+
const oldest = cache.keys().next().value;
|
|
45
|
+
if (oldest === undefined)
|
|
46
|
+
break;
|
|
47
|
+
cache.delete(oldest);
|
|
48
|
+
stats.evictionCount++;
|
|
49
|
+
if (cacheKind === "text") {
|
|
50
|
+
stats.textEvictionCount++;
|
|
51
|
+
} else {
|
|
52
|
+
stats.parsedEvictionCount++;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
stats.textEntryCount = textCache.size;
|
|
56
|
+
stats.parsedEntryCount = parsedCache.size;
|
|
57
|
+
}
|
|
58
|
+
function cloneCachedValue(value) {
|
|
59
|
+
if (value === null || typeof value !== "object")
|
|
60
|
+
return value;
|
|
61
|
+
if (typeof structuredClone === "function") {
|
|
62
|
+
return structuredClone(value);
|
|
63
|
+
}
|
|
64
|
+
stats.cloneFallbackCount++;
|
|
65
|
+
return JSON.parse(JSON.stringify(value));
|
|
66
|
+
}
|
|
67
|
+
async function readCachedTextFile(filePath, directRead) {
|
|
68
|
+
const cacheKey = path.resolve(filePath);
|
|
69
|
+
const stamp = await getStamp(cacheKey);
|
|
70
|
+
if (!stamp) {
|
|
71
|
+
stats.textReadCount++;
|
|
72
|
+
return directRead();
|
|
73
|
+
}
|
|
74
|
+
const cached = textCache.get(cacheKey);
|
|
75
|
+
if (cached && sameStamp(cached, stamp)) {
|
|
76
|
+
stats.textCacheHitCount++;
|
|
77
|
+
return cached.value;
|
|
78
|
+
}
|
|
79
|
+
stats.textCacheMissCount++;
|
|
80
|
+
stats.textReadCount++;
|
|
81
|
+
const value = await directRead();
|
|
82
|
+
const afterReadStamp = await getStamp(cacheKey);
|
|
83
|
+
if (value !== null && canStoreRead(stamp, afterReadStamp)) {
|
|
84
|
+
setBounded(textCache, cacheKey, { ...afterReadStamp, value }, "text");
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
async function readCachedParsedFile(filePath, namespace, readText, parse) {
|
|
89
|
+
const resolvedPath = path.resolve(filePath);
|
|
90
|
+
const cacheKey = `${resolvedPath}\x00${namespace}`;
|
|
91
|
+
const stamp = await getStamp(resolvedPath);
|
|
92
|
+
if (!stamp) {
|
|
93
|
+
stats.parsedReadCount++;
|
|
94
|
+
const content2 = await readText();
|
|
95
|
+
if (content2 === null)
|
|
96
|
+
return null;
|
|
97
|
+
stats.parseCount++;
|
|
98
|
+
return parse(content2);
|
|
99
|
+
}
|
|
100
|
+
const cached = parsedCache.get(cacheKey);
|
|
101
|
+
if (cached && sameStamp(cached, stamp)) {
|
|
102
|
+
stats.parsedCacheHitCount++;
|
|
103
|
+
return cloneCachedValue(cached.value);
|
|
104
|
+
}
|
|
105
|
+
stats.parsedCacheMissCount++;
|
|
106
|
+
stats.parsedReadCount++;
|
|
107
|
+
const content = await readText();
|
|
108
|
+
if (content === null)
|
|
109
|
+
return null;
|
|
110
|
+
stats.parseCount++;
|
|
111
|
+
const value = parse(content);
|
|
112
|
+
const afterReadStamp = await getStamp(resolvedPath);
|
|
113
|
+
if (canStoreRead(stamp, afterReadStamp)) {
|
|
114
|
+
setBounded(parsedCache, cacheKey, { ...afterReadStamp, value }, "parsed");
|
|
115
|
+
}
|
|
116
|
+
return cloneCachedValue(value);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { readCachedTextFile, readCachedParsedFile };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/utils/merge.ts
|
|
3
|
+
var MAX_MERGE_DEPTH = 10;
|
|
4
|
+
function deepMergeInternal(base, override, depth) {
|
|
5
|
+
if (depth >= MAX_MERGE_DEPTH) {
|
|
6
|
+
throw new Error(`deepMerge exceeded maximum depth of ${MAX_MERGE_DEPTH}`);
|
|
7
|
+
}
|
|
8
|
+
const result = { ...base };
|
|
9
|
+
for (const key of Object.keys(override)) {
|
|
10
|
+
const baseVal = base[key];
|
|
11
|
+
const overrideVal = override[key];
|
|
12
|
+
if (typeof baseVal === "object" && baseVal !== null && typeof overrideVal === "object" && overrideVal !== null && !Array.isArray(baseVal) && !Array.isArray(overrideVal)) {
|
|
13
|
+
result[key] = deepMergeInternal(baseVal, overrideVal, depth + 1);
|
|
14
|
+
} else {
|
|
15
|
+
result[key] = overrideVal;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
function deepMerge(base, override) {
|
|
21
|
+
if (!base)
|
|
22
|
+
return override;
|
|
23
|
+
if (!override)
|
|
24
|
+
return base;
|
|
25
|
+
return deepMergeInternal(base, override, 0);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { deepMerge };
|