Skip to content

Commit 9e835ab

Browse files
committed
move openapi parsing into utils
1 parent 3ee9c9e commit 9e835ab

File tree

8 files changed

+34
-61
lines changed

8 files changed

+34
-61
lines changed

src/hackingBuddyGPT/usecases/web_api_testing/simple_openapi_documentation.py

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import os
22
from dataclasses import field
3-
from typing import Dict
43

54
from rich.panel import Panel
65

7-
from hackingBuddyGPT.capabilities import Capability
86
from hackingBuddyGPT.capabilities.http_request import HTTPRequest
97
from hackingBuddyGPT.capabilities.record_note import RecordNote
10-
from hackingBuddyGPT.usecases.agents import Agent
11-
from hackingBuddyGPT.usecases.base import AutonomousAgentUseCase, use_case
8+
from hackingBuddyGPT.usecases.base import AutonomousUseCase, use_case
129
from hackingBuddyGPT.usecases.web_api_testing.documentation.openapi_specification_handler import \
1310
OpenAPISpecificationHandler
11+
from hackingBuddyGPT.utils.capability_manager import CapabilityManager
1412
from hackingBuddyGPT.utils.prompt_generation import PromptGenerationHelper
1513
from hackingBuddyGPT.utils.prompt_generation.information import PromptContext
1614
from hackingBuddyGPT.utils.prompt_generation.prompt_engineer import PromptEngineer
@@ -23,7 +21,8 @@
2321
from hackingBuddyGPT.utils.openai.openai_lib import OpenAILib
2422

2523

26-
class SimpleWebAPIDocumentation(Agent):
24+
@use_case("Minimal implementation of a web API testing use case")
25+
class SimpleWebAPIDocumentation(AutonomousUseCase):
2726
"""
2827
SimpleWebAPIDocumentation is an agent class for automating REST API documentation.
2928
@@ -41,10 +40,10 @@ class SimpleWebAPIDocumentation(Agent):
4140
found_all_http_methods (bool): Flag indicating whether all HTTP methods have been found.
4241
all_steps_done (bool): Flag to indicate whether the full documentation process is complete.
4342
"""
44-
llm: OpenAILib
43+
llm: OpenAILib = None
4544
_prompt_history: Prompt = field(default_factory=list)
4645
_context: Context = field(default_factory=lambda: {"notes": list()})
47-
_capabilities: Dict[str, Capability] = field(default_factory=dict)
46+
_capabilities: CapabilityManager = None
4847
_all_http_methods_found: bool = False
4948
config_path: str = parameter(
5049
desc="Configuration file path",
@@ -75,6 +74,8 @@ class SimpleWebAPIDocumentation(Agent):
7574
default="GET,POST,PUT,PATCH,DELETE",
7675
)
7776

77+
def get_name(self) -> str:
78+
return self.__class__.__name__
7879

7980
def init(self):
8081
"""Initialize the agent with configurations, capabilities, and handlers."""
@@ -90,7 +91,11 @@ def init(self):
9091

9192
self.categorized_endpoints = self.categorize_endpoints(self._correct_endpoints, query_params)
9293

93-
self._setup_capabilities()
94+
# setup capabilities
95+
self._capabilities.init()
96+
self._capabilities.add_capability(HTTPRequest(self.host))
97+
self._capabilities.add_capability(RecordNote(self._context["notes"]))
98+
9499
self._prompt_context = PromptContext.DOCUMENTATION
95100
name, initial_prompt = self._setup_initial_prompt(description=description)
96101
self._initialize_handlers(config=config, description=description, token=token, name=name,
@@ -150,7 +155,7 @@ def _initialize_handlers(self, config, description, token, name, initial_prompt)
150155
"""
151156
self.all_capabilities = {
152157
"http_request": HTTPRequest(self.host)}
153-
self._llm_handler = LLMHandler(self.llm, self._capabilities, all_possible_capabilities=self.all_capabilities)
158+
self._llm_handler = LLMHandler(self.llm, self._capabilities._capabilities, all_possible_capabilities=self.all_capabilities)
154159

155160
self._response_handler = ResponseHandler(llm_handler=self._llm_handler, prompt_context=self._prompt_context,
156161
prompt_helper=self.prompt_helper, config=config)
@@ -226,25 +231,6 @@ def categorize_endpoints(self, endpoints, query: dict):
226231
"multi-level_resource": multi_level_resource,
227232
}
228233

229-
230-
231-
def _setup_capabilities(self):
232-
"""
233-
Initializes the LLM agent's capabilities for interacting with the API.
234-
235-
This sets up tool wrappers that the language model can call, such as:
236-
- `http_request`: For performing HTTP calls against the target API.
237-
- `record_note`: For storing observations, notes, or documentation artifacts.
238-
239-
Side Effects:
240-
- Populates `self._capabilities` with callable tools used during exploration and documentation.
241-
"""
242-
"""Initializes agent's capabilities for API documentation."""
243-
self._capabilities = {
244-
"http_request": HTTPRequest(self.host),
245-
"record_note": RecordNote(self._context["notes"])
246-
}
247-
248234
def all_http_methods_found(self, turn: int) -> bool:
249235
"""
250236
Checks whether all expected HTTP methods (GET, POST, PUT, DELETE) have been discovered
@@ -441,10 +427,4 @@ def run_documentation(self, turn: int, move_type: str) -> None:
441427
self._evaluator.finalize_documentation_metrics(
442428
file_path=self._documentation_handler.file.split(".yaml")[0] + ".txt")
443429

444-
self.all_http_methods_found(turn)
445-
446-
447-
@use_case("Minimal implementation of a web API testing use case")
448-
class SimpleWebAPIDocumentationUseCase(AutonomousAgentUseCase[SimpleWebAPIDocumentation]):
449-
"""Use case for the SimpleWebAPIDocumentation agent."""
450-
pass
430+
self.all_http_methods_found(turn)

src/hackingBuddyGPT/usecases/web_api_testing/simple_web_api_testing.py

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@
88
import pydantic_core
99
from rich.panel import Panel
1010

11-
from hackingBuddyGPT.capabilities import Capability
1211
from hackingBuddyGPT.capabilities.http_request import HTTPRequest
1312
from hackingBuddyGPT.capabilities.parsed_information import ParsedInformation
1413
from hackingBuddyGPT.capabilities.python_test_case import PythonTestCase
1514
from hackingBuddyGPT.capabilities.record_note import RecordNote
16-
from hackingBuddyGPT.usecases.agents import Agent
17-
from hackingBuddyGPT.usecases.base import AutonomousAgentUseCase, use_case
15+
from hackingBuddyGPT.usecases.base import AutonomousUseCase, use_case
16+
from hackingBuddyGPT.utils.capability_manager import CapabilityManager
1817
from hackingBuddyGPT.utils.prompt_generation import PromptGenerationHelper
1918
from hackingBuddyGPT.utils.prompt_generation.information import PenTestingInformation
2019
from hackingBuddyGPT.utils.prompt_generation.information import PromptPurpose
21-
from hackingBuddyGPT.usecases.web_api_testing.documentation.parsing import OpenAPISpecificationParser
20+
from hackingBuddyGPT.utils.openapi.openapi_parser import OpenAPISpecificationParser
2221
from hackingBuddyGPT.usecases.web_api_testing.documentation.report_handler import ReportHandler
2322
from hackingBuddyGPT.utils.prompt_generation.information import PromptContext
2423
from hackingBuddyGPT.utils.prompt_generation.prompt_engineer import PromptEngineer
@@ -36,8 +35,8 @@
3635

3736
# OpenAPI specification file path
3837

39-
40-
class SimpleWebAPITesting(Agent):
38+
@use_case("Minimal implementation of a web API testing use case")
39+
class SimpleWebAPITesting(AutonomousUseCase):
4140
"""
4241
SimpleWebAPITesting is an agent class for automating web API testing.
4342
@@ -53,7 +52,7 @@ class SimpleWebAPITesting(Agent):
5352
_all_test_cases_run (bool): Flag indicating if all HTTP methods have been found.
5453
"""
5554

56-
llm: OpenAILib
55+
llm: OpenAILib = None
5756
host: str = parameter(desc="The host to test", default="https://jsonplaceholder.typicode.com")
5857
config_path: str = parameter(
5958
desc="Configuration file path",
@@ -71,7 +70,7 @@ class SimpleWebAPITesting(Agent):
7170
)
7271
_prompt_history: Prompt = field(default_factory=list)
7372
_context: Context = field(default_factory=lambda: {"notes": list(), "test_cases": list(), "parsed": list()})
74-
_capabilities: Dict[str, Capability] = field(default_factory=dict)
73+
_capabilities: CapabilityManager = None
7574
_all_test_cases_run: bool = False
7675

7776
def init(self):
@@ -86,6 +85,9 @@ def init(self):
8685
self._setup_initial_prompt()
8786
self.last_prompt = ""
8887

88+
def get_name(self) -> str:
89+
return self.__class__.__name__
90+
8991
def _load_openapi_specification(self):
9092
"""
9193
Loads the OpenAPI specification from the configured file path.
@@ -108,6 +110,11 @@ def _setup_environment(self):
108110
- Setting the prompt context to `PromptContext.PENTESTING`.
109111
"""
110112
self._context["host"] = self.host
113+
114+
# setup capabilities
115+
self._capabilities = CapabilityManager(self.log)
116+
self._capabilities.add_capability(HTTPRequest(self.host))
117+
111118
self._setup_capabilities()
112119
self.categorized_endpoints = self._openapi_specification_parser.categorize_endpoints(self.correct_endpoints,
113120
self.query_params)
@@ -128,7 +135,7 @@ def _setup_handlers(self):
128135
129136
If username and password are not found in the config, defaults are used.
130137
"""
131-
self._llm_handler = LLMHandler(self.llm, self._capabilities, all_possible_capabilities=self.all_capabilities)
138+
self._llm_handler = LLMHandler(self.llm, self._capabilities._capabilities, all_possible_capabilities=self.all_capabilities)
132139
self.prompt_helper = PromptGenerationHelper(self.host, self.description)
133140
if "username" in self.config.keys() and "password" in self.config.keys():
134141
username = self.config.get("username")
@@ -194,8 +201,6 @@ def _setup_capabilities(self) -> None:
194201
test_cases = self._context["test_cases"]
195202
self.python_test_case_capability = {"python_test_case": PythonTestCase(test_cases)}
196203
self.parse_capacity = {"parse": ParsedInformation(test_cases)}
197-
self._capabilities = {
198-
"http_request": HTTPRequest(self.host)}
199204
self.all_capabilities = {"python_test_case": PythonTestCase(test_cases), "parse": ParsedInformation(test_cases),
200205
"http_request": HTTPRequest(self.host),
201206
"record_note": RecordNote(notes)}
@@ -539,14 +544,4 @@ def execute_response(self, response, completion):
539544
self._prompt_history.append(tool_message(self._response_handler.extract_key_elements_of_response(result), tool_call_id))
540545

541546
self.adjust_user(result)
542-
return result
543-
544-
545-
@use_case("Minimal implementation of a web API testing use case")
546-
class SimpleWebAPITestingUseCase(AutonomousAgentUseCase[SimpleWebAPITesting]):
547-
"""
548-
A use case for the SimpleWebAPITesting agent, encapsulating the setup and execution
549-
of the web API testing scenario.
550-
"""
551-
552-
pass
547+
return result

src/hackingBuddyGPT/usecases/web_api_testing/utils/endpoint_categorizer.py

Whitespace-only changes.
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ def run(self, recorded_note: str) -> None:
3636
The current implementation is commented out and serves as a placeholder for
3737
integrating with OpenAI's API. Uncomment and modify the code as needed.
3838
"""
39-
"""
4039
assistant = self.client.beta.assistants.create(
4140
name="Yaml File Analysis Assistant",
4241
instructions="You are an OpenAPI specification analyst. Use your knowledge to check "
@@ -86,5 +85,4 @@ def run(self, recorded_note: str) -> None:
8685
)
8786

8887
# The thread now has a vector store with that file in its tool resources.
89-
print(thread.tool_resources.file_search)
90-
"""
88+
print(thread.tool_resources.file_search)

src/hackingBuddyGPT/utils/prompt_generation/information/pentesting_information.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import pandas
1111

12-
from hackingBuddyGPT.usecases.web_api_testing.documentation.parsing import OpenAPISpecificationParser
12+
from hackingBuddyGPT.utils.openapi.openapi_parser import OpenAPISpecificationParser
1313
from hackingBuddyGPT.utils.prompt_generation.information.prompt_information import (
1414
PromptPurpose,
1515
)

0 commit comments

Comments
 (0)