entari-plugin-hyw 4.0.0rc6__py3-none-any.whl → 4.0.0rc8__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.

Potentially problematic release.


This version of entari-plugin-hyw might be problematic. Click here for more details.

Files changed (114) hide show
  1. entari_plugin_hyw/Untitled-1 +1865 -0
  2. entari_plugin_hyw/__init__.py +733 -379
  3. entari_plugin_hyw/history.py +60 -57
  4. entari_plugin_hyw/misc.py +3 -0
  5. entari_plugin_hyw/search_cache.py +154 -0
  6. {entari_plugin_hyw-4.0.0rc6.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/METADATA +3 -1
  7. entari_plugin_hyw-4.0.0rc8.dist-info/RECORD +68 -0
  8. {entari_plugin_hyw-4.0.0rc6.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/WHEEL +1 -1
  9. {entari_plugin_hyw-4.0.0rc6.dist-info → entari_plugin_hyw-4.0.0rc8.dist-info}/top_level.txt +1 -0
  10. hyw_core/__init__.py +94 -0
  11. hyw_core/browser_control/__init__.py +65 -0
  12. hyw_core/browser_control/assets/card-dist/index.html +409 -0
  13. hyw_core/browser_control/assets/index.html +5691 -0
  14. hyw_core/browser_control/engines/__init__.py +17 -0
  15. hyw_core/browser_control/engines/default.py +166 -0
  16. {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/duckduckgo.py +42 -8
  17. {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/google.py +1 -1
  18. {entari_plugin_hyw/browser → hyw_core/browser_control}/manager.py +15 -8
  19. entari_plugin_hyw/render_vue.py → hyw_core/browser_control/renderer.py +29 -14
  20. hyw_core/browser_control/service.py +720 -0
  21. hyw_core/config.py +154 -0
  22. hyw_core/core.py +322 -0
  23. hyw_core/definitions.py +83 -0
  24. entari_plugin_hyw/modular_pipeline.py → hyw_core/pipeline.py +204 -86
  25. {entari_plugin_hyw → hyw_core}/search.py +60 -19
  26. hyw_core/stages/__init__.py +21 -0
  27. entari_plugin_hyw/stage_base.py → hyw_core/stages/base.py +3 -0
  28. entari_plugin_hyw/stage_summary.py → hyw_core/stages/summary.py +36 -7
  29. entari_plugin_hyw/assets/card-dist/index.html +0 -387
  30. entari_plugin_hyw/browser/__init__.py +0 -10
  31. entari_plugin_hyw/browser/engines/bing.py +0 -95
  32. entari_plugin_hyw/browser/service.py +0 -304
  33. entari_plugin_hyw/card-ui/.gitignore +0 -24
  34. entari_plugin_hyw/card-ui/README.md +0 -5
  35. entari_plugin_hyw/card-ui/index.html +0 -16
  36. entari_plugin_hyw/card-ui/package-lock.json +0 -2342
  37. entari_plugin_hyw/card-ui/package.json +0 -31
  38. entari_plugin_hyw/card-ui/public/logos/anthropic.svg +0 -1
  39. entari_plugin_hyw/card-ui/public/logos/cerebras.svg +0 -9
  40. entari_plugin_hyw/card-ui/public/logos/deepseek.png +0 -0
  41. entari_plugin_hyw/card-ui/public/logos/gemini.svg +0 -1
  42. entari_plugin_hyw/card-ui/public/logos/google.svg +0 -1
  43. entari_plugin_hyw/card-ui/public/logos/grok.png +0 -0
  44. entari_plugin_hyw/card-ui/public/logos/huggingface.png +0 -0
  45. entari_plugin_hyw/card-ui/public/logos/microsoft.svg +0 -15
  46. entari_plugin_hyw/card-ui/public/logos/minimax.png +0 -0
  47. entari_plugin_hyw/card-ui/public/logos/mistral.png +0 -0
  48. entari_plugin_hyw/card-ui/public/logos/nvida.png +0 -0
  49. entari_plugin_hyw/card-ui/public/logos/openai.svg +0 -1
  50. entari_plugin_hyw/card-ui/public/logos/openrouter.png +0 -0
  51. entari_plugin_hyw/card-ui/public/logos/perplexity.svg +0 -24
  52. entari_plugin_hyw/card-ui/public/logos/qwen.png +0 -0
  53. entari_plugin_hyw/card-ui/public/logos/xai.png +0 -0
  54. entari_plugin_hyw/card-ui/public/logos/xiaomi.png +0 -0
  55. entari_plugin_hyw/card-ui/public/logos/zai.png +0 -0
  56. entari_plugin_hyw/card-ui/public/vite.svg +0 -1
  57. entari_plugin_hyw/card-ui/src/App.vue +0 -756
  58. entari_plugin_hyw/card-ui/src/assets/vue.svg +0 -1
  59. entari_plugin_hyw/card-ui/src/components/HelloWorld.vue +0 -41
  60. entari_plugin_hyw/card-ui/src/components/MarkdownContent.vue +0 -382
  61. entari_plugin_hyw/card-ui/src/components/SectionCard.vue +0 -41
  62. entari_plugin_hyw/card-ui/src/components/StageCard.vue +0 -240
  63. entari_plugin_hyw/card-ui/src/main.ts +0 -5
  64. entari_plugin_hyw/card-ui/src/style.css +0 -29
  65. entari_plugin_hyw/card-ui/src/test_regex.js +0 -103
  66. entari_plugin_hyw/card-ui/src/types.ts +0 -61
  67. entari_plugin_hyw/card-ui/tsconfig.app.json +0 -16
  68. entari_plugin_hyw/card-ui/tsconfig.json +0 -7
  69. entari_plugin_hyw/card-ui/tsconfig.node.json +0 -26
  70. entari_plugin_hyw/card-ui/vite.config.ts +0 -16
  71. entari_plugin_hyw/definitions.py +0 -155
  72. entari_plugin_hyw/stage_instruct.py +0 -345
  73. entari_plugin_hyw/stage_instruct_deepsearch.py +0 -104
  74. entari_plugin_hyw-4.0.0rc6.dist-info/RECORD +0 -100
  75. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/anthropic.svg +0 -0
  76. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/cerebras.svg +0 -0
  77. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/deepseek.png +0 -0
  78. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/gemini.svg +0 -0
  79. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/google.svg +0 -0
  80. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/grok.png +0 -0
  81. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/huggingface.png +0 -0
  82. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/microsoft.svg +0 -0
  83. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/minimax.png +0 -0
  84. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/mistral.png +0 -0
  85. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/nvida.png +0 -0
  86. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/openai.svg +0 -0
  87. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/openrouter.png +0 -0
  88. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/perplexity.svg +0 -0
  89. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/qwen.png +0 -0
  90. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/xai.png +0 -0
  91. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/xiaomi.png +0 -0
  92. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/logos/zai.png +0 -0
  93. {entari_plugin_hyw → hyw_core/browser_control}/assets/card-dist/vite.svg +0 -0
  94. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/anthropic.svg +0 -0
  95. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/cerebras.svg +0 -0
  96. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/deepseek.png +0 -0
  97. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/gemini.svg +0 -0
  98. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/google.svg +0 -0
  99. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/grok.png +0 -0
  100. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/huggingface.png +0 -0
  101. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/microsoft.svg +0 -0
  102. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/minimax.png +0 -0
  103. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/mistral.png +0 -0
  104. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/nvida.png +0 -0
  105. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/openai.svg +0 -0
  106. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/openrouter.png +0 -0
  107. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/perplexity.svg +0 -0
  108. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/qwen.png +0 -0
  109. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/xai.png +0 -0
  110. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/xiaomi.png +0 -0
  111. {entari_plugin_hyw/assets/icon → hyw_core/browser_control/assets/logos}/zai.png +0 -0
  112. {entari_plugin_hyw/browser → hyw_core/browser_control}/engines/base.py +0 -0
  113. {entari_plugin_hyw/browser → hyw_core/browser_control}/landing.html +0 -0
  114. {entari_plugin_hyw → hyw_core}/image_cache.py +0 -0
@@ -1,345 +0,0 @@
1
- """
2
- Instruct Stage
3
-
4
- Handles initial task planning and search generation.
5
- Analyze user query and execute initial searches.
6
- """
7
-
8
- import json
9
- import time
10
- import asyncio
11
- from typing import Any, Dict, List, Optional, Tuple
12
- from loguru import logger
13
- from openai import AsyncOpenAI
14
-
15
- from .stage_base import BaseStage, StageContext, StageResult
16
- from .definitions import (
17
- get_refuse_answer_tool,
18
- get_web_search_tool,
19
- get_crawl_page_tool,
20
- get_set_mode_tool,
21
- INSTRUCT_SP
22
- )
23
-
24
- class InstructStage(BaseStage):
25
- @property
26
- def name(self) -> str:
27
- return "Instruct"
28
-
29
- def __init__(self, config: Any, search_service: Any, client: AsyncOpenAI):
30
- super().__init__(config, search_service, client)
31
-
32
- self.refuse_answer_tool = get_refuse_answer_tool()
33
- self.web_search_tool = get_web_search_tool()
34
- self.crawl_page_tool = get_crawl_page_tool()
35
- self.set_mode_tool = get_set_mode_tool()
36
-
37
- async def execute(self, context: StageContext) -> StageResult:
38
- start_time = time.time()
39
-
40
- # --- Round 1: Initial Discovery ---
41
- logger.info("Instruct: Starting Round 1 (Initial Discovery)")
42
-
43
- # Build Round 1 User Message
44
- r1_user_content = self._build_user_message(context)
45
- r1_messages = [
46
- {"role": "system", "content": INSTRUCT_SP},
47
- {"role": "user", "content": r1_user_content}
48
- ]
49
-
50
- # Execute Round 1 LLM
51
- r1_response, r1_usage, r1_tool_calls, r1_content = await self._call_llm(
52
- messages=r1_messages,
53
- tools=[self.refuse_answer_tool, self.web_search_tool, self.crawl_page_tool, self.set_mode_tool],
54
- tool_choice="auto"
55
- )
56
-
57
- if context.should_refuse:
58
- # If refused in Round 1, stop here
59
- return self._build_result(start_time, r1_usage, r1_content, len(r1_tool_calls or []))
60
-
61
- # Execute Round 1 Tools
62
- r1_tool_outputs = []
63
- if r1_tool_calls:
64
- r1_tool_outputs = await self._process_tool_calls(context, r1_tool_calls)
65
-
66
- # --- Context Assembly for Round 2 ---
67
-
68
- # Summarize Round 1 actions for context
69
- r1_summary_text = "## Round 1 Execution Summary\n"
70
- if r1_content:
71
- r1_summary_text += f"Thought: {r1_content}\n"
72
-
73
- if r1_tool_outputs:
74
- r1_summary_text += "Tools Executed & Results:\n"
75
- for output in r1_tool_outputs:
76
- # content here is the tool output (e.g. search results text or crawl preview)
77
- r1_summary_text += f"- Action: {output['name']}\n"
78
- r1_summary_text += f" Result: {output['content']}\n"
79
- else:
80
- r1_summary_text += "No tools were executed in Round 1.\n"
81
-
82
- r2_context_str = f"""User Query: {context.user_input}
83
-
84
- {r1_summary_text}
85
- """
86
- # Save to context for next stage
87
- context.review_context = r2_context_str
88
-
89
- # Update instruct_history for logging/record purposes
90
- context.instruct_history.append({
91
- "role": "assistant",
92
- "content": f"[Round 1 Thought]: {r1_content}\n[Round 1 Actions]: {len(r1_tool_outputs)} tools"
93
- })
94
-
95
- return self._build_result(start_time, r1_usage, r1_content, len(r1_tool_calls or []))
96
-
97
- def _build_user_message(self, context: StageContext) -> Any:
98
- text_prompt = f"User Query: {context.user_input}"
99
- if context.images:
100
- user_content: List[Dict[str, Any]] = [{"type": "text", "text": text_prompt}]
101
- for img_b64 in context.images:
102
- url = f"data:image/jpeg;base64,{img_b64}" if not img_b64.startswith("data:") else img_b64
103
- user_content.append({"type": "image_url", "image_url": {"url": url}})
104
- return user_content
105
- return text_prompt
106
-
107
- async def _call_llm(self, messages, tools, tool_choice="auto"):
108
- model_cfg = self.config.get_model_config("instruct")
109
- client = self._client_for(
110
- api_key=model_cfg.get("api_key"),
111
- base_url=model_cfg.get("base_url")
112
- )
113
- model = model_cfg.get("model_name") or self.config.model_name
114
-
115
- try:
116
- response = await client.chat.completions.create(
117
- model=model,
118
- messages=messages,
119
- tools=tools,
120
- tool_choice=tool_choice,
121
- temperature=self.config.temperature,
122
- extra_body=model_cfg.get("extra_body"),
123
- )
124
- except Exception as e:
125
- logger.error(f"InstructStage LLM Error: {e}")
126
- raise e
127
-
128
- usage = {"input_tokens": 0, "output_tokens": 0}
129
- if hasattr(response, "usage") and response.usage:
130
- usage["input_tokens"] = getattr(response.usage, "prompt_tokens", 0) or 0
131
- usage["output_tokens"] = getattr(response.usage, "completion_tokens", 0) or 0
132
-
133
- message = response.choices[0].message
134
- content = message.content or ""
135
- tool_calls = message.tool_calls
136
-
137
- if content:
138
- logger.debug(f"Instruct: Agent Thought -> {content[:100]}...")
139
-
140
- return response, usage, tool_calls, content
141
-
142
- async def _process_tool_calls(self, context: StageContext, tool_calls: List[Any]) -> List[Dict[str, Any]]:
143
- """
144
- Executes tool calls and returns a list of outputs for context building.
145
- Updates context.web_results globally.
146
- """
147
- pending_crawls = [] # List of (url, tool_call_id)
148
- pending_searches = [] # List of (query, tool_call_id)
149
-
150
- results_for_context = []
151
-
152
- for tc in tool_calls:
153
- name = tc.function.name
154
- tc_id = tc.id
155
- try:
156
- args = json.loads(tc.function.arguments)
157
- except json.JSONDecodeError:
158
- results_for_context.append({
159
- "id": tc_id, "name": name, "content": "Error: Invalid JSON arguments"
160
- })
161
- continue
162
-
163
- if name == "refuse_answer":
164
- reason = args.get("reason", "Refused")
165
- logger.warning(f"Instruct: Model Refused Answer. Reason: {reason}")
166
- context.should_refuse = True
167
- context.refuse_reason = reason
168
- results_for_context.append({
169
- "id": tc_id, "name": name, "content": f"Refused: {reason}"
170
- })
171
-
172
- elif name == "web_search":
173
- query = args.get("query")
174
- if query:
175
- logger.info(f"Instruct: Planned search query -> '{query}'")
176
- pending_searches.append((query, tc_id))
177
-
178
- elif name == "crawl_page":
179
- url = args.get("url")
180
- if url:
181
- logger.info(f"Instruct: Planned page crawl -> {url}")
182
- pending_crawls.append((url, tc_id))
183
-
184
- elif name == "set_mode":
185
- mode = args.get("mode", "fast")
186
- if mode in ("fast", "deepsearch"):
187
- context.selected_mode = mode
188
- logger.info(f"Instruct: Mode set to '{mode}'")
189
- results_for_context.append({
190
- "id": tc_id, "name": name, "content": f"Mode set to: {mode}"
191
- })
192
- else:
193
- logger.warning(f"Instruct: Invalid mode '{mode}', defaulting to 'fast'")
194
- context.selected_mode = "fast"
195
-
196
- # Execute Batches
197
-
198
- # 1. Crawls
199
- if pending_crawls:
200
- urls = [u for u, _ in pending_crawls]
201
- logger.info(f"Instruct: Executing {len(urls)} crawls via batch...")
202
-
203
- # Start fetch
204
- fetch_task = asyncio.create_task(self.search_service.fetch_pages_batch(urls))
205
-
206
- # Use image capability from context to determine content mode
207
- is_image_mode = getattr(context, "image_input_supported", True)
208
- tab_ids = []
209
- if is_image_mode:
210
- from .render_vue import get_content_renderer
211
- renderer = await get_content_renderer()
212
- loop = asyncio.get_running_loop()
213
- tab_tasks = [
214
- loop.run_in_executor(renderer._executor, renderer._prepare_tab_sync)
215
- for _ in urls
216
- ]
217
- tab_ids = await asyncio.gather(*tab_tasks, return_exceptions=True)
218
- logger.debug(f"Instruct: Prepared {len(tab_ids)} tabs: {tab_ids}")
219
-
220
- crawl_results_list = await fetch_task
221
-
222
- if is_image_mode and tab_ids:
223
- theme_color = getattr(self.config, "theme_color", "#ef4444")
224
- render_tasks = []
225
- valid_pairs = []
226
- MAX_CHARS = 3000
227
- for i, (page_data, tab_id) in enumerate(zip(crawl_results_list, tab_ids)):
228
- if isinstance(tab_id, Exception):
229
- logger.warning(f"Instruct: Skip rendering page {i} due to tab error: {tab_id}")
230
- continue
231
-
232
- # Truncate content to avoid excessive size
233
- content = page_data.get("content", "")
234
- if len(content) > MAX_CHARS:
235
- content = content[:MAX_CHARS] + "\n\n...(content truncated for length)..."
236
- page_data["content"] = content
237
-
238
- if not content:
239
- logger.warning(f"Instruct: Skip rendering page {i} due to empty content")
240
- continue
241
-
242
- valid_pairs.append((i, page_data))
243
- render_tasks.append(
244
- loop.run_in_executor(
245
- renderer._executor,
246
- renderer._render_page_to_b64_sync,
247
- {"title": page_data.get("title", "Page"), "content": content},
248
- tab_id,
249
- theme_color
250
- )
251
- )
252
-
253
- if render_tasks:
254
- logger.debug(f"Instruct: Parallel rendering {len(render_tasks)} pages...")
255
- screenshots = await asyncio.gather(*render_tasks, return_exceptions=True)
256
- logger.debug(f"Instruct: Parallel rendering finished. Results count: {len(screenshots)}")
257
- for j, (orig_idx, page_data) in enumerate(valid_pairs):
258
- if j < len(screenshots) and not isinstance(screenshots[j], Exception):
259
- crawl_results_list[orig_idx]["screenshot_b64"] = screenshots[j]
260
-
261
- for i, (url, tc_id) in enumerate(pending_crawls):
262
- page_data = crawl_results_list[i]
263
- title = page_data.get("title", "Unknown")
264
-
265
- # Update global context
266
- page_item = {
267
- "_id": context.next_id(),
268
- "_type": "page",
269
- "title": page_data.get("title", "Page"),
270
- "url": page_data.get("url", url),
271
- "content": page_data.get("content", ""),
272
- "is_crawled": True,
273
- }
274
- if page_data.get("screenshot_b64"):
275
- page_item["screenshot_b64"] = page_data["screenshot_b64"]
276
- if page_data.get("raw_screenshot_b64"):
277
- page_item["raw_screenshot_b64"] = page_data["raw_screenshot_b64"]
278
- if page_data.get("images"):
279
- page_item["images"] = page_data["images"]
280
-
281
- context.web_results.append(page_item)
282
-
283
- # Output for Context Assembly
284
- content_preview = page_data.get("content", "")[:500]
285
- results_for_context.append({
286
- "id": tc_id,
287
- "name": "crawl_page",
288
- "content": f"Crawled '{title}' ({url}):\n{content_preview}..."
289
- })
290
-
291
- # 2. Searches
292
- if pending_searches:
293
- queries = [q for q, _ in pending_searches]
294
- logger.info(f"Instruct: Executing {len(queries)} searches via batch...")
295
-
296
- search_results_list = await self.search_service.search_batch(queries)
297
-
298
- for i, (query, tc_id) in enumerate(pending_searches):
299
- web_results = search_results_list[i]
300
- visible_results = [r for r in web_results if not r.get("_hidden")]
301
-
302
- # Update global context
303
- total_images = sum(len(item.get("images", []) or []) for item in web_results)
304
- logger.debug(f"Instruct: Search '{query}' returned {len(web_results)} items with {total_images} images total")
305
- for item in web_results:
306
- item["_id"] = context.next_id()
307
- if "type" in item:
308
- item["_type"] = item["type"]
309
- elif "_type" not in item:
310
- item["_type"] = "search"
311
- item["query"] = query
312
- context.web_results.append(item)
313
-
314
- # Output for Context Assembly
315
- summary = f"Found {len(visible_results)} results for '{query}':\n"
316
- for r in visible_results[:5]:
317
- summary += f"- {r.get('title')} ({r.get('url')}): {(r.get('content') or '')[:100]}...\n"
318
-
319
- results_for_context.append({
320
- "id": tc_id,
321
- "name": "web_search",
322
- "content": summary
323
- })
324
-
325
- return results_for_context
326
-
327
- def _build_result(self, start_time, usage, content, tool_calls_count):
328
- model_cfg = self.config.get_model_config("instruct")
329
- model = model_cfg.get("model_name") or self.config.model_name
330
-
331
- trace = {
332
- "stage": "Instruct",
333
- "model": model,
334
- "usage": usage,
335
- "output": content,
336
- "tool_calls": tool_calls_count,
337
- "time": time.time() - start_time,
338
- }
339
-
340
- return StageResult(
341
- success=True,
342
- data={"reasoning": content},
343
- usage=usage,
344
- trace=trace
345
- )
@@ -1,104 +0,0 @@
1
- """
2
- Instruct Deepsearch Stage
3
-
4
- Handles the deepsearch loop: Supplement information until sufficient or max iterations reached.
5
- Inherits from InstructStage to reuse tool execution logic.
6
- """
7
-
8
- import time
9
- from typing import Any, List
10
- from loguru import logger
11
- from openai import AsyncOpenAI
12
-
13
- from .stage_base import StageContext, StageResult
14
- from .stage_instruct import InstructStage
15
- from .definitions import INSTRUCT_DEEPSEARCH_SP
16
-
17
- class InstructDeepsearchStage(InstructStage):
18
- @property
19
- def name(self) -> str:
20
- return "Instruct Deepsearch"
21
-
22
- def __init__(self, config: Any, search_service: Any, client: AsyncOpenAI):
23
- super().__init__(config, search_service, client)
24
- # Inherits tools from InstructStage (web_search, crawl_page)
25
-
26
- async def execute(self, context: StageContext) -> StageResult:
27
- start_time = time.time()
28
- logger.info("Instruct Deepsearch: Starting supplementary research")
29
-
30
- # Check if we have context to review
31
- if not context.review_context:
32
- logger.warning("Instruct Deepsearch: No context found. Skipping.")
33
- return StageResult(
34
- success=True,
35
- data={"reasoning": "Skipped due to missing context.", "should_stop": True}
36
- )
37
-
38
- # Build System Prompt (Clean)
39
- system_prompt = INSTRUCT_DEEPSEARCH_SP
40
-
41
- # Build Messages
42
- # Inject context as a separate user message explaining the background
43
- context_message = f"## 已收集的信息\n\n```context\n{context.review_context}\n```"
44
-
45
- messages = [
46
- {"role": "system", "content": system_prompt},
47
- {"role": "user", "content": context_message},
48
- {"role": "user", "content": self._build_user_message(context)}
49
- ]
50
-
51
- # Call LLM
52
- # We use only web_search and crawl_page tools (no set_mode, no refuse_answer in this stage)
53
- tools = [self.web_search_tool, self.crawl_page_tool]
54
-
55
- response, usage, tool_calls, content = await self._call_llm(
56
- messages=messages,
57
- tools=tools,
58
- tool_choice="auto"
59
- )
60
-
61
- # Check for empty response = signal to stop
62
- should_stop = False
63
- if not tool_calls or len(tool_calls) == 0:
64
- logger.info("Instruct Deepsearch: No tool calls, signaling to stop loop.")
65
- should_stop = True
66
- else:
67
- # Execute Tools
68
- tool_outputs = await self._process_tool_calls(context, tool_calls)
69
-
70
- # Update context for next iteration
71
- iteration_summary = f"\n## Deepsearch Iteration\n"
72
- if content:
73
- iteration_summary += f"Thought: {content}\n"
74
- for output in tool_outputs:
75
- iteration_summary += f"- {output['name']}: {output['content'][:200]}...\n"
76
- context.review_context += iteration_summary
77
-
78
- # Update history
79
- context.instruct_history.append({
80
- "role": "assistant",
81
- "content": f"[Deepsearch]: {content}\n[Actions]: {len(tool_outputs)} tools"
82
- })
83
-
84
- return self._build_result(start_time, usage, content, len(tool_calls or []), should_stop)
85
-
86
- def _build_result(self, start_time, usage, content, tool_calls_count, should_stop=False):
87
- model_cfg = self.config.get_model_config("instruct")
88
- model = model_cfg.get("model_name") or self.config.model_name
89
-
90
- trace = {
91
- "stage": "Instruct Deepsearch",
92
- "model": model,
93
- "usage": usage,
94
- "output": content,
95
- "tool_calls": tool_calls_count,
96
- "time": time.time() - start_time,
97
- }
98
-
99
- return StageResult(
100
- success=True,
101
- data={"reasoning": content, "should_stop": should_stop},
102
- usage=usage,
103
- trace=trace
104
- )
@@ -1,100 +0,0 @@
1
- entari_plugin_hyw/__init__.py,sha256=t-TAqOaghlzVtoSuMfQoiqdA8wrfB7Riofqp3EpGQPU,21844
2
- entari_plugin_hyw/definitions.py,sha256=sRgNkmzD-XDSbRM2nVQP14WGpMoFrzr9C-cc6xmShDA,6570
3
- entari_plugin_hyw/history.py,sha256=6d1e8DPfv4XQyM9hMjrx08_WKrxqVSJEvSIGRX4JOB0,11085
4
- entari_plugin_hyw/image_cache.py,sha256=t8pr1kgH2ngK9IhrBAhzUqhBWERNztUywMzgCFZEtQk,9899
5
- entari_plugin_hyw/misc.py,sha256=ZGDXeXbSugG4tRrBfUDVd94i2SCaPOmaGtVmPz8mqtY,5413
6
- entari_plugin_hyw/modular_pipeline.py,sha256=-p2Z4oUij-G4sCdf2SeHNm89NlVTYHuU91vUIz9R-IM,16867
7
- entari_plugin_hyw/render_vue.py,sha256=4i5xTZCb9amPgSWo6f7Ev279ZOk-D8Kfmxe2HdcA_vI,14737
8
- entari_plugin_hyw/search.py,sha256=2Rnc6iYIzPEFH7NtSR0Pi0eXFH-EqIia7Kh3txWmD8U,5262
9
- entari_plugin_hyw/stage_base.py,sha256=wNotYPl8LElk-1Yf8NB2OvFeGSV2UGW9uEmlY4QmxzA,2752
10
- entari_plugin_hyw/stage_instruct.py,sha256=2vMLfA7lVRqaPdf9szBfsN7sTAALmkNUsMyUL7tjmGA,14620
11
- entari_plugin_hyw/stage_instruct_deepsearch.py,sha256=_I_xZ-M1xovM4I7NL5eyc21Wg9xdFKnJDQVQActTjUI,3969
12
- entari_plugin_hyw/stage_summary.py,sha256=1g1tL7alHbDdp6Mrq2HrXD8k65VMOL-zdyo3bWAS5RQ,5736
13
- entari_plugin_hyw/assets/card-dist/index.html,sha256=s_RU1rCFowRwFMTuIiUsyGp25WfsIyk-XNWyD9jYqVc,2204580
14
- entari_plugin_hyw/assets/card-dist/vite.svg,sha256=SnSK_UQ5GLsWWRyDTEAdrjPoeGGrXbrQgRw6O0qSFPs,1497
15
- entari_plugin_hyw/assets/card-dist/logos/anthropic.svg,sha256=ASsy1ypo3osNc3n-B0R81tk_dIFsVgg7qQORrd5T2kA,558
16
- entari_plugin_hyw/assets/card-dist/logos/cerebras.svg,sha256=bpmiiYTODwc06knTmPj3GQ7NNtosMog5lkggvB_Z-7M,44166
17
- entari_plugin_hyw/assets/card-dist/logos/deepseek.png,sha256=KWWAr9aeYMc6I07U_1qo7zcXO6e7-kfd9S2XjQumnf4,25338
18
- entari_plugin_hyw/assets/card-dist/logos/gemini.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
19
- entari_plugin_hyw/assets/card-dist/logos/google.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
20
- entari_plugin_hyw/assets/card-dist/logos/grok.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
21
- entari_plugin_hyw/assets/card-dist/logos/huggingface.png,sha256=8eAudeftUDO11jf0coOscPeRkskCb7l9TNMx78q61mY,24564
22
- entari_plugin_hyw/assets/card-dist/logos/microsoft.svg,sha256=-am_6N3UEQYSzldDg-xrdGYjTWsagH-3v4Q_eia1ymE,684
23
- entari_plugin_hyw/assets/card-dist/logos/minimax.png,sha256=tWqVlMdFNPpP8zWWX9tvIsWXI9q76P7O3t3CEZO7NU0,1525
24
- entari_plugin_hyw/assets/card-dist/logos/mistral.png,sha256=0vv7jPmPKiBRYVYYJxVL_wIH_qa_ZssIdV3NDO5vbmk,869
25
- entari_plugin_hyw/assets/card-dist/logos/nvida.png,sha256=JMITdcyjR9Lz6Gub0n1_30d0ynvV1ZSCJRcjy23qgrA,1607
26
- entari_plugin_hyw/assets/card-dist/logos/openai.svg,sha256=LhVwCR4qaXj6qHm31qniQTCkJ-FX932JLSycUis5kao,1692
27
- entari_plugin_hyw/assets/card-dist/logos/openrouter.png,sha256=exxfjWGDWpYH-Vc8xJDbhNVeXFEVxnu6TMxYIBc1WmY,1665
28
- entari_plugin_hyw/assets/card-dist/logos/perplexity.svg,sha256=mHWZFoeWmDYXOIDzm9pj6_sRotaI8xNy5Lkeg5Vzu70,555
29
- entari_plugin_hyw/assets/card-dist/logos/qwen.png,sha256=eqLbnIPbjh2_PsODU_mmqjeD82xXj8fV_kN0fDrNaD0,38419
30
- entari_plugin_hyw/assets/card-dist/logos/xai.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
31
- entari_plugin_hyw/assets/card-dist/logos/xiaomi.png,sha256=WHxlDFGU5FCjb-ure3ngdGG18-efYZUUfqA3_lqCUN0,4084
32
- entari_plugin_hyw/assets/card-dist/logos/zai.png,sha256=K-gnabdsjMLInppHA1Op7Nyt33iegrx1x-yNlvCZ0Tc,2351
33
- entari_plugin_hyw/assets/icon/anthropic.svg,sha256=ASsy1ypo3osNc3n-B0R81tk_dIFsVgg7qQORrd5T2kA,558
34
- entari_plugin_hyw/assets/icon/cerebras.svg,sha256=bpmiiYTODwc06knTmPj3GQ7NNtosMog5lkggvB_Z-7M,44166
35
- entari_plugin_hyw/assets/icon/deepseek.png,sha256=KWWAr9aeYMc6I07U_1qo7zcXO6e7-kfd9S2XjQumnf4,25338
36
- entari_plugin_hyw/assets/icon/gemini.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
37
- entari_plugin_hyw/assets/icon/google.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
38
- entari_plugin_hyw/assets/icon/grok.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
39
- entari_plugin_hyw/assets/icon/huggingface.png,sha256=8eAudeftUDO11jf0coOscPeRkskCb7l9TNMx78q61mY,24564
40
- entari_plugin_hyw/assets/icon/microsoft.svg,sha256=-am_6N3UEQYSzldDg-xrdGYjTWsagH-3v4Q_eia1ymE,684
41
- entari_plugin_hyw/assets/icon/minimax.png,sha256=tWqVlMdFNPpP8zWWX9tvIsWXI9q76P7O3t3CEZO7NU0,1525
42
- entari_plugin_hyw/assets/icon/mistral.png,sha256=0vv7jPmPKiBRYVYYJxVL_wIH_qa_ZssIdV3NDO5vbmk,869
43
- entari_plugin_hyw/assets/icon/nvida.png,sha256=JMITdcyjR9Lz6Gub0n1_30d0ynvV1ZSCJRcjy23qgrA,1607
44
- entari_plugin_hyw/assets/icon/openai.svg,sha256=LhVwCR4qaXj6qHm31qniQTCkJ-FX932JLSycUis5kao,1692
45
- entari_plugin_hyw/assets/icon/openrouter.png,sha256=exxfjWGDWpYH-Vc8xJDbhNVeXFEVxnu6TMxYIBc1WmY,1665
46
- entari_plugin_hyw/assets/icon/perplexity.svg,sha256=mHWZFoeWmDYXOIDzm9pj6_sRotaI8xNy5Lkeg5Vzu70,555
47
- entari_plugin_hyw/assets/icon/qwen.png,sha256=eqLbnIPbjh2_PsODU_mmqjeD82xXj8fV_kN0fDrNaD0,38419
48
- entari_plugin_hyw/assets/icon/xai.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
49
- entari_plugin_hyw/assets/icon/xiaomi.png,sha256=WHxlDFGU5FCjb-ure3ngdGG18-efYZUUfqA3_lqCUN0,4084
50
- entari_plugin_hyw/assets/icon/zai.png,sha256=K-gnabdsjMLInppHA1Op7Nyt33iegrx1x-yNlvCZ0Tc,2351
51
- entari_plugin_hyw/browser/__init__.py,sha256=Cht-i5MowfAdmfW3kiY4sV7oXKDb-DmhZ-_eKwDl6r0,321
52
- entari_plugin_hyw/browser/landing.html,sha256=wgqldumdylz69T83pvOkrigT1Mdb9GY0_KU0ceLGwdY,4642
53
- entari_plugin_hyw/browser/manager.py,sha256=9VuTyXBr1QBcTV8Nj2vSrozstMmNxAytXESUQ6vxLrM,5234
54
- entari_plugin_hyw/browser/service.py,sha256=8PihWOdyJcBV1_2lp3PRmmcgXYFN3uryqs5rE9E5a9M,13647
55
- entari_plugin_hyw/browser/engines/base.py,sha256=q5y4SM1G6xS7-6TQ-nZz9iTWw3XonjJn01fWzoTxr6c,414
56
- entari_plugin_hyw/browser/engines/bing.py,sha256=rIWcvjzvm700xji_OBl6COUAtwXg87DcXQ97DlTzleA,3838
57
- entari_plugin_hyw/browser/engines/duckduckgo.py,sha256=jlCIXR1mpJ0LjSbuHMYNGMYjHiQ9Lw_x-A8242Zajgo,5154
58
- entari_plugin_hyw/browser/engines/google.py,sha256=vCtyOxr63F40hDMW70sS1CyoMsqc0HzyESYrK_qcZLg,6091
59
- entari_plugin_hyw/card-ui/.gitignore,sha256=_nGOe6uxTzy60tl_CIibnOUhXtP-DkOyuM-_s7m4ROg,253
60
- entari_plugin_hyw/card-ui/README.md,sha256=fN9IawCcxEcJ8LM-RfKiAH835fRqyY_iqrRsgSkxiSk,442
61
- entari_plugin_hyw/card-ui/index.html,sha256=Hd7vk8v8PtATbfiEWLYoKDpUT0dlyozW_K5gR_cObfo,328
62
- entari_plugin_hyw/card-ui/package-lock.json,sha256=ulrY6frmLjfMRlgRA0iFrvelpL0IcZZFdpUb9stA9yU,77769
63
- entari_plugin_hyw/card-ui/package.json,sha256=nTcYhyEKU1ww3mCmJZuyJhndxabwgyJMq1RtUm2bKN4,727
64
- entari_plugin_hyw/card-ui/tsconfig.app.json,sha256=879a2y1UXrHyYZT8YoU5tmZ_xA-rC9bMoMaAA4zvUDE,454
65
- entari_plugin_hyw/card-ui/tsconfig.json,sha256=dwtBQLu1geLf2eqZRv_Jx1odhrp9LbX3fIPjfL352Ag,119
66
- entari_plugin_hyw/card-ui/tsconfig.node.json,sha256=w90PtSL-ujWWcT9RuVvVPXgdhF0krtv6KsCT2LOcUSA,653
67
- entari_plugin_hyw/card-ui/vite.config.ts,sha256=TBzPng4T24Jfb19lio5BDS3qKQzWFB6bhoVMNSunq50,351
68
- entari_plugin_hyw/card-ui/public/vite.svg,sha256=SnSK_UQ5GLsWWRyDTEAdrjPoeGGrXbrQgRw6O0qSFPs,1497
69
- entari_plugin_hyw/card-ui/public/logos/anthropic.svg,sha256=ASsy1ypo3osNc3n-B0R81tk_dIFsVgg7qQORrd5T2kA,558
70
- entari_plugin_hyw/card-ui/public/logos/cerebras.svg,sha256=bpmiiYTODwc06knTmPj3GQ7NNtosMog5lkggvB_Z-7M,44166
71
- entari_plugin_hyw/card-ui/public/logos/deepseek.png,sha256=KWWAr9aeYMc6I07U_1qo7zcXO6e7-kfd9S2XjQumnf4,25338
72
- entari_plugin_hyw/card-ui/public/logos/gemini.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
73
- entari_plugin_hyw/card-ui/public/logos/google.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
74
- entari_plugin_hyw/card-ui/public/logos/grok.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
75
- entari_plugin_hyw/card-ui/public/logos/huggingface.png,sha256=8eAudeftUDO11jf0coOscPeRkskCb7l9TNMx78q61mY,24564
76
- entari_plugin_hyw/card-ui/public/logos/microsoft.svg,sha256=-am_6N3UEQYSzldDg-xrdGYjTWsagH-3v4Q_eia1ymE,684
77
- entari_plugin_hyw/card-ui/public/logos/minimax.png,sha256=tWqVlMdFNPpP8zWWX9tvIsWXI9q76P7O3t3CEZO7NU0,1525
78
- entari_plugin_hyw/card-ui/public/logos/mistral.png,sha256=0vv7jPmPKiBRYVYYJxVL_wIH_qa_ZssIdV3NDO5vbmk,869
79
- entari_plugin_hyw/card-ui/public/logos/nvida.png,sha256=JMITdcyjR9Lz6Gub0n1_30d0ynvV1ZSCJRcjy23qgrA,1607
80
- entari_plugin_hyw/card-ui/public/logos/openai.svg,sha256=LhVwCR4qaXj6qHm31qniQTCkJ-FX932JLSycUis5kao,1692
81
- entari_plugin_hyw/card-ui/public/logos/openrouter.png,sha256=exxfjWGDWpYH-Vc8xJDbhNVeXFEVxnu6TMxYIBc1WmY,1665
82
- entari_plugin_hyw/card-ui/public/logos/perplexity.svg,sha256=mHWZFoeWmDYXOIDzm9pj6_sRotaI8xNy5Lkeg5Vzu70,555
83
- entari_plugin_hyw/card-ui/public/logos/qwen.png,sha256=eqLbnIPbjh2_PsODU_mmqjeD82xXj8fV_kN0fDrNaD0,38419
84
- entari_plugin_hyw/card-ui/public/logos/xai.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
85
- entari_plugin_hyw/card-ui/public/logos/xiaomi.png,sha256=WHxlDFGU5FCjb-ure3ngdGG18-efYZUUfqA3_lqCUN0,4084
86
- entari_plugin_hyw/card-ui/public/logos/zai.png,sha256=K-gnabdsjMLInppHA1Op7Nyt33iegrx1x-yNlvCZ0Tc,2351
87
- entari_plugin_hyw/card-ui/src/App.vue,sha256=ofRlf3hTSqDg1l8jgnFwzWg1dBzQVVg5MLOaMW01z68,28858
88
- entari_plugin_hyw/card-ui/src/main.ts,sha256=rm653lPnK5fuTIj-iNLpgr8GAmayuCoKop7IWfo0IBk,111
89
- entari_plugin_hyw/card-ui/src/style.css,sha256=Qm0sv9em6k4VI_j5PI0_E_ng6u20eFpf2lN44H19zzc,671
90
- entari_plugin_hyw/card-ui/src/test_regex.js,sha256=cWmclm6LRKYfjeN1RT5HECdltmo1HvS2BwGCYY_4l14,3040
91
- entari_plugin_hyw/card-ui/src/types.ts,sha256=2HkcsR1ej2y3yR7pvUA_y8XXP_1_NhLVAIKez3OIb3g,1583
92
- entari_plugin_hyw/card-ui/src/assets/vue.svg,sha256=VTLbNPHFKEGIG6uK7KbD6NCSvSGmiaZfTY-M-AQe750,496
93
- entari_plugin_hyw/card-ui/src/components/HelloWorld.vue,sha256=yvBIzJua9BfikUOR1I7GYytlnBbgB6xyposxslAoRLU,856
94
- entari_plugin_hyw/card-ui/src/components/MarkdownContent.vue,sha256=SV95Vuj99tQN2yrU9GqiyhiemWAW8omhYnS8AsH1YIU,13325
95
- entari_plugin_hyw/card-ui/src/components/SectionCard.vue,sha256=owcDNx2JYVmF2J5SYCroR2gvg_cPApQsNunjK1WJpVI,1433
96
- entari_plugin_hyw/card-ui/src/components/StageCard.vue,sha256=MgpOaBlPR--LJoRenN37i72BV8qVgzDdurpoKCvzKyk,11133
97
- entari_plugin_hyw-4.0.0rc6.dist-info/METADATA,sha256=ODqjgpaG9PeWasK1FlsQ5E39DxvyyC7nVy4WMy_HcUk,3766
98
- entari_plugin_hyw-4.0.0rc6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
99
- entari_plugin_hyw-4.0.0rc6.dist-info/top_level.txt,sha256=TIDsn6XPs6KA5e3ezsE65JoXsy03ejDdrB41I4SPjmo,18
100
- entari_plugin_hyw-4.0.0rc6.dist-info/RECORD,,
File without changes