mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 18:17:27 +00:00
149 lines
4.9 KiB
TypeScript
149 lines
4.9 KiB
TypeScript
import fs from "node:fs/promises";
|
|
|
|
import type { ClawdbotConfig } from "../../config/config.js";
|
|
import { defaultRuntime } from "../../runtime.js";
|
|
import { resolveUserPath } from "../../utils.js";
|
|
import { DEFAULT_BROWSER_EVALUATE_ENABLED } from "../../browser/constants.js";
|
|
import { syncSkillsToWorkspace } from "../skills.js";
|
|
import { DEFAULT_AGENT_WORKSPACE_DIR } from "../workspace.js";
|
|
import { ensureSandboxBrowser } from "./browser.js";
|
|
import { resolveSandboxConfigForAgent } from "./config.js";
|
|
import { ensureSandboxContainer } from "./docker.js";
|
|
import { maybePruneSandboxes } from "./prune.js";
|
|
import { resolveSandboxRuntimeStatus } from "./runtime-status.js";
|
|
import { resolveSandboxScopeKey, resolveSandboxWorkspaceDir } from "./shared.js";
|
|
import type { SandboxContext, SandboxWorkspaceInfo } from "./types.js";
|
|
import { ensureSandboxWorkspace } from "./workspace.js";
|
|
|
|
export async function resolveSandboxContext(params: {
|
|
config?: ClawdbotConfig;
|
|
sessionKey?: string;
|
|
workspaceDir?: string;
|
|
}): Promise<SandboxContext | null> {
|
|
const rawSessionKey = params.sessionKey?.trim();
|
|
if (!rawSessionKey) return null;
|
|
|
|
const runtime = resolveSandboxRuntimeStatus({
|
|
cfg: params.config,
|
|
sessionKey: rawSessionKey,
|
|
});
|
|
if (!runtime.sandboxed) return null;
|
|
|
|
const cfg = resolveSandboxConfigForAgent(params.config, runtime.agentId);
|
|
|
|
await maybePruneSandboxes(cfg);
|
|
|
|
const agentWorkspaceDir = resolveUserPath(
|
|
params.workspaceDir?.trim() || DEFAULT_AGENT_WORKSPACE_DIR,
|
|
);
|
|
const workspaceRoot = resolveUserPath(cfg.workspaceRoot);
|
|
const scopeKey = resolveSandboxScopeKey(cfg.scope, rawSessionKey);
|
|
const sandboxWorkspaceDir =
|
|
cfg.scope === "shared" ? workspaceRoot : resolveSandboxWorkspaceDir(workspaceRoot, scopeKey);
|
|
const workspaceDir = cfg.workspaceAccess === "rw" ? agentWorkspaceDir : sandboxWorkspaceDir;
|
|
if (workspaceDir === sandboxWorkspaceDir) {
|
|
await ensureSandboxWorkspace(
|
|
sandboxWorkspaceDir,
|
|
agentWorkspaceDir,
|
|
params.config?.agents?.defaults?.skipBootstrap,
|
|
);
|
|
if (cfg.workspaceAccess !== "rw") {
|
|
try {
|
|
await syncSkillsToWorkspace({
|
|
sourceWorkspaceDir: agentWorkspaceDir,
|
|
targetWorkspaceDir: sandboxWorkspaceDir,
|
|
config: params.config,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : JSON.stringify(error);
|
|
defaultRuntime.error?.(`Sandbox skill sync failed: ${message}`);
|
|
}
|
|
}
|
|
} else {
|
|
await fs.mkdir(workspaceDir, { recursive: true });
|
|
}
|
|
|
|
const containerName = await ensureSandboxContainer({
|
|
sessionKey: rawSessionKey,
|
|
workspaceDir,
|
|
agentWorkspaceDir,
|
|
cfg,
|
|
});
|
|
|
|
const evaluateEnabled =
|
|
params.config?.browser?.evaluateEnabled ?? DEFAULT_BROWSER_EVALUATE_ENABLED;
|
|
const browser = await ensureSandboxBrowser({
|
|
scopeKey,
|
|
workspaceDir,
|
|
agentWorkspaceDir,
|
|
cfg,
|
|
evaluateEnabled,
|
|
});
|
|
|
|
return {
|
|
enabled: true,
|
|
sessionKey: rawSessionKey,
|
|
workspaceDir,
|
|
agentWorkspaceDir,
|
|
workspaceAccess: cfg.workspaceAccess,
|
|
containerName,
|
|
containerWorkdir: cfg.docker.workdir,
|
|
docker: cfg.docker,
|
|
tools: cfg.tools,
|
|
browserAllowHostControl: cfg.browser.allowHostControl,
|
|
browser: browser ?? undefined,
|
|
};
|
|
}
|
|
|
|
export async function ensureSandboxWorkspaceForSession(params: {
|
|
config?: ClawdbotConfig;
|
|
sessionKey?: string;
|
|
workspaceDir?: string;
|
|
}): Promise<SandboxWorkspaceInfo | null> {
|
|
const rawSessionKey = params.sessionKey?.trim();
|
|
if (!rawSessionKey) return null;
|
|
|
|
const runtime = resolveSandboxRuntimeStatus({
|
|
cfg: params.config,
|
|
sessionKey: rawSessionKey,
|
|
});
|
|
if (!runtime.sandboxed) return null;
|
|
|
|
const cfg = resolveSandboxConfigForAgent(params.config, runtime.agentId);
|
|
|
|
const agentWorkspaceDir = resolveUserPath(
|
|
params.workspaceDir?.trim() || DEFAULT_AGENT_WORKSPACE_DIR,
|
|
);
|
|
const workspaceRoot = resolveUserPath(cfg.workspaceRoot);
|
|
const scopeKey = resolveSandboxScopeKey(cfg.scope, rawSessionKey);
|
|
const sandboxWorkspaceDir =
|
|
cfg.scope === "shared" ? workspaceRoot : resolveSandboxWorkspaceDir(workspaceRoot, scopeKey);
|
|
const workspaceDir = cfg.workspaceAccess === "rw" ? agentWorkspaceDir : sandboxWorkspaceDir;
|
|
if (workspaceDir === sandboxWorkspaceDir) {
|
|
await ensureSandboxWorkspace(
|
|
sandboxWorkspaceDir,
|
|
agentWorkspaceDir,
|
|
params.config?.agents?.defaults?.skipBootstrap,
|
|
);
|
|
if (cfg.workspaceAccess !== "rw") {
|
|
try {
|
|
await syncSkillsToWorkspace({
|
|
sourceWorkspaceDir: agentWorkspaceDir,
|
|
targetWorkspaceDir: sandboxWorkspaceDir,
|
|
config: params.config,
|
|
});
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : JSON.stringify(error);
|
|
defaultRuntime.error?.(`Sandbox skill sync failed: ${message}`);
|
|
}
|
|
}
|
|
} else {
|
|
await fs.mkdir(workspaceDir, { recursive: true });
|
|
}
|
|
|
|
return {
|
|
workspaceDir,
|
|
containerWorkdir: cfg.docker.workdir,
|
|
};
|
|
}
|