dtSpark 1.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dtSpark/__init__.py +0 -0
- dtSpark/_description.txt +1 -0
- dtSpark/_full_name.txt +1 -0
- dtSpark/_licence.txt +21 -0
- dtSpark/_metadata.yaml +6 -0
- dtSpark/_name.txt +1 -0
- dtSpark/_version.txt +1 -0
- dtSpark/aws/__init__.py +7 -0
- dtSpark/aws/authentication.py +296 -0
- dtSpark/aws/bedrock.py +578 -0
- dtSpark/aws/costs.py +318 -0
- dtSpark/aws/pricing.py +580 -0
- dtSpark/cli_interface.py +2645 -0
- dtSpark/conversation_manager.py +3050 -0
- dtSpark/core/__init__.py +12 -0
- dtSpark/core/application.py +3355 -0
- dtSpark/core/context_compaction.py +735 -0
- dtSpark/daemon/__init__.py +104 -0
- dtSpark/daemon/__main__.py +10 -0
- dtSpark/daemon/action_monitor.py +213 -0
- dtSpark/daemon/daemon_app.py +730 -0
- dtSpark/daemon/daemon_manager.py +289 -0
- dtSpark/daemon/execution_coordinator.py +194 -0
- dtSpark/daemon/pid_file.py +169 -0
- dtSpark/database/__init__.py +482 -0
- dtSpark/database/autonomous_actions.py +1191 -0
- dtSpark/database/backends.py +329 -0
- dtSpark/database/connection.py +122 -0
- dtSpark/database/conversations.py +520 -0
- dtSpark/database/credential_prompt.py +218 -0
- dtSpark/database/files.py +205 -0
- dtSpark/database/mcp_ops.py +355 -0
- dtSpark/database/messages.py +161 -0
- dtSpark/database/schema.py +673 -0
- dtSpark/database/tool_permissions.py +186 -0
- dtSpark/database/usage.py +167 -0
- dtSpark/files/__init__.py +4 -0
- dtSpark/files/manager.py +322 -0
- dtSpark/launch.py +39 -0
- dtSpark/limits/__init__.py +10 -0
- dtSpark/limits/costs.py +296 -0
- dtSpark/limits/tokens.py +342 -0
- dtSpark/llm/__init__.py +17 -0
- dtSpark/llm/anthropic_direct.py +446 -0
- dtSpark/llm/base.py +146 -0
- dtSpark/llm/context_limits.py +438 -0
- dtSpark/llm/manager.py +177 -0
- dtSpark/llm/ollama.py +578 -0
- dtSpark/mcp_integration/__init__.py +5 -0
- dtSpark/mcp_integration/manager.py +653 -0
- dtSpark/mcp_integration/tool_selector.py +225 -0
- dtSpark/resources/config.yaml.template +631 -0
- dtSpark/safety/__init__.py +22 -0
- dtSpark/safety/llm_service.py +111 -0
- dtSpark/safety/patterns.py +229 -0
- dtSpark/safety/prompt_inspector.py +442 -0
- dtSpark/safety/violation_logger.py +346 -0
- dtSpark/scheduler/__init__.py +20 -0
- dtSpark/scheduler/creation_tools.py +599 -0
- dtSpark/scheduler/execution_queue.py +159 -0
- dtSpark/scheduler/executor.py +1152 -0
- dtSpark/scheduler/manager.py +395 -0
- dtSpark/tools/__init__.py +4 -0
- dtSpark/tools/builtin.py +833 -0
- dtSpark/web/__init__.py +20 -0
- dtSpark/web/auth.py +152 -0
- dtSpark/web/dependencies.py +37 -0
- dtSpark/web/endpoints/__init__.py +17 -0
- dtSpark/web/endpoints/autonomous_actions.py +1125 -0
- dtSpark/web/endpoints/chat.py +621 -0
- dtSpark/web/endpoints/conversations.py +353 -0
- dtSpark/web/endpoints/main_menu.py +547 -0
- dtSpark/web/endpoints/streaming.py +421 -0
- dtSpark/web/server.py +578 -0
- dtSpark/web/session.py +167 -0
- dtSpark/web/ssl_utils.py +195 -0
- dtSpark/web/static/css/dark-theme.css +427 -0
- dtSpark/web/static/js/actions.js +1101 -0
- dtSpark/web/static/js/chat.js +614 -0
- dtSpark/web/static/js/main.js +496 -0
- dtSpark/web/static/js/sse-client.js +242 -0
- dtSpark/web/templates/actions.html +408 -0
- dtSpark/web/templates/base.html +93 -0
- dtSpark/web/templates/chat.html +814 -0
- dtSpark/web/templates/conversations.html +350 -0
- dtSpark/web/templates/goodbye.html +81 -0
- dtSpark/web/templates/login.html +90 -0
- dtSpark/web/templates/main_menu.html +983 -0
- dtSpark/web/templates/new_conversation.html +191 -0
- dtSpark/web/web_interface.py +137 -0
- dtspark-1.0.4.dist-info/METADATA +187 -0
- dtspark-1.0.4.dist-info/RECORD +96 -0
- dtspark-1.0.4.dist-info/WHEEL +5 -0
- dtspark-1.0.4.dist-info/entry_points.txt +3 -0
- dtspark-1.0.4.dist-info/licenses/LICENSE +21 -0
- dtspark-1.0.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Action Execution Queue module.
|
|
3
|
+
|
|
4
|
+
Provides thread-safe sequential execution queue for autonomous actions.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import queue
|
|
11
|
+
import threading
|
|
12
|
+
from typing import Callable, Any, Optional
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class ActionTask:
|
|
18
|
+
"""Represents an action execution task."""
|
|
19
|
+
action_id: int
|
|
20
|
+
user_guid: str
|
|
21
|
+
is_manual: bool = False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ActionExecutionQueue:
|
|
25
|
+
"""
|
|
26
|
+
Thread-safe queue for sequential action execution.
|
|
27
|
+
|
|
28
|
+
Ensures actions are processed one at a time to prevent
|
|
29
|
+
resource contention and ensure predictable behaviour.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, executor_func: Callable[[int, str, bool], Any]):
|
|
33
|
+
"""
|
|
34
|
+
Initialise the execution queue.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
executor_func: Function(action_id, user_guid, is_manual) to execute actions
|
|
38
|
+
"""
|
|
39
|
+
self.executor_func = executor_func
|
|
40
|
+
self._queue: queue.Queue[Optional[ActionTask]] = queue.Queue()
|
|
41
|
+
self._worker_thread: Optional[threading.Thread] = None
|
|
42
|
+
self._is_running = False
|
|
43
|
+
self._shutdown_event = threading.Event()
|
|
44
|
+
|
|
45
|
+
logging.info("ActionExecutionQueue initialised")
|
|
46
|
+
|
|
47
|
+
def start(self):
|
|
48
|
+
"""
|
|
49
|
+
Start the queue worker thread.
|
|
50
|
+
"""
|
|
51
|
+
if self._is_running:
|
|
52
|
+
logging.warning("Execution queue already running")
|
|
53
|
+
return
|
|
54
|
+
|
|
55
|
+
self._shutdown_event.clear()
|
|
56
|
+
self._is_running = True
|
|
57
|
+
self._worker_thread = threading.Thread(
|
|
58
|
+
target=self._worker_loop,
|
|
59
|
+
name="ActionExecutionWorker",
|
|
60
|
+
daemon=True
|
|
61
|
+
)
|
|
62
|
+
self._worker_thread.start()
|
|
63
|
+
logging.info("Action execution queue started")
|
|
64
|
+
|
|
65
|
+
def stop(self, timeout: float = 30.0):
|
|
66
|
+
"""
|
|
67
|
+
Stop the queue worker gracefully.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
timeout: Maximum time to wait for current task to complete
|
|
71
|
+
"""
|
|
72
|
+
if not self._is_running:
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
logging.info("Stopping action execution queue...")
|
|
76
|
+
self._is_running = False
|
|
77
|
+
self._shutdown_event.set()
|
|
78
|
+
|
|
79
|
+
# Put a sentinel value to unblock the queue
|
|
80
|
+
self._queue.put(None)
|
|
81
|
+
|
|
82
|
+
if self._worker_thread and self._worker_thread.is_alive():
|
|
83
|
+
self._worker_thread.join(timeout=timeout)
|
|
84
|
+
if self._worker_thread.is_alive():
|
|
85
|
+
logging.warning("Worker thread did not stop within timeout")
|
|
86
|
+
|
|
87
|
+
logging.info("Action execution queue stopped")
|
|
88
|
+
|
|
89
|
+
def is_running(self) -> bool:
|
|
90
|
+
"""Check if the queue is running."""
|
|
91
|
+
return self._is_running
|
|
92
|
+
|
|
93
|
+
def enqueue(self, action_id: int, user_guid: str, is_manual: bool = False):
|
|
94
|
+
"""
|
|
95
|
+
Add an action to the execution queue.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
action_id: ID of the action to execute
|
|
99
|
+
user_guid: User GUID for execution context
|
|
100
|
+
is_manual: Whether this is a manual "Run Now" execution
|
|
101
|
+
"""
|
|
102
|
+
if not self._is_running:
|
|
103
|
+
logging.warning("Cannot enqueue action: queue not running")
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
task = ActionTask(action_id=action_id, user_guid=user_guid, is_manual=is_manual)
|
|
107
|
+
self._queue.put(task)
|
|
108
|
+
logging.info(f"Enqueued action {action_id} (manual: {is_manual})")
|
|
109
|
+
|
|
110
|
+
def get_queue_size(self) -> int:
|
|
111
|
+
"""Get the number of pending tasks in the queue."""
|
|
112
|
+
return self._queue.qsize()
|
|
113
|
+
|
|
114
|
+
def _worker_loop(self):
|
|
115
|
+
"""
|
|
116
|
+
Worker loop that processes tasks from the queue.
|
|
117
|
+
"""
|
|
118
|
+
logging.info("Action execution worker started")
|
|
119
|
+
|
|
120
|
+
while self._is_running or not self._queue.empty():
|
|
121
|
+
try:
|
|
122
|
+
# Wait for a task with timeout to allow shutdown checks
|
|
123
|
+
try:
|
|
124
|
+
task = self._queue.get(timeout=1.0)
|
|
125
|
+
except queue.Empty:
|
|
126
|
+
# Check if we should shut down
|
|
127
|
+
if self._shutdown_event.is_set():
|
|
128
|
+
break
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
# Check for sentinel value
|
|
132
|
+
if task is None:
|
|
133
|
+
logging.debug("Received shutdown sentinel")
|
|
134
|
+
break
|
|
135
|
+
|
|
136
|
+
# Execute the task
|
|
137
|
+
self._execute_task(task)
|
|
138
|
+
self._queue.task_done()
|
|
139
|
+
|
|
140
|
+
except Exception as e:
|
|
141
|
+
logging.error(f"Error in worker loop: {e}")
|
|
142
|
+
|
|
143
|
+
logging.info("Action execution worker stopped")
|
|
144
|
+
|
|
145
|
+
def _execute_task(self, task: ActionTask):
|
|
146
|
+
"""
|
|
147
|
+
Execute a single task.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
task: The task to execute
|
|
151
|
+
"""
|
|
152
|
+
try:
|
|
153
|
+
logging.info(f"Executing action {task.action_id} (manual: {task.is_manual})")
|
|
154
|
+
self.executor_func(task.action_id, task.user_guid, task.is_manual)
|
|
155
|
+
logging.info(f"Completed action {task.action_id}")
|
|
156
|
+
|
|
157
|
+
except Exception as e:
|
|
158
|
+
logging.error(f"Failed to execute action {task.action_id}: {e}")
|
|
159
|
+
# Don't re-raise - we want to continue processing other tasks
|