unique-web-search 1.9.0__py3-none-any.whl → 1.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -35,6 +35,7 @@ from unique_web_search.services.executors.configs import (
35
35
  WebSearchV2Config,
36
36
  get_default_web_search_mode_config,
37
37
  )
38
+ from unique_web_search.services.query_elicitation import QueryElicitationConfig
38
39
  from unique_web_search.services.search_engine import (
39
40
  get_default_search_engine_config,
40
41
  get_search_engine_config_types_from_names,
@@ -75,7 +76,11 @@ class AnswerGenerationConfig(BaseModel):
75
76
  )
76
77
 
77
78
 
78
- class ExperimentalFeatures(FeatureExtendedSourceSerialization): ...
79
+ class ExperimentalFeatures(FeatureExtendedSourceSerialization):
80
+ query_elicitation_config: QueryElicitationConfig = Field(
81
+ default_factory=QueryElicitationConfig,
82
+ description="Query elicitation configuration",
83
+ )
79
84
 
80
85
 
81
86
  class WebSearchConfig(BaseToolConfig):
@@ -158,7 +163,11 @@ class WebSearchConfig(BaseToolConfig):
158
163
  description="Tool format information for system prompt. This is used to format the tool response for the system prompt.",
159
164
  )
160
165
 
161
- experimental_features: SkipJsonSchema[ExperimentalFeatures] = ExperimentalFeatures()
166
+ experimental_features: ExperimentalFeatures = Field(
167
+ default_factory=ExperimentalFeatures,
168
+ description="Experimental features",
169
+ title="Experimental Features",
170
+ )
162
171
 
163
172
  debug: bool = Field(
164
173
  default=False,
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from time import time
2
3
 
3
4
  from typing_extensions import override
@@ -10,31 +11,32 @@ from unique_toolkit.agentic.tools.tool import (
10
11
  Tool,
11
12
  )
12
13
  from unique_toolkit.agentic.tools.tool_progress_reporter import ProgressState
13
- from unique_toolkit.chat.schemas import (
14
- MessageLog,
15
- MessageLogDetails,
16
- MessageLogEvent,
17
- MessageLogStatus,
18
- )
19
- from unique_toolkit.content import ContentReference
20
14
  from unique_toolkit.language_model.schemas import (
21
15
  LanguageModelFunction,
22
16
  LanguageModelToolDescription,
23
17
  )
24
18
 
25
19
  from unique_web_search.config import WebSearchConfig
26
- from unique_web_search.schema import StepType, WebSearchPlan, WebSearchToolParameters
20
+ from unique_web_search.schema import WebSearchPlan, WebSearchToolParameters
27
21
  from unique_web_search.services.content_processing import ContentProcessor, WebPageChunk
28
22
  from unique_web_search.services.crawlers import get_crawler_service
29
23
  from unique_web_search.services.executors import (
30
24
  WebSearchV1Executor,
31
25
  WebSearchV2Executor,
32
26
  )
33
- from unique_web_search.services.executors.base_executor import WebSearchLogEntry
34
27
  from unique_web_search.services.executors.configs import WebSearchMode
28
+ from unique_web_search.services.executors.context import (
29
+ ExecutorCallbacks,
30
+ ExecutorConfiguration,
31
+ ExecutorServiceContext,
32
+ )
33
+ from unique_web_search.services.message_log import WebSearchMessageLogger
34
+ from unique_web_search.services.query_elicitation import QueryElicitationService
35
35
  from unique_web_search.services.search_engine import get_search_engine_service
36
36
  from unique_web_search.utils import WebSearchDebugInfo, reduce_sources_to_token_limit
37
37
 
38
+ _LOGGER = logging.getLogger(__name__)
39
+
38
40
 
39
41
  class WebSearchTool(Tool[WebSearchConfig]):
40
42
  name = "WebSearch"
@@ -59,7 +61,6 @@ class WebSearchTool(Tool[WebSearchConfig]):
59
61
  )
60
62
  self.debug = self.config.debug
61
63
  self._display_name = kwargs.get("display_name", "Web Search")
62
- self._active_message_log: MessageLog | None = None
63
64
 
64
65
  def content_reducer(web_page_chunks: list[WebPageChunk]) -> list[WebPageChunk]:
65
66
  return reduce_sources_to_token_limit(
@@ -106,35 +107,37 @@ class WebSearchTool(Tool[WebSearchConfig]):
106
107
 
107
108
  @override
108
109
  async def run(self, tool_call: LanguageModelFunction) -> ToolCallResponse:
109
- self.logger.info("Running the WebSearch tool")
110
+ _LOGGER.info("Running the WebSearch tool")
110
111
  start_time = time()
111
112
  parameters = self.tool_parameter_calls.model_validate(
112
113
  tool_call.arguments,
113
114
  )
114
115
 
115
116
  debug_info = WebSearchDebugInfo(parameters=parameters.model_dump())
116
- executor = self._get_executor(tool_call, parameters, debug_info)
117
+
118
+ web_search_message_logger = WebSearchMessageLogger(
119
+ message_step_logger=self._message_step_logger,
120
+ tool_display_name=self.display_name(),
121
+ )
122
+ executor = self._get_executor(
123
+ tool_call, parameters, debug_info, web_search_message_logger
124
+ )
125
+
126
+ notify_from_tool_call = self._ff_tool_progress_reporter_callback()
117
127
 
118
128
  try:
119
- content_chunks, queries_for_log = await executor.run()
129
+ content_chunks = await executor.run()
120
130
  debug_info.num_chunks_in_final_prompts = len(content_chunks)
121
131
  debug_info.execution_time = time() - start_time
122
132
 
123
- self._active_message_log = self.create_or_update_active_message_log(
124
- queries_for_log=queries_for_log,
125
- status=MessageLogStatus.COMPLETED,
126
- )
133
+ await web_search_message_logger.finished()
127
134
 
128
- if (
129
- not feature_flags.is_new_answers_ui_enabled(self.company_id)
130
- and self.tool_progress_reporter
131
- ):
132
- await self.tool_progress_reporter.notify_from_tool_call(
133
- tool_call=tool_call,
134
- name=executor.notify_name,
135
- message=executor.notify_message,
136
- state=ProgressState.FINISHED,
137
- )
135
+ await notify_from_tool_call(
136
+ tool_call=tool_call,
137
+ name=executor.notify_name,
138
+ message=executor.notify_message,
139
+ state=ProgressState.FINISHED,
140
+ )
138
141
 
139
142
  return ToolCallResponse(
140
143
  id=tool_call.id, # type: ignore
@@ -143,22 +146,16 @@ class WebSearchTool(Tool[WebSearchConfig]):
143
146
  content_chunks=content_chunks,
144
147
  )
145
148
  except Exception as e:
146
- self.logger.exception(f"Error executing WebSearch tool: {e}")
149
+ _LOGGER.exception(f"Error executing WebSearch tool: {e}")
147
150
 
148
- self._active_message_log = self.create_or_update_active_message_log(
149
- status=MessageLogStatus.COMPLETED,
150
- )
151
+ await web_search_message_logger.failed()
151
152
 
152
- if (
153
- not feature_flags.is_new_answers_ui_enabled(self.company_id)
154
- and self.tool_progress_reporter
155
- ):
156
- await self.tool_progress_reporter.notify_from_tool_call(
157
- tool_call=tool_call,
158
- name=executor.notify_name,
159
- message=executor.notify_message,
160
- state=ProgressState.FAILED,
161
- )
153
+ await notify_from_tool_call(
154
+ tool_call=tool_call,
155
+ name=executor.notify_name,
156
+ message=executor.notify_message,
157
+ state=ProgressState.FAILED,
158
+ )
162
159
 
163
160
  return ToolCallResponse(
164
161
  id=tool_call.id, # type: ignore
@@ -172,63 +169,59 @@ class WebSearchTool(Tool[WebSearchConfig]):
172
169
  tool_call: LanguageModelFunction,
173
170
  parameters: WebSearchPlan | WebSearchToolParameters,
174
171
  debug_info: WebSearchDebugInfo,
172
+ web_search_message_logger: WebSearchMessageLogger,
175
173
  ) -> WebSearchV1Executor | WebSearchV2Executor:
176
- # Create callback that wraps the service's create_or_update_active_message_log method
177
- def message_log_callback(
178
- *,
179
- progress_message: str | None = None,
180
- queries_for_log: list[WebSearchLogEntry] | list[str] | None = None,
181
- status: MessageLogStatus | None = None,
182
- ) -> MessageLog | None:
183
- return self.create_or_update_active_message_log(
184
- progress_message=progress_message,
185
- queries_for_log=queries_for_log,
186
- status=status,
187
- )
174
+ # Initialize query elicitation service and get callbacks
175
+ elicitation_service = QueryElicitationService(
176
+ chat_service=self._chat_service,
177
+ display_name=self.display_name(),
178
+ config=self.config.experimental_features.query_elicitation_config,
179
+ )
180
+
181
+ # Build context objects
182
+ services = ExecutorServiceContext(
183
+ search_engine_service=self.search_engine_service,
184
+ crawler_service=self.crawler_service,
185
+ content_processor=self.content_processor,
186
+ language_model_service=self.language_model_service,
187
+ chunk_relevancy_sorter=self.chunk_relevancy_sorter,
188
+ )
189
+
190
+ config = ExecutorConfiguration(
191
+ language_model=self.language_model,
192
+ chunk_relevancy_sort_config=self.config.chunk_relevancy_sort_config,
193
+ company_id=self.company_id,
194
+ debug_info=debug_info,
195
+ )
196
+
197
+ callbacks = ExecutorCallbacks(
198
+ message_log_callback=web_search_message_logger,
199
+ content_reducer=self.content_reducer,
200
+ query_elicitation=elicitation_service,
201
+ tool_progress_reporter=self._ff_tool_progress_reporter(),
202
+ )
188
203
 
189
204
  if isinstance(parameters, WebSearchPlan):
190
205
  assert self.config.web_search_mode_config.mode == WebSearchMode.V2
191
206
  return WebSearchV2Executor(
192
- search_service=self.search_engine_service,
193
- language_model_service=self.language_model_service,
194
- language_model=self.language_model,
195
- crawler_service=self.crawler_service,
207
+ services=services,
208
+ config=config,
209
+ callbacks=callbacks,
196
210
  tool_call=tool_call,
197
211
  tool_parameters=parameters,
198
- company_id=self.company_id,
199
- content_processor=self.content_processor,
200
- chunk_relevancy_sorter=self.chunk_relevancy_sorter,
201
- chunk_relevancy_sort_config=self.config.chunk_relevancy_sort_config,
202
- tool_progress_reporter=self.tool_progress_reporter
203
- if not feature_flags.is_new_answers_ui_enabled(self.company_id)
204
- else None,
205
- content_reducer=self.content_reducer,
206
212
  max_steps=self.config.web_search_mode_config.max_steps,
207
- debug_info=debug_info,
208
- message_log_callback=message_log_callback,
209
213
  )
210
214
  elif isinstance(parameters, WebSearchToolParameters):
211
215
  assert self.config.web_search_mode_config.mode == WebSearchMode.V1
212
216
  return WebSearchV1Executor(
213
- search_service=self.search_engine_service,
214
- language_model_service=self.language_model_service,
215
- language_model=self.language_model,
216
- crawler_service=self.crawler_service,
217
+ services=services,
218
+ config=config,
219
+ callbacks=callbacks,
217
220
  tool_call=tool_call,
218
221
  tool_parameters=parameters,
219
- company_id=self.company_id,
222
+ refine_query_system_prompt=self.config.web_search_mode_config.refine_query_mode.system_prompt,
220
223
  mode=self.config.web_search_mode_config.refine_query_mode.mode,
221
224
  max_queries=self.config.web_search_mode_config.max_queries,
222
- content_processor=self.content_processor,
223
- chunk_relevancy_sorter=self.chunk_relevancy_sorter,
224
- chunk_relevancy_sort_config=self.config.chunk_relevancy_sort_config,
225
- tool_progress_reporter=self.tool_progress_reporter
226
- if not feature_flags.is_new_answers_ui_enabled(self.company_id)
227
- else None,
228
- content_reducer=self.content_reducer,
229
- refine_query_system_prompt=self.config.web_search_mode_config.refine_query_mode.system_prompt,
230
- debug_info=debug_info,
231
- message_log_callback=message_log_callback,
232
225
  )
233
226
  else:
234
227
  raise ValueError(f"Invalid parameters: {parameters}")
@@ -244,65 +237,29 @@ class WebSearchTool(Tool[WebSearchConfig]):
244
237
  return []
245
238
  return evaluation_check_list
246
239
 
247
- def _prepare_message_logs_entries(
248
- self, queries_for_log: list[WebSearchLogEntry] | list[str]
249
- ) -> tuple[MessageLogDetails, list[ContentReference]]:
250
- # Handle list of strings (query strings only)
251
- if queries_for_log and isinstance(queries_for_log[0], str):
252
- queries_for_log = [
253
- WebSearchLogEntry(
254
- type=StepType.SEARCH,
255
- message=query,
256
- web_search_results=[],
257
- )
258
- for query in queries_for_log
259
- ]
260
-
261
- details = MessageLogDetails(
262
- data=[
263
- MessageLogEvent(
264
- type="WebSearch",
265
- text=query_for_log.message,
240
+ def _ff_tool_progress_reporter(self):
241
+ if not feature_flags.enable_new_answers_ui_un_14411.is_enabled(self.company_id):
242
+ return self.tool_progress_reporter
243
+ return None
244
+
245
+ def _ff_tool_progress_reporter_callback(self):
246
+ async def notify_from_tool_call(
247
+ tool_call: LanguageModelFunction,
248
+ name: str,
249
+ message: str,
250
+ state: ProgressState,
251
+ ):
252
+ if (
253
+ not feature_flags.enable_new_answers_ui_un_14411.is_enabled(
254
+ self.company_id
266
255
  )
267
- for query_for_log in queries_for_log
268
- ]
269
- )
270
- references = []
271
- sequence_number = 0
272
- for query_for_log in queries_for_log:
273
- for web_search_result in query_for_log.web_search_results:
274
- references.append(
275
- web_search_result.to_content_reference(sequence_number)
256
+ and self.tool_progress_reporter is not None
257
+ ):
258
+ await self.tool_progress_reporter.notify_from_tool_call(
259
+ tool_call, name, message, state
276
260
  )
277
- sequence_number += 1
278
-
279
- return details, references
280
261
 
281
- def create_or_update_active_message_log(
282
- self,
283
- *,
284
- progress_message: str | None = None,
285
- queries_for_log: list[WebSearchLogEntry] | list[str] | None = None,
286
- status: MessageLogStatus | None = None,
287
- ) -> MessageLog | None:
288
- details = MessageLogDetails(data=[])
289
- reference_list = []
290
- if queries_for_log is not None:
291
- details, reference_list = self._prepare_message_logs_entries(
292
- queries_for_log
293
- )
294
-
295
- self._active_message_log = (
296
- self._message_step_logger.create_or_update_message_log(
297
- active_message_log=self._active_message_log,
298
- header=self._display_name,
299
- progress_message=progress_message,
300
- details=details,
301
- references=reference_list,
302
- **({"status": status} if status is not None else {}),
303
- )
304
- )
305
- return self._active_message_log
262
+ return notify_from_tool_call
306
263
 
307
264
 
308
265
  ToolFactory.register_tool(WebSearchTool, WebSearchConfig)
@@ -1,3 +1,8 @@
1
+ from unique_web_search.services.executors.context import (
2
+ ExecutorCallbacks,
3
+ ExecutorConfiguration,
4
+ ExecutorServiceContext,
5
+ )
1
6
  from unique_web_search.services.executors.web_search_v1_executor import (
2
7
  WebSearchV1Executor,
3
8
  )
@@ -5,4 +10,10 @@ from unique_web_search.services.executors.web_search_v2_executor import (
5
10
  WebSearchV2Executor,
6
11
  )
7
12
 
8
- __all__ = ["WebSearchV1Executor", "WebSearchV2Executor"]
13
+ __all__ = [
14
+ "WebSearchV1Executor",
15
+ "WebSearchV2Executor",
16
+ "ExecutorServiceContext",
17
+ "ExecutorConfiguration",
18
+ "ExecutorCallbacks",
19
+ ]
@@ -1,87 +1,65 @@
1
1
  import logging
2
2
  from abc import ABC, abstractmethod
3
3
  from time import time
4
- from typing import Callable, Optional, Protocol
5
4
 
6
- from pydantic import BaseModel
7
- from unique_toolkit import LanguageModelService
8
- from unique_toolkit._common.chunk_relevancy_sorter.config import (
9
- ChunkRelevancySortConfig,
10
- )
11
- from unique_toolkit._common.chunk_relevancy_sorter.service import ChunkRelevancySorter
12
- from unique_toolkit._common.validators import LMI
5
+ from unique_toolkit.agentic.feature_flags import feature_flags
13
6
  from unique_toolkit.agentic.tools.tool_progress_reporter import (
14
7
  ProgressState,
15
- ToolProgressReporter,
16
8
  )
17
- from unique_toolkit.chat.schemas import MessageLog, MessageLogStatus
18
9
  from unique_toolkit.content import ContentChunk
19
10
  from unique_toolkit.language_model import LanguageModelFunction
20
11
 
21
- from unique_web_search.schema import StepType, WebSearchPlan, WebSearchToolParameters
22
- from unique_web_search.services.content_processing import ContentProcessor, WebPageChunk
23
- from unique_web_search.services.crawlers import CrawlerTypes
24
- from unique_web_search.services.search_engine import SearchEngineTypes
12
+ from unique_web_search.schema import WebSearchPlan, WebSearchToolParameters
13
+ from unique_web_search.services.content_processing import WebPageChunk
14
+ from unique_web_search.services.executors.context import (
15
+ ExecutorCallbacks,
16
+ ExecutorConfiguration,
17
+ ExecutorServiceContext,
18
+ )
25
19
  from unique_web_search.services.search_engine.schema import (
26
20
  WebSearchResult,
27
21
  )
28
- from unique_web_search.utils import StepDebugInfo, WebSearchDebugInfo
22
+ from unique_web_search.utils import StepDebugInfo
29
23
 
30
24
  _LOGGER = logging.getLogger(__name__)
31
25
 
32
26
 
33
- class WebSearchLogEntry(BaseModel):
34
- type: StepType
35
- message: str
36
- web_search_results: list[WebSearchResult]
37
-
38
-
39
- class MessageLogCallback(Protocol):
40
- def __call__(
41
- self,
42
- *,
43
- progress_message: str | None = None,
44
- queries_for_log: list[WebSearchLogEntry] | list[str] | None = None,
45
- status: MessageLogStatus | None = None,
46
- ) -> MessageLog | None: ...
47
-
48
-
49
27
  class BaseWebSearchExecutor(ABC):
50
28
  def __init__(
51
29
  self,
52
- search_service: SearchEngineTypes,
53
- language_model_service: LanguageModelService,
54
- language_model: LMI,
55
- crawler_service: CrawlerTypes,
30
+ services: ExecutorServiceContext,
31
+ config: ExecutorConfiguration,
32
+ callbacks: ExecutorCallbacks,
56
33
  tool_call: LanguageModelFunction,
57
34
  tool_parameters: WebSearchPlan | WebSearchToolParameters,
58
- company_id: str,
59
- content_processor: ContentProcessor,
60
- message_log_callback: MessageLogCallback,
61
- chunk_relevancy_sorter: ChunkRelevancySorter | None,
62
- chunk_relevancy_sort_config: ChunkRelevancySortConfig,
63
- debug_info: WebSearchDebugInfo,
64
- content_reducer: Callable[[list[WebPageChunk]], list[WebPageChunk]],
65
- tool_progress_reporter: Optional[ToolProgressReporter] = None,
66
35
  ):
67
- self.company_id = company_id
68
- self.search_service = search_service
69
- self.crawler_service = crawler_service
70
- self.language_model_service = language_model_service
71
- self.tool_progress_reporter = tool_progress_reporter
72
- self.language_model = language_model
73
- self.content_processor = content_processor
74
- self.chunk_relevancy_sorter = chunk_relevancy_sorter
75
- self.chunk_relevancy_sort_config = chunk_relevancy_sort_config
36
+ # Extract from service context
37
+ self.search_service = services.search_engine_service
38
+ self.crawler_service = services.crawler_service
39
+ self.content_processor = services.content_processor
40
+ self.language_model_service = services.language_model_service
41
+ self.chunk_relevancy_sorter = services.chunk_relevancy_sorter
42
+
43
+ # Extract from configuration
44
+ self.language_model = config.language_model
45
+ self.chunk_relevancy_sort_config = config.chunk_relevancy_sort_config
46
+ self.company_id = config.company_id
47
+ self.debug_info = config.debug_info
48
+
49
+ # Extract from callbacks
50
+ self._message_log_callback = callbacks.message_log_callback
51
+ self.content_reducer = callbacks.content_reducer
52
+ self.query_elicitation = callbacks.query_elicitation
53
+ self.tool_progress_reporter = callbacks.tool_progress_reporter
54
+
55
+ # Store tool parameters
76
56
  self.tool_call = tool_call
77
57
  self.tool_parameters = tool_parameters
78
- self.content_reducer = content_reducer
58
+
59
+ # Initialize notification state
79
60
  self._notify_name = ""
80
61
  self._notify_message = ""
81
62
 
82
- self.debug_info = debug_info
83
- self._message_log_callback = message_log_callback
84
-
85
63
  async def notify_callback() -> None:
86
64
  _LOGGER.debug(f"{self.notify_name}: {self.notify_message}")
87
65
  if self.tool_progress_reporter:
@@ -111,9 +89,7 @@ class BaseWebSearchExecutor(ABC):
111
89
  self._notify_message = value
112
90
 
113
91
  @abstractmethod
114
- async def run(
115
- self,
116
- ) -> tuple[list[ContentChunk], list[WebSearchLogEntry]]:
92
+ async def run(self) -> list[ContentChunk]:
117
93
  raise NotImplementedError("Subclasses must implement this method.")
118
94
 
119
95
  async def _content_processing(
@@ -167,3 +143,12 @@ class BaseWebSearchExecutor(ABC):
167
143
  return sorted_chunks.content_chunks
168
144
  else:
169
145
  return content
146
+
147
+ async def _ff_elicitate_queries(self, queries: list[str]) -> list[str]:
148
+ if not feature_flags.enable_elicitation_un_15809.is_enabled(self.company_id):
149
+ return queries
150
+
151
+ # Create a query elicitation
152
+ elicitation = await self.query_elicitation(queries)
153
+
154
+ return elicitation
@@ -0,0 +1,104 @@
1
+ """Context classes for executor dependency injection.
2
+
3
+ This module provides container classes that group related dependencies
4
+ for web search executors, reducing parameter redundancy in __init__ methods.
5
+ """
6
+
7
+ from dataclasses import dataclass
8
+ from typing import Optional, Protocol
9
+
10
+ from unique_toolkit import LanguageModelService
11
+ from unique_toolkit._common.chunk_relevancy_sorter.config import (
12
+ ChunkRelevancySortConfig,
13
+ )
14
+ from unique_toolkit._common.chunk_relevancy_sorter.service import ChunkRelevancySorter
15
+ from unique_toolkit._common.validators import LMI
16
+ from unique_toolkit.agentic.tools.tool_progress_reporter import (
17
+ ToolProgressReporter,
18
+ )
19
+
20
+ from unique_web_search.services.content_processing import ContentProcessor, WebPageChunk
21
+ from unique_web_search.services.crawlers import CrawlerTypes
22
+ from unique_web_search.services.search_engine import SearchEngineTypes
23
+ from unique_web_search.services.search_engine.schema import WebSearchResult
24
+ from unique_web_search.utils import WebSearchDebugInfo
25
+
26
+
27
+ @dataclass
28
+ class ExecutorServiceContext:
29
+ """Container for all service dependencies used by executors.
30
+
31
+ Groups together all the external services that executors depend on,
32
+ making it easier to pass dependencies and reducing parameter redundancy.
33
+
34
+ Attributes:
35
+ search_service: Service for performing web searches
36
+ crawler_service: Service for crawling and extracting web page content
37
+ content_processor: Service for processing and analyzing content
38
+ language_model_service: Service for language model operations
39
+ chunk_relevancy_sorter: Optional service for sorting content chunks by relevance
40
+ """
41
+
42
+ search_engine_service: SearchEngineTypes
43
+ crawler_service: CrawlerTypes
44
+ content_processor: ContentProcessor
45
+ language_model_service: LanguageModelService
46
+ chunk_relevancy_sorter: ChunkRelevancySorter | None
47
+
48
+
49
+ @dataclass
50
+ class ExecutorConfiguration:
51
+ """Container for all configuration parameters used by executors.
52
+
53
+ Groups together all configuration values and metadata that executors need,
54
+ providing a clean separation between services and configuration.
55
+
56
+ Attributes:
57
+ language_model: Language model identifier and configuration
58
+ chunk_relevancy_sort_config: Configuration for chunk relevancy sorting
59
+ company_id: Identifier for the company/organization
60
+ debug_info: Container for debug information and metrics
61
+ """
62
+
63
+ language_model: LMI
64
+ chunk_relevancy_sort_config: ChunkRelevancySortConfig
65
+ company_id: str
66
+ debug_info: WebSearchDebugInfo
67
+
68
+
69
+ class ContentReducer(Protocol):
70
+ def __call__(self, web_page_chunks: list[WebPageChunk]) -> list[WebPageChunk]: ...
71
+
72
+
73
+ class MessageLogCallback(Protocol):
74
+ async def log_progress(self, progress_message: str) -> None: ...
75
+
76
+ async def log_queries(self, queries: list[str]) -> None: ...
77
+
78
+ async def log_web_search_results(
79
+ self, web_search_results: list[WebSearchResult]
80
+ ) -> None: ...
81
+
82
+
83
+ class QueryElicitationProtocol(Protocol):
84
+ async def __call__(self, queries: list[str]) -> list[str]: ...
85
+
86
+
87
+ @dataclass
88
+ class ExecutorCallbacks:
89
+ """Container for callback functions used by executors.
90
+
91
+ Groups together all callback functions and optional reporters,
92
+ making the callback interface clear and extensible.
93
+
94
+ Attributes:
95
+ message_log_callback: Callback for logging messages and progress
96
+ content_reducer: Function to reduce content chunks based on token limits
97
+ query_elicitation: Function to elicit queries from the user
98
+ tool_progress_reporter: Optional reporter for tool execution progress
99
+ """
100
+
101
+ message_log_callback: MessageLogCallback
102
+ content_reducer: ContentReducer
103
+ query_elicitation: QueryElicitationProtocol
104
+ tool_progress_reporter: Optional[ToolProgressReporter] = None