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.

Files changed (172) 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/cli/__init__.py +1 -0
  33. solace_agent_mesh/cli/commands/__init__.py +0 -0
  34. solace_agent_mesh/cli/commands/add/__init__.py +3 -0
  35. solace_agent_mesh/cli/commands/add/add.py +88 -0
  36. solace_agent_mesh/cli/commands/add/agent.py +110 -0
  37. solace_agent_mesh/cli/commands/add/copy_from_plugin.py +90 -0
  38. solace_agent_mesh/cli/commands/add/gateway.py +221 -0
  39. solace_agent_mesh/cli/commands/build.py +631 -0
  40. solace_agent_mesh/cli/commands/chat/__init__.py +3 -0
  41. solace_agent_mesh/cli/commands/chat/chat.py +361 -0
  42. solace_agent_mesh/cli/commands/config.py +29 -0
  43. solace_agent_mesh/cli/commands/init/__init__.py +3 -0
  44. solace_agent_mesh/cli/commands/init/ai_provider_step.py +76 -0
  45. solace_agent_mesh/cli/commands/init/broker_step.py +102 -0
  46. solace_agent_mesh/cli/commands/init/builtin_agent_step.py +88 -0
  47. solace_agent_mesh/cli/commands/init/check_if_already_done.py +13 -0
  48. solace_agent_mesh/cli/commands/init/create_config_file_step.py +52 -0
  49. solace_agent_mesh/cli/commands/init/create_other_project_files_step.py +96 -0
  50. solace_agent_mesh/cli/commands/init/file_service_step.py +73 -0
  51. solace_agent_mesh/cli/commands/init/init.py +114 -0
  52. solace_agent_mesh/cli/commands/init/project_structure_step.py +45 -0
  53. solace_agent_mesh/cli/commands/init/rest_api_step.py +50 -0
  54. solace_agent_mesh/cli/commands/init/web_ui_step.py +40 -0
  55. solace_agent_mesh/cli/commands/plugin/__init__.py +3 -0
  56. solace_agent_mesh/cli/commands/plugin/add.py +98 -0
  57. solace_agent_mesh/cli/commands/plugin/build.py +217 -0
  58. solace_agent_mesh/cli/commands/plugin/create.py +117 -0
  59. solace_agent_mesh/cli/commands/plugin/plugin.py +109 -0
  60. solace_agent_mesh/cli/commands/plugin/remove.py +71 -0
  61. solace_agent_mesh/cli/commands/run.py +68 -0
  62. solace_agent_mesh/cli/commands/visualizer.py +138 -0
  63. solace_agent_mesh/cli/config.py +81 -0
  64. solace_agent_mesh/cli/main.py +306 -0
  65. solace_agent_mesh/cli/utils.py +246 -0
  66. solace_agent_mesh/common/__init__.py +0 -0
  67. solace_agent_mesh/common/action.py +91 -0
  68. solace_agent_mesh/common/action_list.py +37 -0
  69. solace_agent_mesh/common/action_response.py +327 -0
  70. solace_agent_mesh/common/constants.py +3 -0
  71. solace_agent_mesh/common/mysql_database.py +40 -0
  72. solace_agent_mesh/common/postgres_database.py +79 -0
  73. solace_agent_mesh/common/prompt_templates.py +30 -0
  74. solace_agent_mesh/common/prompt_templates_unused_delete.py +161 -0
  75. solace_agent_mesh/common/stimulus_utils.py +152 -0
  76. solace_agent_mesh/common/time.py +24 -0
  77. solace_agent_mesh/common/utils.py +638 -0
  78. solace_agent_mesh/configs/agent_global.yaml +74 -0
  79. solace_agent_mesh/configs/agent_image_processing.yaml +82 -0
  80. solace_agent_mesh/configs/agent_slack.yaml +64 -0
  81. solace_agent_mesh/configs/agent_web_request.yaml +75 -0
  82. solace_agent_mesh/configs/conversation_to_file.yaml +56 -0
  83. solace_agent_mesh/configs/error_catcher.yaml +56 -0
  84. solace_agent_mesh/configs/monitor.yaml +0 -0
  85. solace_agent_mesh/configs/monitor_stim_and_errors_to_slack.yaml +106 -0
  86. solace_agent_mesh/configs/monitor_user_feedback.yaml +58 -0
  87. solace_agent_mesh/configs/orchestrator.yaml +241 -0
  88. solace_agent_mesh/configs/service_embedding.yaml +81 -0
  89. solace_agent_mesh/configs/service_llm.yaml +265 -0
  90. solace_agent_mesh/configs/visualize_websocket.yaml +55 -0
  91. solace_agent_mesh/gateway/__init__.py +0 -0
  92. solace_agent_mesh/gateway/components/__init__.py +0 -0
  93. solace_agent_mesh/gateway/components/gateway_base.py +41 -0
  94. solace_agent_mesh/gateway/components/gateway_input.py +265 -0
  95. solace_agent_mesh/gateway/components/gateway_output.py +289 -0
  96. solace_agent_mesh/gateway/identity/bamboohr_identity.py +18 -0
  97. solace_agent_mesh/gateway/identity/identity_base.py +10 -0
  98. solace_agent_mesh/gateway/identity/identity_provider.py +60 -0
  99. solace_agent_mesh/gateway/identity/no_identity.py +9 -0
  100. solace_agent_mesh/gateway/identity/passthru_identity.py +9 -0
  101. solace_agent_mesh/monitors/base_monitor_component.py +26 -0
  102. solace_agent_mesh/monitors/feedback/user_feedback_monitor.py +75 -0
  103. solace_agent_mesh/monitors/stim_and_errors/stim_and_error_monitor.py +560 -0
  104. solace_agent_mesh/orchestrator/__init__.py +0 -0
  105. solace_agent_mesh/orchestrator/action_manager.py +225 -0
  106. solace_agent_mesh/orchestrator/components/__init__.py +0 -0
  107. solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +54 -0
  108. solace_agent_mesh/orchestrator/components/orchestrator_action_response_component.py +179 -0
  109. solace_agent_mesh/orchestrator/components/orchestrator_register_component.py +107 -0
  110. solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +477 -0
  111. solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +246 -0
  112. solace_agent_mesh/orchestrator/orchestrator_main.py +166 -0
  113. solace_agent_mesh/orchestrator/orchestrator_prompt.py +410 -0
  114. solace_agent_mesh/services/__init__.py +0 -0
  115. solace_agent_mesh/services/authorization/providers/base_authorization_provider.py +56 -0
  116. solace_agent_mesh/services/bamboo_hr_service/__init__.py +3 -0
  117. solace_agent_mesh/services/bamboo_hr_service/bamboo_hr.py +182 -0
  118. solace_agent_mesh/services/common/__init__.py +4 -0
  119. solace_agent_mesh/services/common/auto_expiry.py +45 -0
  120. solace_agent_mesh/services/common/singleton.py +18 -0
  121. solace_agent_mesh/services/file_service/__init__.py +14 -0
  122. solace_agent_mesh/services/file_service/file_manager/__init__.py +0 -0
  123. solace_agent_mesh/services/file_service/file_manager/bucket_file_manager.py +149 -0
  124. solace_agent_mesh/services/file_service/file_manager/file_manager_base.py +162 -0
  125. solace_agent_mesh/services/file_service/file_manager/memory_file_manager.py +64 -0
  126. solace_agent_mesh/services/file_service/file_manager/volume_file_manager.py +106 -0
  127. solace_agent_mesh/services/file_service/file_service.py +432 -0
  128. solace_agent_mesh/services/file_service/file_service_constants.py +54 -0
  129. solace_agent_mesh/services/file_service/file_transformations.py +131 -0
  130. solace_agent_mesh/services/file_service/file_utils.py +322 -0
  131. solace_agent_mesh/services/file_service/transformers/__init__.py +5 -0
  132. solace_agent_mesh/services/history_service/__init__.py +3 -0
  133. solace_agent_mesh/services/history_service/history_providers/__init__.py +0 -0
  134. solace_agent_mesh/services/history_service/history_providers/base_history_provider.py +78 -0
  135. solace_agent_mesh/services/history_service/history_providers/memory_history_provider.py +167 -0
  136. solace_agent_mesh/services/history_service/history_providers/redis_history_provider.py +163 -0
  137. solace_agent_mesh/services/history_service/history_service.py +139 -0
  138. solace_agent_mesh/services/llm_service/components/llm_request_component.py +293 -0
  139. solace_agent_mesh/services/llm_service/components/llm_service_component_base.py +152 -0
  140. solace_agent_mesh/services/middleware_service/__init__.py +0 -0
  141. solace_agent_mesh/services/middleware_service/middleware_service.py +20 -0
  142. solace_agent_mesh/templates/action.py +38 -0
  143. solace_agent_mesh/templates/agent.py +29 -0
  144. solace_agent_mesh/templates/agent.yaml +70 -0
  145. solace_agent_mesh/templates/gateway-config-template.yaml +6 -0
  146. solace_agent_mesh/templates/gateway-default-config.yaml +28 -0
  147. solace_agent_mesh/templates/gateway-flows.yaml +81 -0
  148. solace_agent_mesh/templates/gateway-header.yaml +16 -0
  149. solace_agent_mesh/templates/gateway_base.py +15 -0
  150. solace_agent_mesh/templates/gateway_input.py +98 -0
  151. solace_agent_mesh/templates/gateway_output.py +71 -0
  152. solace_agent_mesh/templates/plugin-pyproject.toml +30 -0
  153. solace_agent_mesh/templates/rest-api-default-config.yaml +23 -0
  154. solace_agent_mesh/templates/rest-api-flows.yaml +80 -0
  155. solace_agent_mesh/templates/slack-default-config.yaml +9 -0
  156. solace_agent_mesh/templates/slack-flows.yaml +90 -0
  157. solace_agent_mesh/templates/solace-agent-mesh-default.yaml +77 -0
  158. solace_agent_mesh/templates/solace-agent-mesh-plugin-default.yaml +8 -0
  159. solace_agent_mesh/templates/web-default-config.yaml +5 -0
  160. solace_agent_mesh/templates/web-flows.yaml +86 -0
  161. solace_agent_mesh/tools/__init__.py +0 -0
  162. solace_agent_mesh/tools/components/__init__.py +0 -0
  163. solace_agent_mesh/tools/components/conversation_formatter.py +111 -0
  164. solace_agent_mesh/tools/components/file_resolver_component.py +58 -0
  165. solace_agent_mesh/tools/config/runtime_config.py +26 -0
  166. solace_agent_mesh-0.1.0.dist-info/METADATA +179 -0
  167. solace_agent_mesh-0.1.0.dist-info/RECORD +170 -0
  168. solace_agent_mesh-0.1.0.dist-info/entry_points.txt +3 -0
  169. solace_agent_mesh-0.0.1.dist-info/licenses/LICENSE.txt → solace_agent_mesh-0.1.0.dist-info/licenses/LICENSE +1 -2
  170. solace_agent_mesh-0.0.1.dist-info/METADATA +0 -51
  171. solace_agent_mesh-0.0.1.dist-info/RECORD +0 -5
  172. {solace_agent_mesh-0.0.1.dist-info → solace_agent_mesh-0.1.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,88 @@
1
+ import click
2
+
3
+ from .agent import add_agent_command
4
+ from .gateway import add_gateway_command, add_interface_command
5
+ from .copy_from_plugin import copy_from_plugin
6
+ from ...config import Config
7
+ from ...utils import log_error
8
+
9
+
10
+ def add_command(add):
11
+ @add.command()
12
+ @click.argument("name")
13
+ @click.option(
14
+ "-c",
15
+ "--copy-from",
16
+ help="Name of the plugin. Copying over an agent config from an existing plugin instead of creating a new one to allow for customization. If your desired agent name is different from the source agent name, use the format <plugin>:<source_agent_name>",
17
+ )
18
+ def agent(name, copy_from):
19
+ """
20
+ Creates a template for an agent.
21
+
22
+ name: Name of the component to create. Must be kebab-case. (don't add 'agent' to the name)
23
+ """
24
+ if copy_from:
25
+ return copy_from_plugin(name, copy_from, "agents")
26
+ return add_agent_command(name)
27
+
28
+ @add.command()
29
+ @click.argument("name")
30
+ @click.option(
31
+ "-i",
32
+ "--interface",
33
+ help="The interface(s) to add to the gateway. For example, to add rest and slack interfaces use: --interface slack --interface rest-api",
34
+ multiple=True,
35
+ )
36
+ @click.option(
37
+ "-c",
38
+ "--copy-from",
39
+ help="Name of the plugin. Copying over a gateway configs from an existing plugin instead of creating a new one to allow for customization. If your desired gateway name is different from the source gateway name, use the format <plugin>:<source_gateway_name>",
40
+ )
41
+ @click.option(
42
+ "-n",
43
+ "--new-interface",
44
+ default=False,
45
+ is_flag=True,
46
+ help="Create a new gateway interface - supported only in plugin projects.",
47
+ )
48
+ def gateway(
49
+ name,
50
+ interface,
51
+ copy_from,
52
+ new_interface,
53
+ ):
54
+ """
55
+ Creates a template for a gateway.
56
+
57
+ name: Name of the component to create. Must be kebab-case. (don't add 'gateway' to the name)
58
+
59
+ If no interfaces is provided, a gateway from scratch will be created.
60
+ """
61
+ interface = list(interface)
62
+
63
+ if new_interface and interface:
64
+ log_error(
65
+ "Error: The --new-interface/-n flag is supported only when no interfaces are provided."
66
+ )
67
+ return 1
68
+
69
+ if copy_from and interface:
70
+ log_error(
71
+ "Error: The --copy-from/-c flag is supported only when no interfaces are provided."
72
+ )
73
+
74
+ # Copy from plugin
75
+ if copy_from:
76
+ return copy_from_plugin(name, copy_from, "gateways")
77
+
78
+ # Creating a new gateway interface
79
+ if new_interface:
80
+ if not Config.is_plugin_project():
81
+ log_error(
82
+ "Error: The --new-interface flag is supported only in plugin projects."
83
+ )
84
+ return 1
85
+ return add_interface_command(name)
86
+
87
+ # Create a new gateway from an interface
88
+ return add_gateway_command(name, interface)
@@ -0,0 +1,110 @@
1
+ import os
2
+ import click
3
+
4
+ from cli.utils import get_display_path, load_template, log_error, get_formatted_names
5
+
6
+
7
+ def add_agent_command(name):
8
+ """
9
+ Creates a template for an agent
10
+ """
11
+ # Name must be kebab-case, and only character, numbers, and hyphens are allowed
12
+ if not name.islower() or not name.replace("-", "").isalnum():
13
+ log_error(
14
+ "Error: Name must be kebab-case. Only lowercase letters, numbers, and hyphens are allowed.",
15
+ )
16
+ return 1
17
+
18
+ formatted_name = get_formatted_names(name)
19
+
20
+ try:
21
+ # Load the template file
22
+ template_file = load_template("agent.yaml", formatted_name)
23
+ if template_file is None:
24
+ log_error("Error: Template file for agent not found.")
25
+ return 1
26
+ except IOError as e:
27
+ log_error(f"Error reading template file: {e}")
28
+ return 1
29
+
30
+ config = click.get_current_context().obj
31
+ config_directory = config["solace_agent_mesh"]["config_directory"]
32
+
33
+ try:
34
+ file_name = f"{formatted_name['SNAKE_CASE_NAME']}.yaml"
35
+ directory = os.path.join(config_directory, "agents")
36
+ path = os.path.join(directory, file_name)
37
+
38
+ # Check if the file already exists
39
+ if os.path.exists(path):
40
+ overwrite = click.confirm(
41
+ f"File {path} already exists. Do you want to overwrite it?",
42
+ default=False,
43
+ )
44
+ if not overwrite:
45
+ click.echo("Template not created.")
46
+ return
47
+
48
+ # Create the directory if it doesn't exist
49
+ os.makedirs(directory, exist_ok=True)
50
+ with open(path, "w", encoding="utf-8") as f:
51
+ f.write(template_file)
52
+ except IOError as e:
53
+ log_error(f"Error creating template: {e}")
54
+ return 1
55
+
56
+ click.echo(f"Created agent template at: {get_display_path(path)}")
57
+
58
+ try:
59
+ # Creating the agent file
60
+ agent_directory = os.path.join(
61
+ config["solace_agent_mesh"]["modules_directory"],
62
+ "agents",
63
+ formatted_name["SNAKE_CASE_NAME"],
64
+ )
65
+ # Create the agent directory
66
+ os.makedirs(agent_directory, exist_ok=True)
67
+ # Create the __init__.py file
68
+ init_file = os.path.join(agent_directory, "__init__.py")
69
+ if not os.path.exists(init_file):
70
+ with open(init_file, "w", encoding="utf-8") as f:
71
+ f.write("")
72
+
73
+ # Create the agent python file
74
+ agent_path = os.path.join(
75
+ agent_directory,
76
+ f"{formatted_name['SNAKE_CASE_NAME']}_agent_component.py",
77
+ )
78
+ agent_template = load_template("agent.py", formatted_name)
79
+ if not os.path.exists(agent_path):
80
+ with open(agent_path, "w", encoding="utf-8") as f:
81
+ f.write(agent_template)
82
+
83
+ click.echo(
84
+ f"Created agent at: {get_display_path(agent_path)}"
85
+ )
86
+
87
+ # Create the agent action
88
+ action_directory = os.path.join(agent_directory, "actions")
89
+ os.makedirs(action_directory, exist_ok=True)
90
+ # Create the __init__.py file
91
+ init_file = os.path.join(action_directory, "__init__.py")
92
+ if not os.path.exists(init_file):
93
+ with open(init_file, "w", encoding="utf-8") as f:
94
+ f.write("")
95
+
96
+ action_path = os.path.join(action_directory, "sample_action.py")
97
+ action_template = load_template("action.py", formatted_name)
98
+ if not os.path.exists(action_path):
99
+ with open(action_path, "w", encoding="utf-8") as f:
100
+ f.write(action_template)
101
+
102
+ click.echo(f"Created sample action at: {get_display_path(action_path)}")
103
+
104
+ temp_file = os.path.join(config_directory, "__TEMPLATES_WILL_BE_HERE__")
105
+ if os.path.exists(temp_file):
106
+ os.remove(temp_file)
107
+ except IOError as e:
108
+ log_error(f"Error creating agent, agent config was created: {e}")
109
+ return 1
110
+
@@ -0,0 +1,90 @@
1
+ import os
2
+ import click
3
+
4
+ from cli.utils import log_error, load_plugin, get_display_path, get_formatted_names
5
+
6
+
7
+ def copy_from_plugin(name, plugin_name, entity_type):
8
+ """
9
+ Creates a template for an agent or gateway by copying from an existing plugin.
10
+
11
+ name: Name of the component to create.
12
+ plugin_name: Name of the plugin. This is either just the plugin or plugin:entity_name
13
+ for cases where the source config name is different from the destination name
14
+ entity_type: Type of the entity to create. (agents or gateways)
15
+ """
16
+ if entity_type not in ["agents", "gateways"]:
17
+ log_error("Invalid entity type.")
18
+ return 1
19
+
20
+ src_entity_name = name
21
+ if ":" in plugin_name:
22
+ plugin_name, src_entity_name = plugin_name.split(":")
23
+
24
+ plugin_name = plugin_name.replace("-", "_")
25
+ plugin_path = load_plugin(plugin_name, return_path_only=True)
26
+ if not plugin_path:
27
+ log_error(f"Could not find '{plugin_name}' installed.")
28
+ return 1
29
+
30
+ name_cases = get_formatted_names(name)
31
+
32
+ item_name = name.replace("-", "_")
33
+ item_name = f"{item_name}.yaml" if entity_type == "agents" else item_name
34
+
35
+ src_entity_name = src_entity_name.replace("-", "_")
36
+ src_entity_name = f"{src_entity_name}.yaml" if entity_type == "agents" else src_entity_name
37
+ template_path = os.path.join(plugin_path, "configs", entity_type, src_entity_name)
38
+
39
+ if not os.path.exists(template_path):
40
+ log_error(f"Could not find '{item_name}' in '{plugin_name}' plugin.")
41
+ return 1
42
+
43
+ config = click.get_current_context().obj
44
+ config_directory = config["solace_agent_mesh"]["config_directory"]
45
+ target_directory = os.path.join(config_directory, entity_type)
46
+ os.makedirs(target_directory, exist_ok=True)
47
+
48
+ def parse_file(content):
49
+ content = (
50
+ content.replace(" src.", f" {plugin_name}.src.")
51
+ .replace("{{MODULE_DIRECTORY}}", f"{plugin_name}.src")
52
+ .replace("src.src.", "src.")
53
+ )
54
+ for case, val in name_cases.items():
55
+ content = content.replace(f"{{{{{case}}}}}", val)
56
+
57
+ return content
58
+
59
+ if entity_type == "agents":
60
+ with open(template_path, "r", encoding="utf-8") as f:
61
+ template_file = parse_file(f.read())
62
+ target_path = os.path.join(target_directory, item_name)
63
+ with open(target_path, "w", encoding="utf-8") as f:
64
+ f.write(template_file)
65
+
66
+ elif entity_type == "gateways":
67
+ target_directory = os.path.join(target_directory, item_name)
68
+ os.makedirs(target_directory, exist_ok=True)
69
+
70
+ for file_item in os.listdir(template_path):
71
+ source_path = os.path.join(template_path, file_item)
72
+ if not os.path.isfile(source_path):
73
+ continue
74
+ with open(source_path, "r", encoding="utf-8") as f:
75
+ template_file = parse_file(f.read())
76
+ target_path = os.path.join(target_directory, file_item)
77
+ with open(target_path, "w", encoding="utf-8") as f:
78
+ f.write(template_file)
79
+
80
+ else:
81
+ log_error("Invalid entity type.")
82
+ return 1
83
+
84
+ temp_file = os.path.join(config_directory, "__TEMPLATES_WILL_BE_HERE__")
85
+ if os.path.exists(temp_file):
86
+ os.remove(temp_file)
87
+
88
+ click.echo(
89
+ f"Copied {entity_type[:-1]} '{name}' from plugin '{plugin_name}' at: {get_display_path(target_directory)}"
90
+ )
@@ -0,0 +1,221 @@
1
+ import os
2
+ import sys
3
+ import click
4
+
5
+ from cli.utils import get_display_path, load_template, log_error, get_formatted_names
6
+ from cli.commands.plugin.build import get_all_plugin_gateway_interfaces
7
+ from cli.config import Config
8
+
9
+ def _add_python_files(modules_directory, template_args, created_file_names):
10
+ # Creating the python files
11
+ module_directory = os.path.join(
12
+ modules_directory,
13
+ "gateways",
14
+ template_args["SNAKE_CASE_NAME"],
15
+ )
16
+ # Create the gateway directory
17
+ os.makedirs(module_directory, exist_ok=True)
18
+ # Create the __init__.py file
19
+ init_file = os.path.join(module_directory, "__init__.py")
20
+ if not os.path.exists(init_file):
21
+ with open(init_file, "w", encoding="utf-8") as f:
22
+ f.write("")
23
+ created_file_names.append(init_file)
24
+
25
+ # Create the gateway python file
26
+ for gateways_file in ["base", "input", "output"]:
27
+ gateway_path = os.path.join(
28
+ module_directory,
29
+ f"{template_args['SNAKE_CASE_NAME']}_{gateways_file}.py",
30
+ )
31
+ gateway_template = load_template(f"gateway_{gateways_file}.py", template_args)
32
+ if not os.path.exists(gateway_path):
33
+ with open(gateway_path, "w", encoding="utf-8") as f:
34
+ f.write(gateway_template)
35
+ created_file_names.append(gateway_path)
36
+
37
+ def add_gateway_command(name, interfaces):
38
+ """
39
+ Creates a gateway configuration directory and files based on provided templates.
40
+
41
+ This function performs the following steps:
42
+ 1. Creates a directory for the gateway in the specified configuration directory.
43
+ 2. Copies a gateway configuration template file to the new gateway directory.
44
+ 3. If a list of interfaces is provided, creates configuration files for each interface based on corresponding templates.
45
+
46
+ Args:
47
+ interfaces (list): A list of interface names for which configuration files should be created.
48
+ formatted_name (dict): A dictionary containing the formatted name of the gateway.
49
+ The key "SNAKE_CASE_NAME" is used to name the gateway directory.
50
+
51
+ Returns:
52
+ int: Returns 1 if an IOError occurs during the creation of the gateway configuration, otherwise returns None.
53
+
54
+ Raises:
55
+ IOError: If there is an error creating the gateway configuration files or directories.
56
+ """
57
+
58
+ # Name must be kebab-case, and only character, numbers, and hyphens are allowed
59
+ if not name.islower() or not name.replace("-", "").isalnum():
60
+ log_error(
61
+ "Error: Name must be kebab-case. Only lowercase letters, numbers, and hyphens are allowed.",
62
+ )
63
+ return 1
64
+
65
+ formatted_name = get_formatted_names(name)
66
+ created_file_names = []
67
+
68
+ try:
69
+ # Create a directory for the gateway in the config directory
70
+ config = click.get_current_context().obj["solace_agent_mesh"]
71
+ config_directory = config["config_directory"]
72
+ gateway_directory = os.path.join(
73
+ config_directory, "gateways", formatted_name["SNAKE_CASE_NAME"]
74
+ )
75
+
76
+ def abort():
77
+ sys.exit(1)
78
+
79
+ plugin_gateway_interfaces = get_all_plugin_gateway_interfaces(config, abort)
80
+
81
+ # Check if the gateway directory already exists
82
+ if os.path.exists(gateway_directory):
83
+ overwrite = click.confirm(
84
+ f"Gateway directory {gateway_directory} already exists. Do you want to overwrite it?",
85
+ default=False,
86
+ )
87
+ if not overwrite:
88
+ click.echo("Gateway template not created.")
89
+ return
90
+ os.makedirs(gateway_directory, exist_ok=True)
91
+
92
+ # Create the gateway config file from the template directory
93
+ # The file name is gateway-default-config.yaml but write it as gateway.yaml in the gateway_directory
94
+ gateway_config_template = load_template("gateway-default-config.yaml")
95
+ gateway_config_path = os.path.join(gateway_directory, "gateway.yaml")
96
+ with open(gateway_config_path, "w", encoding="utf-8") as f:
97
+ f.write(gateway_config_template)
98
+
99
+ created_file_names.append(gateway_config_path)
100
+
101
+ # If the interface list is not empty, create the interface config files
102
+ if interfaces:
103
+ for interface in interfaces:
104
+ # Load the interface template from the templates directory.
105
+ # The name will be {interface}-default-config.yaml
106
+ # Write the file as {interface}.yaml in the gateway_directory
107
+ if interface in plugin_gateway_interfaces:
108
+ interface_default_path = os.path.join(
109
+ plugin_gateway_interfaces[interface],
110
+ f"{interface}-default-config.yaml",
111
+ )
112
+ if not os.path.exists(interface_default_path):
113
+ log_error("Error: Interface template not found.")
114
+ return 1
115
+ with open(interface_default_path, "r", encoding="utf-8") as g:
116
+ interface_template = g.read()
117
+ else:
118
+ interface_template = load_template(
119
+ f"{interface}-default-config.yaml"
120
+ )
121
+ if not interface_template:
122
+ log_error("Error: Interface template not found.")
123
+ return 1
124
+
125
+ interface_config_path = os.path.join(
126
+ gateway_directory, f"{interface}.yaml"
127
+ )
128
+ with open(interface_config_path, "w", encoding="utf-8") as f:
129
+ f.write(interface_template)
130
+
131
+ created_file_names.append(interface_config_path)
132
+
133
+ else:
134
+ click.echo(click.style("No interfaces provided. A gateway from scratch will be created.", fg="yellow"))
135
+ try:
136
+ # Create the gateway config file
137
+ interface_config_path = os.path.join(
138
+ gateway_directory,
139
+ f"{formatted_name['SNAKE_CASE_NAME']}.yaml",
140
+ )
141
+ gateway_template = load_template("gateway-config-template.yaml", formatted_name)
142
+ if not os.path.exists(interface_config_path):
143
+ with open(interface_config_path, "w", encoding="utf-8") as f:
144
+ f.write(gateway_template)
145
+ created_file_names.append(interface_config_path)
146
+
147
+ _add_python_files(config["modules_directory"], formatted_name, created_file_names)
148
+ except IOError as e:
149
+ log_error(f"Error creating gateway, gateway config was created: {e}")
150
+ return 1
151
+
152
+ temp_file = os.path.join(config_directory, "__TEMPLATES_WILL_BE_HERE__")
153
+ if os.path.exists(temp_file):
154
+ os.remove(temp_file)
155
+
156
+ except IOError as e:
157
+ log_error(f"Error creating gateway config: {e}")
158
+ return 1
159
+
160
+ finally:
161
+ if created_file_names:
162
+ click.echo("Created the following gateway template files:")
163
+ for file_name in created_file_names:
164
+ click.echo(f" - {get_display_path(file_name)}")
165
+
166
+
167
+ def add_interface_command(name):
168
+ """
169
+ Creates a new gateway interface with the provided name.
170
+ """
171
+ config = Config.get_plugin_config()
172
+ plugin_name = config.get("solace_agent_mesh_plugin", {}).get("name")
173
+ if not plugin_name or plugin_name == "solace-agent-mesh-plugin":
174
+ log_error("Could not find a valid plugin project")
175
+ return 1
176
+
177
+ plugin_name = plugin_name.replace("-","_")
178
+ template_args = get_formatted_names(name)
179
+ template_args.update({
180
+ "MODULE_DIRECTORY": f"{plugin_name}.src"
181
+ })
182
+ created_file_names = []
183
+
184
+ interfaces_directory = os.path.join("interfaces")
185
+ modules_directory = os.path.join("src")
186
+
187
+ try:
188
+ os.makedirs(interfaces_directory, exist_ok=True)
189
+
190
+ temp_file = os.path.join(interfaces_directory, "__INTERFACES_WILL_BE_HERE__")
191
+ if os.path.exists(temp_file):
192
+ os.remove(temp_file)
193
+
194
+ # Create the interface flows and config file
195
+ interface_flows_path = os.path.join(interfaces_directory, f"{template_args['HYPHENED_NAME']}-flows.yaml")
196
+ interface_config_path = os.path.join(interfaces_directory, f"{template_args['HYPHENED_NAME']}-default-config.yaml")
197
+
198
+ interface_flows_template = load_template("gateway-flows.yaml", template_args)
199
+ interface_flows_template = interface_flows_template.replace(" src.gateway", " solace_agent_mesh.src.gateway")
200
+ if not os.path.exists(interface_flows_path):
201
+ with open(interface_flows_path, "w", encoding="utf-8") as f:
202
+ f.write(interface_flows_template)
203
+ created_file_names.append(interface_flows_path)
204
+
205
+ interface_config_template = load_template("gateway-config-template.yaml", template_args)
206
+ if not os.path.exists(interface_config_path):
207
+ with open(interface_config_path, "w", encoding="utf-8") as f:
208
+ f.write(interface_config_template)
209
+ created_file_names.append(interface_config_path)
210
+
211
+ _add_python_files(modules_directory, template_args, created_file_names)
212
+
213
+ except IOError as e:
214
+ log_error(f"Error creating gateway interface, {e}")
215
+ return 1
216
+
217
+ finally:
218
+ if created_file_names:
219
+ click.echo("Created the following gateway template files:")
220
+ for file_name in created_file_names:
221
+ click.echo(f" - {get_display_path(file_name)}")