dtSpark 1.1.0a3__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 +112 -91
- 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 +8 -6
- dtSpark/web/endpoints/conversations.py +11 -9
- 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/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 +10 -10
- dtSpark/web/templates/conversations.html +2 -2
- dtSpark/web/templates/goodbye.html +2 -2
- dtSpark/web/templates/main_menu.html +17 -17
- dtSpark/web/web_interface.py +2 -2
- {dtspark-1.1.0a3.dist-info → dtspark-1.1.0a6.dist-info}/METADATA +9 -2
- dtspark-1.1.0a6.dist-info/RECORD +96 -0
- dtspark-1.1.0a3.dist-info/RECORD +0 -96
- {dtspark-1.1.0a3.dist-info → dtspark-1.1.0a6.dist-info}/WHEEL +0 -0
- {dtspark-1.1.0a3.dist-info → dtspark-1.1.0a6.dist-info}/entry_points.txt +0 -0
- {dtspark-1.1.0a3.dist-info → dtspark-1.1.0a6.dist-info}/licenses/LICENSE +0 -0
- {dtspark-1.1.0a3.dist-info → dtspark-1.1.0a6.dist-info}/top_level.txt +0 -0
|
@@ -17,151 +17,159 @@ async function sendMessageWithSSE(conversationId, message) {
|
|
|
17
17
|
let streamingMessageElement = null;
|
|
18
18
|
let accumulatedContent = '';
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
try {
|
|
22
|
+
// Create EventSource for SSE
|
|
23
|
+
const encodedMessage = encodeURIComponent(message);
|
|
24
|
+
const eventSource = new EventSource(
|
|
25
|
+
`/api/stream/chat?message=${encodedMessage}&conversation_id=${conversationId}`
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Handle different event types
|
|
29
|
+
eventSource.addEventListener('status', (event) => {
|
|
30
|
+
const data = JSON.parse(event.data);
|
|
31
|
+
console.log('Status:', data);
|
|
32
|
+
|
|
33
|
+
// Update typing indicator with status
|
|
34
|
+
if (typingIndicator && typingIndicator.parentNode) {
|
|
35
|
+
const statusText = data.message || '';
|
|
36
|
+
typingIndicator.querySelector('.visually-hidden').nextSibling.textContent = statusText;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
eventSource.addEventListener('response', (event) => {
|
|
41
|
+
const data = JSON.parse(event.data);
|
|
42
|
+
console.log('Received response event:', data);
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
// Hide typing indicator on first response
|
|
45
|
+
if (typingIndicator && typingIndicator.parentNode) {
|
|
46
|
+
console.log('Hiding typing indicator');
|
|
47
|
+
hideTypingIndicator();
|
|
48
|
+
typingIndicator = null; // Clear reference after hiding
|
|
49
|
+
}
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
51
|
+
if (data.type === 'text') {
|
|
52
|
+
if (data.final) {
|
|
53
|
+
// Final response - this is the main assistant response after tool execution
|
|
54
|
+
console.log('Final response received, content length:', data.content ? data.content.length : 0);
|
|
55
|
+
accumulatedContent += data.content;
|
|
56
|
+
console.log('Accumulated content:', accumulatedContent);
|
|
57
|
+
|
|
58
|
+
// Ensure we have content before displaying
|
|
59
|
+
if (accumulatedContent.trim().length > 0) {
|
|
60
|
+
streamingMessageElement = updateStreamingMessage(
|
|
61
|
+
accumulatedContent,
|
|
62
|
+
streamingMessageElement
|
|
63
|
+
);
|
|
64
|
+
console.log('Updated streaming message element:', streamingMessageElement);
|
|
65
|
+
} else {
|
|
66
|
+
console.warn('No content to display');
|
|
67
|
+
}
|
|
68
|
+
eventSource.close();
|
|
69
|
+
resolve();
|
|
64
70
|
} else {
|
|
65
|
-
|
|
71
|
+
// Non-final response - text that appears with tool calls
|
|
72
|
+
// Display immediately as a separate message
|
|
73
|
+
console.log('Non-final response, appending:', data.content);
|
|
74
|
+
appendMessage('assistant', data.content);
|
|
66
75
|
}
|
|
67
|
-
eventSource.close();
|
|
68
|
-
} else {
|
|
69
|
-
// Non-final response - text that appears with tool calls
|
|
70
|
-
// Display immediately as a separate message
|
|
71
|
-
console.log('Non-final response, appending:', data.content);
|
|
72
|
-
appendMessage('assistant', data.content);
|
|
73
76
|
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
eventSource.addEventListener('tool_start', (event) => {
|
|
80
|
+
const data = JSON.parse(event.data);
|
|
81
|
+
appendToolCall(data.tool_name, data.input);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
eventSource.addEventListener('tool_complete', (event) => {
|
|
85
|
+
const data = JSON.parse(event.data);
|
|
86
|
+
// Display tool result
|
|
87
|
+
appendToolResult(data.tool_use_id, { content: data.content });
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
eventSource.addEventListener('tool_error', (event) => {
|
|
91
|
+
const data = JSON.parse(event.data);
|
|
92
|
+
appendToolResult(data.tool_name, { error: data.error });
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
eventSource.addEventListener('permission_request', (event) => {
|
|
96
|
+
const data = JSON.parse(event.data);
|
|
97
|
+
console.log('Permission request received:', data);
|
|
98
|
+
|
|
99
|
+
// Show permission modal/dialog
|
|
100
|
+
showToolPermissionDialog(data.request_id, data.tool_name, data.tool_description);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
eventSource.addEventListener('progress', (event) => {
|
|
104
|
+
const data = JSON.parse(event.data);
|
|
105
|
+
// Update progress (if we want to show a progress bar)
|
|
106
|
+
console.log('Progress:', data);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
eventSource.addEventListener('complete', (event) => {
|
|
110
|
+
// Stream complete
|
|
111
|
+
console.log('Stream complete');
|
|
112
|
+
eventSource.close();
|
|
87
113
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
114
|
+
// Hide typing indicator if still visible
|
|
115
|
+
if (typingIndicator && typingIndicator.parentNode) {
|
|
116
|
+
console.log('Hiding typing indicator on complete');
|
|
117
|
+
hideTypingIndicator();
|
|
118
|
+
typingIndicator = null;
|
|
119
|
+
}
|
|
92
120
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
console.log('Permission request received:', data);
|
|
121
|
+
resolve();
|
|
122
|
+
});
|
|
96
123
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
124
|
+
eventSource.addEventListener('error', (event) => {
|
|
125
|
+
console.error('SSE error:', event);
|
|
126
|
+
const data = JSON.parse(event.data);
|
|
100
127
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
128
|
+
// Hide typing indicator
|
|
129
|
+
if (typingIndicator && typingIndicator.parentNode) {
|
|
130
|
+
console.log('Hiding typing indicator on error');
|
|
131
|
+
hideTypingIndicator();
|
|
132
|
+
typingIndicator = null;
|
|
133
|
+
}
|
|
106
134
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
console.log('Stream complete');
|
|
110
|
-
eventSource.close();
|
|
135
|
+
// Show error message
|
|
136
|
+
appendMessage('system', `Error: ${data.message}`);
|
|
111
137
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
hideTypingIndicator();
|
|
116
|
-
typingIndicator = null;
|
|
117
|
-
}
|
|
118
|
-
});
|
|
138
|
+
eventSource.close();
|
|
139
|
+
resolve();
|
|
140
|
+
});
|
|
119
141
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const data = JSON.parse(event.data);
|
|
142
|
+
eventSource.onerror = (error) => {
|
|
143
|
+
console.error('EventSource failed:', error);
|
|
123
144
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
145
|
+
// Hide typing indicator
|
|
146
|
+
if (typingIndicator && typingIndicator.parentNode) {
|
|
147
|
+
console.log('Hiding typing indicator on connection error');
|
|
148
|
+
hideTypingIndicator();
|
|
149
|
+
typingIndicator = null;
|
|
150
|
+
}
|
|
130
151
|
|
|
131
|
-
|
|
132
|
-
|
|
152
|
+
// If we haven't received any content, show error
|
|
153
|
+
if (!streamingMessageElement) {
|
|
154
|
+
appendMessage('system', 'Connection error. Please try again.');
|
|
155
|
+
}
|
|
133
156
|
|
|
134
|
-
|
|
135
|
-
|
|
157
|
+
eventSource.close();
|
|
158
|
+
resolve();
|
|
159
|
+
};
|
|
136
160
|
|
|
137
|
-
|
|
138
|
-
console.error('
|
|
161
|
+
} catch (error) {
|
|
162
|
+
console.error('Error sending message:', error);
|
|
139
163
|
|
|
140
164
|
// Hide typing indicator
|
|
141
|
-
if (typingIndicator
|
|
142
|
-
console.log('Hiding typing indicator on connection error');
|
|
165
|
+
if (typingIndicator) {
|
|
143
166
|
hideTypingIndicator();
|
|
144
|
-
typingIndicator = null;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// If we haven't received any content, show error
|
|
148
|
-
if (!streamingMessageElement) {
|
|
149
|
-
appendMessage('system', 'Connection error. Please try again.');
|
|
150
167
|
}
|
|
151
168
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
} catch (error) {
|
|
156
|
-
console.error('Error sending message:', error);
|
|
157
|
-
|
|
158
|
-
// Hide typing indicator
|
|
159
|
-
if (typingIndicator) {
|
|
160
|
-
hideTypingIndicator();
|
|
169
|
+
showToast('Failed to send message', 'error');
|
|
170
|
+
resolve();
|
|
161
171
|
}
|
|
162
|
-
|
|
163
|
-
showToast('Failed to send message', 'error');
|
|
164
|
-
}
|
|
172
|
+
});
|
|
165
173
|
}
|
|
166
174
|
|
|
167
175
|
/**
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
<tbody id="actions-tbody">
|
|
54
54
|
<tr>
|
|
55
55
|
<td colspan="9" class="text-center text-muted py-4">
|
|
56
|
-
<
|
|
56
|
+
<output class="spinner-border spinner-border-sm"></output>
|
|
57
57
|
Loading actions...
|
|
58
58
|
</td>
|
|
59
59
|
</tr>
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
<tbody id="runs-tbody">
|
|
86
86
|
<tr>
|
|
87
87
|
<td colspan="7" class="text-center text-muted py-4">
|
|
88
|
-
<
|
|
88
|
+
<output class="spinner-border spinner-border-sm"></output>
|
|
89
89
|
Loading recent runs...
|
|
90
90
|
</td>
|
|
91
91
|
</tr>
|
|
@@ -172,7 +172,7 @@
|
|
|
172
172
|
|
|
173
173
|
<!-- Tool Permissions -->
|
|
174
174
|
<div class="mb-3">
|
|
175
|
-
<
|
|
175
|
+
<span class="form-label d-block">Tool Permissions</span>
|
|
176
176
|
<div class="card">
|
|
177
177
|
<div class="card-body" style="max-height: 200px; overflow-y: auto;">
|
|
178
178
|
<div id="toolPermissions">
|
|
@@ -374,14 +374,14 @@
|
|
|
374
374
|
<div class="alert alert-success mb-0">
|
|
375
375
|
<i class="bi bi-check-circle-fill"></i>
|
|
376
376
|
Action created successfully!
|
|
377
|
-
<
|
|
377
|
+
<button type="button" id="viewCreatedAction" class="btn btn-link p-0 align-baseline" onclick="viewCreatedAction();">View action details</button>
|
|
378
378
|
</div>
|
|
379
379
|
</div>
|
|
380
380
|
</div>
|
|
381
381
|
|
|
382
382
|
<!-- Loading Indicator -->
|
|
383
383
|
<div id="aiCreateLoading" class="d-none text-center py-4">
|
|
384
|
-
<
|
|
384
|
+
<output class="spinner-border text-primary"></output>
|
|
385
385
|
<p class="mt-2 text-muted">AI is thinking...</p>
|
|
386
386
|
</div>
|
|
387
387
|
</div>
|
dtSpark/web/templates/base.html
CHANGED
|
@@ -53,11 +53,13 @@
|
|
|
53
53
|
<i class="bi bi-plus-circle"></i> New
|
|
54
54
|
</a>
|
|
55
55
|
</li>
|
|
56
|
+
{% if actions_enabled %}
|
|
56
57
|
<li class="nav-item">
|
|
57
58
|
<a class="nav-link" href="/actions">
|
|
58
59
|
<i class="bi bi-robot"></i> Actions
|
|
59
60
|
</a>
|
|
60
61
|
</li>
|
|
62
|
+
{% endif %}
|
|
61
63
|
</ul>
|
|
62
64
|
<ul class="navbar-nav">
|
|
63
65
|
<li class="nav-item">
|
|
@@ -89,5 +91,16 @@
|
|
|
89
91
|
<script src="/static/js/main.js"></script>
|
|
90
92
|
|
|
91
93
|
{% block extra_scripts %}{% endblock %}
|
|
94
|
+
|
|
95
|
+
{% if heartbeat_enabled %}
|
|
96
|
+
<!-- Browser heartbeat - auto-shutdown when browser closes -->
|
|
97
|
+
<script>
|
|
98
|
+
setInterval(() => {
|
|
99
|
+
fetch('/api/heartbeat', { method: 'POST' }).catch(() => {});
|
|
100
|
+
}, {{ heartbeat_interval_ms }});
|
|
101
|
+
// Send initial heartbeat immediately
|
|
102
|
+
fetch('/api/heartbeat', { method: 'POST' }).catch(() => {});
|
|
103
|
+
</script>
|
|
104
|
+
{% endif %}
|
|
92
105
|
</body>
|
|
93
106
|
</html>
|
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>
|
|
@@ -432,7 +432,7 @@ async function showMCPAuditModal() {
|
|
|
432
432
|
</div>
|
|
433
433
|
<div class="modal-body" id="mcp-audit-content">
|
|
434
434
|
<div class="text-center">
|
|
435
|
-
<
|
|
435
|
+
<output class="spinner-border spinner-border-sm"></output>
|
|
436
436
|
</div>
|
|
437
437
|
</div>
|
|
438
438
|
</div>
|
|
@@ -517,7 +517,7 @@ async function showMCPServersModal() {
|
|
|
517
517
|
</div>
|
|
518
518
|
<div class="modal-body" id="mcp-servers-content">
|
|
519
519
|
<div class="text-center">
|
|
520
|
-
<
|
|
520
|
+
<output class="spinner-border spinner-border-sm"></output>
|
|
521
521
|
</div>
|
|
522
522
|
</div>
|
|
523
523
|
</div>
|
|
@@ -611,9 +611,9 @@ async function loadConversationInfo() {
|
|
|
611
611
|
try {
|
|
612
612
|
document.getElementById('info-content').innerHTML = `
|
|
613
613
|
<div class="text-center">
|
|
614
|
-
<
|
|
614
|
+
<output class="spinner-border spinner-border-sm">
|
|
615
615
|
<span class="visually-hidden">Loading...</span>
|
|
616
|
-
</
|
|
616
|
+
</output>
|
|
617
617
|
</div>
|
|
618
618
|
`;
|
|
619
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>
|
|
@@ -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
|
`;
|
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
|