mirror of
https://github.com/FuzzingLabs/fuzzforge_ai.git
synced 2026-08-15 22:40:23 +02:00
feat(modules): add harness-tester module for Rust fuzzing pipeline
This commit is contained in:
@@ -14,6 +14,22 @@ if TYPE_CHECKING:
|
||||
from fastmcp import Context
|
||||
|
||||
|
||||
# Track the current active project path (set by init_project)
|
||||
_current_project_path: Path | None = None
|
||||
|
||||
|
||||
def set_current_project_path(project_path: Path) -> None:
|
||||
"""Set the current project path.
|
||||
|
||||
Called by init_project to track which project is active.
|
||||
|
||||
:param project_path: Path to the project directory.
|
||||
|
||||
"""
|
||||
global _current_project_path
|
||||
_current_project_path = project_path
|
||||
|
||||
|
||||
def get_settings() -> Settings:
|
||||
"""Get MCP server settings from context.
|
||||
|
||||
@@ -31,11 +47,17 @@ def get_settings() -> Settings:
|
||||
def get_project_path() -> Path:
|
||||
"""Get the current project path.
|
||||
|
||||
Returns the project path set by init_project, or falls back to
|
||||
the current working directory if no project has been initialized.
|
||||
|
||||
:return: Path to the current project.
|
||||
|
||||
"""
|
||||
settings: Settings = get_settings()
|
||||
return Path(settings.project.default_path)
|
||||
global _current_project_path
|
||||
if _current_project_path is not None:
|
||||
return _current_project_path
|
||||
# Fall back to current working directory (where the AI agent is working)
|
||||
return Path.cwd()
|
||||
|
||||
|
||||
def get_runner() -> Runner:
|
||||
|
||||
@@ -29,7 +29,8 @@ async def list_modules() -> dict[str, Any]:
|
||||
"""List all available FuzzForge modules.
|
||||
|
||||
Returns information about modules that can be executed,
|
||||
including their identifiers and availability status.
|
||||
including their identifiers, availability status, and metadata
|
||||
such as use cases, input requirements, and output artifacts.
|
||||
|
||||
:return: Dictionary with list of available modules and their details.
|
||||
|
||||
@@ -47,10 +48,26 @@ async def list_modules() -> dict[str, Any]:
|
||||
"identifier": module.identifier,
|
||||
"image": f"{module.identifier}:{module.version or 'latest'}",
|
||||
"available": module.available,
|
||||
"description": module.description,
|
||||
# New metadata fields from pyproject.toml
|
||||
"category": module.category,
|
||||
"language": module.language,
|
||||
"pipeline_stage": module.pipeline_stage,
|
||||
"pipeline_order": module.pipeline_order,
|
||||
"dependencies": module.dependencies,
|
||||
"continuous_mode": module.continuous_mode,
|
||||
"typical_duration": module.typical_duration,
|
||||
# AI-discoverable metadata
|
||||
"use_cases": module.use_cases,
|
||||
"input_requirements": module.input_requirements,
|
||||
"output_artifacts": module.output_artifacts,
|
||||
}
|
||||
for module in modules
|
||||
]
|
||||
|
||||
# Sort by pipeline_order if available
|
||||
available_modules.sort(key=lambda m: (m.get("pipeline_order") or 999, m["identifier"]))
|
||||
|
||||
return {
|
||||
"modules": available_modules,
|
||||
"count": len(available_modules),
|
||||
@@ -151,6 +168,8 @@ async def start_continuous_module(
|
||||
module_identifier=module_identifier,
|
||||
assets_path=actual_assets_path,
|
||||
configuration=configuration,
|
||||
project_path=project_path,
|
||||
execution_id=session_id,
|
||||
)
|
||||
|
||||
# Store execution info for tracking
|
||||
@@ -162,6 +181,7 @@ async def start_continuous_module(
|
||||
"status": "running",
|
||||
"container_id": result["container_id"],
|
||||
"input_dir": result["input_dir"],
|
||||
"project_path": str(project_path),
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Any
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.exceptions import ToolError
|
||||
|
||||
from fuzzforge_mcp.dependencies import get_project_path, get_runner
|
||||
from fuzzforge_mcp.dependencies import get_project_path, get_runner, set_current_project_path
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fuzzforge_runner import Runner
|
||||
@@ -21,8 +21,12 @@ mcp: FastMCP = FastMCP()
|
||||
async def init_project(project_path: str | None = None) -> dict[str, Any]:
|
||||
"""Initialize a new FuzzForge project.
|
||||
|
||||
Creates the necessary storage directories for a project. This should
|
||||
be called before executing modules or workflows.
|
||||
Creates a `.fuzzforge/` directory inside the project for storing:
|
||||
- assets/: Input files (source code, etc.)
|
||||
- inputs/: Prepared module inputs (for debugging)
|
||||
- runs/: Execution results from each module
|
||||
|
||||
This should be called before executing modules or workflows.
|
||||
|
||||
:param project_path: Path to the project directory. If not provided, uses current directory.
|
||||
:return: Project initialization result.
|
||||
@@ -32,13 +36,17 @@ async def init_project(project_path: str | None = None) -> dict[str, Any]:
|
||||
|
||||
try:
|
||||
path = Path(project_path) if project_path else get_project_path()
|
||||
|
||||
# Track this as the current active project
|
||||
set_current_project_path(path)
|
||||
|
||||
storage_path = runner.init_project(path)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"project_path": str(path),
|
||||
"storage_path": str(storage_path),
|
||||
"message": f"Project initialized at {path}",
|
||||
"message": f"Project initialized. Storage at {path}/.fuzzforge/",
|
||||
}
|
||||
|
||||
except Exception as exception:
|
||||
|
||||
Reference in New Issue
Block a user