feat(sandbox): enhance logging with colored output and add AppAssetAttrsInitializer

This commit is contained in:
Harry
2026-01-27 14:19:10 +08:00
parent 64b6a5dd31
commit a29f569e08
6 changed files with 54 additions and 27 deletions

View File

@@ -0,0 +1,24 @@
import logging
from core.app_assets.constants import AppAssetsAttrs
from core.sandbox.sandbox import Sandbox
from services.app_asset_package_service import AppAssetPackageService
from .base import SyncSandboxInitializer
logger = logging.getLogger(__name__)
APP_ASSETS_DOWNLOAD_TIMEOUT = 60 * 10
class AppAssetAttrsInitializer(SyncSandboxInitializer):
def __init__(self, tenant_id: str, app_id: str, assets_id: str) -> None:
self._tenant_id = tenant_id
self._app_id = app_id
self._assets_id = assets_id
def initialize(self, sandbox: Sandbox) -> None:
# Load published app assets and unzip the artifact bundle.
app_assets = AppAssetPackageService.get_tenant_app_assets(self._tenant_id, self._assets_id)
sandbox.attrs.set(AppAssetsAttrs.FILE_TREE, app_assets.asset_tree)
sandbox.attrs.set(AppAssetsAttrs.APP_ASSETS_ID, self._assets_id)

View File

@@ -1,6 +1,5 @@
import logging
from core.app_assets.constants import AppAssetsAttrs
from core.app_assets.storage import AssetPath
from core.sandbox.sandbox import Sandbox
from core.virtual_environment.__base.helpers import pipeline
@@ -20,13 +19,9 @@ class AppAssetsInitializer(AsyncSandboxInitializer):
self._assets_id = assets_id
def initialize(self, sandbox: Sandbox) -> None:
from services.app_asset_package_service import AppAssetPackageService
from services.app_asset_service import AppAssetService
# Load published app assets and unzip the artifact bundle.
app_assets = AppAssetPackageService.get_tenant_app_assets(self._tenant_id, self._assets_id)
sandbox.attrs.set(AppAssetsAttrs.FILE_TREE, app_assets.asset_tree)
sandbox.attrs.set(AppAssetsAttrs.APP_ASSETS_ID, self._assets_id)
vm = sandbox.vm
asset_storage = AppAssetService.get_storage()
zip_ref = AssetPath.build_zip(self._tenant_id, self._app_id, self._assets_id)

View File

@@ -7,7 +7,6 @@ from core.sandbox.sandbox import Sandbox
from core.sandbox.services import AssetDownloadService
from core.sandbox.services.asset_download_service import AssetDownloadItem
from core.virtual_environment.__base.helpers import pipeline
from services.app_asset_package_service import AppAssetPackageService
from services.app_asset_service import AppAssetService
from .base import AsyncSandboxInitializer
@@ -26,13 +25,9 @@ class DraftAppAssetsInitializer(AsyncSandboxInitializer):
def initialize(self, sandbox: Sandbox) -> None:
# Load published app assets and unzip the artifact bundle.
app_assets = AppAssetPackageService.get_tenant_app_assets(self._tenant_id, self._assets_id)
sandbox.attrs.set(AppAssetsAttrs.FILE_TREE, app_assets.asset_tree)
sandbox.attrs.set(AppAssetsAttrs.APP_ASSETS_ID, self._assets_id)
vm = sandbox.vm
build_id = self._assets_id
tree = app_assets.asset_tree
tree = sandbox.attrs.get(AppAssetsAttrs.FILE_TREE)
asset_storage = AppAssetService.get_storage()
nodes = list(tree.walk_files())
if not nodes:

View File

@@ -298,17 +298,18 @@ class LLMNode(Node[LLMNodeData]):
structured_output: LLMStructuredOutput | None = None
sandbox = self.graph_runtime_state.sandbox
if self.tool_call_enabled:
if sandbox:
tool_dependencies = self._extract_tool_dependencies()
generator = self._invoke_llm_with_sandbox(
sandbox=sandbox,
model_instance=model_instance,
prompt_messages=prompt_messages,
stop=stop,
variable_pool=variable_pool,
tool_dependencies=tool_dependencies,
)
has_skill_prompt = self._has_skill_prompt()
if sandbox and has_skill_prompt:
tool_dependencies = self._extract_tool_dependencies()
generator = self._invoke_llm_with_sandbox(
sandbox=sandbox,
model_instance=model_instance,
prompt_messages=prompt_messages,
stop=stop,
variable_pool=variable_pool,
tool_dependencies=tool_dependencies,
)
elif self.tool_call_enabled:
generator = self._invoke_llm_with_tools(
model_instance=model_instance,
prompt_messages=prompt_messages,
@@ -1811,6 +1812,12 @@ class LLMNode(Node[LLMNodeData]):
generation_data,
)
def _has_skill_prompt(self) -> bool:
for prompt in self.node_data.prompt_template:
if isinstance(prompt, LLMNodeChatModelMessage) and prompt.skill:
return True
return False
def _extract_tool_dependencies(self) -> ToolDependencies | None:
"""Extract tool artifact from prompt template."""

View File

@@ -78,6 +78,7 @@ class AppAssetPackageService:
assets: list[AssetItem],
upload_url: str,
tenant_id: str,
app_id: str,
user_id: str,
) -> None:
"""Package assets into a ZIP and upload directly to the given URL."""
@@ -97,13 +98,11 @@ class AppAssetPackageService:
return
asset_storage = AppAssetService.get_storage()
storage_keys = [a.get_storage_key() for a in assets]
download_urls = asset_storage.storage.get_download_urls(storage_keys, 10 * 60)
asset_paths = [AssetPath.draft(tenant_id, app_id, asset.asset_id) for asset in assets]
download_urls = asset_storage.get_download_urls(asset_paths)
download_items = [
SandboxDownloadItem(url=url, path=a.path) for a, url in zip(assets, download_urls, strict=True)
SandboxDownloadItem(url=url, path=asset.path) for asset, url in zip(assets, download_urls, strict=True)
]
with ZipSandbox(tenant_id=tenant_id, user_id=user_id, app_id="asset-packager") as zs:
zs.download_items(download_items)
archive = zs.zip()
@@ -146,6 +145,7 @@ class AppAssetPackageService:
assets=built_assets,
upload_url=runtime_upload_url,
tenant_id=tenant_id,
app_id=app_id,
user_id=account_id,
)
@@ -156,6 +156,7 @@ class AppAssetPackageService:
assets=source_items,
upload_url=source_upload_url,
tenant_id=tenant_id,
app_id=app_id,
user_id=account_id,
)
@@ -181,5 +182,6 @@ class AppAssetPackageService:
assets=built_assets,
upload_url=upload_url,
tenant_id=tenant_id,
app_id=app_id,
user_id=user_id,
)

View File

@@ -3,6 +3,7 @@ import logging
from core.sandbox.builder import SandboxBuilder
from core.sandbox.entities import AppAssets, SandboxType
from core.sandbox.entities.providers import SandboxProviderEntity
from core.sandbox.initializer.app_asset_attrs_initializer import AppAssetAttrsInitializer
from core.sandbox.initializer.app_assets_initializer import AppAssetsInitializer
from core.sandbox.initializer.dify_cli_initializer import DifyCliInitializer
from core.sandbox.initializer.draft_app_assets_initializer import DraftAppAssetsInitializer
@@ -35,6 +36,7 @@ class SandboxService:
.options(sandbox_provider.config)
.user(user_id)
.app(app_id)
.initializer(AppAssetAttrsInitializer(tenant_id, app_id, assets.id))
.initializer(AppAssetsInitializer(tenant_id, app_id, assets.id))
.initializer(DifyCliInitializer(tenant_id, user_id, app_id, assets.id))
.initializer(SkillInitializer(tenant_id, user_id, app_id, assets.id))
@@ -71,6 +73,7 @@ class SandboxService:
.options(sandbox_provider.config)
.user(user_id)
.app(app_id)
.initializer(AppAssetAttrsInitializer(tenant_id, app_id, assets.id))
.initializer(DraftAppAssetsInitializer(tenant_id, app_id, assets.id))
.initializer(DifyCliInitializer(tenant_id, user_id, app_id, assets.id))
.initializer(SkillInitializer(tenant_id, user_id, app_id, assets.id))
@@ -102,6 +105,7 @@ class SandboxService:
.options(sandbox_provider.config)
.user(user_id)
.app(app_id)
.initializer(AppAssetAttrsInitializer(tenant_id, app_id, assets.id))
.initializer(DraftAppAssetsInitializer(tenant_id, app_id, assets.id))
.initializer(DifyCliInitializer(tenant_id, user_id, app_id, assets.id))
.initializer(SkillInitializer(tenant_id, user_id, app_id, assets.id))