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.
- dtSpark/__init__.py +0 -0
- dtSpark/_description.txt +1 -0
- dtSpark/_full_name.txt +1 -0
- dtSpark/_licence.txt +21 -0
- dtSpark/_metadata.yaml +6 -0
- dtSpark/_name.txt +1 -0
- dtSpark/_version.txt +1 -0
- dtSpark/aws/__init__.py +7 -0
- dtSpark/aws/authentication.py +296 -0
- dtSpark/aws/bedrock.py +578 -0
- dtSpark/aws/costs.py +318 -0
- dtSpark/aws/pricing.py +580 -0
- dtSpark/cli_interface.py +2645 -0
- dtSpark/conversation_manager.py +3050 -0
- dtSpark/core/__init__.py +12 -0
- dtSpark/core/application.py +3355 -0
- dtSpark/core/context_compaction.py +735 -0
- dtSpark/daemon/__init__.py +104 -0
- dtSpark/daemon/__main__.py +10 -0
- dtSpark/daemon/action_monitor.py +213 -0
- dtSpark/daemon/daemon_app.py +730 -0
- dtSpark/daemon/daemon_manager.py +289 -0
- dtSpark/daemon/execution_coordinator.py +194 -0
- dtSpark/daemon/pid_file.py +169 -0
- dtSpark/database/__init__.py +482 -0
- dtSpark/database/autonomous_actions.py +1191 -0
- dtSpark/database/backends.py +329 -0
- dtSpark/database/connection.py +122 -0
- dtSpark/database/conversations.py +520 -0
- dtSpark/database/credential_prompt.py +218 -0
- dtSpark/database/files.py +205 -0
- dtSpark/database/mcp_ops.py +355 -0
- dtSpark/database/messages.py +161 -0
- dtSpark/database/schema.py +673 -0
- dtSpark/database/tool_permissions.py +186 -0
- dtSpark/database/usage.py +167 -0
- dtSpark/files/__init__.py +4 -0
- dtSpark/files/manager.py +322 -0
- dtSpark/launch.py +39 -0
- dtSpark/limits/__init__.py +10 -0
- dtSpark/limits/costs.py +296 -0
- dtSpark/limits/tokens.py +342 -0
- dtSpark/llm/__init__.py +17 -0
- dtSpark/llm/anthropic_direct.py +446 -0
- dtSpark/llm/base.py +146 -0
- dtSpark/llm/context_limits.py +438 -0
- dtSpark/llm/manager.py +177 -0
- dtSpark/llm/ollama.py +578 -0
- dtSpark/mcp_integration/__init__.py +5 -0
- dtSpark/mcp_integration/manager.py +653 -0
- dtSpark/mcp_integration/tool_selector.py +225 -0
- dtSpark/resources/config.yaml.template +631 -0
- dtSpark/safety/__init__.py +22 -0
- dtSpark/safety/llm_service.py +111 -0
- dtSpark/safety/patterns.py +229 -0
- dtSpark/safety/prompt_inspector.py +442 -0
- dtSpark/safety/violation_logger.py +346 -0
- dtSpark/scheduler/__init__.py +20 -0
- dtSpark/scheduler/creation_tools.py +599 -0
- dtSpark/scheduler/execution_queue.py +159 -0
- dtSpark/scheduler/executor.py +1152 -0
- dtSpark/scheduler/manager.py +395 -0
- dtSpark/tools/__init__.py +4 -0
- dtSpark/tools/builtin.py +833 -0
- dtSpark/web/__init__.py +20 -0
- dtSpark/web/auth.py +152 -0
- dtSpark/web/dependencies.py +37 -0
- dtSpark/web/endpoints/__init__.py +17 -0
- dtSpark/web/endpoints/autonomous_actions.py +1125 -0
- dtSpark/web/endpoints/chat.py +621 -0
- dtSpark/web/endpoints/conversations.py +353 -0
- dtSpark/web/endpoints/main_menu.py +547 -0
- dtSpark/web/endpoints/streaming.py +421 -0
- dtSpark/web/server.py +578 -0
- dtSpark/web/session.py +167 -0
- dtSpark/web/ssl_utils.py +195 -0
- dtSpark/web/static/css/dark-theme.css +427 -0
- dtSpark/web/static/js/actions.js +1101 -0
- dtSpark/web/static/js/chat.js +614 -0
- dtSpark/web/static/js/main.js +496 -0
- dtSpark/web/static/js/sse-client.js +242 -0
- dtSpark/web/templates/actions.html +408 -0
- dtSpark/web/templates/base.html +93 -0
- dtSpark/web/templates/chat.html +814 -0
- dtSpark/web/templates/conversations.html +350 -0
- dtSpark/web/templates/goodbye.html +81 -0
- dtSpark/web/templates/login.html +90 -0
- dtSpark/web/templates/main_menu.html +983 -0
- dtSpark/web/templates/new_conversation.html +191 -0
- dtSpark/web/web_interface.py +137 -0
- dtspark-1.0.4.dist-info/METADATA +187 -0
- dtspark-1.0.4.dist-info/RECORD +96 -0
- dtspark-1.0.4.dist-info/WHEEL +5 -0
- dtspark-1.0.4.dist-info/entry_points.txt +3 -0
- dtspark-1.0.4.dist-info/licenses/LICENSE +21 -0
- dtspark-1.0.4.dist-info/top_level.txt +1 -0
dtSpark/__init__.py
ADDED
|
File without changes
|
dtSpark/_description.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Spark is a powerful, multi-provider LLM interface for conversational AI with integrated tool support. It supports AWS Bedrock, Anthropic Direct API, and Ollama local models through both CLI and Web interfaces.
|
dtSpark/_full_name.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Secure Personal AI Research Kit
|
dtSpark/_licence.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Digital-Thought
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
dtSpark/_metadata.yaml
ADDED
dtSpark/_name.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dtSpark
|
dtSpark/_version.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.4
|
dtSpark/aws/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""AWS integration module."""
|
|
2
|
+
from .authentication import AWSAuthenticator
|
|
3
|
+
from .bedrock import BedrockService
|
|
4
|
+
from .pricing import BedrockPricing
|
|
5
|
+
from .costs import CostTracker
|
|
6
|
+
|
|
7
|
+
__all__ = ['AWSAuthenticator', 'BedrockService', 'BedrockPricing', 'CostTracker']
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AWS authentication module for handling SSO login.
|
|
3
|
+
|
|
4
|
+
This module provides functionality for:
|
|
5
|
+
- AWS SSO authentication
|
|
6
|
+
- Session credential management
|
|
7
|
+
- Profile configuration
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import boto3
|
|
11
|
+
import logging
|
|
12
|
+
import subprocess
|
|
13
|
+
from typing import Optional
|
|
14
|
+
from botocore.config import Config
|
|
15
|
+
from botocore.exceptions import ClientError, ProfileNotFound, NoCredentialsError
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AWSAuthenticator:
|
|
19
|
+
"""Handles AWS authentication via SSO or API keys."""
|
|
20
|
+
|
|
21
|
+
def __init__(self, profile_name: Optional[str] = None, region: Optional[str] = None,
|
|
22
|
+
bedrock_request_timeout: int = 300,
|
|
23
|
+
access_key_id: Optional[str] = None,
|
|
24
|
+
secret_access_key: Optional[str] = None,
|
|
25
|
+
session_token: Optional[str] = None):
|
|
26
|
+
"""
|
|
27
|
+
Initialise the AWS authenticator.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
profile_name: AWS SSO profile name (defaults to 'default')
|
|
31
|
+
region: AWS region (defaults to us-east-1)
|
|
32
|
+
bedrock_request_timeout: Timeout in seconds for Bedrock Runtime requests (defaults to 300 seconds / 5 minutes)
|
|
33
|
+
access_key_id: AWS access key ID (for API key authentication)
|
|
34
|
+
secret_access_key: AWS secret access key (for API key authentication)
|
|
35
|
+
session_token: AWS session token (optional, for temporary credentials)
|
|
36
|
+
"""
|
|
37
|
+
self.profile_name = profile_name or 'default'
|
|
38
|
+
self.region = region or 'us-east-1'
|
|
39
|
+
self.bedrock_request_timeout = bedrock_request_timeout
|
|
40
|
+
self.access_key_id = access_key_id
|
|
41
|
+
self.secret_access_key = secret_access_key
|
|
42
|
+
self.session_token = session_token
|
|
43
|
+
self.session = None
|
|
44
|
+
self._credentials_valid = False
|
|
45
|
+
self._auth_method = None # Track which method was used: 'api_keys' or 'sso'
|
|
46
|
+
|
|
47
|
+
def authenticate(self) -> bool:
|
|
48
|
+
"""
|
|
49
|
+
Authenticate with AWS using API keys or SSO profile.
|
|
50
|
+
|
|
51
|
+
Priority:
|
|
52
|
+
1. If API keys are provided, use them
|
|
53
|
+
2. Otherwise, use SSO profile
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
True if authentication successful, False otherwise
|
|
57
|
+
"""
|
|
58
|
+
# Check if API keys are provided
|
|
59
|
+
if self.access_key_id and self.secret_access_key:
|
|
60
|
+
return self._authenticate_with_api_keys()
|
|
61
|
+
else:
|
|
62
|
+
return self._authenticate_with_sso()
|
|
63
|
+
|
|
64
|
+
def _authenticate_with_api_keys(self) -> bool:
|
|
65
|
+
"""
|
|
66
|
+
Authenticate using AWS API keys.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
True if authentication successful, False otherwise
|
|
70
|
+
"""
|
|
71
|
+
try:
|
|
72
|
+
logging.info("Attempting authentication with API keys")
|
|
73
|
+
|
|
74
|
+
# Create a session with explicit credentials
|
|
75
|
+
self.session = boto3.Session(
|
|
76
|
+
aws_access_key_id=self.access_key_id,
|
|
77
|
+
aws_secret_access_key=self.secret_access_key,
|
|
78
|
+
aws_session_token=self.session_token, # Optional, may be None
|
|
79
|
+
region_name=self.region
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Test credentials by making a simple API call
|
|
83
|
+
sts_client = self.session.client('sts')
|
|
84
|
+
identity = sts_client.get_caller_identity()
|
|
85
|
+
|
|
86
|
+
logging.info(f"Successfully authenticated with API keys as: {identity['Arn']}")
|
|
87
|
+
logging.info(f"Account ID: {identity['Account']}")
|
|
88
|
+
self._credentials_valid = True
|
|
89
|
+
self._auth_method = 'api_keys'
|
|
90
|
+
return True
|
|
91
|
+
|
|
92
|
+
except NoCredentialsError:
|
|
93
|
+
logging.error("Invalid AWS credentials (API keys)")
|
|
94
|
+
logging.error("Please check your access key ID and secret access key")
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
except ClientError as e:
|
|
98
|
+
error_code = e.response.get('Error', {}).get('Code', 'Unknown')
|
|
99
|
+
if error_code == 'InvalidClientTokenId':
|
|
100
|
+
logging.error("Invalid AWS access key ID")
|
|
101
|
+
elif error_code == 'SignatureDoesNotMatch':
|
|
102
|
+
logging.error("Invalid AWS secret access key")
|
|
103
|
+
elif error_code == 'ExpiredToken':
|
|
104
|
+
logging.error("AWS session token has expired")
|
|
105
|
+
logging.error("Please obtain new temporary credentials")
|
|
106
|
+
else:
|
|
107
|
+
logging.error(f"AWS authentication with API keys failed: {e}")
|
|
108
|
+
return False
|
|
109
|
+
|
|
110
|
+
except Exception as e:
|
|
111
|
+
logging.error(f"Unexpected error during API key authentication: {e}")
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
def _authenticate_with_sso(self) -> bool:
|
|
115
|
+
"""
|
|
116
|
+
Authenticate using AWS SSO profile.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
True if authentication successful, False otherwise
|
|
120
|
+
"""
|
|
121
|
+
try:
|
|
122
|
+
logging.info(f"Attempting authentication with SSO profile '{self.profile_name}'")
|
|
123
|
+
|
|
124
|
+
# Create a session with the specified profile
|
|
125
|
+
self.session = boto3.Session(
|
|
126
|
+
profile_name=self.profile_name,
|
|
127
|
+
region_name=self.region
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Test credentials by making a simple API call
|
|
131
|
+
sts_client = self.session.client('sts')
|
|
132
|
+
identity = sts_client.get_caller_identity()
|
|
133
|
+
|
|
134
|
+
logging.info(f"Successfully authenticated with SSO as: {identity['Arn']}")
|
|
135
|
+
logging.info(f"Account ID: {identity['Account']}")
|
|
136
|
+
self._credentials_valid = True
|
|
137
|
+
self._auth_method = 'sso'
|
|
138
|
+
return True
|
|
139
|
+
|
|
140
|
+
except ProfileNotFound:
|
|
141
|
+
logging.error(f"AWS profile '{self.profile_name}' not found")
|
|
142
|
+
logging.error("Please configure your AWS SSO profile using 'aws configure sso'")
|
|
143
|
+
return False
|
|
144
|
+
|
|
145
|
+
except NoCredentialsError:
|
|
146
|
+
logging.error("No AWS credentials found")
|
|
147
|
+
logging.error("Please configure your AWS credentials or SSO profile")
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
except ClientError as e:
|
|
151
|
+
error_code = e.response.get('Error', {}).get('Code', 'Unknown')
|
|
152
|
+
if error_code == 'ExpiredToken':
|
|
153
|
+
logging.error("AWS session token has expired")
|
|
154
|
+
logging.error(f"Please re-authenticate using: aws sso login --profile {self.profile_name}")
|
|
155
|
+
else:
|
|
156
|
+
logging.error(f"AWS authentication failed: {e}")
|
|
157
|
+
return False
|
|
158
|
+
|
|
159
|
+
except Exception as e:
|
|
160
|
+
error_str = str(e)
|
|
161
|
+
# Check if this is an SSO token expiration error
|
|
162
|
+
if 'Token has expired' in error_str or 'refresh failed' in error_str:
|
|
163
|
+
logging.warning("AWS SSO token has expired")
|
|
164
|
+
logging.info(f"Attempting automatic re-authentication...")
|
|
165
|
+
|
|
166
|
+
# Try to trigger SSO login automatically
|
|
167
|
+
if self.trigger_sso_login():
|
|
168
|
+
logging.info("SSO login successful, retrying authentication...")
|
|
169
|
+
# Retry authentication after successful login
|
|
170
|
+
return self._authenticate_with_sso()
|
|
171
|
+
else:
|
|
172
|
+
logging.error("Automatic SSO login failed")
|
|
173
|
+
logging.error(f"Please manually re-authenticate: aws sso login --profile {self.profile_name}")
|
|
174
|
+
return False
|
|
175
|
+
else:
|
|
176
|
+
logging.error(f"Unexpected error during authentication: {e}")
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
def trigger_sso_login(self) -> bool:
|
|
180
|
+
"""
|
|
181
|
+
Trigger AWS SSO login process by calling the AWS CLI.
|
|
182
|
+
This will open the default browser for authentication.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
True if SSO login succeeded, False otherwise
|
|
186
|
+
"""
|
|
187
|
+
try:
|
|
188
|
+
logging.info(f"Initiating AWS SSO login for profile '{self.profile_name}'")
|
|
189
|
+
|
|
190
|
+
# Run aws sso login command with inherited stdin/stdout/stderr
|
|
191
|
+
# This allows the browser to open and the user to see the output
|
|
192
|
+
result = subprocess.run(
|
|
193
|
+
['aws', 'sso', 'login', '--profile', self.profile_name],
|
|
194
|
+
timeout=300 # 5 minute timeout for login process
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
if result.returncode == 0:
|
|
198
|
+
logging.info("AWS SSO login completed successfully")
|
|
199
|
+
return True
|
|
200
|
+
else:
|
|
201
|
+
logging.error(f"AWS SSO login failed with return code: {result.returncode}")
|
|
202
|
+
return False
|
|
203
|
+
|
|
204
|
+
except subprocess.TimeoutExpired:
|
|
205
|
+
logging.error("AWS SSO login timed out")
|
|
206
|
+
return False
|
|
207
|
+
except FileNotFoundError:
|
|
208
|
+
logging.error("AWS CLI not found. Please ensure AWS CLI is installed and in your PATH")
|
|
209
|
+
return False
|
|
210
|
+
except Exception as e:
|
|
211
|
+
logging.error(f"Error during SSO login: {e}")
|
|
212
|
+
return False
|
|
213
|
+
|
|
214
|
+
def get_session(self) -> Optional[boto3.Session]:
|
|
215
|
+
"""
|
|
216
|
+
Get the authenticated boto3 session.
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
Boto3 session if authenticated, None otherwise
|
|
220
|
+
"""
|
|
221
|
+
if not self._credentials_valid:
|
|
222
|
+
logging.warning("Credentials not valid, please authenticate first")
|
|
223
|
+
return None
|
|
224
|
+
return self.session
|
|
225
|
+
|
|
226
|
+
def get_client(self, service_name: str):
|
|
227
|
+
"""
|
|
228
|
+
Get a boto3 client for a specific AWS service.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
service_name: Name of the AWS service (e.g., 'bedrock', 's3')
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Boto3 client for the specified service
|
|
235
|
+
"""
|
|
236
|
+
if not self._credentials_valid:
|
|
237
|
+
raise ValueError("Not authenticated. Please call authenticate() first")
|
|
238
|
+
|
|
239
|
+
# Configure timeouts based on service type
|
|
240
|
+
# Bedrock Runtime needs longer timeouts for AI model inference (especially with tools)
|
|
241
|
+
if service_name == 'bedrock-runtime':
|
|
242
|
+
read_timeout = self.bedrock_request_timeout # Configurable timeout for AI model inference
|
|
243
|
+
else:
|
|
244
|
+
read_timeout = 120 # 2 minutes for standard AWS services
|
|
245
|
+
|
|
246
|
+
config = Config(
|
|
247
|
+
read_timeout=read_timeout,
|
|
248
|
+
connect_timeout=10, # 10 seconds for connection
|
|
249
|
+
retries={'max_attempts': 3, 'mode': 'standard'}
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
return self.session.client(service_name, config=config)
|
|
253
|
+
|
|
254
|
+
def is_authenticated(self) -> bool:
|
|
255
|
+
"""
|
|
256
|
+
Check if currently authenticated.
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
True if authenticated, False otherwise
|
|
260
|
+
"""
|
|
261
|
+
return self._credentials_valid
|
|
262
|
+
|
|
263
|
+
def get_account_info(self) -> Optional[dict]:
|
|
264
|
+
"""
|
|
265
|
+
Get information about the authenticated AWS account.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
Dictionary with account information or None if not authenticated
|
|
269
|
+
"""
|
|
270
|
+
if not self._credentials_valid:
|
|
271
|
+
return None
|
|
272
|
+
|
|
273
|
+
try:
|
|
274
|
+
sts_client = self.session.client('sts')
|
|
275
|
+
identity = sts_client.get_caller_identity()
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
'account_id': identity['Account'],
|
|
279
|
+
'user_arn': identity['Arn'],
|
|
280
|
+
'user_id': identity['UserId'],
|
|
281
|
+
'region': self.region,
|
|
282
|
+
'profile': self.profile_name,
|
|
283
|
+
'auth_method': self._auth_method # Add authentication method
|
|
284
|
+
}
|
|
285
|
+
except Exception as e:
|
|
286
|
+
logging.error(f"Failed to retrieve account info: {e}")
|
|
287
|
+
return None
|
|
288
|
+
|
|
289
|
+
def get_auth_method(self) -> Optional[str]:
|
|
290
|
+
"""
|
|
291
|
+
Get the authentication method used.
|
|
292
|
+
|
|
293
|
+
Returns:
|
|
294
|
+
'api_keys' or 'sso', or None if not authenticated
|
|
295
|
+
"""
|
|
296
|
+
return self._auth_method
|