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.
@@ -0,0 +1,4 @@
1
+ from unique_toolkit.tools.a2a.config import SubAgentToolConfig
2
+ from unique_toolkit.tools.a2a.service import SubAgentTool
3
+
4
+ __all__ = ["SubAgentToolConfig", "SubAgentTool"]
@@ -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
+ )
@@ -72,6 +72,7 @@ class ToolBuildConfig(BaseModel):
72
72
  default=False,
73
73
  description="This tool must be chosen by the user and no other tools are used for this iteration.",
74
74
  )
75
+ is_sub_agent: bool = False
75
76
 
76
77
  is_enabled: bool = Field(default=True)
77
78
 
@@ -1,5 +1,4 @@
1
1
  from typing import Any, Dict, Optional
2
-
3
2
  from unique_toolkit.tools.schemas import BaseToolConfig
4
3
 
5
4
 
@@ -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.29
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/config.py,sha256=E4lFQA4gCi3_j4hcdnd5YUHhbaWTyIGWrgD18QardQw,3796
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=f9OXcGadBx2tDlhYFu-7oEkl5p9ppoDKTqZbca_NblQ,714
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=jnVKxqJyeJBDb6LvI8bM9dd8XPxrbXV0VCOHMhCdlug,14398
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=_Qt5fUGvA82YHn5LvqNJurLYW41jH9endNwsiSeyXyM,9948
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.29.dist-info/LICENSE,sha256=GlN8wHNdh53xwOPg44URnwag6TEolCjoq3YD_KrWgss,193
119
- unique_toolkit-0.8.29.dist-info/METADATA,sha256=14-dyP0BCriYbAGs3mQBbGUG-SfuOmJDX6lq1Puf2Gg,29245
120
- unique_toolkit-0.8.29.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
121
- unique_toolkit-0.8.29.dist-info/RECORD,,
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,,