mirror of
https://github.com/langgenius/dify.git
synced 2026-09-24 23:22:26 +08:00
feat(agent): support cli tool scoped env (#37324)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
autofix-ci[bot]
parent
c4a8d79be9
commit
fb39df49c8
@@ -508,7 +508,32 @@ def _shell_cli_tool(item: object) -> DifyShellCliToolConfig | None:
|
||||
name = data.get("name") or data.get("tool_name") or data.get("label")
|
||||
if not commands and not isinstance(name, str):
|
||||
return None
|
||||
return DifyShellCliToolConfig(name=name if isinstance(name, str) else None, install_commands=commands)
|
||||
tool_env = data.get("env") if isinstance(data.get("env"), Mapping) else {}
|
||||
env = [
|
||||
env_var
|
||||
for env_var in (_shell_env_var(item) for item in _env_entries(tool_env, "variables"))
|
||||
if env_var is not None
|
||||
]
|
||||
secret_refs = [
|
||||
secret_ref
|
||||
for secret_ref in (_shell_secret_ref(item) for item in _env_entries(tool_env, "secret_refs"))
|
||||
if secret_ref is not None
|
||||
]
|
||||
return DifyShellCliToolConfig(
|
||||
name=name if isinstance(name, str) else None,
|
||||
install_commands=commands,
|
||||
env=env,
|
||||
secret_refs=secret_refs,
|
||||
)
|
||||
|
||||
|
||||
def _env_entries(env: object, key: str) -> list[object]:
|
||||
if not isinstance(env, Mapping):
|
||||
return []
|
||||
entries = env.get(key)
|
||||
if not isinstance(entries, list):
|
||||
return []
|
||||
return entries
|
||||
|
||||
|
||||
def _shell_env_var(item: object) -> DifyShellEnvVarConfig | None:
|
||||
|
||||
@@ -363,8 +363,37 @@ class WorkflowAgentNodeValidator:
|
||||
agent_soul: AgentSoulConfig,
|
||||
) -> None:
|
||||
seen_names: set[str] = set()
|
||||
for env_var in agent_soul.env.variables:
|
||||
name = env_var.name
|
||||
cls._validate_env_entries(
|
||||
binding=binding,
|
||||
seen_names=seen_names,
|
||||
variables=agent_soul.env.variables,
|
||||
secret_refs=agent_soul.env.secret_refs,
|
||||
label="agent",
|
||||
)
|
||||
for cli_tool in agent_soul.tools.cli_tools:
|
||||
if not cli_tool.enabled:
|
||||
continue
|
||||
name = cli_tool.get("name") or cli_tool.get("tool_name") or cli_tool.get("label") or "<unnamed>"
|
||||
cls._validate_env_entries(
|
||||
binding=binding,
|
||||
seen_names=seen_names,
|
||||
variables=cli_tool.env.variables,
|
||||
secret_refs=cli_tool.env.secret_refs,
|
||||
label=f"CLI Tool {name}",
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _validate_env_entries(
|
||||
cls,
|
||||
*,
|
||||
binding: WorkflowAgentNodeBinding,
|
||||
seen_names: set[str],
|
||||
variables: list[Any],
|
||||
secret_refs: list[Any],
|
||||
label: str,
|
||||
) -> None:
|
||||
for env_var in variables:
|
||||
name = cls._env_name(env_var)
|
||||
if not name:
|
||||
continue
|
||||
if name in seen_names:
|
||||
@@ -372,13 +401,13 @@ class WorkflowAgentNodeValidator:
|
||||
f"Workflow Agent node {binding.node_id} has duplicate env/secret name {name}."
|
||||
)
|
||||
seen_names.add(name)
|
||||
for secret_ref in agent_soul.env.secret_refs:
|
||||
name = secret_ref.name
|
||||
for secret_ref in secret_refs:
|
||||
name = cls._env_name(secret_ref)
|
||||
if not name:
|
||||
continue
|
||||
if cls._permission_denied(secret_ref.model_dump(mode="python", exclude_none=True, exclude_defaults=True)):
|
||||
raise WorkflowAgentNodeValidationError(
|
||||
f"Workflow Agent node {binding.node_id} has unauthorized secret reference {name}."
|
||||
f"Workflow Agent node {binding.node_id} has unauthorized secret reference {name} in {label}."
|
||||
)
|
||||
if name in seen_names:
|
||||
raise WorkflowAgentNodeValidationError(
|
||||
@@ -386,6 +415,15 @@ class WorkflowAgentNodeValidator:
|
||||
)
|
||||
seen_names.add(name)
|
||||
|
||||
@staticmethod
|
||||
def _env_name(value: Any) -> str | None:
|
||||
if hasattr(value, "get"):
|
||||
for key in ("name", "key", "env_name", "variable"):
|
||||
item = value.get(key)
|
||||
if isinstance(item, str) and item.strip():
|
||||
return item.strip()
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def _validate_tool_node_agentic_mode(cls, *, node_id: str, node_data: Mapping[str, Any]) -> None:
|
||||
agentic_config = cls._extract_tool_agentic_config(node_data)
|
||||
|
||||
Reference in New Issue
Block a user