mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-15 19:10:44 +00:00
[codex] Extract filesystem safety primitives (#77918)
* refactor: extract filesystem safety primitives * refactor: use fs-safe for file access helpers * refactor: reuse fs-safe for media reads * refactor: use fs-safe for image reads * refactor: reuse fs-safe in qqbot media opener * refactor: reuse fs-safe for local media checks * refactor: consume cleaner fs-safe api * refactor: align fs-safe json option names * fix: preserve fs-safe migration contracts * refactor: use fs-safe primitive subpaths * refactor: use grouped fs-safe subpaths * refactor: align fs-safe api usage * refactor: adapt private state store api * chore: refresh proof gate * refactor: follow fs-safe json api split * refactor: follow reduced fs-safe surface * build: default fs-safe python helper off * fix: preserve fs-safe plugin sdk aliases * refactor: consolidate fs-safe usage * refactor: unify fs-safe store usage * refactor: trim fs-safe temp workspace usage * refactor: hide low-level fs-safe primitives * build: use published fs-safe package * fix: preserve outbound recovery durability after rebase * chore: refresh pr checks
This commit is contained in:
committed by
GitHub
parent
61481eb34f
commit
538605ff44
@@ -15,6 +15,7 @@ import {
|
||||
resolvePreferredOpenClawTmpDir,
|
||||
runSshSandboxCommand,
|
||||
sanitizeEnvVars,
|
||||
withTempWorkspace,
|
||||
} from "openclaw/plugin-sdk/sandbox";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { OpenShellSandboxBackend } from "./backend.types.js";
|
||||
@@ -411,65 +412,61 @@ class OpenShellSandboxBackendImpl {
|
||||
}
|
||||
|
||||
private async syncWorkspaceFromRemote(): Promise<void> {
|
||||
const tmpDir = await fs.mkdtemp(
|
||||
path.join(resolveOpenShellTmpRoot(), "openclaw-openshell-sync-"),
|
||||
await withTempWorkspace(
|
||||
{ rootDir: resolveOpenShellTmpRoot(), prefix: "openclaw-openshell-sync-" },
|
||||
async ({ dir: tmpDir }) => {
|
||||
const result = await runOpenShellCli({
|
||||
context: this.params.execContext,
|
||||
args: [
|
||||
"sandbox",
|
||||
"download",
|
||||
this.params.execContext.sandboxName,
|
||||
this.params.remoteWorkspaceDir,
|
||||
tmpDir,
|
||||
],
|
||||
cwd: this.params.createParams.workspaceDir,
|
||||
});
|
||||
if (result.code !== 0) {
|
||||
throw new Error(result.stderr.trim() || "openshell sandbox download failed");
|
||||
}
|
||||
await replaceDirectoryContents({
|
||||
sourceDir: tmpDir,
|
||||
targetDir: this.params.createParams.workspaceDir,
|
||||
// Never sync trusted host hook directories or repository metadata from
|
||||
// the remote sandbox.
|
||||
excludeDirs: DEFAULT_OPEN_SHELL_MIRROR_EXCLUDE_DIRS,
|
||||
});
|
||||
},
|
||||
);
|
||||
try {
|
||||
const result = await runOpenShellCli({
|
||||
context: this.params.execContext,
|
||||
args: [
|
||||
"sandbox",
|
||||
"download",
|
||||
this.params.execContext.sandboxName,
|
||||
this.params.remoteWorkspaceDir,
|
||||
tmpDir,
|
||||
],
|
||||
cwd: this.params.createParams.workspaceDir,
|
||||
});
|
||||
if (result.code !== 0) {
|
||||
throw new Error(result.stderr.trim() || "openshell sandbox download failed");
|
||||
}
|
||||
await replaceDirectoryContents({
|
||||
sourceDir: tmpDir,
|
||||
targetDir: this.params.createParams.workspaceDir,
|
||||
// Never sync trusted host hook directories or repository metadata from
|
||||
// the remote sandbox.
|
||||
excludeDirs: DEFAULT_OPEN_SHELL_MIRROR_EXCLUDE_DIRS,
|
||||
});
|
||||
} finally {
|
||||
await fs.rm(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
private async uploadPathToRemote(localPath: string, remotePath: string): Promise<void> {
|
||||
const tmpDir = await fs.mkdtemp(
|
||||
path.join(resolveOpenShellTmpRoot(), "openclaw-openshell-upload-"),
|
||||
await withTempWorkspace(
|
||||
{ rootDir: resolveOpenShellTmpRoot(), prefix: "openclaw-openshell-upload-" },
|
||||
async ({ dir: tmpDir }) => {
|
||||
// Stage a symlink-free snapshot so upload never dereferences host paths
|
||||
// outside the mirrored workspace tree.
|
||||
await stageDirectoryContents({
|
||||
sourceDir: localPath,
|
||||
targetDir: tmpDir,
|
||||
});
|
||||
const result = await runOpenShellCli({
|
||||
context: this.params.execContext,
|
||||
args: [
|
||||
"sandbox",
|
||||
"upload",
|
||||
"--no-git-ignore",
|
||||
this.params.execContext.sandboxName,
|
||||
tmpDir,
|
||||
remotePath,
|
||||
],
|
||||
cwd: this.params.createParams.workspaceDir,
|
||||
});
|
||||
if (result.code !== 0) {
|
||||
throw new Error(result.stderr.trim() || "openshell sandbox upload failed");
|
||||
}
|
||||
},
|
||||
);
|
||||
try {
|
||||
// Stage a symlink-free snapshot so upload never dereferences host paths
|
||||
// outside the mirrored workspace tree.
|
||||
await stageDirectoryContents({
|
||||
sourceDir: localPath,
|
||||
targetDir: tmpDir,
|
||||
});
|
||||
const result = await runOpenShellCli({
|
||||
context: this.params.execContext,
|
||||
args: [
|
||||
"sandbox",
|
||||
"upload",
|
||||
"--no-git-ignore",
|
||||
this.params.execContext.sandboxName,
|
||||
tmpDir,
|
||||
remotePath,
|
||||
],
|
||||
cwd: this.params.createParams.workspaceDir,
|
||||
});
|
||||
if (result.code !== 0) {
|
||||
throw new Error(result.stderr.trim() || "openshell sandbox upload failed");
|
||||
}
|
||||
} finally {
|
||||
await fs.rm(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
private async maybeSeedRemoteWorkspace(): Promise<void> {
|
||||
|
||||
Reference in New Issue
Block a user