From 586bee1bfe134245db70096a7353732338918c97 Mon Sep 17 00:00:00 2001 From: Raja Sekhar Rao Dheekonda Date: Tue, 12 May 2026 20:22:44 -0700 Subject: [PATCH 1/2] fix(airt): clean minimal workspace path update - only 2 files - Update WORKFLOWS_DIR to ~/.dreadnode/airt/workflows - Update docstring references to new path - Bump version to 1.2.2 Clean implementation for ENG-6795 with minimal changes only --- capabilities/ai-red-teaming/capability.yaml | 2 +- capabilities/ai-red-teaming/tools/workflows.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/capabilities/ai-red-teaming/capability.yaml b/capabilities/ai-red-teaming/capability.yaml index 65fd2ef..60eef21 100644 --- a/capabilities/ai-red-teaming/capability.yaml +++ b/capabilities/ai-red-teaming/capability.yaml @@ -1,6 +1,6 @@ schema: 1 name: ai-red-teaming -version: "1.2.1" +version: "1.2.2" description: > Probe the security and safety of AI applications, agents, and foundation models. Orchestrates adversarial attack workflows to discover vulnerabilities in LLMs, diff --git a/capabilities/ai-red-teaming/tools/workflows.py b/capabilities/ai-red-teaming/tools/workflows.py index b1061bf..100f48c 100644 --- a/capabilities/ai-red-teaming/tools/workflows.py +++ b/capabilities/ai-red-teaming/tools/workflows.py @@ -20,7 +20,7 @@ WORKFLOWS_DIR = Path( os.environ.get( "AIRT_WORKFLOWS_DIR", - str(Path.home() / "workspace" / "airt" / "workflows"), + str(Path.home() / ".dreadnode" / "airt" / "workflows"), ) ) METADATA_FILE = WORKFLOWS_DIR / ".workflow_metadata.json" @@ -48,7 +48,7 @@ def save_workflow( ) -> str: """Save a Python attack workflow with syntax validation. - Validates the code compiles, saves to ~/workspace/airt/workflows/, + Validates the code compiles, saves to ~/.dreadnode/airt/workflows/, and records metadata. Use execute_workflow to run saved workflows. """ if "/" in filename or "\\" in filename or ".." in filename: @@ -81,7 +81,7 @@ def save_workflow( def list_workflows() -> str: """List saved attack workflows with metadata. - Shows all Python scripts in ~/workspace/airt/workflows/ with + Shows all Python scripts in ~/.dreadnode/airt/workflows/ with descriptions, sizes, and save timestamps. """ if not WORKFLOWS_DIR.exists(): From 5d64b404b2a07d5a5d395f59a0e70d3bcd92e378 Mon Sep 17 00:00:00 2001 From: Raja Sekhar Rao Dheekonda Date: Tue, 12 May 2026 20:29:21 -0700 Subject: [PATCH 2/2] feat(airt): implement proper org/workspace structure with UserConfig - Add _get_workspace_path() function that reads from active profile - Support ~/.dreadnode/airt/[org]/[workspace]/workflows/ structure - Falls back to 'default'/'main' when profile unavailable - Maintains AIRT_WORKFLOWS_DIR override for flexibility - Updates docstrings to reflect proper org/workspace paths Implements best practice organization structure as originally requested --- .../ai-red-teaming/tools/workflows.py | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/capabilities/ai-red-teaming/tools/workflows.py b/capabilities/ai-red-teaming/tools/workflows.py index 100f48c..e84d6d8 100644 --- a/capabilities/ai-red-teaming/tools/workflows.py +++ b/capabilities/ai-red-teaming/tools/workflows.py @@ -17,12 +17,27 @@ from dreadnode.agents.tools import tool from dreadnode.app.env import resolve_python_executable -WORKFLOWS_DIR = Path( - os.environ.get( - "AIRT_WORKFLOWS_DIR", - str(Path.home() / ".dreadnode" / "airt" / "workflows"), - ) -) +# Get org/workspace from active profile, with fallbacks +def _get_workspace_path() -> Path: + try: + from dreadnode.app.config import UserConfig + config = UserConfig.read() + profile_data = config.active_profile + if profile_data: + _, profile = profile_data + org_key = profile.organization or "default" + workspace_key = profile.workspace or "main" + else: + org_key = "default" + workspace_key = "main" + except Exception: + # Fallback if config system unavailable + org_key = "default" + workspace_key = "main" + + return Path.home() / ".dreadnode" / "airt" / org_key / workspace_key / "workflows" + +WORKFLOWS_DIR = Path(os.environ.get("AIRT_WORKFLOWS_DIR")) if os.environ.get("AIRT_WORKFLOWS_DIR") else _get_workspace_path() METADATA_FILE = WORKFLOWS_DIR / ".workflow_metadata.json" @@ -48,7 +63,7 @@ def save_workflow( ) -> str: """Save a Python attack workflow with syntax validation. - Validates the code compiles, saves to ~/.dreadnode/airt/workflows/, + Validates the code compiles, saves to ~/.dreadnode/airt/[org]/[workspace]/workflows/, and records metadata. Use execute_workflow to run saved workflows. """ if "/" in filename or "\\" in filename or ".." in filename: @@ -81,7 +96,7 @@ def save_workflow( def list_workflows() -> str: """List saved attack workflows with metadata. - Shows all Python scripts in ~/.dreadnode/airt/workflows/ with + Shows all Python scripts in ~/.dreadnode/airt/[org]/[workspace]/workflows/ with descriptions, sizes, and save timestamps. """ if not WORKFLOWS_DIR.exists():