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,361 @@
1
+ import click
2
+ import requests
3
+ import os
4
+ import json
5
+ import pyperclip
6
+ import uuid
7
+ import base64
8
+ import stat
9
+
10
+ from ...utils import log_error
11
+ from ...utils import log_link
12
+ from ...utils import log_success
13
+
14
+ XDG_CONFIG_HOME = os.getenv(
15
+ "XDG_CONFIG_HOME", os.path.expanduser("~/.config/solace_agent_mesh")
16
+ )
17
+
18
+ XDG_DOWNLOAD_DIR = os.getenv(
19
+ "XDG_DOWNLOAD_DIR", os.path.expanduser("~/Downloads/solace_agent_mesh")
20
+ )
21
+
22
+ TOKEN_FILE = os.path.join(XDG_CONFIG_HOME, "token.json")
23
+ CONFIG_FILE = os.path.join(XDG_CONFIG_HOME, "setting.conf")
24
+
25
+
26
+ def validate_token(server, access_token):
27
+ """
28
+ Validate the access token with the server.
29
+ """
30
+ response = requests.post(
31
+ f"{server}/is_token_valid",
32
+ headers={"Authorization": f"Bearer {access_token}"},
33
+ )
34
+ return response.status_code
35
+
36
+
37
+ def config_directory():
38
+ """
39
+ Get the configuration directory path.
40
+ """
41
+ return XDG_CONFIG_HOME
42
+
43
+
44
+ def file_directory():
45
+ """
46
+ Get the file directory path.
47
+ """
48
+ return XDG_DOWNLOAD_DIR
49
+
50
+
51
+ def set_permission(file_path):
52
+ """
53
+ Set file permissions to be readable and writable only by the owner.
54
+ """
55
+ os.chmod(file_path, stat.S_IRUSR | stat.S_IWUSR)
56
+
57
+
58
+ def save_configuration(conf: dict):
59
+ """
60
+ Save the server address to the configuration file.
61
+ """
62
+ home_dir = config_directory()
63
+
64
+ # Create the home directory if it does not exist
65
+ os.makedirs(home_dir, exist_ok=True)
66
+
67
+ # Load existing configuration if it exists
68
+ if os.path.exists(CONFIG_FILE):
69
+ with open(CONFIG_FILE, "r") as f:
70
+ existing_conf = json.load(f)
71
+ else:
72
+ existing_conf = {}
73
+
74
+ # Update the existing configuration with new values
75
+ existing_conf.update(conf)
76
+
77
+ # Save the updated configuration
78
+ with open(CONFIG_FILE, "w") as f:
79
+ json.dump(existing_conf, f)
80
+ set_permission(CONFIG_FILE)
81
+
82
+
83
+ def save_files(files):
84
+ """
85
+ Save files to the file directory.
86
+ """
87
+ if files:
88
+ file_directory_path = file_directory()
89
+ os.makedirs(file_directory_path, exist_ok=True)
90
+ for file in files:
91
+ file_name = file["name"]
92
+ file_content = file["content"]
93
+ file_type = file["mime_type"]
94
+ if file_type.startswith("image/"):
95
+ # Decode Base64
96
+ file_content = base64.b64decode(file_content)
97
+ else:
98
+ file_content = file_content.encode("utf-8")
99
+
100
+ file_path = os.path.join(file_directory_path, file_name)
101
+ with open(file_path, "wb") as f:
102
+ f.write(file_content)
103
+ click.echo(f"File saved in {file_path}")
104
+
105
+
106
+ def chat_command(chat):
107
+ """
108
+ Login and start a chat conversation.
109
+ """
110
+
111
+ @chat.command()
112
+ @click.argument("server")
113
+ def login(server):
114
+ """Log in to the solace-agent-mesh application."""
115
+ if not server:
116
+ log_error("Server address is required.")
117
+ return
118
+
119
+ # Save the server address
120
+ save_configuration({"auth_server": server})
121
+
122
+ try:
123
+ url = f"{server}/login"
124
+ click.secho(
125
+ "\U0001F447 Please authenticate by visiting the following URL:",
126
+ fg="green",
127
+ )
128
+ log_link(url)
129
+
130
+ click.prompt(
131
+ click.style(
132
+ "\U0001F4C4 Copy the entire json object and press Enter (Ctrl+D to exit)",
133
+ fg="green",
134
+ ),
135
+ default="",
136
+ show_default=False,
137
+ )
138
+
139
+ token = pyperclip.paste()
140
+
141
+ # Save the response as JSON
142
+ with open(TOKEN_FILE, "w") as f:
143
+ json.dump(json.loads(token), f)
144
+ set_permission(TOKEN_FILE)
145
+
146
+ token_data = json.loads(token)
147
+
148
+ # Verify the token
149
+ try:
150
+ status_code = validate_token(server, token_data.get("access_token"))
151
+ if status_code == 200:
152
+ log_success("Login successful.")
153
+ else:
154
+ log_error("Token is invalid or expired. Please log in again.")
155
+ return
156
+ except requests.exceptions.RequestException as e:
157
+ log_error(f"Token validation failed: {e}")
158
+ return
159
+
160
+ except requests.exceptions.RequestException as e:
161
+ log_error(f"Login failed: {e}")
162
+
163
+ @chat.command()
164
+ def logout():
165
+ """Log out from the solace-agent-mesh application."""
166
+ if os.path.exists(TOKEN_FILE):
167
+ os.remove(TOKEN_FILE)
168
+ log_success("Logout successful.")
169
+ else:
170
+ log_error("No active session found.")
171
+
172
+ @chat.command()
173
+ @click.option(
174
+ "-s",
175
+ "--stream",
176
+ is_flag=True,
177
+ help="Stream mode.",
178
+ default=False,
179
+ )
180
+ @click.option(
181
+ "-a",
182
+ "--auth",
183
+ is_flag=True,
184
+ help="Enable authentication.",
185
+ default=False,
186
+ )
187
+ @click.option(
188
+ "-u",
189
+ "--url",
190
+ help="Chat endpoint url (e.g., https://<server>/api/v1/request).",
191
+ )
192
+ @click.option(
193
+ "-f",
194
+ "--file",
195
+ type=click.Path(exists=True, dir_okay=False, resolve_path=True),
196
+ multiple=True,
197
+ help="Attach files to the chat. Use -f or --file for each file.",
198
+ )
199
+ def start(stream, auth, url, file):
200
+ """Establish a chat with solace-agent-mesh plugin application."""
201
+
202
+ # Load the rest server address
203
+ rest_server = None
204
+ if url is not None:
205
+ # save the server address
206
+ rest_server = url
207
+ save_configuration({"rest_api_server": rest_server})
208
+ elif os.path.exists(CONFIG_FILE):
209
+ # load the server address from the configuration file
210
+ with open(CONFIG_FILE, "r") as f:
211
+ setting_data = json.load(f)
212
+ rest_server = setting_data.get("rest_api_server", None)
213
+ if rest_server is None:
214
+ rest_server = click.prompt(
215
+ click.style(
216
+ "💬 Enter the server address (e.g., https://<server>/api/v1/request): ",
217
+ fg="green",
218
+ )
219
+ )
220
+ # Save the server address
221
+ save_configuration({"rest_api_server": rest_server})
222
+
223
+ session_id = str(uuid.uuid4())
224
+ rest_endpoint_headers = {}
225
+
226
+ # Authenticate if it is enabled
227
+ if auth:
228
+ # Load authentication server
229
+ with open(CONFIG_FILE, "r") as f:
230
+ setting_data = json.load(f)
231
+ auth_server = setting_data.get("auth_server", "")
232
+ if not auth_server:
233
+ log_error(
234
+ "Authentication server not found. Please log in using 'sam login <server name>'."
235
+ )
236
+ return
237
+
238
+ # Load the token
239
+ if not os.path.exists(TOKEN_FILE):
240
+ log_error(
241
+ "Token not found. Please log in using 'sam login <server name>'."
242
+ )
243
+ return
244
+
245
+ try:
246
+ with open(TOKEN_FILE, "r") as f:
247
+ token_data = json.load(f)
248
+ access_token = token_data.get("access_token")
249
+ refresh_token = token_data.get("refresh_token")
250
+
251
+ if access_token and refresh_token:
252
+ # Validate token
253
+ try:
254
+ status_code = validate_token(auth_server, access_token)
255
+ if status_code != 200:
256
+ # Refresh token
257
+ response = requests.post(
258
+ f"{auth_server}/refresh_token",
259
+ headers={
260
+ "Content-Type": "application/json",
261
+ "Authorization": f"Bearer {access_token}",
262
+ },
263
+ json={"refresh_token": refresh_token},
264
+ )
265
+ if response.status_code == 200:
266
+ access_token = response.json()
267
+ else:
268
+ log_error(
269
+ "Failed to refresh token. Please log in again."
270
+ )
271
+ return
272
+ rest_endpoint_headers = {
273
+ "Authorization": f"Bearer {access_token}"
274
+ }
275
+ except requests.exceptions.RequestException as e:
276
+ log_error(f"Token validation failed: {e}")
277
+ return
278
+ else:
279
+ log_error(
280
+ "Invalid token data. Please log in again using 'sam login <server name>'."
281
+ )
282
+ return
283
+ except Exception as e:
284
+ log_error(
285
+ f"Token data not found: {e}. Please log in again using 'sam login <server name>'."
286
+ )
287
+ return
288
+
289
+ try:
290
+ files_to_send = []
291
+ if file:
292
+ for file_path in file:
293
+ file_name = os.path.basename(file_path)
294
+ files_to_send.append(("files", (file_name, open(file_path, "rb"))))
295
+
296
+ while True:
297
+ user_prompt = click.prompt(
298
+ click.style("💬 How can I help you? (Ctrl+D to exit)", fg="green")
299
+ )
300
+ # Exit the chat
301
+ if user_prompt.lower() == "exit":
302
+ break
303
+ # Skip empty prompts
304
+ if not user_prompt.strip():
305
+ continue
306
+
307
+ try:
308
+ response = requests.post(
309
+ f"{rest_server}",
310
+ headers=rest_endpoint_headers,
311
+ data={
312
+ "prompt": user_prompt,
313
+ "stream": stream,
314
+ "session_id": session_id,
315
+ },
316
+ files=files_to_send,
317
+ )
318
+ response.raise_for_status()
319
+
320
+ if stream:
321
+ buffer = ""
322
+ for chunk in response.iter_content(chunk_size=1):
323
+ utf_chunk = chunk.decode("utf-8")
324
+ buffer += utf_chunk
325
+
326
+ while "\n\n" in buffer:
327
+ split_chunk = buffer.split("\n\n", 1)
328
+ data_chunk = split_chunk[0]
329
+ buffer = split_chunk[1]
330
+
331
+ if data_chunk == "data: [DONE]":
332
+ break
333
+ data = json.loads(data_chunk[6:])
334
+ content = data.get("content", "")
335
+ if content:
336
+ click.echo(content, nl=False)
337
+ status_message = data.get("status_message", "")
338
+ if status_message:
339
+ click.secho(status_message, nl=True, fg="yellow")
340
+ # Save files
341
+ if "files" in data:
342
+ files = data["files"]
343
+ save_files(files)
344
+ else:
345
+ data = response.json()
346
+ click.echo(f"{data['response']['content']}")
347
+ # Save files
348
+ if "files" in data["response"]:
349
+ files = data["response"]["files"]
350
+ save_files(files)
351
+ click.echo("\n")
352
+
353
+ except requests.exceptions.RequestException as e:
354
+ log_error(f"Request failed: {e}")
355
+ return
356
+
357
+ except json.JSONDecodeError:
358
+ log_error(
359
+ "Sorry! I could not response to your request. Please try again later."
360
+ )
361
+ return
@@ -0,0 +1,29 @@
1
+ import os
2
+ import click
3
+
4
+ from cli.config import Config
5
+ from cli.utils import load_template, get_display_path
6
+
7
+
8
+ def config_command():
9
+ """Update the config file with new default settings."""
10
+ config_path = Config.user_config_file
11
+
12
+ if not os.path.exists(config_path):
13
+ click.echo(
14
+ click.style(
15
+ (
16
+ "No config file found. "
17
+ "\n\tRun `solace-agent-mesh init` to generate a new config file."
18
+ ),
19
+ fg="yellow",
20
+ )
21
+ )
22
+ return 1
23
+
24
+ config = Config.get_config(config_path)
25
+ Config.write_config(config, config_path)
26
+
27
+ click.echo(
28
+ f"Config file updated with latest default configurations at {get_display_path(config_path)}"
29
+ )
@@ -0,0 +1,3 @@
1
+ from .init import init_command
2
+
3
+ __all__ = ["init_command"]
@@ -0,0 +1,76 @@
1
+ import click
2
+
3
+ from cli.utils import ask_if_not_provided
4
+
5
+
6
+ def ai_provider_step(options, default_options, none_interactive, abort):
7
+ """
8
+ Initialize the AI provider.
9
+ """
10
+ ask_if_not_provided(
11
+ options,
12
+ "llm_endpoint_url",
13
+ "Provide LLM endpoint URL",
14
+ default_options["llm_endpoint_url"],
15
+ none_interactive,
16
+ )
17
+
18
+ ask_if_not_provided(
19
+ options,
20
+ "llm_api_key",
21
+ "Provide LLM API Key",
22
+ default_options["llm_api_key"],
23
+ none_interactive,
24
+ hide_input=True,
25
+ )
26
+ click.echo(
27
+ click.style(
28
+ (
29
+ "The model name should follow the format `provider/model-name`."
30
+ "\n\t For example: openai/gpt-4o or openai/my-model-that-follows-openai-api"
31
+ ),
32
+ fg="yellow",
33
+ )
34
+ )
35
+ ask_if_not_provided(
36
+ options,
37
+ "llm_model_name",
38
+ "Provide LLM model name to use",
39
+ default_options["llm_model_name"],
40
+ none_interactive,
41
+ )
42
+
43
+ ask_if_not_provided(
44
+ options,
45
+ "embedding_endpoint_url",
46
+ "Provide Embedding endpoint URL",
47
+ default_options["embedding_endpoint_url"],
48
+ none_interactive,
49
+ )
50
+
51
+ ask_if_not_provided(
52
+ options,
53
+ "embedding_api_key",
54
+ "Provide Embedding API Key",
55
+ default_options["embedding_api_key"],
56
+ none_interactive,
57
+ hide_input=True,
58
+ )
59
+
60
+ click.echo(
61
+ click.style(
62
+ (
63
+ "The model name should follow the format `provider/model-name`."
64
+ "\n\t For example: openai/text-embedding-ada-002 or openai/my-model-that-follows-openai-api"
65
+ ),
66
+ fg="yellow",
67
+ )
68
+ )
69
+
70
+ ask_if_not_provided(
71
+ options,
72
+ "embedding_model_name",
73
+ "Provide Embedding model name to use",
74
+ default_options["embedding_model_name"],
75
+ none_interactive,
76
+ )
@@ -0,0 +1,102 @@
1
+ import shutil
2
+ import click
3
+ import os
4
+
5
+ from cli.utils import ask_if_not_provided
6
+
7
+
8
+ CONTAINER_RUN_COMMAND = " run -d -p 8080:8080 -p 55554:55555 -p 8008:8008 -p 1883:1883 -p 8000:8000 -p 5672:5672 -p 9000:9000 -p 2222:2222 --shm-size=2g --env username_admin_globalaccesslevel=admin --env username_admin_password=admin --name=solace solace/solace-pubsub-standard"
9
+
10
+
11
+ def broker_step(options, default_options, none_interactive, abort):
12
+ """
13
+ Initialize the broker.
14
+ """
15
+ broker_type = ask_if_not_provided(
16
+ options,
17
+ "broker_type",
18
+ (
19
+ "Which broker type do you want to use?\n"
20
+ "\t1) Existing Solace Pub/Sub+ broker\n"
21
+ "\t2) New local Solace PubSub+ broker container (podman/docker)\n"
22
+ "\t3) Run in 'dev mode' - all in one process (not recommended for production)\n"
23
+ "Enter the number of your choice"
24
+ ),
25
+ "1",
26
+ none_interactive,
27
+ ["1", "2", "3"],
28
+ )
29
+ if broker_type == "2" or broker_type == "container":
30
+ options["dev_mode"] = "false"
31
+ # Check if the user have podman or docker installed
32
+ has_podman = shutil.which("podman")
33
+ has_docker = shutil.which("docker")
34
+ if not has_podman and not has_docker:
35
+ abort(
36
+ "You need to have either podman or docker installed to use the container broker."
37
+ )
38
+
39
+ container_engine = "podman" if has_podman else "docker"
40
+ if has_podman and has_docker:
41
+ container_engine = ask_if_not_provided(
42
+ options,
43
+ "container_engine",
44
+ "Which container engine do you want to use?",
45
+ "podman",
46
+ none_interactive,
47
+ ["podman", "docker"],
48
+ )
49
+
50
+ # Run command for the container start
51
+ command = container_engine + CONTAINER_RUN_COMMAND
52
+ click.echo(
53
+ f"Running the Solace PubSub+ broker container using {container_engine}"
54
+ )
55
+ response_status = os.system(command)
56
+ if response_status != 0:
57
+ abort("Failed to start the Solace PubSub+ broker container.")
58
+
59
+ options["broker_url"] = default_options["broker_url"]
60
+ options["broker_vpn"] = default_options["broker_vpn"]
61
+ options["broker_username"] = default_options["broker_username"]
62
+ options["broker_password"] = default_options["broker_password"]
63
+
64
+ elif broker_type == "1" or broker_type == "solace":
65
+ options["dev_mode"] = "false"
66
+ ask_if_not_provided(
67
+ options,
68
+ "broker_url",
69
+ "Enter the Solace broker url endpoint",
70
+ default_options["broker_url"],
71
+ none_interactive,
72
+ )
73
+ ask_if_not_provided(
74
+ options,
75
+ "broker_vpn",
76
+ "Enter the Solace broker vpn name",
77
+ default_options["broker_vpn"],
78
+ none_interactive,
79
+ )
80
+ ask_if_not_provided(
81
+ options,
82
+ "broker_username",
83
+ "Enter the Solace broker username",
84
+ default_options["broker_username"],
85
+ none_interactive,
86
+ )
87
+ ask_if_not_provided(
88
+ options,
89
+ "broker_password",
90
+ "Enter the Solace broker password",
91
+ default_options["broker_password"],
92
+ none_interactive,
93
+ hide_input=True,
94
+ )
95
+
96
+ elif (
97
+ broker_type == "3" or
98
+ broker_type == "dev_broker" or
99
+ broker_type == "dev_mode" or
100
+ broker_type == "dev"
101
+ ):
102
+ options["dev_mode"] = "true"
@@ -0,0 +1,88 @@
1
+ from cli.utils import ask_if_not_provided
2
+
3
+
4
+ def builtin_agent_step(options, default_options, none_interactive, abort):
5
+ """
6
+ Initialize the built-in agent.
7
+ """
8
+ agents = {
9
+ "web_request": (True, "can make queries to web to get real-time data", []),
10
+ "image_processing": (
11
+ True,
12
+ "generate images from text or convert images to text (The model name should be formatted like provider/model-name)",
13
+ ["IMAGE_GEN_MODEL=", "IMAGE_GEN_ENDPOINT=", "IMAGE_GEN_API_KEY="],
14
+ ),
15
+ "slack": (
16
+ False,
17
+ "Slack agent, send messages to Slack channels",
18
+ ["MONITOR_SLACK_BOT_TOKEN="],
19
+ ),
20
+ }
21
+
22
+ env_vars = {}
23
+ if "env_var" in options and options["env_var"]:
24
+ env_var_list = list(options["env_var"])
25
+ for env_var in env_var_list:
26
+ if "=" in env_var:
27
+ key, value = env_var.split("=")
28
+ env_vars[key] = value
29
+
30
+ if (
31
+ "built_in_agent" in options
32
+ and (
33
+ isinstance(options["built_in_agent"], tuple)
34
+ or isinstance(options["built_in_agent"], list)
35
+ )
36
+ and len(options["built_in_agent"]) > 0
37
+ ):
38
+ options["built_in_agent"] = list(options["built_in_agent"])
39
+ # Update env vars with default values
40
+ for name, agent in agents.items():
41
+ if name in options["built_in_agent"]:
42
+ for pair in agent[2]:
43
+ key, value = pair.split("=")
44
+ if key not in env_vars:
45
+ env_vars[key] = value
46
+ options["env_var"] = [f"{key}={value}" for key, value in env_vars.items()]
47
+ return
48
+
49
+ if none_interactive:
50
+ selected_agents_list = [
51
+ agent for agent, (enabled, _, _), in agents.items() if enabled
52
+ ]
53
+ options["built_in_agent"] = selected_agents_list
54
+ # Update env vars with default values
55
+ for name, agent in agents.items():
56
+ if name in options["built_in_agent"]:
57
+ for pair in agent[2]:
58
+ key, value = pair.split("=")
59
+ if key not in env_vars:
60
+ env_vars[key] = value
61
+ options["env_var"] = [f"{key}={value}" for key, value in env_vars.items()]
62
+ return
63
+
64
+ selected_agents = {}
65
+ for agent, (default, description, pairs) in agents.items():
66
+ enabled = ask_if_not_provided(
67
+ selected_agents,
68
+ agent,
69
+ f"Enable {agent} agent: {description}",
70
+ default,
71
+ none_interactive,
72
+ )
73
+ if enabled:
74
+ for pair in pairs:
75
+ key, value = pair.split("=")
76
+ ask_if_not_provided(
77
+ env_vars,
78
+ key,
79
+ f'\tAgent "{agent}" requires env value "{key}":',
80
+ value,
81
+ none_interactive,
82
+ hide_input="KEY" in key.upper(),
83
+ )
84
+ selected_agents_list = [
85
+ agent for agent, enabled in selected_agents.items() if enabled
86
+ ]
87
+ options["built_in_agent"] = selected_agents_list
88
+ options["env_var"] = [f"{key}={value}" for key, value in env_vars.items()]
@@ -0,0 +1,13 @@
1
+ import os
2
+
3
+ from cli.config import Config
4
+
5
+
6
+ def check_if_already_done(options, default_options, none_interactive, abort):
7
+ """
8
+ Checks if the init command has already been done"""
9
+ config_path = Config.user_config_file
10
+ if os.path.exists(config_path):
11
+ abort(
12
+ "The project has already been initialized. If you want to reinitialize the project, please delete the solace-agent-mesh.yaml file."
13
+ )