webscout 8.2.7__py3-none-any.whl → 8.2.9__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 (281) hide show
  1. webscout/AIauto.py +33 -15
  2. webscout/AIbase.py +96 -37
  3. webscout/AIutel.py +703 -250
  4. webscout/Bard.py +441 -323
  5. webscout/Extra/Act.md +309 -0
  6. webscout/Extra/GitToolkit/__init__.py +10 -0
  7. webscout/Extra/GitToolkit/gitapi/README.md +110 -0
  8. webscout/Extra/GitToolkit/gitapi/__init__.py +12 -0
  9. webscout/Extra/GitToolkit/gitapi/repository.py +195 -0
  10. webscout/Extra/GitToolkit/gitapi/user.py +96 -0
  11. webscout/Extra/GitToolkit/gitapi/utils.py +62 -0
  12. webscout/Extra/YTToolkit/README.md +375 -0
  13. webscout/Extra/YTToolkit/YTdownloader.py +957 -0
  14. webscout/Extra/YTToolkit/__init__.py +3 -0
  15. webscout/Extra/YTToolkit/transcriber.py +476 -0
  16. webscout/Extra/YTToolkit/ytapi/README.md +44 -0
  17. webscout/Extra/YTToolkit/ytapi/__init__.py +6 -0
  18. webscout/Extra/YTToolkit/ytapi/channel.py +307 -0
  19. webscout/Extra/YTToolkit/ytapi/errors.py +13 -0
  20. webscout/Extra/YTToolkit/ytapi/extras.py +118 -0
  21. webscout/Extra/YTToolkit/ytapi/https.py +88 -0
  22. webscout/Extra/YTToolkit/ytapi/patterns.py +61 -0
  23. webscout/Extra/YTToolkit/ytapi/playlist.py +59 -0
  24. webscout/Extra/YTToolkit/ytapi/pool.py +8 -0
  25. webscout/Extra/YTToolkit/ytapi/query.py +40 -0
  26. webscout/Extra/YTToolkit/ytapi/stream.py +63 -0
  27. webscout/Extra/YTToolkit/ytapi/utils.py +62 -0
  28. webscout/Extra/YTToolkit/ytapi/video.py +232 -0
  29. webscout/Extra/__init__.py +7 -0
  30. webscout/Extra/autocoder/__init__.py +9 -0
  31. webscout/Extra/autocoder/autocoder.py +1105 -0
  32. webscout/Extra/autocoder/autocoder_utiles.py +332 -0
  33. webscout/Extra/gguf.md +430 -0
  34. webscout/Extra/gguf.py +684 -0
  35. webscout/Extra/tempmail/README.md +488 -0
  36. webscout/Extra/tempmail/__init__.py +28 -0
  37. webscout/Extra/tempmail/async_utils.py +141 -0
  38. webscout/Extra/tempmail/base.py +161 -0
  39. webscout/Extra/tempmail/cli.py +187 -0
  40. webscout/Extra/tempmail/emailnator.py +84 -0
  41. webscout/Extra/tempmail/mail_tm.py +361 -0
  42. webscout/Extra/tempmail/temp_mail_io.py +292 -0
  43. webscout/Extra/weather.md +281 -0
  44. webscout/Extra/weather.py +194 -0
  45. webscout/Extra/weather_ascii.py +76 -0
  46. webscout/Litlogger/README.md +10 -0
  47. webscout/Litlogger/__init__.py +15 -0
  48. webscout/Litlogger/formats.py +4 -0
  49. webscout/Litlogger/handlers.py +103 -0
  50. webscout/Litlogger/levels.py +13 -0
  51. webscout/Litlogger/logger.py +92 -0
  52. webscout/Provider/AI21.py +177 -0
  53. webscout/Provider/AISEARCH/DeepFind.py +254 -0
  54. webscout/Provider/AISEARCH/Perplexity.py +333 -0
  55. webscout/Provider/AISEARCH/README.md +279 -0
  56. webscout/Provider/AISEARCH/__init__.py +9 -0
  57. webscout/Provider/AISEARCH/felo_search.py +202 -0
  58. webscout/Provider/AISEARCH/genspark_search.py +324 -0
  59. webscout/Provider/AISEARCH/hika_search.py +186 -0
  60. webscout/Provider/AISEARCH/iask_search.py +410 -0
  61. webscout/Provider/AISEARCH/monica_search.py +220 -0
  62. webscout/Provider/AISEARCH/scira_search.py +298 -0
  63. webscout/Provider/AISEARCH/webpilotai_search.py +255 -0
  64. webscout/Provider/Aitopia.py +316 -0
  65. webscout/Provider/AllenAI.py +440 -0
  66. webscout/Provider/Andi.py +228 -0
  67. webscout/Provider/Blackboxai.py +791 -0
  68. webscout/Provider/ChatGPTClone.py +237 -0
  69. webscout/Provider/ChatGPTGratis.py +194 -0
  70. webscout/Provider/ChatSandbox.py +342 -0
  71. webscout/Provider/Cloudflare.py +324 -0
  72. webscout/Provider/Cohere.py +208 -0
  73. webscout/Provider/Deepinfra.py +340 -0
  74. webscout/Provider/ExaAI.py +261 -0
  75. webscout/Provider/ExaChat.py +358 -0
  76. webscout/Provider/Flowith.py +217 -0
  77. webscout/Provider/FreeGemini.py +250 -0
  78. webscout/Provider/Gemini.py +169 -0
  79. webscout/Provider/GithubChat.py +369 -0
  80. webscout/Provider/GizAI.py +295 -0
  81. webscout/Provider/Glider.py +225 -0
  82. webscout/Provider/Groq.py +801 -0
  83. webscout/Provider/HF_space/__init__.py +0 -0
  84. webscout/Provider/HF_space/qwen_qwen2.py +206 -0
  85. webscout/Provider/HeckAI.py +375 -0
  86. webscout/Provider/HuggingFaceChat.py +469 -0
  87. webscout/Provider/Hunyuan.py +283 -0
  88. webscout/Provider/Jadve.py +291 -0
  89. webscout/Provider/Koboldai.py +384 -0
  90. webscout/Provider/LambdaChat.py +411 -0
  91. webscout/Provider/Llama3.py +259 -0
  92. webscout/Provider/MCPCore.py +315 -0
  93. webscout/Provider/Marcus.py +198 -0
  94. webscout/Provider/Nemotron.py +218 -0
  95. webscout/Provider/Netwrck.py +270 -0
  96. webscout/Provider/OLLAMA.py +396 -0
  97. webscout/Provider/OPENAI/BLACKBOXAI.py +766 -0
  98. webscout/Provider/OPENAI/Cloudflare.py +378 -0
  99. webscout/Provider/OPENAI/FreeGemini.py +283 -0
  100. webscout/Provider/OPENAI/NEMOTRON.py +232 -0
  101. webscout/Provider/OPENAI/Qwen3.py +283 -0
  102. webscout/Provider/OPENAI/README.md +952 -0
  103. webscout/Provider/OPENAI/TwoAI.py +357 -0
  104. webscout/Provider/OPENAI/__init__.py +40 -0
  105. webscout/Provider/OPENAI/ai4chat.py +293 -0
  106. webscout/Provider/OPENAI/api.py +969 -0
  107. webscout/Provider/OPENAI/base.py +249 -0
  108. webscout/Provider/OPENAI/c4ai.py +373 -0
  109. webscout/Provider/OPENAI/chatgpt.py +556 -0
  110. webscout/Provider/OPENAI/chatgptclone.py +494 -0
  111. webscout/Provider/OPENAI/chatsandbox.py +173 -0
  112. webscout/Provider/OPENAI/copilot.py +242 -0
  113. webscout/Provider/OPENAI/deepinfra.py +322 -0
  114. webscout/Provider/OPENAI/e2b.py +1414 -0
  115. webscout/Provider/OPENAI/exaai.py +417 -0
  116. webscout/Provider/OPENAI/exachat.py +444 -0
  117. webscout/Provider/OPENAI/flowith.py +162 -0
  118. webscout/Provider/OPENAI/freeaichat.py +359 -0
  119. webscout/Provider/OPENAI/glider.py +326 -0
  120. webscout/Provider/OPENAI/groq.py +364 -0
  121. webscout/Provider/OPENAI/heckai.py +308 -0
  122. webscout/Provider/OPENAI/llmchatco.py +335 -0
  123. webscout/Provider/OPENAI/mcpcore.py +389 -0
  124. webscout/Provider/OPENAI/multichat.py +376 -0
  125. webscout/Provider/OPENAI/netwrck.py +357 -0
  126. webscout/Provider/OPENAI/oivscode.py +287 -0
  127. webscout/Provider/OPENAI/opkfc.py +496 -0
  128. webscout/Provider/OPENAI/pydantic_imports.py +172 -0
  129. webscout/Provider/OPENAI/scirachat.py +477 -0
  130. webscout/Provider/OPENAI/sonus.py +304 -0
  131. webscout/Provider/OPENAI/standardinput.py +433 -0
  132. webscout/Provider/OPENAI/textpollinations.py +339 -0
  133. webscout/Provider/OPENAI/toolbaz.py +413 -0
  134. webscout/Provider/OPENAI/typefully.py +355 -0
  135. webscout/Provider/OPENAI/typegpt.py +364 -0
  136. webscout/Provider/OPENAI/uncovrAI.py +463 -0
  137. webscout/Provider/OPENAI/utils.py +318 -0
  138. webscout/Provider/OPENAI/venice.py +431 -0
  139. webscout/Provider/OPENAI/wisecat.py +387 -0
  140. webscout/Provider/OPENAI/writecream.py +163 -0
  141. webscout/Provider/OPENAI/x0gpt.py +365 -0
  142. webscout/Provider/OPENAI/yep.py +382 -0
  143. webscout/Provider/OpenGPT.py +209 -0
  144. webscout/Provider/Openai.py +496 -0
  145. webscout/Provider/PI.py +429 -0
  146. webscout/Provider/Perplexitylabs.py +415 -0
  147. webscout/Provider/QwenLM.py +254 -0
  148. webscout/Provider/Reka.py +214 -0
  149. webscout/Provider/StandardInput.py +290 -0
  150. webscout/Provider/TTI/README.md +82 -0
  151. webscout/Provider/TTI/__init__.py +7 -0
  152. webscout/Provider/TTI/aiarta.py +365 -0
  153. webscout/Provider/TTI/artbit.py +0 -0
  154. webscout/Provider/TTI/base.py +64 -0
  155. webscout/Provider/TTI/fastflux.py +200 -0
  156. webscout/Provider/TTI/magicstudio.py +201 -0
  157. webscout/Provider/TTI/piclumen.py +203 -0
  158. webscout/Provider/TTI/pixelmuse.py +225 -0
  159. webscout/Provider/TTI/pollinations.py +221 -0
  160. webscout/Provider/TTI/utils.py +11 -0
  161. webscout/Provider/TTS/README.md +192 -0
  162. webscout/Provider/TTS/__init__.py +10 -0
  163. webscout/Provider/TTS/base.py +159 -0
  164. webscout/Provider/TTS/deepgram.py +156 -0
  165. webscout/Provider/TTS/elevenlabs.py +111 -0
  166. webscout/Provider/TTS/gesserit.py +128 -0
  167. webscout/Provider/TTS/murfai.py +113 -0
  168. webscout/Provider/TTS/openai_fm.py +129 -0
  169. webscout/Provider/TTS/parler.py +111 -0
  170. webscout/Provider/TTS/speechma.py +580 -0
  171. webscout/Provider/TTS/sthir.py +94 -0
  172. webscout/Provider/TTS/streamElements.py +333 -0
  173. webscout/Provider/TTS/utils.py +280 -0
  174. webscout/Provider/TeachAnything.py +229 -0
  175. webscout/Provider/TextPollinationsAI.py +308 -0
  176. webscout/Provider/TwoAI.py +475 -0
  177. webscout/Provider/TypliAI.py +305 -0
  178. webscout/Provider/UNFINISHED/ChatHub.py +209 -0
  179. webscout/Provider/UNFINISHED/Youchat.py +330 -0
  180. webscout/Provider/UNFINISHED/liner_api_request.py +263 -0
  181. webscout/Provider/UNFINISHED/puterjs.py +635 -0
  182. webscout/Provider/UNFINISHED/test_lmarena.py +119 -0
  183. webscout/Provider/Venice.py +258 -0
  184. webscout/Provider/VercelAI.py +253 -0
  185. webscout/Provider/WiseCat.py +233 -0
  186. webscout/Provider/WrDoChat.py +370 -0
  187. webscout/Provider/Writecream.py +246 -0
  188. webscout/Provider/WritingMate.py +269 -0
  189. webscout/Provider/__init__.py +174 -0
  190. webscout/Provider/ai4chat.py +174 -0
  191. webscout/Provider/akashgpt.py +335 -0
  192. webscout/Provider/asksteve.py +220 -0
  193. webscout/Provider/cerebras.py +290 -0
  194. webscout/Provider/chatglm.py +215 -0
  195. webscout/Provider/cleeai.py +213 -0
  196. webscout/Provider/copilot.py +425 -0
  197. webscout/Provider/elmo.py +283 -0
  198. webscout/Provider/freeaichat.py +285 -0
  199. webscout/Provider/geminiapi.py +208 -0
  200. webscout/Provider/granite.py +235 -0
  201. webscout/Provider/hermes.py +266 -0
  202. webscout/Provider/julius.py +223 -0
  203. webscout/Provider/koala.py +170 -0
  204. webscout/Provider/learnfastai.py +325 -0
  205. webscout/Provider/llama3mitril.py +215 -0
  206. webscout/Provider/llmchat.py +258 -0
  207. webscout/Provider/llmchatco.py +306 -0
  208. webscout/Provider/lmarena.py +198 -0
  209. webscout/Provider/meta.py +801 -0
  210. webscout/Provider/multichat.py +364 -0
  211. webscout/Provider/oivscode.py +309 -0
  212. webscout/Provider/samurai.py +224 -0
  213. webscout/Provider/scira_chat.py +299 -0
  214. webscout/Provider/scnet.py +243 -0
  215. webscout/Provider/searchchat.py +292 -0
  216. webscout/Provider/sonus.py +258 -0
  217. webscout/Provider/talkai.py +194 -0
  218. webscout/Provider/toolbaz.py +353 -0
  219. webscout/Provider/turboseek.py +266 -0
  220. webscout/Provider/typefully.py +202 -0
  221. webscout/Provider/typegpt.py +289 -0
  222. webscout/Provider/uncovr.py +368 -0
  223. webscout/Provider/x0gpt.py +299 -0
  224. webscout/Provider/yep.py +389 -0
  225. webscout/__init__.py +4 -2
  226. webscout/cli.py +3 -28
  227. webscout/client.py +70 -0
  228. webscout/conversation.py +35 -35
  229. webscout/litagent/Readme.md +276 -0
  230. webscout/litagent/__init__.py +29 -0
  231. webscout/litagent/agent.py +455 -0
  232. webscout/litagent/constants.py +60 -0
  233. webscout/litprinter/__init__.py +59 -0
  234. webscout/optimizers.py +419 -419
  235. webscout/scout/README.md +404 -0
  236. webscout/scout/__init__.py +8 -0
  237. webscout/scout/core/__init__.py +7 -0
  238. webscout/scout/core/crawler.py +210 -0
  239. webscout/scout/core/scout.py +607 -0
  240. webscout/scout/core/search_result.py +96 -0
  241. webscout/scout/core/text_analyzer.py +63 -0
  242. webscout/scout/core/text_utils.py +277 -0
  243. webscout/scout/core/web_analyzer.py +52 -0
  244. webscout/scout/element.py +478 -0
  245. webscout/scout/parsers/__init__.py +69 -0
  246. webscout/scout/parsers/html5lib_parser.py +172 -0
  247. webscout/scout/parsers/html_parser.py +236 -0
  248. webscout/scout/parsers/lxml_parser.py +178 -0
  249. webscout/scout/utils.py +37 -0
  250. webscout/swiftcli/Readme.md +323 -0
  251. webscout/swiftcli/__init__.py +95 -0
  252. webscout/swiftcli/core/__init__.py +7 -0
  253. webscout/swiftcli/core/cli.py +297 -0
  254. webscout/swiftcli/core/context.py +104 -0
  255. webscout/swiftcli/core/group.py +241 -0
  256. webscout/swiftcli/decorators/__init__.py +28 -0
  257. webscout/swiftcli/decorators/command.py +221 -0
  258. webscout/swiftcli/decorators/options.py +220 -0
  259. webscout/swiftcli/decorators/output.py +252 -0
  260. webscout/swiftcli/exceptions.py +21 -0
  261. webscout/swiftcli/plugins/__init__.py +9 -0
  262. webscout/swiftcli/plugins/base.py +135 -0
  263. webscout/swiftcli/plugins/manager.py +269 -0
  264. webscout/swiftcli/utils/__init__.py +59 -0
  265. webscout/swiftcli/utils/formatting.py +252 -0
  266. webscout/swiftcli/utils/parsing.py +267 -0
  267. webscout/version.py +1 -1
  268. webscout/webscout_search.py +2 -182
  269. webscout/webscout_search_async.py +1 -179
  270. webscout/zeroart/README.md +89 -0
  271. webscout/zeroart/__init__.py +135 -0
  272. webscout/zeroart/base.py +66 -0
  273. webscout/zeroart/effects.py +101 -0
  274. webscout/zeroart/fonts.py +1239 -0
  275. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/METADATA +262 -83
  276. webscout-8.2.9.dist-info/RECORD +289 -0
  277. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/WHEEL +1 -1
  278. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/entry_points.txt +1 -0
  279. webscout-8.2.7.dist-info/RECORD +0 -26
  280. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/licenses/LICENSE.md +0 -0
  281. {webscout-8.2.7.dist-info → webscout-8.2.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,339 @@
1
+ import time
2
+ import uuid
3
+ import requests
4
+ import json
5
+ from typing import List, Dict, Optional, Union, Generator, Any
6
+
7
+ # Import base classes and utility structures
8
+ from .base import OpenAICompatibleProvider, BaseChat, BaseCompletions
9
+ from .utils import (
10
+ ChatCompletionChunk, ChatCompletion, Choice, ChoiceDelta,
11
+ ChatCompletionMessage, CompletionUsage, ToolCall, ToolFunction, count_tokens
12
+ )
13
+
14
+ # Import LitAgent for browser fingerprinting
15
+ from webscout.litagent import LitAgent
16
+
17
+ # ANSI escape codes for formatting
18
+ BOLD = "\033[1m"
19
+ RED = "\033[91m"
20
+ RESET = "\033[0m"
21
+
22
+ class Completions(BaseCompletions):
23
+ def __init__(self, client: 'TextPollinations'):
24
+ self._client = client
25
+
26
+ def create(
27
+ self,
28
+ *,
29
+ model: str,
30
+ messages: List[Dict[str, str]],
31
+ max_tokens: Optional[int] = None,
32
+ stream: bool = False,
33
+ temperature: Optional[float] = None,
34
+ top_p: Optional[float] = None,
35
+ tools: Optional[List[Dict[str, Any]]] = None,
36
+ tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
37
+ **kwargs: Any
38
+ ) -> Union[ChatCompletion, Generator[ChatCompletionChunk, None, None]]:
39
+ """
40
+ Creates a model response for the given chat conversation.
41
+ Mimics openai.chat.completions.create
42
+ """
43
+ payload = {
44
+ "model": model,
45
+ "messages": messages,
46
+ "stream": stream,
47
+ }
48
+ if max_tokens is not None:
49
+ payload["max_tokens"] = max_tokens
50
+ if temperature is not None:
51
+ payload["temperature"] = temperature
52
+ if top_p is not None:
53
+ payload["top_p"] = top_p
54
+ if tools is not None:
55
+ payload["tools"] = tools
56
+ if tool_choice is not None:
57
+ payload["tool_choice"] = tool_choice
58
+
59
+ payload.update(kwargs)
60
+
61
+ request_id = str(uuid.uuid4())
62
+ created_time = int(time.time())
63
+
64
+ if stream:
65
+ return self._create_streaming(request_id, created_time, model, payload)
66
+ else:
67
+ return self._create_non_streaming(request_id, created_time, model, payload)
68
+
69
+ def _create_streaming(
70
+ self,
71
+ request_id: str,
72
+ created_time: int,
73
+ model: str,
74
+ payload: Dict[str, Any]
75
+ ) -> Generator[ChatCompletionChunk, None, None]:
76
+ """Implementation for streaming chat completions."""
77
+ try:
78
+
79
+ # Make the streaming request
80
+ response = self._client.session.post(
81
+ self._client.api_endpoint,
82
+ headers=self._client.headers,
83
+ json=payload,
84
+ stream=True,
85
+ timeout=self._client.timeout
86
+ )
87
+
88
+ if not response.ok:
89
+ raise IOError(f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}")
90
+
91
+ # Process the streaming response
92
+ full_response = ""
93
+
94
+ for line in response.iter_lines():
95
+ if line:
96
+ line = line.decode('utf-8').strip()
97
+ if line == "data: [DONE]":
98
+ break
99
+ if line.startswith('data: '):
100
+ try:
101
+ json_data = json.loads(line[6:])
102
+ if 'choices' in json_data and len(json_data['choices']) > 0:
103
+ choice = json_data['choices'][0]
104
+ if 'delta' in choice:
105
+ delta_obj = ChoiceDelta()
106
+
107
+ # Handle content in delta
108
+ if 'content' in choice['delta']:
109
+ content = choice['delta']['content']
110
+ full_response += content
111
+ delta_obj.content = content
112
+
113
+ # Handle tool calls in delta
114
+ if 'tool_calls' in choice['delta']:
115
+ tool_calls = []
116
+ for tool_call_data in choice['delta']['tool_calls']:
117
+ if 'function' in tool_call_data:
118
+ function = ToolFunction(
119
+ name=tool_call_data['function'].get('name', ''),
120
+ arguments=tool_call_data['function'].get('arguments', '')
121
+ )
122
+ tool_call = ToolCall(
123
+ id=tool_call_data.get('id', str(uuid.uuid4())),
124
+ type=tool_call_data.get('type', 'function'),
125
+ function=function
126
+ )
127
+ tool_calls.append(tool_call)
128
+
129
+ if tool_calls:
130
+ delta_obj.tool_calls = tool_calls
131
+
132
+ # Create and yield a chunk
133
+ choice_obj = Choice(index=0, delta=delta_obj, finish_reason=None)
134
+ chunk = ChatCompletionChunk(
135
+ id=request_id,
136
+ choices=[choice_obj],
137
+ created=created_time,
138
+ model=model
139
+ )
140
+
141
+ yield chunk
142
+ except json.JSONDecodeError:
143
+ continue
144
+
145
+ # Final chunk with finish_reason
146
+ delta = ChoiceDelta(content=None)
147
+ choice = Choice(index=0, delta=delta, finish_reason="stop")
148
+ chunk = ChatCompletionChunk(
149
+ id=request_id,
150
+ choices=[choice],
151
+ created=created_time,
152
+ model=model
153
+ )
154
+
155
+ yield chunk
156
+
157
+ except Exception as e:
158
+ print(f"{RED}Error during TextPollinations streaming request: {e}{RESET}")
159
+ raise IOError(f"TextPollinations streaming request failed: {e}") from e
160
+
161
+ def _create_non_streaming(
162
+ self,
163
+ request_id: str,
164
+ created_time: int,
165
+ model: str,
166
+ payload: Dict[str, Any]
167
+ ) -> ChatCompletion:
168
+ """Implementation for non-streaming chat completions."""
169
+ try:
170
+
171
+ # Make the non-streaming request
172
+ response = self._client.session.post(
173
+ self._client.api_endpoint,
174
+ headers=self._client.headers,
175
+ json=payload,
176
+ timeout=self._client.timeout
177
+ )
178
+
179
+ if not response.ok:
180
+ raise IOError(f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}")
181
+
182
+ # Parse the response
183
+ response_json = response.json()
184
+
185
+ # Extract the content
186
+ if 'choices' in response_json and len(response_json['choices']) > 0:
187
+ choice_data = response_json['choices'][0]
188
+ if 'message' in choice_data:
189
+ message_data = choice_data['message']
190
+
191
+ # Extract content
192
+ full_content = message_data.get('content', '')
193
+
194
+ # Create the completion message with potential tool calls
195
+ message = ChatCompletionMessage(role="assistant", content=full_content)
196
+
197
+ # Handle tool calls if present
198
+ if 'tool_calls' in message_data:
199
+ tool_calls = []
200
+ for tool_call_data in message_data['tool_calls']:
201
+ if 'function' in tool_call_data:
202
+ function = ToolFunction(
203
+ name=tool_call_data['function'].get('name', ''),
204
+ arguments=tool_call_data['function'].get('arguments', '')
205
+ )
206
+ tool_call = ToolCall(
207
+ id=tool_call_data.get('id', str(uuid.uuid4())),
208
+ type=tool_call_data.get('type', 'function'),
209
+ function=function
210
+ )
211
+ tool_calls.append(tool_call)
212
+
213
+ if tool_calls:
214
+ message.tool_calls = tool_calls
215
+ else:
216
+ # Fallback if no message is present
217
+ message = ChatCompletionMessage(role="assistant", content="")
218
+ else:
219
+ # Fallback if no choices are present
220
+ message = ChatCompletionMessage(role="assistant", content="")
221
+
222
+ # Create the choice
223
+ choice = Choice(
224
+ index=0,
225
+ message=message,
226
+ finish_reason="stop"
227
+ )
228
+
229
+ # Estimate token usage using count_tokens
230
+ prompt_tokens = count_tokens([msg.get("content", "") for msg in payload.get("messages", [])])
231
+ completion_tokens = count_tokens(full_content)
232
+ usage = CompletionUsage(
233
+ prompt_tokens=prompt_tokens,
234
+ completion_tokens=completion_tokens,
235
+ total_tokens=prompt_tokens + completion_tokens
236
+ )
237
+
238
+ # Create the completion object
239
+ completion = ChatCompletion(
240
+ id=request_id,
241
+ choices=[choice],
242
+ created=created_time,
243
+ model=model,
244
+ usage=usage,
245
+ )
246
+
247
+ return completion
248
+
249
+ except Exception as e:
250
+ print(f"{RED}Error during TextPollinations non-stream request: {e}{RESET}")
251
+ raise IOError(f"TextPollinations request failed: {e}") from e
252
+
253
+ class Chat(BaseChat):
254
+ def __init__(self, client: 'TextPollinations'):
255
+ self.completions = Completions(client)
256
+
257
+ class TextPollinations(OpenAICompatibleProvider):
258
+ """
259
+ OpenAI-compatible client for TextPollinations API.
260
+
261
+ Usage:
262
+ client = TextPollinations()
263
+ response = client.chat.completions.create(
264
+ model="openai-large",
265
+ messages=[{"role": "user", "content": "Hello!"}]
266
+ )
267
+ print(response.choices[0].message.content)
268
+ """
269
+
270
+ AVAILABLE_MODELS = [
271
+ "openai",
272
+ "openai-fast",
273
+ "openai-large",
274
+ "openai-roblox",
275
+ "qwen-coder",
276
+ "llama",
277
+ "llamascout",
278
+ "mistral",
279
+ "unity",
280
+ "mirexa",
281
+ "midijourney",
282
+ "rtist",
283
+ "searchgpt",
284
+ "evil",
285
+ "deepseek-reasoning",
286
+ "phi",
287
+ "hormoz",
288
+ "hypnosis-tracy",
289
+ "deepseek",
290
+ "sur",
291
+ "bidara",
292
+ "openai-audio",
293
+ ]
294
+
295
+ def __init__(
296
+ self,
297
+ timeout: int = 30,
298
+ proxies: dict = {}
299
+ ):
300
+ """
301
+ Initialize the TextPollinations client.
302
+
303
+ Args:
304
+ timeout: Request timeout in seconds
305
+ proxies: Optional proxy configuration
306
+ """
307
+ self.timeout = timeout
308
+ self.api_endpoint = "https://text.pollinations.ai/openai"
309
+ self.proxies = proxies
310
+
311
+ # Initialize session
312
+ self.session = requests.Session()
313
+ if proxies:
314
+ self.session.proxies.update(proxies)
315
+
316
+ # Initialize LitAgent for user agent generation
317
+ agent = LitAgent()
318
+ self.user_agent = agent.random()
319
+
320
+ # Set headers
321
+ self.headers = {
322
+ 'Accept': '*/*',
323
+ 'Accept-Language': 'en-US,en;q=0.9',
324
+ 'User-Agent': self.user_agent,
325
+ 'Content-Type': 'application/json',
326
+ }
327
+
328
+ self.session.headers.update(self.headers)
329
+
330
+ # Initialize chat interface
331
+ self.chat = Chat(self)
332
+
333
+ @property
334
+ def models(self):
335
+ class _ModelList:
336
+ def list(inner_self):
337
+ return type(self).AVAILABLE_MODELS
338
+ return _ModelList()
339
+