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
@@ -75,7 +75,7 @@ class HistoryManager:
75
75
  self._context_history[context_id] = []
76
76
  self._context_history[context_id].append(key)
77
77
 
78
- def save_to_disk(self, key: str, save_root: str = "data/conversations", image_path: Optional[str] = None, web_results: Optional[List[Dict]] = None):
78
+ def save_to_disk(self, key: str, save_root: str = "data/conversations", image_path: Optional[str] = None, web_results: Optional[List[Dict]] = None, vision_trace: Optional[Dict] = None, instruct_traces: Optional[List[Dict]] = None):
79
79
  """Save conversation history to specific folder structure"""
80
80
  import os
81
81
  import time
@@ -83,24 +83,30 @@ class HistoryManager:
83
83
  import shutil
84
84
  import json
85
85
 
86
- if key not in self._history:
86
+ if key not in self._history and not web_results:
87
87
  return
88
88
 
89
89
  try:
90
90
  # Extract user's first message (question) for folder name
91
- user_question = ""
92
- for msg in self._history[key]:
93
- if msg.get("role") == "user":
94
- content = msg.get("content", "")
95
- if isinstance(content, list):
96
- for item in content:
97
- if isinstance(item, dict) and item.get("type") == "text":
98
- user_question = item.get("text", "")
99
- break
100
- else:
101
- user_question = str(content)
102
- break
91
+ user_question = "unknown_query"
92
+ if key in self._history:
93
+ for msg in self._history[key]:
94
+ if msg.get("role") == "user":
95
+ content = msg.get("content", "")
96
+ if isinstance(content, list):
97
+ for item in content:
98
+ if isinstance(item, dict) and item.get("type") == "text":
99
+ user_question = item.get("text", "")
100
+ break
101
+ else:
102
+ user_question = str(content)
103
+ break
103
104
 
105
+ # Use raw query from first web result if available and no history (for pure search debug)
106
+ if user_question == "unknown_query" and web_results and len(web_results) > 0:
107
+ q = web_results[0].get("query", "")
108
+ if q: user_question = q
109
+
104
110
  # Clean and truncate question
105
111
  question_part = re.sub(r'[\\/:*?"<>|\n\r\t]', '', user_question)[:20].strip()
106
112
  if not question_part:
@@ -109,6 +115,13 @@ class HistoryManager:
109
115
  # Create folder: YYYYMMDD_HHMMSS_question
110
116
  time_str = time.strftime("%Y%m%d_%H%M%S", time.localtime())
111
117
  folder_name = f"{time_str}_{question_part}"
118
+
119
+ # Auto-resolve relative paths to absolute if needed
120
+ if not os.path.isabs(save_root):
121
+ # Try to save next to the project root (assuming we are in src/...)
122
+ # But safer to just use CWD
123
+ save_root = os.path.abspath(save_root)
124
+
112
125
  folder_path = os.path.join(save_root, folder_name)
113
126
 
114
127
  os.makedirs(folder_path, exist_ok=True)
@@ -198,51 +211,41 @@ class HistoryManager:
198
211
  except Exception as e:
199
212
  print(f"Failed to copy output image: {e}")
200
213
 
201
- # 4. Save Full Log (Readme style)
202
- timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
203
- model_name = meta.get("model", "unknown")
204
- code = self._key_to_code.get(key, "N/A")
205
-
206
- md_content = f"# Conversation Log: {folder_name}\n\n"
207
- md_content += f"- **Time**: {timestamp}\n"
208
- md_content += f"- **Code**: {code}\n"
209
- md_content += f"- **Model**: {model_name}\n\n"
210
-
211
- md_content += "## History\n\n"
212
-
213
- for msg in self._history[key]:
214
- role = msg.get("role", "unknown").upper()
215
- content = msg.get("content", "")
216
-
217
- md_content += f"### {role}\n\n"
218
-
219
- tool_calls = msg.get("tool_calls")
220
- if tool_calls:
221
- try:
222
- tc_str = json.dumps(tool_calls, ensure_ascii=False, indent=2)
223
- except:
224
- tc_str = str(tool_calls)
225
- md_content += f"**Tool Calls**:\n```json\n{tc_str}\n```\n\n"
226
-
227
- if role == "TOOL":
228
- try:
229
- # Try parsing as JSON first
230
- if isinstance(content, str):
231
- parsed = json.loads(content)
232
- pretty = json.dumps(parsed, ensure_ascii=False, indent=2)
233
- md_content += f"**Output**:\n```json\n{pretty}\n```\n\n"
234
- else:
235
- md_content += f"**Output**:\n```text\n{content}\n```\n\n"
236
- except:
237
- md_content += f"**Output**:\n```text\n{content}\n```\n\n"
238
- else:
239
- if content:
240
- md_content += f"{content}\n\n"
214
+ # 4. Save Vision Log (if vision stage was used)
215
+ if vision_trace and not vision_trace.get("skipped"):
216
+ vision_md = "# Vision Stage Log\n\n"
217
+ vision_md += f"- **Model**: {vision_trace.get('model', 'unknown')}\n"
218
+ vision_md += f"- **Time**: {vision_trace.get('time', 0):.2f}s\n"
219
+ vision_md += f"- **Images Count**: {vision_trace.get('images_count', 0)}\n"
220
+ vision_md += f"- **Input Tokens**: {vision_trace.get('usage', {}).get('input_tokens', 0)}\n"
221
+ vision_md += f"- **Output Tokens**: {vision_trace.get('usage', {}).get('output_tokens', 0)}\n\n"
222
+ vision_md += "## Vision Description Output\n\n"
223
+ vision_md += f"```\n{vision_trace.get('output', '')}\n```\n"
241
224
 
242
- md_content += "---\n\n"
225
+ with open(os.path.join(folder_path, "vision_log.md"), "w", encoding="utf-8") as f:
226
+ f.write(vision_md)
243
227
 
244
- with open(os.path.join(folder_path, "full_log.md"), "w", encoding="utf-8") as f:
245
- f.write(md_content)
228
+ # 5. Save Instruct Log (all instruct rounds)
229
+ if instruct_traces:
230
+ instruct_md = "# Instruct Stage Log\n\n"
231
+ for i, trace in enumerate(instruct_traces):
232
+ stage_name = trace.get("stage_name", f"Round {i+1}")
233
+ instruct_md += f"## {stage_name}\n\n"
234
+ instruct_md += f"- **Model**: {trace.get('model', 'unknown')}\n"
235
+ instruct_md += f"- **Time**: {trace.get('time', 0):.2f}s\n"
236
+ instruct_md += f"- **Tool Calls**: {trace.get('tool_calls', 0)}\n"
237
+ instruct_md += f"- **Input Tokens**: {trace.get('usage', {}).get('input_tokens', 0)}\n"
238
+ instruct_md += f"- **Output Tokens**: {trace.get('usage', {}).get('output_tokens', 0)}\n\n"
239
+
240
+ output = trace.get("output", "")
241
+ if output:
242
+ instruct_md += "### Reasoning Output\n\n"
243
+ instruct_md += f"```\n{output}\n```\n\n"
244
+
245
+ instruct_md += "---\n\n"
246
+
247
+ with open(os.path.join(folder_path, "instruct_log.md"), "w", encoding="utf-8") as f:
248
+ f.write(instruct_md)
246
249
 
247
250
  except Exception as e:
248
251
  print(f"Failed to save conversation: {e}")
entari_plugin_hyw/misc.py CHANGED
@@ -103,6 +103,7 @@ async def render_refuse_answer(
103
103
  output_path: str,
104
104
  reason: str = "Instruct 专家分配此任务流程失败,请尝试提出其他问题~",
105
105
  theme_color: str = "#ef4444",
106
+ tab_id: str = None,
106
107
  ) -> bool:
107
108
  """
108
109
  Render a refuse-to-answer image using the provided reason.
@@ -112,6 +113,7 @@ async def render_refuse_answer(
112
113
  output_path: Path to save the output image
113
114
  reason: The refusal reason to display
114
115
  theme_color: Theme color for the card
116
+ tab_id: Optional tab ID for reusing a prepared browser tab
115
117
 
116
118
  Returns:
117
119
  True if render succeeded, False otherwise
@@ -131,6 +133,7 @@ async def render_refuse_answer(
131
133
  stages_used=[],
132
134
  image_timeout=1000,
133
135
  theme_color=theme_color,
136
+ tab_id=tab_id,
134
137
  )
135
138
 
136
139
 
@@ -0,0 +1,154 @@
1
+ """
2
+ Search Result Cache
3
+
4
+ Caches search results in memory for 10 minutes to support
5
+ deep query operations on search results.
6
+ """
7
+
8
+ import time
9
+ from dataclasses import dataclass, field
10
+ from typing import Dict, List, Any, Optional
11
+
12
+
13
+ @dataclass
14
+ class CacheEntry:
15
+ """A cached search result entry."""
16
+ results: List[Dict[str, Any]]
17
+ query: str
18
+ timestamp: float = field(default_factory=time.time)
19
+
20
+
21
+ class SearchResultCache:
22
+ """
23
+ In-memory cache for search results with TTL-based expiration.
24
+
25
+ Cleanup is lazy - performed at the end of each request.
26
+ """
27
+
28
+ def __init__(self, ttl_seconds: float = 600.0): # 10 minutes default
29
+ self._cache: Dict[str, CacheEntry] = {}
30
+ self.ttl_seconds = ttl_seconds
31
+
32
+ def store(self, message_id: str, results: List[Dict[str, Any]], query: str):
33
+ """
34
+ Store search results associated with a message ID.
35
+
36
+ Args:
37
+ message_id: The sent message ID that contains the search results image
38
+ results: List of search result dicts with url, title, content, etc.
39
+ query: The original search query
40
+ """
41
+ self._cache[message_id] = CacheEntry(
42
+ results=results,
43
+ query=query,
44
+ timestamp=time.time()
45
+ )
46
+
47
+ def get(self, message_id: str) -> Optional[CacheEntry]:
48
+ """
49
+ Get cached search results for a message ID.
50
+
51
+ Returns None if not found or expired.
52
+ """
53
+ entry = self._cache.get(message_id)
54
+ if entry is None:
55
+ return None
56
+
57
+ # Check expiration
58
+ if time.time() - entry.timestamp > self.ttl_seconds:
59
+ del self._cache[message_id]
60
+ return None
61
+
62
+ return entry
63
+
64
+ def cleanup(self):
65
+ """
66
+ Remove all expired entries.
67
+
68
+ Called lazily at the end of each request.
69
+ """
70
+ now = time.time()
71
+ expired_keys = [
72
+ k for k, v in self._cache.items()
73
+ if now - v.timestamp > self.ttl_seconds
74
+ ]
75
+ for k in expired_keys:
76
+ del self._cache[k]
77
+
78
+ def __len__(self) -> int:
79
+ return len(self._cache)
80
+
81
+
82
+ def parse_single_index(text: str) -> Optional[int]:
83
+ """
84
+ Parse a single index from text like "1" or "3".
85
+
86
+ Args:
87
+ text: The text to parse
88
+
89
+ Returns:
90
+ 0-based index or None if not a valid single index
91
+ """
92
+ if not text:
93
+ return None
94
+ text = text.strip()
95
+ if text.isdigit():
96
+ idx = int(text)
97
+ if 1 <= idx <= 10: # 1-based, max 10 results
98
+ return idx - 1 # Convert to 0-based
99
+ return None
100
+
101
+
102
+ def parse_multi_indices(text: str, max_count: int = 3) -> Optional[List[int]]:
103
+ """
104
+ Parse multiple indices from text like "1-2", "1,2,3", "1、2、5".
105
+
106
+ Supports:
107
+ - Range: "1-2", "2-4"
108
+ - Comma separated: "1,2,3", "1, 2, 3"
109
+ - Chinese comma: "1、2、5"
110
+ - Space separated: "1 2 3"
111
+
112
+ Args:
113
+ text: The text to parse
114
+ max_count: Maximum number of indices allowed (default 3), returns None if exceeded
115
+
116
+ Returns:
117
+ List of 0-based indices, or None if empty/invalid/exceeds max_count
118
+ """
119
+ import re
120
+
121
+ if not text:
122
+ return None
123
+
124
+ text = text.strip()
125
+ if not text:
126
+ return None
127
+
128
+ indices = set()
129
+
130
+ # Check for range pattern: "1-3"
131
+ range_match = re.match(r'^(\d+)\s*[-–]\s*(\d+)$', text)
132
+ if range_match:
133
+ start, end = int(range_match.group(1)), int(range_match.group(2))
134
+ if 1 <= start <= 10 and 1 <= end <= 10 and start <= end:
135
+ indices.update(range(start - 1, end)) # 0-based
136
+ if len(indices) > max_count:
137
+ return None # Exceeds max
138
+ return sorted(indices)
139
+ return None
140
+
141
+ # Split by comma, Chinese comma, or space
142
+ parts = re.split(r'[,、\s]+', text)
143
+ for part in parts:
144
+ part = part.strip()
145
+ if part.isdigit():
146
+ idx = int(part)
147
+ if 1 <= idx <= 10:
148
+ indices.add(idx - 1) # 0-based
149
+
150
+ if indices:
151
+ if len(indices) > max_count:
152
+ return None # Exceeds max
153
+ return sorted(indices)
154
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: entari_plugin_hyw
3
- Version: 4.0.0rc6
3
+ Version: 4.0.0rc8
4
4
  Summary: Use large language models to interpret chat messages
5
5
  Author-email: kumoSleeping <zjr2992@outlook.com>
6
6
  License: MIT
@@ -26,6 +26,8 @@ Requires-Dist: json-repair>=0.55.0
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: entari-plugin-server>=0.5.0; extra == "dev"
28
28
  Requires-Dist: satori-python-adapter-onebot11>=0.2.5; extra == "dev"
29
+ Requires-Dist: noneprompt; extra == "dev"
30
+ Requires-Dist: rich; extra == "dev"
29
31
 
30
32
  # Entari Plugin HYW
31
33
 
@@ -0,0 +1,68 @@
1
+ entari_plugin_hyw/Untitled-1,sha256=wbsr5i9iorqBMIYK4aAnpNTek3mXbhvyo2YOYw38pE4,30187
2
+ entari_plugin_hyw/__init__.py,sha256=laQrEH-CdofBg3EEqIEOTwJu0pHlMG0wIvdQo8AycZk,35057
3
+ entari_plugin_hyw/history.py,sha256=0XJwbfvXH5T1EPt4G1J5wWMJsKi0FfmajY5cvw8CQWE,12065
4
+ entari_plugin_hyw/misc.py,sha256=4ABzCHbEA87UCQfBX7AgAqACQwjQIhCSZuqHXPFGokg,5527
5
+ entari_plugin_hyw/search_cache.py,sha256=7MIhTm5_YnZjc0aBaX7AE4AJp0VT8eU6ObR6mTkoerc,4285
6
+ hyw_core/__init__.py,sha256=Jlr9Ic-BLOPTnff6OctUCdjDMdK4nssTF_vHie4QKTo,1958
7
+ hyw_core/config.py,sha256=DHxwToUVLm1nT88gG05e3hVzSLxXMk9BjgjAnhGCADk,4918
8
+ hyw_core/core.py,sha256=G96C9mhmuXRwFOwIYm5M6q0ys1QD_2eQYvP89e_bmWg,10455
9
+ hyw_core/definitions.py,sha256=syYMNy3vdey7VuSlD3JUZ0gjlp5tmVkGHup-nimT0X0,3264
10
+ hyw_core/image_cache.py,sha256=t8pr1kgH2ngK9IhrBAhzUqhBWERNztUywMzgCFZEtQk,9899
11
+ hyw_core/pipeline.py,sha256=ZWwF0DHa29-65lUMU1_Fem3xQmxl7X_vgeni0ErOb8Q,22826
12
+ hyw_core/search.py,sha256=IqYCeWkIPpssLx8vHEv3qbqndLuPy5z6cE_L-IhNcNk,7468
13
+ hyw_core/browser_control/__init__.py,sha256=X1vHZpYXLG-P1RRivVyK014WKnv48GN1ibF9TbMp_-c,1482
14
+ hyw_core/browser_control/landing.html,sha256=wgqldumdylz69T83pvOkrigT1Mdb9GY0_KU0ceLGwdY,4642
15
+ hyw_core/browser_control/manager.py,sha256=U8dVpkWTG5pcIE5WiSQSfTx4gEo9PnBbmBD0KZcLBbU,5513
16
+ hyw_core/browser_control/renderer.py,sha256=hsCjJPMSCAvqTFtiAmyjaw0IE8xmbIjq5VK9dd70gfc,15539
17
+ hyw_core/browser_control/service.py,sha256=cuNVpNhPDnFMptgQGSM1ABTRpsYfXD95AT4ymO0DKgY,32669
18
+ hyw_core/browser_control/assets/index.html,sha256=BpbM0vD9OYicE5MBHSVLo3j_y-MpULI82PMqmBKpWT8,2328623
19
+ hyw_core/browser_control/assets/card-dist/index.html,sha256=fNfT_0TgSZLqwuTtKAl3Wzc4lKRAY_rbWxc_mQHfaCs,2209006
20
+ hyw_core/browser_control/assets/card-dist/vite.svg,sha256=SnSK_UQ5GLsWWRyDTEAdrjPoeGGrXbrQgRw6O0qSFPs,1497
21
+ hyw_core/browser_control/assets/card-dist/logos/anthropic.svg,sha256=ASsy1ypo3osNc3n-B0R81tk_dIFsVgg7qQORrd5T2kA,558
22
+ hyw_core/browser_control/assets/card-dist/logos/cerebras.svg,sha256=bpmiiYTODwc06knTmPj3GQ7NNtosMog5lkggvB_Z-7M,44166
23
+ hyw_core/browser_control/assets/card-dist/logos/deepseek.png,sha256=KWWAr9aeYMc6I07U_1qo7zcXO6e7-kfd9S2XjQumnf4,25338
24
+ hyw_core/browser_control/assets/card-dist/logos/gemini.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
25
+ hyw_core/browser_control/assets/card-dist/logos/google.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
26
+ hyw_core/browser_control/assets/card-dist/logos/grok.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
27
+ hyw_core/browser_control/assets/card-dist/logos/huggingface.png,sha256=8eAudeftUDO11jf0coOscPeRkskCb7l9TNMx78q61mY,24564
28
+ hyw_core/browser_control/assets/card-dist/logos/microsoft.svg,sha256=-am_6N3UEQYSzldDg-xrdGYjTWsagH-3v4Q_eia1ymE,684
29
+ hyw_core/browser_control/assets/card-dist/logos/minimax.png,sha256=tWqVlMdFNPpP8zWWX9tvIsWXI9q76P7O3t3CEZO7NU0,1525
30
+ hyw_core/browser_control/assets/card-dist/logos/mistral.png,sha256=0vv7jPmPKiBRYVYYJxVL_wIH_qa_ZssIdV3NDO5vbmk,869
31
+ hyw_core/browser_control/assets/card-dist/logos/nvida.png,sha256=JMITdcyjR9Lz6Gub0n1_30d0ynvV1ZSCJRcjy23qgrA,1607
32
+ hyw_core/browser_control/assets/card-dist/logos/openai.svg,sha256=LhVwCR4qaXj6qHm31qniQTCkJ-FX932JLSycUis5kao,1692
33
+ hyw_core/browser_control/assets/card-dist/logos/openrouter.png,sha256=exxfjWGDWpYH-Vc8xJDbhNVeXFEVxnu6TMxYIBc1WmY,1665
34
+ hyw_core/browser_control/assets/card-dist/logos/perplexity.svg,sha256=mHWZFoeWmDYXOIDzm9pj6_sRotaI8xNy5Lkeg5Vzu70,555
35
+ hyw_core/browser_control/assets/card-dist/logos/qwen.png,sha256=eqLbnIPbjh2_PsODU_mmqjeD82xXj8fV_kN0fDrNaD0,38419
36
+ hyw_core/browser_control/assets/card-dist/logos/xai.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
37
+ hyw_core/browser_control/assets/card-dist/logos/xiaomi.png,sha256=WHxlDFGU5FCjb-ure3ngdGG18-efYZUUfqA3_lqCUN0,4084
38
+ hyw_core/browser_control/assets/card-dist/logos/zai.png,sha256=K-gnabdsjMLInppHA1Op7Nyt33iegrx1x-yNlvCZ0Tc,2351
39
+ hyw_core/browser_control/assets/logos/anthropic.svg,sha256=ASsy1ypo3osNc3n-B0R81tk_dIFsVgg7qQORrd5T2kA,558
40
+ hyw_core/browser_control/assets/logos/cerebras.svg,sha256=bpmiiYTODwc06knTmPj3GQ7NNtosMog5lkggvB_Z-7M,44166
41
+ hyw_core/browser_control/assets/logos/deepseek.png,sha256=KWWAr9aeYMc6I07U_1qo7zcXO6e7-kfd9S2XjQumnf4,25338
42
+ hyw_core/browser_control/assets/logos/gemini.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
43
+ hyw_core/browser_control/assets/logos/google.svg,sha256=H74CoVmx5opcCtr3Ay3M09dpqL9cd9Whkx-M6an3t7s,599
44
+ hyw_core/browser_control/assets/logos/grok.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
45
+ hyw_core/browser_control/assets/logos/huggingface.png,sha256=8eAudeftUDO11jf0coOscPeRkskCb7l9TNMx78q61mY,24564
46
+ hyw_core/browser_control/assets/logos/microsoft.svg,sha256=-am_6N3UEQYSzldDg-xrdGYjTWsagH-3v4Q_eia1ymE,684
47
+ hyw_core/browser_control/assets/logos/minimax.png,sha256=tWqVlMdFNPpP8zWWX9tvIsWXI9q76P7O3t3CEZO7NU0,1525
48
+ hyw_core/browser_control/assets/logos/mistral.png,sha256=0vv7jPmPKiBRYVYYJxVL_wIH_qa_ZssIdV3NDO5vbmk,869
49
+ hyw_core/browser_control/assets/logos/nvida.png,sha256=JMITdcyjR9Lz6Gub0n1_30d0ynvV1ZSCJRcjy23qgrA,1607
50
+ hyw_core/browser_control/assets/logos/openai.svg,sha256=LhVwCR4qaXj6qHm31qniQTCkJ-FX932JLSycUis5kao,1692
51
+ hyw_core/browser_control/assets/logos/openrouter.png,sha256=exxfjWGDWpYH-Vc8xJDbhNVeXFEVxnu6TMxYIBc1WmY,1665
52
+ hyw_core/browser_control/assets/logos/perplexity.svg,sha256=mHWZFoeWmDYXOIDzm9pj6_sRotaI8xNy5Lkeg5Vzu70,555
53
+ hyw_core/browser_control/assets/logos/qwen.png,sha256=eqLbnIPbjh2_PsODU_mmqjeD82xXj8fV_kN0fDrNaD0,38419
54
+ hyw_core/browser_control/assets/logos/xai.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
55
+ hyw_core/browser_control/assets/logos/xiaomi.png,sha256=WHxlDFGU5FCjb-ure3ngdGG18-efYZUUfqA3_lqCUN0,4084
56
+ hyw_core/browser_control/assets/logos/zai.png,sha256=K-gnabdsjMLInppHA1Op7Nyt33iegrx1x-yNlvCZ0Tc,2351
57
+ hyw_core/browser_control/engines/__init__.py,sha256=G-bjcxWMaPZoR4tUz-OcGhZDkQwkXjK234qVEFvjEbE,338
58
+ hyw_core/browser_control/engines/base.py,sha256=q5y4SM1G6xS7-6TQ-nZz9iTWw3XonjJn01fWzoTxr6c,414
59
+ hyw_core/browser_control/engines/default.py,sha256=BlHCQI4-rN9cEzLLfqvRD4bvhyP2G2KUGlo92J4kFNw,6092
60
+ hyw_core/browser_control/engines/duckduckgo.py,sha256=QVYj1I6Fw6--2-f3DYdHVlOmeLPzet9qG4HUT7ynrSE,6789
61
+ hyw_core/browser_control/engines/google.py,sha256=PmU0_n8UrnQ1oyYVS-Y_jLS6rzgkQZK_7yHlGeAUooY,6098
62
+ hyw_core/stages/__init__.py,sha256=W89cWpq-HBLi2FprtJQSjQNLzpbhM8ZCkqPG61D_imE,521
63
+ hyw_core/stages/base.py,sha256=EfnTkISXbBNxjARykqIhmMrVqw2tqZl7ozJbJEbRnhI,2806
64
+ hyw_core/stages/summary.py,sha256=ODOwhIAmBZJuA4KOhUP7Lygch7XSkshrTZj-MdZjbEs,7085
65
+ entari_plugin_hyw-4.0.0rc8.dist-info/METADATA,sha256=9aXeWqMNxHgWJoRBDjne-8j3TXlSaKV8XJtzKhdNZQY,3844
66
+ entari_plugin_hyw-4.0.0rc8.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
67
+ entari_plugin_hyw-4.0.0rc8.dist-info/top_level.txt,sha256=ah76OrufRX0okOl4Fv8MO6PXiT0IaZ1oG0eDrdAPoNo,27
68
+ entari_plugin_hyw-4.0.0rc8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
hyw_core/__init__.py ADDED
@@ -0,0 +1,94 @@
1
+ """
2
+ hyw-core - Core LLM Pipeline and Browser Automation
3
+
4
+ This package provides:
5
+ - HywCore: Main service class with unified query interface
6
+ - HywCoreConfig: Configuration management with standalone/passthrough support
7
+ - QueryRequest/QueryResponse: Request/response data classes
8
+ - SearchService: Web search abstraction
9
+ - ModularPipeline: LLM pipeline orchestration
10
+ - browser_control: Browser automation subpackage
11
+
12
+ Usage:
13
+ from hyw_core import HywCore, HywCoreConfig, QueryRequest
14
+
15
+ # Standalone usage with YAML config
16
+ config = HywCoreConfig.from_yaml("config.yaml")
17
+ core = HywCore(config)
18
+
19
+ response = await core.query(QueryRequest(
20
+ user_input="What is Python?",
21
+ images=[],
22
+ conversation_history=[]
23
+ ))
24
+
25
+ # Passthrough from parent package
26
+ config = HywCoreConfig.from_dict({
27
+ "model_name": parent_config.model_name,
28
+ "api_key": parent_config.api_key,
29
+ ...
30
+ })
31
+ """
32
+
33
+ __version__ = "4.0.0-rc8"
34
+
35
+ # Core classes
36
+ from .core import HywCore, QueryRequest, QueryResponse
37
+
38
+ # Configuration
39
+ from .config import HywCoreConfig, ModelConfig
40
+
41
+ # Pipeline components
42
+ from .pipeline import ModularPipeline
43
+ from .search import SearchService
44
+
45
+ # Stage components
46
+ from .stages import (
47
+ BaseStage,
48
+ StageContext,
49
+ StageResult,
50
+
51
+ SummaryStage,
52
+ )
53
+
54
+ # Definitions
55
+ from .definitions import (
56
+ SUMMARY_REPORT_SP,
57
+ get_refuse_answer_tool,
58
+ )
59
+
60
+ # Browser control is available as subpackage
61
+ from . import browser_control
62
+
63
+ __all__ = [
64
+ # Version
65
+ "__version__",
66
+
67
+ # Core
68
+ "HywCore",
69
+ "QueryRequest",
70
+ "QueryResponse",
71
+
72
+ # Configuration
73
+ "HywCoreConfig",
74
+ "ModelConfig",
75
+
76
+ # Pipeline
77
+ "ModularPipeline",
78
+ "SearchService",
79
+
80
+ # Stages
81
+ "BaseStage",
82
+ "StageContext",
83
+ "StageResult",
84
+
85
+ "SummaryStage",
86
+
87
+ # Definitions
88
+ "SUMMARY_REPORT_SP",
89
+ "get_refuse_answer_tool",
90
+
91
+
92
+ # Subpackage
93
+ "browser_control",
94
+ ]
@@ -0,0 +1,65 @@
1
+ """
2
+ hyw_core.browser_control - Browser automation and rendering
3
+
4
+ This subpackage provides:
5
+ - BrowserManager: Shared browser instance management
6
+ - PageService: Page fetching and screenshot capabilities
7
+ - RenderService: Vue-based card rendering
8
+ - Search engines: Bing, Google, DuckDuckGo adapters
9
+ """
10
+
11
+ from .manager import (
12
+ SharedBrowserManager,
13
+ get_shared_browser_manager,
14
+ close_shared_browser,
15
+ )
16
+
17
+ from .service import (
18
+ ScreenshotService,
19
+ get_screenshot_service,
20
+ close_screenshot_service,
21
+ prestart_browser,
22
+ )
23
+
24
+ from .renderer import (
25
+ ContentRenderer,
26
+ get_content_renderer,
27
+ set_global_renderer,
28
+ )
29
+
30
+ from .engines.base import SearchEngine
31
+ from .engines.google import GoogleEngine
32
+ from .engines.duckduckgo import DuckDuckGoEngine
33
+ from .engines.default import DefaultEngine
34
+
35
+ # Aliases for cleaner API
36
+ BrowserManager = SharedBrowserManager
37
+ PageService = ScreenshotService
38
+ RenderService = ContentRenderer
39
+
40
+ __all__ = [
41
+ # Browser Management
42
+ "BrowserManager",
43
+ "SharedBrowserManager",
44
+ "get_shared_browser_manager",
45
+ "close_shared_browser",
46
+
47
+ # Page Service
48
+ "PageService",
49
+ "ScreenshotService",
50
+ "get_screenshot_service",
51
+ "close_screenshot_service",
52
+ "prestart_browser",
53
+
54
+ # Render Service
55
+ "RenderService",
56
+ "ContentRenderer",
57
+ "get_content_renderer",
58
+ "set_global_renderer",
59
+
60
+ # Search Engines
61
+ "SearchEngine",
62
+ "GoogleEngine",
63
+ "DuckDuckGoEngine",
64
+ "DefaultEngine",
65
+ ]