lightman_ai 0.20.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.

Potentially problematic release.


This version of lightman_ai might be problematic. Click here for more details.

@@ -0,0 +1,89 @@
1
+ import logging
2
+ import os
3
+ from typing import Any, Self
4
+
5
+ import httpx
6
+ import stamina
7
+ from lightman_ai.integrations.service_desk.constants import (
8
+ SERVICE_DESK_RETRY_ATTEMPTS,
9
+ SERVICE_DESK_RETRY_ON,
10
+ SERVICE_DESK_RETRY_TIMEOUT,
11
+ )
12
+ from lightman_ai.integrations.service_desk.exceptions import (
13
+ MissingIssueIDError,
14
+ handle_service_desk_exceptions,
15
+ )
16
+
17
+ logger = logging.getLogger("lightman")
18
+
19
+
20
+ class ServiceDeskIntegration:
21
+ """
22
+ Service Desk integration using httpx to create tickets.
23
+
24
+ Provides a simple interface to create Service Desk issues with proper
25
+ authentication and error handling.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ base_url: str,
31
+ username: str,
32
+ api_token: str,
33
+ verify_ssl: bool = True,
34
+ timeout: float = 30.0,
35
+ ) -> None:
36
+ self.base_url = base_url.rstrip("/")
37
+ self.username = username
38
+ self.api_token = api_token
39
+ self.client = httpx.AsyncClient(
40
+ base_url=self.base_url,
41
+ auth=(username, api_token),
42
+ headers={
43
+ "Content-Type": "application/json",
44
+ "Accept": "application/json",
45
+ },
46
+ verify=verify_ssl,
47
+ timeout=timeout,
48
+ )
49
+
50
+ @classmethod
51
+ def from_env(cls) -> Self:
52
+ required_vars = ["SERVICE_DESK_URL", "SERVICE_DESK_USER", "SERVICE_DESK_TOKEN"]
53
+ missing = [var for var in required_vars if not os.environ.get(var)]
54
+ if missing:
55
+ raise ValueError(f"Missing required environment variable(s): {', '.join(missing)}")
56
+ return cls(
57
+ base_url=os.environ["SERVICE_DESK_URL"],
58
+ username=os.environ["SERVICE_DESK_USER"],
59
+ api_token=os.environ["SERVICE_DESK_TOKEN"],
60
+ )
61
+
62
+ async def create_request_of_type(
63
+ self,
64
+ *,
65
+ project_key: str,
66
+ summary: str,
67
+ description: str,
68
+ request_id_type: str,
69
+ ) -> str:
70
+ payload: dict[str, Any] = {
71
+ "serviceDeskId": project_key,
72
+ "requestTypeId": request_id_type,
73
+ "requestFieldValues": {"summary": summary, "description": description},
74
+ }
75
+ for attempt in stamina.retry_context(
76
+ on=SERVICE_DESK_RETRY_ON,
77
+ attempts=SERVICE_DESK_RETRY_ATTEMPTS,
78
+ timeout=SERVICE_DESK_RETRY_TIMEOUT,
79
+ ):
80
+ with attempt:
81
+ async with handle_service_desk_exceptions():
82
+ response = await self.client.post("/rest/servicedeskapi/request", json=payload)
83
+ response.raise_for_status()
84
+ data = response.json()
85
+ issue_id = data.get("issueId")
86
+ if not issue_id:
87
+ raise MissingIssueIDError()
88
+ logger.info("Successfully created Service Desk issue: %s", issue_id)
89
+ return str(issue_id)
lightman_ai/main.py ADDED
@@ -0,0 +1,95 @@
1
+ import asyncio
2
+ import logging
3
+
4
+ from lightman_ai.ai.base.agent import BaseAgent
5
+ from lightman_ai.ai.utils import get_agent_class_from_agent_name
6
+ from lightman_ai.article.models import ArticlesList, SelectedArticle, SelectedArticlesList
7
+ from lightman_ai.integrations.service_desk.integration import (
8
+ ServiceDeskIntegration,
9
+ )
10
+ from lightman_ai.sources.the_hacker_news import TheHackerNewsSource
11
+
12
+ logger = logging.getLogger("lightman")
13
+
14
+
15
+ def _get_articles() -> ArticlesList:
16
+ return TheHackerNewsSource().get_articles()
17
+
18
+
19
+ def _classify_articles(articles: ArticlesList, agent: BaseAgent) -> SelectedArticlesList:
20
+ return agent.get_prompt_result(prompt=str(articles))
21
+
22
+
23
+ def _create_service_desk_issues(
24
+ selected_articles: list[SelectedArticle],
25
+ service_desk_client: ServiceDeskIntegration,
26
+ project_key: str,
27
+ request_id_type: str,
28
+ ) -> None:
29
+ async def schedule_task(article: SelectedArticle) -> None:
30
+ try:
31
+ description = f"*Why is relevant:*\n{article.why_is_relevant}\n\n*Source:* {article.link}\n\n*Score:* {article.relevance_score}/10"
32
+ await service_desk_client.create_request_of_type(
33
+ project_key=project_key,
34
+ summary=article.title,
35
+ description=description,
36
+ request_id_type=request_id_type,
37
+ )
38
+ logger.info("Created issue for article %s", article.link)
39
+ except Exception:
40
+ logger.exception("Could not create ServiceDesk issue: %s, %s", article.title, article.link)
41
+ raise
42
+
43
+ async def create_all() -> None:
44
+ tasks = []
45
+ for article in selected_articles:
46
+ tasks.append(schedule_task(article))
47
+ results = await asyncio.gather(*tasks, return_exceptions=True)
48
+ errors = [result for result in results if isinstance(result, Exception)]
49
+ if errors:
50
+ raise ExceptionGroup("Could not create all ServiceDesk issues", errors)
51
+
52
+ asyncio.run(create_all())
53
+
54
+
55
+ def lightman(
56
+ agent: str,
57
+ prompt: str,
58
+ score_threshold: int,
59
+ project_key: str | None = None,
60
+ request_id_type: str | None = None,
61
+ dry_run: bool = False,
62
+ model: str | None = None,
63
+ ) -> list[SelectedArticle]:
64
+ articles: ArticlesList = _get_articles()
65
+
66
+ agent_class = get_agent_class_from_agent_name(agent)
67
+ agent_instance = agent_class(prompt, model, logger=logger)
68
+ logger.info("Selected %s.", agent_instance)
69
+
70
+ classified_articles = _classify_articles(
71
+ articles=articles,
72
+ agent=agent_instance,
73
+ )
74
+
75
+ selected_articles: list[SelectedArticle] = classified_articles.get_articles_with_score_gte_threshold(
76
+ score_threshold
77
+ )
78
+ if selected_articles:
79
+ logger.info("Found these articles: %s", selected_articles)
80
+ else:
81
+ logger.info("No articles found to be relevant. Total returned articles by AI %s", len(classified_articles))
82
+
83
+ if not dry_run:
84
+ if not project_key or not request_id_type:
85
+ raise ValueError("Missing Service Desk's project key or request id type")
86
+
87
+ service_desk_client = ServiceDeskIntegration.from_env()
88
+ _create_service_desk_issues(
89
+ selected_articles=selected_articles,
90
+ service_desk_client=service_desk_client,
91
+ project_key=project_key,
92
+ request_id_type=request_id_type,
93
+ )
94
+
95
+ return selected_articles
lightman_ai/py.typed ADDED
File without changes
@@ -0,0 +1,8 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from lightman_ai.article.models import ArticlesList
4
+
5
+
6
+ class BaseSource(ABC):
7
+ @abstractmethod
8
+ def get_articles(self) -> ArticlesList: ...
@@ -0,0 +1,57 @@
1
+ from typing import override
2
+ from xml.etree import ElementTree
3
+
4
+ import httpx
5
+ import stamina
6
+ from httpx import Client
7
+ from lightman_ai.article.models import Article, ArticlesList
8
+ from lightman_ai.sources.base import BaseSource
9
+
10
+ _RETRY_ON = httpx.TransportError
11
+ _ATTEMPTS = 5
12
+ _TIMEOUT = 5
13
+
14
+
15
+ THN_URL = "https://feeds.feedburner.com/TheHackersNews"
16
+
17
+
18
+ class TheHackerNewsSource(BaseSource):
19
+ @override
20
+ def get_articles(self) -> ArticlesList:
21
+ """Return the articles that are present in THN feed."""
22
+ feed = self.get_feed()
23
+ articles = self._xml_to_list_of_articles(feed)
24
+ return ArticlesList(articles=articles)
25
+
26
+ def get_feed(self) -> str:
27
+ """Retrieve the TheHackerNews' RSS Feed."""
28
+ for attempt in stamina.retry_context(
29
+ on=_RETRY_ON,
30
+ attempts=_ATTEMPTS,
31
+ timeout=_TIMEOUT,
32
+ ):
33
+ with Client() as http_client, attempt:
34
+ hacker_news_feed = http_client.get(THN_URL)
35
+ hacker_news_feed.raise_for_status()
36
+ return hacker_news_feed.text
37
+
38
+ def _xml_to_list_of_articles(self, xml: str) -> list[Article]:
39
+ root = ElementTree.fromstring(xml)
40
+ channel = root.find("channel")
41
+ assert channel
42
+ items = channel.findall("item")
43
+
44
+ parsed = []
45
+
46
+ for item in items:
47
+ title = item.findtext("title", default="").strip()
48
+ description = self._clean(item.findtext("description", default="").strip())
49
+ link = item.findtext("link", default="").strip()
50
+
51
+ parsed.append(Article(title=title, description=description, link=link))
52
+ return parsed
53
+
54
+ @staticmethod
55
+ def _clean(text: str) -> str:
56
+ """Remove non-useful characters."""
57
+ return text.replace("\\n", "").replace(" ", "")
@@ -0,0 +1,394 @@
1
+ Metadata-Version: 2.4
2
+ Name: lightman_ai
3
+ Version: 0.20.1
4
+ Summary: Cybersecurity news aggregator.
5
+ Author-email: sdn4z <imsdn4z@gmail.com>
6
+ License-File: LICENSE
7
+ Requires-Python: <4,>=3.13
8
+ Requires-Dist: click<9.0.0,>=8.1.7
9
+ Requires-Dist: httpx<1.0.0,>=0.28.0
10
+ Requires-Dist: logfire>=3.25.0
11
+ Requires-Dist: pydantic-ai-slim[google,openai]>=0.4.4
12
+ Requires-Dist: pydantic-settings[dotenv]<3.0.0,>=2.9.1
13
+ Requires-Dist: python-dotenv<2.0.0,>=1.1.1
14
+ Requires-Dist: sentry-sdk<3.0.0,>=2.21.0
15
+ Requires-Dist: stamina<26.0.0,>=25.1.0
16
+ Requires-Dist: tiktoken<1.0.0,>=0.9.0
17
+ Requires-Dist: tomlkit<1.0.0,>=0.13.3
18
+ Provides-Extra: lint
19
+ Requires-Dist: mypy<2.0.0,>=1.1.1; extra == 'lint'
20
+ Requires-Dist: ruff<1.0.0,>=0.11.0; extra == 'lint'
21
+ Provides-Extra: local
22
+ Requires-Dist: codespell<3.0.0,>=2.2.4; extra == 'local'
23
+ Requires-Dist: commitizen<5.0.0,>=4.8.3; extra == 'local'
24
+ Requires-Dist: ipdb<1.0.0,>=0.13.13; extra == 'local'
25
+ Requires-Dist: pdbpp<1.0.0,>=0.11.6; extra == 'local'
26
+ Requires-Dist: pre-commit<4.0.0,>=3.2.2; extra == 'local'
27
+ Provides-Extra: test
28
+ Requires-Dist: pytest-asyncio<1.0.0,>=0.26.0; extra == 'test'
29
+ Requires-Dist: pytest-cov<6.0.0,>=5.0.0; extra == 'test'
30
+ Requires-Dist: pytest<9.0.0,>=8.0.0; extra == 'test'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # 🔍 Lightman AI
34
+
35
+ > **AI-Powered Cybersecurity News Intelligence Platform*
36
+
37
+ ---
38
+
39
+ Lightman AI is an intelligent cybersecurity news aggregation and risk assessment platform that helps organizations stay ahead of potential security threats. By leveraging advanced AI agents, it automatically monitors cybersecurity news sources, analyzes content for relevance, and integrates with service desk systems for streamlined threat intelligence workflows.
40
+
41
+ ## ✨ Key Features
42
+
43
+ - 🤖 **AI-Powered Classification**: Uses OpenAI GPT and Google Gemini models to intelligently classify cybersecurity news
44
+ - 📰 **Automated News Aggregation**: Monitors multiple cybersecurity news sources (TheHackerNews for now)
45
+ - 🎯 **Risk Scoring**: Configurable relevance scoring to filter noise and focus on critical threats
46
+ - 🔗 **Service Desk Integration**: Automatically creates tickets for identified security risks
47
+ - 📊 **Evaluation Framework**: Built-in tools to test and optimize AI agent performance
48
+ - ⚙️ **Flexible Configuration**: TOML-based configuration with multiple prompt templates
49
+ - 🚀 **CLI Interface**: Simple command-line interface for automation and scripting
50
+
51
+
52
+ ## 📖 Table of Contents
53
+
54
+ - [Quick Start](#-quick-start)
55
+ - [Installation](#-installation)
56
+ - [Configuration](#-configuration)
57
+ - [Usage](#-usage)
58
+ - [AI Agents & Models](#-ai-agents--models)
59
+ - [Evaluation & Testing](#-evaluation--testing)
60
+ - [Development](#-development)
61
+ - [Contributing](#-contributing)
62
+ - [License](#license)
63
+
64
+ ## 🚀 Quick Start
65
+
66
+ ### pip
67
+
68
+ 1. **Install Lightman AI**:
69
+ ```bash
70
+ pip install lightman_ai
71
+ ```
72
+
73
+ 2. **Configure your AI agent** (OpenAI or Gemini):
74
+ ```bash
75
+ export OPENAI_API_KEY="your-api-key"
76
+ # or
77
+ export GOOGLE_API_KEY="your-api-key"
78
+ ```
79
+
80
+ or store you API KEYs in a .env file
81
+ ```bash
82
+ OPENAI_API_KEY="your-api-key"
83
+ # or
84
+ GOOGLE_API_KEY="your-api-key"
85
+ ```
86
+
87
+ 3. **Run the scanner**:
88
+ ```bash
89
+ lightman run --agent openai --score 7
90
+ ```
91
+ or let it pick up the default values from your `lightman.toml` file
92
+ ```bash
93
+ lightman run
94
+ ```
95
+
96
+ ### Docker
97
+
98
+ 1. **Create configuration file**:
99
+ ```bash
100
+ echo '[default]
101
+ agent = "openai"
102
+ score_threshold = 8
103
+ prompt = "development"
104
+
105
+ [prompts]
106
+ development = "Analyze cybersecurity news for relevance to our organization."' > lightman.toml
107
+ ```
108
+
109
+ 2. **Run with Docker**:
110
+ ```bash
111
+ docker run --rm \
112
+ -v $(pwd)/lightman.toml:/app/lightman.toml \
113
+ -e OPENAI_API_KEY="your-api-key" \
114
+ elementsinteractive/lightman-ai:latest \
115
+ lightman run --config-file /app/lightman.toml --score 7
116
+ ```
117
+
118
+ 4. **View results**: Lightman will analyze cybersecurity news and output relevant articles that meet your score threshold.
119
+
120
+ ## 📥 Installation
121
+
122
+ ### Docker
123
+ Lightman AI has an available Docker image on Docker Hub:
124
+
125
+ ```bash
126
+ # Pull the latest image
127
+ docker pull elementsinteractive/lightman-ai:latest
128
+
129
+ # Create your configuration file
130
+
131
+ echo '[default]
132
+ agent = "openai"
133
+ score_threshold = 8
134
+ prompt = "development"
135
+
136
+ [prompts]
137
+ development = "Analyze cybersecurity news for relevance to our organization."' > lightman.toml
138
+ ```
139
+
140
+
141
+ # Run with mounted configuration
142
+ ```bash
143
+ docker run -d \
144
+ --name lightman-ai \
145
+ -v $(pwd)/lightman.toml:/app/lightman.toml \
146
+ -e OPENAI_API_KEY="your-api-key" \
147
+ elementsinteractive/lightman-ai:latest \
148
+ lightman run --config-file /app/lightman.toml
149
+ ```
150
+
151
+ **Docker Environment Variables:**
152
+ - `OPENAI_API_KEY` - Your OpenAI API key
153
+ - `GOOGLE_API_KEY` - Your Google Gemini API key
154
+ - `SERVICE_DESK_URL` - Service desk instance URL (optional)
155
+ - `SERVICE_DESK_USER` - Service desk username (optional)
156
+ - `SERVICE_DESK_TOKEN` - Service desk API token (optional)
157
+
158
+
159
+
160
+ ### Development Installation
161
+ ```bash
162
+ git clone git@github.com:elementsinteractive/lightman-ai.git
163
+ cd lightman_ai
164
+ just venv # Creates virtual environment and installs dependencies
165
+ ```
166
+
167
+ ## ⚙️ Configuration
168
+
169
+ Lightman AI uses TOML configuration files for flexible setup. Create a `lightman.toml` file:
170
+
171
+ ```toml
172
+ [default]
173
+ agent = 'openai' # AI agent to use (openai, gemini)
174
+ score_threshold = 8 # Minimum relevance score (1-10)
175
+ prompt = 'development' # Prompt template to use
176
+
177
+ # Optional: Service desk integration
178
+ service_desk_project_key = "SEC"
179
+ service_desk_request_id_type = "incident"
180
+
181
+ [prompts]
182
+ development = """
183
+ Analyze the following cybersecurity news articles and determine their relevance to our organization.
184
+ Rate each article from 1-10 based on potential impact and urgency.
185
+ Focus on: data breaches, malware, vulnerabilities, and threat intelligence.
186
+ """
187
+
188
+ custom_prompt = """
189
+ Your custom analysis prompt here...
190
+ """
191
+ ```
192
+
193
+ It also supports having separate files for your prompts and your configuration settings. Specify the path with `--prompt`.
194
+
195
+ `lightman.toml`
196
+ ```toml
197
+ [default]
198
+ agent = 'openai' # AI agent to use (openai, gemini)
199
+ score_threshold = 8 # Minimum relevance score (1-10)
200
+ prompt = 'development' # Prompt template to use
201
+
202
+ # Optional: Service desk integration
203
+ service_desk_project_key = "SEC"
204
+ service_desk_request_id_type = "incident"
205
+ ```
206
+
207
+ `prompts.toml`
208
+ ```toml
209
+ [prompts]
210
+ development = """
211
+ Analyze the following cybersecurity news articles and determine their relevance to our organization.
212
+ Rate each article from 1-10 based on potential impact and urgency.
213
+ Focus on: data breaches, malware, vulnerabilities, and threat intelligence.
214
+ """
215
+
216
+ custom_prompt = """
217
+ Your custom analysis prompt here...
218
+ """
219
+ ```
220
+ ### Environment Variables
221
+
222
+ Set up your AI provider credentials:
223
+
224
+ ```bash
225
+ # For OpenAI
226
+ export OPENAI_API_KEY="your-openai-api-key"
227
+
228
+ # For Google Gemini
229
+ export GOOGLE_API_KEY="your-google-api-key"
230
+
231
+ # Optional: Service desk integration
232
+ export SERVICE_DESK_URL="https://your-company.atlassian.net"
233
+ export SERVICE_DESK_USER="your-username"
234
+ export SERVICE_DESK_TOKEN="your-api-token"
235
+
236
+ ```
237
+ You can also specify a different path for your .env file with the `--env-file` option
238
+
239
+
240
+ ## 🔧 Usage
241
+
242
+ ### Basic Usage
243
+
244
+ ```bash
245
+ # Run with default settings
246
+ lightman run
247
+
248
+ # Use specific AI agent and score threshold
249
+ lightman run --agent gemini --score 7
250
+
251
+ # Use custom prompt template
252
+ lightman run --prompt custom_prompt --config-file ./my-config.toml
253
+
254
+ # Use custom environment file
255
+ lightman run --env-file production.env --agent openai --score 8
256
+
257
+ # Dry run (preview results without creating service desk tickets)
258
+ lightman run --dry-run --agent openai --score 9
259
+ ```
260
+
261
+ ### Command Line Options
262
+
263
+ | Option | Description | Default |
264
+ |--------|-------------|---------|
265
+ | `--agent` | AI agent to use (`openai`, `gemini`) | From config file |
266
+ | `--score` | Minimum relevance score (1-10) | From config file |
267
+ | `--prompt` | Prompt template name | From config file |
268
+ | `--config-file` | Path to configuration file | `lightman.toml` |
269
+ | `--config` | Configuration section to use | `default` |
270
+ | `--env-file` | Path to environment variables file | `.env` |
271
+ | `--dry-run` | Preview results without taking action | `false` |
272
+ | `--prompt-file` | File containing prompt templates | `lightman.toml` |
273
+
274
+ ### Example Workflows
275
+
276
+ **Daily Security Monitoring**:
277
+ ```bash
278
+ # Local installation
279
+ lightman run --agent openai --score 8 --prompt security_critical
280
+
281
+ # With custom environment file
282
+ lightman run --env-file production.env --agent openai --score 8
283
+
284
+ # Docker
285
+ docker run --rm \
286
+ -v $(pwd)/lightman.toml:/app/lightman.toml \
287
+ -e OPENAI_API_KEY="$OPENAI_API_KEY" \
288
+ elementsinteractive/lightman-ai:latest \
289
+ lightman run --config-file /app/lightman.toml --score 8
290
+ ```
291
+
292
+
293
+ **Weekly Risk Assessment**:
294
+ ```bash
295
+ # Local installation
296
+ lightman run --agent gemini --score 6 --prompt weekly_assessment
297
+
298
+ # With environment-specific settings
299
+ lightman run --env-file weekly.env --agent gemini --score 6
300
+
301
+ # Docker
302
+ docker run --rm \
303
+ -v $(pwd)/lightman.toml:/app/lightman.toml \
304
+ -e GOOGLE_API_KEY="$GOOGLE_API_KEY" \
305
+ elementsinteractive/lightman-ai:latest \
306
+ lightman run --config-file /app/lightman.toml --agent gemini --score 6
307
+ ```
308
+
309
+ **Integration Testing**:
310
+ ```bash
311
+ # Test configuration without creating tickets
312
+ lightman run --dry-run --config testing
313
+
314
+ # Test with staging environment
315
+ lightman run --env-file staging.env --dry-run --config testing
316
+ ```
317
+
318
+
319
+
320
+ ## 📊 Evaluation & Testing
321
+
322
+ Lightman AI includes a comprehensive evaluation framework to test and optimize AI agent performance:
323
+
324
+ ### Running Evaluations
325
+
326
+ ```bash
327
+ # Evaluate agent performance
328
+ just eval --agent openai --samples 3 --score 7
329
+
330
+ # Compare different agents
331
+ just eval --agent gemini --samples 5
332
+
333
+ # Add tags to differentiate runs from one another
334
+ just eval --agent gemini --samples 5 --tag "first-run"
335
+ just eval --agent gemini --samples 5 --tag "second-run"
336
+
337
+ # Test custom prompts
338
+ just eval --prompt custom_security --samples 10
339
+
340
+ # Use custom environment file for evaluation
341
+ python -m eval.cli --env-file production.env --agent openai --samples 3
342
+ ```
343
+
344
+ You can also provide defaults in a `toml` file for `eval`.
345
+
346
+ ```toml
347
+ [eval]
348
+ agent = 'openai'
349
+ score_threshold = 8
350
+ prompt = 'classify'
351
+ samples = 3
352
+ ```
353
+
354
+ ### Evaluation Metrics
355
+
356
+ The evaluation system measures:
357
+ - **Precision**: Accuracy of threat identification
358
+ - **Recall**: Coverage of actual security threats
359
+ - **F1 Score**: Balanced performance metric
360
+ - **Score Distribution**: Analysis of relevance scoring patterns
361
+
362
+ ### Evaluation Dataset
363
+
364
+ For precision evaluation, Lightman AI uses a curated set of **unclassified cybersecurity articles** that serve as ground truth data. These articles include:
365
+
366
+ - **Real-world news articles** from various cybersecurity sources
367
+ - **Mixed relevance levels** - both highly relevant and irrelevant security news
368
+ - **Diverse threat categories** - malware, data breaches, vulnerabilities, policy changes
369
+ - **Pre-validated classifications** by security experts for accuracy benchmarking
370
+
371
+ The evaluation framework compares the AI agent's classifications against these known classifications to measure:
372
+ - How accurately the agent identifies truly relevant threats (precision)
373
+ - How well it avoids false positives from irrelevant news
374
+ - Consistency across different types of security content
375
+
376
+ This approach ensures that performance metrics reflect real-world usage scenarios where the AI must distinguish between various types of cybersecurity news content.
377
+
378
+ **Make sure to fill in the `RELEVANT_ARTICLES` with the ones you classify as relevant, so that you can compare the accuracy after running the `eval` script.***
379
+
380
+ ## Sentry
381
+
382
+ - The application will automatically pick up and use environment variables if they are present in your environment or `.env` file.
383
+ - To enable Sentry error monitoring, set the `SENTRY_DSN` environment variable. This is **mandatory** for Sentry to be enabled. If `SENTRY_DSN` is not set, Sentry will be skipped and the application will run normally.
384
+ - If Sentry fails to initialize for any reason (e.g., network issues, invalid DSN), the application will log a warning and continue execution without error monitoring.
385
+ - Sentry is **optional**: the application does not require it to function, and all features will work even if Sentry is not configured or fails to start.
386
+
387
+ ## 📄 License
388
+
389
+ This project is licensed under the [MIT License](LICENSE) - see the LICENSE file for details.
390
+
391
+ ## 🙏 Acknowledgments
392
+
393
+ - **TheHackerNews** for providing cybersecurity news data
394
+
@@ -0,0 +1,34 @@
1
+ lightman_ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ lightman_ai/cli.py,sha256=Y3vl4xsJTBUBHRAR4zlMhjK5Cr2HNWRokWaGGuxFCQU,3775
3
+ lightman_ai/constants.py,sha256=qfZgcTLK51l--JDhns-uRANjccFEPN6iTFsJKn8T4vs,101
4
+ lightman_ai/main.py,sha256=Av4Jr8MhwVLUrVeCg24SCnpaT49hPYFlQJD0ABGfJGc,3379
5
+ lightman_ai/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ lightman_ai/ai/utils.py,sha256=vFTN8Tto7QHMV4DpTzn8Dz06niHm_bbgPivyc-rD1aE,509
7
+ lightman_ai/ai/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ lightman_ai/ai/base/agent.py,sha256=fFjF_nCzoba4hbSfRPmIm9dxW6A45qJWTrSbrq9NFto,985
9
+ lightman_ai/ai/base/exceptions.py,sha256=OLM0Fif66rAZe9I4xHIDHCDN61mObaCMH7KKlfSmw6Y,107
10
+ lightman_ai/ai/gemini/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ lightman_ai/ai/gemini/agent.py,sha256=1pDdKrm2wCxTFxlHQHXWENiys1FWar6kxppGYFC3YgI,641
12
+ lightman_ai/ai/gemini/exceptions.py,sha256=EJm9qSwI9JhrqPssGQP-cO8vOI--u0V1a6X4tQdWW3A,407
13
+ lightman_ai/ai/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ lightman_ai/ai/openai/agent.py,sha256=bMZS-F58WaXDR6f3j5DhtZ4077Gy80_oGYJczB7nV74,1043
15
+ lightman_ai/ai/openai/exceptions.py,sha256=V41fLkhkDguKU9_Wy0vMn0UXHmuAkqqXTmrcNKTNRZE,2414
16
+ lightman_ai/article/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ lightman_ai/article/models.py,sha256=Zyx4CKBNGDcK9IWnPOb6CK6nKH2s40UaqsoZlIjSidU,1598
18
+ lightman_ai/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ lightman_ai/core/config.py,sha256=ppWNoNivNqxGi4TOZIMaTGo46W7Ic1a8cO8hWVAkkps,3031
20
+ lightman_ai/core/exceptions.py,sha256=XKxA-EmLvd9cmbkUfdrBd27gsEFyIkSCQBf4pD-1AJk,239
21
+ lightman_ai/core/sentry.py,sha256=yJYqZWhLH1OR11gVr1YPF0gPUSLjm8klnSmXFdDpyEo,1039
22
+ lightman_ai/core/settings.py,sha256=pVhA0naxk7NRnJXRQB-CHVeIvYCEC2jP4mv8cbdfJYY,296
23
+ lightman_ai/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ lightman_ai/integrations/service_desk/__init__.py,sha256=Ijs7_ysJVwiT_Y1U8iPOV17E7dtkVzNXL00d8cgyaCc,66
25
+ lightman_ai/integrations/service_desk/constants.py,sha256=ropNDMengLp96pXD6wq2voWPeBESt6f2Wnfk7845mck,306
26
+ lightman_ai/integrations/service_desk/exceptions.py,sha256=RjH9Jam7ONDJQ0uhWu3rtJApNybsqfi7TGtT0dlN490,2517
27
+ lightman_ai/integrations/service_desk/integration.py,sha256=5r3bipao_apaDWLRiH4oiBJFb4c1mvo7Sj2AOQUWiFY,2895
28
+ lightman_ai/sources/base.py,sha256=i544j1ubqhx7uKRrbuXq3yhRuRbwJgCQxCIavjznn5s,182
29
+ lightman_ai/sources/the_hacker_news.py,sha256=qyLF4wVHJ7C2O01MGYrKej-KvPI4mHd8ntntfMksX6s,1809
30
+ lightman_ai-0.20.1.dist-info/METADATA,sha256=LuWTKR9ZjUpexQlbBmudcc5euYmrD1DnyRWZtOFPp9w,12558
31
+ lightman_ai-0.20.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
32
+ lightman_ai-0.20.1.dist-info/entry_points.txt,sha256=9H7Ji-zxbCWAaVL5Yg4fG5va0H_5Tr2kMGGMsghaAas,60
33
+ lightman_ai-0.20.1.dist-info/licenses/LICENSE,sha256=NhxDmY3AGgeEsYHIfDGLNkzBVX94pARRDS8H46JZ1zQ,1076
34
+ lightman_ai-0.20.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ lightman-ai = lightman_ai.cli:entry_point