solace-agent-mesh 0.2.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of solace-agent-mesh might be problematic. Click here for more details.
- solace_agent_mesh/agents/global/actions/plotly_graph.py +48 -22
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add/copy_from_plugin.py +8 -6
- solace_agent_mesh/cli/commands/build.py +15 -0
- solace_agent_mesh/cli/commands/init/ai_provider_step.py +45 -28
- solace_agent_mesh/cli/commands/init/broker_step.py +1 -4
- solace_agent_mesh/cli/commands/init/create_config_file_step.py +8 -0
- solace_agent_mesh/cli/commands/init/init.py +50 -37
- solace_agent_mesh/cli/commands/plugin/build.py +52 -10
- solace_agent_mesh/cli/commands/run.py +2 -2
- solace_agent_mesh/cli/main.py +14 -8
- solace_agent_mesh/common/prompt_templates.py +1 -3
- solace_agent_mesh/common/utils.py +88 -19
- solace_agent_mesh/config_portal/__init__.py +0 -0
- solace_agent_mesh/config_portal/backend/__init__.py +0 -0
- solace_agent_mesh/config_portal/backend/common.py +35 -0
- solace_agent_mesh/config_portal/backend/server.py +233 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-DRPGOzHj.js +42 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/components-ZIfdTbrV.js +191 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/entry.client-DX1misIU.js +19 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/index-BJHAE5s4.js +17 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-8147e469.js +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-DgMDqKDc.js +10 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-hhS5izs8.css +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/favicon.ico +0 -0
- solace_agent_mesh/config_portal/frontend/static/client/index.html +7 -0
- solace_agent_mesh/configs/orchestrator.yaml +1 -1
- solace_agent_mesh/orchestrator/components/orchestrator_action_manager_timeout_component.py +4 -0
- solace_agent_mesh/orchestrator/components/orchestrator_stimulus_processor_component.py +28 -15
- solace_agent_mesh/orchestrator/components/orchestrator_streaming_output_component.py +19 -5
- solace_agent_mesh/orchestrator/orchestrator_main.py +11 -5
- solace_agent_mesh/orchestrator/orchestrator_prompt.py +78 -74
- solace_agent_mesh/templates/solace-agent-mesh-default.yaml +9 -0
- solace_agent_mesh-0.2.1.dist-info/METADATA +172 -0
- {solace_agent_mesh-0.2.0.dist-info → solace_agent_mesh-0.2.1.dist-info}/RECORD +38 -26
- solace_agent_mesh/common/prompt_templates_unused_delete.py +0 -161
- solace_agent_mesh-0.2.0.dist-info/METADATA +0 -209
- {solace_agent_mesh-0.2.0.dist-info → solace_agent_mesh-0.2.1.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-0.2.0.dist-info → solace_agent_mesh-0.2.1.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-0.2.0.dist-info → solace_agent_mesh-0.2.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -47,7 +47,7 @@ class PlotlyGraph(Action):
|
|
|
47
47
|
],
|
|
48
48
|
"reasoning": [
|
|
49
49
|
"- user has requested a random bar graph",
|
|
50
|
-
"- invoke the plotly action from the global agent to generate a bar graph with random data"
|
|
50
|
+
"- invoke the plotly action from the global agent to generate a bar graph with random data",
|
|
51
51
|
],
|
|
52
52
|
"response_text": "Certainly! I'd be happy to generate a random bar graph for you.",
|
|
53
53
|
"status_update": "I'll use our plotting tool to create this for you right away.",
|
|
@@ -57,23 +57,23 @@ class PlotlyGraph(Action):
|
|
|
57
57
|
"parameter_name": "plotly_figure_config",
|
|
58
58
|
"parameters": {
|
|
59
59
|
"plotly_figure_config": [
|
|
60
|
-
"{
|
|
61
|
-
|
|
62
|
-
" {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
" }
|
|
60
|
+
"{",
|
|
61
|
+
' "data": [',
|
|
62
|
+
" {",
|
|
63
|
+
' "x": ["A", "B", "C", "D", "E"],',
|
|
64
|
+
' "y": [23, 45, 56, 78, 90],',
|
|
65
|
+
' "type": "bar"',
|
|
66
|
+
" }",
|
|
67
67
|
" ],",
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
" }
|
|
73
|
-
"}
|
|
68
|
+
' "layout": {',
|
|
69
|
+
' "title": "Random Bar Graph",',
|
|
70
|
+
' "xaxis": {"title": "Categories"},',
|
|
71
|
+
' "yaxis": {"title": "Values"}',
|
|
72
|
+
" }",
|
|
73
|
+
"}",
|
|
74
74
|
]
|
|
75
|
-
}
|
|
76
|
-
}
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
77
|
}
|
|
78
78
|
],
|
|
79
79
|
},
|
|
@@ -82,15 +82,38 @@ class PlotlyGraph(Action):
|
|
|
82
82
|
|
|
83
83
|
def invoke(self, params, meta={}) -> ActionResponse:
|
|
84
84
|
if platform.system() == "Windows":
|
|
85
|
-
kaleido_version = version(
|
|
86
|
-
min_version = parse(
|
|
87
|
-
max_version = parse(
|
|
88
|
-
if
|
|
85
|
+
kaleido_version = version("kaleido")
|
|
86
|
+
min_version = parse("0.1.0.post1")
|
|
87
|
+
max_version = parse("0.2.0")
|
|
88
|
+
if (
|
|
89
|
+
parse(kaleido_version) < min_version
|
|
90
|
+
or parse(kaleido_version) >= max_version
|
|
91
|
+
):
|
|
89
92
|
return ActionResponse(
|
|
90
93
|
message="For Windows users, the plotting functionality requires a specific version of Kaleido. Please refer to the documentation."
|
|
91
94
|
)
|
|
92
95
|
obj = params["plotly_figure_config"]
|
|
93
96
|
if isinstance(obj, str):
|
|
97
|
+
# First remove any leading/trailing whitespace
|
|
98
|
+
obj = obj.strip()
|
|
99
|
+
|
|
100
|
+
# Next remove ```yaml or ```json
|
|
101
|
+
if obj.startswith("```yaml") or obj.startswith("```json"):
|
|
102
|
+
obj = obj[7:]
|
|
103
|
+
elif obj.startswith("```"):
|
|
104
|
+
obj = obj[3:]
|
|
105
|
+
# Remove any trailing ``` characters
|
|
106
|
+
if obj.endswith("```"):
|
|
107
|
+
obj = obj[:-3]
|
|
108
|
+
# Remove any leading/trailing whitespace again
|
|
109
|
+
obj = obj.strip()
|
|
110
|
+
|
|
111
|
+
# If the string starts with a quote and ends with that same quote, remove them
|
|
112
|
+
if obj.startswith("'") and obj.endswith("'"):
|
|
113
|
+
obj = obj[1:-1]
|
|
114
|
+
elif obj.startswith('"') and obj.endswith('"'):
|
|
115
|
+
obj = obj[1:-1]
|
|
116
|
+
|
|
94
117
|
# Remove any leading/trailing quote characters
|
|
95
118
|
obj = obj.strip("'\" ")
|
|
96
119
|
try:
|
|
@@ -110,7 +133,9 @@ class PlotlyGraph(Action):
|
|
|
110
133
|
pio.write_image(fig, byte_io)
|
|
111
134
|
byte_io.seek(0)
|
|
112
135
|
file_service = FileService()
|
|
113
|
-
image_name =
|
|
136
|
+
image_name = (
|
|
137
|
+
"generated_graph_" + str(random.randint(100000, 999999)) + ".png"
|
|
138
|
+
)
|
|
114
139
|
image_meta = file_service.upload_from_buffer(
|
|
115
140
|
byte_io.read(),
|
|
116
141
|
image_name,
|
|
@@ -120,7 +145,8 @@ class PlotlyGraph(Action):
|
|
|
120
145
|
files.append(image_meta)
|
|
121
146
|
except Exception as e:
|
|
122
147
|
return ActionResponse(
|
|
123
|
-
message="Could not create plotly graph. Please check the plotly figure configuration. plotly error: "
|
|
148
|
+
message="Could not create plotly graph. Please check the plotly figure configuration. plotly error: "
|
|
149
|
+
+ str(e),
|
|
124
150
|
)
|
|
125
151
|
|
|
126
152
|
return ActionResponse(files=files)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.2.
|
|
1
|
+
__version__ = "0.2.1"
|
|
@@ -16,7 +16,7 @@ def copy_from_plugin(name, plugin_name, entity_type):
|
|
|
16
16
|
if entity_type not in ["agents", "gateways"]:
|
|
17
17
|
log_error("Invalid entity type.")
|
|
18
18
|
return 1
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
src_entity_name = name
|
|
21
21
|
if ":" in plugin_name:
|
|
22
22
|
plugin_name, src_entity_name = plugin_name.split(":")
|
|
@@ -33,11 +33,13 @@ def copy_from_plugin(name, plugin_name, entity_type):
|
|
|
33
33
|
item_name = f"{item_name}.yaml" if entity_type == "agents" else item_name
|
|
34
34
|
|
|
35
35
|
src_entity_name = src_entity_name.replace("-", "_")
|
|
36
|
-
src_entity_name =
|
|
36
|
+
src_entity_name = (
|
|
37
|
+
f"{src_entity_name}.yaml" if entity_type == "agents" else src_entity_name
|
|
38
|
+
)
|
|
37
39
|
template_path = os.path.join(plugin_path, "configs", entity_type, src_entity_name)
|
|
38
40
|
|
|
39
41
|
if not os.path.exists(template_path):
|
|
40
|
-
log_error(f"Could not find '{
|
|
42
|
+
log_error(f"Could not find '{src_entity_name}' in '{plugin_name}' plugin.")
|
|
41
43
|
return 1
|
|
42
44
|
|
|
43
45
|
config = click.get_current_context().obj
|
|
@@ -80,11 +82,11 @@ def copy_from_plugin(name, plugin_name, entity_type):
|
|
|
80
82
|
else:
|
|
81
83
|
log_error("Invalid entity type.")
|
|
82
84
|
return 1
|
|
83
|
-
|
|
85
|
+
|
|
84
86
|
temp_file = os.path.join(config_directory, "__TEMPLATES_WILL_BE_HERE__")
|
|
85
87
|
if os.path.exists(temp_file):
|
|
86
88
|
os.remove(temp_file)
|
|
87
|
-
|
|
89
|
+
|
|
88
90
|
click.echo(
|
|
89
91
|
f"Copied {entity_type[:-1]} '{name}' from plugin '{plugin_name}' at: {get_display_path(target_directory)}"
|
|
90
|
-
)
|
|
92
|
+
)
|
|
@@ -378,7 +378,22 @@ def build_solace_agent_mesh(config, build_config_dir, abort, parsers):
|
|
|
378
378
|
if f.endswith(".yaml")
|
|
379
379
|
and not any(f.startswith(prefix) for prefix in skip_prefixes)
|
|
380
380
|
]
|
|
381
|
+
|
|
382
|
+
# Check if embedding service is enabled
|
|
383
|
+
embedding_enabled = True # Default to True for backward compatibility
|
|
384
|
+
built_in_services = config.get("built_in", {}).get("services", [])
|
|
385
|
+
if built_in_services: # Only check if services section exists
|
|
386
|
+
embedding_enabled = False
|
|
387
|
+
for service in built_in_services:
|
|
388
|
+
if service.get("name") == "embedding" and service.get("enabled"):
|
|
389
|
+
embedding_enabled = True
|
|
390
|
+
break
|
|
391
|
+
|
|
381
392
|
for config_file in config_files:
|
|
393
|
+
# Skip embedding service if not enabled
|
|
394
|
+
if config_file == "service_embedding.yaml" and not embedding_enabled:
|
|
395
|
+
click.echo(f"Skipping embedding service as it is disabled.")
|
|
396
|
+
continue
|
|
382
397
|
try:
|
|
383
398
|
# Read config file
|
|
384
399
|
config_file_path = os.path.join(configs_source_path, config_file)
|
|
@@ -39,38 +39,55 @@ def ai_provider_step(options, default_options, none_interactive, abort):
|
|
|
39
39
|
default_options["llm_model_name"],
|
|
40
40
|
none_interactive,
|
|
41
41
|
)
|
|
42
|
-
|
|
43
|
-
ask_if_not_provided(
|
|
42
|
+
# Ask if the user wants to enable the embedding service
|
|
43
|
+
embedding_enabled = ask_if_not_provided(
|
|
44
44
|
options,
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
default_options["
|
|
45
|
+
"embedding_service_enabled",
|
|
46
|
+
"Enable embedding service for vector embeddings?",
|
|
47
|
+
default_options["embedding_service_enabled"],
|
|
48
48
|
none_interactive,
|
|
49
49
|
)
|
|
50
50
|
|
|
51
|
-
|
|
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
|
-
)
|
|
51
|
+
options["embedding_service_enabled"] = embedding_enabled
|
|
59
52
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
53
|
+
# Only ask for embedding configuration if the service is enabled
|
|
54
|
+
if embedding_enabled:
|
|
55
|
+
ask_if_not_provided(
|
|
56
|
+
options,
|
|
57
|
+
"embedding_endpoint_url",
|
|
58
|
+
"Provide Embedding endpoint URL",
|
|
59
|
+
default_options["embedding_endpoint_url"],
|
|
60
|
+
none_interactive,
|
|
67
61
|
)
|
|
68
|
-
)
|
|
69
62
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
63
|
+
ask_if_not_provided(
|
|
64
|
+
options,
|
|
65
|
+
"embedding_api_key",
|
|
66
|
+
"Provide Embedding API Key",
|
|
67
|
+
default_options["embedding_api_key"],
|
|
68
|
+
none_interactive,
|
|
69
|
+
hide_input=True,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
click.echo(
|
|
73
|
+
click.style(
|
|
74
|
+
(
|
|
75
|
+
"The model name should follow the format `provider/model-name`."
|
|
76
|
+
"\n\t For example: openai/text-embedding-ada-002 or openai/my-model-that-follows-openai-api"
|
|
77
|
+
),
|
|
78
|
+
fg="yellow",
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
ask_if_not_provided(
|
|
83
|
+
options,
|
|
84
|
+
"embedding_model_name",
|
|
85
|
+
"Provide Embedding model name to use",
|
|
86
|
+
default_options["embedding_model_name"],
|
|
87
|
+
none_interactive,
|
|
88
|
+
)
|
|
89
|
+
else:
|
|
90
|
+
# Set empty values for embedding configuration if the service is disabled
|
|
91
|
+
options["embedding_endpoint_url"] = ""
|
|
92
|
+
options["embedding_api_key"] = ""
|
|
93
|
+
options["embedding_model_name"] = ""
|
|
@@ -3,10 +3,7 @@ import click
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
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
|
-
|
|
6
|
+
from solace_agent_mesh.config_portal.backend.common import CONTAINER_RUN_COMMAND
|
|
10
7
|
|
|
11
8
|
def broker_step(options, default_options, none_interactive, abort):
|
|
12
9
|
"""
|
|
@@ -21,6 +21,14 @@ def create_config_file_step(options, default_options, none_interactive, abort):
|
|
|
21
21
|
builtin_agents = options.get("built_in_agent", [])
|
|
22
22
|
for agent in builtin_agents_ref:
|
|
23
23
|
agent["enabled"] = agent["name"] in builtin_agents or agent["name"] == "global"
|
|
24
|
+
|
|
25
|
+
# Set up the built-in services
|
|
26
|
+
builtin_services_ref = (
|
|
27
|
+
sam_config.get("solace_agent_mesh", {}).get("built_in", {}).get("services", [])
|
|
28
|
+
)
|
|
29
|
+
for service in builtin_services_ref:
|
|
30
|
+
if service["name"] == "embedding":
|
|
31
|
+
service["enabled"] = options.get("embedding_service_enabled", False)
|
|
24
32
|
|
|
25
33
|
# Set up the project structure
|
|
26
34
|
sam_config.get("solace_agent_mesh", {})["config_directory"] = options.get("config_dir")
|
|
@@ -9,45 +9,16 @@ from .create_config_file_step import create_config_file_step
|
|
|
9
9
|
from .file_service_step import file_service_step
|
|
10
10
|
from .project_structure_step import project_structure_step
|
|
11
11
|
from .create_other_project_files_step import create_other_project_files_step
|
|
12
|
-
|
|
12
|
+
from solace_agent_mesh.config_portal.backend.server import run_flask
|
|
13
|
+
import click
|
|
14
|
+
import multiprocessing
|
|
15
|
+
import sys
|
|
16
|
+
import time
|
|
13
17
|
from cli.utils import (
|
|
14
18
|
log_error,
|
|
19
|
+
ask_yes_no_question,
|
|
15
20
|
)
|
|
16
|
-
|
|
17
|
-
default_options = {
|
|
18
|
-
"namespace": "",
|
|
19
|
-
"config_dir": "configs",
|
|
20
|
-
"module_dir": "modules",
|
|
21
|
-
"env_file": ".env",
|
|
22
|
-
"build_dir": "build",
|
|
23
|
-
"broker_type": "container",
|
|
24
|
-
"broker_url": "ws://localhost:8008",
|
|
25
|
-
"broker_vpn": "default",
|
|
26
|
-
"broker_username": "default",
|
|
27
|
-
"broker_password": "default",
|
|
28
|
-
"container_engine": "docker",
|
|
29
|
-
"llm_model_name": "openai/gpt-4o",
|
|
30
|
-
"llm_endpoint_url": "https://api.openai.com/v1",
|
|
31
|
-
"llm_api_key": "",
|
|
32
|
-
"embedding_model_name": "openai/text-embedding-ada-002",
|
|
33
|
-
"embedding_endpoint_url": "https://api.openai.com/v1",
|
|
34
|
-
"embedding_api_key": "",
|
|
35
|
-
"built_in_agent": [],
|
|
36
|
-
"file_service_provider": "volume",
|
|
37
|
-
"file_service_config": ["volume=/tmp/solace-agent-mesh"],
|
|
38
|
-
"env_var": [],
|
|
39
|
-
"rest_api_enabled": True,
|
|
40
|
-
"rest_api_server_input_port": "5050",
|
|
41
|
-
"rest_api_server_host": "127.0.0.1",
|
|
42
|
-
"rest_api_server_input_endpoint": "/api/v1/request",
|
|
43
|
-
"rest_api_gateway_name": "rest-api",
|
|
44
|
-
"webui_enabled": True,
|
|
45
|
-
"webui_listen_port": "5001",
|
|
46
|
-
"webui_host": "127.0.0.1"
|
|
47
|
-
}
|
|
48
|
-
"""
|
|
49
|
-
Default options for the init command.
|
|
50
|
-
"""
|
|
21
|
+
from solace_agent_mesh.config_portal.backend.common import default_options
|
|
51
22
|
|
|
52
23
|
|
|
53
24
|
def abort(message: str):
|
|
@@ -61,7 +32,6 @@ def init_command(options={}):
|
|
|
61
32
|
"""
|
|
62
33
|
Initialize the Solace Agent Mesh application.
|
|
63
34
|
"""
|
|
64
|
-
click.echo(click.style("Initializing Solace Agent Mesh", bold=True, fg="blue"))
|
|
65
35
|
skip = False
|
|
66
36
|
if "skip" in options and options["skip"]:
|
|
67
37
|
skip = True
|
|
@@ -77,6 +47,49 @@ def init_command(options={}):
|
|
|
77
47
|
("", create_config_file_step),
|
|
78
48
|
("Setting up project", create_other_project_files_step),
|
|
79
49
|
]
|
|
50
|
+
|
|
51
|
+
check_if_already_done(options, default_options, skip, abort)
|
|
52
|
+
|
|
53
|
+
click.echo(click.style("Initializing Solace Agent Mesh", bold=True, fg="blue"))
|
|
54
|
+
use_web_based_init = ask_yes_no_question("Would you like to configure your project through a web interface in your browser?", True)
|
|
55
|
+
|
|
56
|
+
if use_web_based_init and not skip:
|
|
57
|
+
|
|
58
|
+
with multiprocessing.Manager() as manager:
|
|
59
|
+
# Create a shared configuration dictionary
|
|
60
|
+
shared_config = manager.dict()
|
|
61
|
+
|
|
62
|
+
# Start the Flask server with the shared config
|
|
63
|
+
init_gui_process = multiprocessing.Process(
|
|
64
|
+
target=run_flask,
|
|
65
|
+
args=("127.0.0.1", 5002, shared_config)
|
|
66
|
+
)
|
|
67
|
+
init_gui_process.start()
|
|
68
|
+
|
|
69
|
+
click.echo(click.style("Web configuration portal is running at http://127.0.0.1:5002", fg="green"))
|
|
70
|
+
click.echo("Complete the configuration in your browser to continue...")
|
|
71
|
+
|
|
72
|
+
# Wait for the Flask server to finish
|
|
73
|
+
init_gui_process.join()
|
|
74
|
+
|
|
75
|
+
# Get the configuration from the shared dictionary
|
|
76
|
+
if shared_config:
|
|
77
|
+
# Convert from manager.dict to regular dict
|
|
78
|
+
config_from_portal = dict(shared_config)
|
|
79
|
+
options.update(config_from_portal)
|
|
80
|
+
click.echo(click.style("Configuration received from portal", fg="green"))
|
|
81
|
+
|
|
82
|
+
#if web configuration portal is used, skip the steps that are already done
|
|
83
|
+
steps_if_web_setup_used = [
|
|
84
|
+
("", create_config_file_step),
|
|
85
|
+
("", create_other_project_files_step),
|
|
86
|
+
]
|
|
87
|
+
steps = steps_if_web_setup_used
|
|
88
|
+
else:
|
|
89
|
+
click.echo(click.style("Web configuration failed, please try again.", fg="red"))
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
|
|
80
93
|
non_hidden_steps_count = len([step for step in steps if step[0]])
|
|
81
94
|
|
|
82
95
|
step = 0
|
|
@@ -2,7 +2,12 @@ import subprocess
|
|
|
2
2
|
import os
|
|
3
3
|
import click
|
|
4
4
|
|
|
5
|
-
from cli.utils import
|
|
5
|
+
from cli.utils import (
|
|
6
|
+
log_error,
|
|
7
|
+
apply_document_parsers,
|
|
8
|
+
load_plugin,
|
|
9
|
+
get_formatted_names,
|
|
10
|
+
)
|
|
6
11
|
from cli.config import Config
|
|
7
12
|
|
|
8
13
|
|
|
@@ -27,12 +32,21 @@ def get_all_plugin_gateway_interfaces(config, abort, return_plugin_config=False)
|
|
|
27
32
|
if not os.path.exists(interface_path):
|
|
28
33
|
continue
|
|
29
34
|
|
|
30
|
-
interface_gateway_configs = (
|
|
35
|
+
interface_gateway_configs = (
|
|
36
|
+
(
|
|
37
|
+
Config.load_config(
|
|
38
|
+
os.path.join(plugin_path, Config.user_plugin_config_file)
|
|
39
|
+
)
|
|
40
|
+
or {}
|
|
41
|
+
)
|
|
42
|
+
.get("solace_agent_mesh_plugin", {})
|
|
43
|
+
.get("interface_gateway_configs", {})
|
|
44
|
+
)
|
|
31
45
|
interface_gateway_config = None
|
|
32
46
|
# Ensuring flow and default pair exist
|
|
33
47
|
interface_pairs = {}
|
|
34
48
|
for file in os.listdir(interface_path):
|
|
35
|
-
if file.endswith("-flows.yaml")
|
|
49
|
+
if file.endswith("-flows.yaml"):
|
|
36
50
|
name = file.split("-flows.yaml")[0]
|
|
37
51
|
if name not in interface_pairs:
|
|
38
52
|
interface_pairs[name] = []
|
|
@@ -43,22 +57,35 @@ def get_all_plugin_gateway_interfaces(config, abort, return_plugin_config=False)
|
|
|
43
57
|
if name not in interface_pairs:
|
|
44
58
|
interface_pairs[name] = []
|
|
45
59
|
interface_pairs[name].append(file)
|
|
46
|
-
|
|
60
|
+
|
|
47
61
|
for name, files in interface_pairs.items():
|
|
48
62
|
if len(files) == 2:
|
|
49
63
|
if return_plugin_config:
|
|
50
|
-
for
|
|
64
|
+
for (
|
|
65
|
+
interface_name,
|
|
66
|
+
interface_config,
|
|
67
|
+
) in interface_gateway_configs.items():
|
|
51
68
|
if interface_name == name.replace("-", "_"):
|
|
52
69
|
interface_gateway_config = interface_config
|
|
53
70
|
break
|
|
54
|
-
gateway_interfaces[name] = (
|
|
71
|
+
gateway_interfaces[name] = (
|
|
72
|
+
interface_path,
|
|
73
|
+
interface_gateway_config,
|
|
74
|
+
)
|
|
55
75
|
else:
|
|
56
76
|
gateway_interfaces[name] = interface_path
|
|
57
|
-
|
|
77
|
+
|
|
58
78
|
return gateway_interfaces
|
|
59
79
|
|
|
60
80
|
|
|
61
|
-
def build_plugins(
|
|
81
|
+
def build_plugins(
|
|
82
|
+
config,
|
|
83
|
+
build_config_dir,
|
|
84
|
+
abort,
|
|
85
|
+
parsers,
|
|
86
|
+
plugin_gateway_interfaces,
|
|
87
|
+
build_specific_gateway,
|
|
88
|
+
):
|
|
62
89
|
plugins = config.get("plugins", [])
|
|
63
90
|
plugins_overwrite_dir = os.path.join(build_config_dir, "..", "overwrites")
|
|
64
91
|
|
|
@@ -70,7 +97,9 @@ def build_plugins(config, build_config_dir, abort, parsers, plugin_gateway_inter
|
|
|
70
97
|
name = plugin.get("name")
|
|
71
98
|
load_unspecified_files = plugin.get("load_unspecified_files", True)
|
|
72
99
|
load = plugin.get("load", {})
|
|
73
|
-
agents_to_load = [
|
|
100
|
+
agents_to_load = [
|
|
101
|
+
agent.replace("-", "_") for agent in (load.get("agents") or [])
|
|
102
|
+
]
|
|
74
103
|
gateways_to_load = load.get("gateways") or []
|
|
75
104
|
overwrites_to_load = load.get("overwrites") or []
|
|
76
105
|
|
|
@@ -130,6 +159,14 @@ def build_plugins(config, build_config_dir, abort, parsers, plugin_gateway_inter
|
|
|
130
159
|
agent_config_content = apply_document_parsers(
|
|
131
160
|
agent_config_content, parsers, meta
|
|
132
161
|
)
|
|
162
|
+
# Perform name substitutions
|
|
163
|
+
base_agent_name = agent_config[:-5] # Remove .yaml
|
|
164
|
+
name_cases = get_formatted_names(base_agent_name)
|
|
165
|
+
for case, val in name_cases.items():
|
|
166
|
+
agent_config_content = agent_config_content.replace(
|
|
167
|
+
f"{{{{{case}}}}}", val
|
|
168
|
+
)
|
|
169
|
+
|
|
133
170
|
# Write agent configuration to build directory
|
|
134
171
|
agent_build_path = os.path.join(
|
|
135
172
|
build_config_dir, "agent_" + agent_config
|
|
@@ -165,7 +202,12 @@ def build_plugins(config, build_config_dir, abort, parsers, plugin_gateway_inter
|
|
|
165
202
|
for gateway in gateway_subdirs:
|
|
166
203
|
if load_unspecified_files or gateway in gateway_dirs:
|
|
167
204
|
build_specific_gateway(
|
|
168
|
-
build_config_dir,
|
|
205
|
+
build_config_dir,
|
|
206
|
+
abort,
|
|
207
|
+
parsers,
|
|
208
|
+
gateway_config_path,
|
|
209
|
+
gateway,
|
|
210
|
+
plugin_gateway_interfaces,
|
|
169
211
|
)
|
|
170
212
|
|
|
171
213
|
####################
|
|
@@ -21,7 +21,7 @@ FILES_TO_EXCLUDE = []
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def run_command(
|
|
24
|
-
|
|
24
|
+
use_system_env, config_files, exclude_files, quick_build, ignore_build, force_build
|
|
25
25
|
):
|
|
26
26
|
"""Run the Solace Agent Mesh application."""
|
|
27
27
|
|
|
@@ -34,7 +34,7 @@ def run_command(
|
|
|
34
34
|
|
|
35
35
|
click.echo("Running Solace Agent Mesh application")
|
|
36
36
|
|
|
37
|
-
if
|
|
37
|
+
if not use_system_env:
|
|
38
38
|
try:
|
|
39
39
|
from dotenv import load_dotenv
|
|
40
40
|
|
solace_agent_mesh/cli/main.py
CHANGED
|
@@ -66,11 +66,11 @@ def build(y, no_init):
|
|
|
66
66
|
|
|
67
67
|
@cli.command()
|
|
68
68
|
@click.option(
|
|
69
|
-
"-
|
|
70
|
-
"--use-env",
|
|
69
|
+
"-u",
|
|
70
|
+
"--use-system-env",
|
|
71
71
|
default=False,
|
|
72
72
|
is_flag=True,
|
|
73
|
-
help="
|
|
73
|
+
help="Use only system environment variables (ignore environment variables defined in the config).",
|
|
74
74
|
)
|
|
75
75
|
@click.option(
|
|
76
76
|
"-s",
|
|
@@ -100,13 +100,13 @@ def build(y, no_init):
|
|
|
100
100
|
is_flag=True,
|
|
101
101
|
help="Runs the build command first regardless of the build directory. Mutually exclusive with --ignore-build.",
|
|
102
102
|
)
|
|
103
|
-
def run(
|
|
103
|
+
def run(use_system_env, files, skip, quick_build, ignore_build, force_build):
|
|
104
104
|
"""Run the Solace Agent Mesh application.
|
|
105
105
|
|
|
106
106
|
FILES: Config files to run. Uses all the yaml files in the build directory if not provided.
|
|
107
107
|
"""
|
|
108
108
|
return run_command(
|
|
109
|
-
|
|
109
|
+
use_system_env, list(files), list(skip), quick_build, ignore_build, force_build
|
|
110
110
|
)
|
|
111
111
|
|
|
112
112
|
|
|
@@ -211,15 +211,21 @@ def visualize(port, find_unused_port, host, use_env):
|
|
|
211
211
|
)
|
|
212
212
|
@click.option(
|
|
213
213
|
"--embedding-model-name",
|
|
214
|
-
help="Embedding model name to use",
|
|
214
|
+
help="Embedding model name to use (only used if embedding service is enabled)",
|
|
215
215
|
)
|
|
216
216
|
@click.option(
|
|
217
217
|
"--embedding-endpoint-url",
|
|
218
|
-
help="Embedding endpoint URL",
|
|
218
|
+
help="Embedding endpoint URL (only used if embedding service is enabled)",
|
|
219
219
|
)
|
|
220
220
|
@click.option(
|
|
221
221
|
"--embedding-api-key",
|
|
222
|
-
help="Embedding API Key",
|
|
222
|
+
help="Embedding API Key (only used if embedding service is enabled)",
|
|
223
|
+
)
|
|
224
|
+
@click.option(
|
|
225
|
+
"--embedding-service-enabled",
|
|
226
|
+
is_flag=True,
|
|
227
|
+
default=None,
|
|
228
|
+
help="Enable/disable Embedding Service for vector embeddings",
|
|
223
229
|
)
|
|
224
230
|
@click.option(
|
|
225
231
|
"--built-in-agent",
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
from typing import List
|
|
2
|
-
from langchain_core.messages import HumanMessage
|
|
3
|
-
|
|
4
2
|
import yaml
|
|
5
3
|
|
|
6
4
|
|
|
@@ -22,7 +20,7 @@ matching_locations:
|
|
|
22
20
|
"""
|
|
23
21
|
|
|
24
22
|
|
|
25
|
-
def FilterLocationsUserPrompt(location_filter: str) ->
|
|
23
|
+
def FilterLocationsUserPrompt(location_filter: str) -> str:
|
|
26
24
|
return f"""
|
|
27
25
|
<user-location-filter>
|
|
28
26
|
{location_filter}
|