unique_toolkit 2026.28.0.dev6__py3-none-any.whl → 2026.28.0.dev8__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/_common/chunk_relevancy_sorter/service.py +1 -1
- unique_toolkit/agentic/evaluation/context_relevancy/service.py +1 -1
- unique_toolkit/agentic/tools/experimental/retrieve_search_scope_tool/tool.py +1 -1
- unique_toolkit/agentic/tools/run_context.py +24 -0
- unique_toolkit/agentic/tools/tool.py +44 -5
- unique_toolkit/agentic/tools/tool_manager.py +147 -20
- unique_toolkit/agentic_table/schemas.py +62 -24
- unique_toolkit/agentic_table/synthetic_chat_event.py +67 -0
- unique_toolkit/app/schemas.py +54 -15
- unique_toolkit/app/unique_settings.py +38 -0
- unique_toolkit/chat/functions.py +2 -0
- unique_toolkit/content/schemas.py +13 -0
- unique_toolkit/content/service.py +79 -40
- unique_toolkit/language_model/service.py +21 -21
- unique_toolkit/services/factory.py +10 -2
- unique_toolkit/services/knowledge_base.py +2 -2
- unique_toolkit/short_term_memory/service.py +27 -17
- {unique_toolkit-2026.28.0.dev6.dist-info → unique_toolkit-2026.28.0.dev8.dist-info}/METADATA +2 -2
- {unique_toolkit-2026.28.0.dev6.dist-info → unique_toolkit-2026.28.0.dev8.dist-info}/RECORD +20 -18
- {unique_toolkit-2026.28.0.dev6.dist-info → unique_toolkit-2026.28.0.dev8.dist-info}/WHEEL +0 -0
|
@@ -71,7 +71,7 @@ class ChunkRelevancySorter:
|
|
|
71
71
|
company_id: str | None = None,
|
|
72
72
|
user_id: str | None = None,
|
|
73
73
|
):
|
|
74
|
-
if isinstance(event,
|
|
74
|
+
if isinstance(event, BaseEvent):
|
|
75
75
|
self.chunk_relevancy_evaluator = ContextRelevancyEvaluator.from_event(event)
|
|
76
76
|
else:
|
|
77
77
|
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
@@ -81,7 +81,7 @@ class ContextRelevancyEvaluator:
|
|
|
81
81
|
company_id: str | None = None,
|
|
82
82
|
user_id: str | None = None,
|
|
83
83
|
):
|
|
84
|
-
if isinstance(event,
|
|
84
|
+
if isinstance(event, BaseEvent):
|
|
85
85
|
self.language_model_service = LanguageModelService.from_event(event)
|
|
86
86
|
else:
|
|
87
87
|
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
@@ -116,7 +116,7 @@ class RetrieveSearchScopeTool(Tool[RetrieveSearchScopeConfig]):
|
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
try:
|
|
119
|
-
settings = UniqueSettings.from_chat_event(self.
|
|
119
|
+
settings = UniqueSettings.from_chat_event(self.event)
|
|
120
120
|
kb_service = UniqueServiceFactory(
|
|
121
121
|
settings=settings
|
|
122
122
|
).knowledge_base_service()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
4
|
+
from typing_extensions import Self
|
|
5
|
+
|
|
6
|
+
from unique_toolkit.app.schemas import ChatEvent
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ToolRunContext(BaseModel):
|
|
10
|
+
"""Tool-manager runtime state decoupled from a raw :class:`ChatEvent`."""
|
|
11
|
+
|
|
12
|
+
model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)
|
|
13
|
+
|
|
14
|
+
tool_choices: list[str] = Field(default_factory=list)
|
|
15
|
+
disabled_tools: list[str] = Field(default_factory=list)
|
|
16
|
+
tool_init_event: ChatEvent | None = None
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def from_chat_event(cls, event: ChatEvent) -> Self:
|
|
20
|
+
return cls(
|
|
21
|
+
tool_choices=list(event.payload.tool_choices),
|
|
22
|
+
disabled_tools=list(event.payload.disabled_tools),
|
|
23
|
+
tool_init_event=event,
|
|
24
|
+
)
|
|
@@ -18,7 +18,8 @@ from unique_toolkit.app.schemas import ChatEvent
|
|
|
18
18
|
from unique_toolkit.language_model import LanguageModelToolDescription
|
|
19
19
|
|
|
20
20
|
if TYPE_CHECKING:
|
|
21
|
-
|
|
21
|
+
from unique_toolkit.language_model.service import LanguageModelService
|
|
22
|
+
from unique_toolkit.services.chat_service import ChatService
|
|
22
23
|
from unique_toolkit.language_model.schemas import (
|
|
23
24
|
LanguageModelFunction,
|
|
24
25
|
)
|
|
@@ -169,6 +170,9 @@ class Tool(ABC, Generic[ConfigType]):
|
|
|
169
170
|
def __init__(self, config: ConfigType) -> None: ...
|
|
170
171
|
|
|
171
172
|
@overload
|
|
173
|
+
@deprecated(
|
|
174
|
+
"Passing event is deprecated. Use Tool(config) and inject context in run()."
|
|
175
|
+
)
|
|
172
176
|
def __init__(
|
|
173
177
|
self,
|
|
174
178
|
config: ConfigType,
|
|
@@ -176,17 +180,32 @@ class Tool(ABC, Generic[ConfigType]):
|
|
|
176
180
|
tool_progress_reporter: ToolProgressReporter | None = ...,
|
|
177
181
|
) -> None: ...
|
|
178
182
|
|
|
183
|
+
@overload
|
|
184
|
+
def __init__(
|
|
185
|
+
self,
|
|
186
|
+
config: ConfigType,
|
|
187
|
+
*,
|
|
188
|
+
chat_service: ChatService,
|
|
189
|
+
language_model_service: LanguageModelService,
|
|
190
|
+
tool_progress_reporter: ToolProgressReporter | None = ...,
|
|
191
|
+
) -> None: ...
|
|
192
|
+
|
|
179
193
|
def __init__(
|
|
180
194
|
self,
|
|
181
195
|
config: ConfigType,
|
|
182
196
|
event: ChatEvent | None = None,
|
|
183
197
|
tool_progress_reporter: ToolProgressReporter | None = None,
|
|
198
|
+
*,
|
|
199
|
+
chat_service: ChatService | None = None,
|
|
200
|
+
language_model_service: LanguageModelService | None = None,
|
|
184
201
|
) -> None:
|
|
185
202
|
"""Initialize the tool.
|
|
186
203
|
|
|
187
|
-
Preferred (decoupled):
|
|
204
|
+
Preferred (decoupled): ``Tool(config)`` — configuration only.
|
|
188
205
|
|
|
189
|
-
|
|
206
|
+
Service injection: ``Tool(config, chat_service=..., language_model_service=...)``.
|
|
207
|
+
|
|
208
|
+
Backward compatible: ``Tool(config, event, tool_progress_reporter)`` — creates
|
|
190
209
|
deprecated chat_service, language_model_service, message_step_logger for
|
|
191
210
|
legacy subclasses.
|
|
192
211
|
"""
|
|
@@ -200,6 +219,25 @@ class Tool(ABC, Generic[ConfigType]):
|
|
|
200
219
|
self.logger = getLogger(f"{module_name}.{__name__}")
|
|
201
220
|
self.debug_info: dict[str, Any] = {}
|
|
202
221
|
|
|
222
|
+
if (chat_service is None) != (language_model_service is None):
|
|
223
|
+
raise ValueError(
|
|
224
|
+
"chat_service and language_model_service must be injected together; "
|
|
225
|
+
"supplying only one is not supported."
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
if chat_service is not None and language_model_service is not None:
|
|
229
|
+
from unique_toolkit.agentic.message_log_manager.service import (
|
|
230
|
+
MessageStepLogger,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
self._tool_progress_reporter = tool_progress_reporter
|
|
234
|
+
self._chat_service = chat_service
|
|
235
|
+
self._language_model_service = language_model_service
|
|
236
|
+
self._message_step_logger = MessageStepLogger(
|
|
237
|
+
chat_service=self._chat_service,
|
|
238
|
+
)
|
|
239
|
+
return
|
|
240
|
+
|
|
203
241
|
if event is not None:
|
|
204
242
|
from unique_toolkit.agentic.message_log_manager.service import (
|
|
205
243
|
MessageStepLogger,
|
|
@@ -220,11 +258,12 @@ class Tool(ABC, Generic[ConfigType]):
|
|
|
220
258
|
"Never reuse event. Dangerous. Prefer Tool(config) and inject context in run()."
|
|
221
259
|
)
|
|
222
260
|
def event(self) -> ChatEvent:
|
|
223
|
-
|
|
261
|
+
chat_event = getattr(self, "_event", None)
|
|
262
|
+
if chat_event is None:
|
|
224
263
|
raise AttributeError(
|
|
225
264
|
"event not available (tool was initialized with config only). "
|
|
226
265
|
)
|
|
227
|
-
return
|
|
266
|
+
return chat_event
|
|
228
267
|
|
|
229
268
|
@property
|
|
230
269
|
@deprecated(
|
|
@@ -12,6 +12,7 @@ from openai.types.responses import (
|
|
|
12
12
|
response_create_params,
|
|
13
13
|
)
|
|
14
14
|
from pydantic import BaseModel, Field
|
|
15
|
+
from typing_extensions import Self
|
|
15
16
|
|
|
16
17
|
from unique_toolkit._common.execution import (
|
|
17
18
|
Result,
|
|
@@ -31,6 +32,7 @@ from unique_toolkit.agentic.tools.openai_builtin.base import (
|
|
|
31
32
|
OpenAIBuiltInToolName,
|
|
32
33
|
)
|
|
33
34
|
from unique_toolkit.agentic.tools.openai_builtin.manager import OpenAIBuiltInToolManager
|
|
35
|
+
from unique_toolkit.agentic.tools.run_context import ToolRunContext
|
|
34
36
|
from unique_toolkit.agentic.tools.schemas import ToolCallResponse, ToolPrompts
|
|
35
37
|
from unique_toolkit.agentic.tools.tool import Tool
|
|
36
38
|
from unique_toolkit.agentic.tools.tool_progress_reporter import ToolProgressReporter
|
|
@@ -88,13 +90,62 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
88
90
|
a2a_manager: A2AManager,
|
|
89
91
|
api_mode: _ApiMode,
|
|
90
92
|
builtin_tool_manager: OpenAIBuiltInToolManager | None = None,
|
|
93
|
+
) -> None:
|
|
94
|
+
self._setup(
|
|
95
|
+
logger=logger,
|
|
96
|
+
config=config,
|
|
97
|
+
run_context=ToolRunContext.from_chat_event(event),
|
|
98
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
99
|
+
mcp_manager=mcp_manager,
|
|
100
|
+
a2a_manager=a2a_manager,
|
|
101
|
+
api_mode=api_mode,
|
|
102
|
+
builtin_tool_manager=builtin_tool_manager,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def from_run_context(
|
|
107
|
+
cls,
|
|
108
|
+
logger: Logger,
|
|
109
|
+
config: ToolManagerConfig,
|
|
110
|
+
*,
|
|
111
|
+
run_context: ToolRunContext,
|
|
112
|
+
tool_progress_reporter: ToolProgressReporter,
|
|
113
|
+
mcp_manager: MCPManager,
|
|
114
|
+
a2a_manager: A2AManager,
|
|
115
|
+
api_mode: _ApiMode,
|
|
116
|
+
builtin_tool_manager: OpenAIBuiltInToolManager | None = None,
|
|
117
|
+
) -> Self:
|
|
118
|
+
instance = cls.__new__(cls)
|
|
119
|
+
instance._setup(
|
|
120
|
+
logger=logger,
|
|
121
|
+
config=config,
|
|
122
|
+
run_context=run_context,
|
|
123
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
124
|
+
mcp_manager=mcp_manager,
|
|
125
|
+
a2a_manager=a2a_manager,
|
|
126
|
+
api_mode=api_mode,
|
|
127
|
+
builtin_tool_manager=builtin_tool_manager,
|
|
128
|
+
)
|
|
129
|
+
return instance
|
|
130
|
+
|
|
131
|
+
def _setup(
|
|
132
|
+
self,
|
|
133
|
+
*,
|
|
134
|
+
logger: Logger,
|
|
135
|
+
config: ToolManagerConfig,
|
|
136
|
+
run_context: ToolRunContext,
|
|
137
|
+
tool_progress_reporter: ToolProgressReporter,
|
|
138
|
+
mcp_manager: MCPManager,
|
|
139
|
+
a2a_manager: A2AManager,
|
|
140
|
+
api_mode: _ApiMode,
|
|
141
|
+
builtin_tool_manager: OpenAIBuiltInToolManager | None,
|
|
91
142
|
) -> None:
|
|
92
143
|
self._logger = logger
|
|
93
144
|
self._config = config
|
|
94
145
|
self._tool_progress_reporter = tool_progress_reporter
|
|
95
146
|
self._tools: list[Tool[Any] | OpenAIBuiltInTool[Any]] = []
|
|
96
|
-
self._tool_choices =
|
|
97
|
-
self._disabled_tools =
|
|
147
|
+
self._tool_choices = run_context.tool_choices
|
|
148
|
+
self._disabled_tools = run_context.disabled_tools
|
|
98
149
|
self._exclusive_tools = [
|
|
99
150
|
tool.name for tool in self._config.tools if tool.is_exclusive
|
|
100
151
|
]
|
|
@@ -104,17 +155,33 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
104
155
|
self._a2a_manager = a2a_manager
|
|
105
156
|
self._builtin_tool_manager = builtin_tool_manager
|
|
106
157
|
self._api_mode = api_mode
|
|
107
|
-
self.
|
|
108
|
-
|
|
109
|
-
|
|
158
|
+
self._sub_agents: list[SubAgentTool] = []
|
|
159
|
+
self._builtin_tools: list[OpenAIBuiltInTool[Any]] = []
|
|
160
|
+
self._mcp_tools: list[Tool[Any]] = []
|
|
161
|
+
self._internal_tools: list[Tool[Any]] = []
|
|
162
|
+
self.available_tools: list[
|
|
163
|
+
Tool[Any] | OpenAIBuiltInTool[Any] | SubAgentTool
|
|
164
|
+
] = []
|
|
165
|
+
self._init__tools(run_context.tool_init_event)
|
|
166
|
+
|
|
167
|
+
def _init__tools(self, tool_init_event: ChatEvent | None) -> None:
|
|
110
168
|
tool_choices = self._tool_choices
|
|
111
169
|
tool_configs = self._config.tools
|
|
112
170
|
self._logger.info("Initializing tool definitions...")
|
|
113
171
|
self._logger.info(f"Tool choices: {tool_choices}")
|
|
114
172
|
|
|
115
|
-
|
|
116
|
-
tool_configs,
|
|
117
|
-
|
|
173
|
+
if tool_init_event is not None:
|
|
174
|
+
tool_configs, sub_agents = self._a2a_manager.get_all_sub_agents(
|
|
175
|
+
tool_configs,
|
|
176
|
+
tool_init_event,
|
|
177
|
+
)
|
|
178
|
+
else:
|
|
179
|
+
tool_configs = [
|
|
180
|
+
tool_config
|
|
181
|
+
for tool_config in tool_configs
|
|
182
|
+
if not tool_config.is_sub_agent
|
|
183
|
+
]
|
|
184
|
+
sub_agents = []
|
|
118
185
|
self._sub_agents = sub_agents
|
|
119
186
|
|
|
120
187
|
registered_tool_names = set(t.name for t in self._sub_agents)
|
|
@@ -133,18 +200,27 @@ class _ToolManager(Generic[_ApiMode]):
|
|
|
133
200
|
registered_tool_names.update(t.name for t in self._mcp_tools)
|
|
134
201
|
|
|
135
202
|
# Build internal tools from configurations
|
|
136
|
-
self._internal_tools
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
203
|
+
self._internal_tools.clear()
|
|
204
|
+
for t in tool_configs:
|
|
205
|
+
if t.name in registered_tool_names:
|
|
206
|
+
continue
|
|
207
|
+
if t.name in OpenAIBuiltInToolName:
|
|
208
|
+
continue
|
|
209
|
+
if tool_init_event is not None:
|
|
210
|
+
built_tool = ToolFactory.build_tool_with_settings(
|
|
211
|
+
t.name,
|
|
212
|
+
t,
|
|
213
|
+
t.configuration,
|
|
214
|
+
tool_init_event,
|
|
215
|
+
tool_progress_reporter=self._tool_progress_reporter,
|
|
216
|
+
)
|
|
217
|
+
else:
|
|
218
|
+
self._logger.info(
|
|
219
|
+
"Skipping internal tool '%s' (requires chat event for initialization)",
|
|
220
|
+
t.name,
|
|
221
|
+
)
|
|
222
|
+
continue
|
|
223
|
+
self._internal_tools.append(built_tool)
|
|
148
224
|
|
|
149
225
|
# Combine all types of tools
|
|
150
226
|
self.available_tools = (
|
|
@@ -607,6 +683,30 @@ class ToolManager(_ToolManager[Literal["completions"]]):
|
|
|
607
683
|
builtin_tool_manager=None,
|
|
608
684
|
)
|
|
609
685
|
|
|
686
|
+
@classmethod
|
|
687
|
+
def from_run_context(
|
|
688
|
+
cls,
|
|
689
|
+
logger: Logger,
|
|
690
|
+
config: ToolManagerConfig,
|
|
691
|
+
*,
|
|
692
|
+
run_context: ToolRunContext,
|
|
693
|
+
tool_progress_reporter: ToolProgressReporter,
|
|
694
|
+
mcp_manager: MCPManager,
|
|
695
|
+
a2a_manager: A2AManager,
|
|
696
|
+
api_mode: Literal["completions"] = "completions",
|
|
697
|
+
builtin_tool_manager: OpenAIBuiltInToolManager | None = None,
|
|
698
|
+
) -> Self:
|
|
699
|
+
return super().from_run_context(
|
|
700
|
+
logger=logger,
|
|
701
|
+
config=config,
|
|
702
|
+
run_context=run_context,
|
|
703
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
704
|
+
mcp_manager=mcp_manager,
|
|
705
|
+
a2a_manager=a2a_manager,
|
|
706
|
+
api_mode=api_mode,
|
|
707
|
+
builtin_tool_manager=builtin_tool_manager,
|
|
708
|
+
)
|
|
709
|
+
|
|
610
710
|
|
|
611
711
|
class ResponsesApiToolManager(_ToolManager[Literal["responses"]]):
|
|
612
712
|
def __init__(
|
|
@@ -631,6 +731,33 @@ class ResponsesApiToolManager(_ToolManager[Literal["responses"]]):
|
|
|
631
731
|
builtin_tool_manager=builtin_tool_manager,
|
|
632
732
|
)
|
|
633
733
|
|
|
734
|
+
@classmethod
|
|
735
|
+
def from_run_context(
|
|
736
|
+
cls,
|
|
737
|
+
logger: Logger,
|
|
738
|
+
config: ToolManagerConfig,
|
|
739
|
+
*,
|
|
740
|
+
run_context: ToolRunContext,
|
|
741
|
+
tool_progress_reporter: ToolProgressReporter,
|
|
742
|
+
mcp_manager: MCPManager,
|
|
743
|
+
a2a_manager: A2AManager,
|
|
744
|
+
api_mode: Literal["responses"] = "responses",
|
|
745
|
+
builtin_tool_manager: OpenAIBuiltInToolManager | None = None,
|
|
746
|
+
) -> Self:
|
|
747
|
+
if builtin_tool_manager is None:
|
|
748
|
+
msg = "builtin_tool_manager is required for ResponsesApiToolManager"
|
|
749
|
+
raise ValueError(msg)
|
|
750
|
+
return super().from_run_context(
|
|
751
|
+
logger=logger,
|
|
752
|
+
config=config,
|
|
753
|
+
run_context=run_context,
|
|
754
|
+
tool_progress_reporter=tool_progress_reporter,
|
|
755
|
+
mcp_manager=mcp_manager,
|
|
756
|
+
a2a_manager=a2a_manager,
|
|
757
|
+
api_mode=api_mode,
|
|
758
|
+
builtin_tool_manager=builtin_tool_manager,
|
|
759
|
+
)
|
|
760
|
+
|
|
634
761
|
def get_required_include_params(self) -> list[ResponseIncludable]:
|
|
635
762
|
"""Return Responses API include params required by all active built-in tools."""
|
|
636
763
|
return self._builtin_tool_manager.get_required_include_params()
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from enum import StrEnum
|
|
2
|
-
from typing import Annotated, Any, Generic, Literal, TypeVar
|
|
2
|
+
from typing import Annotated, Any, Generic, Literal, TypeVar, override
|
|
3
3
|
|
|
4
4
|
from pydantic import (
|
|
5
5
|
AliasChoices,
|
|
@@ -20,13 +20,13 @@ from unique_sdk.api_resources._agentic_table import (
|
|
|
20
20
|
SheetType,
|
|
21
21
|
)
|
|
22
22
|
|
|
23
|
+
from unique_toolkit._common.exception import ConfigurationException
|
|
23
24
|
from unique_toolkit._common.pydantic_helpers import get_configuration_dict
|
|
24
25
|
from unique_toolkit.app.schemas import (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
ChatEventUserMessage,
|
|
28
|
-
Correlation,
|
|
26
|
+
AssistantWebhookEvent,
|
|
27
|
+
BaseEventPayload,
|
|
29
28
|
)
|
|
29
|
+
from unique_toolkit.app.unique_settings import UniqueChatEventFilterOptions
|
|
30
30
|
from unique_toolkit.language_model.schemas import (
|
|
31
31
|
LanguageModelMessageRole,
|
|
32
32
|
LanguageModelMessages,
|
|
@@ -112,27 +112,27 @@ A = TypeVar("A", bound=MagicTableAction)
|
|
|
112
112
|
T = TypeVar("T", bound=BaseMetadata)
|
|
113
113
|
|
|
114
114
|
|
|
115
|
-
class MagicTableBasePayload(
|
|
115
|
+
class MagicTableBasePayload(BaseEventPayload, Generic[A, T]):
|
|
116
|
+
"""Magic-table-specific payload.
|
|
117
|
+
|
|
118
|
+
Inherits the common envelope fields (``name``, ``chat_id``, ``assistant_id``,
|
|
119
|
+
``configuration``, ``metadata_filter``, ``correlation``) from
|
|
120
|
+
:class:`BaseEventPayload` and adds magic-table-only fields.
|
|
121
|
+
|
|
122
|
+
Note: previously this carried stub-empty ``user_message`` /
|
|
123
|
+
``assistant_message`` defaults so that ``MagicTableEvent`` could pose as
|
|
124
|
+
a ``ChatEvent``. That coupling is gone; magic-table flows that need a
|
|
125
|
+
chat context should construct a :class:`UniqueContext` explicitly.
|
|
126
|
+
"""
|
|
127
|
+
|
|
116
128
|
model_config = get_configuration_dict()
|
|
117
|
-
name: str = Field(description="The name of the module")
|
|
118
|
-
sheet_name: str
|
|
119
129
|
|
|
130
|
+
# Optional on magic-table (BaseEventPayload requires it for chat).
|
|
131
|
+
configuration: dict[str, Any] = Field(default_factory=dict)
|
|
132
|
+
sheet_name: str
|
|
120
133
|
action: A
|
|
121
|
-
chat_id: str
|
|
122
|
-
assistant_id: str
|
|
123
134
|
table_id: str
|
|
124
|
-
user_message: ChatEventUserMessage = Field(
|
|
125
|
-
default=ChatEventUserMessage(
|
|
126
|
-
id="", text="", original_text="", created_at="", language=""
|
|
127
|
-
)
|
|
128
|
-
)
|
|
129
|
-
assistant_message: ChatEventAssistantMessage = Field(
|
|
130
|
-
default=ChatEventAssistantMessage(id="", created_at="")
|
|
131
|
-
)
|
|
132
|
-
configuration: dict[str, Any] = {}
|
|
133
135
|
metadata: T
|
|
134
|
-
metadata_filter: dict[str, Any] | None = None
|
|
135
|
-
correlation: Correlation | None = None
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
########### Specialized Payload definitions ###########
|
|
@@ -263,10 +263,48 @@ PayloadTypes = (
|
|
|
263
263
|
MagicTablePayloadTypes = Annotated[PayloadTypes, Field(discriminator="action")]
|
|
264
264
|
|
|
265
265
|
|
|
266
|
-
class MagicTableEvent(
|
|
267
|
-
|
|
266
|
+
class MagicTableEvent(
|
|
267
|
+
AssistantWebhookEvent[UniqueChatEventFilterOptions, MagicTablePayloadTypes]
|
|
268
|
+
):
|
|
269
|
+
"""Magic-table webhook event, sibling of :class:`ChatEvent`.
|
|
270
|
+
|
|
271
|
+
No longer extends ``ChatEvent``; both events are siblings under
|
|
272
|
+
:class:`AssistantWebhookEvent`. This makes ``isinstance(magic_table_event,
|
|
273
|
+
ChatEvent)`` correctly return ``False`` and prevents silently passing a
|
|
274
|
+
magic-table event to services that require chat-only fields.
|
|
275
|
+
"""
|
|
276
|
+
|
|
268
277
|
event: MagicTableEventTypes # pyright: ignore[reportIncompatibleVariableOverride]
|
|
269
|
-
|
|
278
|
+
|
|
279
|
+
@override
|
|
280
|
+
def filter_event(
|
|
281
|
+
self, *, filter_options: UniqueChatEventFilterOptions | None = None
|
|
282
|
+
) -> bool:
|
|
283
|
+
if filter_options is None:
|
|
284
|
+
return False
|
|
285
|
+
|
|
286
|
+
if not filter_options.assistant_ids and not filter_options.references_in_code:
|
|
287
|
+
raise ConfigurationException(
|
|
288
|
+
"No filter options provided, all events will be filtered! \n"
|
|
289
|
+
"Please define: \n"
|
|
290
|
+
" - 'UNIQUE_CHAT_EVENT_FILTER_OPTIONS_ASSISTANT_IDS' \n"
|
|
291
|
+
" - 'UNIQUE_CHAT_EVENT_FILTER_OPTIONS_REFERENCES_IN_CODE' \n"
|
|
292
|
+
"in your environment variables."
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
if (
|
|
296
|
+
filter_options.assistant_ids
|
|
297
|
+
and self.payload.assistant_id not in filter_options.assistant_ids
|
|
298
|
+
):
|
|
299
|
+
return True
|
|
300
|
+
|
|
301
|
+
if (
|
|
302
|
+
filter_options.references_in_code
|
|
303
|
+
and self.payload.name not in filter_options.references_in_code
|
|
304
|
+
):
|
|
305
|
+
return True
|
|
306
|
+
|
|
307
|
+
return super().filter_event(filter_options=filter_options)
|
|
270
308
|
|
|
271
309
|
|
|
272
310
|
class LogDetail(BaseModel):
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Synthetic :class:`ChatEvent` for magic-table runs with chat-typed toolkit APIs."""
|
|
2
|
+
|
|
3
|
+
from unique_toolkit.agentic_table.schemas import MagicTableEvent
|
|
4
|
+
from unique_toolkit.app.schemas import (
|
|
5
|
+
ChatEvent,
|
|
6
|
+
ChatEventAssistantMessage,
|
|
7
|
+
ChatEventPayload,
|
|
8
|
+
ChatEventUserMessage,
|
|
9
|
+
EventName,
|
|
10
|
+
)
|
|
11
|
+
from unique_toolkit.app.unique_settings import (
|
|
12
|
+
MAGIC_TABLE_STREAMING_ASSISTANT_MESSAGE_ID,
|
|
13
|
+
MAGIC_TABLE_STREAMING_USER_MESSAGE_ID,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
_MAGIC_TABLE_STREAMING_MESSAGE_CREATED_AT = "1970-01-01T00:00:00Z"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def build_synthetic_chat_event(
|
|
20
|
+
event: MagicTableEvent,
|
|
21
|
+
*,
|
|
22
|
+
event_id: str | None = None,
|
|
23
|
+
description: str = "magic-table",
|
|
24
|
+
) -> ChatEvent:
|
|
25
|
+
"""Build a :class:`ChatEvent` for evaluators/tools that still require chat typing.
|
|
26
|
+
|
|
27
|
+
Discouraged for new code: prefer :meth:`UniqueContext.from_magic_table_event`
|
|
28
|
+
and ``Service.from_context(...)`` / :meth:`ToolManager.from_run_context`
|
|
29
|
+
so callers do not depend on a fabricated chat envelope.
|
|
30
|
+
|
|
31
|
+
Magic-table runs create messages dynamically; placeholder message ids are
|
|
32
|
+
sufficient for search tooling and hallucination evaluation scoping.
|
|
33
|
+
"""
|
|
34
|
+
payload = event.payload
|
|
35
|
+
chat_id = payload.chat_id
|
|
36
|
+
if not chat_id:
|
|
37
|
+
msg = (
|
|
38
|
+
"Magic-table event is missing chat_id; "
|
|
39
|
+
"chat-scoped services cannot be built."
|
|
40
|
+
)
|
|
41
|
+
raise ValueError(msg)
|
|
42
|
+
return ChatEvent(
|
|
43
|
+
id=event_id or event.id,
|
|
44
|
+
event=EventName.EXTERNAL_MODULE_CHOSEN,
|
|
45
|
+
user_id=event.user_id,
|
|
46
|
+
company_id=event.company_id,
|
|
47
|
+
payload=ChatEventPayload(
|
|
48
|
+
name=payload.name,
|
|
49
|
+
chat_id=chat_id,
|
|
50
|
+
assistant_id=payload.assistant_id,
|
|
51
|
+
description=description,
|
|
52
|
+
configuration=payload.configuration,
|
|
53
|
+
metadata_filter=payload.metadata_filter,
|
|
54
|
+
correlation=payload.correlation,
|
|
55
|
+
user_message=ChatEventUserMessage(
|
|
56
|
+
id=MAGIC_TABLE_STREAMING_USER_MESSAGE_ID,
|
|
57
|
+
text="",
|
|
58
|
+
original_text="",
|
|
59
|
+
created_at=_MAGIC_TABLE_STREAMING_MESSAGE_CREATED_AT,
|
|
60
|
+
language="EN",
|
|
61
|
+
),
|
|
62
|
+
assistant_message=ChatEventAssistantMessage(
|
|
63
|
+
id=MAGIC_TABLE_STREAMING_ASSISTANT_MESSAGE_ID,
|
|
64
|
+
created_at=_MAGIC_TABLE_STREAMING_MESSAGE_CREATED_AT,
|
|
65
|
+
),
|
|
66
|
+
),
|
|
67
|
+
)
|
unique_toolkit/app/schemas.py
CHANGED
|
@@ -250,14 +250,36 @@ class ChatEventSkill(BaseModel):
|
|
|
250
250
|
SkillReference = ChatEventSkill
|
|
251
251
|
|
|
252
252
|
|
|
253
|
-
class
|
|
253
|
+
class BaseEventPayload(BaseModel):
|
|
254
|
+
"""Common payload fields shared by all assistant-context webhook events.
|
|
255
|
+
|
|
256
|
+
Both :class:`ChatEventPayload` and :class:`MagicTableBasePayload` extend
|
|
257
|
+
this. Services that only need the common envelope (``chat_id``,
|
|
258
|
+
``assistant_id``, ``metadata_filter``, ``correlation``, ...) should
|
|
259
|
+
accept :class:`AssistantWebhookEvent` and read the payload off this
|
|
260
|
+
shared shape; services that need chat-only fields (``user_message``,
|
|
261
|
+
``assistant_message``) must accept :class:`ChatEvent` explicitly.
|
|
262
|
+
"""
|
|
263
|
+
|
|
254
264
|
model_config = model_config
|
|
255
265
|
|
|
256
|
-
name: str
|
|
257
|
-
description: str
|
|
258
|
-
configuration: dict[str, Any]
|
|
266
|
+
name: str = Field(description="The module / action name driving the event.")
|
|
259
267
|
chat_id: str
|
|
260
268
|
assistant_id: str
|
|
269
|
+
configuration: dict[str, Any]
|
|
270
|
+
# Default is None as empty dict triggers error in `backend-ingestion`
|
|
271
|
+
metadata_filter: dict[str, Any] | None = Field(
|
|
272
|
+
default=None,
|
|
273
|
+
description="Metadata filter compiled after module selection function calling and scope rules.",
|
|
274
|
+
)
|
|
275
|
+
correlation: Correlation | None = Field(
|
|
276
|
+
default=None,
|
|
277
|
+
description="The correlation to parent message in another chat.",
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
class ChatEventPayload(BaseEventPayload):
|
|
282
|
+
description: str
|
|
261
283
|
user_message: ChatEventUserMessage
|
|
262
284
|
assistant_message: ChatEventAssistantMessage
|
|
263
285
|
text: str | None = None
|
|
@@ -296,11 +318,6 @@ class ChatEventPayload(BaseModel):
|
|
|
296
318
|
default_factory=dict,
|
|
297
319
|
description="Parameters extracted from module selection function calling the tool.",
|
|
298
320
|
)
|
|
299
|
-
# Default is None as empty dict triggers error in `backend-ingestion`
|
|
300
|
-
metadata_filter: dict[str, Any] | None = Field(
|
|
301
|
-
default=None,
|
|
302
|
-
description="Metadata filter compiled after module selection function calling and scope rules.",
|
|
303
|
-
)
|
|
304
321
|
raw_scope_rules: UniqueQL | None = Field(
|
|
305
322
|
default=None,
|
|
306
323
|
description="Raw UniqueQL rule that can be compiled to a metadata filter.",
|
|
@@ -317,10 +334,6 @@ class ChatEventPayload(BaseModel):
|
|
|
317
334
|
default=None,
|
|
318
335
|
description="The session configuration for the chat session.",
|
|
319
336
|
)
|
|
320
|
-
correlation: Correlation | None = Field(
|
|
321
|
-
default=None,
|
|
322
|
-
description="The correlation to parent message in another chat.",
|
|
323
|
-
)
|
|
324
337
|
|
|
325
338
|
@field_validator("raw_scope_rules", mode="before")
|
|
326
339
|
def validate_scope_rules(cls, value: dict[str, Any] | None) -> UniqueQL | None:
|
|
@@ -341,13 +354,39 @@ class EventPayload(ChatEventPayload):
|
|
|
341
354
|
# additional_parameters: Optional[EventAdditionalParameters] = None
|
|
342
355
|
|
|
343
356
|
|
|
344
|
-
|
|
357
|
+
PayloadT_co = TypeVar("PayloadT_co", bound=BaseEventPayload, covariant=True)
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class AssistantWebhookEvent(
|
|
361
|
+
BaseEvent[FilterOptionsT], Generic[FilterOptionsT, PayloadT_co]
|
|
362
|
+
):
|
|
363
|
+
"""Umbrella envelope for webhook events that carry assistant/chat context.
|
|
364
|
+
|
|
365
|
+
The payload is constrained to :class:`BaseEventPayload`, giving consumers
|
|
366
|
+
a typed view of the shared envelope fields (``chat_id``, ``assistant_id``,
|
|
367
|
+
``metadata_filter``, ``correlation``, ...). Concrete events specialize
|
|
368
|
+
the payload type:
|
|
369
|
+
|
|
370
|
+
* :class:`ChatEvent` → :class:`ChatEventPayload`
|
|
371
|
+
* ``MagicTableEvent`` → ``MagicTablePayloadTypes`` (discriminated union)
|
|
372
|
+
|
|
373
|
+
``PayloadT_co`` is covariant so that ``AssistantWebhookEvent[..., ChildPayload]``
|
|
374
|
+
is a subtype of ``AssistantWebhookEvent[..., ParentPayload]``. This lets a
|
|
375
|
+
service signature accept *any* assistant-context event while still
|
|
376
|
+
accessing the common ``BaseEventPayload`` shape in a type-checked way.
|
|
377
|
+
"""
|
|
378
|
+
|
|
345
379
|
model_config = model_config
|
|
346
380
|
|
|
347
|
-
payload
|
|
381
|
+
# Covariant payload must stay read-only; reassignment through a widened type is unsound.
|
|
382
|
+
payload: PayloadT_co = Field(frozen=True)
|
|
348
383
|
created_at: Optional[int] = None
|
|
349
384
|
version: Optional[str] = None
|
|
350
385
|
|
|
386
|
+
|
|
387
|
+
class ChatEvent(AssistantWebhookEvent[UniqueChatEventFilterOptions, ChatEventPayload]):
|
|
388
|
+
model_config = model_config
|
|
389
|
+
|
|
351
390
|
class FilterOptions(BaseSettings):
|
|
352
391
|
assistant_ids: list[str] = Field(
|
|
353
392
|
default=[],
|
|
@@ -26,8 +26,13 @@ from unique_toolkit.app.feature_flags import UNIQUE_TOOLKIT_FEATURE_FLAGS
|
|
|
26
26
|
from unique_toolkit.app.find_env_file import EnvFileNotFoundError, find_env_file
|
|
27
27
|
|
|
28
28
|
if TYPE_CHECKING:
|
|
29
|
+
from unique_toolkit.agentic_table.schemas import MagicTableEvent
|
|
29
30
|
from unique_toolkit.app.schemas import BaseEvent, ChatEvent
|
|
30
31
|
|
|
32
|
+
# Placeholder message ids for magic-table runs that create messages dynamically.
|
|
33
|
+
MAGIC_TABLE_STREAMING_ASSISTANT_MESSAGE_ID = "magic-table-streaming-assistant"
|
|
34
|
+
MAGIC_TABLE_STREAMING_USER_MESSAGE_ID = "magic-table-streaming-user"
|
|
35
|
+
|
|
31
36
|
|
|
32
37
|
logger = getLogger(__name__)
|
|
33
38
|
|
|
@@ -485,6 +490,39 @@ class UniqueContext:
|
|
|
485
490
|
chat=ChatContext.from_chat_event(event),
|
|
486
491
|
)
|
|
487
492
|
|
|
493
|
+
@classmethod
|
|
494
|
+
def from_magic_table_event(cls, event: MagicTableEvent) -> Self:
|
|
495
|
+
"""Build auth + chat context from a magic-table webhook event.
|
|
496
|
+
|
|
497
|
+
Magic-table payloads carry ``chat_id`` and ``assistant_id`` but no live
|
|
498
|
+
user/assistant message objects. Placeholder message ids are used so
|
|
499
|
+
chat-scoped services (e.g. :class:`ChatService`) can be constructed via
|
|
500
|
+
:meth:`from_context`; do not use this context for short-term memory
|
|
501
|
+
writes that require a real message id.
|
|
502
|
+
"""
|
|
503
|
+
payload = event.payload
|
|
504
|
+
if not payload.chat_id:
|
|
505
|
+
msg = (
|
|
506
|
+
"Magic-table event is missing chat_id; "
|
|
507
|
+
"chat-scoped services cannot be built."
|
|
508
|
+
)
|
|
509
|
+
raise ValueError(msg)
|
|
510
|
+
parent_chat_id = (
|
|
511
|
+
payload.correlation.parent_chat_id if payload.correlation else None
|
|
512
|
+
)
|
|
513
|
+
return cls(
|
|
514
|
+
auth=AuthContext.from_event(event),
|
|
515
|
+
chat=ChatContext(
|
|
516
|
+
chat_id=payload.chat_id,
|
|
517
|
+
assistant_id=payload.assistant_id,
|
|
518
|
+
last_assistant_message_id=MAGIC_TABLE_STREAMING_ASSISTANT_MESSAGE_ID,
|
|
519
|
+
last_user_message_id=MAGIC_TABLE_STREAMING_USER_MESSAGE_ID,
|
|
520
|
+
last_user_message_text="",
|
|
521
|
+
metadata_filter=payload.metadata_filter,
|
|
522
|
+
parent_chat_id=parent_chat_id,
|
|
523
|
+
),
|
|
524
|
+
)
|
|
525
|
+
|
|
488
526
|
@classmethod
|
|
489
527
|
def from_event(cls, event: BaseEvent[Any]) -> Self:
|
|
490
528
|
"""Build an auth-only context from any BaseEvent."""
|
unique_toolkit/chat/functions.py
CHANGED
|
@@ -180,6 +180,7 @@ def map_references(references: list[ContentReference]) -> list[dict[str, Any]]:
|
|
|
180
180
|
return [
|
|
181
181
|
{
|
|
182
182
|
"name": ref.name,
|
|
183
|
+
"description": ref.description,
|
|
183
184
|
"url": ref.url,
|
|
184
185
|
"sequenceNumber": ref.sequence_number,
|
|
185
186
|
"sourceId": ref.source_id,
|
|
@@ -199,6 +200,7 @@ def map_references_with_original_index(
|
|
|
199
200
|
return [
|
|
200
201
|
{
|
|
201
202
|
"name": ref.name,
|
|
203
|
+
"description": ref.description,
|
|
202
204
|
"url": ref.url,
|
|
203
205
|
"sequenceNumber": ref.sequence_number,
|
|
204
206
|
"sourceId": ref.source_id,
|
|
@@ -215,6 +215,17 @@ class ContentReference(BaseModel):
|
|
|
215
215
|
sequence_number: int
|
|
216
216
|
source: str
|
|
217
217
|
source_id: str
|
|
218
|
+
description: str | None = Field(
|
|
219
|
+
default=None,
|
|
220
|
+
description=(
|
|
221
|
+
"Optional free-text/structured description carried alongside the "
|
|
222
|
+
"reference. Used by MCP tool references (UN-22310) to carry an "
|
|
223
|
+
'enriched ``{"mcp": {connectorName, title, details?, mcpServerId?}}`` '
|
|
224
|
+
"JSON payload the chat frontend renders as a card. Nullable "
|
|
225
|
+
"end-to-end (node-chat persists it as a nullable column; empty "
|
|
226
|
+
"values are dropped before sending)."
|
|
227
|
+
),
|
|
228
|
+
)
|
|
218
229
|
url: str | None = Field(
|
|
219
230
|
default=None,
|
|
220
231
|
description=(
|
|
@@ -241,6 +252,8 @@ class ContentReference(BaseModel):
|
|
|
241
252
|
"source": reference["source"],
|
|
242
253
|
"source_id": reference["sourceId"],
|
|
243
254
|
}
|
|
255
|
+
if "description" in reference:
|
|
256
|
+
kwargs["description"] = reference["description"]
|
|
244
257
|
if "originalIndex" in reference:
|
|
245
258
|
kwargs["original_index"] = reference["originalIndex"]
|
|
246
259
|
|
|
@@ -4,12 +4,12 @@ from typing import Any, overload
|
|
|
4
4
|
|
|
5
5
|
import unique_sdk
|
|
6
6
|
from requests import Response
|
|
7
|
-
from typing_extensions import deprecated
|
|
7
|
+
from typing_extensions import Self, deprecated
|
|
8
8
|
|
|
9
9
|
from unique_toolkit._common.utils.files import is_file_content, is_image_content
|
|
10
10
|
from unique_toolkit._common.validate_required_values import validate_required_values
|
|
11
|
-
from unique_toolkit.app.schemas import
|
|
12
|
-
from unique_toolkit.app.unique_settings import UniqueSettings
|
|
11
|
+
from unique_toolkit.app.schemas import AssistantWebhookEvent, BaseEvent, Correlation
|
|
12
|
+
from unique_toolkit.app.unique_settings import UniqueContext, UniqueSettings
|
|
13
13
|
from unique_toolkit.content import DOMAIN_NAME
|
|
14
14
|
from unique_toolkit.content.constants import DEFAULT_SEARCH_LANGUAGE
|
|
15
15
|
from unique_toolkit.content.functions import (
|
|
@@ -46,7 +46,7 @@ class ContentService:
|
|
|
46
46
|
"Use __init__ with company_id, user_id and chat_id instead or use the classmethod `from_event`"
|
|
47
47
|
)
|
|
48
48
|
@overload
|
|
49
|
-
def __init__(self, event:
|
|
49
|
+
def __init__(self, event: BaseEvent[Any]): ...
|
|
50
50
|
|
|
51
51
|
"""
|
|
52
52
|
Initialize the ContentService with an event (deprecated)
|
|
@@ -68,7 +68,7 @@ class ContentService:
|
|
|
68
68
|
|
|
69
69
|
def __init__(
|
|
70
70
|
self,
|
|
71
|
-
event:
|
|
71
|
+
event: BaseEvent[Any] | None = None,
|
|
72
72
|
company_id: str | None = None,
|
|
73
73
|
user_id: str | None = None,
|
|
74
74
|
chat_id: str | None = None,
|
|
@@ -78,23 +78,32 @@ class ContentService:
|
|
|
78
78
|
Initialize the ContentService with a company_id, user_id and chat_id.
|
|
79
79
|
"""
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
if event is not None:
|
|
82
|
+
if isinstance(event, AssistantWebhookEvent):
|
|
83
|
+
delegated = type(self).from_event(event)
|
|
84
|
+
self._event = event
|
|
85
|
+
self._company_id = delegated._company_id
|
|
86
|
+
self._user_id = delegated._user_id
|
|
87
|
+
self._chat_id = delegated._chat_id
|
|
88
|
+
self._metadata_filter = delegated._metadata_filter
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
self._event = event
|
|
92
|
+
self._metadata_filter = None
|
|
93
|
+
self._company_id = event.company_id
|
|
94
|
+
self._user_id = event.user_id
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
self._event = None
|
|
82
98
|
self._metadata_filter = None
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
self._chat_id: str | None = event.payload.chat_id
|
|
89
|
-
else:
|
|
90
|
-
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
91
|
-
self._company_id = company_id
|
|
92
|
-
self._user_id = user_id
|
|
93
|
-
self._chat_id = chat_id
|
|
94
|
-
self._metadata_filter = metadata_filter
|
|
99
|
+
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
100
|
+
self._company_id = company_id
|
|
101
|
+
self._user_id = user_id
|
|
102
|
+
self._chat_id = chat_id
|
|
103
|
+
self._metadata_filter = metadata_filter
|
|
95
104
|
|
|
96
105
|
@classmethod
|
|
97
|
-
def from_event(cls, event:
|
|
106
|
+
def from_event(cls, event: BaseEvent[Any]):
|
|
98
107
|
"""Initialize the ContentService with an event.
|
|
99
108
|
|
|
100
109
|
When the event has a correlation (e.g. subagent run), delegates to
|
|
@@ -109,32 +118,26 @@ class ContentService:
|
|
|
109
118
|
ContentService: Instance scoped to the event's chat or, when
|
|
110
119
|
correlation is present, the parent chat.
|
|
111
120
|
"""
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
121
|
+
if isinstance(event, AssistantWebhookEvent):
|
|
122
|
+
payload = event.payload
|
|
123
|
+
if payload.correlation is not None:
|
|
124
|
+
return cls.from_correlation(
|
|
125
|
+
event.company_id,
|
|
126
|
+
event.user_id,
|
|
127
|
+
payload.correlation,
|
|
128
|
+
metadata_filter=payload.metadata_filter,
|
|
119
129
|
)
|
|
120
|
-
return cls.from_correlation(
|
|
121
|
-
event.company_id,
|
|
122
|
-
event.user_id,
|
|
123
|
-
event.payload.correlation,
|
|
124
|
-
metadata_filter=getattr(event.payload, "metadata_filter", None),
|
|
125
|
-
)
|
|
126
|
-
chat_id = None
|
|
127
|
-
metadata_filter = None
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
return cls(
|
|
132
|
+
company_id=event.company_id,
|
|
133
|
+
user_id=event.user_id,
|
|
134
|
+
chat_id=payload.chat_id,
|
|
135
|
+
metadata_filter=payload.metadata_filter,
|
|
136
|
+
)
|
|
132
137
|
|
|
133
138
|
return cls(
|
|
134
139
|
company_id=event.company_id,
|
|
135
140
|
user_id=event.user_id,
|
|
136
|
-
chat_id=chat_id,
|
|
137
|
-
metadata_filter=metadata_filter,
|
|
138
141
|
)
|
|
139
142
|
|
|
140
143
|
@classmethod
|
|
@@ -167,11 +170,41 @@ class ContentService:
|
|
|
167
170
|
metadata_filter=metadata_filter,
|
|
168
171
|
)
|
|
169
172
|
|
|
173
|
+
@classmethod
|
|
174
|
+
def from_context(
|
|
175
|
+
cls,
|
|
176
|
+
context: UniqueContext,
|
|
177
|
+
*,
|
|
178
|
+
metadata_filter: dict[str, Any] | None = None,
|
|
179
|
+
) -> Self:
|
|
180
|
+
"""Create a ContentService from a :class:`UniqueContext`.
|
|
181
|
+
|
|
182
|
+
When ``context.chat.parent_chat_id`` is set (subagent correlation),
|
|
183
|
+
content operations are scoped to the parent chat.
|
|
184
|
+
"""
|
|
185
|
+
if context.chat is None:
|
|
186
|
+
msg = "ContentService requires chat context (context.chat is None)"
|
|
187
|
+
raise ValueError(msg)
|
|
188
|
+
chat = context.chat
|
|
189
|
+
effective_filter = (
|
|
190
|
+
metadata_filter if metadata_filter is not None else chat.metadata_filter
|
|
191
|
+
)
|
|
192
|
+
chat_id = (
|
|
193
|
+
chat.parent_chat_id if chat.parent_chat_id is not None else chat.chat_id
|
|
194
|
+
)
|
|
195
|
+
return cls(
|
|
196
|
+
company_id=context.auth.get_confidential_company_id(),
|
|
197
|
+
user_id=context.auth.get_confidential_user_id(),
|
|
198
|
+
chat_id=chat_id,
|
|
199
|
+
metadata_filter=effective_filter,
|
|
200
|
+
)
|
|
201
|
+
|
|
170
202
|
@classmethod
|
|
171
203
|
def from_settings(
|
|
172
204
|
cls,
|
|
173
205
|
settings: UniqueSettings | str | None = None,
|
|
174
206
|
metadata_filter: dict[str, Any] | None = None,
|
|
207
|
+
**kwargs: Any,
|
|
175
208
|
):
|
|
176
209
|
"""
|
|
177
210
|
Initialize the ContentService with a settings object and metadata filter.
|
|
@@ -182,6 +215,12 @@ class ContentService:
|
|
|
182
215
|
elif isinstance(settings, str):
|
|
183
216
|
settings = UniqueSettings.from_env_auto_with_sdk_init(filename=settings)
|
|
184
217
|
|
|
218
|
+
if settings.context.chat is not None:
|
|
219
|
+
return cls.from_context(
|
|
220
|
+
settings.context,
|
|
221
|
+
metadata_filter=metadata_filter,
|
|
222
|
+
)
|
|
223
|
+
|
|
185
224
|
return cls(
|
|
186
225
|
company_id=settings.auth.company_id.get_secret_value(),
|
|
187
226
|
user_id=settings.auth.user_id.get_secret_value(),
|
|
@@ -192,7 +231,7 @@ class ContentService:
|
|
|
192
231
|
@deprecated(
|
|
193
232
|
"The event property is deprecated and will be removed in a future version."
|
|
194
233
|
)
|
|
195
|
-
def event(self) ->
|
|
234
|
+
def event(self) -> BaseEvent[Any] | None:
|
|
196
235
|
"""
|
|
197
236
|
Get the event object (deprecated).
|
|
198
237
|
|
|
@@ -5,7 +5,7 @@ from pydantic import BaseModel
|
|
|
5
5
|
from typing_extensions import deprecated
|
|
6
6
|
|
|
7
7
|
from unique_toolkit._common.validate_required_values import validate_required_values
|
|
8
|
-
from unique_toolkit.app.schemas import
|
|
8
|
+
from unique_toolkit.app.schemas import AssistantWebhookEvent, BaseEvent
|
|
9
9
|
from unique_toolkit.app.unique_settings import UniqueSettings
|
|
10
10
|
from unique_toolkit.content.schemas import ContentChunk
|
|
11
11
|
from unique_toolkit.language_model.constants import (
|
|
@@ -40,7 +40,7 @@ class LanguageModelService:
|
|
|
40
40
|
"Use __init__ with company_id and user_id instead or use the classmethod `from_event`"
|
|
41
41
|
)
|
|
42
42
|
@overload
|
|
43
|
-
def __init__(self, event:
|
|
43
|
+
def __init__(self, event: BaseEvent[Any]): ...
|
|
44
44
|
|
|
45
45
|
"""
|
|
46
46
|
Initialize the LanguageModelService with an event (deprecated)
|
|
@@ -55,30 +55,30 @@ class LanguageModelService:
|
|
|
55
55
|
|
|
56
56
|
def __init__(
|
|
57
57
|
self,
|
|
58
|
-
event:
|
|
58
|
+
event: BaseEvent[Any] | None = None,
|
|
59
59
|
company_id: str | None = None,
|
|
60
60
|
user_id: str | None = None,
|
|
61
61
|
**kwargs: dict[str, Any], # only here for backward compatibility
|
|
62
62
|
):
|
|
63
|
-
if
|
|
63
|
+
if event is not None:
|
|
64
|
+
auth_scoped = type(self).from_event(event)
|
|
65
|
+
self._company_id = auth_scoped._company_id
|
|
66
|
+
self._user_id = auth_scoped._user_id
|
|
64
67
|
self._event = event
|
|
65
|
-
self._chat_id = event.payload.chat_id
|
|
66
|
-
self._assistant_id = event.payload.assistant_id
|
|
67
|
-
self._company_id = event.company_id
|
|
68
|
-
self._user_id = event.user_id
|
|
69
|
-
elif isinstance(event, BaseEvent):
|
|
70
|
-
self._event = event
|
|
71
|
-
self._company_id = event.company_id
|
|
72
|
-
self._user_id = event.user_id
|
|
73
68
|
self._chat_id = None
|
|
74
69
|
self._assistant_id = None
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
70
|
+
if isinstance(event, AssistantWebhookEvent):
|
|
71
|
+
payload = event.payload
|
|
72
|
+
self._chat_id = payload.chat_id
|
|
73
|
+
self._assistant_id = payload.assistant_id
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
77
|
+
self._event = None
|
|
78
|
+
self._company_id: str = company_id
|
|
79
|
+
self._user_id: str = user_id
|
|
80
|
+
self._chat_id: str | None = None
|
|
81
|
+
self._assistant_id: str | None = None
|
|
82
82
|
|
|
83
83
|
@classmethod
|
|
84
84
|
def from_event(cls, event: BaseEvent[Any]):
|
|
@@ -88,7 +88,7 @@ class LanguageModelService:
|
|
|
88
88
|
return cls(company_id=event.company_id, user_id=event.user_id)
|
|
89
89
|
|
|
90
90
|
@classmethod
|
|
91
|
-
def from_settings(cls, settings: UniqueSettings | str | None = None):
|
|
91
|
+
def from_settings(cls, settings: UniqueSettings | str | None = None, **kwargs: Any):
|
|
92
92
|
"""
|
|
93
93
|
Initialize the LanguageModelService with a settings object.
|
|
94
94
|
"""
|
|
@@ -106,7 +106,7 @@ class LanguageModelService:
|
|
|
106
106
|
@deprecated(
|
|
107
107
|
"The event property is deprecated and will be removed in a future version."
|
|
108
108
|
)
|
|
109
|
-
def event(self) ->
|
|
109
|
+
def event(self) -> BaseEvent[Any] | None:
|
|
110
110
|
"""
|
|
111
111
|
Get the event object (deprecated).
|
|
112
112
|
|
|
@@ -138,7 +138,8 @@ class UniqueServiceFactory:
|
|
|
138
138
|
def register_known_services(cls) -> None:
|
|
139
139
|
"""Register the stable toolkit services with the factory.
|
|
140
140
|
|
|
141
|
-
Currently registers :class:`KnowledgeBaseService
|
|
141
|
+
Currently registers :class:`KnowledgeBaseService`, :class:`ChatService`,
|
|
142
|
+
:class:`ContentService`, and :class:`LanguageModelService`.
|
|
142
143
|
:class:`ChunkRelevancySorter` is intentionally excluded to avoid circular
|
|
143
144
|
imports at package init time — use the ``chunk_relevancy_sorter()``
|
|
144
145
|
convenience method instead.
|
|
@@ -149,10 +150,17 @@ class UniqueServiceFactory:
|
|
|
149
150
|
example, :meth:`Identity.from_settings`) so that the experimental
|
|
150
151
|
dependency is visible at every call site.
|
|
151
152
|
"""
|
|
153
|
+
from unique_toolkit.content.service import ContentService
|
|
154
|
+
from unique_toolkit.language_model.service import LanguageModelService
|
|
152
155
|
from unique_toolkit.services.chat_service import ChatService
|
|
153
156
|
from unique_toolkit.services.knowledge_base import KnowledgeBaseService
|
|
154
157
|
|
|
155
|
-
for service_class in [
|
|
158
|
+
for service_class in [
|
|
159
|
+
KnowledgeBaseService,
|
|
160
|
+
ChatService,
|
|
161
|
+
ContentService,
|
|
162
|
+
LanguageModelService,
|
|
163
|
+
]:
|
|
156
164
|
if service_class.__name__ not in cls._registry:
|
|
157
165
|
cls.register(service_class=service_class)
|
|
158
166
|
|
|
@@ -16,7 +16,7 @@ from unique_toolkit._common.metadata_filter_scope import (
|
|
|
16
16
|
merge_scope_clause_into_metadata_filter,
|
|
17
17
|
)
|
|
18
18
|
from unique_toolkit._common.validate_required_values import validate_required_values
|
|
19
|
-
from unique_toolkit.app.schemas import
|
|
19
|
+
from unique_toolkit.app.schemas import AssistantWebhookEvent, BaseEvent
|
|
20
20
|
from unique_toolkit.app.unique_settings import UniqueSettings
|
|
21
21
|
from unique_toolkit.content.constants import (
|
|
22
22
|
DEFAULT_SEARCH_LANGUAGE,
|
|
@@ -93,7 +93,7 @@ class KnowledgeBaseService:
|
|
|
93
93
|
"""
|
|
94
94
|
metadata_filter = None
|
|
95
95
|
|
|
96
|
-
if isinstance(event,
|
|
96
|
+
if isinstance(event, AssistantWebhookEvent):
|
|
97
97
|
metadata_filter = event.payload.metadata_filter
|
|
98
98
|
|
|
99
99
|
return cls(
|
|
@@ -52,23 +52,33 @@ class ShortTermMemoryService:
|
|
|
52
52
|
chat_id: str | None = None,
|
|
53
53
|
message_id: str | None = None,
|
|
54
54
|
):
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
self.
|
|
61
|
-
self.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
self.
|
|
69
|
-
self.
|
|
70
|
-
|
|
71
|
-
|
|
55
|
+
if event is not None:
|
|
56
|
+
if isinstance(event, ChatEvent):
|
|
57
|
+
delegated = type(self).from_event(event)
|
|
58
|
+
self._event = event
|
|
59
|
+
self._company_id = delegated._company_id
|
|
60
|
+
self._user_id = delegated._user_id
|
|
61
|
+
self._chat_id = delegated._chat_id
|
|
62
|
+
self._message_id = delegated._message_id
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
self._event = event
|
|
66
|
+
self._company_id = event.company_id
|
|
67
|
+
self._user_id = event.user_id
|
|
68
|
+
self._chat_id = None
|
|
69
|
+
self._message_id = None
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
self._event = None
|
|
73
|
+
[company_id, user_id] = validate_required_values([company_id, user_id])
|
|
74
|
+
|
|
75
|
+
if not (chat_id or message_id):
|
|
76
|
+
raise ValueError("Chat_id or message_id must be provided")
|
|
77
|
+
|
|
78
|
+
self._company_id = company_id
|
|
79
|
+
self._user_id = user_id
|
|
80
|
+
self._chat_id = chat_id
|
|
81
|
+
self._message_id = message_id
|
|
72
82
|
|
|
73
83
|
@classmethod
|
|
74
84
|
def from_event(cls, event: ChatEvent):
|
{unique_toolkit-2026.28.0.dev6.dist-info → unique_toolkit-2026.28.0.dev8.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.dev8
|
|
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.dev11,<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
|
|
@@ -7,7 +7,7 @@ unique_toolkit/_common/base_model_type_attribute.py,sha256=3t2InDT3nxG9YMEg0M90_
|
|
|
7
7
|
unique_toolkit/_common/chunk_relevancy_sorter/config.py,sha256=_9ACfqI-69DzN2azdt9dUhBRvS6NbTjqqNfm77Qn_5M,1889
|
|
8
8
|
unique_toolkit/_common/chunk_relevancy_sorter/exception.py,sha256=1mY4zjbvnXsd5oIxwiVsma09bS2XRnHrxW8KJBGtgCM,126
|
|
9
9
|
unique_toolkit/_common/chunk_relevancy_sorter/schemas.py,sha256=Cg9vNDPmkn5V_j6ssV58ADcEaDURNP5TeUa1UmRtdHw,1343
|
|
10
|
-
unique_toolkit/_common/chunk_relevancy_sorter/service.py,sha256=
|
|
10
|
+
unique_toolkit/_common/chunk_relevancy_sorter/service.py,sha256=pCwRJRdCqXK_2a7kAm3K9VZRCjaLntek8OtoCyRpHQE,14757
|
|
11
11
|
unique_toolkit/_common/chunk_relevancy_sorter/tests/test_service.py,sha256=giD9b5W8A0xP18dZCcrLUruoGi38BeBvPnO1phY7Sp0,8892
|
|
12
12
|
unique_toolkit/_common/config_checker/README.md,sha256=4WXBP5DIyEwklSi8RkVpKYYUPo_qOvm_8zEAz9WsdcU,11564
|
|
13
13
|
unique_toolkit/_common/config_checker/__init__.py,sha256=iGtDFILDQrjSpxC_hNut_H6hQxQ_exDp6GQrgMSdn0U,1204
|
|
@@ -90,7 +90,7 @@ unique_toolkit/agentic/evaluation/context_relevancy/prompts/__init__.py,sha256=I
|
|
|
90
90
|
unique_toolkit/agentic/evaluation/context_relevancy/prompts/system_prompt.j2,sha256=PFT9Y7QQ85h-ronwK8sq6zJJrxfrZhvZkYHXspMdDHU,985
|
|
91
91
|
unique_toolkit/agentic/evaluation/context_relevancy/prompts/user_prompt.j2,sha256=9HXm0Qg0xAPIE5mnaUiHrscolD_qO7f83qlIjXiP1n4,150
|
|
92
92
|
unique_toolkit/agentic/evaluation/context_relevancy/schema.py,sha256=lZd0TPzH43ifgWWGg3WO6b1AQX8aK2R9y51yH0d1DHM,2919
|
|
93
|
-
unique_toolkit/agentic/evaluation/context_relevancy/service.py,sha256=
|
|
93
|
+
unique_toolkit/agentic/evaluation/context_relevancy/service.py,sha256=OYr5_uQmovFtvsXVItqDw1VUW5rP-LED9XElx-kh5MM,8747
|
|
94
94
|
unique_toolkit/agentic/evaluation/evaluation_manager.py,sha256=4HeKsDg6tLkJXNw3kzjmVLbD-86IRzKLQSuPwYtfYBk,7992
|
|
95
95
|
unique_toolkit/agentic/evaluation/exception.py,sha256=7lcVbCyoN4Md1chNJDFxpUYyWbVrcr9dcc3TxWykJTc,115
|
|
96
96
|
unique_toolkit/agentic/evaluation/hallucination/constants.py,sha256=uEQR-CNKmeXizDaLOLHhwTZ0iYUmFwoKeMLHPm4M0sY,3208
|
|
@@ -187,7 +187,7 @@ unique_toolkit/agentic/tools/experimental/open_file_tool/runtime.py,sha256=SOIFV
|
|
|
187
187
|
unique_toolkit/agentic/tools/experimental/open_file_tool/tool.py,sha256=BXsEeyJ1Njswl_PChfO-vVz2MzFzmDcN2Few9WBWdXU,3774
|
|
188
188
|
unique_toolkit/agentic/tools/experimental/retrieve_search_scope_tool/__init__.py,sha256=kD6BaQWgOWk8fPYVBuCUnfHWcJNuH4KjWAreORAkfWI,357
|
|
189
189
|
unique_toolkit/agentic/tools/experimental/retrieve_search_scope_tool/config.py,sha256=NI-dk1Sai-t32PD5AUIyeGguPeV-qZhn4F8-nIHXAhA,4271
|
|
190
|
-
unique_toolkit/agentic/tools/experimental/retrieve_search_scope_tool/tool.py,sha256=
|
|
190
|
+
unique_toolkit/agentic/tools/experimental/retrieve_search_scope_tool/tool.py,sha256=4r9nX6iFvmYtnV1VnsWaINcnTLvU665ha3pgQSquh8U,7513
|
|
191
191
|
unique_toolkit/agentic/tools/experimental/todo/__init__.py,sha256=QzaC8tqBFrjfZbYSxvWJkWyFYel1ejrbx8IN63d0YCo,583
|
|
192
192
|
unique_toolkit/agentic/tools/experimental/todo/config.py,sha256=52GamaMU6VrCd__JgyRoJfEL_Dp0y8CPf3jwYCkXVBg,3506
|
|
193
193
|
unique_toolkit/agentic/tools/experimental/todo/prompts/__init__.py,sha256=DlBk0Ex5w41XtcmnLdGFK9r4mVfBHweFwc8dZB5tXVI,379
|
|
@@ -214,11 +214,12 @@ unique_toolkit/agentic/tools/openai_builtin/code_interpreter/postprocessors/gene
|
|
|
214
214
|
unique_toolkit/agentic/tools/openai_builtin/code_interpreter/schemas.py,sha256=W7egCmYrPrzic0aXsu9wY5fvQ8y_cl4Tzq_cjVs0mZs,542
|
|
215
215
|
unique_toolkit/agentic/tools/openai_builtin/code_interpreter/service.py,sha256=k10VBHL2vVlEylNF3EWGvm8_wZ_44K1pJ5ngGirUzOA,14275
|
|
216
216
|
unique_toolkit/agentic/tools/openai_builtin/manager.py,sha256=CkfMRsjrRDv_X-zfJHZnxxOdpCK1qzf6RGGxKtUHp9k,3519
|
|
217
|
+
unique_toolkit/agentic/tools/run_context.py,sha256=lk9tS1wn97NcSByNZpJWunnnZTos9H2SsxUkKKAvW_A,783
|
|
217
218
|
unique_toolkit/agentic/tools/schemas.py,sha256=4BTJ0q7fiAVQ2Uy9kVJnS0rcKeKKaYTkOFq8XGZwMJ0,5291
|
|
218
219
|
unique_toolkit/agentic/tools/test/test_mcp_manager.py,sha256=uWrTmnenQ70s5hrTfMYVah2vDT-jZq4nQmvhutypEK8,19195
|
|
219
220
|
unique_toolkit/agentic/tools/test/test_tool_progress_reporter.py,sha256=XHNezB8itj9KzpQgD0cwRtp2AgRUfUkQsHc3bTyPj6c,15801
|
|
220
|
-
unique_toolkit/agentic/tools/tool.py,sha256=
|
|
221
|
-
unique_toolkit/agentic/tools/tool_manager.py,sha256=
|
|
221
|
+
unique_toolkit/agentic/tools/tool.py,sha256=jDGXRD9H0aagibLARWjJaX8DGMFjICeCojgONs40ghY,10721
|
|
222
|
+
unique_toolkit/agentic/tools/tool_manager.py,sha256=FNf_Yfi-Nt8YfGA3A_ZHUStzSuIJiY_rSdRJLVGu6z8,27719
|
|
222
223
|
unique_toolkit/agentic/tools/tool_progress_reporter.py,sha256=GaR0oqDUJZvBB9WCUVYYh0Zvs6U-LMygJCCrqPlitgA,10296
|
|
223
224
|
unique_toolkit/agentic/tools/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
224
225
|
unique_toolkit/agentic/tools/utils/source_handling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -226,8 +227,9 @@ unique_toolkit/agentic/tools/utils/source_handling/schema.py,sha256=iHBKuks6tUy8
|
|
|
226
227
|
unique_toolkit/agentic/tools/utils/source_handling/source_formatting.py,sha256=uZ0QXqrPWgId3ZA67dvjHQ6xrW491LK1xxx_sVJmFHg,9160
|
|
227
228
|
unique_toolkit/agentic/tools/utils/source_handling/tests/test_source_formatting.py,sha256=EA8iVvb3L91OFk2XMbGcFuhe2etqm3Sx9QCYDGiOSOM,6995
|
|
228
229
|
unique_toolkit/agentic_table/__init__.py,sha256=bTMTBUomZysXhMtP9Rnzk6hVa2lZ7Xmrn-THZzE8uWo,1737
|
|
229
|
-
unique_toolkit/agentic_table/schemas.py,sha256=
|
|
230
|
+
unique_toolkit/agentic_table/schemas.py,sha256=IhVVSWZyDVIeyVoiP-FWp26MWwXv8oL4KFPTzeQquCc,12568
|
|
230
231
|
unique_toolkit/agentic_table/service.py,sha256=26hblR33Vp8FWWMgtaQCJ0IQT8hmGzGCQy86BDi2wOo,19670
|
|
232
|
+
unique_toolkit/agentic_table/synthetic_chat_event.py,sha256=MylvYuhx5CVt2DbPetzV0sR8GlkL218DmNFi7A6RYVs,2373
|
|
231
233
|
unique_toolkit/app/__init__.py,sha256=VnyvvCugDYZzEK93vVpSL1zHGduuev6yOvLJOGzpmMc,1568
|
|
232
234
|
unique_toolkit/app/chat_event_filter_options_settings.py,sha256=W0Ydio1UeED5_xqaTzbcGzK2tH4EpA1WHUzdF-iWpqI,364
|
|
233
235
|
unique_toolkit/app/dev_util.py,sha256=cHDuC6jtaptdVISbtMmOCqRTTWBPeCoIUQvUQvcmVyY,5517
|
|
@@ -238,15 +240,15 @@ unique_toolkit/app/init_logging.py,sha256=Lv0FuEiUmxvtV2yovjD0gWNIvLdsi2xdMFeEiN
|
|
|
238
240
|
unique_toolkit/app/init_sdk.py,sha256=5_oDoETr6akwYyBCb0ivTdMNu3SVgPSkrXcDS6ELyY8,2269
|
|
239
241
|
unique_toolkit/app/performance/async_tasks.py,sha256=8Xv5kEmmFDJO7YyyBxv4e7bcNgq-3z_E2_4z1Yn9EqU,1970
|
|
240
242
|
unique_toolkit/app/performance/async_wrapper.py,sha256=yVVcRDkcdyfjsxro-N29SBvi-7773wnfDplef6-y8xw,1077
|
|
241
|
-
unique_toolkit/app/schemas.py,sha256=
|
|
242
|
-
unique_toolkit/app/unique_settings.py,sha256=
|
|
243
|
+
unique_toolkit/app/schemas.py,sha256=NWaj7cpNiXaxU6W-U-bw911cdpXjqsbSUGeVoN4Q3Js,16534
|
|
244
|
+
unique_toolkit/app/unique_settings.py,sha256=nN_5PxBepHXUSd3yL2r7Ex1cVUf8r79uvRk2qa9exh0,25079
|
|
243
245
|
unique_toolkit/app/verification.py,sha256=GxFFwcJMy25fCA_Xe89wKW7bgqOu8PAs5y8QpHF0GSc,3861
|
|
244
246
|
unique_toolkit/app/webhook.py,sha256=evpxLDnvz7P3D7-TV1XBkl8WcoldXpjOkw3tvFRxHr0,2368
|
|
245
247
|
unique_toolkit/chat/__init__.py,sha256=N9RubtxWN7UF0DlxP7YgeNTgjjk6p7AwkbGaVvuZCv0,938
|
|
246
248
|
unique_toolkit/chat/cancellation.py,sha256=HvGZK-daCMSr0M0AnvMY3EBPH1N_UqQPfrbTjwr8owk,5645
|
|
247
249
|
unique_toolkit/chat/constants.py,sha256=05kq6zjqUVB2d6_P7s-90nbljpB3ryxwCI-CAz0r2O4,83
|
|
248
250
|
unique_toolkit/chat/deprecated/service.py,sha256=8_XoopUWHT396Z_5gwMmsI6v4NGVgQirSJCYUW4Gx8c,9339
|
|
249
|
-
unique_toolkit/chat/functions.py,sha256=
|
|
251
|
+
unique_toolkit/chat/functions.py,sha256=8PXqo4X2BJhsbHkD9X5Ykqz-iVqbRJ1UlWuCNl1XSX8,52448
|
|
250
252
|
unique_toolkit/chat/rendering.py,sha256=c8YiV9oADRrJQ5A_QBJ4_UFc0NZ-2vVaa7tupoMusso,880
|
|
251
253
|
unique_toolkit/chat/responses_api.py,sha256=QtCOe3TI242N1JChhoFikxUCvGY6xfTvSmaE9Ta8HSM,19811
|
|
252
254
|
unique_toolkit/chat/schemas.py,sha256=l-Epugu27RoajiX5OkFO-BrVNey-wfTmaXiEmNNmG7s,7396
|
|
@@ -256,8 +258,8 @@ unique_toolkit/chat/utils.py,sha256=CsD9IER2gA1IOV0fmUOl-N0LmKvA7JP9dGrOqeOY0Gg,
|
|
|
256
258
|
unique_toolkit/content/__init__.py,sha256=nnQDfnNTEvI8-3dgWvIojoFDYU7edwd8Kloi6lMDG0M,1586
|
|
257
259
|
unique_toolkit/content/constants.py,sha256=1iy4Y67xobl5VTnJB6SxSyuoBWbdLl9244xfVMUZi5o,60
|
|
258
260
|
unique_toolkit/content/functions.py,sha256=avnlEQ1FkVz2NTbXUkafU04jzygqOJtUMQL605rEL4c,34019
|
|
259
|
-
unique_toolkit/content/schemas.py,sha256=
|
|
260
|
-
unique_toolkit/content/service.py,sha256=
|
|
261
|
+
unique_toolkit/content/schemas.py,sha256=AmnlqMpA_JgbgsaZF6Xdy8kt9lcY0YCqlfqpG1tYWeE,11306
|
|
262
|
+
unique_toolkit/content/service.py,sha256=S_sFtG1hJd-zz7XyP-6Gu-B8_Xx-r5v46qZLWdRRyRs,29477
|
|
261
263
|
unique_toolkit/content/smart_rules.py,sha256=9GlHXm63POTi4jy5hW0qUjeqy-JSeL1wIbURM1GKhc4,11481
|
|
262
264
|
unique_toolkit/content/utils.py,sha256=keDkqu_ZzQY0y_g7g_XLOza3p4XsvfqVVDI9ylM91KY,10115
|
|
263
265
|
unique_toolkit/data_extraction/README.md,sha256=5KxzqPHC29wxBiWJ-87wBQisSgRBkuSnPTb38pGH1wA,3138
|
|
@@ -383,7 +385,7 @@ unique_toolkit/language_model/infos.py,sha256=V3gKj4DyZwapbLAzDBPjw2D8LlWY9UaSAP
|
|
|
383
385
|
unique_toolkit/language_model/prompt.py,sha256=JSawaLjQg3VR-E2fK8engFyJnNdk21zaO8pPIodzN4Q,3991
|
|
384
386
|
unique_toolkit/language_model/reference.py,sha256=T3wr2jP_uRg5wKVIbKqLbxJlcgxfbZQGq3XdjbQ2kSo,6984
|
|
385
387
|
unique_toolkit/language_model/schemas.py,sha256=JZbIT3w1cj5fKrYaQ55X7sjXmCo6i_GqgJ198V3RXSg,29474
|
|
386
|
-
unique_toolkit/language_model/service.py,sha256=
|
|
388
|
+
unique_toolkit/language_model/service.py,sha256=hDoJBBgG_wWs8WuC_c8tnmK8cNu8o5EhJJXRvgwhkFQ,11956
|
|
387
389
|
unique_toolkit/language_model/settings.py,sha256=xkoMv3ATb2ft5V3MA8JvqW-EO8AnZ5t-6rvdbTx6lFU,1490
|
|
388
390
|
unique_toolkit/language_model/stream_transform.py,sha256=iNNGpLY_7G6Bpp9Y4KtbIkQm3WB4yZt75BXcqx0DVkI,2775
|
|
389
391
|
unique_toolkit/language_model/utils.py,sha256=bPQ4l6_YO71w-zaIPanUUmtbXC1_hCvLK0tAFc3VCRc,1902
|
|
@@ -394,16 +396,16 @@ unique_toolkit/monitoring/registry.py,sha256=8r9jqaQoRHZveGRZe_GQvBzvQpmUV4cpw8E
|
|
|
394
396
|
unique_toolkit/protocols/support.py,sha256=x5edzbBmKAUuvm3oLFh52gkgQsqR5LU7M0t8RHK0DZk,5161
|
|
395
397
|
unique_toolkit/services/__init__.py,sha256=b9Wl7Wvz1JmZDbDexIZzBoXZ0wscXuczGAH8LoL-Qak,572
|
|
396
398
|
unique_toolkit/services/chat_service.py,sha256=mh9lZr_AiNR0JSdiEU4kh2vkh5YQG4tASlQIRpeeEQI,95567
|
|
397
|
-
unique_toolkit/services/factory.py,sha256=
|
|
398
|
-
unique_toolkit/services/knowledge_base.py,sha256=
|
|
399
|
+
unique_toolkit/services/factory.py,sha256=7gNeanyHkgX23Iz7RMCQTCkE9gI5asCI11nXxM0jjx4,9832
|
|
400
|
+
unique_toolkit/services/knowledge_base.py,sha256=a9itNRxIrGDIuXkLiTLBsA-m2ncy8F8DwCLCXtWm_GY,43446
|
|
399
401
|
unique_toolkit/short_term_memory/__init__.py,sha256=2mI3AUrffgH7Yt-xS57EGqnHf7jnn6xquoKEhJqk3Wg,185
|
|
400
402
|
unique_toolkit/short_term_memory/constants.py,sha256=698CL6-wjup2MvU19RxSmQk3gX7aqW_OOpZB7sbz_Xg,34
|
|
401
403
|
unique_toolkit/short_term_memory/functions.py,sha256=mbEeWkJ5Jr0cvg1_m6l9aS1L6nWE5ZhviNzpKlCs-a8,7907
|
|
402
404
|
unique_toolkit/short_term_memory/schemas.py,sha256=C6gopsnuIgWJBG7XF87gxMwzLJtqbSGmsKXUf2h1sn4,1666
|
|
403
|
-
unique_toolkit/short_term_memory/service.py,sha256=
|
|
405
|
+
unique_toolkit/short_term_memory/service.py,sha256=2JMBEBn6GoyK-a0xvdcWpPft-3C74xZ1hckAzj97n4M,9264
|
|
404
406
|
unique_toolkit/smart_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
405
407
|
unique_toolkit/smart_rules/compile.py,sha256=vRe0aMJWuVIK-VsqomgxQImzke7MDmwgSxxJfYCa7zw,1386
|
|
406
408
|
unique_toolkit/test_utilities/events.py,sha256=FLrhMh0A_mQutAUjoD0FdMcVQ4Gq31r35OVGzRjvLro,6760
|
|
407
|
-
unique_toolkit-2026.28.0.
|
|
408
|
-
unique_toolkit-2026.28.0.
|
|
409
|
-
unique_toolkit-2026.28.0.
|
|
409
|
+
unique_toolkit-2026.28.0.dev8.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
410
|
+
unique_toolkit-2026.28.0.dev8.dist-info/METADATA,sha256=v9-siqdK8nGyMVGx7bXMB2dX4Z3RTGeS7KZZd4v069U,7427
|
|
411
|
+
unique_toolkit-2026.28.0.dev8.dist-info/RECORD,,
|
|
File without changes
|