unique_toolkit 2026.28.0.dev16__py3-none-any.whl → 2026.28.0.dev18__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/agentic/tools/a2a/manager.py +33 -9
- unique_toolkit/agentic/tools/a2a/tool/service.py +14 -6
- unique_toolkit/agentic/tools/experimental/ask_user_tool/tool.py +19 -3
- unique_toolkit/agentic/tools/experimental/todo/service.py +18 -2
- unique_toolkit/agentic/tools/mcp/manager.py +29 -8
- unique_toolkit/agentic/tools/mcp/tool_wrapper.py +15 -7
- unique_toolkit/agentic/tools/tool.py +13 -0
- unique_toolkit/agentic/tools/tool_manager.py +53 -8
- unique_toolkit/app/unique_settings.py +45 -1
- {unique_toolkit-2026.28.0.dev16.dist-info → unique_toolkit-2026.28.0.dev18.dist-info}/METADATA +2 -2
- {unique_toolkit-2026.28.0.dev16.dist-info → unique_toolkit-2026.28.0.dev18.dist-info}/RECORD +12 -12
- {unique_toolkit-2026.28.0.dev16.dist-info → unique_toolkit-2026.28.0.dev18.dist-info}/WHEEL +0 -0
|
@@ -5,6 +5,8 @@ from unique_toolkit.agentic.tools.a2a.tool import SubAgentTool, SubAgentToolConf
|
|
|
5
5
|
from unique_toolkit.agentic.tools.config import ToolBuildConfig
|
|
6
6
|
from unique_toolkit.agentic.tools.tool_progress_reporter import ToolProgressReporter
|
|
7
7
|
from unique_toolkit.app.schemas import ChatEvent
|
|
8
|
+
from unique_toolkit.chat.service import ChatService
|
|
9
|
+
from unique_toolkit.language_model import LanguageModelService
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class A2AManager:
|
|
@@ -13,10 +15,15 @@ class A2AManager:
|
|
|
13
15
|
logger: Logger,
|
|
14
16
|
tool_progress_reporter: ToolProgressReporter,
|
|
15
17
|
response_watcher: SubAgentResponseWatcher,
|
|
18
|
+
*,
|
|
19
|
+
chat_service: ChatService | None = None,
|
|
20
|
+
language_model_service: LanguageModelService | None = None,
|
|
16
21
|
):
|
|
17
22
|
self._logger = logger
|
|
18
23
|
self._tool_progress_reporter = tool_progress_reporter
|
|
19
24
|
self._response_watcher = response_watcher
|
|
25
|
+
self._chat_service = chat_service
|
|
26
|
+
self._language_model_service = language_model_service
|
|
20
27
|
|
|
21
28
|
def get_all_sub_agents(
|
|
22
29
|
self,
|
|
@@ -45,16 +52,33 @@ class A2AManager:
|
|
|
45
52
|
sub_agent_tool_config = tool_config.configuration
|
|
46
53
|
|
|
47
54
|
try:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
if (
|
|
56
|
+
self._chat_service is not None
|
|
57
|
+
and self._language_model_service is not None
|
|
58
|
+
):
|
|
59
|
+
sub_agents.append(
|
|
60
|
+
SubAgentTool(
|
|
61
|
+
configuration=sub_agent_tool_config,
|
|
62
|
+
event=event,
|
|
63
|
+
tool_progress_reporter=self._tool_progress_reporter,
|
|
64
|
+
name=tool_config.name,
|
|
65
|
+
display_name=tool_config.display_name,
|
|
66
|
+
response_watcher=self._response_watcher,
|
|
67
|
+
chat_service=self._chat_service,
|
|
68
|
+
language_model_service=self._language_model_service,
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
else:
|
|
72
|
+
sub_agents.append(
|
|
73
|
+
SubAgentTool(
|
|
74
|
+
configuration=sub_agent_tool_config,
|
|
75
|
+
event=event,
|
|
76
|
+
tool_progress_reporter=self._tool_progress_reporter,
|
|
77
|
+
name=tool_config.name,
|
|
78
|
+
display_name=tool_config.display_name,
|
|
79
|
+
response_watcher=self._response_watcher,
|
|
80
|
+
)
|
|
56
81
|
)
|
|
57
|
-
)
|
|
58
82
|
except Exception:
|
|
59
83
|
self._logger.warning(
|
|
60
84
|
"Skipping sub-agent '%s' due to initialization failure.",
|
|
@@ -20,7 +20,6 @@ from unique_toolkit._common.referencing import (
|
|
|
20
20
|
from unique_toolkit._common.utils.jinja.render import render_template
|
|
21
21
|
from unique_toolkit.agentic.evaluation.schemas import EvaluationMetricName
|
|
22
22
|
from unique_toolkit.agentic.feature_flags import feature_flags
|
|
23
|
-
from unique_toolkit.agentic.message_log_manager.service import MessageStepLogger
|
|
24
23
|
from unique_toolkit.agentic.tools.a2a.response_watcher import SubAgentResponseWatcher
|
|
25
24
|
from unique_toolkit.agentic.tools.a2a.tool._memory import (
|
|
26
25
|
get_sub_agent_short_term_memory_manager,
|
|
@@ -53,6 +52,7 @@ from unique_toolkit.chat.service import ChatService
|
|
|
53
52
|
from unique_toolkit.content import ContentChunk, ContentReference
|
|
54
53
|
from unique_toolkit.language_model import (
|
|
55
54
|
LanguageModelFunction,
|
|
55
|
+
LanguageModelService,
|
|
56
56
|
LanguageModelToolDescription,
|
|
57
57
|
)
|
|
58
58
|
|
|
@@ -72,12 +72,20 @@ class SubAgentTool(Tool[SubAgentToolConfig]):
|
|
|
72
72
|
name: str = "SubAgentTool",
|
|
73
73
|
display_name: str = "SubAgentTool",
|
|
74
74
|
response_watcher: SubAgentResponseWatcher | None = None,
|
|
75
|
+
*,
|
|
76
|
+
chat_service: ChatService | None = None,
|
|
77
|
+
language_model_service: LanguageModelService | None = None,
|
|
75
78
|
) -> None:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
if chat_service is not None and language_model_service is not None:
|
|
80
|
+
super().__init__(
|
|
81
|
+
configuration,
|
|
82
|
+
event,
|
|
83
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
84
|
+
chat_service=chat_service,
|
|
85
|
+
language_model_service=language_model_service,
|
|
86
|
+
)
|
|
87
|
+
else:
|
|
88
|
+
super().__init__(configuration, event, tool_progress_reporter)
|
|
81
89
|
self._user_id = event.user_id
|
|
82
90
|
self._company_id = event.company_id
|
|
83
91
|
|
|
@@ -13,12 +13,14 @@ from unique_toolkit.agentic.tools.schemas import ToolCallResponse
|
|
|
13
13
|
from unique_toolkit.agentic.tools.tool import Tool
|
|
14
14
|
from unique_toolkit.agentic.tools.tool_progress_reporter import ToolProgressReporter
|
|
15
15
|
from unique_toolkit.app.schemas import ChatEvent
|
|
16
|
+
from unique_toolkit.chat.service import ChatService
|
|
16
17
|
from unique_toolkit.elicitation import (
|
|
17
18
|
ElicitationCancelledException,
|
|
18
19
|
ElicitationDeclinedException,
|
|
19
20
|
ElicitationExpiredException,
|
|
20
21
|
ElicitationMode,
|
|
21
22
|
)
|
|
23
|
+
from unique_toolkit.language_model import LanguageModelService
|
|
22
24
|
from unique_toolkit.language_model.schemas import (
|
|
23
25
|
LanguageModelFunction,
|
|
24
26
|
LanguageModelToolDescription,
|
|
@@ -44,10 +46,24 @@ class AskUserTool(Tool[AskUserToolConfig]):
|
|
|
44
46
|
config: AskUserToolConfig,
|
|
45
47
|
event: ChatEvent,
|
|
46
48
|
tool_progress_reporter: ToolProgressReporter | None = None,
|
|
49
|
+
*,
|
|
50
|
+
chat_service: ChatService | None = None,
|
|
51
|
+
language_model_service: LanguageModelService | None = None,
|
|
47
52
|
) -> None:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
if chat_service is not None and language_model_service is not None:
|
|
54
|
+
super().__init__(
|
|
55
|
+
config=config,
|
|
56
|
+
event=event,
|
|
57
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
58
|
+
chat_service=chat_service,
|
|
59
|
+
language_model_service=language_model_service,
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
super().__init__(
|
|
63
|
+
config=config,
|
|
64
|
+
event=event,
|
|
65
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
66
|
+
)
|
|
51
67
|
self._lock = asyncio.Lock()
|
|
52
68
|
|
|
53
69
|
@override
|
|
@@ -20,7 +20,11 @@ from unique_toolkit.agentic.tools.tool import Tool
|
|
|
20
20
|
from unique_toolkit.agentic.tools.tool_progress_reporter import ToolProgressReporter
|
|
21
21
|
from unique_toolkit.app.schemas import ChatEvent
|
|
22
22
|
from unique_toolkit.chat.schemas import MessageLog, MessageLogStatus
|
|
23
|
-
from unique_toolkit.
|
|
23
|
+
from unique_toolkit.chat.service import ChatService
|
|
24
|
+
from unique_toolkit.language_model import (
|
|
25
|
+
LanguageModelService,
|
|
26
|
+
LanguageModelToolDescription,
|
|
27
|
+
)
|
|
24
28
|
from unique_toolkit.language_model.schemas import LanguageModelFunction
|
|
25
29
|
from unique_toolkit.short_term_memory.service import ShortTermMemoryService
|
|
26
30
|
|
|
@@ -45,8 +49,20 @@ class TodoWriteTool(Tool[TodoConfig]):
|
|
|
45
49
|
config: TodoConfig,
|
|
46
50
|
event: ChatEvent,
|
|
47
51
|
tool_progress_reporter: ToolProgressReporter | None = None,
|
|
52
|
+
*,
|
|
53
|
+
chat_service: ChatService | None = None,
|
|
54
|
+
language_model_service: LanguageModelService | None = None,
|
|
48
55
|
) -> None:
|
|
49
|
-
|
|
56
|
+
if chat_service is not None and language_model_service is not None:
|
|
57
|
+
super().__init__(
|
|
58
|
+
config,
|
|
59
|
+
event,
|
|
60
|
+
tool_progress_reporter,
|
|
61
|
+
chat_service=chat_service,
|
|
62
|
+
language_model_service=language_model_service,
|
|
63
|
+
)
|
|
64
|
+
else:
|
|
65
|
+
super().__init__(config, event, tool_progress_reporter)
|
|
50
66
|
stm_service = ShortTermMemoryService(
|
|
51
67
|
company_id=event.company_id,
|
|
52
68
|
user_id=event.user_id,
|
|
@@ -11,6 +11,8 @@ from unique_toolkit.agentic.tools.schemas import BaseToolConfig
|
|
|
11
11
|
from unique_toolkit.agentic.tools.tool import Tool
|
|
12
12
|
from unique_toolkit.agentic.tools.tool_progress_reporter import ToolProgressReporter
|
|
13
13
|
from unique_toolkit.app.schemas import ChatEvent, McpServer
|
|
14
|
+
from unique_toolkit.chat.service import ChatService
|
|
15
|
+
from unique_toolkit.language_model import LanguageModelService
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
class MCPManager:
|
|
@@ -19,10 +21,15 @@ class MCPManager:
|
|
|
19
21
|
mcp_servers: list[McpServer],
|
|
20
22
|
event: ChatEvent,
|
|
21
23
|
tool_progress_reporter: ToolProgressReporter,
|
|
22
|
-
|
|
24
|
+
*,
|
|
25
|
+
chat_service: ChatService | None = None,
|
|
26
|
+
language_model_service: LanguageModelService | None = None,
|
|
27
|
+
) -> None:
|
|
23
28
|
self._mcp_servers = mcp_servers
|
|
24
29
|
self._event = event
|
|
25
30
|
self._tool_progress_reporter = tool_progress_reporter
|
|
31
|
+
self._chat_service = chat_service
|
|
32
|
+
self._language_model_service = language_model_service
|
|
26
33
|
|
|
27
34
|
def get_mcp_servers(self):
|
|
28
35
|
return self._mcp_servers
|
|
@@ -47,13 +54,27 @@ class MCPManager:
|
|
|
47
54
|
server_user_prompt=server.user_prompt,
|
|
48
55
|
mcp_source_id=server.id,
|
|
49
56
|
)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
+
if (
|
|
58
|
+
self._chat_service is not None
|
|
59
|
+
and self._language_model_service is not None
|
|
60
|
+
):
|
|
61
|
+
wrapper = MCPToolWrapper(
|
|
62
|
+
mcp_server=server,
|
|
63
|
+
mcp_tool=tool,
|
|
64
|
+
config=config,
|
|
65
|
+
event=self._event,
|
|
66
|
+
tool_progress_reporter=self._tool_progress_reporter,
|
|
67
|
+
chat_service=self._chat_service,
|
|
68
|
+
language_model_service=self._language_model_service,
|
|
69
|
+
)
|
|
70
|
+
else:
|
|
71
|
+
wrapper = MCPToolWrapper(
|
|
72
|
+
mcp_server=server,
|
|
73
|
+
mcp_tool=tool,
|
|
74
|
+
config=config,
|
|
75
|
+
event=self._event,
|
|
76
|
+
tool_progress_reporter=self._tool_progress_reporter,
|
|
77
|
+
)
|
|
57
78
|
wrapper.settings = ToolBuildConfig( # TODO: this must be refactored to behave like the other tools.
|
|
58
79
|
name=tool.name,
|
|
59
80
|
configuration=config,
|
|
@@ -10,7 +10,6 @@ import unique_sdk
|
|
|
10
10
|
|
|
11
11
|
from unique_toolkit.agentic.evaluation.schemas import EvaluationMetricName
|
|
12
12
|
from unique_toolkit.agentic.feature_flags import feature_flags
|
|
13
|
-
from unique_toolkit.agentic.message_log_manager.service import MessageStepLogger
|
|
14
13
|
from unique_toolkit.agentic.tools.mcp.models import MCPToolConfig
|
|
15
14
|
from unique_toolkit.agentic.tools.schemas import ToolCallResponse
|
|
16
15
|
from unique_toolkit.agentic.tools.tool import Tool
|
|
@@ -22,6 +21,7 @@ from unique_toolkit.app.schemas import ChatEvent, McpServer, McpTool
|
|
|
22
21
|
from unique_toolkit.chat.schemas import MessageLog, MessageLogStatus
|
|
23
22
|
from unique_toolkit.chat.service import ChatService
|
|
24
23
|
from unique_toolkit.content.functions import upload_content_from_bytes
|
|
24
|
+
from unique_toolkit.language_model import LanguageModelService
|
|
25
25
|
from unique_toolkit.language_model.schemas import (
|
|
26
26
|
LanguageModelFunction,
|
|
27
27
|
LanguageModelToolDescription,
|
|
@@ -40,13 +40,21 @@ class MCPToolWrapper(Tool[MCPToolConfig]):
|
|
|
40
40
|
config: MCPToolConfig,
|
|
41
41
|
event: ChatEvent,
|
|
42
42
|
tool_progress_reporter: ToolProgressReporter | None = None,
|
|
43
|
+
*,
|
|
44
|
+
chat_service: ChatService | None = None,
|
|
45
|
+
language_model_service: LanguageModelService | None = None,
|
|
43
46
|
) -> None:
|
|
44
47
|
self.name = mcp_tool.name
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
if chat_service is not None and language_model_service is not None:
|
|
49
|
+
super().__init__(
|
|
50
|
+
config,
|
|
51
|
+
event,
|
|
52
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
53
|
+
chat_service=chat_service,
|
|
54
|
+
language_model_service=language_model_service,
|
|
55
|
+
)
|
|
56
|
+
else:
|
|
57
|
+
super().__init__(config, event, tool_progress_reporter)
|
|
50
58
|
self._mcp_tool = mcp_tool
|
|
51
59
|
self._mcp_server = mcp_server
|
|
52
60
|
|
|
@@ -384,7 +392,7 @@ class MCPToolWrapper(Tool[MCPToolConfig]):
|
|
|
384
392
|
user_id=self._event.user_id,
|
|
385
393
|
company_id=self._event.company_id,
|
|
386
394
|
name=self.name,
|
|
387
|
-
messageId=self.
|
|
395
|
+
messageId=self._chat_service.assistant_message_id,
|
|
388
396
|
chatId=self._event.payload.chat_id,
|
|
389
397
|
arguments=arguments,
|
|
390
398
|
)
|
|
@@ -180,6 +180,17 @@ class Tool(ABC, Generic[ConfigType]):
|
|
|
180
180
|
tool_progress_reporter: ToolProgressReporter | None = ...,
|
|
181
181
|
) -> None: ...
|
|
182
182
|
|
|
183
|
+
@overload
|
|
184
|
+
def __init__(
|
|
185
|
+
self,
|
|
186
|
+
config: ConfigType,
|
|
187
|
+
event: ChatEvent,
|
|
188
|
+
tool_progress_reporter: ToolProgressReporter | None = ...,
|
|
189
|
+
*,
|
|
190
|
+
chat_service: ChatService,
|
|
191
|
+
language_model_service: LanguageModelService,
|
|
192
|
+
) -> None: ...
|
|
193
|
+
|
|
183
194
|
@overload
|
|
184
195
|
def __init__(
|
|
185
196
|
self,
|
|
@@ -230,6 +241,8 @@ class Tool(ABC, Generic[ConfigType]):
|
|
|
230
241
|
MessageStepLogger,
|
|
231
242
|
)
|
|
232
243
|
|
|
244
|
+
if event is not None:
|
|
245
|
+
self._event = event
|
|
233
246
|
self._tool_progress_reporter = tool_progress_reporter
|
|
234
247
|
self._chat_service = chat_service
|
|
235
248
|
self._language_model_service = language_model_service
|
|
@@ -37,6 +37,8 @@ from unique_toolkit.agentic.tools.schemas import ToolCallResponse, ToolPrompts
|
|
|
37
37
|
from unique_toolkit.agentic.tools.tool import Tool
|
|
38
38
|
from unique_toolkit.agentic.tools.tool_progress_reporter import ToolProgressReporter
|
|
39
39
|
from unique_toolkit.app.schemas import ChatEvent
|
|
40
|
+
from unique_toolkit.chat.service import ChatService
|
|
41
|
+
from unique_toolkit.language_model import LanguageModelService
|
|
40
42
|
from unique_toolkit.language_model.schemas import (
|
|
41
43
|
LanguageModelFunction,
|
|
42
44
|
LanguageModelToolDescription,
|
|
@@ -90,6 +92,8 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
90
92
|
a2a_manager: A2AManager,
|
|
91
93
|
api_mode: _ApiMode,
|
|
92
94
|
builtin_tool_manager: OpenAIBuiltInToolManager | None = None,
|
|
95
|
+
chat_service: ChatService | None = None,
|
|
96
|
+
language_model_service: LanguageModelService | None = None,
|
|
93
97
|
) -> None:
|
|
94
98
|
self._setup(
|
|
95
99
|
logger=logger,
|
|
@@ -100,6 +104,8 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
100
104
|
a2a_manager=a2a_manager,
|
|
101
105
|
api_mode=api_mode,
|
|
102
106
|
builtin_tool_manager=builtin_tool_manager,
|
|
107
|
+
chat_service=chat_service,
|
|
108
|
+
language_model_service=language_model_service,
|
|
103
109
|
)
|
|
104
110
|
|
|
105
111
|
@classmethod
|
|
@@ -114,6 +120,8 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
114
120
|
a2a_manager: A2AManager,
|
|
115
121
|
api_mode: _ApiMode,
|
|
116
122
|
builtin_tool_manager: OpenAIBuiltInToolManager | None = None,
|
|
123
|
+
chat_service: ChatService | None = None,
|
|
124
|
+
language_model_service: LanguageModelService | None = None,
|
|
117
125
|
) -> Self:
|
|
118
126
|
instance = cls.__new__(cls)
|
|
119
127
|
instance._setup(
|
|
@@ -125,6 +133,8 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
125
133
|
a2a_manager=a2a_manager,
|
|
126
134
|
api_mode=api_mode,
|
|
127
135
|
builtin_tool_manager=builtin_tool_manager,
|
|
136
|
+
chat_service=chat_service,
|
|
137
|
+
language_model_service=language_model_service,
|
|
128
138
|
)
|
|
129
139
|
return instance
|
|
130
140
|
|
|
@@ -139,10 +149,14 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
139
149
|
a2a_manager: A2AManager,
|
|
140
150
|
api_mode: _ApiMode,
|
|
141
151
|
builtin_tool_manager: OpenAIBuiltInToolManager | None,
|
|
152
|
+
chat_service: ChatService | None = None,
|
|
153
|
+
language_model_service: LanguageModelService | None = None,
|
|
142
154
|
) -> None:
|
|
143
155
|
self._logger = logger
|
|
144
156
|
self._config = config
|
|
145
157
|
self._tool_progress_reporter = tool_progress_reporter
|
|
158
|
+
self._chat_service = chat_service
|
|
159
|
+
self._language_model_service = language_model_service
|
|
146
160
|
self._tools: list[Tool[Any] | OpenAIBuiltInTool[Any]] = []
|
|
147
161
|
self._tool_choices = run_context.tool_choices
|
|
148
162
|
self._disabled_tools = run_context.disabled_tools
|
|
@@ -218,14 +232,29 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
218
232
|
t.name,
|
|
219
233
|
)
|
|
220
234
|
continue
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
235
|
+
if (
|
|
236
|
+
self._chat_service is not None
|
|
237
|
+
and self._language_model_service is not None
|
|
238
|
+
):
|
|
239
|
+
result = safe_executor.execute(
|
|
240
|
+
ToolFactory.build_tool_with_settings,
|
|
241
|
+
t.name,
|
|
242
|
+
t,
|
|
243
|
+
t.configuration,
|
|
244
|
+
tool_init_event,
|
|
245
|
+
tool_progress_reporter=self._tool_progress_reporter,
|
|
246
|
+
chat_service=self._chat_service,
|
|
247
|
+
language_model_service=self._language_model_service,
|
|
248
|
+
)
|
|
249
|
+
else:
|
|
250
|
+
result = safe_executor.execute(
|
|
251
|
+
ToolFactory.build_tool_with_settings,
|
|
252
|
+
t.name,
|
|
253
|
+
t,
|
|
254
|
+
t.configuration,
|
|
255
|
+
tool_init_event,
|
|
256
|
+
tool_progress_reporter=self._tool_progress_reporter,
|
|
257
|
+
)
|
|
229
258
|
if result.success:
|
|
230
259
|
self._internal_tools.append(result.unpack())
|
|
231
260
|
else:
|
|
@@ -684,6 +713,8 @@ class ToolManager(_ToolManager[Literal["completions"]]):
|
|
|
684
713
|
tool_progress_reporter: ToolProgressReporter,
|
|
685
714
|
mcp_manager: MCPManager,
|
|
686
715
|
a2a_manager: A2AManager,
|
|
716
|
+
chat_service: ChatService | None = None,
|
|
717
|
+
language_model_service: LanguageModelService | None = None,
|
|
687
718
|
) -> None:
|
|
688
719
|
super().__init__(
|
|
689
720
|
logger=logger,
|
|
@@ -694,6 +725,8 @@ class ToolManager(_ToolManager[Literal["completions"]]):
|
|
|
694
725
|
a2a_manager=a2a_manager,
|
|
695
726
|
api_mode="completions",
|
|
696
727
|
builtin_tool_manager=None,
|
|
728
|
+
chat_service=chat_service,
|
|
729
|
+
language_model_service=language_model_service,
|
|
697
730
|
)
|
|
698
731
|
|
|
699
732
|
@classmethod
|
|
@@ -708,6 +741,8 @@ class ToolManager(_ToolManager[Literal["completions"]]):
|
|
|
708
741
|
a2a_manager: A2AManager,
|
|
709
742
|
api_mode: Literal["completions"] = "completions",
|
|
710
743
|
builtin_tool_manager: OpenAIBuiltInToolManager | None = None,
|
|
744
|
+
chat_service: ChatService | None = None,
|
|
745
|
+
language_model_service: LanguageModelService | None = None,
|
|
711
746
|
) -> Self:
|
|
712
747
|
return super().from_run_context(
|
|
713
748
|
logger=logger,
|
|
@@ -718,6 +753,8 @@ class ToolManager(_ToolManager[Literal["completions"]]):
|
|
|
718
753
|
a2a_manager=a2a_manager,
|
|
719
754
|
api_mode=api_mode,
|
|
720
755
|
builtin_tool_manager=builtin_tool_manager,
|
|
756
|
+
chat_service=chat_service,
|
|
757
|
+
language_model_service=language_model_service,
|
|
721
758
|
)
|
|
722
759
|
|
|
723
760
|
|
|
@@ -731,6 +768,8 @@ class ResponsesApiToolManager(_ToolManager[Literal["responses"]]):
|
|
|
731
768
|
mcp_manager: MCPManager,
|
|
732
769
|
a2a_manager: A2AManager,
|
|
733
770
|
builtin_tool_manager: OpenAIBuiltInToolManager,
|
|
771
|
+
chat_service: ChatService | None = None,
|
|
772
|
+
language_model_service: LanguageModelService | None = None,
|
|
734
773
|
) -> None:
|
|
735
774
|
self._builtin_tool_manager = builtin_tool_manager
|
|
736
775
|
super().__init__(
|
|
@@ -742,6 +781,8 @@ class ResponsesApiToolManager(_ToolManager[Literal["responses"]]):
|
|
|
742
781
|
a2a_manager=a2a_manager,
|
|
743
782
|
api_mode="responses",
|
|
744
783
|
builtin_tool_manager=builtin_tool_manager,
|
|
784
|
+
chat_service=chat_service,
|
|
785
|
+
language_model_service=language_model_service,
|
|
745
786
|
)
|
|
746
787
|
|
|
747
788
|
@classmethod
|
|
@@ -756,6 +797,8 @@ class ResponsesApiToolManager(_ToolManager[Literal["responses"]]):
|
|
|
756
797
|
a2a_manager: A2AManager,
|
|
757
798
|
api_mode: Literal["responses"] = "responses",
|
|
758
799
|
builtin_tool_manager: OpenAIBuiltInToolManager | None = None,
|
|
800
|
+
chat_service: ChatService | None = None,
|
|
801
|
+
language_model_service: LanguageModelService | None = None,
|
|
759
802
|
) -> Self:
|
|
760
803
|
if builtin_tool_manager is None:
|
|
761
804
|
msg = "builtin_tool_manager is required for ResponsesApiToolManager"
|
|
@@ -769,6 +812,8 @@ class ResponsesApiToolManager(_ToolManager[Literal["responses"]]):
|
|
|
769
812
|
a2a_manager=a2a_manager,
|
|
770
813
|
api_mode=api_mode,
|
|
771
814
|
builtin_tool_manager=builtin_tool_manager,
|
|
815
|
+
chat_service=chat_service,
|
|
816
|
+
language_model_service=language_model_service,
|
|
772
817
|
)
|
|
773
818
|
|
|
774
819
|
def get_required_include_params(self) -> list[ResponseIncludable]:
|
|
@@ -17,6 +17,7 @@ from pydantic import (
|
|
|
17
17
|
)
|
|
18
18
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
19
19
|
from typing_extensions import Protocol, deprecated
|
|
20
|
+
from unique_sdk.api_resources._llm_models import LLMModels
|
|
20
21
|
|
|
21
22
|
from unique_toolkit._common.config_checker import register_config
|
|
22
23
|
from unique_toolkit.app.chat_event_filter_options_settings import (
|
|
@@ -321,6 +322,14 @@ class ApiType(StrEnum):
|
|
|
321
322
|
LEGACY = "legacy"
|
|
322
323
|
|
|
323
324
|
|
|
325
|
+
class UniqueApiConnectionError(Exception):
|
|
326
|
+
"""Raised when the API connection check fails."""
|
|
327
|
+
|
|
328
|
+
def __init__(self, base_url: str, message: str) -> None:
|
|
329
|
+
self.base_url = base_url
|
|
330
|
+
super().__init__(f"{message} (base URL: {base_url})")
|
|
331
|
+
|
|
332
|
+
|
|
324
333
|
@register_config()
|
|
325
334
|
class UniqueApi(BaseSettings):
|
|
326
335
|
base_url: str = Field(
|
|
@@ -337,6 +346,8 @@ class UniqueApi(BaseSettings):
|
|
|
337
346
|
|
|
338
347
|
api_type: ApiType = Field(default=ApiType.LEGACY)
|
|
339
348
|
|
|
349
|
+
_probe_check_failed: bool = PrivateAttr(default=False)
|
|
350
|
+
|
|
340
351
|
version: str = Field(
|
|
341
352
|
default="2023-12-06",
|
|
342
353
|
validation_alias=AliasChoices(
|
|
@@ -403,6 +414,8 @@ class UniqueApi(BaseSettings):
|
|
|
403
414
|
return parsed, base_path
|
|
404
415
|
|
|
405
416
|
def sdk_url(self) -> str:
|
|
417
|
+
if self._probe_check_failed:
|
|
418
|
+
return self.base_url
|
|
406
419
|
parsed, base_path = self.base_path()
|
|
407
420
|
return urlunparse(parsed._replace(path=base_path, query=None, fragment=None))
|
|
408
421
|
|
|
@@ -411,6 +424,15 @@ class UniqueApi(BaseSettings):
|
|
|
411
424
|
path = base_path + "/openai-proxy"
|
|
412
425
|
return urlunparse(parsed._replace(path=path, query=None, fragment=None))
|
|
413
426
|
|
|
427
|
+
async def check_connection(self, user_id: str, company_id: str) -> bool:
|
|
428
|
+
try:
|
|
429
|
+
model_list = await LLMModels.get_models_async(user_id, company_id)
|
|
430
|
+
self._probe_check_failed = False
|
|
431
|
+
return len(model_list["models"]) > 0
|
|
432
|
+
except Exception as exc:
|
|
433
|
+
self._probe_check_failed = True
|
|
434
|
+
raise UniqueApiConnectionError(self.base_url, str(exc)) from exc
|
|
435
|
+
|
|
414
436
|
|
|
415
437
|
# EventFilterOptions
|
|
416
438
|
# Settings only as only obtained from the environment.
|
|
@@ -612,7 +634,6 @@ class UniqueSettings:
|
|
|
612
634
|
logger.warning(
|
|
613
635
|
f"Environment file '{filename}' not found. Falling back to environment variables only."
|
|
614
636
|
)
|
|
615
|
-
# Fall back to environment variables only
|
|
616
637
|
return cls.from_env()
|
|
617
638
|
|
|
618
639
|
def init_sdk(self) -> None:
|
|
@@ -643,6 +664,29 @@ class UniqueSettings:
|
|
|
643
664
|
settings.init_sdk()
|
|
644
665
|
return settings
|
|
645
666
|
|
|
667
|
+
async def check_connection(self) -> bool:
|
|
668
|
+
"""Verify the API is reachable by listing available models via the SDK.
|
|
669
|
+
|
|
670
|
+
Returns:
|
|
671
|
+
True if the API is reachable and at least one model is available.
|
|
672
|
+
False if the API is reachable but no models are configured.
|
|
673
|
+
|
|
674
|
+
Raises:
|
|
675
|
+
UniqueApiConnectionError: If the SDK call fails due to a network or auth error.
|
|
676
|
+
"""
|
|
677
|
+
# Reset before init_sdk so each retry always probes the canonical computed
|
|
678
|
+
# sdk_url(), not a stale base_url left over from a previous failure.
|
|
679
|
+
self.api._probe_check_failed = False
|
|
680
|
+
self.init_sdk()
|
|
681
|
+
try:
|
|
682
|
+
return await self.api.check_connection(
|
|
683
|
+
self.authcontext.get_confidential_user_id(),
|
|
684
|
+
self.authcontext.get_confidential_company_id(),
|
|
685
|
+
)
|
|
686
|
+
finally:
|
|
687
|
+
# Re-sync api_base with sdk_url() which may have just fallen back.
|
|
688
|
+
self.init_sdk()
|
|
689
|
+
|
|
646
690
|
@classmethod
|
|
647
691
|
def from_chat_event(cls, event: ChatEvent) -> UniqueSettings:
|
|
648
692
|
"""Build a :class:`UniqueSettings` from a :class:`ChatEvent`.
|
{unique_toolkit-2026.28.0.dev16.dist-info → unique_toolkit-2026.28.0.dev18.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-toolkit
|
|
3
|
-
Version: 2026.28.0.
|
|
3
|
+
Version: 2026.28.0.dev18
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Cedric Klinkert, Martin Fadler, Sadique Sheik, Fabian Schläpfer, Pascal Hauri, Ejiroghene Oki-Peter, Rami Azouz, Ricardo Visini, Sanzio Monti
|
|
6
6
|
Author-email: Cedric Klinkert <cedric.klinkert@unique.ch>, Martin Fadler <martin.fadler@unique.ch>, Sadique Sheik <sadique@unique.ch>, Fabian Schläpfer <fabian@unique.ch>, Pascal Hauri <pascal@unique.ch>, Ejiroghene Oki-Peter <oki-peter.ejiroghene@unique.ai>, Rami Azouz <rami.ext@unique.ch>, Ricardo Visini <ricardo.visini@unique.ch>, Sanzio Monti <sanzio.monti@unique.ai>
|
|
@@ -16,7 +16,7 @@ Requires-Dist: sseclient>=0.0.27,<0.0.28
|
|
|
16
16
|
Requires-Dist: openai>=1.105.0,<3
|
|
17
17
|
Requires-Dist: platformdirs>=4.0.0,<5
|
|
18
18
|
Requires-Dist: pillow>=12.1.1
|
|
19
|
-
Requires-Dist: unique-sdk>=2026.28.0.
|
|
19
|
+
Requires-Dist: unique-sdk>=2026.28.0.dev19,<2026.28.0rc0
|
|
20
20
|
Requires-Dist: jambo>=0.1.2,<0.2
|
|
21
21
|
Requires-Dist: jinja2>=3.1.6,<4
|
|
22
22
|
Requires-Dist: docxtpl>=0.20.1,<0.21
|
{unique_toolkit-2026.28.0.dev16.dist-info → unique_toolkit-2026.28.0.dev18.dist-info}/RECORD
RENAMED
|
@@ -155,7 +155,7 @@ unique_toolkit/agentic/tools/a2a/evaluation/_utils.py,sha256=-fvd14FdEnQETGq-GRk
|
|
|
155
155
|
unique_toolkit/agentic/tools/a2a/evaluation/config.py,sha256=DLdDXWiXqkRgl-lmoSJxeMiXMScA4PFu2xVuMAqTHyA,2358
|
|
156
156
|
unique_toolkit/agentic/tools/a2a/evaluation/evaluator.py,sha256=dMlBrQBkytJnBXXLl7GZOtFPN49-Cnd5ySdzsJC1QAU,9735
|
|
157
157
|
unique_toolkit/agentic/tools/a2a/evaluation/summarization_user_message.j2,sha256=acP1YqD_sCy6DT0V2EIfhQTmaUKeqpeWNJ7RGgceo8I,271
|
|
158
|
-
unique_toolkit/agentic/tools/a2a/manager.py,sha256=
|
|
158
|
+
unique_toolkit/agentic/tools/a2a/manager.py,sha256=B5y69urCFCD2ROfAO2mTa-rCJRxUpOJpipPXL7ugpDI,3655
|
|
159
159
|
unique_toolkit/agentic/tools/a2a/postprocessing/__init__.py,sha256=aVtUBPN7kDrqA6Bze34AbqQpcBBqpvfyJG-xF65w7R0,659
|
|
160
160
|
unique_toolkit/agentic/tools/a2a/postprocessing/_display_utils.py,sha256=QydJqT7jfbspnYdouTdvCxLsSGOGikgBXaVDeI_zKsE,7107
|
|
161
161
|
unique_toolkit/agentic/tools/a2a/postprocessing/_ref_utils.py,sha256=tfH3Bhx67uQtH3fYoUr2Zp45HVw7hV_N-5F_qRwiOas,2727
|
|
@@ -173,14 +173,14 @@ unique_toolkit/agentic/tools/a2a/tool/__init__.py,sha256=9x8nGZsMcpF8ch0RKoelGPl
|
|
|
173
173
|
unique_toolkit/agentic/tools/a2a/tool/_memory.py,sha256=w8bxjokrqHQZgApd55b5rHXF-DpgJwaKTg4CvLBLamc,1034
|
|
174
174
|
unique_toolkit/agentic/tools/a2a/tool/_schema.py,sha256=wMwyunViTnxaURvenkATEvyfXn5LvLaP0HxbYqdZGls,158
|
|
175
175
|
unique_toolkit/agentic/tools/a2a/tool/config.py,sha256=v4rZQU42RjUTC5Md-Cye1rUIWDlHpuhc3MzcyvpGQNw,9748
|
|
176
|
-
unique_toolkit/agentic/tools/a2a/tool/service.py,sha256=
|
|
176
|
+
unique_toolkit/agentic/tools/a2a/tool/service.py,sha256=5jOtXSU9oggG1dVUd7PAb3hd_-MLyGnSR5_lUQvYPfA,22160
|
|
177
177
|
unique_toolkit/agentic/tools/a2a/tool/test/test_service_utils.py,sha256=x4leRxnGgqD-XyXPkW2z1ekv4Ja7EStXd-24LGadPZA,24858
|
|
178
178
|
unique_toolkit/agentic/tools/agent_chunks_hanlder.py,sha256=eO0g46wZOQlmWqYYVGiszRVe8K2LX-9qW30ZCdGg5eE,1943
|
|
179
179
|
unique_toolkit/agentic/tools/config.py,sha256=g_NKV94pq6cZ8nH-C69_BNScyQ-tjRjzYE8IKKqqDag,5726
|
|
180
180
|
unique_toolkit/agentic/tools/experimental/__init__.py,sha256=ArEcXHGPtMRNsDnsyo9v1fev0EZWdJ6D7NWdPEFLQKM,956
|
|
181
181
|
unique_toolkit/agentic/tools/experimental/ask_user_tool/__init__.py,sha256=B8srRVw4vMLa4dZE5yoF1Bqpjlv8moh_m-dP2BVRjDc,375
|
|
182
182
|
unique_toolkit/agentic/tools/experimental/ask_user_tool/config.py,sha256=z95ZaxkMvsmjVaUYWWZrvpD21-Us1KNUrMgXzpF4uo4,5923
|
|
183
|
-
unique_toolkit/agentic/tools/experimental/ask_user_tool/tool.py,sha256=
|
|
183
|
+
unique_toolkit/agentic/tools/experimental/ask_user_tool/tool.py,sha256=8durv3z82N5fVN8FsueZUnjrItOwtAK5eMJTksEF75w,5762
|
|
184
184
|
unique_toolkit/agentic/tools/experimental/open_file_tool/__init__.py,sha256=hPkz1tbiup8-QM62QMLWA1PpUmzX5VsNUnXsXw1_dMY,319
|
|
185
185
|
unique_toolkit/agentic/tools/experimental/open_file_tool/config.py,sha256=FQylVpCkOw06PSnfODOBwWARRrAI7UoUELzApWNVb2w,4342
|
|
186
186
|
unique_toolkit/agentic/tools/experimental/open_file_tool/runtime.py,sha256=SOIFV2N8USPGHNBnzId2nJPhZiJ3kGO5AwAiKJBNhdI,14383
|
|
@@ -196,12 +196,12 @@ unique_toolkit/agentic/tools/experimental/todo/prompts/system_prompt.j2,sha256=-
|
|
|
196
196
|
unique_toolkit/agentic/tools/experimental/todo/prompts/tool_description.j2,sha256=PxZ-JEyJfUL8mZncOozNm2JbtrtHQHOH0suahYlXCSc,600
|
|
197
197
|
unique_toolkit/agentic/tools/experimental/todo/prompts/verification_nudge.j2,sha256=NeLOeWE0NS7Z461PMERU_n-9ljgkUJqzMjphq_Xl_Go,108
|
|
198
198
|
unique_toolkit/agentic/tools/experimental/todo/schemas.py,sha256=SgZ4brHBHY4bdczzZf3vP1ME0kYn2DL3rYnTvBtQIk4,4659
|
|
199
|
-
unique_toolkit/agentic/tools/experimental/todo/service.py,sha256=
|
|
199
|
+
unique_toolkit/agentic/tools/experimental/todo/service.py,sha256=Ty_j3zjtlaGcuT6tAbG5gMbGLMzVO8CzTf-Ko05S0HY,10446
|
|
200
200
|
unique_toolkit/agentic/tools/factory.py,sha256=YK9uh2EqotQFb9stsXs-A8lsNaxklTCd_VAafCj0nPY,1459
|
|
201
201
|
unique_toolkit/agentic/tools/mcp/__init__.py,sha256=RLF_p-LDRC7GhiB3fdCi4u3bh6V9PY_w26fg61BLyco,122
|
|
202
|
-
unique_toolkit/agentic/tools/mcp/manager.py,sha256=
|
|
202
|
+
unique_toolkit/agentic/tools/mcp/manager.py,sha256=EfWbfNhB8Lnx2EqBgUXhK7klFLaBv2eezvYq8J0TXyo,3808
|
|
203
203
|
unique_toolkit/agentic/tools/mcp/models.py,sha256=DaBVzwJ4dqtgzm8Mv0-NOGBU04zyVe-RgWntBhkpmnE,742
|
|
204
|
-
unique_toolkit/agentic/tools/mcp/tool_wrapper.py,sha256=
|
|
204
|
+
unique_toolkit/agentic/tools/mcp/tool_wrapper.py,sha256=ehxs3JW-QwWWp5GcI94OnR6wA1AhcMMmvkg3BFx0cgk,15497
|
|
205
205
|
unique_toolkit/agentic/tools/names.py,sha256=MDF0ONLrxeC-iz--EtyrHAox_RN6zasxo5MSbXQYGyw,412
|
|
206
206
|
unique_toolkit/agentic/tools/openai_builtin/__init__.py,sha256=Q6d9mhsLRVF3erT2yMxLld62D3FTZ8nbovI4vLv4Nso,701
|
|
207
207
|
unique_toolkit/agentic/tools/openai_builtin/base.py,sha256=Ob5n1S6HduFbI5RsjIklasRjoKsgCwh840KAb6p2IaI,1858
|
|
@@ -218,8 +218,8 @@ unique_toolkit/agentic/tools/run_context.py,sha256=lk9tS1wn97NcSByNZpJWunnnZTos9
|
|
|
218
218
|
unique_toolkit/agentic/tools/schemas.py,sha256=4BTJ0q7fiAVQ2Uy9kVJnS0rcKeKKaYTkOFq8XGZwMJ0,5291
|
|
219
219
|
unique_toolkit/agentic/tools/test/test_mcp_manager.py,sha256=uWrTmnenQ70s5hrTfMYVah2vDT-jZq4nQmvhutypEK8,19195
|
|
220
220
|
unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py,sha256=XHNezB8itj9KzpQgD0cwRtp2AgRUfUkQsHc3bTyPj6c,15801
|
|
221
|
-
unique_toolkit/agentic/tools/tool.py,sha256=
|
|
222
|
-
unique_toolkit/agentic/tools/tool_manager.py,sha256=
|
|
221
|
+
unique_toolkit/agentic/tools/tool.py,sha256=X567zuGx9H_z0shQkJxPSLG0g-H9brgTFL-sYSlqxrQ,11078
|
|
222
|
+
unique_toolkit/agentic/tools/tool_manager.py,sha256=4-meG0fQJz4fc7SxPNVuO3Cc3TF4Z10lfIXI3edmON0,30526
|
|
223
223
|
unique_toolkit/agentic/tools/tool_progress_reporter.py,sha256=GaR0oqDUJZvBB9WCUVYYh0Zvs6U-LMygJCCrqPlitgA,10296
|
|
224
224
|
unique_toolkit/agentic/tools/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
225
225
|
unique_toolkit/agentic/tools/utils/source_handling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -241,7 +241,7 @@ unique_toolkit/app/init_sdk.py,sha256=5_oDoETr6akwYyBCb0ivTdMNu3SVgPSkrXcDS6ELyY
|
|
|
241
241
|
unique_toolkit/app/performance/async_tasks.py,sha256=8Xv5kEmmFDJO7YyyBxv4e7bcNgq-3z_E2_4z1Yn9EqU,1970
|
|
242
242
|
unique_toolkit/app/performance/async_wrapper.py,sha256=yVVcRDkcdyfjsxro-N29SBvi-7773wnfDplef6-y8xw,1077
|
|
243
243
|
unique_toolkit/app/schemas.py,sha256=NWaj7cpNiXaxU6W-U-bw911cdpXjqsbSUGeVoN4Q3Js,16534
|
|
244
|
-
unique_toolkit/app/unique_settings.py,sha256
|
|
244
|
+
unique_toolkit/app/unique_settings.py,sha256=-bYvxwCw_DvhSViHXgc-pYoNboxhHB8VG2L9YNPiDHU,26861
|
|
245
245
|
unique_toolkit/app/verification.py,sha256=GxFFwcJMy25fCA_Xe89wKW7bgqOu8PAs5y8QpHF0GSc,3861
|
|
246
246
|
unique_toolkit/app/webhook.py,sha256=evpxLDnvz7P3D7-TV1XBkl8WcoldXpjOkw3tvFRxHr0,2368
|
|
247
247
|
unique_toolkit/chat/__init__.py,sha256=N9RubtxWN7UF0DlxP7YgeNTgjjk6p7AwkbGaVvuZCv0,938
|
|
@@ -406,6 +406,6 @@ unique_toolkit/short_term_memory/service.py,sha256=2JMBEBn6GoyK-a0xvdcWpPft-3C74
|
|
|
406
406
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
407
407
|
unique_toolkit/smart_rules/compile.py,sha256=vRe0aMJWuVIK-VsqomgxQImzke7MDmwgSxxJfYCa7zw,1386
|
|
408
408
|
unique_toolkit/test_utilities/events.py,sha256=FLrhMh0A_mQutAUjoD0FdMcVQ4Gq31r35OVGzRjvLro,6760
|
|
409
|
-
unique_toolkit-2026.28.0.
|
|
410
|
-
unique_toolkit-2026.28.0.
|
|
411
|
-
unique_toolkit-2026.28.0.
|
|
409
|
+
unique_toolkit-2026.28.0.dev18.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
410
|
+
unique_toolkit-2026.28.0.dev18.dist-info/METADATA,sha256=0nKYiLrYRB0SJRS7mJwCWdxc8Jwda375qqEQHL3U_d8,7428
|
|
411
|
+
unique_toolkit-2026.28.0.dev18.dist-info/RECORD,,
|
|
File without changes
|