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
dtSpark/core/application.py
CHANGED
|
@@ -84,6 +84,16 @@ def copy_to_clipboard(text: str) -> bool:
|
|
|
84
84
|
logging.error(f"Failed to copy to clipboard: {e}")
|
|
85
85
|
return False
|
|
86
86
|
|
|
87
|
+
# Common string constants (SonarCloud S1192)
|
|
88
|
+
_SETTING_BEDROCK_COST_TRACKING = 'llm_providers.aws_bedrock.cost_tracking.enabled'
|
|
89
|
+
_SETTING_COST_TRACKING = 'aws.cost_tracking.enabled'
|
|
90
|
+
_SETTING_OLLAMA_ENABLED = 'llm_providers.ollama.enabled'
|
|
91
|
+
_DEFAULT_RUNNING_DIR = "./running"
|
|
92
|
+
_PROMPT_ACCESS_MODE = "Select access mode"
|
|
93
|
+
_MSG_NO_MODELS = "No models available"
|
|
94
|
+
_MSG_MANAGED_CONVERSATION = "This conversation is managed by configuration"
|
|
95
|
+
_MSG_DELETE_CANCELLED = "Delete operation cancelled"
|
|
96
|
+
|
|
87
97
|
class AWSBedrockCLI(AbstractApp):
|
|
88
98
|
def __init__(self):
|
|
89
99
|
super().__init__(short_name=agent_type(), full_name=full_name(), version=version(),
|
|
@@ -371,10 +381,11 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
371
381
|
aws_session_token = self.settings.get('aws.session_token', None)
|
|
372
382
|
|
|
373
383
|
# Configure CLI cost tracking display
|
|
374
|
-
cost_tracking_enabled = self._get_nested_setting(
|
|
384
|
+
cost_tracking_enabled = self._get_nested_setting(_SETTING_BEDROCK_COST_TRACKING, None)
|
|
375
385
|
if cost_tracking_enabled is None:
|
|
376
|
-
cost_tracking_enabled = self.settings.get(
|
|
386
|
+
cost_tracking_enabled = self.settings.get(_SETTING_COST_TRACKING, False)
|
|
377
387
|
self.cli.cost_tracking_enabled = cost_tracking_enabled
|
|
388
|
+
self.cli.actions_enabled = self._get_nested_setting('autonomous_actions.enabled', False)
|
|
378
389
|
|
|
379
390
|
progress.update(task_config, advance=100)
|
|
380
391
|
|
|
@@ -391,7 +402,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
391
402
|
# Handle missing or various value types
|
|
392
403
|
if aws_enabled_raw is None:
|
|
393
404
|
# Setting not found via any method - check if other providers are enabled
|
|
394
|
-
ollama_check = self._get_nested_setting(
|
|
405
|
+
ollama_check = self._get_nested_setting(_SETTING_OLLAMA_ENABLED, False)
|
|
395
406
|
anthropic_check = self._get_nested_setting('llm_providers.anthropic.enabled', False)
|
|
396
407
|
if ollama_check or anthropic_check:
|
|
397
408
|
# Other providers configured, don't default to AWS
|
|
@@ -432,7 +443,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
432
443
|
self.cli.print_warning("Failed to authenticate with AWS Bedrock")
|
|
433
444
|
|
|
434
445
|
# Check if Ollama is available as fallback
|
|
435
|
-
ollama_enabled = self._get_nested_setting(
|
|
446
|
+
ollama_enabled = self._get_nested_setting(_SETTING_OLLAMA_ENABLED, False)
|
|
436
447
|
if not ollama_enabled:
|
|
437
448
|
self.cli.print_error("AWS authentication required (Ollama not configured)")
|
|
438
449
|
self.cli.print_info(f"Run: aws sso login --profile {aws_profile}")
|
|
@@ -457,7 +468,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
457
468
|
progress.update(task_llm, advance=20, description="[cyan]Checking Ollama...")
|
|
458
469
|
|
|
459
470
|
# Check Ollama configuration
|
|
460
|
-
ollama_enabled = self._get_nested_setting(
|
|
471
|
+
ollama_enabled = self._get_nested_setting(_SETTING_OLLAMA_ENABLED, False)
|
|
461
472
|
if ollama_enabled:
|
|
462
473
|
try:
|
|
463
474
|
ollama_url = self._get_nested_setting(
|
|
@@ -529,9 +540,9 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
529
540
|
|
|
530
541
|
# Task 3.5: Retrieve Bedrock cost information (silently, display later)
|
|
531
542
|
# Only if cost tracking is enabled in configuration
|
|
532
|
-
cost_tracking_enabled = self._get_nested_setting(
|
|
543
|
+
cost_tracking_enabled = self._get_nested_setting(_SETTING_BEDROCK_COST_TRACKING, None)
|
|
533
544
|
if cost_tracking_enabled is None:
|
|
534
|
-
cost_tracking_enabled = self.settings.get(
|
|
545
|
+
cost_tracking_enabled = self.settings.get(_SETTING_COST_TRACKING, False)
|
|
535
546
|
if cost_tracking_enabled and self.authenticator:
|
|
536
547
|
task_costs = progress.add_task("[cyan]Retrieving usage costs...", total=100)
|
|
537
548
|
self.bedrock_costs = None
|
|
@@ -796,77 +807,87 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
796
807
|
)
|
|
797
808
|
progress.update(task_conv, advance=100)
|
|
798
809
|
|
|
799
|
-
# Task 7: Initialise autonomous action scheduler
|
|
810
|
+
# Task 7: Initialise autonomous action scheduler (if enabled)
|
|
811
|
+
self.actions_enabled = self._get_nested_setting('autonomous_actions.enabled', False)
|
|
800
812
|
task_scheduler = progress.add_task("[cyan]Initialising action scheduler...", total=100)
|
|
801
|
-
try:
|
|
802
|
-
from dtSpark.scheduler import (
|
|
803
|
-
ActionSchedulerManager,
|
|
804
|
-
ActionExecutionQueue,
|
|
805
|
-
ActionExecutor
|
|
806
|
-
)
|
|
807
813
|
|
|
808
|
-
|
|
809
|
-
|
|
814
|
+
if not self.actions_enabled:
|
|
815
|
+
logging.info("Autonomous actions are disabled via configuration")
|
|
816
|
+
self.action_scheduler = None
|
|
817
|
+
self.execution_queue = None
|
|
818
|
+
self.action_executor = None
|
|
819
|
+
self.daemon_is_running = False
|
|
820
|
+
progress.update(task_scheduler, advance=100)
|
|
821
|
+
else:
|
|
822
|
+
try:
|
|
823
|
+
from dtSpark.scheduler import (
|
|
824
|
+
ActionSchedulerManager,
|
|
825
|
+
ActionExecutionQueue,
|
|
826
|
+
ActionExecutor
|
|
827
|
+
)
|
|
810
828
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
if self.mcp_manager:
|
|
814
|
-
def get_tools_func():
|
|
815
|
-
import asyncio
|
|
816
|
-
loop = getattr(self.mcp_manager, '_initialization_loop', None)
|
|
817
|
-
if loop and not loop.is_closed():
|
|
818
|
-
return loop.run_until_complete(self.mcp_manager.list_all_tools())
|
|
819
|
-
return []
|
|
820
|
-
|
|
821
|
-
self.action_executor = ActionExecutor(
|
|
822
|
-
database=self.database,
|
|
823
|
-
llm_manager=self.llm_manager,
|
|
824
|
-
mcp_manager=self.mcp_manager,
|
|
825
|
-
get_tools_func=get_tools_func,
|
|
826
|
-
config=config_for_manager
|
|
827
|
-
)
|
|
829
|
+
# Get database path for scheduler job store
|
|
830
|
+
db_path = self.database.db_path or ':memory:'
|
|
828
831
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
832
|
+
# Create executor with LLM manager and optional MCP manager
|
|
833
|
+
get_tools_func = None
|
|
834
|
+
if self.mcp_manager:
|
|
835
|
+
def get_tools_func():
|
|
836
|
+
import asyncio
|
|
837
|
+
loop = getattr(self.mcp_manager, '_initialization_loop', None)
|
|
838
|
+
if loop and not loop.is_closed():
|
|
839
|
+
return loop.run_until_complete(self.mcp_manager.list_all_tools())
|
|
840
|
+
return []
|
|
841
|
+
|
|
842
|
+
self.action_executor = ActionExecutor(
|
|
843
|
+
database=self.database,
|
|
844
|
+
llm_manager=self.llm_manager,
|
|
845
|
+
mcp_manager=self.mcp_manager,
|
|
846
|
+
get_tools_func=get_tools_func,
|
|
847
|
+
config=config_for_manager
|
|
848
|
+
)
|
|
833
849
|
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
execution_callback=lambda action_id, user_guid: self.execution_queue.enqueue(
|
|
838
|
-
action_id, user_guid, is_manual=False
|
|
850
|
+
# Create execution queue
|
|
851
|
+
self.execution_queue = ActionExecutionQueue(
|
|
852
|
+
executor_func=self.action_executor.execute
|
|
839
853
|
)
|
|
840
|
-
)
|
|
841
854
|
|
|
842
|
-
|
|
843
|
-
|
|
855
|
+
# Create scheduler manager
|
|
856
|
+
self.action_scheduler = ActionSchedulerManager(
|
|
857
|
+
db_path=db_path,
|
|
858
|
+
execution_callback=lambda action_id, user_guid: self.execution_queue.enqueue(
|
|
859
|
+
action_id, user_guid, is_manual=False
|
|
860
|
+
)
|
|
861
|
+
)
|
|
844
862
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
self.action_scheduler.initialise()
|
|
848
|
-
self.execution_queue.start()
|
|
863
|
+
# Check if daemon is running (for warning display later)
|
|
864
|
+
self.daemon_is_running = self._check_daemon_running()
|
|
849
865
|
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
logging.warning("Daemon is not running - scheduled actions will NOT execute until daemon is started")
|
|
866
|
+
# Initialise execution components (for manual "Run Now" from UI)
|
|
867
|
+
# Note: Scheduled execution is ONLY handled by the daemon process
|
|
868
|
+
self.action_scheduler.initialise()
|
|
869
|
+
self.execution_queue.start()
|
|
855
870
|
|
|
856
|
-
|
|
871
|
+
# UI never starts the scheduler - daemon handles all scheduled execution
|
|
872
|
+
if self.daemon_is_running:
|
|
873
|
+
logging.info("Daemon is running - scheduled actions will be executed by daemon")
|
|
874
|
+
else:
|
|
875
|
+
logging.warning("Daemon is not running - scheduled actions will NOT execute until daemon is started")
|
|
857
876
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
877
|
+
progress.update(task_scheduler, advance=100)
|
|
878
|
+
|
|
879
|
+
except ImportError as e:
|
|
880
|
+
logging.warning(f"Action scheduler not available (APScheduler not installed): {e}")
|
|
881
|
+
self.action_scheduler = None
|
|
882
|
+
self.execution_queue = None
|
|
883
|
+
self.action_executor = None
|
|
884
|
+
progress.update(task_scheduler, advance=100)
|
|
885
|
+
except Exception as e:
|
|
886
|
+
logging.error(f"Failed to initialise action scheduler: {e}")
|
|
887
|
+
self.action_scheduler = None
|
|
888
|
+
self.execution_queue = None
|
|
889
|
+
self.action_executor = None
|
|
890
|
+
progress.update(task_scheduler, advance=100)
|
|
870
891
|
|
|
871
892
|
# Display application info first (user identification)
|
|
872
893
|
self.cli.display_application_info(self.user_guid)
|
|
@@ -881,8 +902,8 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
881
902
|
if mcp_enabled and self.mcp_manager:
|
|
882
903
|
self.cli.display_mcp_status(self.mcp_manager)
|
|
883
904
|
|
|
884
|
-
# Display daemon status warning if daemon is not running
|
|
885
|
-
if hasattr(self, 'daemon_is_running') and not self.daemon_is_running:
|
|
905
|
+
# Display daemon status warning if daemon is not running (only when actions are enabled)
|
|
906
|
+
if self.actions_enabled and hasattr(self, 'daemon_is_running') and not self.daemon_is_running:
|
|
886
907
|
# Check if there are any scheduled actions
|
|
887
908
|
try:
|
|
888
909
|
actions = self.database.get_all_actions(include_disabled=False)
|
|
@@ -1638,7 +1659,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1638
1659
|
enable_filesystem_tools = Confirm.ask("Enable embedded filesystem tools?", default=False)
|
|
1639
1660
|
|
|
1640
1661
|
# Default values
|
|
1641
|
-
filesystem_allowed_path =
|
|
1662
|
+
filesystem_allowed_path = _DEFAULT_RUNNING_DIR
|
|
1642
1663
|
filesystem_access_mode = "read_write"
|
|
1643
1664
|
|
|
1644
1665
|
if enable_filesystem_tools:
|
|
@@ -1648,7 +1669,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1648
1669
|
|
|
1649
1670
|
filesystem_allowed_path = Prompt.ask(
|
|
1650
1671
|
"Allowed directory path (tools can only access files within this directory)",
|
|
1651
|
-
default=
|
|
1672
|
+
default=_DEFAULT_RUNNING_DIR
|
|
1652
1673
|
)
|
|
1653
1674
|
|
|
1654
1675
|
# Access mode
|
|
@@ -1661,7 +1682,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1661
1682
|
cli.console.print(" [2] Read/Write - Full access (read + write files, create directories)")
|
|
1662
1683
|
cli.console.print()
|
|
1663
1684
|
access_mode_choice = Prompt.ask(
|
|
1664
|
-
|
|
1685
|
+
_PROMPT_ACCESS_MODE,
|
|
1665
1686
|
choices=["1", "2"],
|
|
1666
1687
|
default="2"
|
|
1667
1688
|
)
|
|
@@ -1674,7 +1695,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1674
1695
|
enable_document_tools = Confirm.ask("Enable embedded document tools (MS Office & PDF)?", default=False)
|
|
1675
1696
|
|
|
1676
1697
|
# Default values
|
|
1677
|
-
document_allowed_path =
|
|
1698
|
+
document_allowed_path = _DEFAULT_RUNNING_DIR
|
|
1678
1699
|
document_access_mode = "read"
|
|
1679
1700
|
document_max_file_size = "50"
|
|
1680
1701
|
document_max_pdf_pages = "100"
|
|
@@ -1689,7 +1710,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1689
1710
|
|
|
1690
1711
|
document_allowed_path = Prompt.ask(
|
|
1691
1712
|
"Allowed directory path for documents",
|
|
1692
|
-
default=
|
|
1713
|
+
default=_DEFAULT_RUNNING_DIR
|
|
1693
1714
|
)
|
|
1694
1715
|
|
|
1695
1716
|
# Access mode
|
|
@@ -1702,7 +1723,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1702
1723
|
cli.console.print(" [2] Read/Write - Read and create documents")
|
|
1703
1724
|
cli.console.print()
|
|
1704
1725
|
doc_access_mode_choice = Prompt.ask(
|
|
1705
|
-
|
|
1726
|
+
_PROMPT_ACCESS_MODE,
|
|
1706
1727
|
choices=["1", "2"],
|
|
1707
1728
|
default="1"
|
|
1708
1729
|
)
|
|
@@ -1742,7 +1763,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1742
1763
|
enable_archive_tools = Confirm.ask("Enable embedded archive tools (ZIP, TAR)?", default=False)
|
|
1743
1764
|
|
|
1744
1765
|
# Default values
|
|
1745
|
-
archive_allowed_path =
|
|
1766
|
+
archive_allowed_path = _DEFAULT_RUNNING_DIR
|
|
1746
1767
|
archive_access_mode = "read"
|
|
1747
1768
|
archive_max_file_size = "100"
|
|
1748
1769
|
archive_max_files_to_list = "1000"
|
|
@@ -1754,7 +1775,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1754
1775
|
|
|
1755
1776
|
archive_allowed_path = Prompt.ask(
|
|
1756
1777
|
"Allowed directory path for archives",
|
|
1757
|
-
default=
|
|
1778
|
+
default=_DEFAULT_RUNNING_DIR
|
|
1758
1779
|
)
|
|
1759
1780
|
|
|
1760
1781
|
# Access mode
|
|
@@ -1767,7 +1788,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
1767
1788
|
cli.console.print(" [2] Read/Write - Read and extract archives to disk")
|
|
1768
1789
|
cli.console.print()
|
|
1769
1790
|
archive_access_mode_choice = Prompt.ask(
|
|
1770
|
-
|
|
1791
|
+
_PROMPT_ACCESS_MODE,
|
|
1771
1792
|
choices=["1", "2"],
|
|
1772
1793
|
default="1"
|
|
1773
1794
|
)
|
|
@@ -2211,14 +2232,14 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
2211
2232
|
if document_templates_path:
|
|
2212
2233
|
escaped_templates_path = document_templates_path.replace('\\', '/')
|
|
2213
2234
|
config_content = re.sub(
|
|
2214
|
-
r'(templates_path:\s+)(
|
|
2235
|
+
r'(templates_path:\s+)([^\s#]+)',
|
|
2215
2236
|
f'\\g<1>{escaped_templates_path}',
|
|
2216
2237
|
config_content
|
|
2217
2238
|
)
|
|
2218
2239
|
# Default author (if provided)
|
|
2219
2240
|
if document_default_author:
|
|
2220
2241
|
config_content = re.sub(
|
|
2221
|
-
r'(default_author:\s+)(
|
|
2242
|
+
r'(default_author:\s+)([^\s#]+)',
|
|
2222
2243
|
f'\\g<1>{document_default_author}',
|
|
2223
2244
|
config_content
|
|
2224
2245
|
)
|
|
@@ -2377,9 +2398,9 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
2377
2398
|
def regather_and_display_costs(self):
|
|
2378
2399
|
"""Re-gather AWS Bedrock cost information and display it."""
|
|
2379
2400
|
# Check if cost tracking is enabled (new path with legacy fallback)
|
|
2380
|
-
cost_tracking_enabled = self._get_nested_setting(
|
|
2401
|
+
cost_tracking_enabled = self._get_nested_setting(_SETTING_BEDROCK_COST_TRACKING, None)
|
|
2381
2402
|
if cost_tracking_enabled is None:
|
|
2382
|
-
cost_tracking_enabled = self.settings.get(
|
|
2403
|
+
cost_tracking_enabled = self.settings.get(_SETTING_COST_TRACKING, False)
|
|
2383
2404
|
if not cost_tracking_enabled:
|
|
2384
2405
|
self.cli.print_warning("Cost tracking is disabled in configuration")
|
|
2385
2406
|
return
|
|
@@ -2748,7 +2769,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
2748
2769
|
# Step 1: Select model (will be used for both creation and execution)
|
|
2749
2770
|
models = self.llm_manager.list_all_models()
|
|
2750
2771
|
if not models:
|
|
2751
|
-
self.cli.print_error(
|
|
2772
|
+
self.cli.print_error(_MSG_NO_MODELS)
|
|
2752
2773
|
return
|
|
2753
2774
|
|
|
2754
2775
|
self.cli.console.print("\n[bold cyan]Select Model[/bold cyan]")
|
|
@@ -2942,7 +2963,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
2942
2963
|
progress.update(task, advance=100)
|
|
2943
2964
|
|
|
2944
2965
|
if not models:
|
|
2945
|
-
self.cli.print_error(
|
|
2966
|
+
self.cli.print_error(_MSG_NO_MODELS)
|
|
2946
2967
|
return None
|
|
2947
2968
|
|
|
2948
2969
|
model_id = self.cli.display_models(models)
|
|
@@ -3223,7 +3244,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
3223
3244
|
# Check if conversation is predefined - if so, block file deletion
|
|
3224
3245
|
if self.database.is_conversation_predefined(self.conversation_manager.current_conversation_id):
|
|
3225
3246
|
self.cli.print_error("Cannot delete files from predefined conversations")
|
|
3226
|
-
self.cli.print_info(
|
|
3247
|
+
self.cli.print_info(_MSG_MANAGED_CONVERSATION)
|
|
3227
3248
|
self.cli.wait_for_enter()
|
|
3228
3249
|
continue
|
|
3229
3250
|
|
|
@@ -3247,7 +3268,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
3247
3268
|
file_ids_input = self.cli.get_input("File IDs to delete").strip()
|
|
3248
3269
|
|
|
3249
3270
|
if not file_ids_input:
|
|
3250
|
-
self.cli.print_info(
|
|
3271
|
+
self.cli.print_info(_MSG_DELETE_CANCELLED)
|
|
3251
3272
|
self.cli.wait_for_enter()
|
|
3252
3273
|
continue
|
|
3253
3274
|
|
|
@@ -3267,7 +3288,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
3267
3288
|
else:
|
|
3268
3289
|
self.cli.print_error("Failed to delete files")
|
|
3269
3290
|
else:
|
|
3270
|
-
self.cli.print_info(
|
|
3291
|
+
self.cli.print_info(_MSG_DELETE_CANCELLED)
|
|
3271
3292
|
else:
|
|
3272
3293
|
# Parse comma-separated IDs
|
|
3273
3294
|
try:
|
|
@@ -3297,7 +3318,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
3297
3318
|
if failed_ids:
|
|
3298
3319
|
self.cli.print_error(f"Failed to delete files with IDs: {', '.join(map(str, failed_ids))}")
|
|
3299
3320
|
else:
|
|
3300
|
-
self.cli.print_info(
|
|
3321
|
+
self.cli.print_info(_MSG_DELETE_CANCELLED)
|
|
3301
3322
|
|
|
3302
3323
|
except ValueError:
|
|
3303
3324
|
self.cli.print_error("Invalid file IDs. Please enter comma-separated numbers or 'all'")
|
|
@@ -3309,7 +3330,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
3309
3330
|
# Check if conversation is predefined - if so, block model changes
|
|
3310
3331
|
if self.database.is_conversation_predefined(self.conversation_manager.current_conversation_id):
|
|
3311
3332
|
self.cli.print_error("Cannot change model for predefined conversations")
|
|
3312
|
-
self.cli.print_info(
|
|
3333
|
+
self.cli.print_info(_MSG_MANAGED_CONVERSATION)
|
|
3313
3334
|
self.cli.wait_for_enter()
|
|
3314
3335
|
continue
|
|
3315
3336
|
|
|
@@ -3327,7 +3348,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
3327
3348
|
progress.update(task, advance=100)
|
|
3328
3349
|
|
|
3329
3350
|
if not models:
|
|
3330
|
-
self.cli.print_error(
|
|
3351
|
+
self.cli.print_error(_MSG_NO_MODELS)
|
|
3331
3352
|
self.cli.wait_for_enter()
|
|
3332
3353
|
continue
|
|
3333
3354
|
|
|
@@ -3374,7 +3395,7 @@ class AWSBedrockCLI(AbstractApp):
|
|
|
3374
3395
|
# Check if conversation is predefined - if so, block instruction changes
|
|
3375
3396
|
if self.database.is_conversation_predefined(self.conversation_manager.current_conversation_id):
|
|
3376
3397
|
self.cli.print_error("Cannot change instructions for predefined conversations")
|
|
3377
|
-
self.cli.print_info(
|
|
3398
|
+
self.cli.print_info(_MSG_MANAGED_CONVERSATION)
|
|
3378
3399
|
self.cli.wait_for_enter()
|
|
3379
3400
|
continue
|
|
3380
3401
|
|