fix: centralize sandbox temp path management

This commit is contained in:
Harry
2026-03-12 16:03:01 +08:00
parent 1d1f09dc92
commit 2aff0ada8f
4 changed files with 24 additions and 12 deletions

View File

@ -72,14 +72,14 @@ class SandboxBashSession:
tools: ToolDependencies,
cli_api_session: CliApiSession,
) -> str:
node_tools_path = f"{cli.tools_root}/{node_id}"
node_tools_path = cli.node_tools_path(node_id)
config_json = json.dumps(
DifyCliConfig.create(session=cli_api_session, tenant_id=self._tenant_id, tool_deps=tools).model_dump(
mode="json"
),
ensure_ascii=False,
)
config_path = shlex.quote(f"{node_tools_path}/{DifyCli.CONFIG_FILENAME}")
config_path = shlex.quote(cli.node_config_path(node_id))
vm = self._sandbox.vm
# Merge mkdir + config write into a single pipeline to reduce round-trips.

View File

@ -19,15 +19,25 @@ class DifyCli:
# --- instance attributes ---
root: str
bin_dir: str
bin_path: str
tools_root: str
global_tools_path: str
global_config_path: str
def __init__(self, env_id: str) -> None:
self.root = f"/tmp/.dify/{env_id}"
self.bin_path = f"{self.root}/bin/dify"
self.bin_dir = f"{self.root}/bin"
self.bin_path = f"{self.bin_dir}/dify"
self.tools_root = f"{self.root}/tools"
self.global_tools_path = f"{self.root}/tools/global"
self.global_config_path = f"{self.global_tools_path}/{DifyCli.CONFIG_FILENAME}"
def node_tools_path(self, node_id: str) -> str:
return f"{self.tools_root}/{node_id}"
def node_config_path(self, node_id: str) -> str:
return f"{self.node_tools_path(node_id)}/{DifyCli.CONFIG_FILENAME}"
class AppAssets:
@ -40,7 +50,9 @@ class AppAssets:
PATH: Final[str] = "skills"
root: str
zip_path: str
def __init__(self, env_id: str) -> None:
self.zip_path = f"/tmp/.dify/{env_id}/assets.zip"
self.root = f"/tmp/.dify/{env_id}"
self.zip_path = f"{self.root}/assets.zip"

View File

@ -26,11 +26,11 @@ class AppAssetsInitializer(AsyncSandboxInitializer):
(
pipeline(vm)
.add(
["mkdir", "-p", f"/tmp/.dify/{sandbox.id}"],
["mkdir", "-p", assets.root],
error_message="Failed to create assets temp directory",
)
.add(
["curl", "-fsSL", download_url, "-o", assets.zip_path],
["sh", "-c", 'curl -fsSL "$1" -o "$2"', "sh", download_url, assets.zip_path],
error_message="Failed to download assets zip",
)
# Create the assets directory first to ensure it exists even if zip is empty
@ -41,12 +41,12 @@ class AppAssetsInitializer(AsyncSandboxInitializer):
# unzip with silent error and return 1 if the zip is empty
# FIXME(Mairuis): should use a more robust way to check if the zip is empty
.add(
["sh", "-c", f"unzip {assets.zip_path} -d {AppAssets.PATH} 2>/dev/null || [ $? -eq 1 ]"],
["sh", "-c", 'unzip "$1" -d "$2" 2>/dev/null || [ $? -eq 1 ]', "sh", assets.zip_path, AppAssets.PATH],
error_message="Failed to unzip assets",
)
# Ensure directories have execute permission for traversal and files are readable
.add(
["sh", "-c", f"chmod -R u+rwX,go+rX {AppAssets.PATH}"],
["sh", "-c", 'chmod -R u+rwX,go+rX "$1"', "sh", AppAssets.PATH],
error_message="Failed to set permissions on assets",
)
.execute(timeout=APP_ASSETS_DOWNLOAD_TIMEOUT, raise_on_error=True)

View File

@ -33,9 +33,9 @@ class DifyCliInitializer(AsyncSandboxInitializer):
# FIXME(Mairuis): should be more robust, effectively.
binary = self._locator.resolve(vm.metadata.os, vm.metadata.arch)
pipeline(vm).add(
["mkdir", "-p", f"{cli.root}/bin"], error_message="Failed to create dify CLI directory"
).execute(raise_on_error=True)
pipeline(vm).add(["mkdir", "-p", cli.bin_dir], error_message="Failed to create dify CLI directory").execute(
raise_on_error=True
)
vm.upload_file(cli.bin_path, BytesIO(binary.path.read_bytes()))
@ -69,7 +69,7 @@ class DifyCliInitializer(AsyncSandboxInitializer):
config = DifyCliConfig.create(self._cli_api_session, ctx.tenant_id, bundle.get_tool_dependencies())
config_json = json.dumps(config.model_dump(mode="json"), ensure_ascii=False)
config_path = f"{cli.global_tools_path}/{DifyCli.CONFIG_FILENAME}"
config_path = cli.global_config_path
vm.upload_file(config_path, BytesIO(config_json.encode("utf-8")))
pipeline(vm, cwd=cli.global_tools_path).add(