refactor: Major upgrade to v5.1b6 - AWS SSM support & Distributed Architecture

Core & Protocols:
- Native AWS SSM support added (aws ssm start-session).
- Improved Pexpect logic for ssm, kubectl, and docker.
- Cleaned connection success messages (omitting ports for non-IP protocols).

gRPC Layer:
- Migrated gRPC modules to 'connpy/grpc_layer/'.
- Implemented dynamic node naming (e.g. ssm-i-xxxx@aws) for accurate server-side logging.
- Added automatic sys.path resolution for gRPC generated modules.
- Enhanced InteractNode response with initial connection status.

Printer & Concurrency:
- Implemented ThreadLocalStream for isolated thread-safe output.
- Self-healing Console objects to prevent 'closed file' errors in test/async environments.
- Capture clean plugin output in remote executions.

AI & Services:
- Improved tool registration and debug visualization.
- Restored native dictionary returns for AI tools to fix Web UI rendering.
- Increased backup retention to 100 copies in SyncService.
- Silenced noisy auto-sync CLI messages.

Quality & Docs:
- Total tests: 267 (all passing).
- New test suites for gRPC layer and printer concurrency.
- Updated .gitignore to exclude internal planning docs.
- Full technical documentation regenerated with pdoc.
This commit is contained in:
2026-04-24 19:23:00 -03:00
parent 287acde1e4
commit 1c814eb9fd
94 changed files with 12656 additions and 22613 deletions
+16 -11
View File
@@ -73,10 +73,13 @@ class NodeService(BaseService):
def get_node_details(self, unique_id):
"""Return full configuration dictionary for a specific node."""
details = self.config.getitem(unique_id)
if not details:
try:
details = self.config.getitem(unique_id)
if not details:
raise NodeNotFoundError(f"Node '{unique_id}' not found.")
return details
except (KeyError, TypeError):
raise NodeNotFoundError(f"Node '{unique_id}' not found.")
return details
def explode_unique(self, unique_id):
"""Explode a unique ID into a dictionary of its parts."""
@@ -86,6 +89,14 @@ class NodeService(BaseService):
"""Generate and update the internal nodes cache."""
self.config._generate_nodes_cache(nodes=nodes, folders=folders, profiles=profiles)
def validate_parent_folder(self, unique_id):
"""Check if parent folder exists for a given node unique ID."""
node_folder = unique_id.partition("@")[2]
if node_folder:
parent_folder = f"@{node_folder}"
if parent_folder not in self.config._getallfolders():
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")
def add_node(self, unique_id, data, is_folder=False):
"""Logic for adding a new node or folder to configuration."""
@@ -104,9 +115,7 @@ class NodeService(BaseService):
# Check if parent folder exists when creating a subfolder
if "subfolder" in uniques:
parent_folder = f"@{uniques['folder']}"
if parent_folder not in all_folders:
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")
self.validate_parent_folder(unique_id)
self.config._folder_add(**uniques)
self.config._saveconfig(self.config.file)
@@ -115,11 +124,7 @@ class NodeService(BaseService):
raise NodeAlreadyExistsError(f"Node '{unique_id}' already exists.")
# Check if parent folder exists when creating a node in a folder
node_folder = unique_id.partition("@")[2]
if node_folder:
parent_folder = f"@{node_folder}"
if parent_folder not in all_folders:
raise NodeNotFoundError(f"Folder '{parent_folder}' not found.")
self.validate_parent_folder(unique_id)
# Ensure 'id' is in data for config._connections_add
if "id" not in data: