unique_toolkit 0.8.29__py3-none-any.whl → 0.8.30__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.
- unique_toolkit/tools/a2a/__init__.py +4 -0
- unique_toolkit/tools/a2a/config.py +29 -0
- unique_toolkit/tools/a2a/manager.py +50 -0
- unique_toolkit/tools/a2a/memory.py +27 -0
- unique_toolkit/tools/a2a/schema.py +15 -0
- unique_toolkit/tools/a2a/service.py +154 -0
- unique_toolkit/tools/config.py +1 -0
- unique_toolkit/tools/mcp/models.py +0 -1
- unique_toolkit/tools/test/test_mcp_manager.py +55 -1
- unique_toolkit/tools/tool_manager.py +10 -1
- {unique_toolkit-0.8.29.dist-info → unique_toolkit-0.8.30.dist-info}/METADATA +8 -1
- {unique_toolkit-0.8.29.dist-info → unique_toolkit-0.8.30.dist-info}/RECORD +14 -8
- {unique_toolkit-0.8.29.dist-info → unique_toolkit-0.8.30.dist-info}/LICENSE +0 -0
- {unique_toolkit-0.8.29.dist-info → unique_toolkit-0.8.30.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from unique_toolkit.tools.schemas import BaseToolConfig
|
|
2
|
+
|
|
3
|
+
from unique_toolkit.tools.config import get_configuration_dict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
DEFAULT_PARAM_DESCRIPTION_SUB_AGENT_USER_MESSAGE = """
|
|
7
|
+
This is the message that will be sent to the sub-agent.
|
|
8
|
+
""".strip()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SubAgentToolConfig(BaseToolConfig):
|
|
12
|
+
model_config = get_configuration_dict()
|
|
13
|
+
|
|
14
|
+
name: str = "default_name"
|
|
15
|
+
assistant_id: str = ""
|
|
16
|
+
chat_id: str | None = None
|
|
17
|
+
reuse_chat: bool = True
|
|
18
|
+
tool_description_for_system_prompt: str = ""
|
|
19
|
+
tool_description: str = ""
|
|
20
|
+
param_description_sub_agent_user_message: str = (
|
|
21
|
+
DEFAULT_PARAM_DESCRIPTION_SUB_AGENT_USER_MESSAGE
|
|
22
|
+
)
|
|
23
|
+
tool_format_information_for_system_prompt: str = ""
|
|
24
|
+
|
|
25
|
+
tool_description_for_user_prompt: str = ""
|
|
26
|
+
tool_format_information_for_user_prompt: str = ""
|
|
27
|
+
|
|
28
|
+
poll_interval: float = 1.0
|
|
29
|
+
max_wait: float = 120.0
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from logging import Logger
|
|
2
|
+
|
|
3
|
+
from unique_toolkit.app.schemas import ChatEvent
|
|
4
|
+
from unique_toolkit.tools.a2a.service import SubAgentTool, ToolProgressReporter
|
|
5
|
+
|
|
6
|
+
from unique_toolkit.tools.a2a.config import SubAgentToolConfig
|
|
7
|
+
from unique_toolkit.tools.config import ToolBuildConfig
|
|
8
|
+
from unique_toolkit.tools.schemas import BaseToolConfig
|
|
9
|
+
from unique_toolkit.tools.tool import Tool
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class A2AManager:
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
logger: Logger,
|
|
16
|
+
tool_progress_reporter: ToolProgressReporter,
|
|
17
|
+
):
|
|
18
|
+
self._logger = logger
|
|
19
|
+
self._tool_progress_reporter = tool_progress_reporter
|
|
20
|
+
|
|
21
|
+
def get_all_sub_agents(
|
|
22
|
+
self, tool_configs: list[ToolBuildConfig], event: ChatEvent
|
|
23
|
+
) -> tuple[list[ToolBuildConfig], list[Tool[BaseToolConfig]]]:
|
|
24
|
+
sub_agents = []
|
|
25
|
+
|
|
26
|
+
for tool_config in tool_configs:
|
|
27
|
+
if not tool_config.is_sub_agent:
|
|
28
|
+
continue
|
|
29
|
+
|
|
30
|
+
if not isinstance(tool_config.configuration, SubAgentToolConfig):
|
|
31
|
+
self._logger.error(
|
|
32
|
+
"tool_config.configuration must be of type SubAgentToolConfig"
|
|
33
|
+
)
|
|
34
|
+
continue
|
|
35
|
+
|
|
36
|
+
sub_agent_tool_config: SubAgentToolConfig = tool_config.configuration
|
|
37
|
+
|
|
38
|
+
sub_agents.append(
|
|
39
|
+
SubAgentTool(
|
|
40
|
+
configuration=sub_agent_tool_config,
|
|
41
|
+
event=event,
|
|
42
|
+
tool_progress_reporter=self._tool_progress_reporter,
|
|
43
|
+
)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
filtered_tool_config = [
|
|
47
|
+
tool_config for tool_config in tool_configs if not tool_config.is_sub_agent
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
return filtered_tool_config, sub_agents
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from unique_toolkit import ShortTermMemoryService
|
|
2
|
+
|
|
3
|
+
from unique_toolkit.short_term_memory.persistent_short_term_memory_manager import (
|
|
4
|
+
PersistentShortMemoryManager,
|
|
5
|
+
)
|
|
6
|
+
from unique_toolkit.tools.a2a.schema import SubAgentShortTermMemorySchema
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _get_short_term_memory_name(assistant_id: str) -> str:
|
|
10
|
+
return f"sub_agent_chat_id_{assistant_id}"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_sub_agent_short_term_memory_manager(
|
|
14
|
+
company_id: str, user_id: str, chat_id: str, assistant_id: str
|
|
15
|
+
) -> PersistentShortMemoryManager[SubAgentShortTermMemorySchema]:
|
|
16
|
+
short_term_memory_service = ShortTermMemoryService(
|
|
17
|
+
company_id=company_id,
|
|
18
|
+
user_id=user_id,
|
|
19
|
+
chat_id=chat_id,
|
|
20
|
+
message_id=None,
|
|
21
|
+
)
|
|
22
|
+
short_term_memory_manager = PersistentShortMemoryManager(
|
|
23
|
+
short_term_memory_service=short_term_memory_service,
|
|
24
|
+
short_term_memory_schema=SubAgentShortTermMemorySchema,
|
|
25
|
+
short_term_memory_name=_get_short_term_memory_name(assistant_id),
|
|
26
|
+
)
|
|
27
|
+
return short_term_memory_manager
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
from unique_toolkit.tools.schemas import ToolCallResponse
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SubAgentToolInput(BaseModel):
|
|
7
|
+
user_message: str
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class SubAgentToolCallResponse(ToolCallResponse):
|
|
11
|
+
assistant_message: str
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SubAgentShortTermMemorySchema(BaseModel):
|
|
15
|
+
chat_id: str
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from pydantic import Field, create_model
|
|
2
|
+
from unique_sdk.utils.chat_in_space import send_message_and_wait_for_completion
|
|
3
|
+
from unique_toolkit.app import ChatEvent
|
|
4
|
+
from unique_toolkit.language_model import (
|
|
5
|
+
LanguageModelFunction,
|
|
6
|
+
LanguageModelMessage,
|
|
7
|
+
LanguageModelToolDescription,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from unique_toolkit.evaluators.schemas import EvaluationMetricName
|
|
11
|
+
from unique_toolkit.tools.schemas import ToolCallResponse
|
|
12
|
+
from unique_toolkit.tools.a2a.config import SubAgentToolConfig
|
|
13
|
+
from unique_toolkit.tools.a2a.memory import (
|
|
14
|
+
get_sub_agent_short_term_memory_manager,
|
|
15
|
+
)
|
|
16
|
+
from unique_toolkit.tools.a2a.schema import (
|
|
17
|
+
SubAgentShortTermMemorySchema,
|
|
18
|
+
SubAgentToolCallResponse,
|
|
19
|
+
SubAgentToolInput,
|
|
20
|
+
)
|
|
21
|
+
from unique_toolkit.tools.tool import Tool
|
|
22
|
+
|
|
23
|
+
from unique_toolkit.tools.tool_progress_reporter import (
|
|
24
|
+
ProgressState,
|
|
25
|
+
ToolProgressReporter,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SubAgentTool(Tool[SubAgentToolConfig]):
|
|
30
|
+
name: str = "SubAgentTool"
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
configuration: SubAgentToolConfig,
|
|
35
|
+
event: ChatEvent,
|
|
36
|
+
tool_progress_reporter: ToolProgressReporter | None = None,
|
|
37
|
+
):
|
|
38
|
+
super().__init__(configuration, event, tool_progress_reporter)
|
|
39
|
+
self._user_id = event.user_id
|
|
40
|
+
self._company_id = event.company_id
|
|
41
|
+
self.name = configuration.name
|
|
42
|
+
|
|
43
|
+
self._short_term_memory_manager = get_sub_agent_short_term_memory_manager(
|
|
44
|
+
company_id=self._company_id,
|
|
45
|
+
user_id=self._user_id,
|
|
46
|
+
chat_id=event.payload.chat_id,
|
|
47
|
+
assistant_id=self.config.assistant_id,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def tool_description(self) -> LanguageModelToolDescription:
|
|
51
|
+
tool_input_model_with_description = create_model(
|
|
52
|
+
"SubAgentToolInput",
|
|
53
|
+
user_message=(
|
|
54
|
+
str,
|
|
55
|
+
Field(description=self.config.param_description_sub_agent_user_message),
|
|
56
|
+
),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
return LanguageModelToolDescription(
|
|
60
|
+
name=self.name,
|
|
61
|
+
description=self.config.tool_description,
|
|
62
|
+
parameters=tool_input_model_with_description,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
def tool_description_for_system_prompt(self) -> str:
|
|
66
|
+
return self.config.tool_description_for_system_prompt
|
|
67
|
+
|
|
68
|
+
def tool_format_information_for_system_prompt(self) -> str:
|
|
69
|
+
return self.config.tool_format_information_for_system_prompt
|
|
70
|
+
|
|
71
|
+
def tool_description_for_user_prompt(self) -> str:
|
|
72
|
+
return self.config.tool_description_for_user_prompt
|
|
73
|
+
|
|
74
|
+
def tool_format_information_for_user_prompt(self) -> str:
|
|
75
|
+
return self.config.tool_format_information_for_user_prompt
|
|
76
|
+
|
|
77
|
+
def evaluation_check_list(self) -> list[EvaluationMetricName]:
|
|
78
|
+
return []
|
|
79
|
+
|
|
80
|
+
def get_evaluation_checks_based_on_tool_response(
|
|
81
|
+
self,
|
|
82
|
+
tool_response: ToolCallResponse,
|
|
83
|
+
) -> list[EvaluationMetricName]:
|
|
84
|
+
return []
|
|
85
|
+
|
|
86
|
+
async def _get_chat_id(self) -> str | None:
|
|
87
|
+
if not self.config.reuse_chat:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
if self.config.chat_id is not None:
|
|
91
|
+
return self.config.chat_id
|
|
92
|
+
|
|
93
|
+
# Check if there is a saved chat id in short term memory
|
|
94
|
+
short_term_memory = await self._short_term_memory_manager.load_async()
|
|
95
|
+
|
|
96
|
+
if short_term_memory is not None:
|
|
97
|
+
return short_term_memory.chat_id
|
|
98
|
+
|
|
99
|
+
return None
|
|
100
|
+
|
|
101
|
+
async def _save_chat_id(self, chat_id: str) -> None:
|
|
102
|
+
if not self.config.reuse_chat:
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
await self._short_term_memory_manager.save_async(
|
|
106
|
+
SubAgentShortTermMemorySchema(chat_id=chat_id)
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
async def run(self, tool_call: LanguageModelFunction) -> ToolCallResponse:
|
|
110
|
+
tool_input = SubAgentToolInput.model_validate(tool_call.arguments)
|
|
111
|
+
|
|
112
|
+
if self.tool_progress_reporter:
|
|
113
|
+
await self.tool_progress_reporter.notify_from_tool_call(
|
|
114
|
+
tool_call=tool_call,
|
|
115
|
+
name=f"{self.name}",
|
|
116
|
+
message=f"{tool_input.user_message}",
|
|
117
|
+
state=ProgressState.RUNNING,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Check if there is a saved chat id in short term memory
|
|
121
|
+
chat_id = await self._get_chat_id()
|
|
122
|
+
|
|
123
|
+
response = await send_message_and_wait_for_completion(
|
|
124
|
+
user_id=self._user_id,
|
|
125
|
+
assistant_id=self.config.assistant_id,
|
|
126
|
+
company_id=self._company_id,
|
|
127
|
+
text=tool_input.user_message, # type: ignore
|
|
128
|
+
chat_id=chat_id, # type: ignore
|
|
129
|
+
poll_interval=self.config.poll_interval,
|
|
130
|
+
max_wait=self.config.max_wait,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if chat_id is None:
|
|
134
|
+
await self._save_chat_id(response["chatId"])
|
|
135
|
+
|
|
136
|
+
if response["text"] is None:
|
|
137
|
+
raise ValueError("No response returned from sub agent")
|
|
138
|
+
|
|
139
|
+
self._text = response["text"]
|
|
140
|
+
return ToolCallResponse(
|
|
141
|
+
id=tool_call.id, # type: ignore
|
|
142
|
+
name=tool_call.name,
|
|
143
|
+
content=response["text"],
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
def get_tool_call_result_for_loop_history(
|
|
147
|
+
self,
|
|
148
|
+
tool_response: ToolCallResponse,
|
|
149
|
+
) -> LanguageModelMessage:
|
|
150
|
+
return ToolCallResponse(
|
|
151
|
+
id=tool_call.id, # type: ignore
|
|
152
|
+
name=tool_call.name,
|
|
153
|
+
content=response["text"],
|
|
154
|
+
)
|
unique_toolkit/tools/config.py
CHANGED
|
@@ -15,6 +15,8 @@ from unique_toolkit.tools.tool import Tool
|
|
|
15
15
|
from unique_toolkit.tools.tool_manager import ToolManager, ToolManagerConfig
|
|
16
16
|
from unique_toolkit.tools.tool_progress_reporter import ToolProgressReporter
|
|
17
17
|
|
|
18
|
+
from unique_toolkit.tools.a2a.manager import A2AManager
|
|
19
|
+
|
|
18
20
|
|
|
19
21
|
class MockParameters(BaseModel):
|
|
20
22
|
pass
|
|
@@ -161,6 +163,14 @@ class TestMCPManager:
|
|
|
161
163
|
event=self.event,
|
|
162
164
|
tool_progress_reporter=tool_progress_reporter,
|
|
163
165
|
)
|
|
166
|
+
|
|
167
|
+
@pytest.fixture
|
|
168
|
+
def a2a_manager(self,tool_progress_reporter):
|
|
169
|
+
"""Create MCP manager fixture"""
|
|
170
|
+
return A2AManager(
|
|
171
|
+
logger=self.logger,
|
|
172
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
173
|
+
)
|
|
164
174
|
|
|
165
175
|
@pytest.fixture
|
|
166
176
|
def tool_manager_config(self, internal_tools):
|
|
@@ -168,19 +178,23 @@ class TestMCPManager:
|
|
|
168
178
|
return ToolManagerConfig(tools=internal_tools, max_tool_calls=10)
|
|
169
179
|
|
|
170
180
|
@pytest.fixture
|
|
171
|
-
def tool_manager(self, tool_manager_config, mcp_manager, tool_progress_reporter):
|
|
181
|
+
def tool_manager(self, tool_manager_config, mcp_manager, a2a_manager,tool_progress_reporter):
|
|
172
182
|
"""Create tool manager fixture"""
|
|
183
|
+
|
|
184
|
+
|
|
173
185
|
return ToolManager(
|
|
174
186
|
logger=self.logger,
|
|
175
187
|
config=tool_manager_config,
|
|
176
188
|
event=self.event,
|
|
177
189
|
tool_progress_reporter=tool_progress_reporter,
|
|
178
190
|
mcp_manager=mcp_manager,
|
|
191
|
+
a2a_manager=a2a_manager
|
|
179
192
|
)
|
|
180
193
|
|
|
181
194
|
def test_tool_manager_initialization(self, tool_manager):
|
|
182
195
|
"""Test tool manager is initialized correctly"""
|
|
183
196
|
assert tool_manager is not None
|
|
197
|
+
|
|
184
198
|
assert (
|
|
185
199
|
len(tool_manager.get_tools()) >= 2
|
|
186
200
|
) # Should have both internal and MCP tools
|
|
@@ -255,12 +269,20 @@ class TestMCPManager:
|
|
|
255
269
|
"""Test the _init__tools method behavior with different scenarios"""
|
|
256
270
|
|
|
257
271
|
# Test 1: Normal initialization with both tool types
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
a2a_manager = A2AManager(
|
|
275
|
+
logger=self.logger,
|
|
276
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
277
|
+
)
|
|
278
|
+
|
|
258
279
|
tool_manager = ToolManager(
|
|
259
280
|
logger=self.logger,
|
|
260
281
|
config=tool_manager_config,
|
|
261
282
|
event=self.event,
|
|
262
283
|
tool_progress_reporter=tool_progress_reporter,
|
|
263
284
|
mcp_manager=mcp_manager,
|
|
285
|
+
a2a_manager=a2a_manager
|
|
264
286
|
)
|
|
265
287
|
|
|
266
288
|
# Verify both tools are loaded
|
|
@@ -285,12 +307,20 @@ class TestMCPManager:
|
|
|
285
307
|
event_with_disabled.payload.tool_choices = ["internal_search", "mcp_test_tool"]
|
|
286
308
|
event_with_disabled.payload.disabled_tools = ["internal_search"]
|
|
287
309
|
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
a2a_manager = A2AManager(
|
|
313
|
+
logger=self.logger,
|
|
314
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
315
|
+
)
|
|
316
|
+
|
|
288
317
|
tool_manager = ToolManager(
|
|
289
318
|
logger=self.logger,
|
|
290
319
|
config=tool_manager_config,
|
|
291
320
|
event=event_with_disabled,
|
|
292
321
|
tool_progress_reporter=tool_progress_reporter,
|
|
293
322
|
mcp_manager=mcp_manager,
|
|
323
|
+
a2a_manager=a2a_manager,
|
|
294
324
|
)
|
|
295
325
|
|
|
296
326
|
# Should only have MCP tool, internal tool should be filtered out
|
|
@@ -315,12 +345,20 @@ class TestMCPManager:
|
|
|
315
345
|
event_with_limited_choices.payload.tool_choices = ["internal_search"]
|
|
316
346
|
event_with_limited_choices.payload.disabled_tools = []
|
|
317
347
|
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
a2a_manager = A2AManager(
|
|
351
|
+
logger=self.logger,
|
|
352
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
353
|
+
)
|
|
354
|
+
|
|
318
355
|
tool_manager = ToolManager(
|
|
319
356
|
logger=self.logger,
|
|
320
357
|
config=tool_manager_config,
|
|
321
358
|
event=event_with_limited_choices,
|
|
322
359
|
tool_progress_reporter=tool_progress_reporter,
|
|
323
360
|
mcp_manager=mcp_manager,
|
|
361
|
+
a2a_manager=a2a_manager,
|
|
324
362
|
)
|
|
325
363
|
|
|
326
364
|
# Should only have internal search tool
|
|
@@ -348,12 +386,20 @@ class TestMCPManager:
|
|
|
348
386
|
tools=[exclusive_tool_config], max_tool_calls=10
|
|
349
387
|
)
|
|
350
388
|
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
a2a_manager = A2AManager(
|
|
392
|
+
logger=self.logger,
|
|
393
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
394
|
+
)
|
|
395
|
+
|
|
351
396
|
tool_manager = ToolManager(
|
|
352
397
|
logger=self.logger,
|
|
353
398
|
config=config_with_exclusive,
|
|
354
399
|
event=self.event,
|
|
355
400
|
tool_progress_reporter=tool_progress_reporter,
|
|
356
401
|
mcp_manager=mcp_manager,
|
|
402
|
+
a2a_manager=a2a_manager
|
|
357
403
|
)
|
|
358
404
|
|
|
359
405
|
# Should only have the exclusive tool, MCP tools should be ignored
|
|
@@ -383,12 +429,20 @@ class TestMCPManager:
|
|
|
383
429
|
tools=[disabled_tool_config], max_tool_calls=10
|
|
384
430
|
)
|
|
385
431
|
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
a2a_manager = A2AManager(
|
|
435
|
+
logger=self.logger,
|
|
436
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
437
|
+
)
|
|
438
|
+
|
|
386
439
|
tool_manager = ToolManager(
|
|
387
440
|
logger=self.logger,
|
|
388
441
|
config=config_with_disabled,
|
|
389
442
|
event=self.event,
|
|
390
443
|
tool_progress_reporter=tool_progress_reporter,
|
|
391
444
|
mcp_manager=mcp_manager,
|
|
445
|
+
a2a_manager=a2a_manager
|
|
392
446
|
)
|
|
393
447
|
|
|
394
448
|
# Should only have MCP tool, disabled internal tool should be filtered out
|
|
@@ -2,7 +2,10 @@ import asyncio
|
|
|
2
2
|
from logging import Logger, getLogger
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
|
+
|
|
5
6
|
from pydantic import BaseModel, Field
|
|
7
|
+
from unique_toolkit.tools.a2a.manager import A2AManager
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
from unique_toolkit.app.schemas import ChatEvent
|
|
8
11
|
from unique_toolkit.evals.schemas import EvaluationMetricName
|
|
@@ -71,6 +74,7 @@ class ToolManager:
|
|
|
71
74
|
event: ChatEvent,
|
|
72
75
|
tool_progress_reporter: ToolProgressReporter,
|
|
73
76
|
mcp_manager: MCPManager,
|
|
77
|
+
a2a_manager: A2AManager,
|
|
74
78
|
):
|
|
75
79
|
self._logger = logger
|
|
76
80
|
self._config = config
|
|
@@ -81,6 +85,7 @@ class ToolManager:
|
|
|
81
85
|
# this needs to be a set of strings to avoid duplicates
|
|
82
86
|
self._tool_evaluation_check_list: set[EvaluationMetricName] = set()
|
|
83
87
|
self._mcp_manager = mcp_manager
|
|
88
|
+
self._a2a_manager = a2a_manager
|
|
84
89
|
self._init__tools(event)
|
|
85
90
|
|
|
86
91
|
def _init__tools(self, event: ChatEvent) -> None:
|
|
@@ -90,6 +95,10 @@ class ToolManager:
|
|
|
90
95
|
self._logger.info(f"Tool choices: {tool_choices}")
|
|
91
96
|
self._logger.info(f"Tool configs: {tool_configs}")
|
|
92
97
|
|
|
98
|
+
tool_configs, sub_agents = self._a2a_manager.get_all_sub_agents(
|
|
99
|
+
tool_configs, event
|
|
100
|
+
)
|
|
101
|
+
|
|
93
102
|
# Build internal tools from configurations
|
|
94
103
|
internal_tools = [
|
|
95
104
|
ToolFactory.build_tool_with_settings(
|
|
@@ -105,7 +114,7 @@ class ToolManager:
|
|
|
105
114
|
# Get MCP tools (these are already properly instantiated)
|
|
106
115
|
mcp_tools = self._mcp_manager.get_all_mcp_tools()
|
|
107
116
|
# Combine both types of tools
|
|
108
|
-
self.available_tools = internal_tools + mcp_tools
|
|
117
|
+
self.available_tools = internal_tools + mcp_tools + sub_agents
|
|
109
118
|
|
|
110
119
|
for t in self.available_tools:
|
|
111
120
|
if t.is_exclusive():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: unique_toolkit
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.30
|
|
4
4
|
Summary:
|
|
5
5
|
License: Proprietary
|
|
6
6
|
Author: Martin Fadler
|
|
@@ -114,6 +114,10 @@ All notable changes to this project will be documented in this file.
|
|
|
114
114
|
|
|
115
115
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
116
116
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
117
|
+
|
|
118
|
+
## [0.8.30] - 2025-08-28
|
|
119
|
+
- Added A2A manager
|
|
120
|
+
|
|
117
121
|
## [0.8.29] - 2025-08-27
|
|
118
122
|
- Include `MessageExecution` and `MessageLog` in toolkit
|
|
119
123
|
|
|
@@ -126,6 +130,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
126
130
|
## [0.8.26] - 2025-08-27
|
|
127
131
|
- Optimized MCP manager
|
|
128
132
|
|
|
133
|
+
## [0.8.26] - 2025-08-27
|
|
134
|
+
- Optimized MCP manager
|
|
135
|
+
|
|
129
136
|
## [0.8.25] - 2025-08-27
|
|
130
137
|
- Load environment variables automatically from plattform dirs or environment
|
|
131
138
|
- General Endpoint definition utility
|
|
@@ -99,23 +99,29 @@ unique_toolkit/short_term_memory/service.py,sha256=5PeVBu1ZCAfyDb2HLVvlmqSbyzBBu
|
|
|
99
99
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
100
100
|
unique_toolkit/smart_rules/compile.py,sha256=cxWjb2dxEI2HGsakKdVCkSNi7VK9mr08w5sDcFCQyWI,9553
|
|
101
101
|
unique_toolkit/thinking_manager/thinking_manager.py,sha256=AJfmrTXTr-DxBnJ2_zYYpYo57kr5deqT0LiZb8UdaDQ,4175
|
|
102
|
-
unique_toolkit/tools/
|
|
102
|
+
unique_toolkit/tools/a2a/__init__.py,sha256=BIPxaqnfTD9IywxrqTLbGnkqNQrfLnKbdzF5ELYzCxM,171
|
|
103
|
+
unique_toolkit/tools/a2a/config.py,sha256=NjLBt8Bmxmh0XSU6W20_c-0jZoj4x8EX7Uodgyg1F7Y,866
|
|
104
|
+
unique_toolkit/tools/a2a/manager.py,sha256=nUEhjQmBh49rHWXAMDiRxR62vaPQdbSaBwaa_upUSEA,1667
|
|
105
|
+
unique_toolkit/tools/a2a/memory.py,sha256=cP4vaVAtL0IrlBT8QlYl72M6HCrds_Q7QRCIrwwP71A,1005
|
|
106
|
+
unique_toolkit/tools/a2a/schema.py,sha256=1R7qIu2l2qnUJDGRuUnZLqPPkHnT3x4d3d4PALoBzcY,296
|
|
107
|
+
unique_toolkit/tools/a2a/service.py,sha256=bQv6gooQyP_wvwEV_7Bhkvq4kHcLXtQfMQWov5UPT9A,5178
|
|
108
|
+
unique_toolkit/tools/config.py,sha256=nYwglwUSb3fxhqYxI83k-qoecuF5Zcol5FMOxHvTNeE,3827
|
|
103
109
|
unique_toolkit/tools/factory.py,sha256=w3uNHuYBIJ330Xi8PTdAkr8G3OMbQH2cBgvk5UT16oE,1253
|
|
104
110
|
unique_toolkit/tools/mcp/__init__.py,sha256=RLF_p-LDRC7GhiB3fdCi4u3bh6V9PY_w26fg61BLyco,122
|
|
105
111
|
unique_toolkit/tools/mcp/manager.py,sha256=lQcCsfCMqW2j6uCwNmgYoQDwjm8YosvCh4-apw3KZKs,2683
|
|
106
|
-
unique_toolkit/tools/mcp/models.py,sha256=
|
|
112
|
+
unique_toolkit/tools/mcp/models.py,sha256=6-qFq3ip2OhqRC5H6YzhsC27w5CYrWln75dWmeIovRk,713
|
|
107
113
|
unique_toolkit/tools/mcp/tool_wrapper.py,sha256=w7Fbo4FSMYvtgSq7Sqt1dmAPvqHjoBQS-TwnSp0p6j0,9927
|
|
108
114
|
unique_toolkit/tools/schemas.py,sha256=rArQccbfIv7CWcozClAZ-BVlOwAsjpgL8KUab_WeO3k,4817
|
|
109
|
-
unique_toolkit/tools/test/test_mcp_manager.py,sha256=
|
|
115
|
+
unique_toolkit/tools/test/test_mcp_manager.py,sha256=kzEq4cdhV4vI8FvqKBCvMVXSyJRMrUdedg14Ps5g8ko,15678
|
|
110
116
|
unique_toolkit/tools/test/test_tool_progress_reporter.py,sha256=GTtmBqOUo0-4fh_q0lRgxDhwKeankc3FHFD5ULZAm4Y,6299
|
|
111
117
|
unique_toolkit/tools/tool.py,sha256=E0qORpQBrdksAylf_RuPaEbXKi_AlswVGv-67t3DNZI,5879
|
|
112
|
-
unique_toolkit/tools/tool_manager.py,sha256=
|
|
118
|
+
unique_toolkit/tools/tool_manager.py,sha256=9gncHvsv_8bHAeufV99u6V_lskoT5QG8vT_RP5AA_-0,10208
|
|
113
119
|
unique_toolkit/tools/tool_progress_reporter.py,sha256=ixud9VoHey1vlU1t86cW0-WTvyTwMxNSWBon8I11SUk,7955
|
|
114
120
|
unique_toolkit/tools/utils/execution/execution.py,sha256=vjG2Y6awsGNtlvyQAGCTthQ5thWHYnn-vzZXaYLb3QE,7922
|
|
115
121
|
unique_toolkit/tools/utils/source_handling/schema.py,sha256=vzAyf6ZWNexjMO0OrnB8y2glGkvAilmGGQXd6zcDaKw,870
|
|
116
122
|
unique_toolkit/tools/utils/source_handling/source_formatting.py,sha256=C7uayNbdkNVJdEARA5CENnHtNY1SU6etlaqbgHNyxaQ,9152
|
|
117
123
|
unique_toolkit/tools/utils/source_handling/tests/test_source_formatting.py,sha256=oM5ZxEgzROrnX1229KViCAFjRxl9wCTzWZoinYSHleM,6979
|
|
118
|
-
unique_toolkit-0.8.
|
|
119
|
-
unique_toolkit-0.8.
|
|
120
|
-
unique_toolkit-0.8.
|
|
121
|
-
unique_toolkit-0.8.
|
|
124
|
+
unique_toolkit-0.8.30.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
|
|
125
|
+
unique_toolkit-0.8.30.dist-info/METADATA,sha256=3HA-gaW3UOJjBHHeFK9DyuMzHzFi529HIABflY9Y5CI,29342
|
|
126
|
+
unique_toolkit-0.8.30.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
127
|
+
unique_toolkit-0.8.30.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|