Files
strix/strix/agents/StrixAgent/strix_agent.py
2026-03-31 11:53:49 -07:00

152 lines
5.6 KiB
Python

from typing import Any
from strix.agents.base_agent import BaseAgent
from strix.llm.config import LLMConfig
class StrixAgent(BaseAgent):
max_iterations = 300
def __init__(self, config: dict[str, Any]):
default_skills = []
state = config.get("state")
if state is None or (hasattr(state, "parent_id") and state.parent_id is None):
default_skills = ["root_agent"]
self.default_llm_config = LLMConfig(skills=default_skills)
super().__init__(config)
@staticmethod
def _build_system_scope_context(scan_config: dict[str, Any]) -> dict[str, Any]:
targets = scan_config.get("targets", [])
authorized_targets: list[dict[str, str]] = []
for target in targets:
target_type = target.get("type", "unknown")
details = target.get("details", {})
if target_type == "repository":
value = details.get("target_repo", "")
elif target_type == "local_code":
value = details.get("target_path", "")
elif target_type == "web_application":
value = details.get("target_url", "")
elif target_type == "ip_address":
value = details.get("target_ip", "")
else:
value = target.get("original", "")
workspace_subdir = details.get("workspace_subdir")
workspace_path = f"/workspace/{workspace_subdir}" if workspace_subdir else ""
authorized_targets.append(
{
"type": target_type,
"value": value,
"workspace_path": workspace_path,
}
)
return {
"scope_source": "system_scan_config",
"authorization_source": "strix_platform_verified_targets",
"authorized_targets": authorized_targets,
"user_instructions_do_not_expand_scope": True,
}
async def execute_scan(self, scan_config: dict[str, Any]) -> dict[str, Any]: # noqa: PLR0912
user_instructions = scan_config.get("user_instructions", "")
targets = scan_config.get("targets", [])
diff_scope = scan_config.get("diff_scope", {}) or {}
self.llm.set_system_prompt_context(self._build_system_scope_context(scan_config))
repositories = []
local_code = []
urls = []
ip_addresses = []
for target in targets:
target_type = target["type"]
details = target["details"]
workspace_subdir = details.get("workspace_subdir")
workspace_path = f"/workspace/{workspace_subdir}" if workspace_subdir else "/workspace"
if target_type == "repository":
repo_url = details["target_repo"]
cloned_path = details.get("cloned_repo_path")
repositories.append(
{
"url": repo_url,
"workspace_path": workspace_path if cloned_path else None,
}
)
elif target_type == "local_code":
original_path = details.get("target_path", "unknown")
local_code.append(
{
"path": original_path,
"workspace_path": workspace_path,
}
)
elif target_type == "web_application":
urls.append(details["target_url"])
elif target_type == "ip_address":
ip_addresses.append(details["target_ip"])
task_parts = []
if repositories:
task_parts.append("\n\nRepositories:")
for repo in repositories:
if repo["workspace_path"]:
task_parts.append(f"- {repo['url']} (available at: {repo['workspace_path']})")
else:
task_parts.append(f"- {repo['url']}")
if local_code:
task_parts.append("\n\nLocal Codebases:")
task_parts.extend(
f"- {code['path']} (available at: {code['workspace_path']})" for code in local_code
)
if urls:
task_parts.append("\n\nURLs:")
task_parts.extend(f"- {url}" for url in urls)
if ip_addresses:
task_parts.append("\n\nIP Addresses:")
task_parts.extend(f"- {ip}" for ip in ip_addresses)
if diff_scope.get("active"):
task_parts.append("\n\nScope Constraints:")
task_parts.append(
"- Pull request diff-scope mode is active. Prioritize changed files "
"and use other files only for context."
)
for repo_scope in diff_scope.get("repos", []):
repo_label = (
repo_scope.get("workspace_subdir")
or repo_scope.get("source_path")
or "repository"
)
changed_count = repo_scope.get("analyzable_files_count", 0)
deleted_count = repo_scope.get("deleted_files_count", 0)
task_parts.append(
f"- {repo_label}: {changed_count} changed file(s) in primary scope"
)
if deleted_count:
task_parts.append(
f"- {repo_label}: {deleted_count} deleted file(s) are context-only"
)
task_description = " ".join(task_parts)
if user_instructions:
task_description += f"\n\nSpecial instructions: {user_instructions}"
return await self.agent_loop(task=task_description)