@probelabs/visor 0.1.144 → 0.1.145
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/config.d.ts.map +1 -1
- package/dist/docs/architecture.md +28 -0
- package/dist/docs/configuration.md +2 -0
- package/dist/docs/sandbox-engines.md +357 -0
- package/dist/docs/security.md +40 -0
- package/dist/generated/config-schema.d.ts +5 -0
- package/dist/generated/config-schema.d.ts.map +1 -1
- package/dist/generated/config-schema.json +9 -0
- package/dist/index.js +670 -162
- package/dist/output/traces/{run-2026-02-25T17-29-59-894Z.ndjson → run-2026-02-26T07-47-34-788Z.ndjson} +84 -84
- package/dist/{traces/run-2026-02-25T17-30-47-149Z.ndjson → output/traces/run-2026-02-26T07-48-25-935Z.ndjson} +1118 -1118
- package/dist/providers/mcp-check-provider.d.ts.map +1 -1
- package/dist/sandbox/bubblewrap-sandbox.d.ts +30 -0
- package/dist/sandbox/bubblewrap-sandbox.d.ts.map +1 -0
- package/dist/sandbox/index.d.ts +3 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/sandbox-manager.d.ts +3 -2
- package/dist/sandbox/sandbox-manager.d.ts.map +1 -1
- package/dist/sandbox/seatbelt-sandbox.d.ts +36 -0
- package/dist/sandbox/seatbelt-sandbox.d.ts.map +1 -0
- package/dist/sandbox/types.d.ts +3 -1
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sdk/{check-provider-registry-VTNNTMWC.mjs → check-provider-registry-HFPKHYTG.mjs} +3 -3
- package/dist/sdk/{check-provider-registry-WBEOZCGW.mjs → check-provider-registry-HK6M4PDQ.mjs} +6 -6
- package/dist/sdk/{check-provider-registry-GKLK3I2X.mjs → check-provider-registry-TG5G2TF3.mjs} +6 -6
- package/dist/sdk/{chunk-D3UC5KUJ.mjs → chunk-5FXGIBJQ.mjs} +467 -100
- package/dist/sdk/chunk-5FXGIBJQ.mjs.map +1 -0
- package/dist/sdk/{chunk-FG6THKK7.mjs → chunk-6XPTQBXL.mjs} +3 -3
- package/dist/sdk/{chunk-FG6THKK7.mjs.map → chunk-6XPTQBXL.mjs.map} +1 -1
- package/dist/sdk/{chunk-N7LW3Q5B.mjs → chunk-E6SMU2Z4.mjs} +467 -100
- package/dist/sdk/chunk-E6SMU2Z4.mjs.map +1 -0
- package/dist/sdk/{chunk-PXWWPPNF.mjs → chunk-GZMQPC6D.mjs} +459 -92
- package/dist/sdk/chunk-GZMQPC6D.mjs.map +1 -0
- package/dist/sdk/{chunk-CLQTOZKH.mjs → chunk-I42ZCVA5.mjs} +3 -3
- package/dist/sdk/chunk-K3M5YVEU.mjs +1502 -0
- package/dist/sdk/chunk-K3M5YVEU.mjs.map +1 -0
- package/dist/sdk/{chunk-PQWAAGUP.mjs → chunk-L3XPYQ6I.mjs} +2 -2
- package/dist/sdk/chunk-L6ABOJVL.mjs +739 -0
- package/dist/sdk/chunk-L6ABOJVL.mjs.map +1 -0
- package/dist/sdk/chunk-OM3WYVFI.mjs +443 -0
- package/dist/sdk/chunk-OM3WYVFI.mjs.map +1 -0
- package/dist/sdk/{chunk-AKCHIYWU.mjs → chunk-YOKAA4IU.mjs} +96 -63
- package/dist/sdk/chunk-YOKAA4IU.mjs.map +1 -0
- package/dist/sdk/{config-KOKJ3PYE.mjs → config-AAB2FL22.mjs} +2 -2
- package/dist/sdk/{failure-condition-evaluator-LWH3NQ2S.mjs → failure-condition-evaluator-O464EJMD.mjs} +3 -3
- package/dist/sdk/failure-condition-evaluator-V3EJGD55.mjs +17 -0
- package/dist/sdk/{github-frontend-UUASYGNV.mjs → github-frontend-MSX6Q2WL.mjs} +3 -3
- package/dist/sdk/github-frontend-PSGUGYHT.mjs +1356 -0
- package/dist/sdk/github-frontend-PSGUGYHT.mjs.map +1 -0
- package/dist/sdk/{host-LAF3NFPZ.mjs → host-5BJ25CUZ.mjs} +2 -2
- package/dist/sdk/host-BYIV4QJ3.mjs +63 -0
- package/dist/sdk/host-BYIV4QJ3.mjs.map +1 -0
- package/dist/sdk/{routing-LEUV6A4K.mjs → routing-AJNUTCH7.mjs} +4 -4
- package/dist/sdk/routing-RIHVCEIU.mjs +25 -0
- package/dist/sdk/{schedule-tool-handler-EYDCUGOB.mjs → schedule-tool-handler-4O2VKNG2.mjs} +6 -6
- package/dist/sdk/{schedule-tool-handler-W7IB4MK3.mjs → schedule-tool-handler-BTLEDYAI.mjs} +3 -3
- package/dist/sdk/{schedule-tool-handler-7RGTKO24.mjs → schedule-tool-handler-R7PNPWWK.mjs} +6 -6
- package/dist/sdk/sdk.d.mts +3 -1
- package/dist/sdk/sdk.d.ts +3 -1
- package/dist/sdk/sdk.js +568 -168
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +5 -5
- package/dist/sdk/{trace-helpers-NNBQNFWZ.mjs → trace-helpers-OZTZBK6T.mjs} +2 -2
- package/dist/sdk/trace-helpers-QQSTZGDT.mjs +25 -0
- package/dist/sdk/{workflow-check-provider-WW5U6R2P.mjs → workflow-check-provider-3IIKJFM4.mjs} +3 -3
- package/dist/sdk/workflow-check-provider-3IIKJFM4.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-FLBIJQ4Z.mjs → workflow-check-provider-OM62QYHF.mjs} +6 -6
- package/dist/sdk/workflow-check-provider-OM62QYHF.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-2G2CEXFR.mjs → workflow-check-provider-RARO4N5E.mjs} +6 -6
- package/dist/sdk/workflow-check-provider-RARO4N5E.mjs.map +1 -0
- package/dist/slack/socket-runner.d.ts.map +1 -1
- package/dist/traces/{run-2026-02-25T17-29-59-894Z.ndjson → run-2026-02-26T07-47-34-788Z.ndjson} +84 -84
- package/dist/{output/traces/run-2026-02-25T17-30-47-149Z.ndjson → traces/run-2026-02-26T07-48-25-935Z.ndjson} +1118 -1118
- package/dist/utils/workspace-manager.d.ts +9 -0
- package/dist/utils/workspace-manager.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/sdk/chunk-AKCHIYWU.mjs.map +0 -1
- package/dist/sdk/chunk-D3UC5KUJ.mjs.map +0 -1
- package/dist/sdk/chunk-N7LW3Q5B.mjs.map +0 -1
- package/dist/sdk/chunk-PXWWPPNF.mjs.map +0 -1
- /package/dist/sdk/{check-provider-registry-GKLK3I2X.mjs.map → check-provider-registry-HFPKHYTG.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-VTNNTMWC.mjs.map → check-provider-registry-HK6M4PDQ.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-WBEOZCGW.mjs.map → check-provider-registry-TG5G2TF3.mjs.map} +0 -0
- /package/dist/sdk/{chunk-CLQTOZKH.mjs.map → chunk-I42ZCVA5.mjs.map} +0 -0
- /package/dist/sdk/{chunk-PQWAAGUP.mjs.map → chunk-L3XPYQ6I.mjs.map} +0 -0
- /package/dist/sdk/{config-KOKJ3PYE.mjs.map → config-AAB2FL22.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-LWH3NQ2S.mjs.map → failure-condition-evaluator-O464EJMD.mjs.map} +0 -0
- /package/dist/sdk/{routing-LEUV6A4K.mjs.map → failure-condition-evaluator-V3EJGD55.mjs.map} +0 -0
- /package/dist/sdk/{github-frontend-UUASYGNV.mjs.map → github-frontend-MSX6Q2WL.mjs.map} +0 -0
- /package/dist/sdk/{host-LAF3NFPZ.mjs.map → host-5BJ25CUZ.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-7RGTKO24.mjs.map → routing-AJNUTCH7.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-EYDCUGOB.mjs.map → routing-RIHVCEIU.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-handler-W7IB4MK3.mjs.map → schedule-tool-handler-4O2VKNG2.mjs.map} +0 -0
- /package/dist/sdk/{trace-helpers-NNBQNFWZ.mjs.map → schedule-tool-handler-BTLEDYAI.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-2G2CEXFR.mjs.map → schedule-tool-handler-R7PNPWWK.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-FLBIJQ4Z.mjs.map → trace-helpers-OZTZBK6T.mjs.map} +0 -0
- /package/dist/sdk/{workflow-check-provider-WW5U6R2P.mjs.map → trace-helpers-QQSTZGDT.mjs.map} +0 -0
package/dist/sdk/sdk.js
CHANGED
|
@@ -646,7 +646,7 @@ var require_package = __commonJS({
|
|
|
646
646
|
"package.json"(exports2, module2) {
|
|
647
647
|
module2.exports = {
|
|
648
648
|
name: "@probelabs/visor",
|
|
649
|
-
version: "0.1.
|
|
649
|
+
version: "0.1.145",
|
|
650
650
|
main: "dist/index.js",
|
|
651
651
|
bin: {
|
|
652
652
|
visor: "./dist/index.js"
|
|
@@ -760,7 +760,7 @@ var require_package = __commonJS({
|
|
|
760
760
|
"@opentelemetry/sdk-node": "^0.203.0",
|
|
761
761
|
"@opentelemetry/sdk-trace-base": "^1.30.1",
|
|
762
762
|
"@opentelemetry/semantic-conventions": "^1.30.1",
|
|
763
|
-
"@probelabs/probe": "^0.6.0-
|
|
763
|
+
"@probelabs/probe": "^0.6.0-rc260",
|
|
764
764
|
"@types/commander": "^2.12.0",
|
|
765
765
|
"@types/uuid": "^10.0.0",
|
|
766
766
|
acorn: "^8.16.0",
|
|
@@ -864,11 +864,11 @@ function getTracer() {
|
|
|
864
864
|
}
|
|
865
865
|
async function withActiveSpan(name, attrs, fn) {
|
|
866
866
|
const tracer = getTracer();
|
|
867
|
-
return await new Promise((
|
|
867
|
+
return await new Promise((resolve13, reject) => {
|
|
868
868
|
const callback = async (span) => {
|
|
869
869
|
try {
|
|
870
870
|
const res = await fn(span);
|
|
871
|
-
|
|
871
|
+
resolve13(res);
|
|
872
872
|
} catch (err) {
|
|
873
873
|
try {
|
|
874
874
|
if (err instanceof Error) span.recordException(err);
|
|
@@ -6972,7 +6972,7 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
6972
6972
|
if (chromiumPath) {
|
|
6973
6973
|
env.PUPPETEER_EXECUTABLE_PATH = chromiumPath;
|
|
6974
6974
|
}
|
|
6975
|
-
const result = await new Promise((
|
|
6975
|
+
const result = await new Promise((resolve13) => {
|
|
6976
6976
|
const proc = (0, import_child_process.spawn)(
|
|
6977
6977
|
"npx",
|
|
6978
6978
|
[
|
|
@@ -7002,13 +7002,13 @@ async function renderMermaidToPng(mermaidCode) {
|
|
|
7002
7002
|
});
|
|
7003
7003
|
proc.on("close", (code) => {
|
|
7004
7004
|
if (code === 0) {
|
|
7005
|
-
|
|
7005
|
+
resolve13({ success: true });
|
|
7006
7006
|
} else {
|
|
7007
|
-
|
|
7007
|
+
resolve13({ success: false, error: stderr || `Exit code ${code}` });
|
|
7008
7008
|
}
|
|
7009
7009
|
});
|
|
7010
7010
|
proc.on("error", (err) => {
|
|
7011
|
-
|
|
7011
|
+
resolve13({ success: false, error: err.message });
|
|
7012
7012
|
});
|
|
7013
7013
|
});
|
|
7014
7014
|
if (!result.success) {
|
|
@@ -9213,7 +9213,7 @@ ${"=".repeat(60)}
|
|
|
9213
9213
|
* Generate mock response for testing
|
|
9214
9214
|
*/
|
|
9215
9215
|
async generateMockResponse(_prompt, _checkName, _schema) {
|
|
9216
|
-
await new Promise((
|
|
9216
|
+
await new Promise((resolve13) => setTimeout(resolve13, 500));
|
|
9217
9217
|
const name = (_checkName || "").toLowerCase();
|
|
9218
9218
|
if (name.includes("extract-facts")) {
|
|
9219
9219
|
const arr = Array.from({ length: 6 }, (_, i) => ({
|
|
@@ -9574,7 +9574,7 @@ var init_command_executor = __esm({
|
|
|
9574
9574
|
* Execute command with stdin input
|
|
9575
9575
|
*/
|
|
9576
9576
|
executeWithStdin(command, options) {
|
|
9577
|
-
return new Promise((
|
|
9577
|
+
return new Promise((resolve13, reject) => {
|
|
9578
9578
|
const childProcess = (0, import_child_process2.exec)(
|
|
9579
9579
|
command,
|
|
9580
9580
|
{
|
|
@@ -9586,7 +9586,7 @@ var init_command_executor = __esm({
|
|
|
9586
9586
|
if (error && error.killed && (error.code === "ETIMEDOUT" || error.signal === "SIGTERM")) {
|
|
9587
9587
|
reject(new Error(`Command timed out after ${options.timeout || 3e4}ms`));
|
|
9588
9588
|
} else {
|
|
9589
|
-
|
|
9589
|
+
resolve13({
|
|
9590
9590
|
stdout: stdout || "",
|
|
9591
9591
|
stderr: stderr || "",
|
|
9592
9592
|
exitCode: error ? error.code || 1 : 0
|
|
@@ -14506,6 +14506,11 @@ var init_config_schema = __esm({
|
|
|
14506
14506
|
SandboxConfig: {
|
|
14507
14507
|
type: "object",
|
|
14508
14508
|
properties: {
|
|
14509
|
+
engine: {
|
|
14510
|
+
type: "string",
|
|
14511
|
+
enum: ["docker", "bubblewrap", "seatbelt"],
|
|
14512
|
+
description: "Sandbox engine type: 'docker' (default), 'bubblewrap' (Linux namespaces), or 'seatbelt' (macOS sandbox-exec)"
|
|
14513
|
+
},
|
|
14509
14514
|
image: {
|
|
14510
14515
|
type: "string",
|
|
14511
14516
|
description: 'Docker image to use (e.g., "node:20-alpine")'
|
|
@@ -15883,92 +15888,120 @@ ${errors}`);
|
|
|
15883
15888
|
message: `Sandbox name '${name}' contains invalid characters. Only letters, numbers, dots, hyphens, underscores allowed.`
|
|
15884
15889
|
});
|
|
15885
15890
|
}
|
|
15886
|
-
|
|
15887
|
-
config.image ? "image" : null,
|
|
15888
|
-
config.dockerfile || config.dockerfile_inline ? "dockerfile" : null,
|
|
15889
|
-
config.compose ? "compose" : null
|
|
15890
|
-
].filter(Boolean);
|
|
15891
|
-
if (modes.length === 0) {
|
|
15892
|
-
errors.push({
|
|
15893
|
-
field: `sandboxes.${name}`,
|
|
15894
|
-
message: `Sandbox '${name}' must specify one of: image, dockerfile, dockerfile_inline, or compose`
|
|
15895
|
-
});
|
|
15896
|
-
} else if (modes.length > 1) {
|
|
15897
|
-
errors.push({
|
|
15898
|
-
field: `sandboxes.${name}`,
|
|
15899
|
-
message: `Sandbox '${name}' has multiple modes (${modes.join(", ")}). Specify exactly one.`
|
|
15900
|
-
});
|
|
15901
|
-
}
|
|
15902
|
-
if (config.compose && !config.service) {
|
|
15903
|
-
errors.push({
|
|
15904
|
-
field: `sandboxes.${name}.service`,
|
|
15905
|
-
message: `Sandbox '${name}' uses compose mode but is missing required 'service' field`
|
|
15906
|
-
});
|
|
15907
|
-
}
|
|
15908
|
-
if (config.dockerfile && /\.\./.test(config.dockerfile)) {
|
|
15909
|
-
errors.push({
|
|
15910
|
-
field: `sandboxes.${name}.dockerfile`,
|
|
15911
|
-
message: `Dockerfile path '${config.dockerfile}' in sandbox '${name}' must not contain '..' path traversal`
|
|
15912
|
-
});
|
|
15913
|
-
}
|
|
15914
|
-
if (config.compose && /\.\./.test(config.compose)) {
|
|
15891
|
+
if (config.engine && !["docker", "bubblewrap", "seatbelt"].includes(config.engine)) {
|
|
15915
15892
|
errors.push({
|
|
15916
|
-
field: `sandboxes.${name}.
|
|
15917
|
-
message: `
|
|
15893
|
+
field: `sandboxes.${name}.engine`,
|
|
15894
|
+
message: `Sandbox '${name}' has invalid engine '${config.engine}'. Must be 'docker', 'bubblewrap', or 'seatbelt'.`
|
|
15918
15895
|
});
|
|
15919
15896
|
}
|
|
15920
|
-
|
|
15921
|
-
|
|
15897
|
+
const isNativeEngine = config.engine === "bubblewrap" || config.engine === "seatbelt";
|
|
15898
|
+
if (isNativeEngine) {
|
|
15899
|
+
const dockerOnlyFields = [
|
|
15900
|
+
["image", config.image],
|
|
15901
|
+
["dockerfile", config.dockerfile],
|
|
15902
|
+
["dockerfile_inline", config.dockerfile_inline],
|
|
15903
|
+
["compose", config.compose],
|
|
15904
|
+
["service", config.service],
|
|
15905
|
+
["cache", config.cache],
|
|
15906
|
+
["visor_path", config.visor_path],
|
|
15907
|
+
["resources", config.resources]
|
|
15908
|
+
];
|
|
15909
|
+
for (const [field, value] of dockerOnlyFields) {
|
|
15910
|
+
if (value !== void 0) {
|
|
15911
|
+
errors.push({
|
|
15912
|
+
field: `sandboxes.${name}.${field}`,
|
|
15913
|
+
message: `Sandbox '${name}' uses ${config.engine} engine but has Docker-only field '${field}'. Remove it or switch to engine: docker.`
|
|
15914
|
+
});
|
|
15915
|
+
}
|
|
15916
|
+
}
|
|
15917
|
+
} else {
|
|
15918
|
+
const modes = [
|
|
15919
|
+
config.image ? "image" : null,
|
|
15920
|
+
config.dockerfile || config.dockerfile_inline ? "dockerfile" : null,
|
|
15921
|
+
config.compose ? "compose" : null
|
|
15922
|
+
].filter(Boolean);
|
|
15923
|
+
if (modes.length === 0) {
|
|
15922
15924
|
errors.push({
|
|
15923
|
-
field: `sandboxes.${name}
|
|
15924
|
-
message: `
|
|
15925
|
+
field: `sandboxes.${name}`,
|
|
15926
|
+
message: `Sandbox '${name}' must specify one of: image, dockerfile, dockerfile_inline, or compose`
|
|
15927
|
+
});
|
|
15928
|
+
} else if (modes.length > 1) {
|
|
15929
|
+
errors.push({
|
|
15930
|
+
field: `sandboxes.${name}`,
|
|
15931
|
+
message: `Sandbox '${name}' has multiple modes (${modes.join(", ")}). Specify exactly one.`
|
|
15925
15932
|
});
|
|
15926
15933
|
}
|
|
15927
|
-
if (
|
|
15934
|
+
if (config.compose && !config.service) {
|
|
15928
15935
|
errors.push({
|
|
15929
|
-
field: `sandboxes.${name}.
|
|
15930
|
-
message: `
|
|
15936
|
+
field: `sandboxes.${name}.service`,
|
|
15937
|
+
message: `Sandbox '${name}' uses compose mode but is missing required 'service' field`
|
|
15931
15938
|
});
|
|
15932
15939
|
}
|
|
15933
|
-
|
|
15934
|
-
if (config.visor_path) {
|
|
15935
|
-
if (!config.visor_path.startsWith("/")) {
|
|
15940
|
+
if (config.dockerfile && /\.\./.test(config.dockerfile)) {
|
|
15936
15941
|
errors.push({
|
|
15937
|
-
field: `sandboxes.${name}.
|
|
15938
|
-
message: `
|
|
15942
|
+
field: `sandboxes.${name}.dockerfile`,
|
|
15943
|
+
message: `Dockerfile path '${config.dockerfile}' in sandbox '${name}' must not contain '..' path traversal`
|
|
15939
15944
|
});
|
|
15940
15945
|
}
|
|
15941
|
-
if (/\.\./.test(config.
|
|
15946
|
+
if (config.compose && /\.\./.test(config.compose)) {
|
|
15942
15947
|
errors.push({
|
|
15943
|
-
field: `sandboxes.${name}.
|
|
15944
|
-
message: `
|
|
15948
|
+
field: `sandboxes.${name}.compose`,
|
|
15949
|
+
message: `Compose file path '${config.compose}' in sandbox '${name}' must not contain '..' path traversal`
|
|
15945
15950
|
});
|
|
15946
15951
|
}
|
|
15947
|
-
|
|
15948
|
-
|
|
15949
|
-
for (const p of config.cache.paths) {
|
|
15950
|
-
if (!p.startsWith("/")) {
|
|
15952
|
+
if (config.visor_path) {
|
|
15953
|
+
if (!config.visor_path.startsWith("/")) {
|
|
15951
15954
|
errors.push({
|
|
15952
|
-
field: `sandboxes.${name}.
|
|
15953
|
-
message: `
|
|
15954
|
-
value: p
|
|
15955
|
+
field: `sandboxes.${name}.visor_path`,
|
|
15956
|
+
message: `visor_path '${config.visor_path}' in sandbox '${name}' must be an absolute path (start with /)`
|
|
15955
15957
|
});
|
|
15956
15958
|
}
|
|
15957
|
-
if (/\.\./.test(
|
|
15959
|
+
if (/\.\./.test(config.visor_path)) {
|
|
15958
15960
|
errors.push({
|
|
15959
|
-
field: `sandboxes.${name}.
|
|
15960
|
-
message: `
|
|
15961
|
-
|
|
15961
|
+
field: `sandboxes.${name}.visor_path`,
|
|
15962
|
+
message: `visor_path '${config.visor_path}' in sandbox '${name}' must not contain '..' path traversal`
|
|
15963
|
+
});
|
|
15964
|
+
}
|
|
15965
|
+
}
|
|
15966
|
+
if (config.cache?.paths) {
|
|
15967
|
+
for (const p of config.cache.paths) {
|
|
15968
|
+
if (!p.startsWith("/")) {
|
|
15969
|
+
errors.push({
|
|
15970
|
+
field: `sandboxes.${name}.cache.paths`,
|
|
15971
|
+
message: `Cache path '${p}' in sandbox '${name}' must be absolute (start with /)`,
|
|
15972
|
+
value: p
|
|
15973
|
+
});
|
|
15974
|
+
}
|
|
15975
|
+
if (/\.\./.test(p)) {
|
|
15976
|
+
errors.push({
|
|
15977
|
+
field: `sandboxes.${name}.cache.paths`,
|
|
15978
|
+
message: `Cache path '${p}' in sandbox '${name}' must not contain '..' path traversal`,
|
|
15979
|
+
value: p
|
|
15980
|
+
});
|
|
15981
|
+
}
|
|
15982
|
+
}
|
|
15983
|
+
}
|
|
15984
|
+
if (config.resources?.cpu !== void 0) {
|
|
15985
|
+
if (typeof config.resources.cpu !== "number" || config.resources.cpu <= 0) {
|
|
15986
|
+
errors.push({
|
|
15987
|
+
field: `sandboxes.${name}.resources.cpu`,
|
|
15988
|
+
message: `CPU limit in sandbox '${name}' must be a positive number`,
|
|
15989
|
+
value: config.resources.cpu
|
|
15962
15990
|
});
|
|
15963
15991
|
}
|
|
15964
15992
|
}
|
|
15965
15993
|
}
|
|
15966
|
-
if (config.
|
|
15967
|
-
if (
|
|
15994
|
+
if (config.workdir) {
|
|
15995
|
+
if (!config.workdir.startsWith("/")) {
|
|
15996
|
+
errors.push({
|
|
15997
|
+
field: `sandboxes.${name}.workdir`,
|
|
15998
|
+
message: `Workdir '${config.workdir}' in sandbox '${name}' must be an absolute path (start with /)`
|
|
15999
|
+
});
|
|
16000
|
+
}
|
|
16001
|
+
if (/\.\./.test(config.workdir)) {
|
|
15968
16002
|
errors.push({
|
|
15969
|
-
field: `sandboxes.${name}.
|
|
15970
|
-
message: `
|
|
15971
|
-
value: config.resources.cpu
|
|
16003
|
+
field: `sandboxes.${name}.workdir`,
|
|
16004
|
+
message: `Workdir '${config.workdir}' in sandbox '${name}' must not contain '..' path traversal`
|
|
15972
16005
|
});
|
|
15973
16006
|
}
|
|
15974
16007
|
}
|
|
@@ -19334,7 +19367,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19334
19367
|
* Returns the actual bound port number
|
|
19335
19368
|
*/
|
|
19336
19369
|
async start() {
|
|
19337
|
-
return new Promise((
|
|
19370
|
+
return new Promise((resolve13, reject) => {
|
|
19338
19371
|
try {
|
|
19339
19372
|
this.server = import_http.default.createServer((req, res) => {
|
|
19340
19373
|
this.handleRequest(req, res).catch((error) => {
|
|
@@ -19368,7 +19401,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19368
19401
|
);
|
|
19369
19402
|
}
|
|
19370
19403
|
this.startKeepalive();
|
|
19371
|
-
|
|
19404
|
+
resolve13(this.port);
|
|
19372
19405
|
});
|
|
19373
19406
|
} catch (error) {
|
|
19374
19407
|
reject(error);
|
|
@@ -19431,7 +19464,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19431
19464
|
logger.debug(
|
|
19432
19465
|
`[CustomToolsSSEServer:${this.sessionId}] Grace period before stop: ${waitMs}ms (activeToolCalls=${this.activeToolCalls})`
|
|
19433
19466
|
);
|
|
19434
|
-
await new Promise((
|
|
19467
|
+
await new Promise((resolve13) => setTimeout(resolve13, waitMs));
|
|
19435
19468
|
}
|
|
19436
19469
|
}
|
|
19437
19470
|
if (this.activeToolCalls > 0) {
|
|
@@ -19440,7 +19473,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19440
19473
|
`[CustomToolsSSEServer:${this.sessionId}] Waiting for ${this.activeToolCalls} active tool call(s) before stop`
|
|
19441
19474
|
);
|
|
19442
19475
|
while (this.activeToolCalls > 0 && Date.now() - startedAt < effectiveDrainTimeoutMs) {
|
|
19443
|
-
await new Promise((
|
|
19476
|
+
await new Promise((resolve13) => setTimeout(resolve13, 250));
|
|
19444
19477
|
}
|
|
19445
19478
|
if (this.activeToolCalls > 0) {
|
|
19446
19479
|
logger.warn(
|
|
@@ -19465,21 +19498,21 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19465
19498
|
}
|
|
19466
19499
|
this.connections.clear();
|
|
19467
19500
|
if (this.server) {
|
|
19468
|
-
await new Promise((
|
|
19501
|
+
await new Promise((resolve13, reject) => {
|
|
19469
19502
|
const timeout = setTimeout(() => {
|
|
19470
19503
|
if (this.debug) {
|
|
19471
19504
|
logger.debug(
|
|
19472
19505
|
`[CustomToolsSSEServer:${this.sessionId}] Force closing server after timeout`
|
|
19473
19506
|
);
|
|
19474
19507
|
}
|
|
19475
|
-
this.server?.close(() =>
|
|
19508
|
+
this.server?.close(() => resolve13());
|
|
19476
19509
|
}, 5e3);
|
|
19477
19510
|
this.server.close((error) => {
|
|
19478
19511
|
clearTimeout(timeout);
|
|
19479
19512
|
if (error) {
|
|
19480
19513
|
reject(error);
|
|
19481
19514
|
} else {
|
|
19482
|
-
|
|
19515
|
+
resolve13();
|
|
19483
19516
|
}
|
|
19484
19517
|
});
|
|
19485
19518
|
});
|
|
@@ -19905,7 +19938,7 @@ var init_mcp_custom_sse_server = __esm({
|
|
|
19905
19938
|
logger.warn(
|
|
19906
19939
|
`[CustomToolsSSEServer:${this.sessionId}] Tool ${toolName} failed (attempt ${attempt + 1}/${retryCount + 1}): ${errorMsg}. Retrying in ${delay}ms`
|
|
19907
19940
|
);
|
|
19908
|
-
await new Promise((
|
|
19941
|
+
await new Promise((resolve13) => setTimeout(resolve13, delay));
|
|
19909
19942
|
attempt++;
|
|
19910
19943
|
}
|
|
19911
19944
|
}
|
|
@@ -20210,8 +20243,8 @@ var init_ai_check_provider = __esm({
|
|
|
20210
20243
|
}
|
|
20211
20244
|
const fs22 = require("fs").promises;
|
|
20212
20245
|
try {
|
|
20213
|
-
const
|
|
20214
|
-
return
|
|
20246
|
+
const stat2 = await fs22.stat(resolvedPath);
|
|
20247
|
+
return stat2.isFile();
|
|
20215
20248
|
} catch {
|
|
20216
20249
|
return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
|
|
20217
20250
|
}
|
|
@@ -23459,8 +23492,8 @@ var init_claude_code_check_provider = __esm({
|
|
|
23459
23492
|
resolvedPath = import_path8.default.resolve(process.cwd(), str);
|
|
23460
23493
|
}
|
|
23461
23494
|
try {
|
|
23462
|
-
const
|
|
23463
|
-
return
|
|
23495
|
+
const stat2 = await import_promises5.default.stat(resolvedPath);
|
|
23496
|
+
return stat2.isFile();
|
|
23464
23497
|
} catch {
|
|
23465
23498
|
return hasFileExtension && (isRelativePath || isAbsolutePath || hasPathSeparators);
|
|
23466
23499
|
}
|
|
@@ -29089,8 +29122,8 @@ var require_util2 = __commonJS({
|
|
|
29089
29122
|
function createDeferredPromise() {
|
|
29090
29123
|
let res;
|
|
29091
29124
|
let rej;
|
|
29092
|
-
const promise = new Promise((
|
|
29093
|
-
res =
|
|
29125
|
+
const promise = new Promise((resolve13, reject) => {
|
|
29126
|
+
res = resolve13;
|
|
29094
29127
|
rej = reject;
|
|
29095
29128
|
});
|
|
29096
29129
|
return { promise, resolve: res, reject: rej };
|
|
@@ -30595,8 +30628,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
30595
30628
|
});
|
|
30596
30629
|
}
|
|
30597
30630
|
});
|
|
30598
|
-
const busboyResolve = new Promise((
|
|
30599
|
-
busboy.on("finish",
|
|
30631
|
+
const busboyResolve = new Promise((resolve13, reject) => {
|
|
30632
|
+
busboy.on("finish", resolve13);
|
|
30600
30633
|
busboy.on("error", (err) => reject(new TypeError(err)));
|
|
30601
30634
|
});
|
|
30602
30635
|
if (this.body !== null) for await (const chunk of consumeBody(this[kState].body)) busboy.write(chunk);
|
|
@@ -31130,9 +31163,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
31130
31163
|
}
|
|
31131
31164
|
close(callback) {
|
|
31132
31165
|
if (callback === void 0) {
|
|
31133
|
-
return new Promise((
|
|
31166
|
+
return new Promise((resolve13, reject) => {
|
|
31134
31167
|
this.close((err, data) => {
|
|
31135
|
-
return err ? reject(err) :
|
|
31168
|
+
return err ? reject(err) : resolve13(data);
|
|
31136
31169
|
});
|
|
31137
31170
|
});
|
|
31138
31171
|
}
|
|
@@ -31170,12 +31203,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
31170
31203
|
err = null;
|
|
31171
31204
|
}
|
|
31172
31205
|
if (callback === void 0) {
|
|
31173
|
-
return new Promise((
|
|
31206
|
+
return new Promise((resolve13, reject) => {
|
|
31174
31207
|
this.destroy(err, (err2, data) => {
|
|
31175
31208
|
return err2 ? (
|
|
31176
31209
|
/* istanbul ignore next: should never error */
|
|
31177
31210
|
reject(err2)
|
|
31178
|
-
) :
|
|
31211
|
+
) : resolve13(data);
|
|
31179
31212
|
});
|
|
31180
31213
|
});
|
|
31181
31214
|
}
|
|
@@ -32237,16 +32270,16 @@ var require_client = __commonJS({
|
|
|
32237
32270
|
return this[kNeedDrain] < 2;
|
|
32238
32271
|
}
|
|
32239
32272
|
async [kClose]() {
|
|
32240
|
-
return new Promise((
|
|
32273
|
+
return new Promise((resolve13) => {
|
|
32241
32274
|
if (!this[kSize]) {
|
|
32242
|
-
|
|
32275
|
+
resolve13(null);
|
|
32243
32276
|
} else {
|
|
32244
|
-
this[kClosedResolve] =
|
|
32277
|
+
this[kClosedResolve] = resolve13;
|
|
32245
32278
|
}
|
|
32246
32279
|
});
|
|
32247
32280
|
}
|
|
32248
32281
|
async [kDestroy](err) {
|
|
32249
|
-
return new Promise((
|
|
32282
|
+
return new Promise((resolve13) => {
|
|
32250
32283
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
32251
32284
|
for (let i = 0; i < requests.length; i++) {
|
|
32252
32285
|
const request = requests[i];
|
|
@@ -32257,7 +32290,7 @@ var require_client = __commonJS({
|
|
|
32257
32290
|
this[kClosedResolve]();
|
|
32258
32291
|
this[kClosedResolve] = null;
|
|
32259
32292
|
}
|
|
32260
|
-
|
|
32293
|
+
resolve13();
|
|
32261
32294
|
};
|
|
32262
32295
|
if (this[kHTTP2Session] != null) {
|
|
32263
32296
|
util.destroy(this[kHTTP2Session], err);
|
|
@@ -32837,7 +32870,7 @@ var require_client = __commonJS({
|
|
|
32837
32870
|
});
|
|
32838
32871
|
}
|
|
32839
32872
|
try {
|
|
32840
|
-
const socket = await new Promise((
|
|
32873
|
+
const socket = await new Promise((resolve13, reject) => {
|
|
32841
32874
|
client[kConnector]({
|
|
32842
32875
|
host,
|
|
32843
32876
|
hostname,
|
|
@@ -32849,7 +32882,7 @@ var require_client = __commonJS({
|
|
|
32849
32882
|
if (err) {
|
|
32850
32883
|
reject(err);
|
|
32851
32884
|
} else {
|
|
32852
|
-
|
|
32885
|
+
resolve13(socket2);
|
|
32853
32886
|
}
|
|
32854
32887
|
});
|
|
32855
32888
|
});
|
|
@@ -33473,12 +33506,12 @@ upgrade: ${upgrade}\r
|
|
|
33473
33506
|
cb();
|
|
33474
33507
|
}
|
|
33475
33508
|
}
|
|
33476
|
-
const waitForDrain = () => new Promise((
|
|
33509
|
+
const waitForDrain = () => new Promise((resolve13, reject) => {
|
|
33477
33510
|
assert(callback === null);
|
|
33478
33511
|
if (socket[kError]) {
|
|
33479
33512
|
reject(socket[kError]);
|
|
33480
33513
|
} else {
|
|
33481
|
-
callback =
|
|
33514
|
+
callback = resolve13;
|
|
33482
33515
|
}
|
|
33483
33516
|
});
|
|
33484
33517
|
if (client[kHTTPConnVersion] === "h2") {
|
|
@@ -33824,8 +33857,8 @@ var require_pool_base = __commonJS({
|
|
|
33824
33857
|
if (this[kQueue].isEmpty()) {
|
|
33825
33858
|
return Promise.all(this[kClients].map((c) => c.close()));
|
|
33826
33859
|
} else {
|
|
33827
|
-
return new Promise((
|
|
33828
|
-
this[kClosedResolve] =
|
|
33860
|
+
return new Promise((resolve13) => {
|
|
33861
|
+
this[kClosedResolve] = resolve13;
|
|
33829
33862
|
});
|
|
33830
33863
|
}
|
|
33831
33864
|
}
|
|
@@ -34403,7 +34436,7 @@ var require_readable = __commonJS({
|
|
|
34403
34436
|
if (this.closed) {
|
|
34404
34437
|
return Promise.resolve(null);
|
|
34405
34438
|
}
|
|
34406
|
-
return new Promise((
|
|
34439
|
+
return new Promise((resolve13, reject) => {
|
|
34407
34440
|
const signalListenerCleanup = signal ? util.addAbortListener(signal, () => {
|
|
34408
34441
|
this.destroy();
|
|
34409
34442
|
}) : noop;
|
|
@@ -34412,7 +34445,7 @@ var require_readable = __commonJS({
|
|
|
34412
34445
|
if (signal && signal.aborted) {
|
|
34413
34446
|
reject(signal.reason || Object.assign(new Error("The operation was aborted"), { name: "AbortError" }));
|
|
34414
34447
|
} else {
|
|
34415
|
-
|
|
34448
|
+
resolve13(null);
|
|
34416
34449
|
}
|
|
34417
34450
|
}).on("error", noop).on("data", function(chunk) {
|
|
34418
34451
|
limit -= chunk.length;
|
|
@@ -34434,11 +34467,11 @@ var require_readable = __commonJS({
|
|
|
34434
34467
|
throw new TypeError("unusable");
|
|
34435
34468
|
}
|
|
34436
34469
|
assert(!stream[kConsume]);
|
|
34437
|
-
return new Promise((
|
|
34470
|
+
return new Promise((resolve13, reject) => {
|
|
34438
34471
|
stream[kConsume] = {
|
|
34439
34472
|
type,
|
|
34440
34473
|
stream,
|
|
34441
|
-
resolve:
|
|
34474
|
+
resolve: resolve13,
|
|
34442
34475
|
reject,
|
|
34443
34476
|
length: 0,
|
|
34444
34477
|
body: []
|
|
@@ -34473,12 +34506,12 @@ var require_readable = __commonJS({
|
|
|
34473
34506
|
}
|
|
34474
34507
|
}
|
|
34475
34508
|
function consumeEnd(consume2) {
|
|
34476
|
-
const { type, body, resolve:
|
|
34509
|
+
const { type, body, resolve: resolve13, stream, length } = consume2;
|
|
34477
34510
|
try {
|
|
34478
34511
|
if (type === "text") {
|
|
34479
|
-
|
|
34512
|
+
resolve13(toUSVString(Buffer.concat(body)));
|
|
34480
34513
|
} else if (type === "json") {
|
|
34481
|
-
|
|
34514
|
+
resolve13(JSON.parse(Buffer.concat(body)));
|
|
34482
34515
|
} else if (type === "arrayBuffer") {
|
|
34483
34516
|
const dst = new Uint8Array(length);
|
|
34484
34517
|
let pos = 0;
|
|
@@ -34486,12 +34519,12 @@ var require_readable = __commonJS({
|
|
|
34486
34519
|
dst.set(buf, pos);
|
|
34487
34520
|
pos += buf.byteLength;
|
|
34488
34521
|
}
|
|
34489
|
-
|
|
34522
|
+
resolve13(dst.buffer);
|
|
34490
34523
|
} else if (type === "blob") {
|
|
34491
34524
|
if (!Blob2) {
|
|
34492
34525
|
Blob2 = require("buffer").Blob;
|
|
34493
34526
|
}
|
|
34494
|
-
|
|
34527
|
+
resolve13(new Blob2(body, { type: stream[kContentType] }));
|
|
34495
34528
|
}
|
|
34496
34529
|
consumeFinish(consume2);
|
|
34497
34530
|
} catch (err) {
|
|
@@ -34748,9 +34781,9 @@ var require_api_request = __commonJS({
|
|
|
34748
34781
|
};
|
|
34749
34782
|
function request(opts, callback) {
|
|
34750
34783
|
if (callback === void 0) {
|
|
34751
|
-
return new Promise((
|
|
34784
|
+
return new Promise((resolve13, reject) => {
|
|
34752
34785
|
request.call(this, opts, (err, data) => {
|
|
34753
|
-
return err ? reject(err) :
|
|
34786
|
+
return err ? reject(err) : resolve13(data);
|
|
34754
34787
|
});
|
|
34755
34788
|
});
|
|
34756
34789
|
}
|
|
@@ -34923,9 +34956,9 @@ var require_api_stream = __commonJS({
|
|
|
34923
34956
|
};
|
|
34924
34957
|
function stream(opts, factory, callback) {
|
|
34925
34958
|
if (callback === void 0) {
|
|
34926
|
-
return new Promise((
|
|
34959
|
+
return new Promise((resolve13, reject) => {
|
|
34927
34960
|
stream.call(this, opts, factory, (err, data) => {
|
|
34928
|
-
return err ? reject(err) :
|
|
34961
|
+
return err ? reject(err) : resolve13(data);
|
|
34929
34962
|
});
|
|
34930
34963
|
});
|
|
34931
34964
|
}
|
|
@@ -35206,9 +35239,9 @@ var require_api_upgrade = __commonJS({
|
|
|
35206
35239
|
};
|
|
35207
35240
|
function upgrade(opts, callback) {
|
|
35208
35241
|
if (callback === void 0) {
|
|
35209
|
-
return new Promise((
|
|
35242
|
+
return new Promise((resolve13, reject) => {
|
|
35210
35243
|
upgrade.call(this, opts, (err, data) => {
|
|
35211
|
-
return err ? reject(err) :
|
|
35244
|
+
return err ? reject(err) : resolve13(data);
|
|
35212
35245
|
});
|
|
35213
35246
|
});
|
|
35214
35247
|
}
|
|
@@ -35297,9 +35330,9 @@ var require_api_connect = __commonJS({
|
|
|
35297
35330
|
};
|
|
35298
35331
|
function connect(opts, callback) {
|
|
35299
35332
|
if (callback === void 0) {
|
|
35300
|
-
return new Promise((
|
|
35333
|
+
return new Promise((resolve13, reject) => {
|
|
35301
35334
|
connect.call(this, opts, (err, data) => {
|
|
35302
|
-
return err ? reject(err) :
|
|
35335
|
+
return err ? reject(err) : resolve13(data);
|
|
35303
35336
|
});
|
|
35304
35337
|
});
|
|
35305
35338
|
}
|
|
@@ -35823,7 +35856,7 @@ var require_mock_interceptor = __commonJS({
|
|
|
35823
35856
|
var require_mock_client = __commonJS({
|
|
35824
35857
|
"node_modules/undici/lib/mock/mock-client.js"(exports2, module2) {
|
|
35825
35858
|
"use strict";
|
|
35826
|
-
var { promisify:
|
|
35859
|
+
var { promisify: promisify7 } = require("util");
|
|
35827
35860
|
var Client2 = require_client();
|
|
35828
35861
|
var { buildMockDispatch } = require_mock_utils();
|
|
35829
35862
|
var {
|
|
@@ -35863,7 +35896,7 @@ var require_mock_client = __commonJS({
|
|
|
35863
35896
|
return new MockInterceptor(opts, this[kDispatches]);
|
|
35864
35897
|
}
|
|
35865
35898
|
async [kClose]() {
|
|
35866
|
-
await
|
|
35899
|
+
await promisify7(this[kOriginalClose])();
|
|
35867
35900
|
this[kConnected] = 0;
|
|
35868
35901
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
35869
35902
|
}
|
|
@@ -35876,7 +35909,7 @@ var require_mock_client = __commonJS({
|
|
|
35876
35909
|
var require_mock_pool = __commonJS({
|
|
35877
35910
|
"node_modules/undici/lib/mock/mock-pool.js"(exports2, module2) {
|
|
35878
35911
|
"use strict";
|
|
35879
|
-
var { promisify:
|
|
35912
|
+
var { promisify: promisify7 } = require("util");
|
|
35880
35913
|
var Pool = require_pool();
|
|
35881
35914
|
var { buildMockDispatch } = require_mock_utils();
|
|
35882
35915
|
var {
|
|
@@ -35916,7 +35949,7 @@ var require_mock_pool = __commonJS({
|
|
|
35916
35949
|
return new MockInterceptor(opts, this[kDispatches]);
|
|
35917
35950
|
}
|
|
35918
35951
|
async [kClose]() {
|
|
35919
|
-
await
|
|
35952
|
+
await promisify7(this[kOriginalClose])();
|
|
35920
35953
|
this[kConnected] = 0;
|
|
35921
35954
|
this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
|
|
35922
35955
|
}
|
|
@@ -38922,7 +38955,7 @@ var require_fetch = __commonJS({
|
|
|
38922
38955
|
async function dispatch({ body }) {
|
|
38923
38956
|
const url = requestCurrentURL(request);
|
|
38924
38957
|
const agent = fetchParams.controller.dispatcher;
|
|
38925
|
-
return new Promise((
|
|
38958
|
+
return new Promise((resolve13, reject) => agent.dispatch(
|
|
38926
38959
|
{
|
|
38927
38960
|
path: url.pathname + url.search,
|
|
38928
38961
|
origin: url.origin,
|
|
@@ -38998,7 +39031,7 @@ var require_fetch = __commonJS({
|
|
|
38998
39031
|
}
|
|
38999
39032
|
}
|
|
39000
39033
|
}
|
|
39001
|
-
|
|
39034
|
+
resolve13({
|
|
39002
39035
|
status,
|
|
39003
39036
|
statusText,
|
|
39004
39037
|
headersList: headers[kHeadersList],
|
|
@@ -39041,7 +39074,7 @@ var require_fetch = __commonJS({
|
|
|
39041
39074
|
const val = headersList[n + 1].toString("latin1");
|
|
39042
39075
|
headers[kHeadersList].append(key, val);
|
|
39043
39076
|
}
|
|
39044
|
-
|
|
39077
|
+
resolve13({
|
|
39045
39078
|
status,
|
|
39046
39079
|
statusText: STATUS_CODES[status],
|
|
39047
39080
|
headersList: headers[kHeadersList],
|
|
@@ -42582,7 +42615,8 @@ var init_mcp_check_provider = __esm({
|
|
|
42582
42615
|
fileCount: prInfo.files.length,
|
|
42583
42616
|
outputs: this.buildOutputContext(dependencyResults),
|
|
42584
42617
|
args: sessionInfo?.args || {},
|
|
42585
|
-
env: this.getSafeEnvironmentVariables()
|
|
42618
|
+
env: this.getSafeEnvironmentVariables(),
|
|
42619
|
+
inputs: config.workflowInputs || sessionInfo?.workflowInputs || {}
|
|
42586
42620
|
};
|
|
42587
42621
|
let methodArgs = cfg.methodArgs || {};
|
|
42588
42622
|
if (cfg.argsTransform) {
|
|
@@ -42835,7 +42869,7 @@ var init_mcp_check_provider = __esm({
|
|
|
42835
42869
|
logger.warn(
|
|
42836
42870
|
`MCP ${transportName} failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms: ${error instanceof Error ? error.message : String(error)}`
|
|
42837
42871
|
);
|
|
42838
|
-
await new Promise((
|
|
42872
|
+
await new Promise((resolve13) => setTimeout(resolve13, delay));
|
|
42839
42873
|
attempt += 1;
|
|
42840
42874
|
} finally {
|
|
42841
42875
|
try {
|
|
@@ -43117,7 +43151,7 @@ async function acquirePromptLock() {
|
|
|
43117
43151
|
activePrompt = true;
|
|
43118
43152
|
return;
|
|
43119
43153
|
}
|
|
43120
|
-
await new Promise((
|
|
43154
|
+
await new Promise((resolve13) => waiters.push(resolve13));
|
|
43121
43155
|
activePrompt = true;
|
|
43122
43156
|
}
|
|
43123
43157
|
function releasePromptLock() {
|
|
@@ -43127,7 +43161,7 @@ function releasePromptLock() {
|
|
|
43127
43161
|
}
|
|
43128
43162
|
async function interactivePrompt(options) {
|
|
43129
43163
|
await acquirePromptLock();
|
|
43130
|
-
return new Promise((
|
|
43164
|
+
return new Promise((resolve13, reject) => {
|
|
43131
43165
|
const dbg = process.env.VISOR_DEBUG === "true";
|
|
43132
43166
|
try {
|
|
43133
43167
|
if (dbg) {
|
|
@@ -43214,12 +43248,12 @@ async function interactivePrompt(options) {
|
|
|
43214
43248
|
};
|
|
43215
43249
|
const finish = (value) => {
|
|
43216
43250
|
cleanup();
|
|
43217
|
-
|
|
43251
|
+
resolve13(value);
|
|
43218
43252
|
};
|
|
43219
43253
|
if (options.timeout && options.timeout > 0) {
|
|
43220
43254
|
timeoutId = setTimeout(() => {
|
|
43221
43255
|
cleanup();
|
|
43222
|
-
if (defaultValue !== void 0) return
|
|
43256
|
+
if (defaultValue !== void 0) return resolve13(defaultValue);
|
|
43223
43257
|
return reject(new Error("Input timeout"));
|
|
43224
43258
|
}, options.timeout);
|
|
43225
43259
|
}
|
|
@@ -43351,7 +43385,7 @@ async function interactivePrompt(options) {
|
|
|
43351
43385
|
});
|
|
43352
43386
|
}
|
|
43353
43387
|
async function simplePrompt(prompt) {
|
|
43354
|
-
return new Promise((
|
|
43388
|
+
return new Promise((resolve13) => {
|
|
43355
43389
|
const rl = readline.createInterface({
|
|
43356
43390
|
input: process.stdin,
|
|
43357
43391
|
output: process.stdout
|
|
@@ -43367,7 +43401,7 @@ async function simplePrompt(prompt) {
|
|
|
43367
43401
|
rl.question(`${prompt}
|
|
43368
43402
|
> `, (answer) => {
|
|
43369
43403
|
rl.close();
|
|
43370
|
-
|
|
43404
|
+
resolve13(answer.trim());
|
|
43371
43405
|
});
|
|
43372
43406
|
});
|
|
43373
43407
|
}
|
|
@@ -43535,7 +43569,7 @@ function isStdinAvailable() {
|
|
|
43535
43569
|
return !process.stdin.isTTY;
|
|
43536
43570
|
}
|
|
43537
43571
|
async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
43538
|
-
return new Promise((
|
|
43572
|
+
return new Promise((resolve13, reject) => {
|
|
43539
43573
|
let data = "";
|
|
43540
43574
|
let timeoutId;
|
|
43541
43575
|
if (timeout) {
|
|
@@ -43562,7 +43596,7 @@ async function readStdin(timeout, maxSize = 1024 * 1024) {
|
|
|
43562
43596
|
};
|
|
43563
43597
|
const onEnd = () => {
|
|
43564
43598
|
cleanup();
|
|
43565
|
-
|
|
43599
|
+
resolve13(data.trim());
|
|
43566
43600
|
};
|
|
43567
43601
|
const onError = (err) => {
|
|
43568
43602
|
cleanup();
|
|
@@ -50488,8 +50522,8 @@ var init_runner = __esm({
|
|
|
50488
50522
|
stats.sort((a, b) => (b.errorMessage ? 1 : 0) - (a.errorMessage ? 1 : 0));
|
|
50489
50523
|
const results = this.aggregateResultsFromJournal();
|
|
50490
50524
|
let totalDuration = 0;
|
|
50491
|
-
for (const
|
|
50492
|
-
totalDuration = Math.max(totalDuration,
|
|
50525
|
+
for (const stat2 of stats) {
|
|
50526
|
+
totalDuration = Math.max(totalDuration, stat2.totalDuration);
|
|
50493
50527
|
}
|
|
50494
50528
|
try {
|
|
50495
50529
|
for (const s of stats) {
|
|
@@ -51155,13 +51189,275 @@ var init_cache_volume_manager = __esm({
|
|
|
51155
51189
|
}
|
|
51156
51190
|
});
|
|
51157
51191
|
|
|
51192
|
+
// src/sandbox/bubblewrap-sandbox.ts
|
|
51193
|
+
var bubblewrap_sandbox_exports = {};
|
|
51194
|
+
__export(bubblewrap_sandbox_exports, {
|
|
51195
|
+
BubblewrapSandbox: () => BubblewrapSandbox
|
|
51196
|
+
});
|
|
51197
|
+
var import_util5, import_child_process6, import_fs6, import_path10, execFileAsync4, EXEC_MAX_BUFFER4, BubblewrapSandbox;
|
|
51198
|
+
var init_bubblewrap_sandbox = __esm({
|
|
51199
|
+
"src/sandbox/bubblewrap-sandbox.ts"() {
|
|
51200
|
+
"use strict";
|
|
51201
|
+
import_util5 = require("util");
|
|
51202
|
+
import_child_process6 = require("child_process");
|
|
51203
|
+
import_fs6 = require("fs");
|
|
51204
|
+
import_path10 = require("path");
|
|
51205
|
+
init_logger();
|
|
51206
|
+
init_sandbox_telemetry();
|
|
51207
|
+
execFileAsync4 = (0, import_util5.promisify)(import_child_process6.execFile);
|
|
51208
|
+
EXEC_MAX_BUFFER4 = 50 * 1024 * 1024;
|
|
51209
|
+
BubblewrapSandbox = class {
|
|
51210
|
+
name;
|
|
51211
|
+
config;
|
|
51212
|
+
repoPath;
|
|
51213
|
+
constructor(name, config, repoPath) {
|
|
51214
|
+
this.name = name;
|
|
51215
|
+
this.config = config;
|
|
51216
|
+
this.repoPath = (0, import_path10.resolve)(repoPath);
|
|
51217
|
+
}
|
|
51218
|
+
/**
|
|
51219
|
+
* Check if bwrap binary is available on the system.
|
|
51220
|
+
*/
|
|
51221
|
+
static async isAvailable() {
|
|
51222
|
+
try {
|
|
51223
|
+
await execFileAsync4("which", ["bwrap"], { timeout: 5e3 });
|
|
51224
|
+
return true;
|
|
51225
|
+
} catch {
|
|
51226
|
+
return false;
|
|
51227
|
+
}
|
|
51228
|
+
}
|
|
51229
|
+
/**
|
|
51230
|
+
* Execute a command inside a bubblewrap sandbox.
|
|
51231
|
+
* Each exec creates a fresh namespace — no persistent container.
|
|
51232
|
+
*/
|
|
51233
|
+
async exec(options) {
|
|
51234
|
+
const args = this.buildArgs(options);
|
|
51235
|
+
args.push("--", "/bin/sh", "-c", options.command);
|
|
51236
|
+
logger.debug(
|
|
51237
|
+
`[BubblewrapSandbox] Executing in sandbox '${this.name}': ${options.command.slice(0, 100)}`
|
|
51238
|
+
);
|
|
51239
|
+
try {
|
|
51240
|
+
const { stdout, stderr } = await execFileAsync4("bwrap", args, {
|
|
51241
|
+
maxBuffer: options.maxBuffer || EXEC_MAX_BUFFER4,
|
|
51242
|
+
timeout: options.timeoutMs || 6e5
|
|
51243
|
+
});
|
|
51244
|
+
addEvent2("visor.sandbox.bwrap.exec", {
|
|
51245
|
+
"visor.sandbox.name": this.name,
|
|
51246
|
+
"visor.sandbox.exit_code": 0
|
|
51247
|
+
});
|
|
51248
|
+
return { stdout, stderr, exitCode: 0 };
|
|
51249
|
+
} catch (err) {
|
|
51250
|
+
const execErr = err;
|
|
51251
|
+
const exitCode = typeof execErr.code === "number" ? execErr.code : 1;
|
|
51252
|
+
addEvent2("visor.sandbox.bwrap.exec", {
|
|
51253
|
+
"visor.sandbox.name": this.name,
|
|
51254
|
+
"visor.sandbox.exit_code": exitCode
|
|
51255
|
+
});
|
|
51256
|
+
return {
|
|
51257
|
+
stdout: execErr.stdout || "",
|
|
51258
|
+
stderr: execErr.stderr || "",
|
|
51259
|
+
exitCode
|
|
51260
|
+
};
|
|
51261
|
+
}
|
|
51262
|
+
}
|
|
51263
|
+
/**
|
|
51264
|
+
* No-op: bubblewrap processes are ephemeral (no persistent container to stop).
|
|
51265
|
+
*/
|
|
51266
|
+
async stop() {
|
|
51267
|
+
}
|
|
51268
|
+
/**
|
|
51269
|
+
* Build the bwrap command-line arguments.
|
|
51270
|
+
*/
|
|
51271
|
+
buildArgs(options) {
|
|
51272
|
+
const workdir = this.config.workdir || "/workspace";
|
|
51273
|
+
const args = [];
|
|
51274
|
+
args.push("--ro-bind", "/usr", "/usr");
|
|
51275
|
+
args.push("--ro-bind", "/bin", "/bin");
|
|
51276
|
+
if ((0, import_fs6.existsSync)("/lib")) {
|
|
51277
|
+
args.push("--ro-bind", "/lib", "/lib");
|
|
51278
|
+
}
|
|
51279
|
+
if ((0, import_fs6.existsSync)("/lib64")) {
|
|
51280
|
+
args.push("--ro-bind", "/lib64", "/lib64");
|
|
51281
|
+
}
|
|
51282
|
+
if ((0, import_fs6.existsSync)("/etc/resolv.conf")) {
|
|
51283
|
+
args.push("--ro-bind", "/etc/resolv.conf", "/etc/resolv.conf");
|
|
51284
|
+
}
|
|
51285
|
+
if ((0, import_fs6.existsSync)("/etc/ssl")) {
|
|
51286
|
+
args.push("--ro-bind", "/etc/ssl", "/etc/ssl");
|
|
51287
|
+
}
|
|
51288
|
+
args.push("--dev", "/dev");
|
|
51289
|
+
args.push("--proc", "/proc");
|
|
51290
|
+
args.push("--tmpfs", "/tmp");
|
|
51291
|
+
args.push("--tmpfs", "/root");
|
|
51292
|
+
if (this.config.read_only) {
|
|
51293
|
+
args.push("--ro-bind", this.repoPath, workdir);
|
|
51294
|
+
} else {
|
|
51295
|
+
args.push("--bind", this.repoPath, workdir);
|
|
51296
|
+
}
|
|
51297
|
+
args.push("--chdir", workdir);
|
|
51298
|
+
args.push("--unshare-pid");
|
|
51299
|
+
args.push("--new-session");
|
|
51300
|
+
args.push("--die-with-parent");
|
|
51301
|
+
if (this.config.network === false) {
|
|
51302
|
+
args.push("--unshare-net");
|
|
51303
|
+
}
|
|
51304
|
+
args.push("--clearenv");
|
|
51305
|
+
for (const [key, value] of Object.entries(options.env)) {
|
|
51306
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
51307
|
+
throw new Error(`Invalid environment variable name: '${key}'`);
|
|
51308
|
+
}
|
|
51309
|
+
args.push("--setenv", key, value);
|
|
51310
|
+
}
|
|
51311
|
+
return args;
|
|
51312
|
+
}
|
|
51313
|
+
};
|
|
51314
|
+
}
|
|
51315
|
+
});
|
|
51316
|
+
|
|
51317
|
+
// src/sandbox/seatbelt-sandbox.ts
|
|
51318
|
+
var seatbelt_sandbox_exports = {};
|
|
51319
|
+
__export(seatbelt_sandbox_exports, {
|
|
51320
|
+
SeatbeltSandbox: () => SeatbeltSandbox
|
|
51321
|
+
});
|
|
51322
|
+
var import_util6, import_child_process7, import_path11, import_fs7, execFileAsync5, EXEC_MAX_BUFFER5, SeatbeltSandbox;
|
|
51323
|
+
var init_seatbelt_sandbox = __esm({
|
|
51324
|
+
"src/sandbox/seatbelt-sandbox.ts"() {
|
|
51325
|
+
"use strict";
|
|
51326
|
+
import_util6 = require("util");
|
|
51327
|
+
import_child_process7 = require("child_process");
|
|
51328
|
+
import_path11 = require("path");
|
|
51329
|
+
import_fs7 = require("fs");
|
|
51330
|
+
init_logger();
|
|
51331
|
+
init_sandbox_telemetry();
|
|
51332
|
+
execFileAsync5 = (0, import_util6.promisify)(import_child_process7.execFile);
|
|
51333
|
+
EXEC_MAX_BUFFER5 = 50 * 1024 * 1024;
|
|
51334
|
+
SeatbeltSandbox = class {
|
|
51335
|
+
name;
|
|
51336
|
+
config;
|
|
51337
|
+
repoPath;
|
|
51338
|
+
constructor(name, config, repoPath) {
|
|
51339
|
+
this.name = name;
|
|
51340
|
+
this.config = config;
|
|
51341
|
+
this.repoPath = (0, import_fs7.realpathSync)((0, import_path11.resolve)(repoPath));
|
|
51342
|
+
}
|
|
51343
|
+
/**
|
|
51344
|
+
* Check if sandbox-exec binary is available on the system.
|
|
51345
|
+
*/
|
|
51346
|
+
static async isAvailable() {
|
|
51347
|
+
try {
|
|
51348
|
+
await execFileAsync5("which", ["sandbox-exec"], { timeout: 5e3 });
|
|
51349
|
+
return true;
|
|
51350
|
+
} catch {
|
|
51351
|
+
return false;
|
|
51352
|
+
}
|
|
51353
|
+
}
|
|
51354
|
+
/**
|
|
51355
|
+
* Execute a command inside a macOS seatbelt sandbox.
|
|
51356
|
+
* Each exec creates a fresh sandbox process — no persistent container.
|
|
51357
|
+
*/
|
|
51358
|
+
async exec(options) {
|
|
51359
|
+
const profile = this.buildProfile();
|
|
51360
|
+
for (const key of Object.keys(options.env)) {
|
|
51361
|
+
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
|
|
51362
|
+
throw new Error(`Invalid environment variable name: '${key}'`);
|
|
51363
|
+
}
|
|
51364
|
+
}
|
|
51365
|
+
const args = ["-p", profile];
|
|
51366
|
+
args.push("/usr/bin/env", "-i");
|
|
51367
|
+
for (const [key, value] of Object.entries(options.env)) {
|
|
51368
|
+
args.push(`${key}=${value}`);
|
|
51369
|
+
}
|
|
51370
|
+
args.push("/bin/sh", "-c", options.command);
|
|
51371
|
+
logger.debug(
|
|
51372
|
+
`[SeatbeltSandbox] Executing in sandbox '${this.name}': ${options.command.slice(0, 100)}`
|
|
51373
|
+
);
|
|
51374
|
+
try {
|
|
51375
|
+
const { stdout, stderr } = await execFileAsync5("sandbox-exec", args, {
|
|
51376
|
+
maxBuffer: options.maxBuffer || EXEC_MAX_BUFFER5,
|
|
51377
|
+
timeout: options.timeoutMs || 6e5,
|
|
51378
|
+
cwd: this.repoPath
|
|
51379
|
+
});
|
|
51380
|
+
addEvent2("visor.sandbox.seatbelt.exec", {
|
|
51381
|
+
"visor.sandbox.name": this.name,
|
|
51382
|
+
"visor.sandbox.exit_code": 0
|
|
51383
|
+
});
|
|
51384
|
+
return { stdout, stderr, exitCode: 0 };
|
|
51385
|
+
} catch (err) {
|
|
51386
|
+
const execErr = err;
|
|
51387
|
+
const exitCode = typeof execErr.code === "number" ? execErr.code : 1;
|
|
51388
|
+
addEvent2("visor.sandbox.seatbelt.exec", {
|
|
51389
|
+
"visor.sandbox.name": this.name,
|
|
51390
|
+
"visor.sandbox.exit_code": exitCode
|
|
51391
|
+
});
|
|
51392
|
+
return {
|
|
51393
|
+
stdout: execErr.stdout || "",
|
|
51394
|
+
stderr: execErr.stderr || "",
|
|
51395
|
+
exitCode
|
|
51396
|
+
};
|
|
51397
|
+
}
|
|
51398
|
+
}
|
|
51399
|
+
/**
|
|
51400
|
+
* No-op: sandbox-exec processes are ephemeral (no persistent container to stop).
|
|
51401
|
+
*/
|
|
51402
|
+
async stop() {
|
|
51403
|
+
}
|
|
51404
|
+
/**
|
|
51405
|
+
* Escape a path for use inside an SBPL profile string.
|
|
51406
|
+
* Escapes backslashes and double quotes.
|
|
51407
|
+
*/
|
|
51408
|
+
escapePath(p) {
|
|
51409
|
+
return p.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
51410
|
+
}
|
|
51411
|
+
/**
|
|
51412
|
+
* Build the SBPL (Seatbelt Profile Language) profile string.
|
|
51413
|
+
*/
|
|
51414
|
+
buildProfile() {
|
|
51415
|
+
const repoPath = this.escapePath(this.repoPath);
|
|
51416
|
+
const lines = [];
|
|
51417
|
+
lines.push("(version 1)");
|
|
51418
|
+
lines.push("(deny default)");
|
|
51419
|
+
lines.push("(allow process-exec)");
|
|
51420
|
+
lines.push("(allow process-fork)");
|
|
51421
|
+
lines.push("(allow file-read*");
|
|
51422
|
+
lines.push(' (literal "/")');
|
|
51423
|
+
lines.push(' (subpath "/usr")');
|
|
51424
|
+
lines.push(' (subpath "/bin")');
|
|
51425
|
+
lines.push(' (subpath "/sbin")');
|
|
51426
|
+
lines.push(' (subpath "/Library")');
|
|
51427
|
+
lines.push(' (subpath "/System")');
|
|
51428
|
+
lines.push(' (subpath "/private")');
|
|
51429
|
+
lines.push(' (subpath "/var")');
|
|
51430
|
+
lines.push(' (subpath "/etc")');
|
|
51431
|
+
lines.push(' (subpath "/dev")');
|
|
51432
|
+
lines.push(' (subpath "/tmp"))');
|
|
51433
|
+
lines.push("(allow file-write*");
|
|
51434
|
+
lines.push(' (subpath "/tmp")');
|
|
51435
|
+
lines.push(' (subpath "/private/tmp")');
|
|
51436
|
+
lines.push(' (subpath "/dev"))');
|
|
51437
|
+
lines.push('(allow file-write* (regex #"/private/var/folders/.*/T/xcrun_db"))');
|
|
51438
|
+
lines.push(`(allow file-read* (subpath "${repoPath}"))`);
|
|
51439
|
+
if (!this.config.read_only) {
|
|
51440
|
+
lines.push(`(allow file-write* (subpath "${repoPath}"))`);
|
|
51441
|
+
}
|
|
51442
|
+
if (this.config.network !== false) {
|
|
51443
|
+
lines.push("(allow network*)");
|
|
51444
|
+
}
|
|
51445
|
+
lines.push("(allow sysctl-read)");
|
|
51446
|
+
lines.push("(allow mach-lookup)");
|
|
51447
|
+
lines.push("(allow signal)");
|
|
51448
|
+
return lines.join("\n");
|
|
51449
|
+
}
|
|
51450
|
+
};
|
|
51451
|
+
}
|
|
51452
|
+
});
|
|
51453
|
+
|
|
51158
51454
|
// src/sandbox/sandbox-manager.ts
|
|
51159
|
-
var
|
|
51455
|
+
var import_path12, import_fs8, SandboxManager;
|
|
51160
51456
|
var init_sandbox_manager = __esm({
|
|
51161
51457
|
"src/sandbox/sandbox-manager.ts"() {
|
|
51162
51458
|
"use strict";
|
|
51163
|
-
|
|
51164
|
-
|
|
51459
|
+
import_path12 = require("path");
|
|
51460
|
+
import_fs8 = require("fs");
|
|
51165
51461
|
init_docker_image_sandbox();
|
|
51166
51462
|
init_docker_compose_sandbox();
|
|
51167
51463
|
init_cache_volume_manager();
|
|
@@ -51180,10 +51476,10 @@ var init_sandbox_manager = __esm({
|
|
|
51180
51476
|
}
|
|
51181
51477
|
constructor(sandboxDefs, repoPath, gitBranch) {
|
|
51182
51478
|
this.sandboxDefs = sandboxDefs;
|
|
51183
|
-
this.repoPath = (0,
|
|
51479
|
+
this.repoPath = (0, import_path12.resolve)(repoPath);
|
|
51184
51480
|
this.gitBranch = gitBranch;
|
|
51185
51481
|
this.cacheManager = new CacheVolumeManager();
|
|
51186
|
-
this.visorDistPath = (0,
|
|
51482
|
+
this.visorDistPath = (0, import_fs8.existsSync)((0, import_path12.join)(__dirname, "index.js")) ? __dirname : (0, import_path12.resolve)((0, import_path12.dirname)(__dirname));
|
|
51187
51483
|
}
|
|
51188
51484
|
/**
|
|
51189
51485
|
* Resolve which sandbox a check should use.
|
|
@@ -51213,6 +51509,18 @@ var init_sandbox_manager = __esm({
|
|
|
51213
51509
|
throw new Error(`Sandbox '${name}' is not defined`);
|
|
51214
51510
|
}
|
|
51215
51511
|
const mode = config.compose ? "compose" : "image";
|
|
51512
|
+
if (config.engine === "bubblewrap") {
|
|
51513
|
+
const { BubblewrapSandbox: BubblewrapSandbox2 } = (init_bubblewrap_sandbox(), __toCommonJS(bubblewrap_sandbox_exports));
|
|
51514
|
+
const instance = new BubblewrapSandbox2(name, config, this.repoPath);
|
|
51515
|
+
this.instances.set(name, instance);
|
|
51516
|
+
return instance;
|
|
51517
|
+
}
|
|
51518
|
+
if (config.engine === "seatbelt") {
|
|
51519
|
+
const { SeatbeltSandbox: SeatbeltSandbox2 } = (init_seatbelt_sandbox(), __toCommonJS(seatbelt_sandbox_exports));
|
|
51520
|
+
const instance = new SeatbeltSandbox2(name, config, this.repoPath);
|
|
51521
|
+
this.instances.set(name, instance);
|
|
51522
|
+
return instance;
|
|
51523
|
+
}
|
|
51216
51524
|
return withActiveSpan2(
|
|
51217
51525
|
"visor.sandbox.start",
|
|
51218
51526
|
{
|
|
@@ -51860,8 +52168,8 @@ var init_workspace_manager = __esm({
|
|
|
51860
52168
|
);
|
|
51861
52169
|
if (this.cleanupRequested && this.activeOperations === 0) {
|
|
51862
52170
|
logger.debug(`[Workspace] All references released, proceeding with deferred cleanup`);
|
|
51863
|
-
for (const
|
|
51864
|
-
|
|
52171
|
+
for (const resolve13 of this.cleanupResolvers) {
|
|
52172
|
+
resolve13();
|
|
51865
52173
|
}
|
|
51866
52174
|
this.cleanupResolvers = [];
|
|
51867
52175
|
}
|
|
@@ -51911,13 +52219,34 @@ var init_workspace_manager = __esm({
|
|
|
51911
52219
|
const mainProjectPath = path23.join(this.workspacePath, mainProjectName);
|
|
51912
52220
|
const isGitRepo = await this.isGitRepository(this.originalPath);
|
|
51913
52221
|
if (isGitRepo) {
|
|
51914
|
-
await this.
|
|
52222
|
+
const exists = await this.pathExists(mainProjectPath);
|
|
52223
|
+
if (exists) {
|
|
52224
|
+
logger.info(`[Workspace] Reusing existing main project worktree: ${mainProjectPath}`);
|
|
52225
|
+
const isValid = await this.isGitRepository(mainProjectPath);
|
|
52226
|
+
if (!isValid) {
|
|
52227
|
+
logger.warn(`[Workspace] Existing path is not a valid git dir, recreating`);
|
|
52228
|
+
await fsp2.rm(mainProjectPath, { recursive: true, force: true });
|
|
52229
|
+
try {
|
|
52230
|
+
await commandExecutor.execute(
|
|
52231
|
+
`git -C ${shellEscape(this.originalPath)} worktree prune`,
|
|
52232
|
+
{ timeout: 1e4 }
|
|
52233
|
+
);
|
|
52234
|
+
} catch {
|
|
52235
|
+
}
|
|
52236
|
+
await this.createMainProjectWorktree(mainProjectPath);
|
|
52237
|
+
}
|
|
52238
|
+
} else {
|
|
52239
|
+
await this.createMainProjectWorktree(mainProjectPath);
|
|
52240
|
+
}
|
|
51915
52241
|
} else {
|
|
51916
52242
|
logger.debug(`Original path is not a git repo, creating symlink`);
|
|
51917
|
-
|
|
51918
|
-
|
|
51919
|
-
|
|
51920
|
-
|
|
52243
|
+
const exists = await this.pathExists(mainProjectPath);
|
|
52244
|
+
if (!exists) {
|
|
52245
|
+
try {
|
|
52246
|
+
await fsp2.symlink(this.originalPath, mainProjectPath);
|
|
52247
|
+
} catch (error) {
|
|
52248
|
+
throw new Error(`Failed to create symlink for main project: ${error}`);
|
|
52249
|
+
}
|
|
51921
52250
|
}
|
|
51922
52251
|
}
|
|
51923
52252
|
this.registerCleanupHandlers();
|
|
@@ -51977,6 +52306,15 @@ var init_workspace_manager = __esm({
|
|
|
51977
52306
|
* @param timeout Maximum time to wait for active operations (default: 60s)
|
|
51978
52307
|
*/
|
|
51979
52308
|
async cleanup(timeout = 6e4) {
|
|
52309
|
+
if (!this.config.cleanupOnExit) {
|
|
52310
|
+
logger.debug(`[Workspace] Skipping cleanup (cleanupOnExit=false): ${this.workspacePath}`);
|
|
52311
|
+
_WorkspaceManager.instances.delete(this.sessionId);
|
|
52312
|
+
this.initialized = false;
|
|
52313
|
+
this.mainProjectInfo = null;
|
|
52314
|
+
this.projects.clear();
|
|
52315
|
+
this.usedNames.clear();
|
|
52316
|
+
return;
|
|
52317
|
+
}
|
|
51980
52318
|
logger.info(
|
|
51981
52319
|
`Cleaning up workspace: ${this.workspacePath} (active operations: ${this.activeOperations})`
|
|
51982
52320
|
);
|
|
@@ -51986,19 +52324,19 @@ var init_workspace_manager = __esm({
|
|
|
51986
52324
|
);
|
|
51987
52325
|
this.cleanupRequested = true;
|
|
51988
52326
|
await Promise.race([
|
|
51989
|
-
new Promise((
|
|
52327
|
+
new Promise((resolve13) => {
|
|
51990
52328
|
if (this.activeOperations === 0) {
|
|
51991
|
-
|
|
52329
|
+
resolve13();
|
|
51992
52330
|
} else {
|
|
51993
|
-
this.cleanupResolvers.push(
|
|
52331
|
+
this.cleanupResolvers.push(resolve13);
|
|
51994
52332
|
}
|
|
51995
52333
|
}),
|
|
51996
|
-
new Promise((
|
|
52334
|
+
new Promise((resolve13) => {
|
|
51997
52335
|
setTimeout(() => {
|
|
51998
52336
|
logger.warn(
|
|
51999
52337
|
`[Workspace] Cleanup timeout after ${timeout}ms, proceeding anyway (${this.activeOperations} operations still active)`
|
|
52000
52338
|
);
|
|
52001
|
-
|
|
52339
|
+
resolve13();
|
|
52002
52340
|
}, timeout);
|
|
52003
52341
|
})
|
|
52004
52342
|
]);
|
|
@@ -52028,6 +52366,68 @@ var init_workspace_manager = __esm({
|
|
|
52028
52366
|
logger.warn(`Failed to cleanup workspace: ${error}`);
|
|
52029
52367
|
}
|
|
52030
52368
|
}
|
|
52369
|
+
/**
|
|
52370
|
+
* Check if a path exists (file or directory).
|
|
52371
|
+
*/
|
|
52372
|
+
async pathExists(p) {
|
|
52373
|
+
try {
|
|
52374
|
+
await fsp2.access(p);
|
|
52375
|
+
return true;
|
|
52376
|
+
} catch {
|
|
52377
|
+
return false;
|
|
52378
|
+
}
|
|
52379
|
+
}
|
|
52380
|
+
/**
|
|
52381
|
+
* Clean up stale workspace directories older than maxAge.
|
|
52382
|
+
* Call periodically (e.g. at socket-runner startup) to prevent disk bloat.
|
|
52383
|
+
*/
|
|
52384
|
+
static async cleanupStale(basePath = process.env.VISOR_WORKSPACE_PATH || "/tmp/visor-workspaces", maxAgeMs = 24 * 60 * 60 * 1e3) {
|
|
52385
|
+
let cleaned = 0;
|
|
52386
|
+
try {
|
|
52387
|
+
const entries = await fsp2.readdir(basePath, { withFileTypes: true });
|
|
52388
|
+
const now = Date.now();
|
|
52389
|
+
for (const entry of entries) {
|
|
52390
|
+
if (!entry.isDirectory()) continue;
|
|
52391
|
+
const dirPath = path23.join(basePath, entry.name);
|
|
52392
|
+
try {
|
|
52393
|
+
const stat2 = await fsp2.stat(dirPath);
|
|
52394
|
+
if (now - stat2.mtimeMs > maxAgeMs) {
|
|
52395
|
+
try {
|
|
52396
|
+
const subdirs = await fsp2.readdir(dirPath, { withFileTypes: true });
|
|
52397
|
+
for (const sub of subdirs) {
|
|
52398
|
+
if (!sub.isDirectory()) continue;
|
|
52399
|
+
const subPath = path23.join(dirPath, sub.name);
|
|
52400
|
+
const gitFilePath = path23.join(subPath, ".git");
|
|
52401
|
+
try {
|
|
52402
|
+
const gitContent = await fsp2.readFile(gitFilePath, "utf-8");
|
|
52403
|
+
const match = gitContent.match(/gitdir:\s*(.+)/);
|
|
52404
|
+
if (match) {
|
|
52405
|
+
const worktreeGitDir = match[1].trim();
|
|
52406
|
+
const repoGitDir = worktreeGitDir.replace(/\/\.git\/worktrees\/.*$/, "");
|
|
52407
|
+
await commandExecutor.execute(
|
|
52408
|
+
`git -C ${shellEscape(repoGitDir)} worktree remove ${shellEscape(subPath)} --force`,
|
|
52409
|
+
{ timeout: 1e4 }
|
|
52410
|
+
);
|
|
52411
|
+
}
|
|
52412
|
+
} catch {
|
|
52413
|
+
}
|
|
52414
|
+
}
|
|
52415
|
+
} catch {
|
|
52416
|
+
}
|
|
52417
|
+
await fsp2.rm(dirPath, { recursive: true, force: true });
|
|
52418
|
+
cleaned++;
|
|
52419
|
+
}
|
|
52420
|
+
} catch {
|
|
52421
|
+
}
|
|
52422
|
+
}
|
|
52423
|
+
if (cleaned > 0) {
|
|
52424
|
+
logger.info(`[Workspace] Cleaned up ${cleaned} stale workspace(s) from ${basePath}`);
|
|
52425
|
+
}
|
|
52426
|
+
} catch (error) {
|
|
52427
|
+
logger.debug(`[Workspace] Stale cleanup error: ${error}`);
|
|
52428
|
+
}
|
|
52429
|
+
return cleaned;
|
|
52430
|
+
}
|
|
52031
52431
|
/**
|
|
52032
52432
|
* Create worktree for the main project
|
|
52033
52433
|
*
|
|
@@ -52322,12 +52722,12 @@ var ndjson_sink_exports = {};
|
|
|
52322
52722
|
__export(ndjson_sink_exports, {
|
|
52323
52723
|
NdjsonSink: () => NdjsonSink
|
|
52324
52724
|
});
|
|
52325
|
-
var
|
|
52725
|
+
var import_fs9, import_path13, NdjsonSink;
|
|
52326
52726
|
var init_ndjson_sink = __esm({
|
|
52327
52727
|
"src/frontends/ndjson-sink.ts"() {
|
|
52328
52728
|
"use strict";
|
|
52329
|
-
|
|
52330
|
-
|
|
52729
|
+
import_fs9 = __toESM(require("fs"));
|
|
52730
|
+
import_path13 = __toESM(require("path"));
|
|
52331
52731
|
NdjsonSink = class {
|
|
52332
52732
|
name = "ndjson-sink";
|
|
52333
52733
|
cfg;
|
|
@@ -52348,7 +52748,7 @@ var init_ndjson_sink = __esm({
|
|
|
52348
52748
|
payload: envelope && envelope.payload || envelope,
|
|
52349
52749
|
safe: true
|
|
52350
52750
|
});
|
|
52351
|
-
await
|
|
52751
|
+
await import_fs9.default.promises.appendFile(this.filePath, line + "\n");
|
|
52352
52752
|
} catch (err) {
|
|
52353
52753
|
ctx.logger.error("[ndjson-sink] Failed to write event:", err);
|
|
52354
52754
|
}
|
|
@@ -52359,8 +52759,8 @@ var init_ndjson_sink = __esm({
|
|
|
52359
52759
|
this.unsub = void 0;
|
|
52360
52760
|
}
|
|
52361
52761
|
resolveFile(p) {
|
|
52362
|
-
if (
|
|
52363
|
-
return
|
|
52762
|
+
if (import_path13.default.isAbsolute(p)) return p;
|
|
52763
|
+
return import_path13.default.join(process.cwd(), p);
|
|
52364
52764
|
}
|
|
52365
52765
|
};
|
|
52366
52766
|
}
|
|
@@ -53183,8 +53583,8 @@ ${content}
|
|
|
53183
53583
|
* Sleep utility
|
|
53184
53584
|
*/
|
|
53185
53585
|
sleep(ms) {
|
|
53186
|
-
return new Promise((
|
|
53187
|
-
const t = setTimeout(
|
|
53586
|
+
return new Promise((resolve13) => {
|
|
53587
|
+
const t = setTimeout(resolve13, ms);
|
|
53188
53588
|
if (typeof t.unref === "function") {
|
|
53189
53589
|
try {
|
|
53190
53590
|
t.unref();
|
|
@@ -53458,8 +53858,8 @@ ${end}`);
|
|
|
53458
53858
|
async updateGroupedComment(ctx, comments, group, changedIds) {
|
|
53459
53859
|
const existingLock = this.updateLocks.get(group);
|
|
53460
53860
|
let resolveLock;
|
|
53461
|
-
const ourLock = new Promise((
|
|
53462
|
-
resolveLock =
|
|
53861
|
+
const ourLock = new Promise((resolve13) => {
|
|
53862
|
+
resolveLock = resolve13;
|
|
53463
53863
|
});
|
|
53464
53864
|
this.updateLocks.set(group, ourLock);
|
|
53465
53865
|
try {
|
|
@@ -53771,7 +54171,7 @@ ${blocks}
|
|
|
53771
54171
|
* Sleep utility for enforcing delays
|
|
53772
54172
|
*/
|
|
53773
54173
|
sleep(ms) {
|
|
53774
|
-
return new Promise((
|
|
54174
|
+
return new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
53775
54175
|
}
|
|
53776
54176
|
};
|
|
53777
54177
|
}
|