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,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