feat(sandbox): refactor sandbox file handling to include app_id

- Updated API routes to use app_id instead of sandbox_id for file operations, aligning with user-specific sandbox workspaces.
- Enhanced SandboxFileService and related classes to accommodate app_id in file listing and download functionalities.
- Refactored storage key generation for sandbox archives to include app_id, ensuring proper file organization.
- Adjusted frontend contracts and services to reflect the new app_id parameter in API calls.
This commit is contained in:
Harry
2026-01-30 22:20:04 +08:00
parent bc1d3bdf57
commit bb4dd85ae3
16 changed files with 187 additions and 116 deletions

View File

@ -21,9 +21,9 @@ class SandboxFileService:
)
@classmethod
def exists(cls, *, tenant_id: str, sandbox_id: str) -> bool:
def exists(cls, *, tenant_id: str, app_id: str, sandbox_id: str) -> bool:
"""Check if the sandbox source exists and is available."""
browser = SandboxFileBrowser(tenant_id=tenant_id, sandbox_id=sandbox_id)
browser = SandboxFileBrowser(tenant_id=tenant_id, app_id=app_id, sandbox_id=sandbox_id)
return browser.exists()
@classmethod
@ -31,18 +31,19 @@ class SandboxFileService:
cls,
*,
tenant_id: str,
app_id: str,
sandbox_id: str,
path: str | None = None,
recursive: bool = False,
) -> list[SandboxFileNode]:
browser = SandboxFileBrowser(tenant_id=tenant_id, sandbox_id=sandbox_id)
browser = SandboxFileBrowser(tenant_id=tenant_id, app_id=app_id, sandbox_id=sandbox_id)
if not browser.exists():
return []
return browser.list_files(path=path, recursive=recursive)
@classmethod
def download_file(cls, *, tenant_id: str, sandbox_id: str, path: str) -> SandboxFileDownloadTicket:
browser = SandboxFileBrowser(tenant_id=tenant_id, sandbox_id=sandbox_id)
def download_file(cls, *, tenant_id: str, app_id: str, sandbox_id: str, path: str) -> SandboxFileDownloadTicket:
browser = SandboxFileBrowser(tenant_id=tenant_id, app_id=app_id, sandbox_id=sandbox_id)
if not browser.exists():
raise ValueError("Sandbox source not found")
return browser.download_file(path=path)

View File

@ -31,7 +31,7 @@ class SandboxService:
if not assets:
raise ValueError(f"No assets found for tid={tenant_id}, app_id={app_id}")
archive_storage = ArchiveSandboxStorage(tenant_id, workflow_execution_id, storage.storage_runner)
archive_storage = ArchiveSandboxStorage(tenant_id, app_id, workflow_execution_id, storage.storage_runner)
sandbox = (
SandboxBuilder(tenant_id, SandboxType(sandbox_provider.provider_type))
.options(sandbox_provider.config)
@ -49,8 +49,10 @@ class SandboxService:
return sandbox
@classmethod
def delete_draft_storage(cls, tenant_id: str, user_id: str) -> None:
archive_storage = ArchiveSandboxStorage(tenant_id, SandboxBuilder.draft_id(user_id), storage.storage_runner)
def delete_draft_storage(cls, tenant_id: str, app_id: str, user_id: str) -> None:
archive_storage = ArchiveSandboxStorage(
tenant_id, app_id, SandboxBuilder.draft_id(user_id), storage.storage_runner
)
archive_storage.delete()
@classmethod
@ -65,10 +67,12 @@ class SandboxService:
if not assets:
raise ValueError(f"No assets found for tid={tenant_id}, app_id={app_id}")
SandboxService.delete_draft_storage(tenant_id, app_id, user_id)
AppAssetPackageService.build_assets(tenant_id, app_id, assets)
sandbox_id = SandboxBuilder.draft_id(user_id)
archive_storage = ArchiveSandboxStorage(
tenant_id, sandbox_id, storage.storage_runner, exclude_patterns=[AppAssets.PATH]
tenant_id, app_id, sandbox_id, storage.storage_runner, exclude_patterns=[AppAssets.PATH]
)
sandbox = (
@ -102,7 +106,7 @@ class SandboxService:
AppAssetPackageService.build_assets(tenant_id, app_id, assets)
sandbox_id = SandboxBuilder.draft_id(user_id)
archive_storage = ArchiveSandboxStorage(
tenant_id, sandbox_id, storage.storage_runner, exclude_patterns=[AppAssets.PATH]
tenant_id, app_id, sandbox_id, storage.storage_runner, exclude_patterns=[AppAssets.PATH]
)
sandbox = (