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,350 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Conversations - {{ app_name }}{% endblock %}
4
+
5
+ {% block extra_head %}
6
+ <style>
7
+ .list-group-item .flex-grow-1:hover {
8
+ background-color: rgba(0, 123, 255, 0.05);
9
+ border-radius: 0.25rem;
10
+ }
11
+ .list-group-item {
12
+ transition: background-color 0.2s ease;
13
+ }
14
+ </style>
15
+ {% endblock %}
16
+
17
+ {% block content %}
18
+ <div class="row">
19
+ <div class="col-12">
20
+ <h2 class="mb-4">
21
+ <i class="bi bi-list-ul"></i> Conversations
22
+ <button class="btn btn-primary float-end" onclick="showNewConversationModal()">
23
+ <i class="bi bi-plus-circle-fill"></i> New Conversation
24
+ </button>
25
+ </h2>
26
+ </div>
27
+ </div>
28
+
29
+ <!-- Conversations List -->
30
+ <div class="row">
31
+ <div class="col-12">
32
+ <div class="card">
33
+ <div class="card-body" id="conversations-list">
34
+ <div class="text-center">
35
+ <div class="spinner-border text-primary" role="status">
36
+ <span class="visually-hidden">Loading...</span>
37
+ </div>
38
+ <p class="mt-2">Loading conversations...</p>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ <!-- Delete Confirmation Modal -->
46
+ <div class="modal fade" id="deleteConversationModal" tabindex="-1">
47
+ <div class="modal-dialog">
48
+ <div class="modal-content">
49
+ <div class="modal-header">
50
+ <h5 class="modal-title"><i class="bi bi-exclamation-triangle-fill text-danger"></i> Delete Conversation</h5>
51
+ <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
52
+ </div>
53
+ <div class="modal-body">
54
+ <p>Are you sure you want to delete this conversation?</p>
55
+ <p class="mb-0"><strong id="delete-conversation-name"></strong></p>
56
+ <p class="text-danger small mt-2">
57
+ <i class="bi bi-exclamation-circle"></i> This action cannot be undone. All messages and conversation history will be permanently deleted.
58
+ </p>
59
+ </div>
60
+ <div class="modal-footer">
61
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
62
+ Cancel
63
+ </button>
64
+ <button type="button" class="btn btn-danger" id="confirm-delete-btn" onclick="confirmDelete()">
65
+ <i class="bi bi-trash-fill"></i> Delete Conversation
66
+ </button>
67
+ </div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+
72
+ <!-- New Conversation Modal -->
73
+ <div class="modal fade" id="newConversationModal" tabindex="-1">
74
+ <div class="modal-dialog modal-lg">
75
+ <div class="modal-content">
76
+ <div class="modal-header">
77
+ <h5 class="modal-title"><i class="bi bi-plus-circle-fill"></i> New Conversation</h5>
78
+ <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
79
+ </div>
80
+ <div class="modal-body">
81
+ <form id="new-conversation-form">
82
+ <div class="mb-3">
83
+ <label for="conversation-name" class="form-label">Conversation Name</label>
84
+ <input
85
+ type="text"
86
+ class="form-control"
87
+ id="conversation-name"
88
+ name="name"
89
+ placeholder="Enter a name for this conversation"
90
+ required
91
+ >
92
+ </div>
93
+
94
+ <div class="mb-3">
95
+ <label for="model-select" class="form-label">Model</label>
96
+ <select class="form-select" id="model-select" name="model_id" required>
97
+ <option value="">Loading models...</option>
98
+ </select>
99
+ </div>
100
+
101
+ <div class="mb-3">
102
+ <label for="instructions" class="form-label">
103
+ Instructions / System Prompt
104
+ <span class="text-muted">(Optional)</span>
105
+ </label>
106
+ <textarea
107
+ class="form-control"
108
+ id="instructions"
109
+ name="instructions"
110
+ rows="4"
111
+ placeholder="Enter system instructions for this conversation..."
112
+ ></textarea>
113
+ </div>
114
+
115
+ <div class="mb-3">
116
+ <label for="file-attachments" class="form-label">
117
+ File Attachments
118
+ <span class="text-muted">(Optional)</span>
119
+ </label>
120
+ <input
121
+ class="form-control"
122
+ type="file"
123
+ id="file-attachments"
124
+ name="files"
125
+ multiple
126
+ >
127
+ <div class="form-text">
128
+ Supported: txt, md, json, yaml, xml, csv, log, py, js, ts, java, cpp, c, h
129
+ </div>
130
+ </div>
131
+ </form>
132
+ </div>
133
+ <div class="modal-footer">
134
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
135
+ Cancel
136
+ </button>
137
+ <button type="button" class="btn btn-primary" onclick="createConversation()">
138
+ <i class="bi bi-check-circle-fill"></i> Create Conversation
139
+ </button>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </div>
144
+ {% endblock %}
145
+
146
+ {% block extra_scripts %}
147
+ <script>
148
+ // Load conversations on page load
149
+ window.addEventListener('load', () => {
150
+ loadConversations();
151
+ });
152
+
153
+ // Load conversations
154
+ async function loadConversations() {
155
+ try {
156
+ const response = await fetch('/api/conversations');
157
+ const conversations = await response.json();
158
+
159
+ if (conversations.length === 0) {
160
+ document.getElementById('conversations-list').innerHTML = `
161
+ <div class="text-center text-muted">
162
+ <i class="bi bi-inbox" style="font-size: 3rem;"></i>
163
+ <p class="mt-3">No conversations yet</p>
164
+ <button class="btn btn-primary" onclick="showNewConversationModal()">
165
+ <i class="bi bi-plus-circle-fill"></i> Create Your First Conversation
166
+ </button>
167
+ </div>
168
+ `;
169
+ return;
170
+ }
171
+
172
+ let html = '<div class="list-group">';
173
+ conversations.forEach(conv => {
174
+ const createdDate = new Date(conv.created_at).toLocaleString();
175
+ const lastMessageDate = conv.last_message_at ?
176
+ new Date(conv.last_message_at).toLocaleString() :
177
+ 'No messages yet';
178
+
179
+ html += `
180
+ <div class="list-group-item">
181
+ <div class="d-flex w-100 justify-content-between align-items-start">
182
+ <div class="flex-grow-1" style="cursor: pointer;" onclick="window.location.href='/chat/${conv.id}'">
183
+ <h6 class="mb-1">
184
+ <i class="bi bi-chat-dots"></i> ${conv.name}
185
+ </h6>
186
+ <p class="mb-1 small">
187
+ <strong>Model:</strong> <code>${conv.model_id}</code>
188
+ </p>
189
+ <small class="text-muted">
190
+ Created: ${createdDate} | Last message: ${lastMessageDate}
191
+ </small>
192
+ </div>
193
+ <div class="d-flex flex-column align-items-end ms-3">
194
+ <small class="text-muted mb-2">${conv.message_count} messages</small>
195
+ <button class="btn btn-sm btn-outline-danger" onclick="deleteConversation(${conv.id}, '${conv.name.replace(/'/g, "\\'")}')">
196
+ <i class="bi bi-trash"></i> Delete
197
+ </button>
198
+ </div>
199
+ </div>
200
+ </div>
201
+ `;
202
+ });
203
+ html += '</div>';
204
+
205
+ document.getElementById('conversations-list').innerHTML = html;
206
+
207
+ } catch (error) {
208
+ document.getElementById('conversations-list').innerHTML = `
209
+ <div class="alert alert-danger">
210
+ <i class="bi bi-exclamation-triangle-fill"></i> Failed to load conversations
211
+ </div>
212
+ `;
213
+ }
214
+ }
215
+
216
+ // Show new conversation modal
217
+ async function showNewConversationModal() {
218
+ // Load available models
219
+ await loadModels();
220
+
221
+ const modal = new bootstrap.Modal(document.getElementById('newConversationModal'));
222
+ modal.show();
223
+ }
224
+
225
+ // Load available models
226
+ async function loadModels() {
227
+ try {
228
+ const response = await fetch('/api/models');
229
+ const models = await response.json();
230
+
231
+ const select = document.getElementById('model-select');
232
+ select.innerHTML = '<option value="">Select a model...</option>';
233
+
234
+ models.forEach(model => {
235
+ const option = document.createElement('option');
236
+ option.value = model.id;
237
+
238
+ // Show service provider and optionally model maker
239
+ let displayText = model.name;
240
+ if (model.model_maker && model.provider !== model.model_maker) {
241
+ // Show both: "Model Name [Model Maker via Service Provider]"
242
+ displayText += ` [${model.model_maker} via ${model.provider}]`;
243
+ } else {
244
+ // Show service only: "Model Name [Service Provider]"
245
+ displayText += ` [${model.provider}]`;
246
+ }
247
+
248
+ option.textContent = displayText;
249
+ select.appendChild(option);
250
+ });
251
+
252
+ } catch (error) {
253
+ document.getElementById('model-select').innerHTML = `
254
+ <option value="">Failed to load models</option>
255
+ `;
256
+ }
257
+ }
258
+
259
+ // Create conversation
260
+ async function createConversation() {
261
+ const form = document.getElementById('new-conversation-form');
262
+ const formData = new FormData(form);
263
+
264
+ try {
265
+ // Disable button
266
+ event.target.disabled = true;
267
+ event.target.innerHTML = '<i class="bi bi-hourglass-split"></i> Creating...';
268
+
269
+ const response = await fetch('/api/conversations', {
270
+ method: 'POST',
271
+ body: formData
272
+ });
273
+
274
+ if (!response.ok) {
275
+ throw new Error('Failed to create conversation');
276
+ }
277
+
278
+ const conversation = await response.json();
279
+
280
+ // Close modal
281
+ bootstrap.Modal.getInstance(document.getElementById('newConversationModal')).hide();
282
+
283
+ // Redirect to chat
284
+ window.location.href = `/chat/${conversation.id}`;
285
+
286
+ } catch (error) {
287
+ alert('Failed to create conversation: ' + error.message);
288
+
289
+ // Re-enable button
290
+ event.target.disabled = false;
291
+ event.target.innerHTML = '<i class="bi bi-check-circle-fill"></i> Create Conversation';
292
+ }
293
+ }
294
+
295
+ // Global variable to store conversation to delete
296
+ let conversationToDelete = null;
297
+
298
+ // Show delete confirmation modal
299
+ function deleteConversation(conversationId, conversationName) {
300
+ conversationToDelete = conversationId;
301
+ document.getElementById('delete-conversation-name').textContent = conversationName;
302
+
303
+ const modal = new bootstrap.Modal(document.getElementById('deleteConversationModal'));
304
+ modal.show();
305
+ }
306
+
307
+ // Confirm and execute deletion
308
+ async function confirmDelete() {
309
+ if (!conversationToDelete) {
310
+ return;
311
+ }
312
+
313
+ const deleteBtn = document.getElementById('confirm-delete-btn');
314
+
315
+ try {
316
+ // Disable button
317
+ deleteBtn.disabled = true;
318
+ deleteBtn.innerHTML = '<i class="bi bi-hourglass-split"></i> Deleting...';
319
+
320
+ const response = await fetch(`/api/conversations/${conversationToDelete}`, {
321
+ method: 'DELETE'
322
+ });
323
+
324
+ if (!response.ok) {
325
+ throw new Error('Failed to delete conversation');
326
+ }
327
+
328
+ // Close modal
329
+ bootstrap.Modal.getInstance(document.getElementById('deleteConversationModal')).hide();
330
+
331
+ // Reset button state
332
+ deleteBtn.disabled = false;
333
+ deleteBtn.innerHTML = '<i class="bi bi-trash-fill"></i> Delete Conversation';
334
+
335
+ // Clear conversation to delete
336
+ conversationToDelete = null;
337
+
338
+ // Reload conversations list
339
+ await loadConversations();
340
+
341
+ } catch (error) {
342
+ alert('Failed to delete conversation: ' + error.message);
343
+
344
+ // Re-enable button
345
+ deleteBtn.disabled = false;
346
+ deleteBtn.innerHTML = '<i class="bi bi-trash-fill"></i> Delete Conversation';
347
+ }
348
+ }
349
+ </script>
350
+ {% endblock %}
@@ -0,0 +1,81 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Thank You - {{ app_name }}{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="row justify-content-center">
7
+ <div class="col-md-8 col-lg-6">
8
+ <div class="card mt-5 border-success">
9
+ <div class="card-body text-center py-5">
10
+ <div class="mb-4">
11
+ <i class="bi bi-check-circle-fill text-success" style="font-size: 4rem;"></i>
12
+ </div>
13
+
14
+ <h2 class="card-title mb-4">
15
+ {% if shutdown %}
16
+ <i class="bi bi-power"></i> Shutting Down
17
+ {% else %}
18
+ <i class="bi bi-wave"></i> Session Ended
19
+ {% endif %}
20
+ </h2>
21
+
22
+ <p class="lead mb-4">
23
+ Thank you for using Spark!
24
+ </p>
25
+
26
+ {% if shutdown %}
27
+ <div class="alert alert-info">
28
+ <i class="bi bi-info-circle-fill"></i> The web server is shutting down...
29
+ <div class="mt-2">
30
+ <div class="spinner-border spinner-border-sm" role="status">
31
+ <span class="visually-hidden">Shutting down...</span>
32
+ </div>
33
+ <span class="ms-2">Please wait</span>
34
+ </div>
35
+ </div>
36
+
37
+ <p class="text-muted small mt-4">
38
+ You can close this browser window. The CLI will return to the command prompt.
39
+ </p>
40
+ {% else %}
41
+ <div class="alert alert-success">
42
+ <i class="bi bi-check-circle-fill"></i> Your session has been logged out successfully
43
+ </div>
44
+
45
+ <p class="text-muted small mt-4">
46
+ The web server is still running. You can close this window or
47
+ <a href="/login" class="alert-link">log in again</a>.
48
+ </p>
49
+ {% endif %}
50
+
51
+ <hr class="my-4">
52
+
53
+ <div class="text-muted small">
54
+ <i class="bi bi-chat-dots-fill"></i> SPARK
55
+ <br>
56
+ <span class="text-muted" style="font-size: 0.85em;">
57
+ Secure Personal AI Research Kit
58
+ </span>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ {% endblock %}
65
+
66
+ {% block extra_scripts %}
67
+ {% if shutdown %}
68
+ <script>
69
+ // Trigger server shutdown after a short delay
70
+ setTimeout(function() {
71
+ fetch('/api/shutdown', { method: 'POST' })
72
+ .then(() => {
73
+ console.log('Shutdown request sent');
74
+ })
75
+ .catch((error) => {
76
+ console.error('Shutdown request failed:', error);
77
+ });
78
+ }, 1000);
79
+ </script>
80
+ {% endif %}
81
+ {% endblock %}
@@ -0,0 +1,90 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Login - {{ app_name }}{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="row justify-content-center">
7
+ <div class="col-md-6 col-lg-4">
8
+ <div class="card mt-5">
9
+ <div class="card-body">
10
+ <h3 class="card-title text-center mb-4">
11
+ <i class="bi bi-shield-lock-fill"></i> Authentication Required
12
+ </h3>
13
+
14
+ {% if error %}
15
+ <div class="alert alert-danger" role="alert">
16
+ <i class="bi bi-exclamation-triangle-fill"></i> {{ error }}
17
+ </div>
18
+ {% endif %}
19
+
20
+ <p class="text-muted text-center mb-4">
21
+ Enter the authentication code displayed in the CLI to access the web interface.
22
+ </p>
23
+
24
+ <form method="POST" action="/login">
25
+ <div class="mb-3">
26
+ <label for="code" class="form-label">Authentication Code</label>
27
+ <input
28
+ type="text"
29
+ class="form-control form-control-lg text-center"
30
+ id="code"
31
+ name="code"
32
+ placeholder="Enter code"
33
+ required
34
+ autofocus
35
+ style="letter-spacing: 0.2em; font-family: monospace;"
36
+ value="{{ code }}"
37
+ >
38
+ <div class="form-text">
39
+ <i class="bi bi-info-circle"></i> This code can only be used once
40
+ </div>
41
+ </div>
42
+
43
+ <div class="d-grid">
44
+ <button type="submit" class="btn btn-primary btn-lg">
45
+ <i class="bi bi-key-fill"></i> Authenticate
46
+ </button>
47
+ </div>
48
+ </form>
49
+
50
+ <hr class="my-4">
51
+
52
+ <div class="text-center text-muted small">
53
+ <i class="bi bi-shield-check"></i> Localhost only - Single session
54
+ </div>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="text-center mt-3 text-muted small">
59
+ <i class="bi bi-info-circle"></i> The authentication code is displayed when you start the web interface from the CLI
60
+ </div>
61
+ </div>
62
+ </div>
63
+ {% endblock %}
64
+
65
+ {% block extra_scripts %}
66
+ <script>
67
+ // Auto-focus on code input
68
+ document.getElementById('code').focus();
69
+
70
+ // Auto-capitalise input
71
+ document.getElementById('code').addEventListener('input', function(e) {
72
+ e.target.value = e.target.value.toUpperCase();
73
+ });
74
+
75
+ // Auto-submit if code is pre-filled from URL
76
+ document.addEventListener('DOMContentLoaded', function() {
77
+ const codeInput = document.getElementById('code');
78
+ const form = codeInput.closest('form');
79
+
80
+ // Check if code is pre-filled and non-empty
81
+ if (codeInput.value && codeInput.value.trim() !== '') {
82
+ console.log('Code pre-filled from URL, auto-submitting form');
83
+ // Add a small delay to let the user see the page loaded
84
+ setTimeout(function() {
85
+ form.submit();
86
+ }, 500);
87
+ }
88
+ });
89
+ </script>
90
+ {% endblock %}