agentic-threat-hunting-framework 0.4.0__py3-none-any.whl → 0.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentic_threat_hunting_framework-0.4.0.dist-info → agentic_threat_hunting_framework-0.5.1.dist-info}/METADATA +1 -1
- {agentic_threat_hunting_framework-0.4.0.dist-info → agentic_threat_hunting_framework-0.5.1.dist-info}/RECORD +12 -11
- {agentic_threat_hunting_framework-0.4.0.dist-info → agentic_threat_hunting_framework-0.5.1.dist-info}/WHEEL +1 -1
- athf/agents/base.py +6 -15
- athf/cli.py +10 -2
- athf/commands/__init__.py +6 -1
- athf/commands/similar.py +2 -2
- athf/core/web_search.py +1 -1
- athf/plugin_system.py +48 -0
- {agentic_threat_hunting_framework-0.4.0.dist-info → agentic_threat_hunting_framework-0.5.1.dist-info}/entry_points.txt +0 -0
- {agentic_threat_hunting_framework-0.4.0.dist-info → agentic_threat_hunting_framework-0.5.1.dist-info}/licenses/LICENSE +0 -0
- {agentic_threat_hunting_framework-0.4.0.dist-info → agentic_threat_hunting_framework-0.5.1.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentic-threat-hunting-framework
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Agentic Threat Hunting Framework - Memory and AI for threat hunters
|
|
5
5
|
Author-email: Sydney Marrone <athf@nebulock.io>
|
|
6
6
|
Maintainer-email: Sydney Marrone <athf@nebulock.io>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
agentic_threat_hunting_framework-0.
|
|
1
|
+
agentic_threat_hunting_framework-0.5.1.dist-info/licenses/LICENSE,sha256=_KObErRfiKoolznt-DF0nJnr3U9Rdh7Z4Ba7G5qqckk,1071
|
|
2
2
|
athf/__init__.py,sha256=OrjZe8P97_BTEkscapnwSsqKSjwXNP9d8-HtGr19Ni0,241
|
|
3
3
|
athf/__version__.py,sha256=wCIQoU9b7qKcSNQiIOgHaD2buzBC-dlQYtvg8X5WS4A,59
|
|
4
|
-
athf/cli.py,sha256=
|
|
4
|
+
athf/cli.py,sha256=108PnDRlaytJj9KzjzcTLljB3DeerMIXZOeAQJrmtPU,5052
|
|
5
|
+
athf/plugin_system.py,sha256=c_9-oUiR6tuYpWpEmeVRayU8-TXlkjvZC3EUxuYWW4M,1515
|
|
5
6
|
athf/agents/__init__.py,sha256=iaSJpvnXm9rz4QS7gBrsaLEjm49uvsMs4BLPOJeyp78,346
|
|
6
|
-
athf/agents/base.py,sha256=
|
|
7
|
+
athf/agents/base.py,sha256=ZLqSW6I0pKqs1Z3OIoV8urkysMRzNDs52yNIxDgQjTU,3981
|
|
7
8
|
athf/agents/llm/__init__.py,sha256=qSGA-NaInjsDkMpGQwnTz3S1OgCVlzetpMcDS_to1co,671
|
|
8
9
|
athf/agents/llm/hunt_researcher.py,sha256=dIyD2Izh3zdf62kCHug1DwXFgmWhOMQUTim7qM3UAIs,27071
|
|
9
10
|
athf/agents/llm/hypothesis_generator.py,sha256=XkbJz8IS4zwQjEy-ZD0zy2XW5uRnAy87Lii-5XTY0WU,8564
|
|
10
|
-
athf/commands/__init__.py,sha256
|
|
11
|
+
athf/commands/__init__.py,sha256=-ZOfg6uV1eSh7RDW7dKzdufuYvQTT0KGMF4JB6waHsY,635
|
|
11
12
|
athf/commands/agent.py,sha256=c7ZeZa3OArXyXTgVjmUB2JXa3m9IpLFJ_FEVDhaDLE8,19000
|
|
12
13
|
athf/commands/context.py,sha256=V-at81-OgKcLY-In48-AccTnHfTgdofmnjE8S5kypoI,12678
|
|
13
14
|
athf/commands/env.py,sha256=JPKRsv48cgsIAjSFaGJ1-Nu0nQKGSVg4AbiFxb9jVX4,11887
|
|
@@ -15,7 +16,7 @@ athf/commands/hunt.py,sha256=aQdgNddqy_VrxZOkxhuPxIr4KLZtX5a2ZLb9079vLlw,25169
|
|
|
15
16
|
athf/commands/init.py,sha256=Qn0iETNyuQvM-ySqCeoDz-pPemeuzROX_karQF5yN_o,12685
|
|
16
17
|
athf/commands/investigate.py,sha256=mK_id5vjfN_ukqB_-fyia0FNa0pBmtn0Xv6CKHQI1Qo,24663
|
|
17
18
|
athf/commands/research.py,sha256=FrLph4agaGQ_rIxMh0OQwh1MIGDFtj40zJ3E1ZFwaAw,18112
|
|
18
|
-
athf/commands/similar.py,sha256=
|
|
19
|
+
athf/commands/similar.py,sha256=FTTVr4zzP9bdJrirscp6pOxdQbE8zot6pa20-_TYiuo,11804
|
|
19
20
|
athf/commands/splunk.py,sha256=7n7Jl1ExqZCNxUhG0kAKgAvZMqbIoGSgx2Moq7vAu-Y,11622
|
|
20
21
|
athf/core/__init__.py,sha256=yG7C8ljx3UW4QZoYvDjUxsWHlbS8M-GLGB7Je7rRfqo,31
|
|
21
22
|
athf/core/attack_matrix.py,sha256=QZKKmxckQ6-U7lqVdGUJoj2jEAhP3Juvr3sqaNx2oTw,3238
|
|
@@ -25,7 +26,7 @@ athf/core/investigation_parser.py,sha256=wbfjnq4gFgIc0a4bHIAnidVNPhbHDpIXWY1SGLk
|
|
|
25
26
|
athf/core/research_manager.py,sha256=i4fUjuZJcAik8I4pwbLkQlu6cuxkWDlqaIRQrzAfB0s,14512
|
|
26
27
|
athf/core/splunk_client.py,sha256=Xib2zVwV2l8eChzqUahI3PZ7Z2XS2wz01sPbF1E0Q18,11611
|
|
27
28
|
athf/core/template_engine.py,sha256=Awp0n9E5Q1dYA35XDKKAd5VJLdpaDl2N967hackUVa8,6010
|
|
28
|
-
athf/core/web_search.py,sha256=
|
|
29
|
+
athf/core/web_search.py,sha256=B9IhmwH7gy2RVA6WSN3L7yGp3Q4L8OsiiwcEvnnZejU,10320
|
|
29
30
|
athf/data/__init__.py,sha256=QtgONloCaS3E9Ow995FMxyy6BbszpfmYeWpySQ2b9Mc,502
|
|
30
31
|
athf/data/docs/CHANGELOG.md,sha256=JKkzzs1n5jSERHFi6fDt6sYEe52MSaY127dfzthkUA8,8655
|
|
31
32
|
athf/data/docs/CLI_REFERENCE.md,sha256=pb76UqkY_WHJMBEXwEmK0TJR8kcGzoBPlJ0WdGMKDQM,54875
|
|
@@ -51,8 +52,8 @@ athf/data/prompts/ai-workflow.md,sha256=rZtOcGuAEi35qx7182TwHJEORdz1-RxkZMBVkg61
|
|
|
51
52
|
athf/data/prompts/basic-prompts.md,sha256=2bunpO35RoBdJWYthXVi40RNl2UWrfwOaFthBLHF5sU,8463
|
|
52
53
|
athf/data/templates/HUNT_LOCK.md,sha256=zXxHaKMWbRDLewLTegYJMbXRM72s9gFFvjdwFfGNeJE,7386
|
|
53
54
|
athf/utils/__init__.py,sha256=aEAPI1xnAsowOtc036cCb9ZOek5nrrfevu8PElhbNgk,30
|
|
54
|
-
agentic_threat_hunting_framework-0.
|
|
55
|
-
agentic_threat_hunting_framework-0.
|
|
56
|
-
agentic_threat_hunting_framework-0.
|
|
57
|
-
agentic_threat_hunting_framework-0.
|
|
58
|
-
agentic_threat_hunting_framework-0.
|
|
55
|
+
agentic_threat_hunting_framework-0.5.1.dist-info/METADATA,sha256=A9gPoTr0bXjdPo_l76Fn1tIxJFAL3RFQRRUPSDT6N8I,15949
|
|
56
|
+
agentic_threat_hunting_framework-0.5.1.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
57
|
+
agentic_threat_hunting_framework-0.5.1.dist-info/entry_points.txt,sha256=GopR2iTiBs-yNMWiUZ2DaFIFglXxWJx1XPjTa3ePtfE,39
|
|
58
|
+
agentic_threat_hunting_framework-0.5.1.dist-info/top_level.txt,sha256=Cxxg6SMLfawDJWBITsciRzq27XV8fiaAor23o9Byoes,5
|
|
59
|
+
agentic_threat_hunting_framework-0.5.1.dist-info/RECORD,,
|
athf/agents/base.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Base classes for
|
|
1
|
+
"""Base classes for ATHF agents."""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
@@ -89,6 +89,8 @@ class LLMAgent(Agent[InputT, OutputT]):
|
|
|
89
89
|
) -> None:
|
|
90
90
|
"""Log LLM call metrics to centralized tracker.
|
|
91
91
|
|
|
92
|
+
Override this method in subclasses or plugins to implement custom metrics tracking.
|
|
93
|
+
|
|
92
94
|
Args:
|
|
93
95
|
agent_name: Name of the agent (e.g., "hypothesis-generator")
|
|
94
96
|
model_id: Bedrock model ID
|
|
@@ -97,19 +99,8 @@ class LLMAgent(Agent[InputT, OutputT]):
|
|
|
97
99
|
cost_usd: Estimated cost in USD
|
|
98
100
|
duration_ms: Call duration in milliseconds
|
|
99
101
|
"""
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
MetricsTracker.get_instance().log_bedrock_call(
|
|
104
|
-
agent=agent_name,
|
|
105
|
-
model_id=model_id,
|
|
106
|
-
input_tokens=input_tokens,
|
|
107
|
-
output_tokens=output_tokens,
|
|
108
|
-
cost_usd=cost_usd,
|
|
109
|
-
duration_ms=duration_ms,
|
|
110
|
-
)
|
|
111
|
-
except Exception:
|
|
112
|
-
pass # Never fail agent execution due to metrics logging
|
|
102
|
+
# No-op by default. Override in plugins for custom metrics tracking.
|
|
103
|
+
pass
|
|
113
104
|
|
|
114
105
|
def _get_llm_client(self) -> Any:
|
|
115
106
|
"""Get AWS Bedrock runtime client for Claude models.
|
|
@@ -125,7 +116,7 @@ class LLMAgent(Agent[InputT, OutputT]):
|
|
|
125
116
|
return None
|
|
126
117
|
|
|
127
118
|
try:
|
|
128
|
-
import boto3
|
|
119
|
+
import boto3
|
|
129
120
|
|
|
130
121
|
# Get AWS region from environment or use default
|
|
131
122
|
region = os.getenv("AWS_REGION", os.getenv("AWS_DEFAULT_REGION", "us-east-1"))
|
athf/cli.py
CHANGED
|
@@ -95,8 +95,16 @@ cli.add_command(similar)
|
|
|
95
95
|
# Agent commands
|
|
96
96
|
cli.add_command(agent)
|
|
97
97
|
|
|
98
|
-
# Integration commands
|
|
99
|
-
|
|
98
|
+
# Integration commands (optional, requires additional dependencies)
|
|
99
|
+
if splunk is not None:
|
|
100
|
+
cli.add_command(splunk)
|
|
101
|
+
|
|
102
|
+
# Load and register plugins
|
|
103
|
+
from athf.plugin_system import PluginRegistry
|
|
104
|
+
|
|
105
|
+
PluginRegistry.load_plugins()
|
|
106
|
+
for name, cmd in PluginRegistry._commands.items():
|
|
107
|
+
cli.add_command(cmd, name=name)
|
|
100
108
|
|
|
101
109
|
|
|
102
110
|
@cli.command(hidden=True)
|
athf/commands/__init__.py
CHANGED
|
@@ -7,7 +7,12 @@ from athf.commands.init import init
|
|
|
7
7
|
from athf.commands.investigate import investigate
|
|
8
8
|
from athf.commands.research import research
|
|
9
9
|
from athf.commands.similar import similar
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
# Optional: Splunk integration (requires requests package)
|
|
12
|
+
try:
|
|
13
|
+
from athf.commands.splunk import splunk
|
|
14
|
+
except ImportError:
|
|
15
|
+
splunk = None # type: ignore[assignment]
|
|
11
16
|
|
|
12
17
|
__all__ = [
|
|
13
18
|
"init",
|
athf/commands/similar.py
CHANGED
|
@@ -132,8 +132,8 @@ def _find_similar_hunts(
|
|
|
132
132
|
) -> List[Dict[str, Any]]:
|
|
133
133
|
"""Find similar hunts using TF-IDF similarity."""
|
|
134
134
|
try:
|
|
135
|
-
from sklearn.feature_extraction.text import TfidfVectorizer
|
|
136
|
-
from sklearn.metrics.pairwise import cosine_similarity
|
|
135
|
+
from sklearn.feature_extraction.text import TfidfVectorizer
|
|
136
|
+
from sklearn.metrics.pairwise import cosine_similarity
|
|
137
137
|
except ImportError:
|
|
138
138
|
console.print("[red]Error: scikit-learn not installed[/red]")
|
|
139
139
|
console.print("[dim]Install with: pip install scikit-learn[/dim]")
|
athf/core/web_search.py
CHANGED
|
@@ -84,7 +84,7 @@ class TavilySearchClient:
|
|
|
84
84
|
"""Get or create Tavily client instance."""
|
|
85
85
|
if self._client is None:
|
|
86
86
|
try:
|
|
87
|
-
from tavily import TavilyClient
|
|
87
|
+
from tavily import TavilyClient
|
|
88
88
|
|
|
89
89
|
self._client = TavilyClient(api_key=self.api_key)
|
|
90
90
|
except ImportError:
|
athf/plugin_system.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Plugin system for ATHF extensions."""
|
|
2
|
+
from typing import Dict, Type, Callable
|
|
3
|
+
import importlib.metadata
|
|
4
|
+
from click import Command
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PluginRegistry:
|
|
8
|
+
"""Central registry for ATHF plugins."""
|
|
9
|
+
|
|
10
|
+
_agents: Dict[str, Type] = {}
|
|
11
|
+
_commands: Dict[str, Command] = {}
|
|
12
|
+
|
|
13
|
+
@classmethod
|
|
14
|
+
def register_agent(cls, name: str, agent_class: Type) -> None:
|
|
15
|
+
"""Register an agent plugin."""
|
|
16
|
+
cls._agents[name] = agent_class
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def register_command(cls, name: str, command: Command) -> None:
|
|
20
|
+
"""Register a CLI command plugin."""
|
|
21
|
+
cls._commands[name] = command
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def get_agent(cls, name: str) -> Type:
|
|
25
|
+
"""Get registered agent by name."""
|
|
26
|
+
return cls._agents.get(name)
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def get_command(cls, name: str) -> Command:
|
|
30
|
+
"""Get registered command by name."""
|
|
31
|
+
return cls._commands.get(name)
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def load_plugins(cls) -> None:
|
|
35
|
+
"""Auto-discover and load all installed plugins."""
|
|
36
|
+
try:
|
|
37
|
+
for ep in importlib.metadata.entry_points(group='athf.commands'):
|
|
38
|
+
command = ep.load()
|
|
39
|
+
cls.register_command(ep.name, command)
|
|
40
|
+
except Exception:
|
|
41
|
+
pass # No plugins installed yet
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
for ep in importlib.metadata.entry_points(group='athf.agents'):
|
|
45
|
+
agent = ep.load()
|
|
46
|
+
cls.register_agent(ep.name, agent)
|
|
47
|
+
except Exception:
|
|
48
|
+
pass # No plugins installed yet
|
|
File without changes
|
|
File without changes
|
|
File without changes
|