mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-11-01 13:25:18 +08:00
Merge pull request #2542 from Nikarhub/feat/box-local-env
feat(box): 支持 box.local.env 注入每次 exec,便于 skill 读取配置/凭据
This commit is contained in:
@@ -126,6 +126,7 @@ class BoxService:
|
||||
self.profile = self._load_profile()
|
||||
self.custom_image = self._load_custom_image()
|
||||
self.workspace_quota_mb = self._load_workspace_quota_mb()
|
||||
self.default_env = self._load_default_env()
|
||||
self._admission_policy = (
|
||||
require_cloud_admission_policy(_get_box_config(ap).get('admission')) if self._cloud_managed else None
|
||||
)
|
||||
@@ -1452,6 +1453,10 @@ class BoxService:
|
||||
def build_spec(self, spec_payload: dict, skip_host_mount_validation: bool = False) -> BoxSpec:
|
||||
spec_payload = dict(spec_payload)
|
||||
spec_payload.setdefault('env', {})
|
||||
if self.default_env:
|
||||
merged_env = dict(self.default_env)
|
||||
merged_env.update(spec_payload.get('env') or {})
|
||||
spec_payload['env'] = merged_env
|
||||
if spec_payload.get('host_path') in (None, '') and self.default_workspace is not None:
|
||||
spec_payload['host_path'] = self.default_workspace
|
||||
if spec_payload.get('workspace_quota_mb') in (None, '') and self.workspace_quota_mb is not None:
|
||||
@@ -1750,6 +1755,35 @@ class BoxService:
|
||||
raise BoxValidationError('workspace_quota_mb must be greater than or equal to 0')
|
||||
return value
|
||||
|
||||
def _load_default_env(self) -> dict[str, str]:
|
||||
"""Return ``box.local.env`` as operator-provided sandbox defaults.
|
||||
|
||||
These values are merged into every Box exec payload so sandbox commands
|
||||
can read settings such as a service base URL. A per-call ``env`` supplied
|
||||
by the agent or caller overrides the matching defaults. Non-dict configs
|
||||
and non-string keys or values are ignored.
|
||||
|
||||
The setting is instance-wide, so it is disabled in multi-workspace
|
||||
deployments to keep operator values from reaching every tenant's sandbox.
|
||||
"""
|
||||
raw_env = self._local_config().get('env')
|
||||
if not isinstance(raw_env, dict):
|
||||
return {}
|
||||
if self._cloud_managed:
|
||||
if raw_env:
|
||||
self.ap.logger.warning('box.local.env is ignored in multi-workspace deployments.')
|
||||
return {}
|
||||
|
||||
env: dict[str, str] = {}
|
||||
for key, value in raw_env.items():
|
||||
if not isinstance(key, str) or not isinstance(value, str):
|
||||
continue
|
||||
normalized_key = key.strip()
|
||||
if not normalized_key:
|
||||
continue
|
||||
env[normalized_key] = value
|
||||
return env
|
||||
|
||||
def _ensure_default_workspace(self):
|
||||
if self.default_workspace is None:
|
||||
return
|
||||
|
||||
@@ -457,6 +457,11 @@ box:
|
||||
- './data/box'
|
||||
- '/tmp'
|
||||
workspace_quota_mb: null # Optional disk quota override (>= 0). null = profile default.
|
||||
# Extra environment variables injected into every Box exec payload.
|
||||
# The agent-supplied per-call env overrides matching keys. Values must be strings.
|
||||
# Every sandbox command, including untrusted agent commands, can read them;
|
||||
# do not put secrets here. Loaded at startup; ignored in multi-workspace deployments.
|
||||
env: {}
|
||||
# Default nsjail cgroup memory limit for each MCP stdio server process, in MB.
|
||||
# Node.js MCP servers (npx/bunx) need more memory than Python ones because V8
|
||||
# and WebAssembly modules (e.g. undici llhttp) reserve large virtual address
|
||||
|
||||
Reference in New Issue
Block a user