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,152 @@
|
|
|
1
|
+
"""This is the base class that provides LLM and Embedding service access"""
|
|
2
|
+
|
|
3
|
+
from abc import ABC , abstractmethod
|
|
4
|
+
from solace_ai_connector.components.component_base import ComponentBase
|
|
5
|
+
from solace_ai_connector.common.message import Message
|
|
6
|
+
from solace_ai_connector.common.utils import ensure_slash_on_end
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
agent_info = {
|
|
11
|
+
"class_name": "LLMServiceComponentBase",
|
|
12
|
+
"description": "This is the base class that provides LLM and Embedding service access",
|
|
13
|
+
"config_parameters": [
|
|
14
|
+
{
|
|
15
|
+
"name": "llm_service_topic",
|
|
16
|
+
"required": False,
|
|
17
|
+
"description": "The topic to use for the LLM service",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "embedding_service_topic",
|
|
21
|
+
"required": False,
|
|
22
|
+
"description": "The topic to use for the Embedding service",
|
|
23
|
+
},
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class LLMServiceComponentBase(ComponentBase, ABC):
|
|
29
|
+
|
|
30
|
+
def __init__(self, module_info={}, **kwargs):
|
|
31
|
+
super().__init__(module_info, **kwargs)
|
|
32
|
+
self.current_message = None
|
|
33
|
+
self.current_request_data = None
|
|
34
|
+
|
|
35
|
+
self.llm_service_topic = self.get_config("llm_service_topic")
|
|
36
|
+
if self.llm_service_topic:
|
|
37
|
+
self.llm_service_topic = ensure_slash_on_end(self.llm_service_topic)
|
|
38
|
+
# Check that the component's broker request/response is enabled
|
|
39
|
+
if not self.is_broker_request_response_enabled():
|
|
40
|
+
raise ValueError(
|
|
41
|
+
"LLM service topic is set, but the component does not "
|
|
42
|
+
f"have its broker request/response enabled, {self.__class__.__name__}"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
self.embedding_service_topic = self.get_config("embedding_service_topic")
|
|
46
|
+
if self.embedding_service_topic:
|
|
47
|
+
self.embedding_service_topic = ensure_slash_on_end(
|
|
48
|
+
self.embedding_service_topic
|
|
49
|
+
)
|
|
50
|
+
# Check that the component's broker request/response is enabled
|
|
51
|
+
if not self.is_broker_request_response_enabled():
|
|
52
|
+
raise ValueError(
|
|
53
|
+
"Embedding service topic is set, but the component does not "
|
|
54
|
+
f"have its broker request/response enabled, {self.__class__.__name__}"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def process_pre_invoke(self, message):
|
|
58
|
+
self.current_request_data = super().process_pre_invoke(message)
|
|
59
|
+
return self.current_request_data
|
|
60
|
+
|
|
61
|
+
def process_post_invoke(self, result, message):
|
|
62
|
+
super().process_post_invoke(result, message)
|
|
63
|
+
self.current_request_data = None
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def invoke(self, message, data):
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
def do_llm_service_request_stream(self, message):
|
|
70
|
+
for response_message, last_message in self.do_broker_request_response(
|
|
71
|
+
message,
|
|
72
|
+
stream=True,
|
|
73
|
+
streaming_complete_expression="input.payload:last_chunk",
|
|
74
|
+
):
|
|
75
|
+
yield response_message.get_payload(), last_message
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
def do_llm_service_request(self, messages, stream=False, resolve_files=False):
|
|
79
|
+
"""Send a message to the LLM service"""
|
|
80
|
+
if not self.llm_service_topic:
|
|
81
|
+
raise ValueError(f"LLM service topic not set on {self.__class__.__name__}")
|
|
82
|
+
|
|
83
|
+
user_properties = self.current_message.get_user_properties().copy()
|
|
84
|
+
|
|
85
|
+
# Add the topic suffix
|
|
86
|
+
stimulus_uuid = user_properties.get("stimulus_uuid", "x")
|
|
87
|
+
session_id = user_properties.get("session_id", "x")
|
|
88
|
+
originator_id = user_properties.get("originator_id", "x")
|
|
89
|
+
|
|
90
|
+
topic = f"{self.llm_service_topic}{stimulus_uuid}/{session_id}/{originator_id}"
|
|
91
|
+
user_properties["resolve_files"] = resolve_files
|
|
92
|
+
|
|
93
|
+
if self.current_request_data:
|
|
94
|
+
action_list_id = self.current_request_data.get("action_list_id")
|
|
95
|
+
action_idx = self.current_request_data.get("action_idx")
|
|
96
|
+
action_name = self.current_request_data.get("action_name")
|
|
97
|
+
|
|
98
|
+
source_info = {
|
|
99
|
+
"type": "agent",
|
|
100
|
+
"agent_name": self.info.get("agent_name"),
|
|
101
|
+
"action_list_id": action_list_id,
|
|
102
|
+
"action_idx": action_idx,
|
|
103
|
+
"action_name": action_name,
|
|
104
|
+
}
|
|
105
|
+
else:
|
|
106
|
+
source_info = {
|
|
107
|
+
"type": "agent",
|
|
108
|
+
"agent_name": self.info.get("agent_name"),
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
user_properties["llm_request_source_info"] = source_info
|
|
112
|
+
|
|
113
|
+
message = Message(
|
|
114
|
+
topic=topic,
|
|
115
|
+
payload={"messages": messages, "stream": stream},
|
|
116
|
+
user_properties=user_properties,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
if stream:
|
|
120
|
+
return self.do_llm_service_request_stream(message)
|
|
121
|
+
else:
|
|
122
|
+
return self.do_broker_request_response(message).get_payload()
|
|
123
|
+
|
|
124
|
+
def do_embedding_service_request(self, items, resolve_files=False):
|
|
125
|
+
"""Send a message to the Embedding service"""
|
|
126
|
+
if not self.embedding_service_topic:
|
|
127
|
+
raise ValueError(
|
|
128
|
+
f"Embedding service topic not set on {self.__class__.__name__}"
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
user_properties = self.current_message.get_user_properties().copy()
|
|
132
|
+
|
|
133
|
+
# Add the topic suffix
|
|
134
|
+
stimulus_uuid = user_properties.get("stimulus_uuid", "x")
|
|
135
|
+
session_id = user_properties.get("session_id", "x")
|
|
136
|
+
originator_id = user_properties.get("originator_id", "x")
|
|
137
|
+
|
|
138
|
+
topic = f"{self.embedding_service_topic}{stimulus_uuid}/{session_id}/{originator_id}"
|
|
139
|
+
user_properties["resolve_files"] = resolve_files
|
|
140
|
+
|
|
141
|
+
message = Message(
|
|
142
|
+
topic=topic,
|
|
143
|
+
payload={
|
|
144
|
+
"items": items,
|
|
145
|
+
},
|
|
146
|
+
user_properties=user_properties,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
self.do_broker_request_response(message).get_payload().get("embeddings", [])
|
|
151
|
+
)
|
|
152
|
+
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from ..common.singleton import SingletonMeta
|
|
2
|
+
|
|
3
|
+
class MiddlewareService(metaclass=SingletonMeta):
|
|
4
|
+
def __init__(self):
|
|
5
|
+
self._middleware = {}
|
|
6
|
+
self._register_defaults()
|
|
7
|
+
|
|
8
|
+
def _register_defaults(self):
|
|
9
|
+
# Default middleware that just returns actions unchanged
|
|
10
|
+
self.register("filter_action", lambda user_properties, actions: actions)
|
|
11
|
+
# Default middleware that allows all actions
|
|
12
|
+
self.register("base_agent_filter", lambda user_properties, action: True)
|
|
13
|
+
# Default middleware that allows all action requests
|
|
14
|
+
self.register("validate_action_request", lambda user_properties, action_details: True)
|
|
15
|
+
|
|
16
|
+
def register(self, name: str, middleware_fn):
|
|
17
|
+
self._middleware[name] = middleware_fn
|
|
18
|
+
|
|
19
|
+
def get(self, name: str):
|
|
20
|
+
return self._middleware.get(name, lambda *args, **kwargs: args[0] if len(args) == 1 else args)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Action description"""
|
|
2
|
+
|
|
3
|
+
from solace_ai_connector.common.log import log
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
from solace_agent_mesh.common.action import Action
|
|
7
|
+
from solace_agent_mesh.common.action_response import ActionResponse
|
|
8
|
+
|
|
9
|
+
# To import from a local file, like this file, use a relative path from the {{SNAKE_CASE_NAME}}
|
|
10
|
+
# For example, to load this class, use:
|
|
11
|
+
# from {{SNAKE_CASE_NAME}}.actions.sample_action import SampleAction
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SampleAction(Action):
|
|
15
|
+
def __init__(self, **kwargs):
|
|
16
|
+
super().__init__(
|
|
17
|
+
{
|
|
18
|
+
"name": "sample_action",
|
|
19
|
+
"prompt_directive": ("detailed description of the action. " "examples, chain of thought, etc." "details for parameters"),
|
|
20
|
+
"params": [
|
|
21
|
+
{
|
|
22
|
+
"name": "sampleParam",
|
|
23
|
+
"desc": "Description of the parameter",
|
|
24
|
+
"type": "type of parameter (string, int, etc.)",
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"required_scopes": ["{{SNAKE_CASE_NAME}}:sample_action:read"],
|
|
28
|
+
},
|
|
29
|
+
**kwargs,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
def invoke(self, params, meta={}) -> ActionResponse:
|
|
33
|
+
log.debug("Doing sample action: %s", params["sampleParam"])
|
|
34
|
+
return self.do_action(params["sampleParam"])
|
|
35
|
+
|
|
36
|
+
def do_action(self, sample) -> ActionResponse:
|
|
37
|
+
sample += " Action performed"
|
|
38
|
+
return ActionResponse(message=sample)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""The agent component for the {{SPACED_NAME}}"""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import copy
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
8
|
+
sys.path.append(os.path.dirname(SCRIPT_DIR))
|
|
9
|
+
|
|
10
|
+
from solace_agent_mesh.agents.base_agent_component import (
|
|
11
|
+
agent_info,
|
|
12
|
+
BaseAgentComponent,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
# Sample action import
|
|
16
|
+
from {{SNAKE_CASE_NAME}}.actions.sample_action import SampleAction
|
|
17
|
+
|
|
18
|
+
info = copy.deepcopy(agent_info)
|
|
19
|
+
info["agent_name"] = "{{SNAKE_CASE_NAME}}"
|
|
20
|
+
info["class_name"] = "{{CAMEL_CASE_NAME}}AgentComponent"
|
|
21
|
+
info["description"] = (
|
|
22
|
+
"This agent handles ... It should be used "
|
|
23
|
+
"when an user explicitly requests information ... "
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
class {{CAMEL_CASE_NAME}}AgentComponent(BaseAgentComponent):
|
|
27
|
+
info = info
|
|
28
|
+
# sample action
|
|
29
|
+
actions = [SampleAction]
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# This is the configuration file for the {{SPACED_NAME}} agent
|
|
2
|
+
#
|
|
3
|
+
# It fulfills a few functions:
|
|
4
|
+
# 1. A flow to do periodic registration of this agent with the orchestrator
|
|
5
|
+
# 2. A flow to process action requests and produce action responses
|
|
6
|
+
# This requires a custom component to process the action requests
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
log:
|
|
10
|
+
stdout_log_level: INFO
|
|
11
|
+
log_file_level: INFO
|
|
12
|
+
log_file: solace_ai_connector.log
|
|
13
|
+
|
|
14
|
+
shared_config:
|
|
15
|
+
- broker_config: &broker_connection
|
|
16
|
+
dev_mode: ${SOLACE_DEV_MODE, false}
|
|
17
|
+
broker_url: ${SOLACE_BROKER_URL}
|
|
18
|
+
broker_username: ${SOLACE_BROKER_USERNAME}
|
|
19
|
+
broker_password: ${SOLACE_BROKER_PASSWORD}
|
|
20
|
+
broker_vpn: ${SOLACE_BROKER_VPN}
|
|
21
|
+
temporary_queue: ${USE_TEMPORARY_QUEUES, false}
|
|
22
|
+
|
|
23
|
+
flows:
|
|
24
|
+
|
|
25
|
+
# Flow to handle action requests
|
|
26
|
+
- name: {{SNAKE_CASE_NAME}}_action_request_processor
|
|
27
|
+
components:
|
|
28
|
+
# Input from a Solace broker
|
|
29
|
+
- component_name: broker_input
|
|
30
|
+
component_module: broker_input
|
|
31
|
+
component_config:
|
|
32
|
+
<<: *broker_connection
|
|
33
|
+
payload_encoding: utf-8
|
|
34
|
+
payload_format: json
|
|
35
|
+
broker_queue_name: ${SOLACE_AGENT_MESH_NAMESPACE}agent_{{SNAKE_CASE_NAME}}_action_request
|
|
36
|
+
broker_subscriptions:
|
|
37
|
+
# Subscribe to all {{SNAKE_CASE_NAME}} actions - note that if we
|
|
38
|
+
# wanted to handle some {{SNAKE_CASE_NAME}} actions elsewhere, we would
|
|
39
|
+
# need to be more specific here
|
|
40
|
+
- topic: ${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1/actionRequest/*/*/{{SNAKE_CASE_NAME}}/>
|
|
41
|
+
qos: 1
|
|
42
|
+
|
|
43
|
+
# Custom component to process the action request
|
|
44
|
+
- component_name: action_request_processor
|
|
45
|
+
component_base_path: .
|
|
46
|
+
# path is completed at build time
|
|
47
|
+
component_module: {{MODULE_DIRECTORY}}.agents.{{SNAKE_CASE_NAME}}.{{SNAKE_CASE_NAME}}_agent_component
|
|
48
|
+
component_config:
|
|
49
|
+
llm_service_topic: ${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1/llm-service/request/general-good/
|
|
50
|
+
embedding_service_topic: ${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1/embedding-service/request/text/
|
|
51
|
+
# Pass required configuration to the component
|
|
52
|
+
broker_request_response:
|
|
53
|
+
enabled: true
|
|
54
|
+
broker_config: *broker_connection
|
|
55
|
+
request_expiry_ms: 120000
|
|
56
|
+
payload_encoding: utf-8
|
|
57
|
+
payload_format: json
|
|
58
|
+
response_topic_prefix: ${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1
|
|
59
|
+
response_queue_prefix: ${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1
|
|
60
|
+
component_input:
|
|
61
|
+
source_expression: input.payload
|
|
62
|
+
|
|
63
|
+
# Output to a Solace broker
|
|
64
|
+
- component_name: broker_output
|
|
65
|
+
component_module: broker_output
|
|
66
|
+
component_config:
|
|
67
|
+
<<: *broker_connection
|
|
68
|
+
payload_encoding: utf-8
|
|
69
|
+
payload_format: json
|
|
70
|
+
copy_user_properties: true
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
- history_policy: &default_history_policy
|
|
2
|
+
type: "memory" # "memory", "redis", or your custom module name
|
|
3
|
+
module_path: . # Path to module, Only needed if you are using a custom module
|
|
4
|
+
time_to_live: 3600 # 1 hour
|
|
5
|
+
expiration_check_interval: 300 # 5 minutes
|
|
6
|
+
history_policy: # History provider configs (Passed to the history type provider)
|
|
7
|
+
max_turns: 40
|
|
8
|
+
max_characters: 50000
|
|
9
|
+
enforce_alternate_message_roles: true
|
|
10
|
+
|
|
11
|
+
- identity_config: &default_identity_config
|
|
12
|
+
type: "passthru" # "passthru", "bamboohr", or your custom module name
|
|
13
|
+
module_path: . # Path to module, Only needed if you are using a custom module
|
|
14
|
+
configuration: {}
|
|
15
|
+
|
|
16
|
+
- gateway_config: &gateway_config
|
|
17
|
+
gateway_id: {{GATEWAY_ID}}
|
|
18
|
+
system_purpose: >
|
|
19
|
+
The system is an AI Chatbot, that is providing information reasoning and general assistance for writing
|
|
20
|
+
and coding to the users in this system.
|
|
21
|
+
interaction_type: "interactive"
|
|
22
|
+
|
|
23
|
+
identity:
|
|
24
|
+
<<: *default_identity_config
|
|
25
|
+
|
|
26
|
+
retain_history: true
|
|
27
|
+
history_config:
|
|
28
|
+
<<: *default_history_policy
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
|
|
2
|
+
# Gateway to Solace
|
|
3
|
+
- name: gateway_input_flow
|
|
4
|
+
components:
|
|
5
|
+
- component_name: input_gateway
|
|
6
|
+
component_module: {{MODULE_DIRECTORY}}.gateways.{{SNAKE_CASE_NAME}}.{{SNAKE_CASE_NAME}}_input
|
|
7
|
+
component_base_path: .
|
|
8
|
+
component_config:
|
|
9
|
+
<<: *gateway_interface_config
|
|
10
|
+
- component_name: gateway_input
|
|
11
|
+
component_base_path: .
|
|
12
|
+
component_module: src.gateway.components.gateway_input
|
|
13
|
+
component_config:
|
|
14
|
+
identity_key_field: identity
|
|
15
|
+
<<: *gateway_config
|
|
16
|
+
component_input:
|
|
17
|
+
source_expression: previous
|
|
18
|
+
input_transforms:
|
|
19
|
+
- type: copy
|
|
20
|
+
source_value: *response_format_prompt
|
|
21
|
+
dest_expression: input.user_properties:response_format_prompt
|
|
22
|
+
- component_name: broker_output
|
|
23
|
+
component_module: broker_output
|
|
24
|
+
component_config:
|
|
25
|
+
<<: *broker_connection
|
|
26
|
+
payload_encoding: utf-8
|
|
27
|
+
payload_format: json
|
|
28
|
+
copy_user_properties: true
|
|
29
|
+
input_transforms:
|
|
30
|
+
- type: copy
|
|
31
|
+
source_expression: previous
|
|
32
|
+
dest_expression: user_data.output:payload
|
|
33
|
+
- type: copy
|
|
34
|
+
source_expression: template:${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1/stimulus/gateway/gateway_input/{{GATEWAY_ID}}
|
|
35
|
+
dest_expression: user_data.output:topic
|
|
36
|
+
component_input:
|
|
37
|
+
source_expression: user_data.output
|
|
38
|
+
|
|
39
|
+
# Solace output Gateway
|
|
40
|
+
- name: gateway_output_flow
|
|
41
|
+
trace_level: DEBUG
|
|
42
|
+
components:
|
|
43
|
+
- component_name: broker_input
|
|
44
|
+
component_module: broker_input
|
|
45
|
+
component_config:
|
|
46
|
+
<<: *broker_connection
|
|
47
|
+
broker_queue_name: ${SOLACE_AGENT_MESH_NAMESPACE}_{{GATEWAY_ID}}
|
|
48
|
+
broker_subscriptions:
|
|
49
|
+
- topic: ${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1/response/orchestrator/{{GATEWAY_ID}}
|
|
50
|
+
qos: 1
|
|
51
|
+
- topic: ${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1/streamingResponse/orchestrator/{{GATEWAY_ID}}
|
|
52
|
+
qos: 1
|
|
53
|
+
- topic: ${SOLACE_AGENT_MESH_NAMESPACE}solace-agent-mesh/v1/responseComplete/orchestrator/{{GATEWAY_ID}}
|
|
54
|
+
qos: 1
|
|
55
|
+
payload_encoding: utf-8
|
|
56
|
+
payload_format: json
|
|
57
|
+
|
|
58
|
+
- component_name: output_gateway
|
|
59
|
+
component_base_path: .
|
|
60
|
+
component_module: src.gateway.components.gateway_output
|
|
61
|
+
component_config:
|
|
62
|
+
<<: *gateway_config
|
|
63
|
+
copy_user_properties: true
|
|
64
|
+
component_input:
|
|
65
|
+
source_expression: input.payload
|
|
66
|
+
|
|
67
|
+
- component_name: output_gateway
|
|
68
|
+
component_module: {{MODULE_DIRECTORY}}.gateways.{{SNAKE_CASE_NAME}}.{{SNAKE_CASE_NAME}}_output
|
|
69
|
+
component_base_path: .
|
|
70
|
+
component_config:
|
|
71
|
+
<<: *gateway_interface_config
|
|
72
|
+
input_transforms:
|
|
73
|
+
- type: copy
|
|
74
|
+
source_expression: input.user_properties
|
|
75
|
+
dest_expression: user_data.component_input:message_info
|
|
76
|
+
- type: copy
|
|
77
|
+
source_expression: input.payload
|
|
78
|
+
dest_expression: user_data.component_input:content
|
|
79
|
+
component_input:
|
|
80
|
+
source_expression: user_data.component_input
|
|
81
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
log:
|
|
3
|
+
stdout_log_level: INFO
|
|
4
|
+
log_file_level: INFO
|
|
5
|
+
log_file: solace_ai_connector.log
|
|
6
|
+
|
|
7
|
+
shared_config:
|
|
8
|
+
- broker_config: &broker_connection
|
|
9
|
+
broker_connection_share: ${SOLACE_BROKER_URL}
|
|
10
|
+
dev_mode: ${SOLACE_DEV_MODE, false}
|
|
11
|
+
broker_url: ${SOLACE_BROKER_URL}
|
|
12
|
+
broker_username: ${SOLACE_BROKER_USERNAME}
|
|
13
|
+
broker_password: ${SOLACE_BROKER_PASSWORD}
|
|
14
|
+
broker_vpn: ${SOLACE_BROKER_VPN}
|
|
15
|
+
temporary_queue: ${USE_TEMPORARY_QUEUES, false}
|
|
16
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Base class for all {{CAMEL_CASE_NAME}} gateways"""
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from solace_ai_connector.components.component_base import ComponentBase
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# You can use a singleton pattern or a class variable to
|
|
8
|
+
# share a state between the input and output gateways
|
|
9
|
+
|
|
10
|
+
class {{CAMEL_CASE_NAME}}Base(ComponentBase, ABC):
|
|
11
|
+
"""Base class for all {{CAMEL_CASE_NAME}} gateways"""
|
|
12
|
+
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def invoke(self, message, data):
|
|
15
|
+
pass
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import queue
|
|
4
|
+
import threading
|
|
5
|
+
|
|
6
|
+
from solace_ai_connector.common.log import log
|
|
7
|
+
from solace_ai_connector.common.message import Message
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
10
|
+
sys.path.append(os.path.dirname(SCRIPT_DIR))
|
|
11
|
+
|
|
12
|
+
from {{SNAKE_CASE_NAME}}.{{SNAKE_CASE_NAME}}_base import {{CAMEL_CASE_NAME}}Base
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
info = {
|
|
16
|
+
"class_name": "{{CAMEL_CASE_NAME}}Input",
|
|
17
|
+
"description": (
|
|
18
|
+
"Description of your gateway input."
|
|
19
|
+
),
|
|
20
|
+
"config_parameters": [],
|
|
21
|
+
"output_schema": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"properties": {
|
|
24
|
+
"event": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"properties": {
|
|
27
|
+
"text": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
},
|
|
30
|
+
"files": {
|
|
31
|
+
"type": "array",
|
|
32
|
+
"items": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"properties": {
|
|
35
|
+
"name": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
},
|
|
38
|
+
"content": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
},
|
|
41
|
+
"size": {
|
|
42
|
+
"type": "number",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
"required": ["event"],
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class {{CAMEL_CASE_NAME}}Input({{CAMEL_CASE_NAME}}Base):
|
|
56
|
+
def __init__(self, **kwargs):
|
|
57
|
+
super().__init__(info, **kwargs)
|
|
58
|
+
log.debug("{{CAMEL_CASE_NAME}}Input initialized")
|
|
59
|
+
|
|
60
|
+
self.message_queue = queue.Queue()
|
|
61
|
+
|
|
62
|
+
self.{{SNAKE_CASE_NAME}}_thread = threading.Thread(target=self.start_{{SNAKE_CASE_NAME}}, args=(self.message_queue))
|
|
63
|
+
self.{{SNAKE_CASE_NAME}}_thread.daemon = True
|
|
64
|
+
self.{{SNAKE_CASE_NAME}}_thread.start()
|
|
65
|
+
|
|
66
|
+
def stop_component(self):
|
|
67
|
+
log.debug("Stopping {{CAMEL_CASE_NAME}}Input component")
|
|
68
|
+
if self.{{SNAKE_CASE_NAME}}_thread:
|
|
69
|
+
self.{{SNAKE_CASE_NAME}}_thread.join()
|
|
70
|
+
|
|
71
|
+
def start_{{SNAKE_CASE_NAME}}(self, message_queue):
|
|
72
|
+
# This is a placeholder for the actual implementation
|
|
73
|
+
payload = {
|
|
74
|
+
"text": "Hello, World!",
|
|
75
|
+
"files": [
|
|
76
|
+
{
|
|
77
|
+
"name": "file.txt",
|
|
78
|
+
"content": "base64 encoded content",
|
|
79
|
+
"size": 10,
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
user_properties = {
|
|
84
|
+
"session_id": "session_id",
|
|
85
|
+
"identity": "test@email.com"
|
|
86
|
+
}
|
|
87
|
+
message = Message(payload=payload, user_properties=user_properties)
|
|
88
|
+
message.set_previous(payload)
|
|
89
|
+
message_queue.put(message)
|
|
90
|
+
|
|
91
|
+
def get_next_message(self):
|
|
92
|
+
"""Get the next message from the queue.
|
|
93
|
+
"""
|
|
94
|
+
return self.message_queue.get()
|
|
95
|
+
|
|
96
|
+
def invoke(self, message:Message, data:dict):
|
|
97
|
+
log.debug("{{CAMEL_CASE_NAME}}Output invoked, %s", data)
|
|
98
|
+
return data
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from solace_ai_connector.common.log import log
|
|
5
|
+
from solace_ai_connector.common.message import Message
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
8
|
+
sys.path.append(os.path.dirname(SCRIPT_DIR))
|
|
9
|
+
|
|
10
|
+
from {{SNAKE_CASE_NAME}}.{{SNAKE_CASE_NAME}}_base import {{CAMEL_CASE_NAME}}Base
|
|
11
|
+
|
|
12
|
+
info = {
|
|
13
|
+
"class_name": "{{CAMEL_CASE_NAME}}Output",
|
|
14
|
+
"description": (
|
|
15
|
+
"Description of your gateway output."
|
|
16
|
+
),
|
|
17
|
+
"config_parameters": [],
|
|
18
|
+
"input_schema": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"properties": {
|
|
21
|
+
"message_info": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"properties": {
|
|
24
|
+
"session_id": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
"required": ["session_id"],
|
|
29
|
+
},
|
|
30
|
+
"content": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"properties": {
|
|
33
|
+
"text": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
},
|
|
36
|
+
"files": {
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"properties": {
|
|
41
|
+
"name": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
},
|
|
44
|
+
"content": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
},
|
|
47
|
+
"mime_type": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
"required": ["message_info", "content"],
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class {{CAMEL_CASE_NAME}}Output({{CAMEL_CASE_NAME}}Base):
|
|
62
|
+
def __init__(self, **kwargs):
|
|
63
|
+
super().__init__(info, **kwargs)
|
|
64
|
+
log.debug("{{CAMEL_CASE_NAME}}Output initialized")
|
|
65
|
+
|
|
66
|
+
def stop_component(self):
|
|
67
|
+
log.debug("Stopping {{CAMEL_CASE_NAME}}Output Component")
|
|
68
|
+
|
|
69
|
+
def invoke(self, message:Message, data:dict):
|
|
70
|
+
log.debug("{{CAMEL_CASE_NAME}}Output invoked, %s", data)
|
|
71
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[tool.hatch.metadata]
|
|
6
|
+
allow-direct-references = true
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "{{name}}"
|
|
10
|
+
dynamic = ["version"]
|
|
11
|
+
authors = [
|
|
12
|
+
{ name="{{author}}", email="" },
|
|
13
|
+
]
|
|
14
|
+
description = "{{description}}"
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
requires-python = ">=3.10"
|
|
17
|
+
dependencies = []
|
|
18
|
+
|
|
19
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
20
|
+
"src" = "{{snake_name}}/src"
|
|
21
|
+
"interfaces" = "{{snake_name}}/interfaces"
|
|
22
|
+
"configs" = "{{snake_name}}/configs"
|
|
23
|
+
"solace-agent-mesh-plugin.yaml" = "{{snake_name}}/solace-agent-mesh-plugin.yaml"
|
|
24
|
+
|
|
25
|
+
[tool.hatch.build.targets.wheel]
|
|
26
|
+
packages = ["{{snake_name}}"]
|
|
27
|
+
|
|
28
|
+
[tool.hatch.version]
|
|
29
|
+
path = "src/__init__.py"
|
|
30
|
+
|