open-swarm 0.1.1743070217__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 (89) hide show
  1. open_swarm-0.1.1743070217.dist-info/METADATA +258 -0
  2. open_swarm-0.1.1743070217.dist-info/RECORD +89 -0
  3. open_swarm-0.1.1743070217.dist-info/WHEEL +5 -0
  4. open_swarm-0.1.1743070217.dist-info/entry_points.txt +3 -0
  5. open_swarm-0.1.1743070217.dist-info/licenses/LICENSE +21 -0
  6. open_swarm-0.1.1743070217.dist-info/top_level.txt +1 -0
  7. swarm/__init__.py +3 -0
  8. swarm/agent/__init__.py +7 -0
  9. swarm/agent/agent.py +49 -0
  10. swarm/apps.py +53 -0
  11. swarm/auth.py +56 -0
  12. swarm/consumers.py +141 -0
  13. swarm/core.py +326 -0
  14. swarm/extensions/__init__.py +1 -0
  15. swarm/extensions/blueprint/__init__.py +36 -0
  16. swarm/extensions/blueprint/agent_utils.py +45 -0
  17. swarm/extensions/blueprint/blueprint_base.py +562 -0
  18. swarm/extensions/blueprint/blueprint_discovery.py +112 -0
  19. swarm/extensions/blueprint/blueprint_utils.py +17 -0
  20. swarm/extensions/blueprint/common_utils.py +12 -0
  21. swarm/extensions/blueprint/django_utils.py +203 -0
  22. swarm/extensions/blueprint/interactive_mode.py +102 -0
  23. swarm/extensions/blueprint/modes/rest_mode.py +37 -0
  24. swarm/extensions/blueprint/output_utils.py +95 -0
  25. swarm/extensions/blueprint/spinner.py +91 -0
  26. swarm/extensions/cli/__init__.py +0 -0
  27. swarm/extensions/cli/blueprint_runner.py +251 -0
  28. swarm/extensions/cli/cli_args.py +88 -0
  29. swarm/extensions/cli/commands/__init__.py +0 -0
  30. swarm/extensions/cli/commands/blueprint_management.py +31 -0
  31. swarm/extensions/cli/commands/config_management.py +15 -0
  32. swarm/extensions/cli/commands/edit_config.py +77 -0
  33. swarm/extensions/cli/commands/list_blueprints.py +22 -0
  34. swarm/extensions/cli/commands/validate_env.py +57 -0
  35. swarm/extensions/cli/commands/validate_envvars.py +39 -0
  36. swarm/extensions/cli/interactive_shell.py +41 -0
  37. swarm/extensions/cli/main.py +36 -0
  38. swarm/extensions/cli/selection.py +43 -0
  39. swarm/extensions/cli/utils/discover_commands.py +32 -0
  40. swarm/extensions/cli/utils/env_setup.py +15 -0
  41. swarm/extensions/cli/utils.py +105 -0
  42. swarm/extensions/config/__init__.py +6 -0
  43. swarm/extensions/config/config_loader.py +208 -0
  44. swarm/extensions/config/config_manager.py +258 -0
  45. swarm/extensions/config/server_config.py +49 -0
  46. swarm/extensions/config/setup_wizard.py +103 -0
  47. swarm/extensions/config/utils/__init__.py +0 -0
  48. swarm/extensions/config/utils/logger.py +36 -0
  49. swarm/extensions/launchers/__init__.py +1 -0
  50. swarm/extensions/launchers/build_launchers.py +14 -0
  51. swarm/extensions/launchers/build_swarm_wrapper.py +12 -0
  52. swarm/extensions/launchers/swarm_api.py +68 -0
  53. swarm/extensions/launchers/swarm_cli.py +304 -0
  54. swarm/extensions/launchers/swarm_wrapper.py +29 -0
  55. swarm/extensions/mcp/__init__.py +1 -0
  56. swarm/extensions/mcp/cache_utils.py +36 -0
  57. swarm/extensions/mcp/mcp_client.py +341 -0
  58. swarm/extensions/mcp/mcp_constants.py +7 -0
  59. swarm/extensions/mcp/mcp_tool_provider.py +110 -0
  60. swarm/llm/chat_completion.py +195 -0
  61. swarm/messages.py +132 -0
  62. swarm/migrations/0010_initial_chat_models.py +51 -0
  63. swarm/migrations/__init__.py +0 -0
  64. swarm/models.py +45 -0
  65. swarm/repl/__init__.py +1 -0
  66. swarm/repl/repl.py +87 -0
  67. swarm/serializers.py +12 -0
  68. swarm/settings.py +189 -0
  69. swarm/tool_executor.py +239 -0
  70. swarm/types.py +126 -0
  71. swarm/urls.py +89 -0
  72. swarm/util.py +124 -0
  73. swarm/utils/color_utils.py +40 -0
  74. swarm/utils/context_utils.py +272 -0
  75. swarm/utils/general_utils.py +162 -0
  76. swarm/utils/logger.py +61 -0
  77. swarm/utils/logger_setup.py +25 -0
  78. swarm/utils/message_sequence.py +173 -0
  79. swarm/utils/message_utils.py +95 -0
  80. swarm/utils/redact.py +68 -0
  81. swarm/views/__init__.py +41 -0
  82. swarm/views/api_views.py +46 -0
  83. swarm/views/chat_views.py +76 -0
  84. swarm/views/core_views.py +118 -0
  85. swarm/views/message_views.py +40 -0
  86. swarm/views/model_views.py +135 -0
  87. swarm/views/utils.py +457 -0
  88. swarm/views/web_views.py +149 -0
  89. swarm/wsgi.py +16 -0
File without changes
@@ -0,0 +1,251 @@
1
+ # src/swarm/extensions/blueprint/modes/cli_mode/blueprint_runner.py
2
+
3
+ import importlib.util
4
+ import os
5
+ import sys
6
+ import logging
7
+ from typing import Optional, Dict, Any, List
8
+ import asyncio
9
+ import argparse
10
+
11
+ from swarm.utils.general_utils import color_text
12
+
13
+ # Initialize logger for this module
14
+ from swarm.utils.logger_setup import setup_logger
15
+
16
+ logger = setup_logger(__name__)
17
+
18
+
19
+ def load_blueprint(blueprint_path: str) -> Any:
20
+ """
21
+ Dynamically load a blueprint module from the given file path.
22
+
23
+ Args:
24
+ blueprint_path (str): Path to the blueprint's Python file.
25
+
26
+ Returns:
27
+ Any: The loaded blueprint module.
28
+
29
+ Raises:
30
+ ImportError: If the module cannot be imported.
31
+ """
32
+ spec = importlib.util.spec_from_file_location("blueprint_module", blueprint_path)
33
+ print(f"DEBUG: Attempting to load blueprint at path: {blueprint_path}")
34
+ module = importlib.util.module_from_spec(spec)
35
+ try:
36
+ spec.loader.exec_module(module) # type: ignore
37
+ logger.info(f"Successfully loaded blueprint from {blueprint_path}")
38
+ except Exception as e:
39
+ logger.error(f"Failed to import blueprint at {blueprint_path}: {e}")
40
+ raise ImportError(f"Failed to import blueprint at {blueprint_path}: {e}")
41
+ return module
42
+
43
+
44
+ def run_blueprint_framework(blueprint_module: Any) -> None:
45
+ """
46
+ Runs the blueprint in framework integration mode by invoking its execute() function.
47
+
48
+ Args:
49
+ blueprint_module: The loaded blueprint module.
50
+
51
+ Raises:
52
+ AttributeError: If the blueprint does not have an execute() function.
53
+ """
54
+ if not hasattr(blueprint_module, 'execute'):
55
+ logger.error("The blueprint does not have an execute() function.")
56
+ raise AttributeError("The blueprint does not have an execute() function.")
57
+
58
+ execute_func = blueprint_module.execute
59
+
60
+ # Optionally, load configuration from environment or a config file
61
+ config = {}
62
+
63
+ try:
64
+ result = execute_func(config)
65
+ print("Execution Result:")
66
+ print("Status:", result.get("status"))
67
+ print("Messages:")
68
+ for msg in result.get("messages", []):
69
+ print(f"{msg.get('role')}: {msg.get('content')}")
70
+ print("Metadata:", result.get("metadata"))
71
+ logger.info(f"Blueprint executed successfully with result: {result}")
72
+ except Exception as e:
73
+ logger.error(f"Error executing blueprint: {e}")
74
+ print(f"Error executing blueprint: {e}")
75
+
76
+
77
+ def run_blueprint_interactive(blueprint_module: Any) -> None:
78
+ """
79
+ Runs the blueprint in interactive standalone mode by invoking its interactive_mode() function.
80
+
81
+ Args:
82
+ blueprint_module: The loaded blueprint module.
83
+
84
+ Raises:
85
+ AttributeError: If the blueprint does not have an interactive_mode() function.
86
+ """
87
+ if not hasattr(blueprint_module, 'interactive_mode'):
88
+ logger.error("The blueprint does not have an interactive_mode() function.")
89
+ raise AttributeError("The blueprint does not have an interactive_mode() function.")
90
+
91
+ interactive_func = blueprint_module.interactive_mode
92
+
93
+ try:
94
+ interactive_func()
95
+ logger.info("Blueprint interactive mode executed successfully.")
96
+ except Exception as e:
97
+ logger.error(f"Error in interactive mode: {e}")
98
+ print(f"Error in interactive mode: {e}")
99
+
100
+
101
+ async def run_blueprint_mode(
102
+ blueprints_to_load: List[str],
103
+ config: Dict[str, Any],
104
+ blueprints_metadata: Dict[str, Dict[str, Any]],
105
+ args: Any
106
+ ) -> None:
107
+ """
108
+ Executes the selected blueprints in the specified mode.
109
+
110
+ Args:
111
+ blueprints_to_load (List[str]): List of blueprint names to load.
112
+ config (Dict[str, Any]): Configuration dictionary.
113
+ blueprints_metadata (Dict[str, Dict[str, Any]]): Metadata of available blueprints.
114
+ args (Any): Parsed command-line arguments.
115
+ """
116
+ for blueprint_name in blueprints_to_load:
117
+ blueprint_class = blueprints_metadata[blueprint_name].get("blueprint_class")
118
+ if not blueprint_class:
119
+ logger.warning(f"No blueprint_class defined for blueprint '{blueprint_name}'. Skipping.")
120
+ continue
121
+
122
+ blueprint_instance = blueprint_class(config=config)
123
+ logger.info(f"Running blueprint '{blueprint_name}' in '{args.mode}' mode.")
124
+
125
+ if args.mode == "cli":
126
+ try:
127
+ blueprint_instance.interactive_mode(stream=False)
128
+ logger.info(f"Blueprint '{blueprint_name}' executed in CLI mode.")
129
+ except Exception as e:
130
+ logger.error(f"Error running blueprint '{blueprint_name}' in CLI mode: {e}")
131
+ elif args.mode == "rest":
132
+ try:
133
+ # Implement REST mode logic here
134
+ # Example: blueprint_instance.rest_mode()
135
+ logger.info(f"Blueprint '{blueprint_name}' executed in REST mode.")
136
+ except Exception as e:
137
+ logger.error(f"Error running blueprint '{blueprint_name}' in REST mode: {e}")
138
+ elif args.mode == "mcp-host":
139
+ try:
140
+ # Implement MCP-host mode logic here
141
+ # Example: blueprint_instance.mcp_host_mode()
142
+ logger.info(f"Blueprint '{blueprint_name}' executed in MCP-host mode.")
143
+ except Exception as e:
144
+ logger.error(f"Error running blueprint '{blueprint_name}' in MCP-host mode: {e}")
145
+ else:
146
+ logger.error(f"Unsupported mode: {args.mode}")
147
+ print(color_text(f"Unsupported mode: {args.mode}", "red"))
148
+
149
+
150
+ def prompt_user_to_select_blueprint(blueprints_metadata: Dict[str, Dict[str, Any]]) -> Optional[str]:
151
+ """
152
+ Allow the user to select a blueprint from available options.
153
+
154
+ Args:
155
+ blueprints_metadata (Dict[str, Dict[str, Any]]): Metadata of available blueprints.
156
+
157
+ Returns:
158
+ Optional[str]: Selected blueprint name, or None if no selection is made.
159
+ """
160
+ if not blueprints_metadata:
161
+ logger.warning("No blueprints available. Blueprint selection skipped.")
162
+ print(color_text("No blueprints available. Please add blueprints to continue.", "yellow"))
163
+ return None
164
+
165
+ print("\nAvailable Blueprints:")
166
+ for idx, (key, metadata) in enumerate(blueprints_metadata.items(), start=1):
167
+ print(f"{idx}. {metadata.get('title', key)} - {metadata.get('description', 'No description available')}")
168
+
169
+ while True:
170
+ try:
171
+ choice_input = input("\nEnter the number of the blueprint you want to run (0 to cancel): ").strip()
172
+ if not choice_input:
173
+ print(f"Please enter a number between 0 and {len(blueprints_metadata)}.")
174
+ logger.warning("User entered empty input for blueprint selection.")
175
+ continue
176
+
177
+ choice = int(choice_input)
178
+ if choice == 0:
179
+ logger.info("User chose to cancel blueprint selection.")
180
+ return None
181
+ elif 1 <= choice <= len(blueprints_metadata):
182
+ selected_key = list(blueprints_metadata.keys())[choice - 1]
183
+ logger.info(f"User selected blueprint: '{selected_key}'")
184
+ return selected_key
185
+ else:
186
+ print(f"Please enter a number between 0 and {len(blueprints_metadata)}.")
187
+ logger.warning(f"User entered invalid blueprint number: {choice}")
188
+ except ValueError:
189
+ print("Invalid input. Please enter a valid number.")
190
+ logger.warning("User entered non-integer value for blueprint selection.")
191
+
192
+
193
+ def main():
194
+ """
195
+ Main entry point for the blueprint runner CLI.
196
+ """
197
+ parser = argparse.ArgumentParser(description="Blueprint Runner CLI")
198
+ parser.add_argument(
199
+ "blueprint_path",
200
+ type=str,
201
+ help="Path to the blueprint's Python file."
202
+ )
203
+ parser.add_argument(
204
+ "--interactive",
205
+ action="store_true",
206
+ help="Run the blueprint in interactive mode."
207
+ )
208
+ parser.add_argument(
209
+ "--mode",
210
+ type=str,
211
+ choices=["cli", "rest", "mcp-host"],
212
+ default="cli",
213
+ help="Mode to run the blueprint."
214
+ )
215
+
216
+ args = parser.parse_args()
217
+
218
+ try:
219
+ blueprint_module = load_blueprint(args.blueprint_path)
220
+ except ImportError as e:
221
+ print(color_text(str(e), "red"))
222
+ sys.exit(1)
223
+
224
+ if args.interactive:
225
+ try:
226
+ run_blueprint_interactive(blueprint_module)
227
+ except AttributeError as e:
228
+ print(color_text(str(e), "red"))
229
+ sys.exit(1)
230
+ else:
231
+ try:
232
+ run_blueprint_framework(blueprint_module)
233
+ except AttributeError as e:
234
+ print(color_text(str(e), "red"))
235
+ sys.exit(1)
236
+
237
+
238
+ if __name__ == "__main__":
239
+ try:
240
+ main()
241
+ except KeyboardInterrupt:
242
+ print("\nReceived shutdown signal (Ctrl+C)")
243
+ logger.info("Received shutdown signal (Ctrl+C)")
244
+ sys.exit(0)
245
+ except Exception as e:
246
+ logger.error(f"Unhandled exception: {e}")
247
+ print(color_text(f"\nFatal error: {e}", "red"))
248
+ sys.exit(1)
249
+ finally:
250
+ logger.info("Blueprint runner terminated.")
251
+ sys.exit(0)
@@ -0,0 +1,88 @@
1
+ # src/swarm/extensions/blueprint/modes/cli_mode/cli_args.py
2
+
3
+ import argparse
4
+ from typing import Namespace
5
+
6
+ def parse_arguments() -> Namespace:
7
+ """
8
+ Parse command-line arguments for dynamic LLM configuration, MCP server management, and other overrides.
9
+
10
+ Returns:
11
+ argparse.Namespace: Parsed command-line arguments.
12
+ """
13
+ parser = argparse.ArgumentParser(
14
+ description="Run Open Swarm MCP in various modes or manage configurations."
15
+ )
16
+ subparsers = parser.add_subparsers(dest="command", help="Available commands")
17
+
18
+ # Subparser for running modes
19
+ run_parser = subparsers.add_parser("run", help="Run Open Swarm MCP in various modes.")
20
+ run_parser.add_argument(
21
+ "--mode",
22
+ type=str,
23
+ choices=["cli", "rest", "mcp-host"],
24
+ default="cli",
25
+ help="Select the mode to run the MCP (cli, rest, mcp-host). Default is 'cli'."
26
+ )
27
+ run_parser.add_argument(
28
+ "--config",
29
+ type=str,
30
+ default=None, # Will be set dynamically in main.py
31
+ help="Path to the MCP server configuration file."
32
+ )
33
+ run_parser.add_argument(
34
+ "--llm",
35
+ type=str,
36
+ help="Override the LLM specified in the config."
37
+ )
38
+ run_parser.add_argument(
39
+ "--llm-model",
40
+ type=str,
41
+ help="Override the LLM model specified in the config."
42
+ )
43
+ run_parser.add_argument(
44
+ "--temperature",
45
+ type=float,
46
+ help="Override the LLM temperature specified in the config."
47
+ )
48
+ run_parser.add_argument(
49
+ "--blueprint",
50
+ type=str,
51
+ action='append',
52
+ help="Specify one or more blueprints to load (can be used multiple times)."
53
+ )
54
+ run_parser.add_argument(
55
+ "--setup",
56
+ action='store_true',
57
+ help="Re-run the setup wizard regardless of existing configuration."
58
+ )
59
+
60
+ # Subparser for configuration management
61
+ config_parser = subparsers.add_parser("config", help="Manage Swarm MCP configurations.")
62
+ config_subparsers = config_parser.add_subparsers(dest="config_command", help="Configuration commands")
63
+
64
+ # Add LLM
65
+ add_llm_parser = config_subparsers.add_parser("add-llm", help="Add a new LLM.")
66
+ # No additional arguments; will use interactive prompts
67
+
68
+ # Remove LLM
69
+ remove_llm_parser = config_subparsers.add_parser("remove-llm", help="Remove an existing LLM.")
70
+ remove_llm_parser.add_argument(
71
+ "llm_name",
72
+ type=str,
73
+ help="Name of the LLM to remove."
74
+ )
75
+
76
+ # Add MCP server
77
+ add_server_parser = config_subparsers.add_parser("add-server", help="Add a new MCP server.")
78
+ # No additional arguments; will use interactive prompts
79
+
80
+ # Remove MCP server
81
+ remove_server_parser = config_subparsers.add_parser("remove-server", help="Remove an existing MCP server.")
82
+ remove_server_parser.add_argument(
83
+ "server_name",
84
+ type=str,
85
+ help="Name of the MCP server to remove."
86
+ )
87
+
88
+ return parser.parse_args()
File without changes
@@ -0,0 +1,31 @@
1
+ # Handles blueprint discovery and validation for the CLI
2
+
3
+ from swarm.extensions.blueprint.discovery import discover_blueprints
4
+ from swarm.extensions.config.config_loader import load_server_config
5
+
6
+ def list_blueprints():
7
+ """List available blueprints and their metadata."""
8
+ blueprints = discover_blueprints()
9
+ if not blueprints:
10
+ print("No blueprints discovered.")
11
+ return
12
+ print("Discovered Blueprints:")
13
+ for name, metadata in blueprints.items():
14
+ print(f"- {name}: {metadata.get('description', 'No description available.')}")
15
+
16
+ cat > src/swarm/extensions/cli/commands/config_management.py << 'EOF'
17
+ # Handles configuration management workflows (e.g., LLM, MCP servers)
18
+
19
+ from swarm.extensions.config.config_loader import (
20
+ load_server_config,
21
+ save_server_config,
22
+ )
23
+
24
+ def add_llm(model_name, api_key):
25
+ """Add a new LLM configuration."""
26
+ config = load_server_config()
27
+ if "llms" not in config:
28
+ config["llms"] = {}
29
+ config["llms"][model_name] = {"api_key": api_key}
30
+ save_server_config(config)
31
+ print(f"Added LLM '{model_name}' to configuration.")
@@ -0,0 +1,15 @@
1
+ # Handles configuration management workflows (e.g., LLM, MCP servers)
2
+
3
+ from swarm.extensions.config.config_loader import (
4
+ load_server_config,
5
+ save_server_config,
6
+ )
7
+
8
+ def add_llm(model_name, api_key):
9
+ """Add a new LLM configuration."""
10
+ config = load_server_config()
11
+ if "llms" not in config:
12
+ config["llms"] = {}
13
+ config["llms"][model_name] = {"api_key": api_key}
14
+ save_server_config(config)
15
+ print(f"Added LLM '{model_name}' to configuration.")
@@ -0,0 +1,77 @@
1
+ import argparse
2
+ import json
3
+ from swarm.extensions.config.config_loader import (
4
+ load_server_config,
5
+ save_server_config,
6
+ )
7
+ from pathlib import Path
8
+
9
+ CONFIG_PATH = Path("swarm_config.json").resolve()
10
+
11
+ def list_config(config):
12
+ """
13
+ List current configuration settings.
14
+
15
+ Args:
16
+ config (dict): The current configuration.
17
+ """
18
+ print(json.dumps(config, indent=4))
19
+
20
+ def edit_config_interactive(config):
21
+ """
22
+ Interactive editing of the configuration file.
23
+
24
+ Args:
25
+ config (dict): The current configuration.
26
+ """
27
+ print("Current configuration:")
28
+ list_config(config)
29
+
30
+ print("\nEdit the settings (leave blank to keep current value):")
31
+ for key, value in config.items():
32
+ new_value = input(f"{key} [{value}]: ").strip()
33
+ if new_value:
34
+ config[key] = new_value
35
+
36
+ print("\nUpdated configuration:")
37
+ list_config(config)
38
+
39
+ def edit_config_field(config, field, value):
40
+ """
41
+ Edit a specific field in the configuration.
42
+
43
+ Args:
44
+ config (dict): The current configuration.
45
+ field (str): The field to edit.
46
+ value (str): The new value for the field.
47
+ """
48
+ if field not in config:
49
+ print(f"Field '{field}' not found in configuration.")
50
+ return
51
+ config[field] = value
52
+ print(f"Updated {field} to {value}.")
53
+
54
+ def main():
55
+ parser = argparse.ArgumentParser(description="Edit the swarm_config.json file.")
56
+ parser.add_argument("--list", action="store_true", help="List current configuration")
57
+ parser.add_argument("--field", help="The configuration field to edit")
58
+ parser.add_argument("--value", help="The new value for the specified field")
59
+ parser.add_argument("--interactive", action="store_true", help="Interactively edit the configuration")
60
+ args = parser.parse_args()
61
+
62
+ try:
63
+ config = load_server_config(str(CONFIG_PATH))
64
+ except FileNotFoundError as e:
65
+ print(f"Error: {e}")
66
+ return
67
+
68
+ if args.list:
69
+ list_config(config)
70
+ elif args.interactive:
71
+ edit_config_interactive(config)
72
+ save_server_config(str(CONFIG_PATH), config)
73
+ elif args.field and args.value:
74
+ edit_config_field(config, args.field, args.value)
75
+ save_server_config(str(CONFIG_PATH), config)
76
+ else:
77
+ parser.print_help()
@@ -0,0 +1,22 @@
1
+ """
2
+ Command: list_blueprints
3
+ Description: Lists all blueprints available in the system.
4
+ """
5
+
6
+ from pathlib import Path
7
+ from swarm.extensions.blueprint.blueprint_discovery import discover_blueprints
8
+
9
+ # Metadata for dynamic registration
10
+ description = "Lists all blueprints available in the system."
11
+ usage = "list_blueprints"
12
+
13
+ def list_blueprints():
14
+ """Returns a list of blueprints."""
15
+ blueprints_dir = Path(__file__).resolve().parent.parent.parent / "blueprints"
16
+ return discover_blueprints([str(blueprints_dir)])
17
+
18
+ def execute():
19
+ """Execute the command to list blueprints."""
20
+ blueprints = list_blueprints()
21
+ for blueprint_id, metadata in blueprints.items():
22
+ print(f"Blueprint ID: {blueprint_id}, Title: {metadata.get('title', 'No title')}")
@@ -0,0 +1,57 @@
1
+ import os
2
+ import argparse
3
+ from swarm.extensions.config.config_loader import load_server_config
4
+ from swarm.extensions.blueprint.blueprint_base import BlueprintBase
5
+
6
+ CONFIG_PATH = "swarm_config.json"
7
+
8
+ def validate_all_env_vars(config):
9
+ """
10
+ Validate all environment variables for the current configuration.
11
+ """
12
+ required_vars = config.get("required_env_vars", [])
13
+ missing_vars = [var for var in required_vars if var not in os.environ]
14
+
15
+ if missing_vars:
16
+ print(f"Missing environment variables: {', '.join(missing_vars)}")
17
+ return False
18
+ print("All required environment variables are set.")
19
+ return True
20
+
21
+ def validate_blueprint_env_vars(config, blueprint_name):
22
+ """
23
+ Validate environment variables for a specific blueprint.
24
+
25
+ Args:
26
+ config (dict): The configuration dictionary.
27
+ blueprint_name (str): The name of the blueprint to validate.
28
+ """
29
+ blueprint_config = config.get("blueprints", {}).get(blueprint_name, {})
30
+ blueprint = BlueprintBase(blueprint_config)
31
+ required_vars = blueprint.required_env_vars()
32
+ missing_vars = [var for var in required_vars if var not in os.environ]
33
+
34
+ if missing_vars:
35
+ print(f"Missing environment variables for blueprint '{blueprint_name}': {', '.join(missing_vars)}")
36
+ return False
37
+ print(f"All required environment variables are set for blueprint '{blueprint_name}'.")
38
+ return True
39
+
40
+ def main():
41
+ parser = argparse.ArgumentParser(description="Validate environment variables.")
42
+ parser.add_argument("--blueprint", help="Validate environment variables for a specific blueprint.")
43
+ args = parser.parse_args()
44
+
45
+ try:
46
+ config = load_server_config(CONFIG_PATH)
47
+ except FileNotFoundError as e:
48
+ print(f"Error: {e}")
49
+ return
50
+
51
+ if args.blueprint:
52
+ validate_blueprint_env_vars(config, args.blueprint)
53
+ else:
54
+ validate_all_env_vars(config)
55
+
56
+ if __name__ == "__main__":
57
+ main()
@@ -0,0 +1,39 @@
1
+ from swarm.extensions.blueprint.blueprint_discovery import discover_blueprints
2
+ from swarm.extensions.config.config_loader import load_env_config, validate_env_vars
3
+ import argparse
4
+
5
+ def validate_envvars(blueprint_name=None):
6
+ """
7
+ Validate environment variables for blueprints.
8
+
9
+ Args:
10
+ blueprint_name (str, optional): The name of the blueprint to validate.
11
+ Validates all blueprints if None.
12
+ """
13
+ # Discover blueprints
14
+ blueprints = discover_blueprints(["blueprints"])
15
+
16
+ if blueprint_name:
17
+ blueprint = blueprints.get(blueprint_name)
18
+ if not blueprint:
19
+ print(f"Blueprint '{blueprint_name}' not found.")
20
+ return
21
+ required_vars = blueprint.get("env_vars", [])
22
+ env_vars = load_env_config()
23
+ validation = validate_env_vars(env_vars, required_vars)
24
+ print(f"Validation for '{blueprint_name}': {validation}")
25
+ else:
26
+ # Global validation
27
+ env_vars = load_env_config()
28
+ print("Global Environment Validation:")
29
+ for blueprint_name, blueprint_data in blueprints.items():
30
+ required_vars = blueprint_data.get("env_vars", [])
31
+ validation = validate_env_vars(env_vars, required_vars)
32
+ print(f"Validation for '{blueprint_name}': {validation}")
33
+
34
+ def main():
35
+ parser = argparse.ArgumentParser(description="Validate environment variables.")
36
+ parser.add_argument("--blueprint", help="Specify a blueprint to validate")
37
+ args = parser.parse_args()
38
+
39
+ validate_envvars(blueprint_name=args.blueprint)
@@ -0,0 +1,41 @@
1
+ """
2
+ Interactive CLI shell for dynamic commands.
3
+ """
4
+
5
+ from swarm.extensions.cli.utils.discover_commands import discover_commands
6
+ import os
7
+
8
+ COMMANDS_DIR = os.path.join(os.path.dirname(__file__), "commands")
9
+
10
+ def interactive_shell():
11
+ """Launch an interactive CLI shell."""
12
+ commands = discover_commands(COMMANDS_DIR)
13
+
14
+ print("Welcome to the Swarm CLI Interactive Shell!")
15
+ print("Type 'help' to see available commands, or 'exit' to quit.")
16
+
17
+ while True:
18
+ try:
19
+ user_input = input("swarm> ").strip()
20
+ if user_input == "exit":
21
+ print("Exiting CLI shell.")
22
+ break
23
+ elif user_input == "help":
24
+ show_help(commands)
25
+ elif user_input in commands:
26
+ command = commands[user_input]["execute"]
27
+ if command:
28
+ command()
29
+ else:
30
+ print(f"Command '{user_input}' is not executable.")
31
+ else:
32
+ print(f"Unknown command: {user_input}")
33
+ except KeyboardInterrupt:
34
+ print("\nExiting CLI shell.")
35
+ break
36
+
37
+ def show_help(commands):
38
+ """Display available commands."""
39
+ print("Available commands:")
40
+ for cmd, metadata in commands.items():
41
+ print(f" - {cmd}: {metadata['description']}")
@@ -0,0 +1,36 @@
1
+ """
2
+ Main entry point for Swarm CLI.
3
+ """
4
+
5
+ import argparse
6
+ import os
7
+ from swarm.extensions.cli.utils.discover_commands import discover_commands
8
+ from swarm.extensions.cli.interactive_shell import interactive_shell
9
+
10
+ COMMANDS_DIR = os.path.join(os.path.dirname(__file__), "commands")
11
+
12
+ def parse_args(commands):
13
+ """Parse CLI arguments dynamically."""
14
+ parser = argparse.ArgumentParser(description="Swarm CLI Utility")
15
+ subparsers = parser.add_subparsers(dest="command")
16
+
17
+ for cmd_name, metadata in commands.items():
18
+ subparsers.add_parser(cmd_name, help=metadata["description"])
19
+
20
+ return parser.parse_args()
21
+
22
+ def main():
23
+ commands = discover_commands(COMMANDS_DIR)
24
+ args = parse_args(commands)
25
+
26
+ if args.command:
27
+ command = commands.get(args.command, {}).get("execute")
28
+ if command:
29
+ command()
30
+ else:
31
+ print(f"Command '{args.command}' is not executable.")
32
+ else:
33
+ interactive_shell()
34
+
35
+ if __name__ == "__main__":
36
+ main()