unique_deep_research 3.2.0__tar.gz → 3.2.2__tar.gz

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.
Files changed (23) hide show
  1. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/CHANGELOG.md +6 -0
  2. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/PKG-INFO +7 -1
  3. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/pyproject.toml +1 -1
  4. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/service.py +34 -26
  5. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/LICENSE +0 -0
  6. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/README.md +0 -0
  7. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/__init__.py +0 -0
  8. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/config.py +0 -0
  9. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/markdown_utils.py +0 -0
  10. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/templates/clarifying_agent.j2 +0 -0
  11. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/templates/openai/oai_research_system_message.j2 +0 -0
  12. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/templates/report_cleanup_prompt.j2 +0 -0
  13. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/templates/research_instructions_agent.j2 +0 -0
  14. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/templates/unique/compress_research_system.j2 +0 -0
  15. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/templates/unique/lead_agent_system.j2 +0 -0
  16. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/templates/unique/report_writer_system_open_deep_research.j2 +0 -0
  17. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/templates/unique/research_agent_system.j2 +0 -0
  18. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/unique_custom/__init__.py +0 -0
  19. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/unique_custom/agents.py +0 -0
  20. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/unique_custom/citation.py +0 -0
  21. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/unique_custom/state.py +0 -0
  22. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/unique_custom/tools.py +0 -0
  23. {unique_deep_research-3.2.0 → unique_deep_research-3.2.2}/unique_deep_research/unique_custom/utils.py +0 -0
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.2.2] - 2026-02-05
9
+ - Fix bug where deep research tool was not using the correct headers causing an authentication error
10
+
11
+ ## [3.2.1] - 2026-02-05
12
+ - Use deep research logger instead of tool logger
13
+
8
14
  ## [3.2.0] - 2026-02-03
9
15
  - Use a backwards compatible config style
10
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: unique_deep_research
3
- Version: 3.2.0
3
+ Version: 3.2.2
4
4
  Summary: Deep Research Tool for complex research tasks
5
5
  License: Proprietary
6
6
  Author: Martin Fadler
@@ -36,6 +36,12 @@ All notable changes to this project will be documented in this file.
36
36
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
37
37
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
38
38
 
39
+ ## [3.2.2] - 2026-02-05
40
+ - Fix bug where deep research tool was not using the correct headers causing an authentication error
41
+
42
+ ## [3.2.1] - 2026-02-05
43
+ - Use deep research logger instead of tool logger
44
+
39
45
  ## [3.2.0] - 2026-02-03
40
46
  - Use a backwards compatible config style
41
47
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "unique_deep_research"
3
- version = "3.2.0"
3
+ version = "3.2.2"
4
4
  description = "Deep Research Tool for complex research tasks"
5
5
  authors = [
6
6
  "Martin Fadler <martin.fadler@unique.ch>",
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  from typing import Any, Optional
2
3
 
3
4
  from httpx import AsyncClient
@@ -65,6 +66,8 @@ from .unique_custom.utils import (
65
66
  get_next_message_order,
66
67
  )
67
68
 
69
+ _LOGGER = logging.getLogger(__name__)
70
+
68
71
 
69
72
  class DeepResearchToolInput(BaseModel):
70
73
  model_config = ConfigDict(extra="forbid")
@@ -107,9 +110,16 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
107
110
  self.company_id = event.company_id
108
111
  self.user_id = event.user_id
109
112
 
110
- self.client = get_async_openai_client()
113
+ self.client = get_async_openai_client(
114
+ additional_headers={
115
+ "x-company-id": self.company_id,
116
+ "x-user-id": self.user_id,
117
+ "x-assistant-id": self.event.payload.assistant_id,
118
+ "x-chat-id": self.chat_id,
119
+ }
120
+ )
111
121
 
112
- self.logger.info(f"Using async OpenAI client pointed to {self.client.base_url}")
122
+ _LOGGER.info(f"Using async OpenAI client pointed to {self.client.base_url}")
113
123
 
114
124
  self.content_service = ContentService(
115
125
  company_id=self.company_id,
@@ -207,7 +217,7 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
207
217
  except Exception as e:
208
218
  if self.is_message_execution():
209
219
  await self._update_execution_status(MessageExecutionUpdateStatus.FAILED)
210
- self.logger.exception(f"Deep Research tool run failed: {e}")
220
+ _LOGGER.exception(f"Deep Research tool run failed: {e}")
211
221
  await self.chat_service.modify_assistant_message_async(
212
222
  content="Deep Research failed to complete for an unknown reason",
213
223
  set_completed_at=True,
@@ -220,13 +230,13 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
220
230
  )
221
231
 
222
232
  async def _run(self, tool_call: LanguageModelFunction) -> ToolCallResponse:
223
- self.logger.info("Starting Deep Research tool run")
233
+ _LOGGER.info("Starting Deep Research tool run")
224
234
 
225
235
  await self._clear_original_message()
226
236
 
227
237
  # Question answer and message execution will have the same message id, so we need to check if it is a message execution
228
238
  if await self.is_followup_question_answer() and not self.is_message_execution():
229
- self.logger.info("This is a follow-up question answer")
239
+ _LOGGER.info("This is a follow-up question answer")
230
240
  self.chat_service.create_message_execution(
231
241
  message_id=self.event.payload.assistant_message.id,
232
242
  type=MessageExecutionType.DEEP_RESEARCH,
@@ -240,7 +250,7 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
240
250
  content="",
241
251
  )
242
252
  if self.is_message_execution():
243
- self.logger.info("Starting research")
253
+ _LOGGER.info("Starting research")
244
254
  # Run research
245
255
  self.write_message_log_text_message("**Generating research plan**")
246
256
  research_brief = await self.generate_research_brief_from_dict(
@@ -386,15 +396,15 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
386
396
  result = "", []
387
397
  match self.config.engine.get_type():
388
398
  case DeepResearchEngine.OPENAI:
389
- self.logger.info("Running OpenAI research")
399
+ _LOGGER.info("Running OpenAI research")
390
400
  result = await self.openai_research(research_brief)
391
401
  case DeepResearchEngine.UNIQUE:
392
- self.logger.info("Running Custom research")
402
+ _LOGGER.info("Running Custom research")
393
403
  result = await self.custom_research(research_brief)
394
404
  self.write_message_log_text_message("**Research done**")
395
405
  return result
396
406
  except Exception as e:
397
- self.logger.exception(f"Research failed: {e}")
407
+ _LOGGER.exception(f"Research failed: {e}")
398
408
  return "", []
399
409
 
400
410
  async def custom_research(self, research_brief: str) -> tuple[str, list[Any]]:
@@ -464,14 +474,14 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
464
474
  content=processed_result,
465
475
  references=references,
466
476
  )
467
- self.logger.info(
477
+ _LOGGER.info(
468
478
  f"Custom research completed with {len(references)} validated citations"
469
479
  )
470
480
  return processed_result, []
471
481
 
472
482
  except Exception as e:
473
483
  error_msg = f"Custom research failed: {str(e)}"
474
- self.logger.exception(error_msg)
484
+ _LOGGER.exception(error_msg)
475
485
  return error_msg, []
476
486
 
477
487
  async def openai_research(self, research_brief: str) -> tuple[str, list[Any]]:
@@ -553,14 +563,14 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
553
563
  match event.type:
554
564
  case "response.completed":
555
565
  if event.response.usage:
556
- self.logger.info(
566
+ _LOGGER.info(
557
567
  f"OpenAI research token usage: {event.response.usage}"
558
568
  )
559
569
  # Extract the final output with annotations
560
570
  if event.response.output and len(event.response.output) > 0:
561
571
  final_output = event.response.output[-1]
562
572
  if not isinstance(final_output, ResponseOutputMessage):
563
- self.logger.warning(
573
+ _LOGGER.warning(
564
574
  f"Unexpected output type: {type(final_output)}"
565
575
  )
566
576
  continue
@@ -573,9 +583,7 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
573
583
  # Extract final report and references
574
584
  report_text = content_item.text
575
585
  annotations = content_item.annotations or []
576
- self.logger.info(
577
- "Final report extracted from OpenAI stream"
578
- )
586
+ _LOGGER.info("Final report extracted from OpenAI stream")
579
587
  return report_text, annotations
580
588
  return event.response.output_text or "", []
581
589
  case "response.incomplete":
@@ -607,7 +615,7 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
607
615
  if isinstance(
608
616
  event.item.action, ActionSearch
609
617
  ) and isinstance(event.item.action.query, str):
610
- self.logger.info("OpenAI web search")
618
+ _LOGGER.info("OpenAI web search")
611
619
  self.chat_service.create_message_log(
612
620
  message_id=self.event.payload.assistant_message.id,
613
621
  text="**Searching the web**",
@@ -630,13 +638,13 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
630
638
  elif isinstance(
631
639
  event.item.action, ActionOpenPage
632
640
  ) or isinstance(event.item.action, ActionFind):
633
- self.logger.info("OpenAI reading web page")
641
+ _LOGGER.info("OpenAI reading web page")
634
642
  if (
635
643
  not event.item.action.url
636
644
  or not isinstance(event.item.action.url, str)
637
645
  or "https://" not in event.item.action.url
638
646
  ):
639
- self.logger.warning(
647
+ _LOGGER.warning(
640
648
  f"Invalid URL from OpenAI: {event.item.action}"
641
649
  )
642
650
  continue
@@ -646,12 +654,12 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
646
654
  event.item.action.url,
647
655
  )
648
656
  if not success:
649
- self.logger.info(
657
+ _LOGGER.info(
650
658
  f"Failed to crawl URL: {event.item.action.url} but openai still opened the page"
651
659
  )
652
660
  continue
653
661
  if not title:
654
- self.logger.info(
662
+ _LOGGER.info(
655
663
  f"No title found for URL: {event.item.action.url}"
656
664
  )
657
665
  continue
@@ -678,7 +686,7 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
678
686
  ),
679
687
  )
680
688
  else:
681
- self.logger.info(
689
+ _LOGGER.info(
682
690
  f"OpenAI web action unexpected type: {type(event.item)}"
683
691
  )
684
692
  case "response.failed":
@@ -699,9 +707,9 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
699
707
  if event.response.error:
700
708
  return event.response.error.message, []
701
709
  except Exception as e:
702
- self.logger.exception(f"Error processing research stream event: {e}")
710
+ _LOGGER.exception(f"Error processing research stream event: {e}")
703
711
 
704
- self.logger.error("Stream ended without completion")
712
+ _LOGGER.error("Stream ended without completion")
705
713
  return "", []
706
714
 
707
715
  async def _postprocess_report_with_gpt(self, research_result: str) -> str:
@@ -737,10 +745,10 @@ class DeepResearchTool(Tool[DeepResearchToolConfig]):
737
745
 
738
746
  formatted_result = response.choices[0].message.content
739
747
  if formatted_result:
740
- self.logger.info("Successfully post-processed research report")
748
+ _LOGGER.info("Successfully post-processed research report")
741
749
  return formatted_result
742
750
  else:
743
- self.logger.warning("Post-processing returned empty result, using original")
751
+ _LOGGER.warning("Post-processing returned empty result, using original")
744
752
  return research_result
745
753
 
746
754
  def get_tool_call_result_for_loop_history(