dtSpark 1.0.4__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.
Files changed (96) hide show
  1. dtSpark/__init__.py +0 -0
  2. dtSpark/_description.txt +1 -0
  3. dtSpark/_full_name.txt +1 -0
  4. dtSpark/_licence.txt +21 -0
  5. dtSpark/_metadata.yaml +6 -0
  6. dtSpark/_name.txt +1 -0
  7. dtSpark/_version.txt +1 -0
  8. dtSpark/aws/__init__.py +7 -0
  9. dtSpark/aws/authentication.py +296 -0
  10. dtSpark/aws/bedrock.py +578 -0
  11. dtSpark/aws/costs.py +318 -0
  12. dtSpark/aws/pricing.py +580 -0
  13. dtSpark/cli_interface.py +2645 -0
  14. dtSpark/conversation_manager.py +3050 -0
  15. dtSpark/core/__init__.py +12 -0
  16. dtSpark/core/application.py +3355 -0
  17. dtSpark/core/context_compaction.py +735 -0
  18. dtSpark/daemon/__init__.py +104 -0
  19. dtSpark/daemon/__main__.py +10 -0
  20. dtSpark/daemon/action_monitor.py +213 -0
  21. dtSpark/daemon/daemon_app.py +730 -0
  22. dtSpark/daemon/daemon_manager.py +289 -0
  23. dtSpark/daemon/execution_coordinator.py +194 -0
  24. dtSpark/daemon/pid_file.py +169 -0
  25. dtSpark/database/__init__.py +482 -0
  26. dtSpark/database/autonomous_actions.py +1191 -0
  27. dtSpark/database/backends.py +329 -0
  28. dtSpark/database/connection.py +122 -0
  29. dtSpark/database/conversations.py +520 -0
  30. dtSpark/database/credential_prompt.py +218 -0
  31. dtSpark/database/files.py +205 -0
  32. dtSpark/database/mcp_ops.py +355 -0
  33. dtSpark/database/messages.py +161 -0
  34. dtSpark/database/schema.py +673 -0
  35. dtSpark/database/tool_permissions.py +186 -0
  36. dtSpark/database/usage.py +167 -0
  37. dtSpark/files/__init__.py +4 -0
  38. dtSpark/files/manager.py +322 -0
  39. dtSpark/launch.py +39 -0
  40. dtSpark/limits/__init__.py +10 -0
  41. dtSpark/limits/costs.py +296 -0
  42. dtSpark/limits/tokens.py +342 -0
  43. dtSpark/llm/__init__.py +17 -0
  44. dtSpark/llm/anthropic_direct.py +446 -0
  45. dtSpark/llm/base.py +146 -0
  46. dtSpark/llm/context_limits.py +438 -0
  47. dtSpark/llm/manager.py +177 -0
  48. dtSpark/llm/ollama.py +578 -0
  49. dtSpark/mcp_integration/__init__.py +5 -0
  50. dtSpark/mcp_integration/manager.py +653 -0
  51. dtSpark/mcp_integration/tool_selector.py +225 -0
  52. dtSpark/resources/config.yaml.template +631 -0
  53. dtSpark/safety/__init__.py +22 -0
  54. dtSpark/safety/llm_service.py +111 -0
  55. dtSpark/safety/patterns.py +229 -0
  56. dtSpark/safety/prompt_inspector.py +442 -0
  57. dtSpark/safety/violation_logger.py +346 -0
  58. dtSpark/scheduler/__init__.py +20 -0
  59. dtSpark/scheduler/creation_tools.py +599 -0
  60. dtSpark/scheduler/execution_queue.py +159 -0
  61. dtSpark/scheduler/executor.py +1152 -0
  62. dtSpark/scheduler/manager.py +395 -0
  63. dtSpark/tools/__init__.py +4 -0
  64. dtSpark/tools/builtin.py +833 -0
  65. dtSpark/web/__init__.py +20 -0
  66. dtSpark/web/auth.py +152 -0
  67. dtSpark/web/dependencies.py +37 -0
  68. dtSpark/web/endpoints/__init__.py +17 -0
  69. dtSpark/web/endpoints/autonomous_actions.py +1125 -0
  70. dtSpark/web/endpoints/chat.py +621 -0
  71. dtSpark/web/endpoints/conversations.py +353 -0
  72. dtSpark/web/endpoints/main_menu.py +547 -0
  73. dtSpark/web/endpoints/streaming.py +421 -0
  74. dtSpark/web/server.py +578 -0
  75. dtSpark/web/session.py +167 -0
  76. dtSpark/web/ssl_utils.py +195 -0
  77. dtSpark/web/static/css/dark-theme.css +427 -0
  78. dtSpark/web/static/js/actions.js +1101 -0
  79. dtSpark/web/static/js/chat.js +614 -0
  80. dtSpark/web/static/js/main.js +496 -0
  81. dtSpark/web/static/js/sse-client.js +242 -0
  82. dtSpark/web/templates/actions.html +408 -0
  83. dtSpark/web/templates/base.html +93 -0
  84. dtSpark/web/templates/chat.html +814 -0
  85. dtSpark/web/templates/conversations.html +350 -0
  86. dtSpark/web/templates/goodbye.html +81 -0
  87. dtSpark/web/templates/login.html +90 -0
  88. dtSpark/web/templates/main_menu.html +983 -0
  89. dtSpark/web/templates/new_conversation.html +191 -0
  90. dtSpark/web/web_interface.py +137 -0
  91. dtspark-1.0.4.dist-info/METADATA +187 -0
  92. dtspark-1.0.4.dist-info/RECORD +96 -0
  93. dtspark-1.0.4.dist-info/WHEEL +5 -0
  94. dtspark-1.0.4.dist-info/entry_points.txt +3 -0
  95. dtspark-1.0.4.dist-info/licenses/LICENSE +21 -0
  96. dtspark-1.0.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,346 @@
1
+ """
2
+ Violation logger for Cyber Security audit trail.
3
+
4
+ This module handles database operations for logging prompt inspection violations,
5
+ enabling security monitoring, compliance, and incident response.
6
+
7
+
8
+ """
9
+
10
+ import sqlite3
11
+ import logging
12
+ from datetime import datetime
13
+ from typing import List, Dict, Optional
14
+
15
+
16
+ class ViolationLogger:
17
+ """
18
+ Logs prompt inspection violations to database for audit trail.
19
+ """
20
+
21
+ def __init__(self, database_connection: sqlite3.Connection, config: Dict):
22
+ """
23
+ Initialise violation logger.
24
+
25
+ Args:
26
+ database_connection: SQLite database connection
27
+ config: Configuration dictionary
28
+ """
29
+ self.conn = database_connection
30
+ self.config = config
31
+ self.enabled = config.get('log_violations', True)
32
+ self.alert_threshold = config.get('violation_threshold', 5)
33
+ self.alert_enabled = config.get('alert_on_repeated_violations', True)
34
+
35
+ def log_violation(self, user_guid: str, violation_types: List[str],
36
+ severity: str, prompt_snippet: str, detection_method: str,
37
+ action_taken: str, confidence_score: Optional[float] = None,
38
+ conversation_id: Optional[int] = None):
39
+ """
40
+ Log a prompt inspection violation to database.
41
+
42
+ Args:
43
+ user_guid: User's unique identifier
44
+ violation_types: List of violation types detected
45
+ severity: Severity level (none, low, medium, high, critical)
46
+ prompt_snippet: First 500 characters of the violating prompt
47
+ detection_method: How violation was detected (pattern, llm, hybrid)
48
+ action_taken: Action taken (blocked, warned, sanitised, logged)
49
+ confidence_score: Optional confidence score (0.0-1.0)
50
+ conversation_id: Optional conversation ID
51
+ """
52
+ if not self.enabled:
53
+ return
54
+
55
+ try:
56
+ cursor = self.conn.cursor()
57
+
58
+ # Log each violation type separately for better analysis
59
+ for violation_type in violation_types:
60
+ cursor.execute('''
61
+ INSERT INTO prompt_inspection_violations
62
+ (user_guid, conversation_id, violation_type, severity,
63
+ prompt_snippet, detection_method, action_taken,
64
+ confidence_score, timestamp)
65
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
66
+ ''', (
67
+ user_guid,
68
+ conversation_id,
69
+ violation_type,
70
+ severity,
71
+ prompt_snippet[:500], # Ensure max 500 chars
72
+ detection_method,
73
+ action_taken,
74
+ confidence_score,
75
+ datetime.now()
76
+ ))
77
+
78
+ self.conn.commit()
79
+
80
+ logging.info(f"Logged {len(violation_types)} violation(s) for user {user_guid}: {', '.join(violation_types)}")
81
+
82
+ # Check if alert threshold reached
83
+ if self.alert_enabled:
84
+ self._check_alert_threshold(user_guid)
85
+
86
+ except Exception as e:
87
+ logging.error(f"Failed to log violation: {e}")
88
+ self.conn.rollback()
89
+
90
+ def get_user_violation_count(self, user_guid: str, hours: int = 24) -> int:
91
+ """
92
+ Get count of violations for a user in the last N hours.
93
+
94
+ Args:
95
+ user_guid: User's unique identifier
96
+ hours: Number of hours to look back (default 24)
97
+
98
+ Returns:
99
+ Count of violations
100
+ """
101
+ try:
102
+ cursor = self.conn.cursor()
103
+ cursor.execute('''
104
+ SELECT COUNT(*)
105
+ FROM prompt_inspection_violations
106
+ WHERE user_guid = ?
107
+ AND timestamp >= datetime('now', '-' || ? || ' hours')
108
+ ''', (user_guid, hours))
109
+
110
+ return cursor.fetchone()[0]
111
+
112
+ except Exception as e:
113
+ logging.error(f"Failed to get user violation count: {e}")
114
+ return 0
115
+
116
+ def get_user_violations(self, user_guid: str, limit: int = 50) -> List[Dict]:
117
+ """
118
+ Get recent violations for a user.
119
+
120
+ Args:
121
+ user_guid: User's unique identifier
122
+ limit: Maximum number of records to return
123
+
124
+ Returns:
125
+ List of violation records
126
+ """
127
+ try:
128
+ cursor = self.conn.cursor()
129
+ cursor.execute('''
130
+ SELECT id, conversation_id, violation_type, severity,
131
+ prompt_snippet, detection_method, action_taken,
132
+ confidence_score, timestamp
133
+ FROM prompt_inspection_violations
134
+ WHERE user_guid = ?
135
+ ORDER BY timestamp DESC
136
+ LIMIT ?
137
+ ''', (user_guid, limit))
138
+
139
+ rows = cursor.fetchall()
140
+ return [
141
+ {
142
+ 'id': row[0],
143
+ 'conversation_id': row[1],
144
+ 'violation_type': row[2],
145
+ 'severity': row[3],
146
+ 'prompt_snippet': row[4],
147
+ 'detection_method': row[5],
148
+ 'action_taken': row[6],
149
+ 'confidence_score': row[7],
150
+ 'timestamp': row[8]
151
+ }
152
+ for row in rows
153
+ ]
154
+
155
+ except Exception as e:
156
+ logging.error(f"Failed to get user violations: {e}")
157
+ return []
158
+
159
+ def get_violation_statistics(self, user_guid: Optional[str] = None,
160
+ days: int = 30) -> Dict:
161
+ """
162
+ Get violation statistics for reporting and analysis.
163
+
164
+ Args:
165
+ user_guid: Optional user to filter by
166
+ days: Number of days to analyse (default 30)
167
+
168
+ Returns:
169
+ Dictionary with statistics
170
+ """
171
+ try:
172
+ cursor = self.conn.cursor()
173
+
174
+ # Base query
175
+ base_where = "WHERE timestamp >= datetime('now', '-' || ? || ' days')"
176
+ params = [days]
177
+
178
+ if user_guid:
179
+ base_where += " AND user_guid = ?"
180
+ params.append(user_guid)
181
+
182
+ # Total violations
183
+ cursor.execute(f'''
184
+ SELECT COUNT(*)
185
+ FROM prompt_inspection_violations
186
+ {base_where}
187
+ ''', params)
188
+ total = cursor.fetchone()[0]
189
+
190
+ # By severity
191
+ cursor.execute(f'''
192
+ SELECT severity, COUNT(*)
193
+ FROM prompt_inspection_violations
194
+ {base_where}
195
+ GROUP BY severity
196
+ ''', params)
197
+ by_severity = {row[0]: row[1] for row in cursor.fetchall()}
198
+
199
+ # By violation type
200
+ cursor.execute(f'''
201
+ SELECT violation_type, COUNT(*)
202
+ FROM prompt_inspection_violations
203
+ {base_where}
204
+ GROUP BY violation_type
205
+ ORDER BY COUNT(*) DESC
206
+ LIMIT 10
207
+ ''', params)
208
+ by_type = {row[0]: row[1] for row in cursor.fetchall()}
209
+
210
+ # By action taken
211
+ cursor.execute(f'''
212
+ SELECT action_taken, COUNT(*)
213
+ FROM prompt_inspection_violations
214
+ {base_where}
215
+ GROUP BY action_taken
216
+ ''', params)
217
+ by_action = {row[0]: row[1] for row in cursor.fetchall()}
218
+
219
+ # Top users (if not filtered by user)
220
+ top_users = []
221
+ if not user_guid:
222
+ cursor.execute(f'''
223
+ SELECT user_guid, COUNT(*) as count
224
+ FROM prompt_inspection_violations
225
+ {base_where}
226
+ GROUP BY user_guid
227
+ ORDER BY count DESC
228
+ LIMIT 10
229
+ ''', params)
230
+ top_users = [{'user_guid': row[0], 'count': row[1]} for row in cursor.fetchall()]
231
+
232
+ return {
233
+ 'total': total,
234
+ 'by_severity': by_severity,
235
+ 'by_type': by_type,
236
+ 'by_action': by_action,
237
+ 'top_users': top_users,
238
+ 'days': days
239
+ }
240
+
241
+ except Exception as e:
242
+ logging.error(f"Failed to get violation statistics: {e}")
243
+ return {
244
+ 'total': 0,
245
+ 'by_severity': {},
246
+ 'by_type': {},
247
+ 'by_action': {},
248
+ 'top_users': [],
249
+ 'days': days
250
+ }
251
+
252
+ def _check_alert_threshold(self, user_guid: str):
253
+ """
254
+ Check if user has exceeded violation threshold and log alert.
255
+
256
+ Args:
257
+ user_guid: User's unique identifier
258
+ """
259
+ count = self.get_user_violation_count(user_guid, hours=24)
260
+
261
+ if count >= self.alert_threshold:
262
+ logging.warning(
263
+ f"SECURITY ALERT: User {user_guid} has {count} violations in the last 24 hours "
264
+ f"(threshold: {self.alert_threshold})"
265
+ )
266
+
267
+ def export_violations_to_csv(self, file_path: str, user_guid: Optional[str] = None,
268
+ days: int = 30) -> bool:
269
+ """
270
+ Export violations to CSV for audit and analysis.
271
+
272
+ Args:
273
+ file_path: Path to output CSV file
274
+ user_guid: Optional user to filter by
275
+ days: Number of days to export (default 30)
276
+
277
+ Returns:
278
+ True if successful
279
+ """
280
+ try:
281
+ import csv
282
+
283
+ cursor = self.conn.cursor()
284
+
285
+ # Build query
286
+ base_where = "WHERE timestamp >= datetime('now', '-' || ? || ' days')"
287
+ params = [days]
288
+
289
+ if user_guid:
290
+ base_where += " AND user_guid = ?"
291
+ params.append(user_guid)
292
+
293
+ cursor.execute(f'''
294
+ SELECT user_guid, conversation_id, violation_type, severity,
295
+ prompt_snippet, detection_method, action_taken,
296
+ confidence_score, timestamp
297
+ FROM prompt_inspection_violations
298
+ {base_where}
299
+ ORDER BY timestamp DESC
300
+ ''', params)
301
+
302
+ rows = cursor.fetchall()
303
+
304
+ # Write to CSV
305
+ with open(file_path, 'w', newline='', encoding='utf-8') as csvfile:
306
+ writer = csv.writer(csvfile)
307
+
308
+ # Header
309
+ writer.writerow([
310
+ 'User GUID', 'Conversation ID', 'Violation Type', 'Severity',
311
+ 'Prompt Snippet', 'Detection Method', 'Action Taken',
312
+ 'Confidence Score', 'Timestamp'
313
+ ])
314
+
315
+ # Data rows
316
+ writer.writerows(rows)
317
+
318
+ logging.info(f"Exported {len(rows)} violation records to {file_path}")
319
+ return True
320
+
321
+ except Exception as e:
322
+ logging.error(f"Failed to export violations to CSV: {e}")
323
+ return False
324
+
325
+ def cleanup_old_violations(self, days: int = 90):
326
+ """
327
+ Clean up old violation records.
328
+
329
+ Args:
330
+ days: Delete records older than this many days (default 90)
331
+ """
332
+ try:
333
+ cursor = self.conn.cursor()
334
+ cursor.execute('''
335
+ DELETE FROM prompt_inspection_violations
336
+ WHERE timestamp < datetime('now', '-' || ? || ' days')
337
+ ''', (days,))
338
+
339
+ deleted = cursor.rowcount
340
+ self.conn.commit()
341
+
342
+ logging.info(f"Cleaned up {deleted} old violation records (older than {days} days)")
343
+
344
+ except Exception as e:
345
+ logging.error(f"Failed to cleanup old violations: {e}")
346
+ self.conn.rollback()
@@ -0,0 +1,20 @@
1
+ """
2
+ Scheduler module for autonomous action execution.
3
+
4
+ This module provides:
5
+ - ActionSchedulerManager: APScheduler wrapper for scheduling actions
6
+ - ActionExecutionQueue: Thread-safe sequential execution queue
7
+ - ActionExecutor: LLM invocation and result handling
8
+
9
+
10
+ """
11
+
12
+ from .manager import ActionSchedulerManager
13
+ from .execution_queue import ActionExecutionQueue
14
+ from .executor import ActionExecutor
15
+
16
+ __all__ = [
17
+ 'ActionSchedulerManager',
18
+ 'ActionExecutionQueue',
19
+ 'ActionExecutor'
20
+ ]