realtimex-deeptutor 0.5.0.post1__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.
Files changed (276) hide show
  1. realtimex_deeptutor/__init__.py +67 -0
  2. realtimex_deeptutor-0.5.0.post1.dist-info/METADATA +1612 -0
  3. realtimex_deeptutor-0.5.0.post1.dist-info/RECORD +276 -0
  4. realtimex_deeptutor-0.5.0.post1.dist-info/WHEEL +5 -0
  5. realtimex_deeptutor-0.5.0.post1.dist-info/entry_points.txt +2 -0
  6. realtimex_deeptutor-0.5.0.post1.dist-info/licenses/LICENSE +661 -0
  7. realtimex_deeptutor-0.5.0.post1.dist-info/top_level.txt +2 -0
  8. src/__init__.py +40 -0
  9. src/agents/__init__.py +24 -0
  10. src/agents/base_agent.py +657 -0
  11. src/agents/chat/__init__.py +24 -0
  12. src/agents/chat/chat_agent.py +435 -0
  13. src/agents/chat/prompts/en/chat_agent.yaml +35 -0
  14. src/agents/chat/prompts/zh/chat_agent.yaml +35 -0
  15. src/agents/chat/session_manager.py +311 -0
  16. src/agents/co_writer/__init__.py +0 -0
  17. src/agents/co_writer/edit_agent.py +260 -0
  18. src/agents/co_writer/narrator_agent.py +423 -0
  19. src/agents/co_writer/prompts/en/edit_agent.yaml +113 -0
  20. src/agents/co_writer/prompts/en/narrator_agent.yaml +88 -0
  21. src/agents/co_writer/prompts/zh/edit_agent.yaml +113 -0
  22. src/agents/co_writer/prompts/zh/narrator_agent.yaml +88 -0
  23. src/agents/guide/__init__.py +16 -0
  24. src/agents/guide/agents/__init__.py +11 -0
  25. src/agents/guide/agents/chat_agent.py +104 -0
  26. src/agents/guide/agents/interactive_agent.py +223 -0
  27. src/agents/guide/agents/locate_agent.py +149 -0
  28. src/agents/guide/agents/summary_agent.py +150 -0
  29. src/agents/guide/guide_manager.py +500 -0
  30. src/agents/guide/prompts/en/chat_agent.yaml +41 -0
  31. src/agents/guide/prompts/en/interactive_agent.yaml +202 -0
  32. src/agents/guide/prompts/en/locate_agent.yaml +68 -0
  33. src/agents/guide/prompts/en/summary_agent.yaml +157 -0
  34. src/agents/guide/prompts/zh/chat_agent.yaml +41 -0
  35. src/agents/guide/prompts/zh/interactive_agent.yaml +626 -0
  36. src/agents/guide/prompts/zh/locate_agent.yaml +68 -0
  37. src/agents/guide/prompts/zh/summary_agent.yaml +157 -0
  38. src/agents/ideagen/__init__.py +12 -0
  39. src/agents/ideagen/idea_generation_workflow.py +426 -0
  40. src/agents/ideagen/material_organizer_agent.py +173 -0
  41. src/agents/ideagen/prompts/en/idea_generation.yaml +187 -0
  42. src/agents/ideagen/prompts/en/material_organizer.yaml +69 -0
  43. src/agents/ideagen/prompts/zh/idea_generation.yaml +187 -0
  44. src/agents/ideagen/prompts/zh/material_organizer.yaml +69 -0
  45. src/agents/question/__init__.py +24 -0
  46. src/agents/question/agents/__init__.py +18 -0
  47. src/agents/question/agents/generate_agent.py +381 -0
  48. src/agents/question/agents/relevance_analyzer.py +207 -0
  49. src/agents/question/agents/retrieve_agent.py +239 -0
  50. src/agents/question/coordinator.py +718 -0
  51. src/agents/question/example.py +109 -0
  52. src/agents/question/prompts/en/coordinator.yaml +75 -0
  53. src/agents/question/prompts/en/generate_agent.yaml +77 -0
  54. src/agents/question/prompts/en/relevance_analyzer.yaml +41 -0
  55. src/agents/question/prompts/en/retrieve_agent.yaml +32 -0
  56. src/agents/question/prompts/zh/coordinator.yaml +75 -0
  57. src/agents/question/prompts/zh/generate_agent.yaml +77 -0
  58. src/agents/question/prompts/zh/relevance_analyzer.yaml +39 -0
  59. src/agents/question/prompts/zh/retrieve_agent.yaml +30 -0
  60. src/agents/research/agents/__init__.py +23 -0
  61. src/agents/research/agents/decompose_agent.py +507 -0
  62. src/agents/research/agents/manager_agent.py +228 -0
  63. src/agents/research/agents/note_agent.py +180 -0
  64. src/agents/research/agents/rephrase_agent.py +263 -0
  65. src/agents/research/agents/reporting_agent.py +1333 -0
  66. src/agents/research/agents/research_agent.py +714 -0
  67. src/agents/research/data_structures.py +451 -0
  68. src/agents/research/main.py +188 -0
  69. src/agents/research/prompts/en/decompose_agent.yaml +89 -0
  70. src/agents/research/prompts/en/manager_agent.yaml +24 -0
  71. src/agents/research/prompts/en/note_agent.yaml +121 -0
  72. src/agents/research/prompts/en/rephrase_agent.yaml +58 -0
  73. src/agents/research/prompts/en/reporting_agent.yaml +380 -0
  74. src/agents/research/prompts/en/research_agent.yaml +173 -0
  75. src/agents/research/prompts/zh/decompose_agent.yaml +89 -0
  76. src/agents/research/prompts/zh/manager_agent.yaml +24 -0
  77. src/agents/research/prompts/zh/note_agent.yaml +121 -0
  78. src/agents/research/prompts/zh/rephrase_agent.yaml +58 -0
  79. src/agents/research/prompts/zh/reporting_agent.yaml +380 -0
  80. src/agents/research/prompts/zh/research_agent.yaml +173 -0
  81. src/agents/research/research_pipeline.py +1309 -0
  82. src/agents/research/utils/__init__.py +60 -0
  83. src/agents/research/utils/citation_manager.py +799 -0
  84. src/agents/research/utils/json_utils.py +98 -0
  85. src/agents/research/utils/token_tracker.py +297 -0
  86. src/agents/solve/__init__.py +80 -0
  87. src/agents/solve/analysis_loop/__init__.py +14 -0
  88. src/agents/solve/analysis_loop/investigate_agent.py +414 -0
  89. src/agents/solve/analysis_loop/note_agent.py +190 -0
  90. src/agents/solve/main_solver.py +862 -0
  91. src/agents/solve/memory/__init__.py +34 -0
  92. src/agents/solve/memory/citation_memory.py +353 -0
  93. src/agents/solve/memory/investigate_memory.py +226 -0
  94. src/agents/solve/memory/solve_memory.py +340 -0
  95. src/agents/solve/prompts/en/analysis_loop/investigate_agent.yaml +55 -0
  96. src/agents/solve/prompts/en/analysis_loop/note_agent.yaml +54 -0
  97. src/agents/solve/prompts/en/solve_loop/manager_agent.yaml +67 -0
  98. src/agents/solve/prompts/en/solve_loop/precision_answer_agent.yaml +62 -0
  99. src/agents/solve/prompts/en/solve_loop/response_agent.yaml +90 -0
  100. src/agents/solve/prompts/en/solve_loop/solve_agent.yaml +75 -0
  101. src/agents/solve/prompts/en/solve_loop/tool_agent.yaml +38 -0
  102. src/agents/solve/prompts/zh/analysis_loop/investigate_agent.yaml +53 -0
  103. src/agents/solve/prompts/zh/analysis_loop/note_agent.yaml +54 -0
  104. src/agents/solve/prompts/zh/solve_loop/manager_agent.yaml +66 -0
  105. src/agents/solve/prompts/zh/solve_loop/precision_answer_agent.yaml +62 -0
  106. src/agents/solve/prompts/zh/solve_loop/response_agent.yaml +90 -0
  107. src/agents/solve/prompts/zh/solve_loop/solve_agent.yaml +76 -0
  108. src/agents/solve/prompts/zh/solve_loop/tool_agent.yaml +41 -0
  109. src/agents/solve/solve_loop/__init__.py +22 -0
  110. src/agents/solve/solve_loop/citation_manager.py +74 -0
  111. src/agents/solve/solve_loop/manager_agent.py +274 -0
  112. src/agents/solve/solve_loop/precision_answer_agent.py +96 -0
  113. src/agents/solve/solve_loop/response_agent.py +301 -0
  114. src/agents/solve/solve_loop/solve_agent.py +325 -0
  115. src/agents/solve/solve_loop/tool_agent.py +470 -0
  116. src/agents/solve/utils/__init__.py +64 -0
  117. src/agents/solve/utils/config_validator.py +313 -0
  118. src/agents/solve/utils/display_manager.py +223 -0
  119. src/agents/solve/utils/error_handler.py +363 -0
  120. src/agents/solve/utils/json_utils.py +98 -0
  121. src/agents/solve/utils/performance_monitor.py +407 -0
  122. src/agents/solve/utils/token_tracker.py +541 -0
  123. src/api/__init__.py +0 -0
  124. src/api/main.py +240 -0
  125. src/api/routers/__init__.py +1 -0
  126. src/api/routers/agent_config.py +69 -0
  127. src/api/routers/chat.py +296 -0
  128. src/api/routers/co_writer.py +337 -0
  129. src/api/routers/config.py +627 -0
  130. src/api/routers/dashboard.py +18 -0
  131. src/api/routers/guide.py +337 -0
  132. src/api/routers/ideagen.py +436 -0
  133. src/api/routers/knowledge.py +821 -0
  134. src/api/routers/notebook.py +247 -0
  135. src/api/routers/question.py +537 -0
  136. src/api/routers/research.py +394 -0
  137. src/api/routers/settings.py +164 -0
  138. src/api/routers/solve.py +305 -0
  139. src/api/routers/system.py +252 -0
  140. src/api/run_server.py +61 -0
  141. src/api/utils/history.py +172 -0
  142. src/api/utils/log_interceptor.py +21 -0
  143. src/api/utils/notebook_manager.py +415 -0
  144. src/api/utils/progress_broadcaster.py +72 -0
  145. src/api/utils/task_id_manager.py +100 -0
  146. src/config/__init__.py +0 -0
  147. src/config/accessors.py +18 -0
  148. src/config/constants.py +34 -0
  149. src/config/defaults.py +18 -0
  150. src/config/schema.py +38 -0
  151. src/config/settings.py +50 -0
  152. src/core/errors.py +62 -0
  153. src/knowledge/__init__.py +23 -0
  154. src/knowledge/add_documents.py +606 -0
  155. src/knowledge/config.py +65 -0
  156. src/knowledge/example_add_documents.py +236 -0
  157. src/knowledge/extract_numbered_items.py +1039 -0
  158. src/knowledge/initializer.py +621 -0
  159. src/knowledge/kb.py +22 -0
  160. src/knowledge/manager.py +782 -0
  161. src/knowledge/progress_tracker.py +182 -0
  162. src/knowledge/start_kb.py +535 -0
  163. src/logging/__init__.py +103 -0
  164. src/logging/adapters/__init__.py +17 -0
  165. src/logging/adapters/lightrag.py +184 -0
  166. src/logging/adapters/llamaindex.py +141 -0
  167. src/logging/config.py +80 -0
  168. src/logging/handlers/__init__.py +20 -0
  169. src/logging/handlers/console.py +75 -0
  170. src/logging/handlers/file.py +201 -0
  171. src/logging/handlers/websocket.py +127 -0
  172. src/logging/logger.py +709 -0
  173. src/logging/stats/__init__.py +16 -0
  174. src/logging/stats/llm_stats.py +179 -0
  175. src/services/__init__.py +56 -0
  176. src/services/config/__init__.py +61 -0
  177. src/services/config/knowledge_base_config.py +210 -0
  178. src/services/config/loader.py +260 -0
  179. src/services/config/unified_config.py +603 -0
  180. src/services/embedding/__init__.py +45 -0
  181. src/services/embedding/adapters/__init__.py +22 -0
  182. src/services/embedding/adapters/base.py +106 -0
  183. src/services/embedding/adapters/cohere.py +127 -0
  184. src/services/embedding/adapters/jina.py +99 -0
  185. src/services/embedding/adapters/ollama.py +116 -0
  186. src/services/embedding/adapters/openai_compatible.py +96 -0
  187. src/services/embedding/client.py +159 -0
  188. src/services/embedding/config.py +156 -0
  189. src/services/embedding/provider.py +119 -0
  190. src/services/llm/__init__.py +152 -0
  191. src/services/llm/capabilities.py +313 -0
  192. src/services/llm/client.py +302 -0
  193. src/services/llm/cloud_provider.py +530 -0
  194. src/services/llm/config.py +200 -0
  195. src/services/llm/error_mapping.py +103 -0
  196. src/services/llm/exceptions.py +152 -0
  197. src/services/llm/factory.py +450 -0
  198. src/services/llm/local_provider.py +347 -0
  199. src/services/llm/providers/anthropic.py +95 -0
  200. src/services/llm/providers/base_provider.py +93 -0
  201. src/services/llm/providers/open_ai.py +83 -0
  202. src/services/llm/registry.py +71 -0
  203. src/services/llm/telemetry.py +40 -0
  204. src/services/llm/types.py +27 -0
  205. src/services/llm/utils.py +333 -0
  206. src/services/prompt/__init__.py +25 -0
  207. src/services/prompt/manager.py +206 -0
  208. src/services/rag/__init__.py +64 -0
  209. src/services/rag/components/__init__.py +29 -0
  210. src/services/rag/components/base.py +59 -0
  211. src/services/rag/components/chunkers/__init__.py +18 -0
  212. src/services/rag/components/chunkers/base.py +34 -0
  213. src/services/rag/components/chunkers/fixed.py +71 -0
  214. src/services/rag/components/chunkers/numbered_item.py +94 -0
  215. src/services/rag/components/chunkers/semantic.py +97 -0
  216. src/services/rag/components/embedders/__init__.py +14 -0
  217. src/services/rag/components/embedders/base.py +32 -0
  218. src/services/rag/components/embedders/openai.py +63 -0
  219. src/services/rag/components/indexers/__init__.py +18 -0
  220. src/services/rag/components/indexers/base.py +35 -0
  221. src/services/rag/components/indexers/graph.py +172 -0
  222. src/services/rag/components/indexers/lightrag.py +156 -0
  223. src/services/rag/components/indexers/vector.py +146 -0
  224. src/services/rag/components/parsers/__init__.py +18 -0
  225. src/services/rag/components/parsers/base.py +35 -0
  226. src/services/rag/components/parsers/markdown.py +52 -0
  227. src/services/rag/components/parsers/pdf.py +115 -0
  228. src/services/rag/components/parsers/text.py +86 -0
  229. src/services/rag/components/retrievers/__init__.py +18 -0
  230. src/services/rag/components/retrievers/base.py +34 -0
  231. src/services/rag/components/retrievers/dense.py +200 -0
  232. src/services/rag/components/retrievers/hybrid.py +164 -0
  233. src/services/rag/components/retrievers/lightrag.py +169 -0
  234. src/services/rag/components/routing.py +286 -0
  235. src/services/rag/factory.py +234 -0
  236. src/services/rag/pipeline.py +215 -0
  237. src/services/rag/pipelines/__init__.py +32 -0
  238. src/services/rag/pipelines/academic.py +44 -0
  239. src/services/rag/pipelines/lightrag.py +43 -0
  240. src/services/rag/pipelines/llamaindex.py +313 -0
  241. src/services/rag/pipelines/raganything.py +384 -0
  242. src/services/rag/service.py +244 -0
  243. src/services/rag/types.py +73 -0
  244. src/services/search/__init__.py +284 -0
  245. src/services/search/base.py +87 -0
  246. src/services/search/consolidation.py +398 -0
  247. src/services/search/providers/__init__.py +128 -0
  248. src/services/search/providers/baidu.py +188 -0
  249. src/services/search/providers/exa.py +194 -0
  250. src/services/search/providers/jina.py +161 -0
  251. src/services/search/providers/perplexity.py +153 -0
  252. src/services/search/providers/serper.py +209 -0
  253. src/services/search/providers/tavily.py +161 -0
  254. src/services/search/types.py +114 -0
  255. src/services/setup/__init__.py +34 -0
  256. src/services/setup/init.py +285 -0
  257. src/services/tts/__init__.py +16 -0
  258. src/services/tts/config.py +99 -0
  259. src/tools/__init__.py +91 -0
  260. src/tools/code_executor.py +536 -0
  261. src/tools/paper_search_tool.py +171 -0
  262. src/tools/query_item_tool.py +310 -0
  263. src/tools/question/__init__.py +15 -0
  264. src/tools/question/exam_mimic.py +616 -0
  265. src/tools/question/pdf_parser.py +211 -0
  266. src/tools/question/question_extractor.py +397 -0
  267. src/tools/rag_tool.py +173 -0
  268. src/tools/tex_chunker.py +339 -0
  269. src/tools/tex_downloader.py +253 -0
  270. src/tools/web_search.py +71 -0
  271. src/utils/config_manager.py +206 -0
  272. src/utils/document_validator.py +168 -0
  273. src/utils/error_rate_tracker.py +111 -0
  274. src/utils/error_utils.py +82 -0
  275. src/utils/json_parser.py +110 -0
  276. src/utils/network/circuit_breaker.py +79 -0
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Configuration Loader
5
+ ====================
6
+
7
+ Unified configuration loading for all DeepTutor modules.
8
+ Provides YAML configuration loading, path resolution, and language parsing.
9
+ """
10
+
11
+ import asyncio
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ import yaml
16
+
17
+ # PROJECT_ROOT points to the actual project root directory (DeepTutor/)
18
+ # Path(__file__) = src/services/config/loader.py
19
+ # .parent = src/services/config/
20
+ # .parent.parent = src/services/
21
+ # .parent.parent.parent = src/
22
+ # .parent.parent.parent.parent = DeepTutor/ (project root)
23
+ PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent.parent
24
+
25
+
26
+ def _deep_merge(base: dict[str, Any], override: dict[str, Any]) -> dict[str, Any]:
27
+ """
28
+ Deep merge two dictionaries, values in override will override values in base
29
+
30
+ Args:
31
+ base: Base configuration
32
+ override: Override configuration
33
+
34
+ Returns:
35
+ Merged configuration
36
+ """
37
+ result = base.copy()
38
+
39
+ for key, value in override.items():
40
+ if key in result and isinstance(result[key], dict) and isinstance(value, dict):
41
+ # Recursively merge dictionaries
42
+ result[key] = _deep_merge(result[key], value)
43
+ else:
44
+ # Direct override
45
+ result[key] = value
46
+
47
+ return result
48
+
49
+
50
+ def _load_yaml_file(file_path: Path) -> dict[str, Any]:
51
+ """Load a YAML file and return its contents as a dict."""
52
+ with open(file_path, encoding="utf-8") as f:
53
+ return yaml.safe_load(f) or {}
54
+
55
+
56
+ async def _load_yaml_file_async(file_path: Path) -> dict[str, Any]:
57
+ """Async version of _load_yaml_file."""
58
+ return await asyncio.to_thread(_load_yaml_file, file_path)
59
+
60
+
61
+ def load_config_with_main(config_file: str, project_root: Path | None = None) -> dict[str, Any]:
62
+ """
63
+ Load configuration file, automatically merge with main.yaml common configuration
64
+
65
+ Args:
66
+ config_file: Sub-module configuration file name (e.g., "solve_config.yaml")
67
+ project_root: Project root directory (if None, will try to auto-detect)
68
+
69
+ Returns:
70
+ Merged configuration dictionary
71
+ """
72
+ if project_root is None:
73
+ project_root = PROJECT_ROOT
74
+
75
+ config_dir = project_root / "config"
76
+
77
+ # 1. Load main.yaml (common configuration)
78
+ main_config = {}
79
+ main_config_path = config_dir / "main.yaml"
80
+ if main_config_path.exists():
81
+ try:
82
+ main_config = _load_yaml_file(main_config_path)
83
+ except Exception as e:
84
+ print(f"⚠️ Failed to load main.yaml: {e}")
85
+
86
+ # 2. Load sub-module configuration file
87
+ module_config = {}
88
+ module_config_path = config_dir / config_file
89
+ if module_config_path.exists():
90
+ try:
91
+ module_config = _load_yaml_file(module_config_path)
92
+ except Exception as e:
93
+ print(f"⚠️ Failed to load {config_file}: {e}")
94
+
95
+ # 3. Merge configurations: main.yaml as base, sub-module config overrides
96
+ merged_config = _deep_merge(main_config, module_config)
97
+
98
+ return merged_config
99
+
100
+
101
+ async def load_config_with_main_async(
102
+ config_file: str, project_root: Path | None = None
103
+ ) -> dict[str, Any]:
104
+ """
105
+ Async version of load_config_with_main for non-blocking file operations.
106
+
107
+ Load configuration file, automatically merge with main.yaml common configuration
108
+
109
+ Args:
110
+ config_file: Sub-module configuration file name (e.g., "solve_config.yaml")
111
+ project_root: Project root directory (if None, will try to auto-detect)
112
+
113
+ Returns:
114
+ Merged configuration dictionary
115
+ """
116
+ if project_root is None:
117
+ project_root = PROJECT_ROOT
118
+
119
+ config_dir = project_root / "config"
120
+
121
+ # 1. Load main.yaml (common configuration)
122
+ main_config = {}
123
+ main_config_path = config_dir / "main.yaml"
124
+ if main_config_path.exists():
125
+ try:
126
+ main_config = await _load_yaml_file_async(main_config_path)
127
+ except Exception as e:
128
+ print(f"⚠️ Failed to load main.yaml: {e}")
129
+
130
+ # 2. Load sub-module configuration file
131
+ module_config = {}
132
+ module_config_path = config_dir / config_file
133
+ if module_config_path.exists():
134
+ try:
135
+ module_config = await _load_yaml_file_async(module_config_path)
136
+ except Exception as e:
137
+ print(f"⚠️ Failed to load {config_file}: {e}")
138
+
139
+ # 3. Merge configurations: main.yaml as base, sub-module config overrides
140
+ merged_config = _deep_merge(main_config, module_config)
141
+
142
+ return merged_config
143
+
144
+
145
+ def get_path_from_config(config: dict[str, Any], path_key: str, default: str = None) -> str:
146
+ """
147
+ Get path from configuration, supports searching in paths and system
148
+
149
+ Args:
150
+ config: Configuration dictionary
151
+ path_key: Path key name (e.g., "log_dir", "workspace")
152
+ default: Default value
153
+
154
+ Returns:
155
+ Path string
156
+ """
157
+ # Priority: search in paths
158
+ if "paths" in config and path_key in config["paths"]:
159
+ return config["paths"][path_key]
160
+
161
+ # Search in system (backward compatibility)
162
+ if "system" in config and path_key in config["system"]:
163
+ return config["system"][path_key]
164
+
165
+ # Search in tools (e.g., run_code.workspace)
166
+ if "tools" in config:
167
+ if path_key == "workspace" and "run_code" in config["tools"]:
168
+ return config["tools"]["run_code"].get("workspace", default)
169
+
170
+ return default
171
+
172
+
173
+ def parse_language(language: Any) -> str:
174
+ """
175
+ Unified language configuration parser, supports multiple input formats
176
+
177
+ Supported language representations:
178
+ - English: "en", "english", "English"
179
+ - Chinese: "zh", "chinese", "Chinese"
180
+
181
+ Args:
182
+ language: Language configuration value (can be "zh"/"en"/"Chinese"/"English" etc.)
183
+
184
+ Returns:
185
+ Standardized language code: 'zh' or 'en', defaults to 'zh'
186
+ """
187
+ if not language:
188
+ return "zh"
189
+
190
+ if isinstance(language, str):
191
+ lang_lower = language.lower()
192
+ if lang_lower in ["en", "english"]:
193
+ return "en"
194
+ if lang_lower in ["zh", "chinese"]:
195
+ return "zh"
196
+
197
+ return "zh" # Default Chinese
198
+
199
+
200
+ def get_agent_params(module_name: str) -> dict:
201
+ """
202
+ Get agent parameters (temperature, max_tokens) for a specific module.
203
+
204
+ This function loads parameters from config/agents.yaml which serves as the
205
+ SINGLE source of truth for all agent temperature and max_tokens settings.
206
+
207
+ Args:
208
+ module_name: Module name, one of:
209
+ - "guide": Guide module agents
210
+ - "solve": Solve module agents
211
+ - "research": Research module agents
212
+ - "question": Question module agents
213
+ - "ideagen": IdeaGen module agents
214
+ - "co_writer": CoWriter module agents
215
+ - "narrator": Narrator agent (independent, for TTS)
216
+
217
+ Returns:
218
+ dict: Dictionary containing:
219
+ - temperature: float, default 0.5
220
+ - max_tokens: int, default 4096
221
+
222
+ Example:
223
+ >>> params = get_agent_params("guide")
224
+ >>> params["temperature"] # 0.5
225
+ >>> params["max_tokens"] # 8192
226
+ """
227
+ # Default values
228
+ defaults = {
229
+ "temperature": 0.5,
230
+ "max_tokens": 4096,
231
+ }
232
+
233
+ # Try to load from agents.yaml
234
+ try:
235
+ config_path = PROJECT_ROOT / "config" / "agents.yaml"
236
+
237
+ if config_path.exists():
238
+ with open(config_path, encoding="utf-8") as f:
239
+ agents_config = yaml.safe_load(f) or {}
240
+
241
+ if module_name in agents_config:
242
+ module_config = agents_config[module_name]
243
+ return {
244
+ "temperature": module_config.get("temperature", defaults["temperature"]),
245
+ "max_tokens": module_config.get("max_tokens", defaults["max_tokens"]),
246
+ }
247
+ except Exception as e:
248
+ print(f"⚠️ Failed to load agents.yaml: {e}, using defaults")
249
+
250
+ return defaults
251
+
252
+
253
+ __all__ = [
254
+ "PROJECT_ROOT",
255
+ "load_config_with_main",
256
+ "get_path_from_config",
257
+ "parse_language",
258
+ "get_agent_params",
259
+ "_deep_merge",
260
+ ]