solace-agent-mesh 0.0.1__py3-none-any.whl → 0.1.0__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.
- solace_agent_mesh/__init__.py +0 -3
- solace_agent_mesh/agents/__init__.py +0 -0
- solace_agent_mesh/agents/base_agent_component.py +224 -0
- solace_agent_mesh/agents/global/__init__.py +0 -0
- solace_agent_mesh/agents/global/actions/__init__.py +0 -0
- solace_agent_mesh/agents/global/actions/agent_state_change.py +54 -0
- solace_agent_mesh/agents/global/actions/clear_history.py +32 -0
- solace_agent_mesh/agents/global/actions/convert_file_to_markdown.py +160 -0
- solace_agent_mesh/agents/global/actions/create_file.py +70 -0
- solace_agent_mesh/agents/global/actions/error_action.py +45 -0
- solace_agent_mesh/agents/global/actions/plantuml_diagram.py +93 -0
- solace_agent_mesh/agents/global/actions/plotly_graph.py +117 -0
- solace_agent_mesh/agents/global/actions/retrieve_file.py +51 -0
- solace_agent_mesh/agents/global/global_agent_component.py +38 -0
- solace_agent_mesh/agents/image_processing/__init__.py +0 -0
- solace_agent_mesh/agents/image_processing/actions/__init__.py +0 -0
- solace_agent_mesh/agents/image_processing/actions/create_image.py +75 -0
- solace_agent_mesh/agents/image_processing/actions/describe_image.py +115 -0
- solace_agent_mesh/agents/image_processing/image_processing_agent_component.py +23 -0
- solace_agent_mesh/agents/slack/__init__.py +1 -0
- solace_agent_mesh/agents/slack/actions/__init__.py +1 -0
- solace_agent_mesh/agents/slack/actions/post_message.py +177 -0
- solace_agent_mesh/agents/slack/slack_agent_component.py +59 -0
- solace_agent_mesh/agents/web_request/__init__.py +0 -0
- solace_agent_mesh/agents/web_request/actions/__init__.py +0 -0
- solace_agent_mesh/agents/web_request/actions/do_image_search.py +84 -0
- solace_agent_mesh/agents/web_request/actions/do_news_search.py +47 -0
- solace_agent_mesh/agents/web_request/actions/do_suggestion_search.py +34 -0
- solace_agent_mesh/agents/web_request/actions/do_web_request.py +134 -0
- solace_agent_mesh/agents/web_request/actions/download_file.py +69 -0
- solace_agent_mesh/agents/web_request/web_request_agent_component.py +33 -0
- solace_agent_mesh/cli/__init__.py +1 -0
- solace_agent_mesh/cli/commands/__init__.py +0 -0
- solace_agent_mesh/cli/commands/add/__init__.py +3 -0
- solace_agent_mesh/cli/commands/add/add.py +88 -0
- solace_agent_mesh/cli/commands/add/agent.py +110 -0
- solace_agent_mesh/cli/commands/add/copy_from_plugin.py +90 -0
- solace_agent_mesh/cli/commands/add/gateway.py +221 -0
- solace_agent_mesh/cli/commands/build.py +631 -0
- solace_agent_mesh/cli/commands/chat/__init__.py +3 -0
- solace_agent_mesh/cli/commands/chat/chat.py +361 -0
- solace_agent_mesh/cli/commands/config.py +29 -0
- solace_agent_mesh/cli/commands/init/__init__.py +3 -0
- solace_agent_mesh/cli/commands/init/ai_provider_step.py +76 -0
- solace_agent_mesh/cli/commands/init/broker_step.py +102 -0
- solace_agent_mesh/cli/commands/init/builtin_agent_step.py +88 -0
- solace_agent_mesh/cli/commands/init/check_if_already_done.py +13 -0
- solace_agent_mesh/cli/commands/init/create_config_file_step.py +52 -0
- solace_agent_mesh/cli/commands/init/create_other_project_files_step.py +96 -0
- solace_agent_mesh/cli/commands/init/file_service_step.py +73 -0
- solace_agent_mesh/cli/commands/init/init.py +114 -0
- solace_agent_mesh/cli/commands/init/project_structure_step.py +45 -0
- solace_agent_mesh/cli/commands/init/rest_api_step.py +50 -0
- solace_agent_mesh/cli/commands/init/web_ui_step.py +40 -0
- solace_agent_mesh/cli/commands/plugin/__init__.py +3 -0
- solace_agent_mesh/cli/commands/plugin/add.py +98 -0
- solace_agent_mesh/cli/commands/plugin/build.py +217 -0
- solace_agent_mesh/cli/commands/plugin/create.py +117 -0
- solace_agent_mesh/cli/commands/plugin/plugin.py +109 -0
- solace_agent_mesh/cli/commands/plugin/remove.py +71 -0
- solace_agent_mesh/cli/commands/run.py +68 -0
- solace_agent_mesh/cli/commands/visualizer.py +138 -0
- solace_agent_mesh/cli/config.py +81 -0
- solace_agent_mesh/cli/main.py +306 -0
- solace_agent_mesh/cli/utils.py +246 -0
- solace_agent_mesh/common/__init__.py +0 -0
- solace_agent_mesh/common/action.py +91 -0
- solace_agent_mesh/common/action_list.py +37 -0
- solace_agent_mesh/common/action_response.py +327 -0
- solace_agent_mesh/common/constants.py +3 -0
- solace_agent_mesh/common/mysql_database.py +40 -0
- solace_agent_mesh/common/postgres_database.py +79 -0
- solace_agent_mesh/common/prompt_templates.py +30 -0
- solace_agent_mesh/common/prompt_templates_unused_delete.py +161 -0
- solace_agent_mesh/common/stimulus_utils.py +152 -0
- solace_agent_mesh/common/time.py +24 -0
- solace_agent_mesh/common/utils.py +638 -0
- solace_agent_mesh/configs/agent_global.yaml +74 -0
- solace_agent_mesh/configs/agent_image_processing.yaml +82 -0
- solace_agent_mesh/configs/agent_slack.yaml +64 -0
- solace_agent_mesh/configs/agent_web_request.yaml +75 -0
- solace_agent_mesh/configs/conversation_to_file.yaml +56 -0
- solace_agent_mesh/configs/error_catcher.yaml +56 -0
- solace_agent_mesh/configs/monitor.yaml +0 -0
- solace_agent_mesh/configs/monitor_stim_and_errors_to_slack.yaml +106 -0
- solace_agent_mesh/configs/monitor_user_feedback.yaml +58 -0
- solace_agent_mesh/configs/orchestrator.yaml +241 -0
- solace_agent_mesh/configs/service_embedding.yaml +81 -0
- solace_agent_mesh/configs/service_llm.yaml +265 -0
- solace_agent_mesh/configs/visualize_websocket.yaml +55 -0
- solace_agent_mesh/gateway/__init__.py +0 -0
- solace_agent_mesh/gateway/components/__init__.py +0 -0
- solace_agent_mesh/gateway/components/gateway_base.py +41 -0
- solace_agent_mesh/gateway/components/gateway_input.py +265 -0
- solace_agent_mesh/gateway/components/gateway_output.py +289 -0
- solace_agent_mesh/gateway/identity/bamboohr_identity.py +18 -0
- solace_agent_mesh/gateway/identity/identity_base.py +10 -0
- solace_agent_mesh/gateway/identity/identity_provider.py +60 -0
- solace_agent_mesh/gateway/identity/no_identity.py +9 -0
- solace_agent_mesh/gateway/identity/passthru_identity.py +9 -0
- solace_agent_mesh/monitors/base_monitor_component.py +26 -0
- solace_agent_mesh/monitors/feedback/user_feedback_monitor.py +75 -0
- solace_agent_mesh/monitors/stim_and_errors/stim_and_error_monitor.py +560 -0
- solace_agent_mesh/orchestrator/__init__.py +0 -0
- solace_agent_mesh/orchestrator/action_manager.py +225 -0
- solace_agent_mesh/orchestrator/components/__init__.py +0 -0
- solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +54 -0
- solace_agent_mesh/orchestrator/components/orchestrator_action_response_component.py +179 -0
- solace_agent_mesh/orchestrator/components/orchestrator_register_component.py +107 -0
- solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +477 -0
- solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +246 -0
- solace_agent_mesh/orchestrator/orchestrator_main.py +166 -0
- solace_agent_mesh/orchestrator/orchestrator_prompt.py +410 -0
- solace_agent_mesh/services/__init__.py +0 -0
- solace_agent_mesh/services/authorization/providers/base_authorization_provider.py +56 -0
- solace_agent_mesh/services/bamboo_hr_service/__init__.py +3 -0
- solace_agent_mesh/services/bamboo_hr_service/bamboo_hr.py +182 -0
- solace_agent_mesh/services/common/__init__.py +4 -0
- solace_agent_mesh/services/common/auto_expiry.py +45 -0
- solace_agent_mesh/services/common/singleton.py +18 -0
- solace_agent_mesh/services/file_service/__init__.py +14 -0
- solace_agent_mesh/services/file_service/file_manager/__init__.py +0 -0
- solace_agent_mesh/services/file_service/file_manager/bucket_file_manager.py +149 -0
- solace_agent_mesh/services/file_service/file_manager/file_manager_base.py +162 -0
- solace_agent_mesh/services/file_service/file_manager/memory_file_manager.py +64 -0
- solace_agent_mesh/services/file_service/file_manager/volume_file_manager.py +106 -0
- solace_agent_mesh/services/file_service/file_service.py +432 -0
- solace_agent_mesh/services/file_service/file_service_constants.py +54 -0
- solace_agent_mesh/services/file_service/file_transformations.py +131 -0
- solace_agent_mesh/services/file_service/file_utils.py +322 -0
- solace_agent_mesh/services/file_service/transformers/__init__.py +5 -0
- solace_agent_mesh/services/history_service/__init__.py +3 -0
- solace_agent_mesh/services/history_service/history_providers/__init__.py +0 -0
- solace_agent_mesh/services/history_service/history_providers/base_history_provider.py +78 -0
- solace_agent_mesh/services/history_service/history_providers/memory_history_provider.py +167 -0
- solace_agent_mesh/services/history_service/history_providers/redis_history_provider.py +163 -0
- solace_agent_mesh/services/history_service/history_service.py +139 -0
- solace_agent_mesh/services/llm_service/components/llm_request_component.py +293 -0
- solace_agent_mesh/services/llm_service/components/llm_service_component_base.py +152 -0
- solace_agent_mesh/services/middleware_service/__init__.py +0 -0
- solace_agent_mesh/services/middleware_service/middleware_service.py +20 -0
- solace_agent_mesh/templates/action.py +38 -0
- solace_agent_mesh/templates/agent.py +29 -0
- solace_agent_mesh/templates/agent.yaml +70 -0
- solace_agent_mesh/templates/gateway-config-template.yaml +6 -0
- solace_agent_mesh/templates/gateway-default-config.yaml +28 -0
- solace_agent_mesh/templates/gateway-flows.yaml +81 -0
- solace_agent_mesh/templates/gateway-header.yaml +16 -0
- solace_agent_mesh/templates/gateway_base.py +15 -0
- solace_agent_mesh/templates/gateway_input.py +98 -0
- solace_agent_mesh/templates/gateway_output.py +71 -0
- solace_agent_mesh/templates/plugin-pyproject.toml +30 -0
- solace_agent_mesh/templates/rest-api-default-config.yaml +23 -0
- solace_agent_mesh/templates/rest-api-flows.yaml +80 -0
- solace_agent_mesh/templates/slack-default-config.yaml +9 -0
- solace_agent_mesh/templates/slack-flows.yaml +90 -0
- solace_agent_mesh/templates/solace-agent-mesh-default.yaml +77 -0
- solace_agent_mesh/templates/solace-agent-mesh-plugin-default.yaml +8 -0
- solace_agent_mesh/templates/web-default-config.yaml +5 -0
- solace_agent_mesh/templates/web-flows.yaml +86 -0
- solace_agent_mesh/tools/__init__.py +0 -0
- solace_agent_mesh/tools/components/__init__.py +0 -0
- solace_agent_mesh/tools/components/conversation_formatter.py +111 -0
- solace_agent_mesh/tools/components/file_resolver_component.py +58 -0
- solace_agent_mesh/tools/config/runtime_config.py +26 -0
- solace_agent_mesh-0.1.0.dist-info/METADATA +179 -0
- solace_agent_mesh-0.1.0.dist-info/RECORD +170 -0
- solace_agent_mesh-0.1.0.dist-info/entry_points.txt +3 -0
- solace_agent_mesh-0.0.1.dist-info/licenses/LICENSE.txt → solace_agent_mesh-0.1.0.dist-info/licenses/LICENSE +1 -2
- solace_agent_mesh-0.0.1.dist-info/METADATA +0 -51
- solace_agent_mesh-0.0.1.dist-info/RECORD +0 -5
- {solace_agent_mesh-0.0.1.dist-info → solace_agent_mesh-0.1.0.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)
|