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,111 @@
1
+ """
2
+ LLM service wrapper for prompt inspection.
3
+
4
+ Provides unified interface to multiple LLM providers (AWS Bedrock, Ollama, Anthropic Direct)
5
+ specifically for prompt inspection and security analysis tasks.
6
+
7
+
8
+ """
9
+
10
+ import logging
11
+ from typing import Optional, Dict, List, Any
12
+
13
+
14
+ class InspectionLLMService:
15
+ """
16
+ LLM service wrapper for prompt inspection with multi-provider support.
17
+ """
18
+
19
+ def __init__(self, config: Dict, provider_manager: Optional[Any] = None):
20
+ """
21
+ Initialise inspection LLM service.
22
+
23
+ Args:
24
+ config: LLM inspection configuration
25
+ provider_manager: Provider manager with access to all LLM providers
26
+ """
27
+ self.config = config
28
+ self.provider_manager = provider_manager
29
+ self.model_id = config.get('model')
30
+ self.provider_name = config.get('provider') # Optional: AWS Bedrock, Ollama, Anthropic Direct
31
+ self.max_tokens = config.get('max_tokens', 500)
32
+
33
+ # Determine which provider to use
34
+ self.provider = None
35
+ if provider_manager:
36
+ self.provider = self._get_provider()
37
+
38
+ if self.provider:
39
+ logging.info(f"Inspection LLM service initialised: provider={self.provider_name}, model={self.model_id}")
40
+ else:
41
+ logging.warning("Inspection LLM service could not initialise provider")
42
+
43
+ def _get_provider(self):
44
+ """
45
+ Get the configured LLM provider.
46
+
47
+ Returns:
48
+ Provider instance or None
49
+ """
50
+ try:
51
+ # If specific provider requested, use that
52
+ if self.provider_name:
53
+ if self.provider_name.lower() == 'aws bedrock':
54
+ return self.provider_manager.get_bedrock_provider()
55
+ elif self.provider_name.lower() == 'ollama':
56
+ return self.provider_manager.get_ollama_provider()
57
+ elif self.provider_name.lower() == 'anthropic direct':
58
+ return self.provider_manager.get_anthropic_provider()
59
+
60
+ # Otherwise, auto-detect based on model ID
61
+ return self.provider_manager.get_provider_for_model(self.model_id)
62
+
63
+ except Exception as e:
64
+ logging.error(f"Failed to get LLM provider for inspection: {e}")
65
+ return None
66
+
67
+ def invoke_model(self, messages: List[Dict], max_tokens: Optional[int] = None,
68
+ temperature: float = 0.1) -> Optional[Dict]:
69
+ """
70
+ Invoke LLM for prompt analysis.
71
+
72
+ Args:
73
+ messages: List of message dicts with role and content
74
+ max_tokens: Maximum tokens to generate (default from config)
75
+ temperature: Temperature for generation (default 0.1 for consistency)
76
+
77
+ Returns:
78
+ Response dict with content, or None on failure
79
+ """
80
+ if not self.provider:
81
+ logging.error("No LLM provider available for inspection")
82
+ return None
83
+
84
+ try:
85
+ # Use configured max_tokens if not specified
86
+ if max_tokens is None:
87
+ max_tokens = self.max_tokens
88
+
89
+ # Invoke via provider
90
+ response = self.provider.invoke_model(
91
+ model_id=self.model_id,
92
+ messages=messages,
93
+ max_tokens=max_tokens,
94
+ temperature=temperature,
95
+ tools=None # No tools for inspection
96
+ )
97
+
98
+ return response
99
+
100
+ except Exception as e:
101
+ logging.error(f"Failed to invoke LLM for inspection: {e}")
102
+ return None
103
+
104
+ def is_available(self) -> bool:
105
+ """
106
+ Check if LLM service is available for inspection.
107
+
108
+ Returns:
109
+ True if provider and model are configured
110
+ """
111
+ return self.provider is not None and self.model_id is not None
@@ -0,0 +1,229 @@
1
+ """
2
+ Attack pattern definitions for prompt inspection.
3
+
4
+ This module contains regex patterns and keyword lists for detecting:
5
+ - Prompt injection attempts
6
+ - Jailbreak attempts
7
+ - Code injection patterns
8
+ - Excessive content
9
+ - Other security risks
10
+
11
+
12
+ """
13
+
14
+ import re
15
+ from typing import Dict, List, Tuple, Optional
16
+
17
+ # Prompt injection patterns - attempts to override system instructions
18
+ PROMPT_INJECTION_PATTERNS = [
19
+ r'ignore\s+(previous|all|above|earlier|prior)\s+(instructions?|prompts?|rules?|directives?)',
20
+ r'disregard\s+(previous|all|above|earlier|prior)\s+(instructions?|prompts?|rules?)',
21
+ r'forget\s+(previous|all|above|earlier|prior)\s+(instructions?|prompts?|rules?)',
22
+ r'new\s+(instruction|directive|command|task|role):\s*',
23
+ r'system:\s*(you\s+)?(are|must|should|will)\s+now',
24
+ r'override\s+(previous|all|system)\s+(instructions?|settings?|rules?)',
25
+ r'</s>|<\|im_end\|>|<\|endoftext\|>|<\|system\|>', # Model control tokens
26
+ r'\[INST\]|\[/INST\]', # Instruction markers
27
+ r'<\|assistant\|>|<\|user\|>', # Role markers
28
+ ]
29
+
30
+ # Jailbreak patterns - attempts to bypass safety guidelines
31
+ JAILBREAK_PATTERNS = [
32
+ r'\b(DAN|Developer\s+Mode|Sudo\s+Mode|God\s+Mode|Admin\s+Mode)\b',
33
+ r'pretend\s+you\s+(are|have)\s+no\s+(restrictions?|limitations?|rules?|ethics?|guidelines?)',
34
+ r'roleplay\s+as\s+(an?\s+)?(unrestricted|unfiltered|uncensored)',
35
+ r'act\s+as\s+if\s+you\s+(have\s+)?no\s+(restrictions?|limitations?|rules?)',
36
+ r'bypass\s+(safety|content|moderation|filter)',
37
+ r'without\s+(any\s+)?(ethical|moral|safety)\s+(concerns?|considerations?|restrictions?)',
38
+ r'evil\s+(ai|assistant|mode)',
39
+ r'jailbreak|jailbroken',
40
+ ]
41
+
42
+ # Code injection patterns - malicious code attempts
43
+ CODE_INJECTION_PATTERNS = [
44
+ r';\s*rm\s+-rf',
45
+ r';\s*DROP\s+TABLE',
46
+ r';\s*DELETE\s+FROM',
47
+ r'<script[^>]*>.*?</script>',
48
+ r'\$\([^)]+\)|`[^`]+`', # Command substitution
49
+ r'\|\s*bash|\|\s*sh|\|\s*zsh',
50
+ r'&&\s*(rm|del|format|wget|curl)\s',
51
+ r'eval\s*\(',
52
+ r'exec\s*\(',
53
+ r'system\s*\(',
54
+ r'__import__\s*\(',
55
+ ]
56
+
57
+ # PII patterns - potential personally identifiable information
58
+ PII_PATTERNS = [
59
+ r'\b\d{3}-\d{2}-\d{4}\b', # SSN pattern
60
+ r'\b\d{16}\b', # Credit card pattern
61
+ r'\b[A-Z]{2}\d{6,8}\b', # Passport pattern
62
+ r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b', # IP address
63
+ r'password\s*[:=]\s*\S+', # Password disclosure
64
+ r'api[_-]?key\s*[:=]\s*\S+', # API key
65
+ r'secret\s*[:=]\s*\S+', # Secret disclosure
66
+ ]
67
+
68
+ # Excessive repetition pattern
69
+ EXCESSIVE_REPETITION_PATTERN = r'(.{10,}?)\1{5,}' # Same pattern repeated 5+ times
70
+
71
+
72
+ class PatternMatcher:
73
+ """
74
+ Pattern-based detection for prompt security issues.
75
+ """
76
+
77
+ def __init__(self):
78
+ """Initialise pattern matcher with compiled regex patterns."""
79
+ self.prompt_injection_regex = [re.compile(p, re.IGNORECASE) for p in PROMPT_INJECTION_PATTERNS]
80
+ self.jailbreak_regex = [re.compile(p, re.IGNORECASE) for p in JAILBREAK_PATTERNS]
81
+ self.code_injection_regex = [re.compile(p, re.IGNORECASE) for p in CODE_INJECTION_PATTERNS]
82
+ self.pii_regex = [re.compile(p, re.IGNORECASE) for p in PII_PATTERNS]
83
+ self.repetition_regex = re.compile(EXCESSIVE_REPETITION_PATTERN, re.IGNORECASE)
84
+
85
+ def check_prompt_injection(self, text: str) -> Tuple[bool, Optional[str]]:
86
+ """
87
+ Check for prompt injection patterns.
88
+
89
+ Args:
90
+ text: Text to analyse
91
+
92
+ Returns:
93
+ Tuple of (detected, matched_pattern)
94
+ """
95
+ for pattern in self.prompt_injection_regex:
96
+ match = pattern.search(text)
97
+ if match:
98
+ return True, match.group(0)
99
+ return False, None
100
+
101
+ def check_jailbreak(self, text: str) -> Tuple[bool, Optional[str]]:
102
+ """
103
+ Check for jailbreak attempt patterns.
104
+
105
+ Args:
106
+ text: Text to analyse
107
+
108
+ Returns:
109
+ Tuple of (detected, matched_pattern)
110
+ """
111
+ for pattern in self.jailbreak_regex:
112
+ match = pattern.search(text)
113
+ if match:
114
+ return True, match.group(0)
115
+ return False, None
116
+
117
+ def check_code_injection(self, text: str) -> Tuple[bool, Optional[str]]:
118
+ """
119
+ Check for code injection patterns.
120
+
121
+ Args:
122
+ text: Text to analyse
123
+
124
+ Returns:
125
+ Tuple of (detected, matched_pattern)
126
+ """
127
+ for pattern in self.code_injection_regex:
128
+ match = pattern.search(text)
129
+ if match:
130
+ return True, match.group(0)
131
+ return False, None
132
+
133
+ def check_pii(self, text: str) -> Tuple[bool, Optional[str]]:
134
+ """
135
+ Check for potential PII exposure.
136
+
137
+ Args:
138
+ text: Text to analyse
139
+
140
+ Returns:
141
+ Tuple of (detected, matched_pattern)
142
+ """
143
+ for pattern in self.pii_regex:
144
+ match = pattern.search(text)
145
+ if match:
146
+ # Return redacted version
147
+ return True, "[REDACTED]"
148
+ return False, None
149
+
150
+ def check_excessive_repetition(self, text: str) -> bool:
151
+ """
152
+ Check for excessive repetition (potential DoS).
153
+
154
+ Args:
155
+ text: Text to analyse
156
+
157
+ Returns:
158
+ True if excessive repetition detected
159
+ """
160
+ return bool(self.repetition_regex.search(text))
161
+
162
+ def scan_all(self, text: str, config: Dict) -> Dict[str, any]:
163
+ """
164
+ Run all configured pattern checks.
165
+
166
+ Args:
167
+ text: Text to analyse
168
+ config: Configuration dict with enabled checks
169
+
170
+ Returns:
171
+ Dict with scan results
172
+ """
173
+ results = {
174
+ 'violations': [],
175
+ 'severity': 'none',
176
+ 'detected_patterns': []
177
+ }
178
+
179
+ # Check prompt injection
180
+ if config.get('check_prompt_injection', True):
181
+ detected, pattern = self.check_prompt_injection(text)
182
+ if detected:
183
+ results['violations'].append('prompt_injection')
184
+ results['detected_patterns'].append(pattern)
185
+ results['severity'] = 'high'
186
+
187
+ # Check jailbreak
188
+ if config.get('check_jailbreak', True):
189
+ detected, pattern = self.check_jailbreak(text)
190
+ if detected:
191
+ results['violations'].append('jailbreak')
192
+ results['detected_patterns'].append(pattern)
193
+ if results['severity'] == 'none':
194
+ results['severity'] = 'high'
195
+
196
+ # Check code injection
197
+ if config.get('check_code_injection', True):
198
+ detected, pattern = self.check_code_injection(text)
199
+ if detected:
200
+ results['violations'].append('code_injection')
201
+ results['detected_patterns'].append(pattern)
202
+ results['severity'] = 'critical'
203
+
204
+ # Check PII
205
+ if config.get('check_pii', False):
206
+ detected, pattern = self.check_pii(text)
207
+ if detected:
208
+ results['violations'].append('pii_exposure')
209
+ results['detected_patterns'].append(pattern)
210
+ if results['severity'] in ['none', 'low']:
211
+ results['severity'] = 'medium'
212
+
213
+ # Check excessive length
214
+ if config.get('check_excessive_length', True):
215
+ max_length = config.get('max_prompt_length', 50000)
216
+ if len(text) > max_length:
217
+ results['violations'].append('excessive_length')
218
+ results['detected_patterns'].append(f'Length: {len(text)} > {max_length}')
219
+ if results['severity'] == 'none':
220
+ results['severity'] = 'medium'
221
+
222
+ # Check excessive repetition
223
+ if self.check_excessive_repetition(text):
224
+ results['violations'].append('excessive_repetition')
225
+ results['detected_patterns'].append('Detected repetitive pattern')
226
+ if results['severity'] == 'none':
227
+ results['severity'] = 'low'
228
+
229
+ return results