solace-agent-mesh 0.0.1__py3-none-any.whl → 0.1.1__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.

Potentially problematic release.


This version of solace-agent-mesh might be problematic. Click here for more details.

Files changed (176) hide show
  1. solace_agent_mesh/__init__.py +0 -3
  2. solace_agent_mesh/agents/__init__.py +0 -0
  3. solace_agent_mesh/agents/base_agent_component.py +224 -0
  4. solace_agent_mesh/agents/global/__init__.py +0 -0
  5. solace_agent_mesh/agents/global/actions/__init__.py +0 -0
  6. solace_agent_mesh/agents/global/actions/agent_state_change.py +54 -0
  7. solace_agent_mesh/agents/global/actions/clear_history.py +32 -0
  8. solace_agent_mesh/agents/global/actions/convert_file_to_markdown.py +160 -0
  9. solace_agent_mesh/agents/global/actions/create_file.py +70 -0
  10. solace_agent_mesh/agents/global/actions/error_action.py +45 -0
  11. solace_agent_mesh/agents/global/actions/plantuml_diagram.py +93 -0
  12. solace_agent_mesh/agents/global/actions/plotly_graph.py +117 -0
  13. solace_agent_mesh/agents/global/actions/retrieve_file.py +51 -0
  14. solace_agent_mesh/agents/global/global_agent_component.py +38 -0
  15. solace_agent_mesh/agents/image_processing/__init__.py +0 -0
  16. solace_agent_mesh/agents/image_processing/actions/__init__.py +0 -0
  17. solace_agent_mesh/agents/image_processing/actions/create_image.py +75 -0
  18. solace_agent_mesh/agents/image_processing/actions/describe_image.py +115 -0
  19. solace_agent_mesh/agents/image_processing/image_processing_agent_component.py +23 -0
  20. solace_agent_mesh/agents/slack/__init__.py +1 -0
  21. solace_agent_mesh/agents/slack/actions/__init__.py +1 -0
  22. solace_agent_mesh/agents/slack/actions/post_message.py +177 -0
  23. solace_agent_mesh/agents/slack/slack_agent_component.py +59 -0
  24. solace_agent_mesh/agents/web_request/__init__.py +0 -0
  25. solace_agent_mesh/agents/web_request/actions/__init__.py +0 -0
  26. solace_agent_mesh/agents/web_request/actions/do_image_search.py +84 -0
  27. solace_agent_mesh/agents/web_request/actions/do_news_search.py +47 -0
  28. solace_agent_mesh/agents/web_request/actions/do_suggestion_search.py +34 -0
  29. solace_agent_mesh/agents/web_request/actions/do_web_request.py +134 -0
  30. solace_agent_mesh/agents/web_request/actions/download_file.py +69 -0
  31. solace_agent_mesh/agents/web_request/web_request_agent_component.py +33 -0
  32. solace_agent_mesh/assets/web-visualizer/assets/index-C5awueeJ.js +109 -0
  33. solace_agent_mesh/assets/web-visualizer/assets/index-D0qORgkg.css +1 -0
  34. solace_agent_mesh/assets/web-visualizer/index.html +14 -0
  35. solace_agent_mesh/assets/web-visualizer/vite.svg +1 -0
  36. solace_agent_mesh/cli/__init__.py +1 -0
  37. solace_agent_mesh/cli/commands/__init__.py +0 -0
  38. solace_agent_mesh/cli/commands/add/__init__.py +3 -0
  39. solace_agent_mesh/cli/commands/add/add.py +88 -0
  40. solace_agent_mesh/cli/commands/add/agent.py +110 -0
  41. solace_agent_mesh/cli/commands/add/copy_from_plugin.py +90 -0
  42. solace_agent_mesh/cli/commands/add/gateway.py +221 -0
  43. solace_agent_mesh/cli/commands/build.py +631 -0
  44. solace_agent_mesh/cli/commands/chat/__init__.py +3 -0
  45. solace_agent_mesh/cli/commands/chat/chat.py +361 -0
  46. solace_agent_mesh/cli/commands/config.py +29 -0
  47. solace_agent_mesh/cli/commands/init/__init__.py +3 -0
  48. solace_agent_mesh/cli/commands/init/ai_provider_step.py +76 -0
  49. solace_agent_mesh/cli/commands/init/broker_step.py +102 -0
  50. solace_agent_mesh/cli/commands/init/builtin_agent_step.py +88 -0
  51. solace_agent_mesh/cli/commands/init/check_if_already_done.py +13 -0
  52. solace_agent_mesh/cli/commands/init/create_config_file_step.py +52 -0
  53. solace_agent_mesh/cli/commands/init/create_other_project_files_step.py +96 -0
  54. solace_agent_mesh/cli/commands/init/file_service_step.py +73 -0
  55. solace_agent_mesh/cli/commands/init/init.py +114 -0
  56. solace_agent_mesh/cli/commands/init/project_structure_step.py +45 -0
  57. solace_agent_mesh/cli/commands/init/rest_api_step.py +50 -0
  58. solace_agent_mesh/cli/commands/init/web_ui_step.py +40 -0
  59. solace_agent_mesh/cli/commands/plugin/__init__.py +3 -0
  60. solace_agent_mesh/cli/commands/plugin/add.py +98 -0
  61. solace_agent_mesh/cli/commands/plugin/build.py +217 -0
  62. solace_agent_mesh/cli/commands/plugin/create.py +117 -0
  63. solace_agent_mesh/cli/commands/plugin/plugin.py +109 -0
  64. solace_agent_mesh/cli/commands/plugin/remove.py +71 -0
  65. solace_agent_mesh/cli/commands/run.py +68 -0
  66. solace_agent_mesh/cli/commands/visualizer.py +138 -0
  67. solace_agent_mesh/cli/config.py +81 -0
  68. solace_agent_mesh/cli/main.py +306 -0
  69. solace_agent_mesh/cli/utils.py +246 -0
  70. solace_agent_mesh/common/__init__.py +0 -0
  71. solace_agent_mesh/common/action.py +91 -0
  72. solace_agent_mesh/common/action_list.py +37 -0
  73. solace_agent_mesh/common/action_response.py +327 -0
  74. solace_agent_mesh/common/constants.py +3 -0
  75. solace_agent_mesh/common/mysql_database.py +40 -0
  76. solace_agent_mesh/common/postgres_database.py +79 -0
  77. solace_agent_mesh/common/prompt_templates.py +30 -0
  78. solace_agent_mesh/common/prompt_templates_unused_delete.py +161 -0
  79. solace_agent_mesh/common/stimulus_utils.py +152 -0
  80. solace_agent_mesh/common/time.py +24 -0
  81. solace_agent_mesh/common/utils.py +638 -0
  82. solace_agent_mesh/configs/agent_global.yaml +74 -0
  83. solace_agent_mesh/configs/agent_image_processing.yaml +82 -0
  84. solace_agent_mesh/configs/agent_slack.yaml +64 -0
  85. solace_agent_mesh/configs/agent_web_request.yaml +75 -0
  86. solace_agent_mesh/configs/conversation_to_file.yaml +56 -0
  87. solace_agent_mesh/configs/error_catcher.yaml +56 -0
  88. solace_agent_mesh/configs/monitor.yaml +0 -0
  89. solace_agent_mesh/configs/monitor_stim_and_errors_to_slack.yaml +106 -0
  90. solace_agent_mesh/configs/monitor_user_feedback.yaml +58 -0
  91. solace_agent_mesh/configs/orchestrator.yaml +241 -0
  92. solace_agent_mesh/configs/service_embedding.yaml +81 -0
  93. solace_agent_mesh/configs/service_llm.yaml +265 -0
  94. solace_agent_mesh/configs/visualize_websocket.yaml +55 -0
  95. solace_agent_mesh/gateway/__init__.py +0 -0
  96. solace_agent_mesh/gateway/components/__init__.py +0 -0
  97. solace_agent_mesh/gateway/components/gateway_base.py +41 -0
  98. solace_agent_mesh/gateway/components/gateway_input.py +265 -0
  99. solace_agent_mesh/gateway/components/gateway_output.py +289 -0
  100. solace_agent_mesh/gateway/identity/bamboohr_identity.py +18 -0
  101. solace_agent_mesh/gateway/identity/identity_base.py +10 -0
  102. solace_agent_mesh/gateway/identity/identity_provider.py +60 -0
  103. solace_agent_mesh/gateway/identity/no_identity.py +9 -0
  104. solace_agent_mesh/gateway/identity/passthru_identity.py +9 -0
  105. solace_agent_mesh/monitors/base_monitor_component.py +26 -0
  106. solace_agent_mesh/monitors/feedback/user_feedback_monitor.py +75 -0
  107. solace_agent_mesh/monitors/stim_and_errors/stim_and_error_monitor.py +560 -0
  108. solace_agent_mesh/orchestrator/__init__.py +0 -0
  109. solace_agent_mesh/orchestrator/action_manager.py +225 -0
  110. solace_agent_mesh/orchestrator/components/__init__.py +0 -0
  111. solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +54 -0
  112. solace_agent_mesh/orchestrator/components/orchestrator_action_response_component.py +179 -0
  113. solace_agent_mesh/orchestrator/components/orchestrator_register_component.py +107 -0
  114. solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +477 -0
  115. solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +246 -0
  116. solace_agent_mesh/orchestrator/orchestrator_main.py +166 -0
  117. solace_agent_mesh/orchestrator/orchestrator_prompt.py +410 -0
  118. solace_agent_mesh/services/__init__.py +0 -0
  119. solace_agent_mesh/services/authorization/providers/base_authorization_provider.py +56 -0
  120. solace_agent_mesh/services/bamboo_hr_service/__init__.py +3 -0
  121. solace_agent_mesh/services/bamboo_hr_service/bamboo_hr.py +182 -0
  122. solace_agent_mesh/services/common/__init__.py +4 -0
  123. solace_agent_mesh/services/common/auto_expiry.py +45 -0
  124. solace_agent_mesh/services/common/singleton.py +18 -0
  125. solace_agent_mesh/services/file_service/__init__.py +14 -0
  126. solace_agent_mesh/services/file_service/file_manager/__init__.py +0 -0
  127. solace_agent_mesh/services/file_service/file_manager/bucket_file_manager.py +149 -0
  128. solace_agent_mesh/services/file_service/file_manager/file_manager_base.py +162 -0
  129. solace_agent_mesh/services/file_service/file_manager/memory_file_manager.py +64 -0
  130. solace_agent_mesh/services/file_service/file_manager/volume_file_manager.py +106 -0
  131. solace_agent_mesh/services/file_service/file_service.py +432 -0
  132. solace_agent_mesh/services/file_service/file_service_constants.py +54 -0
  133. solace_agent_mesh/services/file_service/file_transformations.py +131 -0
  134. solace_agent_mesh/services/file_service/file_utils.py +322 -0
  135. solace_agent_mesh/services/file_service/transformers/__init__.py +5 -0
  136. solace_agent_mesh/services/history_service/__init__.py +3 -0
  137. solace_agent_mesh/services/history_service/history_providers/__init__.py +0 -0
  138. solace_agent_mesh/services/history_service/history_providers/base_history_provider.py +78 -0
  139. solace_agent_mesh/services/history_service/history_providers/memory_history_provider.py +167 -0
  140. solace_agent_mesh/services/history_service/history_providers/redis_history_provider.py +163 -0
  141. solace_agent_mesh/services/history_service/history_service.py +139 -0
  142. solace_agent_mesh/services/llm_service/components/llm_request_component.py +293 -0
  143. solace_agent_mesh/services/llm_service/components/llm_service_component_base.py +152 -0
  144. solace_agent_mesh/services/middleware_service/__init__.py +0 -0
  145. solace_agent_mesh/services/middleware_service/middleware_service.py +20 -0
  146. solace_agent_mesh/templates/action.py +38 -0
  147. solace_agent_mesh/templates/agent.py +29 -0
  148. solace_agent_mesh/templates/agent.yaml +70 -0
  149. solace_agent_mesh/templates/gateway-config-template.yaml +6 -0
  150. solace_agent_mesh/templates/gateway-default-config.yaml +28 -0
  151. solace_agent_mesh/templates/gateway-flows.yaml +81 -0
  152. solace_agent_mesh/templates/gateway-header.yaml +16 -0
  153. solace_agent_mesh/templates/gateway_base.py +15 -0
  154. solace_agent_mesh/templates/gateway_input.py +98 -0
  155. solace_agent_mesh/templates/gateway_output.py +71 -0
  156. solace_agent_mesh/templates/plugin-pyproject.toml +30 -0
  157. solace_agent_mesh/templates/rest-api-default-config.yaml +24 -0
  158. solace_agent_mesh/templates/rest-api-flows.yaml +80 -0
  159. solace_agent_mesh/templates/slack-default-config.yaml +9 -0
  160. solace_agent_mesh/templates/slack-flows.yaml +90 -0
  161. solace_agent_mesh/templates/solace-agent-mesh-default.yaml +77 -0
  162. solace_agent_mesh/templates/solace-agent-mesh-plugin-default.yaml +8 -0
  163. solace_agent_mesh/templates/web-default-config.yaml +5 -0
  164. solace_agent_mesh/templates/web-flows.yaml +86 -0
  165. solace_agent_mesh/tools/__init__.py +0 -0
  166. solace_agent_mesh/tools/components/__init__.py +0 -0
  167. solace_agent_mesh/tools/components/conversation_formatter.py +111 -0
  168. solace_agent_mesh/tools/components/file_resolver_component.py +58 -0
  169. solace_agent_mesh/tools/config/runtime_config.py +26 -0
  170. solace_agent_mesh-0.1.1.dist-info/METADATA +179 -0
  171. solace_agent_mesh-0.1.1.dist-info/RECORD +174 -0
  172. solace_agent_mesh-0.1.1.dist-info/entry_points.txt +3 -0
  173. solace_agent_mesh-0.0.1.dist-info/licenses/LICENSE.txt → solace_agent_mesh-0.1.1.dist-info/licenses/LICENSE +1 -2
  174. solace_agent_mesh-0.0.1.dist-info/METADATA +0 -51
  175. solace_agent_mesh-0.0.1.dist-info/RECORD +0 -5
  176. {solace_agent_mesh-0.0.1.dist-info → solace_agent_mesh-0.1.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,217 @@
1
+ import subprocess
2
+ import os
3
+ import click
4
+
5
+ from cli.utils import log_error, apply_document_parsers, load_plugin
6
+ from cli.config import Config
7
+
8
+
9
+ def build_command():
10
+ """Builds the plugin python module."""
11
+ subprocess.check_call(["python", "-m", "build"])
12
+
13
+
14
+ def get_all_plugin_gateway_interfaces(config, abort):
15
+ plugins = config.get("plugins", [])
16
+ gateway_interfaces = {}
17
+
18
+ for plugin in plugins:
19
+ if plugin.get("includes_gateway_interface"):
20
+ name = plugin.get("name")
21
+ plugin_path = load_plugin(name, return_path_only=True)
22
+ if not plugin_path:
23
+ log_error(f"Plugin '{name}' is not installed.")
24
+ abort()
25
+ interface_path = os.path.join(plugin_path, "interfaces")
26
+
27
+ if not os.path.exists(interface_path):
28
+ continue
29
+
30
+ # Ensuring flow and default pair exist
31
+ interface_pairs = {}
32
+ for file in os.listdir(interface_path):
33
+ if file.endswith("-flows.yaml") :
34
+ name = file.split("-flows.yaml")[0]
35
+ if name not in interface_pairs:
36
+ interface_pairs[name] = []
37
+ interface_pairs[name].append(file)
38
+
39
+ elif file.endswith("-default-config.yaml"):
40
+ name = file.split("-default-config.yaml")[0]
41
+ if name not in interface_pairs:
42
+ interface_pairs[name] = []
43
+ interface_pairs[name].append(file)
44
+
45
+ for name, files in interface_pairs.items():
46
+ if len(files) == 2:
47
+ gateway_interfaces[name] = interface_path
48
+
49
+ return gateway_interfaces
50
+
51
+
52
+ def build_plugins(config, build_config_dir, abort, parsers, plugin_gateway_interfaces, build_specific_gateway):
53
+ plugins = config.get("plugins", [])
54
+ plugins_overwrite_dir = os.path.join(build_config_dir, "..", "overwrites")
55
+
56
+ os.makedirs(build_config_dir, exist_ok=True)
57
+ os.makedirs(plugins_overwrite_dir, exist_ok=True)
58
+
59
+ for plugin in plugins:
60
+ click.echo("Building plugin: " + plugin.get("name"))
61
+ name = plugin.get("name")
62
+ load_unspecified_files = plugin.get("load_unspecified_files", True)
63
+ load = plugin.get("load", {})
64
+ agents_to_load = [agent.replace("-", "_") for agent in (load.get("agents") or [])]
65
+ gateways_to_load = load.get("gateways") or []
66
+ overwrites_to_load = load.get("overwrites") or []
67
+
68
+ plugin_path = load_plugin(name, return_path_only=True)
69
+ if not plugin_path:
70
+ log_error(f"Plugin '{name}' is not installed.")
71
+ abort()
72
+
73
+ try:
74
+ # Path to plugin config in the module
75
+ plugin_file_path = os.path.join(plugin_path, Config.user_plugin_config_file)
76
+ plugin_config = Config.load_config(plugin_file_path)
77
+
78
+ if not plugin_config or "solace_agent_mesh_plugin" not in plugin_config:
79
+ raise ValueError("Invalid solace-agent-mesh plugin module.")
80
+ except Exception:
81
+ log_error(
82
+ f"Error loading plugin '{name}': Invalid solace-agent-mesh plugin module."
83
+ )
84
+ abort()
85
+
86
+ ################
87
+ # Build Agents #
88
+ ################
89
+ agent_config_path = os.path.join(plugin_path, "configs", "agents")
90
+ if os.path.exists(agent_config_path):
91
+ click.echo("Building agents for plugin: " + name)
92
+ # Get all agent configuration files
93
+ agent_configs = [
94
+ f for f in os.listdir(agent_config_path) if f.endswith(".yaml")
95
+ ]
96
+ yaml_agents = [f"{agent}.yaml" for agent in agents_to_load]
97
+ if not load_unspecified_files:
98
+ agent_configs = [f for f in agent_configs if f in yaml_agents]
99
+
100
+ # Ensuring all user requested agents are present
101
+ for agent_config in yaml_agents:
102
+ if agent_config not in agent_configs:
103
+ log_error(
104
+ f"Agent '{agent_config[:-5]}' was not found in the plugin '{name}'"
105
+ )
106
+ abort()
107
+
108
+ for agent_config in agent_configs:
109
+ try:
110
+ # Read agent configuration file
111
+ agent_config_file = os.path.join(agent_config_path, agent_config)
112
+ with open(agent_config_file, "r", encoding="utf-8") as f:
113
+ agent_config_content = f.read()
114
+ # Apply document parsers
115
+ meta = {
116
+ "skip_relative_import_path": True,
117
+ "extra_literals": {
118
+ "MODULE_DIRECTORY": f"{name}.src",
119
+ },
120
+ }
121
+ agent_config_content = apply_document_parsers(
122
+ agent_config_content, parsers, meta
123
+ )
124
+ # Write agent configuration to build directory
125
+ agent_build_path = os.path.join(
126
+ build_config_dir, "agent_" + agent_config
127
+ )
128
+ with open(agent_build_path, "w", encoding="utf-8") as f:
129
+ f.write(agent_config_content)
130
+ except IOError as e:
131
+ log_error(
132
+ f'Error reading agent configuration file for "{agent_config}" from plugin "{name}": {e}'
133
+ )
134
+ abort()
135
+ except Exception as e:
136
+ log_error(
137
+ f'Error building agent configuration for "{agent_config}" from plugin "{name}": {e}'
138
+ )
139
+ abort()
140
+
141
+ ##################
142
+ # Build Gateways #
143
+ ##################
144
+ gateway_config_path = os.path.join(plugin_path, "configs", "gateways")
145
+ gateway_dirs = [gateway.replace("-", "_") for gateway in gateways_to_load]
146
+ if os.path.exists(gateway_config_path):
147
+ gateway_subdirs = os.listdir(gateway_config_path)
148
+ for gateway in gateway_dirs:
149
+ if gateway not in gateway_subdirs:
150
+ log_error(
151
+ f"Gateway '{gateway}' was not found in the plugin '{name}'"
152
+ )
153
+ abort()
154
+
155
+ # Loop over the subdirectories of gateways_config_path
156
+ for gateway in gateway_subdirs:
157
+ if load_unspecified_files or gateway in gateway_dirs:
158
+ build_specific_gateway(
159
+ build_config_dir, abort, parsers, gateway_config_path, gateway, plugin_gateway_interfaces
160
+ )
161
+
162
+ ####################
163
+ # Build Overwrites #
164
+ ####################
165
+ overwrite_config_path = os.path.join(plugin_path, "configs", "overwrite")
166
+ if os.path.exists(overwrite_config_path):
167
+ click.echo("Building overwrite for plugin: " + name)
168
+ # Get all overwrite configuration files
169
+ overwrite_configs = [
170
+ f for f in os.listdir(overwrite_config_path) if f.endswith(".yaml")
171
+ ]
172
+ if not load_unspecified_files:
173
+ overwrite_configs = [
174
+ f for f in overwrite_configs if f in overwrites_to_load
175
+ ]
176
+
177
+ # Ensuring all user requested overwrites are present
178
+ for overwrite_config in overwrites_to_load:
179
+ if overwrite_config not in overwrite_configs:
180
+ log_error(
181
+ f"Overwrite '{overwrite_config}' was not found in the plugin '{name}'"
182
+ )
183
+ abort()
184
+ for overwrite_config in overwrite_configs:
185
+ try:
186
+ # Read overwrite configuration file
187
+ overwrite_config_file = os.path.join(
188
+ overwrite_config_path, overwrite_config
189
+ )
190
+ with open(overwrite_config_file, "r", encoding="utf-8") as f:
191
+ overwrite_config_content = f.read()
192
+ # Apply document parsers
193
+ meta = {
194
+ "skip_relative_import_path": True,
195
+ "extra_literals": {
196
+ "MODULE_DIRECTORY": f"{name}.src",
197
+ },
198
+ }
199
+ overwrite_config_content = apply_document_parsers(
200
+ overwrite_config_content, parsers, meta
201
+ )
202
+ # Write overwrite configuration to build directory
203
+ overwrite_build_path = os.path.join(
204
+ plugins_overwrite_dir, overwrite_config
205
+ )
206
+ with open(overwrite_build_path, "w", encoding="utf-8") as f:
207
+ f.write(overwrite_config_content)
208
+ except IOError as e:
209
+ log_error(
210
+ f'Error reading overwrite configuration file for "{overwrite_config}" from plugin "{name}": {e}'
211
+ )
212
+ abort()
213
+ except Exception as e:
214
+ log_error(
215
+ f'Error building overwrite configuration for "{overwrite_config}" from plugin "{name}": {e}'
216
+ )
217
+ abort()
@@ -0,0 +1,117 @@
1
+ import click
2
+ import os
3
+
4
+ from cli.config import Config
5
+ from cli.utils import load_template
6
+ from cli.utils import log_error, ask_question
7
+
8
+
9
+ DEFAULT_DESCRIPTION = "A solace-agent-mesh plugin project."
10
+ DEFAULT_AUTHOR = "Author Name"
11
+ EMPTY_FILE_MSG = "THIS WILL IS ONLY HERE TO PREVENT GIT FROM IGNORING THIS DIRECTORY"
12
+
13
+ def create_command(
14
+ path: str, description: str = None, author: str = None, skip: bool = False
15
+ ):
16
+ """Initializes and creates a new solace-agent-mesh plugin project.
17
+
18
+ Project structure:
19
+
20
+ plugin-name/
21
+ ├─ configs/
22
+ │ ├─ overwrite/
23
+ ├─ src/
24
+ │ ├─ __init__.py
25
+ │ ├─ agents/
26
+ │ │ ├─ __init__.py
27
+ │ ├─ gateways/
28
+ │ │ ├─ __init__.py
29
+ ├─ interfaces/
30
+ ├─ solace-agent-mesh-plugin.yaml
31
+ ├─ .gitignore
32
+ ├─ pyproject.toml
33
+ ├─ README.md
34
+
35
+ """
36
+ if not skip:
37
+ if not path:
38
+ path = ask_question("Plugin name (A path if it shouldn't be created in the current directory)")
39
+ if not description:
40
+ description = ask_question("Plugin description", "")
41
+ if not author:
42
+ author = ask_question("Plugin author", "")
43
+ if not path:
44
+ log_error("Plugin name is required.")
45
+ return 1
46
+ click.echo(f"Creating solace-agent-mesh plugin '{path}'.")
47
+
48
+ # Create the plugin directory
49
+ click.echo("Creating plugin directory...")
50
+ os.makedirs(path, exist_ok=True)
51
+
52
+ # Check into the plugin directory
53
+ os.chdir(path)
54
+
55
+ # Get the directory base name
56
+ name = str(os.path.basename(path))
57
+
58
+ config = Config.get_default_plugin_config()
59
+ config["solace_agent_mesh_plugin"]["name"] = name
60
+
61
+ # Write the plugin config file
62
+ Config.write_config(config, Config.user_plugin_config_file)
63
+
64
+ # Create the .gitignore file
65
+ ignore_files = ["*.pyc", "__pycache__", "*.egg-info", "dist"]
66
+ with open(".gitignore", "w", encoding="utf-8") as f:
67
+ f.write("\n".join(ignore_files))
68
+
69
+ # Create README.md
70
+ with open("README.md", "w", encoding="utf-8") as f:
71
+ f.write(f"# {name.upper()}\n\n{description or DEFAULT_DESCRIPTION}")
72
+
73
+ # Create directories and __init__.py files
74
+ py_paths = ["agents", "gateways"]
75
+ py_paths = [os.path.join("src", path) for path in py_paths]
76
+ directories = [
77
+ "interfaces",
78
+ "configs",
79
+ "src",
80
+ os.path.join("configs", "overwrite"),
81
+ ] + py_paths
82
+
83
+ for path in directories:
84
+ os.makedirs(path, exist_ok=True)
85
+
86
+ for py_path in py_paths:
87
+ with open(os.path.join(py_path, "__init__.py"), "w", encoding="utf-8") as f:
88
+ f.write("")
89
+
90
+ with open(os.path.join("configs", "__TEMPLATES_WILL_BE_HERE__"), "w", encoding="utf-8") as f:
91
+ f.write(EMPTY_FILE_MSG)
92
+
93
+ with open(os.path.join("interfaces", "__INTERFACES_WILL_BE_HERE__"), "w", encoding="utf-8") as f:
94
+ f.write(EMPTY_FILE_MSG)
95
+
96
+ with open(os.path.join("src", "__init__.py"), "w", encoding="utf-8") as f:
97
+ f.write('__version__ = "0.0.1"\n')
98
+
99
+ # Create pyproject.toml
100
+ pyproject = load_template("plugin-pyproject.toml")
101
+ pyproject = (pyproject
102
+ .replace("{{name}}", name)
103
+ .replace("{{snake_name}}", name.replace("-", "_"))
104
+ .replace("{{description}}", description or DEFAULT_DESCRIPTION)
105
+ .replace("{{author}}", author or DEFAULT_AUTHOR)
106
+ )
107
+
108
+ with open("pyproject.toml", "w", encoding="utf-8") as f:
109
+ f.write(pyproject)
110
+
111
+ click.echo(f"Plugin project '{name}' was created successfully.")
112
+ click.echo(
113
+ click.style(f"\tUse `cd {name}` to check into project.", fg="blue")
114
+ )
115
+ click.echo(
116
+ click.style("\tUse `solace-agent-mesh add` to add agents and gateways.", fg="blue")
117
+ )
@@ -0,0 +1,109 @@
1
+ import click
2
+
3
+ from cli.utils import log_error
4
+ from .add import add_command
5
+ from .remove import remove_command
6
+ from .create import create_command
7
+ from .build import build_command
8
+
9
+
10
+ def plugin_command(plugin):
11
+
12
+ @plugin.command()
13
+ @click.option(
14
+ "-n",
15
+ "--name",
16
+ help="Plugin name. (A path if it shouldn't be created in the current directory)",
17
+ )
18
+ @click.option(
19
+ "-d",
20
+ "--description",
21
+ help="Plugin description.",
22
+ )
23
+ @click.option(
24
+ "-a",
25
+ "--author",
26
+ help="Plugin author.",
27
+ )
28
+ @click.option(
29
+ "-s",
30
+ "--skip",
31
+ is_flag=True,
32
+ help="Skip the prompts and use the default values. (Name is required)",
33
+ )
34
+ def create(name, description, author, skip):
35
+ """Initializes and creates a new solace-agent-mesh plugin project."""
36
+ create_command(name, description, author, skip)
37
+
38
+ @plugin.command()
39
+ def build():
40
+ """Build the solace-agent-mesh plugin project."""
41
+ build_command()
42
+
43
+ @plugin.command()
44
+ @click.argument("name")
45
+ @click.option("--add-all", is_flag=True, help="Added the plugin with default of loading all exported files from the plugin")
46
+ @click.option("--pip", is_flag=True, help="Install with pip.")
47
+ @click.option("--poetry", is_flag=True, help="Install with poetry.")
48
+ @click.option("--conda", is_flag=True, help="Install with conda.")
49
+ @click.option(
50
+ "-u",
51
+ "--from-url",
52
+ help="Install the plugin from a the given URL instead of the given name. (URL can be a file path or a git URL)",
53
+ )
54
+ def add(name, add_all, pip, poetry, conda, from_url):
55
+ """
56
+ Add a new plugin to solace-agent-mesh config yaml.
57
+ Optional install the module if not found.
58
+
59
+ Only one installation method can be selected at a time.
60
+ """
61
+ # Only one option can be true at a time
62
+ if sum([pip, poetry, conda]) > 1:
63
+ log_error("Only one installation method can be selected.")
64
+ return 1
65
+ installer = "pip" if pip else "poetry" if poetry else "conda" if conda else None
66
+ return add_command(name, installer, from_url, add_all)
67
+
68
+ @plugin.command()
69
+ @click.argument("name")
70
+ @click.option(
71
+ "--pip-uninstall",
72
+ default=False,
73
+ is_flag=True,
74
+ help="Removes the plugin module using pip",
75
+ )
76
+ @click.option(
77
+ "--poetry-uninstall",
78
+ default=False,
79
+ is_flag=True,
80
+ help="Removes the plugin module using poetry",
81
+ )
82
+ @click.option(
83
+ "--conda-uninstall",
84
+ default=False,
85
+ is_flag=True,
86
+ help="Removes the plugin module using conda",
87
+ )
88
+ def remove(name, pip_uninstall, poetry_uninstall, conda_uninstall):
89
+ """
90
+ Remove a plugin by removing it from solace-agent-mesh config yaml
91
+ Optionally uninstall the module.
92
+
93
+ Only one uninstallation method can be selected at a time.
94
+ """
95
+ # Only one option can be true at a time
96
+ if sum([pip_uninstall, poetry_uninstall, conda_uninstall]) > 1:
97
+ log_error("Only one uninstallation method can be selected.")
98
+ return 1
99
+
100
+ installer = (
101
+ "pip"
102
+ if pip_uninstall
103
+ else "poetry"
104
+ if poetry_uninstall
105
+ else "conda"
106
+ if conda_uninstall
107
+ else None
108
+ )
109
+ return remove_command(name, installer)
@@ -0,0 +1,71 @@
1
+ import subprocess
2
+ import importlib.util
3
+ import click
4
+
5
+ from cli.utils import log_error
6
+ from cli.config import Config
7
+
8
+
9
+ def remove_command(name: str, installer: str = None):
10
+ """
11
+ Remove a plugin by removing it from solace-agent-mesh config yaml
12
+ Optionally uninstall the module
13
+
14
+ Args:
15
+ name (str): The name of the module to remove.
16
+ installer (str, optional): Installer to use for uninstallation.
17
+ Should be one of 'pip', 'poetry', 'conda', or None.
18
+ """
19
+ name = name.replace("-", "_")
20
+ sam_config = Config.get_user_config()
21
+ if not sam_config:
22
+ log_error("No configuration found.")
23
+ return 1
24
+
25
+ plugin = None
26
+ plugins = sam_config.get("solace_agent_mesh", {}).get("plugins", [])
27
+ for p in plugins:
28
+ if p.get("name") == name:
29
+ plugin = p
30
+ plugins.remove(plugin)
31
+ Config.write_config(sam_config)
32
+ click.echo(f"Plugin '{name}' was removed from solace-agent-mesh config.")
33
+ break
34
+
35
+ if not plugin:
36
+ log_error(f"Plugin '{name}' not found in the config.")
37
+ return
38
+
39
+ if installer:
40
+ # Check if the module exists
41
+ if importlib.util.find_spec(name) is None:
42
+ log_error(
43
+ f"Module '{name}' is not installed. Run without uninstall flag to just remove from config."
44
+ )
45
+ return 1
46
+
47
+ # Attempt to uninstall using the specified installer
48
+ click.echo(f"Attempting to uninstall module '{name}' using {installer}...")
49
+ try:
50
+ if installer == "pip":
51
+ subprocess.check_call(["pip", "uninstall", "-y", name])
52
+ elif installer == "poetry":
53
+ subprocess.check_call(["poetry", "remove", name])
54
+ elif installer == "conda":
55
+ subprocess.check_call(["conda", "remove", "-y", name])
56
+ else:
57
+ log_error(
58
+ f"Unsupported installer: {installer} - (pip, poetry, or conda)."
59
+ )
60
+ return 1
61
+ click.echo(f"Successfully uninstalled module '{name}'.")
62
+ except subprocess.CalledProcessError as e:
63
+ log_error(f"Error occurred while uninstalling module '{name}': {e}")
64
+ return 1
65
+ else:
66
+ click.echo(
67
+ click.style(
68
+ f"Module '{name}' was only removed from the config. Use your package manager to uninstall from environment.",
69
+ fg="yellow",
70
+ )
71
+ )
@@ -0,0 +1,68 @@
1
+ import sys
2
+ import os
3
+ import click
4
+
5
+ from cli.commands.build import build_command
6
+ from cli.utils import log_error
7
+
8
+
9
+ def run_solace_ai_connector(configs):
10
+ try:
11
+ from solace_ai_connector.main import main
12
+ except ImportError:
13
+ log_error("Failed to import Solace AI Connector.")
14
+ return 1
15
+
16
+ sys.argv = [sys.argv[0].replace("solace-agent-mesh", "solace-ai-connector"), *configs]
17
+ return sys.exit(main())
18
+
19
+
20
+ FILES_TO_EXCLUDE = []
21
+
22
+
23
+ def run_command(
24
+ use_env, config_files, exclude_files, quick_build, ignore_build, force_build
25
+ ):
26
+ """Run the Solace Agent Mesh application."""
27
+
28
+ config = click.get_current_context().obj["solace_agent_mesh"]
29
+ build_dir = config["build"]["build_directory"]
30
+ build_config_dir = os.path.join(build_dir, "configs")
31
+
32
+ if force_build or (not ignore_build and not os.path.exists(build_dir)):
33
+ build_command(skip_without_asking=quick_build)
34
+
35
+ click.echo("Running Solace Agent Mesh application")
36
+
37
+ if use_env:
38
+ try:
39
+ from dotenv import load_dotenv
40
+
41
+ env_file = config["env_file"]
42
+ load_dotenv(env_file, override=True)
43
+ except ImportError:
44
+ log_error(
45
+ "Failed to import dotenv. Please install it using 'pip install python-dotenv'"
46
+ )
47
+ return 1
48
+ except Exception as e:
49
+ log_error(f"Failed to load environment variables. {e}")
50
+ return 1
51
+
52
+ if not config_files:
53
+ if not os.path.exists(build_config_dir):
54
+ log_error("No build directory found. Run 'solace-agent-mesh build' first.")
55
+ return 1
56
+
57
+ config_files = [
58
+ os.path.join(build_config_dir, f)
59
+ for f in os.listdir(build_config_dir)
60
+ if f.endswith(".yaml")
61
+ ]
62
+
63
+ # Exclude files
64
+ # only basename of the files
65
+ exclude_files = [os.path.basename(f) for f in exclude_files] + FILES_TO_EXCLUDE
66
+ config_files = [f for f in config_files if os.path.basename(f) not in exclude_files]
67
+
68
+ return run_solace_ai_connector(config_files)