dtSpark 1.1.0a2__py3-none-any.whl → 1.1.0a6__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/_version.txt +1 -1
- dtSpark/aws/authentication.py +1 -1
- dtSpark/aws/bedrock.py +238 -239
- dtSpark/aws/costs.py +9 -5
- dtSpark/aws/pricing.py +25 -21
- dtSpark/cli_interface.py +69 -62
- dtSpark/conversation_manager.py +54 -47
- dtSpark/core/application.py +151 -111
- dtSpark/core/context_compaction.py +241 -226
- dtSpark/daemon/__init__.py +36 -22
- dtSpark/daemon/action_monitor.py +46 -17
- dtSpark/daemon/daemon_app.py +126 -104
- dtSpark/daemon/daemon_manager.py +59 -23
- dtSpark/daemon/pid_file.py +3 -2
- dtSpark/database/autonomous_actions.py +3 -0
- dtSpark/database/credential_prompt.py +52 -54
- dtSpark/files/manager.py +6 -12
- dtSpark/limits/__init__.py +1 -1
- dtSpark/limits/tokens.py +2 -2
- dtSpark/llm/anthropic_direct.py +246 -141
- dtSpark/llm/ollama.py +3 -1
- dtSpark/mcp_integration/manager.py +4 -4
- dtSpark/mcp_integration/tool_selector.py +83 -77
- dtSpark/resources/config.yaml.template +10 -0
- dtSpark/safety/patterns.py +45 -46
- dtSpark/safety/prompt_inspector.py +8 -1
- dtSpark/scheduler/creation_tools.py +273 -181
- dtSpark/scheduler/executor.py +503 -221
- dtSpark/tools/builtin.py +70 -53
- dtSpark/web/endpoints/autonomous_actions.py +12 -9
- dtSpark/web/endpoints/chat.py +18 -6
- dtSpark/web/endpoints/conversations.py +57 -17
- dtSpark/web/endpoints/main_menu.py +132 -105
- dtSpark/web/endpoints/streaming.py +2 -2
- dtSpark/web/server.py +65 -5
- dtSpark/web/ssl_utils.py +3 -3
- dtSpark/web/static/css/dark-theme.css +8 -29
- dtSpark/web/static/js/actions.js +2 -1
- dtSpark/web/static/js/chat.js +6 -8
- dtSpark/web/static/js/main.js +8 -8
- dtSpark/web/static/js/sse-client.js +130 -122
- dtSpark/web/templates/actions.html +5 -5
- dtSpark/web/templates/base.html +13 -0
- dtSpark/web/templates/chat.html +52 -50
- dtSpark/web/templates/conversations.html +50 -22
- dtSpark/web/templates/goodbye.html +2 -2
- dtSpark/web/templates/main_menu.html +17 -17
- dtSpark/web/templates/new_conversation.html +51 -20
- dtSpark/web/web_interface.py +2 -2
- {dtspark-1.1.0a2.dist-info → dtspark-1.1.0a6.dist-info}/METADATA +9 -2
- dtspark-1.1.0a6.dist-info/RECORD +96 -0
- dtspark-1.1.0a2.dist-info/RECORD +0 -96
- {dtspark-1.1.0a2.dist-info → dtspark-1.1.0a6.dist-info}/WHEEL +0 -0
- {dtspark-1.1.0a2.dist-info → dtspark-1.1.0a6.dist-info}/entry_points.txt +0 -0
- {dtspark-1.1.0a2.dist-info → dtspark-1.1.0a6.dist-info}/licenses/LICENSE +0 -0
- {dtspark-1.1.0a2.dist-info → dtspark-1.1.0a6.dist-info}/top_level.txt +0 -0
dtSpark/web/templates/chat.html
CHANGED
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
<div class="card-body overflow-auto" id="chat-messages">
|
|
22
22
|
<!-- Messages will be appended here -->
|
|
23
23
|
<div class="text-center text-muted">
|
|
24
|
-
<
|
|
24
|
+
<output class="spinner-border spinner-border-sm">
|
|
25
25
|
<span class="visually-hidden">Loading...</span>
|
|
26
|
-
</
|
|
26
|
+
</output>
|
|
27
27
|
<span class="ms-2">Loading chat history...</span>
|
|
28
28
|
</div>
|
|
29
29
|
</div>
|
|
@@ -48,14 +48,14 @@
|
|
|
48
48
|
></textarea>
|
|
49
49
|
</div>
|
|
50
50
|
<div class="d-flex justify-content-between align-items-center">
|
|
51
|
-
<
|
|
51
|
+
<fieldset class="btn-group">
|
|
52
52
|
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="showCommandMenu()">
|
|
53
53
|
<i class="bi bi-terminal"></i> Commands
|
|
54
54
|
</button>
|
|
55
55
|
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="attachFiles()">
|
|
56
56
|
<i class="bi bi-paperclip"></i> Attach
|
|
57
57
|
</button>
|
|
58
|
-
</
|
|
58
|
+
</fieldset>
|
|
59
59
|
<button type="submit" class="btn btn-primary" id="send-btn">
|
|
60
60
|
<i class="bi bi-send-fill"></i> Send
|
|
61
61
|
</button>
|
|
@@ -76,9 +76,9 @@
|
|
|
76
76
|
</div>
|
|
77
77
|
<div class="modal-body" id="info-content">
|
|
78
78
|
<div class="text-center">
|
|
79
|
-
<
|
|
79
|
+
<output class="spinner-border spinner-border-sm">
|
|
80
80
|
<span class="visually-hidden">Loading...</span>
|
|
81
|
-
</
|
|
81
|
+
</output>
|
|
82
82
|
</div>
|
|
83
83
|
</div>
|
|
84
84
|
</div>
|
|
@@ -324,70 +324,72 @@ async function performExport() {
|
|
|
324
324
|
|
|
325
325
|
// Change model
|
|
326
326
|
async function showChangeModelModal() {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
327
|
+
// Check if model is locked first
|
|
328
|
+
try {
|
|
329
|
+
const configResponse = await fetch('/api/models');
|
|
330
|
+
const configData = await configResponse.json();
|
|
331
|
+
|
|
332
|
+
if (configData.model_locked) {
|
|
333
|
+
showToast(`Model changing is disabled - model is locked to '${configData.mandatory_model}' via configuration`, 'error');
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const models = configData.models || configData;
|
|
338
|
+
|
|
339
|
+
const modalHTML = `
|
|
340
|
+
<div class="modal fade" id="changeModelModal" tabindex="-1">
|
|
341
|
+
<div class="modal-dialog">
|
|
342
|
+
<div class="modal-content">
|
|
343
|
+
<div class="modal-header">
|
|
344
|
+
<h5 class="modal-title"><i class="bi bi-arrow-repeat"></i> Change Model</h5>
|
|
345
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
346
|
+
</div>
|
|
347
|
+
<div class="modal-body">
|
|
348
|
+
<div class="mb-3">
|
|
349
|
+
<label class="form-label">Select New Model</label>
|
|
350
|
+
<select class="form-select" id="new-model-select">
|
|
351
|
+
<option value="">Select a model...</option>
|
|
352
|
+
</select>
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
<div class="modal-footer">
|
|
356
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
357
|
+
<button type="button" class="btn btn-primary" onclick="performChangeModel()">
|
|
358
|
+
<i class="bi bi-check-circle-fill"></i> Change Model
|
|
359
|
+
</button>
|
|
341
360
|
</div>
|
|
342
|
-
</div>
|
|
343
|
-
<div class="modal-footer">
|
|
344
|
-
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
345
|
-
<button type="button" class="btn btn-primary" onclick="performChangeModel()">
|
|
346
|
-
<i class="bi bi-check-circle-fill"></i> Change Model
|
|
347
|
-
</button>
|
|
348
361
|
</div>
|
|
349
362
|
</div>
|
|
350
363
|
</div>
|
|
351
|
-
|
|
352
|
-
`;
|
|
353
|
-
|
|
354
|
-
// Remove old modal if exists
|
|
355
|
-
const oldModal = document.getElementById('changeModelModal');
|
|
356
|
-
if (oldModal) oldModal.remove();
|
|
364
|
+
`;
|
|
357
365
|
|
|
358
|
-
|
|
366
|
+
// Remove old modal if exists
|
|
367
|
+
const oldModal = document.getElementById('changeModelModal');
|
|
368
|
+
if (oldModal) oldModal.remove();
|
|
359
369
|
|
|
360
|
-
|
|
361
|
-
try {
|
|
362
|
-
const response = await fetch('/api/models');
|
|
363
|
-
const models = await response.json();
|
|
370
|
+
document.body.insertAdjacentHTML('beforeend', modalHTML);
|
|
364
371
|
|
|
365
372
|
const select = document.getElementById('new-model-select');
|
|
366
|
-
select.innerHTML = '<option value="">Select a model...</option>';
|
|
367
|
-
|
|
368
373
|
models.forEach(model => {
|
|
369
374
|
const option = document.createElement('option');
|
|
370
375
|
option.value = model.id;
|
|
371
376
|
|
|
372
|
-
// Show service provider and optionally model maker
|
|
373
377
|
let displayText = model.name;
|
|
374
378
|
if (model.model_maker && model.provider !== model.model_maker) {
|
|
375
|
-
// Show both: "Model Name [Model Maker via Service Provider]"
|
|
376
379
|
displayText += ` [${model.model_maker} via ${model.provider}]`;
|
|
377
380
|
} else {
|
|
378
|
-
// Show service only: "Model Name [Service Provider]"
|
|
379
381
|
displayText += ` [${model.provider}]`;
|
|
380
382
|
}
|
|
381
383
|
|
|
382
384
|
option.textContent = displayText;
|
|
383
385
|
select.appendChild(option);
|
|
384
386
|
});
|
|
387
|
+
|
|
388
|
+
const modal = new bootstrap.Modal(document.getElementById('changeModelModal'));
|
|
389
|
+
modal.show();
|
|
385
390
|
} catch (error) {
|
|
386
|
-
|
|
391
|
+
showToast('Failed to load models', 'error');
|
|
387
392
|
}
|
|
388
|
-
|
|
389
|
-
const modal = new bootstrap.Modal(document.getElementById('changeModelModal'));
|
|
390
|
-
modal.show();
|
|
391
393
|
}
|
|
392
394
|
|
|
393
395
|
async function performChangeModel() {
|
|
@@ -430,7 +432,7 @@ async function showMCPAuditModal() {
|
|
|
430
432
|
</div>
|
|
431
433
|
<div class="modal-body" id="mcp-audit-content">
|
|
432
434
|
<div class="text-center">
|
|
433
|
-
<
|
|
435
|
+
<output class="spinner-border spinner-border-sm"></output>
|
|
434
436
|
</div>
|
|
435
437
|
</div>
|
|
436
438
|
</div>
|
|
@@ -515,7 +517,7 @@ async function showMCPServersModal() {
|
|
|
515
517
|
</div>
|
|
516
518
|
<div class="modal-body" id="mcp-servers-content">
|
|
517
519
|
<div class="text-center">
|
|
518
|
-
<
|
|
520
|
+
<output class="spinner-border spinner-border-sm"></output>
|
|
519
521
|
</div>
|
|
520
522
|
</div>
|
|
521
523
|
</div>
|
|
@@ -609,9 +611,9 @@ async function loadConversationInfo() {
|
|
|
609
611
|
try {
|
|
610
612
|
document.getElementById('info-content').innerHTML = `
|
|
611
613
|
<div class="text-center">
|
|
612
|
-
<
|
|
614
|
+
<output class="spinner-border spinner-border-sm">
|
|
613
615
|
<span class="visually-hidden">Loading...</span>
|
|
614
|
-
</
|
|
616
|
+
</output>
|
|
615
617
|
</div>
|
|
616
618
|
`;
|
|
617
619
|
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
<div class="card">
|
|
33
33
|
<div class="card-body" id="conversations-list">
|
|
34
34
|
<div class="text-center">
|
|
35
|
-
<
|
|
35
|
+
<output class="spinner-border text-primary">
|
|
36
36
|
<span class="visually-hidden">Loading...</span>
|
|
37
|
-
</
|
|
37
|
+
</output>
|
|
38
38
|
<p class="mt-2">Loading conversations...</p>
|
|
39
39
|
</div>
|
|
40
40
|
</div>
|
|
@@ -226,28 +226,49 @@ async function showNewConversationModal() {
|
|
|
226
226
|
async function loadModels() {
|
|
227
227
|
try {
|
|
228
228
|
const response = await fetch('/api/models');
|
|
229
|
-
const
|
|
229
|
+
const data = await response.json();
|
|
230
|
+
|
|
231
|
+
const models = data.models || data;
|
|
232
|
+
const modelLocked = data.model_locked || false;
|
|
230
233
|
|
|
231
234
|
const select = document.getElementById('model-select');
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
235
|
+
|
|
236
|
+
if (modelLocked) {
|
|
237
|
+
select.innerHTML = '';
|
|
238
|
+
models.forEach(model => {
|
|
239
|
+
const option = document.createElement('option');
|
|
240
|
+
option.value = model.id;
|
|
241
|
+
let displayText = model.name;
|
|
242
|
+
if (model.provider) {
|
|
243
|
+
displayText += ` [${model.provider}]`;
|
|
244
|
+
}
|
|
245
|
+
option.textContent = displayText;
|
|
246
|
+
option.selected = true;
|
|
247
|
+
select.appendChild(option);
|
|
248
|
+
});
|
|
249
|
+
select.disabled = true;
|
|
250
|
+
|
|
251
|
+
const infoDiv = document.createElement('div');
|
|
252
|
+
infoDiv.className = 'form-text text-info';
|
|
253
|
+
infoDiv.innerHTML = '<i class="bi bi-lock-fill"></i> Model is locked via configuration';
|
|
254
|
+
select.parentNode.appendChild(infoDiv);
|
|
255
|
+
} else {
|
|
256
|
+
select.innerHTML = '<option value="">Select a model...</option>';
|
|
257
|
+
models.forEach(model => {
|
|
258
|
+
const option = document.createElement('option');
|
|
259
|
+
option.value = model.id;
|
|
260
|
+
|
|
261
|
+
let displayText = model.name;
|
|
262
|
+
if (model.model_maker && model.provider !== model.model_maker) {
|
|
263
|
+
displayText += ` [${model.model_maker} via ${model.provider}]`;
|
|
264
|
+
} else {
|
|
265
|
+
displayText += ` [${model.provider}]`;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
option.textContent = displayText;
|
|
269
|
+
select.appendChild(option);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
251
272
|
|
|
252
273
|
} catch (error) {
|
|
253
274
|
document.getElementById('model-select').innerHTML = `
|
|
@@ -259,6 +280,13 @@ async function loadModels() {
|
|
|
259
280
|
// Create conversation
|
|
260
281
|
async function createConversation() {
|
|
261
282
|
const form = document.getElementById('new-conversation-form');
|
|
283
|
+
|
|
284
|
+
// Re-enable disabled select so its value is included in form data
|
|
285
|
+
const modelSelect = document.getElementById('model-select');
|
|
286
|
+
if (modelSelect.disabled) {
|
|
287
|
+
modelSelect.disabled = false;
|
|
288
|
+
}
|
|
289
|
+
|
|
262
290
|
const formData = new FormData(form);
|
|
263
291
|
|
|
264
292
|
try {
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
<div class="alert alert-info">
|
|
28
28
|
<i class="bi bi-info-circle-fill"></i> The web server is shutting down...
|
|
29
29
|
<div class="mt-2">
|
|
30
|
-
<
|
|
30
|
+
<output class="spinner-border spinner-border-sm">
|
|
31
31
|
<span class="visually-hidden">Shutting down...</span>
|
|
32
|
-
</
|
|
32
|
+
</output>
|
|
33
33
|
<span class="ms-2">Please wait</span>
|
|
34
34
|
</div>
|
|
35
35
|
</div>
|
|
@@ -166,28 +166,28 @@
|
|
|
166
166
|
</div>
|
|
167
167
|
|
|
168
168
|
<!-- Tab Navigation -->
|
|
169
|
-
<
|
|
170
|
-
<
|
|
169
|
+
<div class="nav nav-tabs mb-4" id="mainTabs" role="tablist">
|
|
170
|
+
<div class="nav-item">
|
|
171
171
|
<button class="nav-link active" id="overview-tab" data-bs-toggle="tab" data-bs-target="#overview" type="button" role="tab">
|
|
172
172
|
<i class="bi bi-speedometer2"></i> Overview
|
|
173
173
|
</button>
|
|
174
|
-
</
|
|
175
|
-
<
|
|
174
|
+
</div>
|
|
175
|
+
<div class="nav-item">
|
|
176
176
|
<button class="nav-link" id="llms-tab" data-bs-toggle="tab" data-bs-target="#llms" type="button" role="tab">
|
|
177
177
|
<i class="bi bi-cpu"></i> LLMs
|
|
178
178
|
</button>
|
|
179
|
-
</
|
|
180
|
-
<
|
|
179
|
+
</div>
|
|
180
|
+
<div class="nav-item">
|
|
181
181
|
<button class="nav-link" id="integrations-tab" data-bs-toggle="tab" data-bs-target="#integrations" type="button" role="tab">
|
|
182
182
|
<i class="bi bi-plug"></i> Integrations
|
|
183
183
|
</button>
|
|
184
|
-
</
|
|
185
|
-
<
|
|
184
|
+
</div>
|
|
185
|
+
<div class="nav-item">
|
|
186
186
|
<button class="nav-link" id="system-tab" data-bs-toggle="tab" data-bs-target="#system" type="button" role="tab">
|
|
187
187
|
<i class="bi bi-gear"></i> System
|
|
188
188
|
</button>
|
|
189
|
-
</
|
|
190
|
-
</
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
191
|
|
|
192
192
|
<!-- Tab Content -->
|
|
193
193
|
<div class="tab-content" id="mainTabContent">
|
|
@@ -202,7 +202,7 @@
|
|
|
202
202
|
<h5 class="card-title mb-3"><i class="bi bi-cpu"></i> LLM Providers</h5>
|
|
203
203
|
<div id="llm-providers-overview" class="d-flex justify-content-around flex-wrap gap-2">
|
|
204
204
|
<div class="text-center py-3">
|
|
205
|
-
<
|
|
205
|
+
<output class="spinner-border spinner-border-sm text-primary"></output>
|
|
206
206
|
<span class="ms-2">Loading providers...</span>
|
|
207
207
|
</div>
|
|
208
208
|
</div>
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
<!-- Provider Selector Icons -->
|
|
259
259
|
<div class="provider-selector" id="provider-selector">
|
|
260
260
|
<div class="text-center py-3 w-100">
|
|
261
|
-
<
|
|
261
|
+
<output class="spinner-border spinner-border-sm text-primary"></output>
|
|
262
262
|
<span class="ms-2">Loading providers...</span>
|
|
263
263
|
</div>
|
|
264
264
|
</div>
|
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
</div>
|
|
284
284
|
<div class="card-body p-0" id="tool-sources-list">
|
|
285
285
|
<div class="text-center py-4">
|
|
286
|
-
<
|
|
286
|
+
<output class="spinner-border spinner-border-sm text-primary"></output>
|
|
287
287
|
<span class="ms-2">Loading tools...</span>
|
|
288
288
|
</div>
|
|
289
289
|
</div>
|
|
@@ -317,7 +317,7 @@
|
|
|
317
317
|
</div>
|
|
318
318
|
<div class="card-body" id="user-identity">
|
|
319
319
|
<div class="text-center py-3">
|
|
320
|
-
<
|
|
320
|
+
<output class="spinner-border spinner-border-sm text-primary"></output>
|
|
321
321
|
<span class="ms-2">Loading user identity...</span>
|
|
322
322
|
</div>
|
|
323
323
|
</div>
|
|
@@ -642,7 +642,7 @@ function selectProvider(providerType) {
|
|
|
642
642
|
</div>
|
|
643
643
|
<div class="card-body" id="costs-info">
|
|
644
644
|
<div class="text-center py-3">
|
|
645
|
-
<
|
|
645
|
+
<output class="spinner-border spinner-border-sm text-primary"></output>
|
|
646
646
|
<span class="ms-2">Loading costs...</span>
|
|
647
647
|
</div>
|
|
648
648
|
</div>
|
|
@@ -799,7 +799,7 @@ async function selectToolSource(source, event) {
|
|
|
799
799
|
headerEl.innerHTML = '<i class="bi bi-box-fill"></i> Embedded Tools';
|
|
800
800
|
contentEl.innerHTML = `
|
|
801
801
|
<div class="text-center py-4">
|
|
802
|
-
<
|
|
802
|
+
<output class="spinner-border spinner-border-sm text-primary"></output>
|
|
803
803
|
<span class="ms-2">Loading embedded tools...</span>
|
|
804
804
|
</div>
|
|
805
805
|
`;
|
|
@@ -890,7 +890,7 @@ async function selectToolSource(source, event) {
|
|
|
890
890
|
// Fetch tools from API
|
|
891
891
|
contentEl.innerHTML = `
|
|
892
892
|
<div class="text-center py-4">
|
|
893
|
-
<
|
|
893
|
+
<output class="spinner-border spinner-border-sm text-primary"></output>
|
|
894
894
|
<span class="ms-2">Loading tools...</span>
|
|
895
895
|
</div>
|
|
896
896
|
`;
|
|
@@ -92,28 +92,53 @@
|
|
|
92
92
|
async function loadModels() {
|
|
93
93
|
try {
|
|
94
94
|
const response = await fetch('/api/models');
|
|
95
|
-
const
|
|
95
|
+
const data = await response.json();
|
|
96
|
+
|
|
97
|
+
const models = data.models || data;
|
|
98
|
+
const modelLocked = data.model_locked || false;
|
|
96
99
|
|
|
97
100
|
const select = document.getElementById('model-select');
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
101
|
+
|
|
102
|
+
if (modelLocked) {
|
|
103
|
+
// Model is locked - show only the mandatory model and disable selection
|
|
104
|
+
select.innerHTML = '';
|
|
105
|
+
models.forEach(model => {
|
|
106
|
+
const option = document.createElement('option');
|
|
107
|
+
option.value = model.id;
|
|
108
|
+
|
|
109
|
+
let displayText = model.name;
|
|
110
|
+
if (model.provider) {
|
|
111
|
+
displayText += ` [${model.provider}]`;
|
|
112
|
+
}
|
|
113
|
+
option.textContent = displayText;
|
|
114
|
+
option.selected = true;
|
|
115
|
+
select.appendChild(option);
|
|
116
|
+
});
|
|
117
|
+
select.disabled = true;
|
|
118
|
+
|
|
119
|
+
// Add info message below the select
|
|
120
|
+
const infoDiv = document.createElement('div');
|
|
121
|
+
infoDiv.className = 'form-text text-info';
|
|
122
|
+
infoDiv.innerHTML = '<i class="bi bi-lock-fill"></i> Model is locked via configuration';
|
|
123
|
+
select.parentNode.appendChild(infoDiv);
|
|
124
|
+
} else {
|
|
125
|
+
select.innerHTML = '<option value="">Select a model...</option>';
|
|
126
|
+
models.forEach(model => {
|
|
127
|
+
const option = document.createElement('option');
|
|
128
|
+
option.value = model.id;
|
|
129
|
+
|
|
130
|
+
// Show service provider and optionally model maker
|
|
131
|
+
let displayText = model.name;
|
|
132
|
+
if (model.model_maker && model.provider !== model.model_maker) {
|
|
133
|
+
displayText += ` [${model.model_maker} via ${model.provider}]`;
|
|
134
|
+
} else {
|
|
135
|
+
displayText += ` [${model.provider}]`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
option.textContent = displayText;
|
|
139
|
+
select.appendChild(option);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
117
142
|
} catch (error) {
|
|
118
143
|
console.error('Error loading models:', error);
|
|
119
144
|
showToast('Failed to load models', 'error');
|
|
@@ -146,6 +171,12 @@ function showToast(message, type = 'info') {
|
|
|
146
171
|
document.getElementById('new-conversation-form').addEventListener('submit', async (e) => {
|
|
147
172
|
e.preventDefault();
|
|
148
173
|
|
|
174
|
+
// Re-enable disabled select so its value is included in form data
|
|
175
|
+
const modelSelect = document.getElementById('model-select');
|
|
176
|
+
if (modelSelect.disabled) {
|
|
177
|
+
modelSelect.disabled = false;
|
|
178
|
+
}
|
|
179
|
+
|
|
149
180
|
const formData = new FormData(e.target);
|
|
150
181
|
|
|
151
182
|
try {
|
dtSpark/web/web_interface.py
CHANGED
|
@@ -124,7 +124,7 @@ class WebInterface:
|
|
|
124
124
|
True if response was accepted, False if request not found
|
|
125
125
|
"""
|
|
126
126
|
if request_id not in self._permission_requests:
|
|
127
|
-
logger.warning(
|
|
127
|
+
logger.warning("Permission response submitted for unknown request")
|
|
128
128
|
return False
|
|
129
129
|
|
|
130
130
|
# Store the response
|
|
@@ -133,5 +133,5 @@ class WebInterface:
|
|
|
133
133
|
# Update request status
|
|
134
134
|
self._permission_requests[request_id]['status'] = 'responded'
|
|
135
135
|
|
|
136
|
-
logger.info(
|
|
136
|
+
logger.info("Permission response submitted and recorded")
|
|
137
137
|
return True
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dtSpark
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.0a6
|
|
4
4
|
Summary: Secure Personal AI Research Kit - Multi-provider LLM CLI/Web interface with MCP tool integration
|
|
5
5
|
Home-page: https://github.com/digital-thought/dtSpark
|
|
6
6
|
Author: Matthew Westwood-Hill
|
|
@@ -42,7 +42,7 @@ Requires-Dist: httpx>=0.24.0
|
|
|
42
42
|
Requires-Dist: aiohttp>=3.8.0
|
|
43
43
|
Requires-Dist: mcp>=0.9.0
|
|
44
44
|
Requires-Dist: pyyaml>=6.0
|
|
45
|
-
Requires-Dist: dtPyAppFramework>=4.
|
|
45
|
+
Requires-Dist: dtPyAppFramework>=4.1.2
|
|
46
46
|
Requires-Dist: tiktoken>=0.5.0
|
|
47
47
|
Requires-Dist: ollama>=0.2.0
|
|
48
48
|
Requires-Dist: cryptography>=41.0.0
|
|
@@ -83,6 +83,13 @@ Dynamic: requires-python
|
|
|
83
83
|
[](https://opensource.org/licenses/MIT)
|
|
84
84
|
[](https://www.python.org/downloads/)
|
|
85
85
|
|
|
86
|
+
[](https://sonarcloud.io/summary/new_code?id=Digital-Thought_dtSpark)
|
|
87
|
+
[](https://sonarcloud.io/summary/new_code?id=Digital-Thought_dtSpark)
|
|
88
|
+
[](https://sonarcloud.io/summary/new_code?id=Digital-Thought_dtSpark)
|
|
89
|
+
[](https://sonarcloud.io/summary/new_code?id=Digital-Thought_dtSpark)
|
|
90
|
+
[](https://sonarcloud.io/summary/new_code?id=Digital-Thought_dtSpark)
|
|
91
|
+
[](https://sonarcloud.io/summary/new_code?id=Digital-Thought_dtSpark)
|
|
92
|
+
|
|
86
93
|
**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.
|
|
87
94
|
|
|
88
95
|
## Key Features
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
dtSpark/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
dtSpark/_description.txt,sha256=4OTFeEBVY3q0IbKbSdmi7lQ9bT5aeFHl9mUmQ7qluSg,209
|
|
3
|
+
dtSpark/_full_name.txt,sha256=wsMYXtT12WMrY9gT1JHiKdE4k7H59psECS6cSD07giQ,31
|
|
4
|
+
dtSpark/_licence.txt,sha256=Mvt5wkOkst8VGlk48vwN3CgHwMHLfmplKSPOUEbTfOw,1071
|
|
5
|
+
dtSpark/_metadata.yaml,sha256=h3PQd2QsY5yUBzS2b6EueTwkmd57svsbAKcwDVVEfIo,188
|
|
6
|
+
dtSpark/_name.txt,sha256=kDZC5_a3iMKIPOUvtLXl0C9N5DiOfgUCsecwTUnkJhs,7
|
|
7
|
+
dtSpark/_version.txt,sha256=gjNl3xINivNOurU564CJITfMDtfS5cMPFUF0a2kFUEM,7
|
|
8
|
+
dtSpark/cli_interface.py,sha256=Aae-vQ-aIaOiON-salTw-eDFo2eGI1-f_EJI6wmOYCo,97412
|
|
9
|
+
dtSpark/conversation_manager.py,sha256=VcfZSwrRuuUbVZa8kQVJjHwG4un5HA0nqYuajsUovoI,132593
|
|
10
|
+
dtSpark/launch.py,sha256=j8XYpmDswWUIzhpMc32E0Fhbhk_qhOQUAwJSpqh37f0,892
|
|
11
|
+
dtSpark/aws/__init__.py,sha256=tVuUKO69R3ZOkHQNQo81ukGTdU0OAyYVxkH0DgtwaTM,261
|
|
12
|
+
dtSpark/aws/authentication.py,sha256=dgYxrwtZHoGVhFb3HCsP7zA8tnM7qSsVUYHDqVkJbzY,11287
|
|
13
|
+
dtSpark/aws/bedrock.py,sha256=CK0fFYeMv1U0pnkkIFmNqIctBCOqhqHiYkJrYdNFqbA,23177
|
|
14
|
+
dtSpark/aws/costs.py,sha256=D8fnAL1NGCngA40rHqvdarf9g2TbrP5WxmehkIV5-uQ,12066
|
|
15
|
+
dtSpark/aws/pricing.py,sha256=y0SBRJoFDq1uXr9v0IYPxCnsHVivI77CD2f28i84d1E,23286
|
|
16
|
+
dtSpark/core/__init__.py,sha256=kORX-9C7L91WxMTMUHXr3Yc09rb6oJNzEH5_KDRdgqM,477
|
|
17
|
+
dtSpark/core/application.py,sha256=NBbxrr7RW0Y_jJjXzgPWN6VJIvRpnfh6ePxkyYtbm0E,171801
|
|
18
|
+
dtSpark/core/context_compaction.py,sha256=D-2OlnhHReOcgxIRX80Dnc1SPu-RfiyGgQ-2vQ0XneA,31474
|
|
19
|
+
dtSpark/daemon/__init__.py,sha256=Dw4lvbnKm7GngU_Iy_F_J4CBFDUZFaVZRXb-bAPd8HY,3495
|
|
20
|
+
dtSpark/daemon/__main__.py,sha256=sRNG4RJ-Ejvd-f7OAU5slPOtxVpCoC2OfazdTJro69Q,170
|
|
21
|
+
dtSpark/daemon/action_monitor.py,sha256=FYwPOrDN2_Q4zwvc2zrU4PVaZTw1gaC0fCFc2LcVvEk,8618
|
|
22
|
+
dtSpark/daemon/daemon_app.py,sha256=g6WhFOWGOdtB15-0Ctk24htiRDdRNB_mAqUOZX1rjiM,28900
|
|
23
|
+
dtSpark/daemon/daemon_manager.py,sha256=dPV9ISY2IopETH6-nJ1dk2X2KXi6XB0mYBbaZ2Tnclo,10057
|
|
24
|
+
dtSpark/daemon/execution_coordinator.py,sha256=ykZ2iKe6XaoD3JCOjhnEbiD8q12d7opg9ZafZFiW7lQ,5869
|
|
25
|
+
dtSpark/daemon/pid_file.py,sha256=Nm0rmjisr5a2YRAOwMkqpFpAXLjJ3V0IB-E6t4ZnAWA,4687
|
|
26
|
+
dtSpark/database/__init__.py,sha256=NaNZ-06nPUaXrq1C4W_YHdUWvcfMUAD8qdJOhPJSYco,25950
|
|
27
|
+
dtSpark/database/autonomous_actions.py,sha256=FCpxhzpM5Mjnt6dCTYxK2-iqC-Y5iNuWEFSGPZYnH_8,36143
|
|
28
|
+
dtSpark/database/backends.py,sha256=HAskNCI5QsF5QeYVD596XHn4ITlfqJkJW2jEkJUpYl0,9347
|
|
29
|
+
dtSpark/database/connection.py,sha256=egEGhp7gb7beoEZCYUUflY2YMAC5gdDs_XTWuB0CwiM,3672
|
|
30
|
+
dtSpark/database/conversations.py,sha256=kldbkVe1UMz52FSrX8RyCYNeAPE7P6pfpIGWHDsijpU,18338
|
|
31
|
+
dtSpark/database/credential_prompt.py,sha256=hRvYfZyOi1rqwHz-bmgVAuBR9zubS7Yvn3QE2UWGSM8,6789
|
|
32
|
+
dtSpark/database/files.py,sha256=WDOE_aShfzlDvEQcwx9bZKPFz1unrIoBDQqpjG8UBdA,7006
|
|
33
|
+
dtSpark/database/mcp_ops.py,sha256=jgc8Ig1iogvrbOV8cUcSlmFRuhp14x1K8sgicPl2Neg,12706
|
|
34
|
+
dtSpark/database/messages.py,sha256=h2iVIWFzashtNlbg-8ln37H12yeKTOofRVXgDR1yPtY,5296
|
|
35
|
+
dtSpark/database/schema.py,sha256=j7Av9Ag9Q60pz99d26wjqvaHvQ4OZh8zAd5HX9_6Rjw,23336
|
|
36
|
+
dtSpark/database/tool_permissions.py,sha256=6NjYmU82BAq2lFsyhgzkudVoOpWAw-R-l2AV1_Z0KC4,6227
|
|
37
|
+
dtSpark/database/usage.py,sha256=6DwKvQTxx8F-P7cNU7dPjqCinIp9cst6OiUgJkY008o,5368
|
|
38
|
+
dtSpark/files/__init__.py,sha256=BTSp2hvW4NI6GSka3eKoNCfvzcxUPPWJOiqbY5gXe4I,90
|
|
39
|
+
dtSpark/files/manager.py,sha256=7JzBGhvzSNT6BjGuAg6X9AifBprNIaNUqQiEkl8gDVQ,10627
|
|
40
|
+
dtSpark/limits/__init__.py,sha256=vCqYQvR8Ss6Q64ySUj-Vx_8cWUFLGUH9z330Wd4dNBg,262
|
|
41
|
+
dtSpark/limits/costs.py,sha256=YpPTQ3uqCkrOr4xpVOkIEml_vdLbzIAak_rV__2-wxg,10213
|
|
42
|
+
dtSpark/limits/tokens.py,sha256=UF5razY6qxFUA0HrxBMJ-zVJ5VhOauitcrZrJx66bJ0,13590
|
|
43
|
+
dtSpark/llm/__init__.py,sha256=Govebgc3ukJFyu7eyIwTeUcsBwpUTeWkF4xIstW9kQk,608
|
|
44
|
+
dtSpark/llm/anthropic_direct.py,sha256=AexKSBOALVMLmnIOMTZr4wPLLooKFNY22o3jVESYK6A,20241
|
|
45
|
+
dtSpark/llm/base.py,sha256=M8DaC_uZSa7UNt7Cx_EUBZcx6dbHCeEQBTSYGgBbphM,4217
|
|
46
|
+
dtSpark/llm/context_limits.py,sha256=YnyPpG7f6esS7KcS1hUrKLijYWL25crmQsWA_DeIhco,16627
|
|
47
|
+
dtSpark/llm/manager.py,sha256=Qg9glX5ZhepWaRnb8ILZiPoiwqzC8Y318JgwuJf9m58,5837
|
|
48
|
+
dtSpark/llm/ollama.py,sha256=BQOS6j8nRipoHzPv6gxwzpjucdJ-HLQ3ixNvTEPROKM,20897
|
|
49
|
+
dtSpark/mcp_integration/__init__.py,sha256=pFw-yTSSJ1yx_ksTe94eq8pBrwDD-5Z-UqSM3VO4deQ,157
|
|
50
|
+
dtSpark/mcp_integration/manager.py,sha256=yfSymFPXAN-80Rl0M5D-Upb3vIvRq_tvGAI5wVR-IdQ,25241
|
|
51
|
+
dtSpark/mcp_integration/tool_selector.py,sha256=GHH1pEyi5E2QA2JdfrWFGkZlVucuhSIh4jBJOb54TjU,11029
|
|
52
|
+
dtSpark/resources/config.yaml.template,sha256=8N3zeXHSafIlU-UO8IGztrYcTbNwZyrkspVqC_PclGM,27346
|
|
53
|
+
dtSpark/safety/__init__.py,sha256=fdcZ4qNbYhH7Un9iKLwNe2GDr_doUmpSgtv-oNS8qPE,460
|
|
54
|
+
dtSpark/safety/llm_service.py,sha256=N2J9_Od-fGGvk9BkddD6CFd81PrJ03sMjSz6egBDYr4,3820
|
|
55
|
+
dtSpark/safety/patterns.py,sha256=ZeHuLHrtunZhOHIo3ZG0r9b2e1f9Dp9X_FtJMf8gefE,8467
|
|
56
|
+
dtSpark/safety/prompt_inspector.py,sha256=c5vIvIRyj-TC9rS-V07KpVNvw4xwHdbKSlPW7N3NBhA,16440
|
|
57
|
+
dtSpark/safety/violation_logger.py,sha256=HCWKOWuhIe4_BIx9Ccb_mcdW-14fWRMGH6YqFc-3o8c,11769
|
|
58
|
+
dtSpark/scheduler/__init__.py,sha256=DkhER25jUoqFU1c4xTDZyoJhMJ-wFS6yZqvsp3cr0zo,494
|
|
59
|
+
dtSpark/scheduler/creation_tools.py,sha256=rhIf0naBn-8_8Bp_wGbBdPH8MP5uQQLHOfYX0XoScfs,23342
|
|
60
|
+
dtSpark/scheduler/execution_queue.py,sha256=7_yXnGxO-arZTl0qPbyE-kDhZDVXQKT2z9zIKj9s1SA,4954
|
|
61
|
+
dtSpark/scheduler/executor.py,sha256=s_-6WKdTYEK1-xjYJNXGcAj6vdN27Cf6TI9zNYPSsk0,51371
|
|
62
|
+
dtSpark/scheduler/manager.py,sha256=vwtmQadqf3cv1QzdZJzFqC0l3bBzIplGZ79BUjfsh4o,12846
|
|
63
|
+
dtSpark/tools/__init__.py,sha256=TPK-c8CmXheEkoiFzL9PMP8ve0hTpw9iIV2xlGLTsMc,147
|
|
64
|
+
dtSpark/tools/builtin.py,sha256=oTdOsxK8x4-DR4wDOYZdBNdZZ7MlqgplM5GLV6OaWQQ,88941
|
|
65
|
+
dtSpark/web/__init__.py,sha256=5OrzA2yIR9NBf9mlTPnrQ0afMJTBuEgnzxq4QmIYe54,428
|
|
66
|
+
dtSpark/web/auth.py,sha256=uSIHwJOiklkjZSpLcznwOL1pVQktKeWifZygt068M9Y,4384
|
|
67
|
+
dtSpark/web/dependencies.py,sha256=ku54-Vb8wYvGVQ8Kluzxj8zm2Re3wDgU5LzFJ0NVIsI,874
|
|
68
|
+
dtSpark/web/server.py,sha256=J27-tMSRYhB24vf03e56o3wPVhLCo7QFVbLUn88iGdM,23500
|
|
69
|
+
dtSpark/web/session.py,sha256=yoz4yKGqUiYtxc5qoKtyBxNH0JrITSUyzgfu5iTo_Lw,4972
|
|
70
|
+
dtSpark/web/ssl_utils.py,sha256=PcZazlLeZTqIWeLY3N4xrk7CcxBNQXMcDJ6ou4r6-F4,6652
|
|
71
|
+
dtSpark/web/web_interface.py,sha256=vLGfinZpQqqVq6E8Xfb4GvpQ4lR6c26R9on94tT_LAk,4681
|
|
72
|
+
dtSpark/web/endpoints/__init__.py,sha256=uOTiOKx6IDZ2kc0-2GS2hqZD2qX6KtwAhMMZQbS7pWc,356
|
|
73
|
+
dtSpark/web/endpoints/autonomous_actions.py,sha256=U0YY2sjgS9C3OhmUUKg7kaW4aNWCeFq9amGtkXYrO6k,36727
|
|
74
|
+
dtSpark/web/endpoints/chat.py,sha256=c5MWZE-SY26Hr0X3DIFU_LQ15m1E-fFZ7hnQbmzXd1w,26041
|
|
75
|
+
dtSpark/web/endpoints/conversations.py,sha256=ADEsoZlN9roa_uoazvFMSw_w-gFpXHKd6tJyZuxop2w,13248
|
|
76
|
+
dtSpark/web/endpoints/main_menu.py,sha256=shAP7F5zREbs2A7BmZAIzt5LpR83tZHrNXiFdWgsmFg,20621
|
|
77
|
+
dtSpark/web/endpoints/streaming.py,sha256=qo0ugUWYvJJF5QvvLpuIvFIlVWgOpfPyUK59HeoRgdY,14603
|
|
78
|
+
dtSpark/web/static/css/dark-theme.css,sha256=vMHtvATXuPFYCKlcwexa5ttq15IIffUWiBchxDqxwvo,7673
|
|
79
|
+
dtSpark/web/static/js/actions.js,sha256=EI-ur3eNV97flgpUcM4M5YOQtn_VPS1o4aFiPvthx3U,37463
|
|
80
|
+
dtSpark/web/static/js/chat.js,sha256=JE1v7i-Bn6arcMQbbLvV1u-bzlRrjPoJwkuTXTsa84o,21737
|
|
81
|
+
dtSpark/web/static/js/main.js,sha256=0JUuRtVlWxpRgCZoHwM4_tRxyBrNKwTPQmN_meKEI4M,16133
|
|
82
|
+
dtSpark/web/static/js/sse-client.js,sha256=JZnLDar6j8m7TxuHJ9JQDl7E3LqUiWSbQHt6yMaskPI,9104
|
|
83
|
+
dtSpark/web/templates/actions.html,sha256=08Pk8aqmNEr3uEQTzmnFklETqd1hUcE8PCtUZVMZJso,18875
|
|
84
|
+
dtSpark/web/templates/base.html,sha256=Om8MLeJPAB27CGOELUx63I3ZVtKpTlnrEvKaUsZQImU,4221
|
|
85
|
+
dtSpark/web/templates/chat.html,sha256=QuyIJOrfKbsLgGH7ELGLBJe_JBnuF73_Sx6EFuMflcc,45104
|
|
86
|
+
dtSpark/web/templates/conversations.html,sha256=JFDvjDUyRkO60KwRsO-F3Dzvtyb9Q4wOHSxiibakTJE,13997
|
|
87
|
+
dtSpark/web/templates/goodbye.html,sha256=ZdEzgP9MD4kMPrLHkg_3wAod2Hfr9hSTRyBq9fB9DV4,2817
|
|
88
|
+
dtSpark/web/templates/login.html,sha256=OkLf_uzMYhl_o9ER1RQZc8ch6-bCaiOokEhKbeEl8E8,3274
|
|
89
|
+
dtSpark/web/templates/main_menu.html,sha256=80NUCu-nzvpMLHGz4gvabjLVmdASldesYtKjvm38Hv0,39120
|
|
90
|
+
dtSpark/web/templates/new_conversation.html,sha256=wL9ZZbn3M8ktEoX7H5n4r6XKSEImtO2aXnuNKsB-pEw,8047
|
|
91
|
+
dtspark-1.1.0a6.dist-info/licenses/LICENSE,sha256=jIuWlmbirwQabTwxfzE7SXT1LpCG-y_GRQ3VnoRTKgo,1101
|
|
92
|
+
dtspark-1.1.0a6.dist-info/METADATA,sha256=t2IBA-ybdErR_JSrTwcM7Gh6fqrnk7r5UZ1EMHdWpC8,7410
|
|
93
|
+
dtspark-1.1.0a6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
94
|
+
dtspark-1.1.0a6.dist-info/entry_points.txt,sha256=IpIwa_a6XY8Z2w7DtgYAhpFHHEbha-zhLkyttWd3zpw,76
|
|
95
|
+
dtspark-1.1.0a6.dist-info/top_level.txt,sha256=x-6lMA6vNuxyDNJGNOKI4dyy7L0kOb9V98I5z46bJVY,8
|
|
96
|
+
dtspark-1.1.0a6.dist-info/RECORD,,
|