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,191 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}New Conversation - {{ app_name }}{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="row">
7
+ <div class="col-12">
8
+ <h2 class="mb-4">
9
+ <i class="bi bi-plus-circle-fill"></i> New Conversation
10
+ </h2>
11
+ </div>
12
+ </div>
13
+
14
+ <div class="row">
15
+ <div class="col-lg-8 offset-lg-2">
16
+ <div class="card">
17
+ <div class="card-body">
18
+ <form id="new-conversation-form">
19
+ <div class="mb-3">
20
+ <label for="conversation-name" class="form-label">Conversation Name</label>
21
+ <input
22
+ type="text"
23
+ class="form-control"
24
+ id="conversation-name"
25
+ name="name"
26
+ placeholder="Enter a name for this conversation"
27
+ required
28
+ />
29
+ </div>
30
+
31
+ <div class="mb-3">
32
+ <label for="model-select" class="form-label">Model</label>
33
+ <select class="form-select" id="model-select" name="model_id" required>
34
+ <option value="">Loading models...</option>
35
+ </select>
36
+ </div>
37
+
38
+ <div class="mb-3">
39
+ <label for="instructions" class="form-label">Instructions (Optional)</label>
40
+ <textarea
41
+ class="form-control"
42
+ id="instructions"
43
+ name="instructions"
44
+ rows="4"
45
+ placeholder="Enter system instructions for this conversation (optional)"
46
+ ></textarea>
47
+ </div>
48
+
49
+ <div class="mb-3">
50
+ <label for="files" class="form-label">Attach Files (Optional)</label>
51
+ <input
52
+ type="file"
53
+ class="form-control"
54
+ id="files"
55
+ name="files"
56
+ multiple
57
+ />
58
+ <div class="form-text">
59
+ Supported formats: txt, md, json, yaml, yml, xml, csv, log, py, js, ts, java, cpp, c, h
60
+ </div>
61
+ </div>
62
+
63
+ <div class="d-grid gap-2">
64
+ <button type="submit" class="btn btn-primary btn-lg">
65
+ <i class="bi bi-plus-circle-fill"></i> Create Conversation
66
+ </button>
67
+ <a href="/menu" class="btn btn-secondary">
68
+ <i class="bi bi-x-circle"></i> Cancel
69
+ </a>
70
+ </div>
71
+ </form>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+
77
+ <!-- Toast container for notifications -->
78
+ <div class="toast-container position-fixed bottom-0 end-0 p-3">
79
+ <div id="toast" class="toast" role="alert">
80
+ <div class="toast-header">
81
+ <strong class="me-auto">Notification</strong>
82
+ <button type="button" class="btn-close" data-bs-dismiss="toast"></button>
83
+ </div>
84
+ <div class="toast-body" id="toast-message"></div>
85
+ </div>
86
+ </div>
87
+ {% endblock %}
88
+
89
+ {% block extra_scripts %}
90
+ <script>
91
+ // Load available models
92
+ async function loadModels() {
93
+ try {
94
+ const response = await fetch('/api/models');
95
+ const models = await response.json();
96
+
97
+ const select = document.getElementById('model-select');
98
+ select.innerHTML = '<option value="">Select a model...</option>';
99
+
100
+ models.forEach(model => {
101
+ const option = document.createElement('option');
102
+ option.value = model.id;
103
+
104
+ // Show service provider and optionally model maker
105
+ let displayText = model.name;
106
+ if (model.model_maker && model.provider !== model.model_maker) {
107
+ // Show both: "Model Name [Model Maker via Service Provider]"
108
+ displayText += ` [${model.model_maker} via ${model.provider}]`;
109
+ } else {
110
+ // Show service only: "Model Name [Service Provider]"
111
+ displayText += ` [${model.provider}]`;
112
+ }
113
+
114
+ option.textContent = displayText;
115
+ select.appendChild(option);
116
+ });
117
+ } catch (error) {
118
+ console.error('Error loading models:', error);
119
+ showToast('Failed to load models', 'error');
120
+ }
121
+ }
122
+
123
+ // Show toast notification
124
+ function showToast(message, type = 'info') {
125
+ const toast = document.getElementById('toast');
126
+ const toastBody = document.getElementById('toast-message');
127
+ const toastHeader = toast.querySelector('.toast-header');
128
+
129
+ toastBody.textContent = message;
130
+
131
+ // Update toast style based on type
132
+ toastHeader.className = 'toast-header';
133
+ if (type === 'success') {
134
+ toastHeader.classList.add('bg-success', 'text-white');
135
+ } else if (type === 'error') {
136
+ toastHeader.classList.add('bg-danger', 'text-white');
137
+ } else if (type === 'warning') {
138
+ toastHeader.classList.add('bg-warning');
139
+ }
140
+
141
+ const bsToast = new bootstrap.Toast(toast);
142
+ bsToast.show();
143
+ }
144
+
145
+ // Handle form submission
146
+ document.getElementById('new-conversation-form').addEventListener('submit', async (e) => {
147
+ e.preventDefault();
148
+
149
+ const formData = new FormData(e.target);
150
+
151
+ try {
152
+ const response = await fetch('/api/conversations', {
153
+ method: 'POST',
154
+ body: formData
155
+ });
156
+
157
+ if (!response.ok) {
158
+ const error = await response.json();
159
+ throw new Error(error.detail || 'Failed to create conversation');
160
+ }
161
+
162
+ const data = await response.json();
163
+
164
+ // Check for file upload warnings
165
+ if (data.warnings && data.warnings.length > 0) {
166
+ // Show warnings but still proceed
167
+ data.warnings.forEach(warning => {
168
+ showToast(warning, 'warning');
169
+ });
170
+ showToast('Conversation created (some files failed to upload)', 'success');
171
+ } else {
172
+ showToast('Conversation created successfully!', 'success');
173
+ }
174
+
175
+ // Redirect to chat page after a short delay
176
+ setTimeout(() => {
177
+ window.location.href = `/chat/${data.id}`;
178
+ }, data.warnings && data.warnings.length > 0 ? 2000 : 1000);
179
+
180
+ } catch (error) {
181
+ console.error('Error creating conversation:', error);
182
+ showToast(error.message || 'Failed to create conversation', 'error');
183
+ }
184
+ });
185
+
186
+ // Load models on page load
187
+ document.addEventListener('DOMContentLoaded', () => {
188
+ loadModels();
189
+ });
190
+ </script>
191
+ {% endblock %}
@@ -0,0 +1,137 @@
1
+ """
2
+ Web interface adapter for ConversationManager.
3
+
4
+ This module provides a web-compatible interface for handling tool permissions
5
+ and other interactive prompts via HTTP/SSE.
6
+
7
+
8
+ """
9
+
10
+ import logging
11
+ import queue
12
+ import uuid
13
+ from typing import Optional, Dict
14
+
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class WebInterface:
20
+ """
21
+ Web interface adapter for handling interactive prompts.
22
+
23
+ This class acts as a bridge between ConversationManager and the web UI,
24
+ managing permission requests and responses via queues.
25
+ """
26
+
27
+ def __init__(self):
28
+ """Initialise the web interface."""
29
+ self._permission_requests = {} # request_id -> request_data
30
+ self._permission_responses = {} # request_id -> response
31
+ self._pending_request_id = None
32
+
33
+ def prompt_tool_permission(self, tool_name: str, tool_description: str = None) -> Optional[str]:
34
+ """
35
+ Request tool permission from web user.
36
+
37
+ This method:
38
+ 1. Creates a permission request with a unique ID
39
+ 2. Stores it for the web UI to retrieve
40
+ 3. Waits for a response (with timeout)
41
+ 4. Returns the user's choice
42
+
43
+ Args:
44
+ tool_name: Name of the tool
45
+ tool_description: Optional description of the tool
46
+
47
+ Returns:
48
+ 'allowed' if user grants permission for all future uses
49
+ 'denied' if user denies this and all future uses
50
+ 'once' if user grants permission for this time only
51
+ None if user cancelled or timeout
52
+ """
53
+ # Generate unique request ID
54
+ request_id = str(uuid.uuid4())
55
+
56
+ # Store the permission request
57
+ self._permission_requests[request_id] = {
58
+ 'tool_name': tool_name,
59
+ 'tool_description': tool_description,
60
+ 'status': 'pending'
61
+ }
62
+
63
+ # Store the current pending request ID
64
+ self._pending_request_id = request_id
65
+
66
+ logger.info(f"Web permission request created: {request_id} for tool: {tool_name}")
67
+
68
+ # Wait for response (with timeout)
69
+ # In a real implementation, this would use asyncio or threading.Event
70
+ # For now, we implement a simple polling mechanism
71
+ import time
72
+ timeout_seconds = 300 # 5 minutes timeout
73
+ poll_interval = 0.5 # Poll every 0.5 seconds
74
+ elapsed = 0
75
+
76
+ while elapsed < timeout_seconds:
77
+ if request_id in self._permission_responses:
78
+ response = self._permission_responses[request_id]
79
+
80
+ # Clean up
81
+ del self._permission_requests[request_id]
82
+ del self._permission_responses[request_id]
83
+ if self._pending_request_id == request_id:
84
+ self._pending_request_id = None
85
+
86
+ logger.info(f"Web permission response received for {request_id}: {response}")
87
+ return response
88
+
89
+ time.sleep(poll_interval)
90
+ elapsed += poll_interval
91
+
92
+ # Timeout - clean up and return None
93
+ logger.warning(f"Web permission request {request_id} timed out after {timeout_seconds}s")
94
+ if request_id in self._permission_requests:
95
+ del self._permission_requests[request_id]
96
+ if self._pending_request_id == request_id:
97
+ self._pending_request_id = None
98
+
99
+ return None
100
+
101
+ def get_pending_permission_request(self) -> Optional[Dict]:
102
+ """
103
+ Get the current pending permission request if any.
104
+
105
+ Returns:
106
+ Dictionary with request_id, tool_name, tool_description, or None
107
+ """
108
+ if self._pending_request_id and self._pending_request_id in self._permission_requests:
109
+ return {
110
+ 'request_id': self._pending_request_id,
111
+ **self._permission_requests[self._pending_request_id]
112
+ }
113
+ return None
114
+
115
+ def submit_permission_response(self, request_id: str, response: str) -> bool:
116
+ """
117
+ Submit a response to a pending permission request.
118
+
119
+ Args:
120
+ request_id: The request ID
121
+ response: User's response ('once', 'allowed', 'denied', or None for cancel)
122
+
123
+ Returns:
124
+ True if response was accepted, False if request not found
125
+ """
126
+ if request_id not in self._permission_requests:
127
+ logger.warning(f"Permission response submitted for unknown request: {request_id}")
128
+ return False
129
+
130
+ # Store the response
131
+ self._permission_responses[request_id] = response
132
+
133
+ # Update request status
134
+ self._permission_requests[request_id]['status'] = 'responded'
135
+
136
+ logger.info(f"Permission response submitted for {request_id}: {response}")
137
+ return True
@@ -0,0 +1,187 @@
1
+ Metadata-Version: 2.4
2
+ Name: dtSpark
3
+ Version: 1.0.4
4
+ Summary: Secure Personal AI Research Kit - Multi-provider LLM CLI/Web interface with MCP tool integration
5
+ Home-page: https://github.com/digital-thought/dtSpark
6
+ Author: Matthew Westwood-Hill
7
+ Author-email: Matthew Westwood-Hill <matthew@digital-thought.org>
8
+ License: MIT
9
+ Project-URL: Homepage, https://github.com/digital-thought/dtSpark
10
+ Project-URL: Documentation, https://github.com/digital-thought/dtSpark#readme
11
+ Project-URL: Repository, https://github.com/digital-thought/dtSpark
12
+ Project-URL: Issues, https://github.com/digital-thought/dtSpark/issues
13
+ Keywords: llm,ai,chatbot,aws,bedrock,anthropic,claude,ollama,mcp,model-context-protocol,cli,web
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Environment :: Console
16
+ Classifier: Environment :: Web Environment
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Intended Audience :: Information Technology
19
+ Classifier: Intended Audience :: Science/Research
20
+ Classifier: License :: OSI Approved :: MIT License
21
+ Classifier: Operating System :: OS Independent
22
+ Classifier: Programming Language :: Python :: 3
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
27
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
28
+ Classifier: Topic :: Communications :: Chat
29
+ Requires-Python: >=3.10
30
+ Description-Content-Type: text/markdown
31
+ License-File: LICENSE
32
+ Requires-Dist: boto3>=1.28.0
33
+ Requires-Dist: botocore>=1.31.0
34
+ Requires-Dist: fastapi>=0.100.0
35
+ Requires-Dist: uvicorn>=0.22.0
36
+ Requires-Dist: jinja2>=3.1.0
37
+ Requires-Dist: python-multipart>=0.0.6
38
+ Requires-Dist: sse-starlette>=1.6.0
39
+ Requires-Dist: rich>=13.0.0
40
+ Requires-Dist: prompt_toolkit>=3.0.0
41
+ Requires-Dist: httpx>=0.24.0
42
+ Requires-Dist: aiohttp>=3.8.0
43
+ Requires-Dist: mcp>=0.9.0
44
+ Requires-Dist: pyyaml>=6.0
45
+ Requires-Dist: dtPyAppFramework>=4.0.3
46
+ Requires-Dist: tiktoken>=0.5.0
47
+ Requires-Dist: ollama>=0.2.0
48
+ Requires-Dist: cryptography>=41.0.0
49
+ Requires-Dist: anthropic>=0.18.0
50
+ Requires-Dist: APScheduler>=3.10.0
51
+ Requires-Dist: markdown>=3.4.0
52
+ Provides-Extra: dev
53
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
54
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
55
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
56
+ Requires-Dist: black>=23.0.0; extra == "dev"
57
+ Requires-Dist: isort>=5.12.0; extra == "dev"
58
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
59
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
60
+ Provides-Extra: mysql
61
+ Requires-Dist: mysql-connector-python>=8.0.0; extra == "mysql"
62
+ Provides-Extra: postgresql
63
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == "postgresql"
64
+ Provides-Extra: mssql
65
+ Requires-Dist: pyodbc>=4.0.0; extra == "mssql"
66
+ Provides-Extra: all-databases
67
+ Requires-Dist: mysql-connector-python>=8.0.0; extra == "all-databases"
68
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == "all-databases"
69
+ Requires-Dist: pyodbc>=4.0.0; extra == "all-databases"
70
+ Dynamic: author
71
+ Dynamic: home-page
72
+ Dynamic: license-file
73
+ Dynamic: requires-python
74
+
75
+ # Spark - Secure Personal AI Research Kit
76
+
77
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
78
+ [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
79
+
80
+ **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.
81
+
82
+ ## Key Features
83
+
84
+ - **Multi-Provider Support** - AWS Bedrock, Anthropic Direct API, and Ollama local models
85
+ - **Dual Interface** - Rich CLI terminal UI and modern Web browser interface
86
+ - **MCP Tool Integration** - Connect external tools via Model Context Protocol
87
+ - **Intelligent Context Management** - Automatic conversation compaction with model-aware limits
88
+ - **Security Features** - Prompt inspection, tool permissions, and audit logging
89
+ - **Multiple Database Backends** - SQLite, MySQL, PostgreSQL, and Microsoft SQL Server
90
+
91
+ ## Quick Start
92
+
93
+ ### Installation
94
+
95
+ ```bash
96
+ pip install dtSpark
97
+ ```
98
+
99
+ ### First-Time Setup
100
+
101
+ Run the interactive setup wizard to configure Spark:
102
+
103
+ ```bash
104
+ spark --setup
105
+ ```
106
+
107
+ This guides you through:
108
+ - LLM provider selection and configuration
109
+ - Database setup
110
+ - Interface preferences
111
+ - Security settings
112
+
113
+ ### Running Spark
114
+
115
+ ```bash
116
+ # Start with CLI interface
117
+ spark
118
+
119
+ # Or use the alternative command
120
+ dtSpark
121
+ ```
122
+
123
+ ## Documentation
124
+
125
+ Comprehensive documentation is available in the [docs](docs/) folder:
126
+
127
+ - [Installation Guide](docs/installation.md) - Detailed installation instructions
128
+ - [Configuration Reference](docs/configuration.md) - Complete config.yaml documentation
129
+ - [Features Guide](docs/features.md) - Detailed feature documentation
130
+ - [CLI Reference](docs/cli-reference.md) - Command-line options and chat commands
131
+ - [Web Interface](docs/web-interface.md) - Web UI guide
132
+ - [MCP Integration](docs/mcp-integration.md) - Tool integration documentation
133
+ - [Security](docs/security.md) - Security features and best practices
134
+
135
+ ## Architecture Overview
136
+
137
+ ```mermaid
138
+ graph LR
139
+ subgraph Interfaces
140
+ CLI[CLI]
141
+ WEB[Web]
142
+ end
143
+
144
+ subgraph Core
145
+ CM[Conversation<br/>Manager]
146
+ end
147
+
148
+ subgraph Providers
149
+ BEDROCK[AWS Bedrock]
150
+ ANTHROPIC[Anthropic]
151
+ OLLAMA[Ollama]
152
+ end
153
+
154
+ subgraph Tools
155
+ MCP[MCP Servers]
156
+ BUILTIN[Built-in Tools]
157
+ end
158
+
159
+ CLI --> CM
160
+ WEB --> CM
161
+ CM --> BEDROCK
162
+ CM --> ANTHROPIC
163
+ CM --> OLLAMA
164
+ CM --> MCP
165
+ CM --> BUILTIN
166
+ ```
167
+
168
+ ## Requirements
169
+
170
+ - Python 3.10 or higher
171
+ - AWS credentials (for Bedrock)
172
+ - Anthropic API key (for direct API)
173
+ - Ollama server (for local models)
174
+
175
+ ## Licence
176
+
177
+ MIT Licence - see [LICENSE](LICENSE) for details.
178
+
179
+ ## Author
180
+
181
+ Matthew Westwood-Hill
182
+ matthew@digital-thought.org
183
+
184
+ ## Support
185
+
186
+ - **Documentation**: [docs/](docs/)
187
+ - **Issues**: [GitHub Issues](https://github.com/digital-thought/dtSpark/issues)
@@ -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=0bd7iPS59nWpAOQUOsdoohIYYjz-FwPKQxYjiMMnG9Y,6
8
+ dtSpark/cli_interface.py,sha256=aB-rFAh6o8GOwwecx-rSHEj3W4bmQHp51OPEBtC2CEw,96911
9
+ dtSpark/conversation_manager.py,sha256=e1aTJpUjxV96G9xrssJl1ujPJMZZwtfufQ8ZDb1WyAI,132270
10
+ dtSpark/launch.py,sha256=iE5f4KQIlQEbNioCx0PyVGYWREHIGBFuup_np4FZvZ4,941
11
+ dtSpark/aws/__init__.py,sha256=tVuUKO69R3ZOkHQNQo81ukGTdU0OAyYVxkH0DgtwaTM,261
12
+ dtSpark/aws/authentication.py,sha256=3rEyFK2BjeN-A1ztjtm3bdfA_XGWkdJlsmdlvCsV2QE,11288
13
+ dtSpark/aws/bedrock.py,sha256=j1OknN76LehIMRmoqzx8G3DUSqk2IsO3Fiy5AxQp7Fw,24250
14
+ dtSpark/aws/costs.py,sha256=eyjigH_Yef7g5cKqhR2QUx_7y4E6-NsLd9-WL52I2vM,11931
15
+ dtSpark/aws/pricing.py,sha256=pk85e--C5Iz0Y-6iWv_VfENAnrcWQ_9XK0fJQSlk5Xk,23388
16
+ dtSpark/core/__init__.py,sha256=kORX-9C7L91WxMTMUHXr3Yc09rb6oJNzEH5_KDRdgqM,477
17
+ dtSpark/core/application.py,sha256=sPGXH3GNH7VszCaBR8WW8GvSzfQ-7ccAs2U2BT6e15o,154605
18
+ dtSpark/core/context_compaction.py,sha256=FWN352EW8n-eWv0MzbOiWIiKcooRxeIAb7611eN-kdY,31898
19
+ dtSpark/daemon/__init__.py,sha256=xdKEyMsNXgIv6nNerpDcwf94c80n-BFoJFaucWxVF64,3300
20
+ dtSpark/daemon/__main__.py,sha256=sRNG4RJ-Ejvd-f7OAU5slPOtxVpCoC2OfazdTJro69Q,170
21
+ dtSpark/daemon/action_monitor.py,sha256=grejmbWWCMyDVQZ8HXn71OaGEMTFD-QK_N9g-oCemso,7772
22
+ dtSpark/daemon/daemon_app.py,sha256=ZuCJYTeb5dfUOF53F9ydF5rw1orGx35Utez-wI2VMTw,28673
23
+ dtSpark/daemon/daemon_manager.py,sha256=a5OitkSTjSzUaOj4gYzTmZh5QmAN3dxMelOPwESj-W0,9170
24
+ dtSpark/daemon/execution_coordinator.py,sha256=ykZ2iKe6XaoD3JCOjhnEbiD8q12d7opg9ZafZFiW7lQ,5869
25
+ dtSpark/daemon/pid_file.py,sha256=gAfxJcGfdvsjpY40Y1RV8DFB6mSAA4VH8HI26edxJns,4596
26
+ dtSpark/database/__init__.py,sha256=NaNZ-06nPUaXrq1C4W_YHdUWvcfMUAD8qdJOhPJSYco,25950
27
+ dtSpark/database/autonomous_actions.py,sha256=4HCgL6TuIZptA21vE39eReqBeOgXQ0mPJ5HXymbnH50,36022
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=0YEu7sjTn5PGVNs7tQ6gMwBZ_j_FjuhrzkCEmXugWmw,6531
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=QsCux3dJBnVqpXvWW8EE-uGHZTe_d6orOvJ2uGSod98,10909
40
+ dtSpark/limits/__init__.py,sha256=q0E5-J6qneu7ZIWjGLeMXbouDhE1oGVkAUIkWe2M5Bg,250
41
+ dtSpark/limits/costs.py,sha256=YpPTQ3uqCkrOr4xpVOkIEml_vdLbzIAak_rV__2-wxg,10213
42
+ dtSpark/limits/tokens.py,sha256=ExbD-91hrJ0gHKoq-L6xYWU8Zxn5Wgqme25ATmgJ8MM,13590
43
+ dtSpark/llm/__init__.py,sha256=Govebgc3ukJFyu7eyIwTeUcsBwpUTeWkF4xIstW9kQk,608
44
+ dtSpark/llm/anthropic_direct.py,sha256=gq66qyA5Mup0ySSRMczP2B6cbsxQMN82uULeQ-aEc68,18450
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=r7ePWK1sfSveN6--Ln-Brtrxkli61uJWSrPU0Qy0MZg,20633
49
+ dtSpark/mcp_integration/__init__.py,sha256=pFw-yTSSJ1yx_ksTe94eq8pBrwDD-5Z-UqSM3VO4deQ,157
50
+ dtSpark/mcp_integration/manager.py,sha256=b-FfmAas344Ordj6AIdwxCgl0dqPx0WiLIu4Vt4URBA,25149
51
+ dtSpark/mcp_integration/tool_selector.py,sha256=VYtKXdYEFK_aC22wOWKI0hm9S67DsZtHScI1HpZVnjE,10003
52
+ dtSpark/resources/config.yaml.template,sha256=A3goAx9qD9_lqbfB6UqKoIVSDYjo_EZFVP-snqQnwHA,23966
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=W9xe-HoeQOl4UfGz7xxFm9VldKeoUg79FVd7ZUXQswE,8040
56
+ dtSpark/safety/prompt_inspector.py,sha256=6FAR7UtcsEYtbfOEdwHsJ__cjqdAsKjNtKPXp85c0sw,16297
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=vShUXGI9VaQni3en3OIXuGx2HNT0uEL0MTkk46nh0sQ,21906
60
+ dtSpark/scheduler/execution_queue.py,sha256=7_yXnGxO-arZTl0qPbyE-kDhZDVXQKT2z9zIKj9s1SA,4954
61
+ dtSpark/scheduler/executor.py,sha256=n42MGNyZOoQohpYh1QFenZzFsv560S0h-o_-7FajkJc,43709
62
+ dtSpark/scheduler/manager.py,sha256=vwtmQadqf3cv1QzdZJzFqC0l3bBzIplGZ79BUjfsh4o,12846
63
+ dtSpark/tools/__init__.py,sha256=TPK-c8CmXheEkoiFzL9PMP8ve0hTpw9iIV2xlGLTsMc,147
64
+ dtSpark/tools/builtin.py,sha256=Bgyi99VJvcXtJS6M69s_Sn-TcdM7PSvkjLuYTt6EH9g,29484
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=sDOTEmLt3A0xhj-0rmM3jL8Spz3bf5_zfPNHqIDzH7A,20913
69
+ dtSpark/web/session.py,sha256=yoz4yKGqUiYtxc5qoKtyBxNH0JrITSUyzgfu5iTo_Lw,4972
70
+ dtSpark/web/ssl_utils.py,sha256=keDhLzEbc9REUGSdMls0vxBV3yPunR490u4j6EvB8dg,6624
71
+ dtSpark/web/web_interface.py,sha256=Jl50HxTatj6yzKFBvOxp51jlhNe3CqOqnBjT1uL8HEw,4713
72
+ dtSpark/web/endpoints/__init__.py,sha256=uOTiOKx6IDZ2kc0-2GS2hqZD2qX6KtwAhMMZQbS7pWc,356
73
+ dtSpark/web/endpoints/autonomous_actions.py,sha256=tHJtFvJJtpr34LujQu-udZvT4vY5TpJB3Sn0WPJ8giM,36588
74
+ dtSpark/web/endpoints/chat.py,sha256=w4Vi3X2e7orID0Ny5xF7vyTHe9mk8gaH7o67GB50psc,20641
75
+ dtSpark/web/endpoints/conversations.py,sha256=uFNpd_9DF1jqTEKFd9qRWK-uffXyTwz4Px9JIur_128,11728
76
+ dtSpark/web/endpoints/main_menu.py,sha256=8VUUBN7DopM0_Jy4Uaqkg-HHXxGVxz9uRcQ1_zXzM-Q,17752
77
+ dtSpark/web/endpoints/streaming.py,sha256=vhpLefhc1PUDlmZ3Lx4IXizZfHy45zPgv5POhb-TdFU,14581
78
+ dtSpark/web/static/css/dark-theme.css,sha256=K2q2C1s5kjqi_O1xAF86HTVFsI6sEfwPAPhVEfmT02M,8117
79
+ dtSpark/web/static/js/actions.js,sha256=NC9nLFfKEwffE88yBoaaGosmi4q9RoSVOPnziTD08GQ,37421
80
+ dtSpark/web/static/js/chat.js,sha256=s-TeeFgpRAsz0npeQHKPhQCgQawe03LBwLQYa7bjM84,21863
81
+ dtSpark/web/static/js/main.js,sha256=A5m_VDyEzMcfCL9nnId2oCtFecvWRlpedzzPbt34QGY,16235
82
+ dtSpark/web/static/js/sse-client.js,sha256=-YyRXNzSoQWrNLDvT8xGXtbgll_1JiP8p398OtQU7H8,8438
83
+ dtSpark/web/templates/actions.html,sha256=KHJ552XjwPCCOrz0WUkehRzNwuBkS7qVpsAoCx1lGZI,18852
84
+ dtSpark/web/templates/base.html,sha256=ne7kY8mnT5GpGDcxokQhNsn6H4tVksBE9BsXcJAsdmI,3765
85
+ dtSpark/web/templates/chat.html,sha256=OQiqmOV-Q71MxXt7M7yLcCGH0Jyhen4p3hLqU6829aw,32655
86
+ dtSpark/web/templates/conversations.html,sha256=URJX3W5-MjUjuUAXixziY1yFG-T6Ho5_u9Up7FcH70E,13004
87
+ dtSpark/web/templates/goodbye.html,sha256=4VnUgq6gHCMeJuty51qq8SZuTtpEMMUOsgTBut37Mc8,2825
88
+ dtSpark/web/templates/login.html,sha256=OkLf_uzMYhl_o9ER1RQZc8ch6-bCaiOokEhKbeEl8E8,3274
89
+ dtSpark/web/templates/main_menu.html,sha256=AXVFdEwAUWLFF_hXB7GrutwLTtfCqmuR1Yl5i39y3Co,37871
90
+ dtSpark/web/templates/new_conversation.html,sha256=hoiQ4Ew3lpFWHTsYza0JiBqqWJs7St7jTusKDnxRR8w,6844
91
+ dtspark-1.0.4.dist-info/licenses/LICENSE,sha256=jIuWlmbirwQabTwxfzE7SXT1LpCG-y_GRQ3VnoRTKgo,1101
92
+ dtspark-1.0.4.dist-info/METADATA,sha256=xrfDylfewoaeddXM9zaXzV6Yt5kDYLJeW7yga2mDhG0,5999
93
+ dtspark-1.0.4.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
94
+ dtspark-1.0.4.dist-info/entry_points.txt,sha256=IpIwa_a6XY8Z2w7DtgYAhpFHHEbha-zhLkyttWd3zpw,76
95
+ dtspark-1.0.4.dist-info/top_level.txt,sha256=x-6lMA6vNuxyDNJGNOKI4dyy7L0kOb9V98I5z46bJVY,8
96
+ dtspark-1.0.4.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ dtSpark = dtSpark.launch:main
3
+ spark = dtSpark.launch:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2025 Matthew Westwood-Hill / 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.
@@ -0,0 +1 @@
1
+ dtSpark