webscout 8.3.6__py3-none-any.whl → 2025.10.11__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 webscout might be problematic. Click here for more details.
- webscout/AIauto.py +250 -250
- webscout/AIbase.py +379 -379
- webscout/AIutel.py +60 -58
- webscout/Bard.py +1012 -1012
- webscout/Bing_search.py +417 -417
- webscout/DWEBS.py +529 -529
- webscout/Extra/Act.md +309 -309
- webscout/Extra/GitToolkit/__init__.py +10 -10
- webscout/Extra/GitToolkit/gitapi/README.md +110 -110
- webscout/Extra/GitToolkit/gitapi/__init__.py +11 -11
- webscout/Extra/GitToolkit/gitapi/repository.py +195 -195
- webscout/Extra/GitToolkit/gitapi/user.py +96 -96
- webscout/Extra/GitToolkit/gitapi/utils.py +61 -61
- webscout/Extra/YTToolkit/README.md +375 -375
- webscout/Extra/YTToolkit/YTdownloader.py +956 -956
- webscout/Extra/YTToolkit/__init__.py +2 -2
- webscout/Extra/YTToolkit/transcriber.py +475 -475
- webscout/Extra/YTToolkit/ytapi/README.md +44 -44
- webscout/Extra/YTToolkit/ytapi/__init__.py +6 -6
- webscout/Extra/YTToolkit/ytapi/channel.py +307 -307
- webscout/Extra/YTToolkit/ytapi/errors.py +13 -13
- webscout/Extra/YTToolkit/ytapi/extras.py +118 -118
- webscout/Extra/YTToolkit/ytapi/https.py +88 -88
- webscout/Extra/YTToolkit/ytapi/patterns.py +61 -61
- webscout/Extra/YTToolkit/ytapi/playlist.py +58 -58
- webscout/Extra/YTToolkit/ytapi/pool.py +7 -7
- webscout/Extra/YTToolkit/ytapi/query.py +39 -39
- webscout/Extra/YTToolkit/ytapi/stream.py +62 -62
- webscout/Extra/YTToolkit/ytapi/utils.py +62 -62
- webscout/Extra/YTToolkit/ytapi/video.py +232 -232
- webscout/Extra/autocoder/__init__.py +9 -9
- webscout/Extra/autocoder/autocoder.py +1105 -1105
- webscout/Extra/autocoder/autocoder_utiles.py +332 -332
- webscout/Extra/gguf.md +429 -429
- webscout/Extra/gguf.py +1213 -1213
- webscout/Extra/tempmail/README.md +487 -487
- webscout/Extra/tempmail/__init__.py +27 -27
- webscout/Extra/tempmail/async_utils.py +140 -140
- webscout/Extra/tempmail/base.py +160 -160
- webscout/Extra/tempmail/cli.py +186 -186
- webscout/Extra/tempmail/emailnator.py +84 -84
- webscout/Extra/tempmail/mail_tm.py +360 -360
- webscout/Extra/tempmail/temp_mail_io.py +291 -291
- webscout/Extra/weather.md +281 -281
- webscout/Extra/weather.py +193 -193
- webscout/Litlogger/README.md +10 -10
- webscout/Litlogger/__init__.py +15 -15
- webscout/Litlogger/formats.py +13 -13
- webscout/Litlogger/handlers.py +121 -121
- webscout/Litlogger/levels.py +13 -13
- webscout/Litlogger/logger.py +134 -134
- webscout/Provider/AISEARCH/Perplexity.py +332 -332
- webscout/Provider/AISEARCH/README.md +279 -279
- webscout/Provider/AISEARCH/__init__.py +33 -11
- webscout/Provider/AISEARCH/felo_search.py +206 -206
- webscout/Provider/AISEARCH/genspark_search.py +323 -323
- webscout/Provider/AISEARCH/hika_search.py +185 -185
- webscout/Provider/AISEARCH/iask_search.py +410 -410
- webscout/Provider/AISEARCH/monica_search.py +219 -219
- webscout/Provider/AISEARCH/scira_search.py +316 -314
- webscout/Provider/AISEARCH/stellar_search.py +177 -177
- webscout/Provider/AISEARCH/webpilotai_search.py +255 -255
- webscout/Provider/Aitopia.py +314 -315
- webscout/Provider/Andi.py +3 -3
- webscout/Provider/Apriel.py +306 -0
- webscout/Provider/ChatGPTClone.py +236 -236
- webscout/Provider/ChatSandbox.py +343 -342
- webscout/Provider/Cloudflare.py +324 -324
- webscout/Provider/Cohere.py +208 -207
- webscout/Provider/Deepinfra.py +370 -369
- webscout/Provider/ExaAI.py +260 -260
- webscout/Provider/ExaChat.py +308 -387
- webscout/Provider/Flowith.py +221 -221
- webscout/Provider/GMI.py +293 -0
- webscout/Provider/Gemini.py +164 -162
- webscout/Provider/GeminiProxy.py +167 -166
- webscout/Provider/GithubChat.py +371 -370
- webscout/Provider/Groq.py +800 -800
- webscout/Provider/HeckAI.py +383 -379
- webscout/Provider/Jadve.py +282 -297
- webscout/Provider/K2Think.py +308 -0
- webscout/Provider/Koboldai.py +206 -384
- webscout/Provider/LambdaChat.py +423 -425
- webscout/Provider/Nemotron.py +244 -245
- webscout/Provider/Netwrck.py +248 -247
- webscout/Provider/OLLAMA.py +395 -394
- webscout/Provider/OPENAI/Cloudflare.py +394 -395
- webscout/Provider/OPENAI/FalconH1.py +452 -457
- webscout/Provider/OPENAI/FreeGemini.py +297 -299
- webscout/Provider/OPENAI/{monochat.py → K2Think.py} +432 -329
- webscout/Provider/OPENAI/NEMOTRON.py +241 -244
- webscout/Provider/OPENAI/PI.py +428 -427
- webscout/Provider/OPENAI/README.md +959 -959
- webscout/Provider/OPENAI/TogetherAI.py +345 -345
- webscout/Provider/OPENAI/TwoAI.py +466 -467
- webscout/Provider/OPENAI/__init__.py +33 -59
- webscout/Provider/OPENAI/ai4chat.py +313 -303
- webscout/Provider/OPENAI/base.py +249 -269
- webscout/Provider/OPENAI/chatglm.py +528 -0
- webscout/Provider/OPENAI/chatgpt.py +593 -588
- webscout/Provider/OPENAI/chatgptclone.py +521 -524
- webscout/Provider/OPENAI/chatsandbox.py +202 -177
- webscout/Provider/OPENAI/deepinfra.py +319 -315
- webscout/Provider/OPENAI/e2b.py +1665 -1665
- webscout/Provider/OPENAI/exaai.py +420 -420
- webscout/Provider/OPENAI/exachat.py +452 -452
- webscout/Provider/OPENAI/friendli.py +232 -232
- webscout/Provider/OPENAI/{refact.py → gmi.py} +324 -274
- webscout/Provider/OPENAI/groq.py +364 -364
- webscout/Provider/OPENAI/heckai.py +314 -311
- webscout/Provider/OPENAI/llmchatco.py +337 -337
- webscout/Provider/OPENAI/netwrck.py +355 -354
- webscout/Provider/OPENAI/oivscode.py +290 -290
- webscout/Provider/OPENAI/opkfc.py +518 -518
- webscout/Provider/OPENAI/pydantic_imports.py +1 -1
- webscout/Provider/OPENAI/scirachat.py +535 -529
- webscout/Provider/OPENAI/sonus.py +308 -308
- webscout/Provider/OPENAI/standardinput.py +442 -442
- webscout/Provider/OPENAI/textpollinations.py +340 -348
- webscout/Provider/OPENAI/toolbaz.py +419 -413
- webscout/Provider/OPENAI/typefully.py +362 -362
- webscout/Provider/OPENAI/utils.py +295 -295
- webscout/Provider/OPENAI/venice.py +436 -436
- webscout/Provider/OPENAI/wisecat.py +387 -387
- webscout/Provider/OPENAI/writecream.py +166 -166
- webscout/Provider/OPENAI/x0gpt.py +378 -378
- webscout/Provider/OPENAI/yep.py +389 -389
- webscout/Provider/OpenGPT.py +230 -230
- webscout/Provider/Openai.py +244 -496
- webscout/Provider/PI.py +405 -404
- webscout/Provider/Perplexitylabs.py +430 -431
- webscout/Provider/QwenLM.py +272 -254
- webscout/Provider/STT/__init__.py +32 -2
- webscout/Provider/{Llama3.py → Sambanova.py} +257 -258
- webscout/Provider/StandardInput.py +309 -309
- webscout/Provider/TTI/README.md +82 -82
- webscout/Provider/TTI/__init__.py +33 -12
- webscout/Provider/TTI/aiarta.py +413 -413
- webscout/Provider/TTI/base.py +136 -136
- webscout/Provider/TTI/bing.py +243 -243
- webscout/Provider/TTI/gpt1image.py +149 -149
- webscout/Provider/TTI/imagen.py +196 -196
- webscout/Provider/TTI/infip.py +211 -211
- webscout/Provider/TTI/magicstudio.py +232 -232
- webscout/Provider/TTI/monochat.py +219 -219
- webscout/Provider/TTI/piclumen.py +214 -214
- webscout/Provider/TTI/pixelmuse.py +232 -232
- webscout/Provider/TTI/pollinations.py +232 -232
- webscout/Provider/TTI/together.py +288 -288
- webscout/Provider/TTI/utils.py +12 -12
- webscout/Provider/TTI/venice.py +367 -367
- webscout/Provider/TTS/README.md +192 -192
- webscout/Provider/TTS/__init__.py +33 -10
- webscout/Provider/TTS/parler.py +110 -110
- webscout/Provider/TTS/streamElements.py +333 -333
- webscout/Provider/TTS/utils.py +280 -280
- webscout/Provider/TeachAnything.py +237 -236
- webscout/Provider/TextPollinationsAI.py +311 -318
- webscout/Provider/TogetherAI.py +356 -357
- webscout/Provider/TwoAI.py +313 -569
- webscout/Provider/TypliAI.py +312 -311
- webscout/Provider/UNFINISHED/ChatHub.py +208 -208
- webscout/Provider/UNFINISHED/ChutesAI.py +313 -313
- webscout/Provider/{GizAI.py → UNFINISHED/GizAI.py} +294 -294
- webscout/Provider/{Marcus.py → UNFINISHED/Marcus.py} +198 -198
- webscout/Provider/{Qodo.py → UNFINISHED/Qodo.py} +477 -477
- webscout/Provider/UNFINISHED/VercelAIGateway.py +338 -338
- webscout/Provider/{XenAI.py → UNFINISHED/XenAI.py} +324 -324
- webscout/Provider/UNFINISHED/Youchat.py +330 -330
- webscout/Provider/UNFINISHED/liner.py +334 -0
- webscout/Provider/UNFINISHED/liner_api_request.py +262 -262
- webscout/Provider/UNFINISHED/puterjs.py +634 -634
- webscout/Provider/UNFINISHED/samurai.py +223 -223
- webscout/Provider/UNFINISHED/test_lmarena.py +119 -119
- webscout/Provider/Venice.py +251 -250
- webscout/Provider/VercelAI.py +256 -255
- webscout/Provider/WiseCat.py +232 -231
- webscout/Provider/WrDoChat.py +367 -366
- webscout/Provider/__init__.py +33 -86
- webscout/Provider/ai4chat.py +174 -174
- webscout/Provider/akashgpt.py +331 -334
- webscout/Provider/cerebras.py +446 -340
- webscout/Provider/chatglm.py +394 -214
- webscout/Provider/cleeai.py +211 -212
- webscout/Provider/deepseek_assistant.py +1 -1
- webscout/Provider/elmo.py +282 -282
- webscout/Provider/geminiapi.py +208 -208
- webscout/Provider/granite.py +261 -261
- webscout/Provider/hermes.py +263 -265
- webscout/Provider/julius.py +223 -222
- webscout/Provider/learnfastai.py +309 -309
- webscout/Provider/llama3mitril.py +214 -214
- webscout/Provider/llmchat.py +243 -243
- webscout/Provider/llmchatco.py +290 -290
- webscout/Provider/meta.py +801 -801
- webscout/Provider/oivscode.py +309 -309
- webscout/Provider/scira_chat.py +384 -457
- webscout/Provider/searchchat.py +292 -291
- webscout/Provider/sonus.py +258 -258
- webscout/Provider/toolbaz.py +370 -364
- webscout/Provider/turboseek.py +274 -265
- webscout/Provider/typefully.py +208 -207
- webscout/Provider/x0gpt.py +1 -0
- webscout/Provider/yep.py +372 -371
- webscout/__init__.py +30 -31
- webscout/__main__.py +5 -5
- webscout/auth/api_key_manager.py +189 -189
- webscout/auth/config.py +175 -175
- webscout/auth/models.py +185 -185
- webscout/auth/routes.py +664 -664
- webscout/auth/simple_logger.py +236 -236
- webscout/cli.py +523 -523
- webscout/conversation.py +438 -438
- webscout/exceptions.py +361 -361
- webscout/litagent/Readme.md +298 -298
- webscout/litagent/__init__.py +28 -28
- webscout/litagent/agent.py +581 -581
- webscout/litagent/constants.py +59 -59
- webscout/litprinter/__init__.py +58 -58
- webscout/models.py +181 -181
- webscout/optimizers.py +419 -419
- webscout/prompt_manager.py +288 -288
- webscout/sanitize.py +1078 -1078
- webscout/scout/README.md +401 -401
- webscout/scout/__init__.py +8 -8
- webscout/scout/core/__init__.py +6 -6
- webscout/scout/core/crawler.py +297 -297
- webscout/scout/core/scout.py +706 -706
- webscout/scout/core/search_result.py +95 -95
- webscout/scout/core/text_analyzer.py +62 -62
- webscout/scout/core/text_utils.py +277 -277
- webscout/scout/core/web_analyzer.py +51 -51
- webscout/scout/element.py +599 -599
- webscout/scout/parsers/__init__.py +69 -69
- webscout/scout/parsers/html5lib_parser.py +172 -172
- webscout/scout/parsers/html_parser.py +236 -236
- webscout/scout/parsers/lxml_parser.py +178 -178
- webscout/scout/utils.py +37 -37
- webscout/swiftcli/Readme.md +323 -323
- webscout/swiftcli/__init__.py +95 -95
- webscout/swiftcli/core/__init__.py +7 -7
- webscout/swiftcli/core/cli.py +308 -308
- webscout/swiftcli/core/context.py +104 -104
- webscout/swiftcli/core/group.py +241 -241
- webscout/swiftcli/decorators/__init__.py +28 -28
- webscout/swiftcli/decorators/command.py +221 -221
- webscout/swiftcli/decorators/options.py +220 -220
- webscout/swiftcli/decorators/output.py +302 -302
- webscout/swiftcli/exceptions.py +21 -21
- webscout/swiftcli/plugins/__init__.py +9 -9
- webscout/swiftcli/plugins/base.py +135 -135
- webscout/swiftcli/plugins/manager.py +269 -269
- webscout/swiftcli/utils/__init__.py +59 -59
- webscout/swiftcli/utils/formatting.py +252 -252
- webscout/swiftcli/utils/parsing.py +267 -267
- webscout/update_checker.py +117 -117
- webscout/version.py +1 -1
- webscout/webscout_search.py +1183 -1183
- webscout/webscout_search_async.py +649 -649
- webscout/yep_search.py +346 -346
- webscout/zeroart/README.md +89 -89
- webscout/zeroart/__init__.py +134 -134
- webscout/zeroart/base.py +66 -66
- webscout/zeroart/effects.py +100 -100
- webscout/zeroart/fonts.py +1238 -1238
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/METADATA +937 -936
- webscout-2025.10.11.dist-info/RECORD +300 -0
- webscout/Provider/AISEARCH/DeepFind.py +0 -254
- webscout/Provider/AllenAI.py +0 -440
- webscout/Provider/Blackboxai.py +0 -793
- webscout/Provider/FreeGemini.py +0 -250
- webscout/Provider/GptOss.py +0 -207
- webscout/Provider/Hunyuan.py +0 -283
- webscout/Provider/Kimi.py +0 -445
- webscout/Provider/MCPCore.py +0 -322
- webscout/Provider/MiniMax.py +0 -207
- webscout/Provider/OPENAI/BLACKBOXAI.py +0 -1045
- webscout/Provider/OPENAI/MiniMax.py +0 -298
- webscout/Provider/OPENAI/Qwen3.py +0 -304
- webscout/Provider/OPENAI/autoproxy.py +0 -1067
- webscout/Provider/OPENAI/copilot.py +0 -321
- webscout/Provider/OPENAI/gptoss.py +0 -288
- webscout/Provider/OPENAI/kimi.py +0 -469
- webscout/Provider/OPENAI/mcpcore.py +0 -431
- webscout/Provider/OPENAI/multichat.py +0 -378
- webscout/Provider/OPENAI/qodo.py +0 -630
- webscout/Provider/OPENAI/xenai.py +0 -514
- webscout/Provider/Reka.py +0 -214
- webscout/Provider/UNFINISHED/fetch_together_models.py +0 -90
- webscout/Provider/asksteve.py +0 -220
- webscout/Provider/copilot.py +0 -441
- webscout/Provider/freeaichat.py +0 -294
- webscout/Provider/koala.py +0 -182
- webscout/Provider/lmarena.py +0 -198
- webscout/Provider/monochat.py +0 -275
- webscout/Provider/multichat.py +0 -375
- webscout/Provider/scnet.py +0 -244
- webscout/Provider/talkai.py +0 -194
- webscout/tempid.py +0 -128
- webscout-8.3.6.dist-info/RECORD +0 -327
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/WHEEL +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/entry_points.txt +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/licenses/LICENSE.md +0 -0
- {webscout-8.3.6.dist-info → webscout-2025.10.11.dist-info}/top_level.txt +0 -0
webscout/Provider/OPENAI/kimi.py
DELETED
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
import json
|
|
3
|
-
import time
|
|
4
|
-
import uuid
|
|
5
|
-
import random
|
|
6
|
-
from typing import List, Dict, Optional, Union, Generator, Any
|
|
7
|
-
|
|
8
|
-
# Import curl_cffi for improved request handling
|
|
9
|
-
from curl_cffi.requests import Session
|
|
10
|
-
from curl_cffi import CurlError
|
|
11
|
-
|
|
12
|
-
# Import base classes and utility structures
|
|
13
|
-
from .base import OpenAICompatibleProvider, BaseChat, BaseCompletions
|
|
14
|
-
from .utils import (
|
|
15
|
-
ChatCompletion,
|
|
16
|
-
ChatCompletionChunk,
|
|
17
|
-
Choice,
|
|
18
|
-
ChatCompletionMessage,
|
|
19
|
-
ChoiceDelta,
|
|
20
|
-
CompletionUsage,
|
|
21
|
-
format_prompt,
|
|
22
|
-
get_system_prompt,
|
|
23
|
-
count_tokens
|
|
24
|
-
)
|
|
25
|
-
|
|
26
|
-
# Attempt to import LitAgent, fallback if not available
|
|
27
|
-
try:
|
|
28
|
-
from webscout.litagent import LitAgent
|
|
29
|
-
except ImportError:
|
|
30
|
-
pass
|
|
31
|
-
|
|
32
|
-
from webscout import exceptions
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class Completions(BaseCompletions):
|
|
36
|
-
def __init__(self, client: 'Kimi'):
|
|
37
|
-
self._client = client
|
|
38
|
-
|
|
39
|
-
def create(
|
|
40
|
-
self,
|
|
41
|
-
*,
|
|
42
|
-
model: str,
|
|
43
|
-
messages: List[Dict[str, str]],
|
|
44
|
-
max_tokens: Optional[int] = 4000,
|
|
45
|
-
stream: bool = False,
|
|
46
|
-
temperature: Optional[float] = None,
|
|
47
|
-
top_p: Optional[float] = None,
|
|
48
|
-
timeout: Optional[int] = None,
|
|
49
|
-
proxies: Optional[Dict[str, str]] = None,
|
|
50
|
-
**kwargs: Any
|
|
51
|
-
) -> Union[ChatCompletion, Generator[ChatCompletionChunk, None, None]]:
|
|
52
|
-
"""
|
|
53
|
-
Create a completion using the Kimi API.
|
|
54
|
-
|
|
55
|
-
Args:
|
|
56
|
-
model: The model to use (k1.5, k2, k1.5-thinking)
|
|
57
|
-
messages: List of message dictionaries with 'role' and 'content'
|
|
58
|
-
max_tokens: Maximum tokens for response
|
|
59
|
-
stream: Whether to stream the response
|
|
60
|
-
temperature: Sampling temperature (not used by Kimi)
|
|
61
|
-
top_p: Top-p sampling (not used by Kimi)
|
|
62
|
-
timeout: Request timeout
|
|
63
|
-
proxies: Proxy configuration
|
|
64
|
-
|
|
65
|
-
Returns:
|
|
66
|
-
ChatCompletion or generator of ChatCompletionChunk
|
|
67
|
-
"""
|
|
68
|
-
# Validate model
|
|
69
|
-
if model not in self._client.AVAILABLE_MODELS:
|
|
70
|
-
raise ValueError(f"Invalid model: {model}. Choose from: {self._client.AVAILABLE_MODELS}")
|
|
71
|
-
|
|
72
|
-
# Ensure authentication and chat creation
|
|
73
|
-
self._client._authenticate()
|
|
74
|
-
self._client._create_chat()
|
|
75
|
-
|
|
76
|
-
# Format messages exactly like the original Kimi.py
|
|
77
|
-
# Use the first user message content directly, no formatting needed
|
|
78
|
-
user_content = ""
|
|
79
|
-
system_content = ""
|
|
80
|
-
|
|
81
|
-
for msg in messages:
|
|
82
|
-
role = msg.get("role", "user")
|
|
83
|
-
content = msg.get("content", "")
|
|
84
|
-
if role == "system":
|
|
85
|
-
system_content = content
|
|
86
|
-
elif role == "user":
|
|
87
|
-
user_content = content
|
|
88
|
-
|
|
89
|
-
# If we have system content, prepend it to user content
|
|
90
|
-
if system_content:
|
|
91
|
-
final_content = f"{system_content}\n\n{user_content}"
|
|
92
|
-
else:
|
|
93
|
-
final_content = user_content
|
|
94
|
-
|
|
95
|
-
# Create payload exactly like the original Kimi.py
|
|
96
|
-
payload = {
|
|
97
|
-
"kimiplus_id": "kimi",
|
|
98
|
-
"extend": {"sidebar": True},
|
|
99
|
-
"model": model,
|
|
100
|
-
"use_search": self._client.web_search,
|
|
101
|
-
"messages": [
|
|
102
|
-
{
|
|
103
|
-
"role": "user",
|
|
104
|
-
"content": final_content
|
|
105
|
-
}
|
|
106
|
-
],
|
|
107
|
-
"refs": [],
|
|
108
|
-
"history": [],
|
|
109
|
-
"scene_labels": [],
|
|
110
|
-
"use_semantic_memory": False,
|
|
111
|
-
"use_deep_research": False
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
# Generate request ID and timestamp
|
|
115
|
-
request_id = f"chatcmpl-{uuid.uuid4().hex}"
|
|
116
|
-
created_time = int(time.time())
|
|
117
|
-
|
|
118
|
-
if stream:
|
|
119
|
-
return self._create_stream(request_id, created_time, model, messages, payload, timeout, proxies)
|
|
120
|
-
else:
|
|
121
|
-
return self._create_non_stream(request_id, created_time, model, messages, payload, timeout, proxies)
|
|
122
|
-
|
|
123
|
-
def _create_stream(
|
|
124
|
-
self, request_id: str, created_time: int, model: str, messages: List[Dict[str, str]],
|
|
125
|
-
payload: Dict[str, Any], timeout: Optional[int] = None, proxies: Optional[Dict[str, str]] = None
|
|
126
|
-
) -> Generator[ChatCompletionChunk, None, None]:
|
|
127
|
-
try:
|
|
128
|
-
response = self._client.session.post(
|
|
129
|
-
self._client.chat_completion_endpoint.format(chat_id=self._client.chat_id),
|
|
130
|
-
json=payload,
|
|
131
|
-
stream=True,
|
|
132
|
-
timeout=timeout or self._client.timeout,
|
|
133
|
-
impersonate="chrome110"
|
|
134
|
-
)
|
|
135
|
-
response.raise_for_status()
|
|
136
|
-
|
|
137
|
-
# Calculate prompt tokens using the messages parameter
|
|
138
|
-
prompt_tokens = count_tokens(messages)
|
|
139
|
-
completion_tokens = 0
|
|
140
|
-
total_tokens = prompt_tokens
|
|
141
|
-
|
|
142
|
-
for line in response.iter_lines(decode_unicode=True):
|
|
143
|
-
if line:
|
|
144
|
-
if line.startswith("data: "):
|
|
145
|
-
json_str = line[6:]
|
|
146
|
-
if json_str == "[DONE]":
|
|
147
|
-
break
|
|
148
|
-
|
|
149
|
-
try:
|
|
150
|
-
data = json.loads(json_str)
|
|
151
|
-
if data.get("event") == "cmpl":
|
|
152
|
-
content = data.get("text")
|
|
153
|
-
if content:
|
|
154
|
-
completion_tokens += count_tokens(content)
|
|
155
|
-
total_tokens = prompt_tokens + completion_tokens
|
|
156
|
-
|
|
157
|
-
delta = ChoiceDelta(content=content, role=None, tool_calls=None)
|
|
158
|
-
choice = Choice(index=0, delta=delta, finish_reason=None, logprobs=None)
|
|
159
|
-
chunk = ChatCompletionChunk(
|
|
160
|
-
id=request_id,
|
|
161
|
-
choices=[choice],
|
|
162
|
-
created=created_time,
|
|
163
|
-
model=model,
|
|
164
|
-
system_fingerprint=None
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
# Add usage information
|
|
168
|
-
chunk.usage = {
|
|
169
|
-
"prompt_tokens": prompt_tokens,
|
|
170
|
-
"completion_tokens": completion_tokens,
|
|
171
|
-
"total_tokens": total_tokens,
|
|
172
|
-
"estimated_cost": None
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
yield chunk
|
|
176
|
-
except json.JSONDecodeError:
|
|
177
|
-
continue
|
|
178
|
-
|
|
179
|
-
# Final chunk with finish_reason="stop"
|
|
180
|
-
delta = ChoiceDelta(content=None, role=None, tool_calls=None)
|
|
181
|
-
choice = Choice(index=0, delta=delta, finish_reason="stop", logprobs=None)
|
|
182
|
-
chunk = ChatCompletionChunk(
|
|
183
|
-
id=request_id,
|
|
184
|
-
choices=[choice],
|
|
185
|
-
created=created_time,
|
|
186
|
-
model=model,
|
|
187
|
-
system_fingerprint=None
|
|
188
|
-
)
|
|
189
|
-
chunk.usage = {
|
|
190
|
-
"prompt_tokens": prompt_tokens,
|
|
191
|
-
"completion_tokens": completion_tokens,
|
|
192
|
-
"total_tokens": total_tokens,
|
|
193
|
-
"estimated_cost": None
|
|
194
|
-
}
|
|
195
|
-
yield chunk
|
|
196
|
-
|
|
197
|
-
except CurlError as e:
|
|
198
|
-
print(f"Error during Kimi stream request: {e}")
|
|
199
|
-
raise IOError(f"Kimi request failed: {e}") from e
|
|
200
|
-
except Exception as e:
|
|
201
|
-
print(f"Error processing Kimi stream: {e}")
|
|
202
|
-
raise
|
|
203
|
-
|
|
204
|
-
def _create_non_stream(
|
|
205
|
-
self, request_id: str, created_time: int, model: str, messages: List[Dict[str, str]],
|
|
206
|
-
payload: Dict[str, Any], timeout: Optional[int] = None, proxies: Optional[Dict[str, str]] = None
|
|
207
|
-
) -> ChatCompletion:
|
|
208
|
-
try:
|
|
209
|
-
response = self._client.session.post(
|
|
210
|
-
self._client.chat_completion_endpoint.format(chat_id=self._client.chat_id),
|
|
211
|
-
json=payload,
|
|
212
|
-
timeout=timeout or self._client.timeout,
|
|
213
|
-
impersonate="chrome110",
|
|
214
|
-
stream=True
|
|
215
|
-
)
|
|
216
|
-
response.raise_for_status()
|
|
217
|
-
|
|
218
|
-
# Collect all streaming data
|
|
219
|
-
full_text = ""
|
|
220
|
-
for line in response.iter_lines():
|
|
221
|
-
if line:
|
|
222
|
-
# Decode bytes to string if needed
|
|
223
|
-
if isinstance(line, bytes):
|
|
224
|
-
line = line.decode('utf-8')
|
|
225
|
-
if line.startswith("data: "):
|
|
226
|
-
json_str = line[6:]
|
|
227
|
-
if json_str == "[DONE]":
|
|
228
|
-
break
|
|
229
|
-
|
|
230
|
-
try:
|
|
231
|
-
data = json.loads(json_str)
|
|
232
|
-
if data.get("event") == "cmpl":
|
|
233
|
-
content = data.get("text")
|
|
234
|
-
if content:
|
|
235
|
-
full_text += content
|
|
236
|
-
except json.JSONDecodeError:
|
|
237
|
-
continue
|
|
238
|
-
|
|
239
|
-
# Create the message object
|
|
240
|
-
message = ChatCompletionMessage(
|
|
241
|
-
role="assistant",
|
|
242
|
-
content=full_text
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
# Create the choice object
|
|
246
|
-
choice = Choice(
|
|
247
|
-
index=0,
|
|
248
|
-
message=message,
|
|
249
|
-
finish_reason="stop"
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
# Create usage object with proper token counting
|
|
253
|
-
prompt_tokens = count_tokens(messages)
|
|
254
|
-
completion_tokens = count_tokens(full_text) if full_text else 0
|
|
255
|
-
usage = CompletionUsage(
|
|
256
|
-
prompt_tokens=prompt_tokens,
|
|
257
|
-
completion_tokens=completion_tokens,
|
|
258
|
-
total_tokens=prompt_tokens + completion_tokens
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
# Create the completion object
|
|
262
|
-
completion = ChatCompletion(
|
|
263
|
-
id=request_id,
|
|
264
|
-
choices=[choice],
|
|
265
|
-
created=created_time,
|
|
266
|
-
model=model,
|
|
267
|
-
usage=usage,
|
|
268
|
-
)
|
|
269
|
-
return completion
|
|
270
|
-
|
|
271
|
-
except CurlError as e:
|
|
272
|
-
print(f"Error during Kimi request: {e}")
|
|
273
|
-
raise IOError(f"Kimi request failed: {e}") from e
|
|
274
|
-
except Exception as e:
|
|
275
|
-
print(f"Error processing Kimi response: {e}")
|
|
276
|
-
raise
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
class Chat(BaseChat):
|
|
280
|
-
def __init__(self, client: 'Kimi'):
|
|
281
|
-
self._client = client
|
|
282
|
-
self.completions = Completions(client)
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
class Kimi(OpenAICompatibleProvider):
|
|
286
|
-
"""
|
|
287
|
-
OpenAI-compatible Kimi provider.
|
|
288
|
-
|
|
289
|
-
This provider implements the OpenAI API interface for Kimi models.
|
|
290
|
-
It supports the following models:
|
|
291
|
-
- k1.5
|
|
292
|
-
- k2
|
|
293
|
-
- k1.5-thinking
|
|
294
|
-
|
|
295
|
-
Examples:
|
|
296
|
-
>>> from webscout.Provider.OPENAI.kimi import Kimi
|
|
297
|
-
>>> client = Kimi()
|
|
298
|
-
>>> response = client.chat.completions.create(
|
|
299
|
-
... model="k2",
|
|
300
|
-
... messages=[{"role": "user", "content": "Hello!"}]
|
|
301
|
-
... )
|
|
302
|
-
>>> print(response.choices[0].message.content)
|
|
303
|
-
"""
|
|
304
|
-
|
|
305
|
-
AVAILABLE_MODELS = ["k1.5", "k2", "k1.5-thinking"]
|
|
306
|
-
|
|
307
|
-
def __init__(
|
|
308
|
-
self,
|
|
309
|
-
api_key: Optional[str] = None,
|
|
310
|
-
base_url: Optional[str] = None,
|
|
311
|
-
timeout: int = 30,
|
|
312
|
-
proxies: Optional[Dict[str, str]] = None,
|
|
313
|
-
browser: str = "chrome",
|
|
314
|
-
web_search: bool = False,
|
|
315
|
-
**kwargs
|
|
316
|
-
):
|
|
317
|
-
"""
|
|
318
|
-
Initialize the Kimi provider.
|
|
319
|
-
|
|
320
|
-
Args:
|
|
321
|
-
api_key: Not used for Kimi (authentication is handled via device registration)
|
|
322
|
-
base_url: Not used for Kimi
|
|
323
|
-
timeout: Request timeout in seconds
|
|
324
|
-
proxies: Proxy configuration
|
|
325
|
-
browser: Browser to impersonate
|
|
326
|
-
web_search: Whether to enable web search
|
|
327
|
-
**kwargs: Additional arguments
|
|
328
|
-
"""
|
|
329
|
-
super().__init__(api_key=api_key, base_url=base_url, timeout=timeout, **kwargs)
|
|
330
|
-
|
|
331
|
-
self.timeout = timeout
|
|
332
|
-
self.proxies = proxies or {}
|
|
333
|
-
self.web_search = web_search
|
|
334
|
-
|
|
335
|
-
# Kimi API endpoints
|
|
336
|
-
self.register_endpoint = "https://www.kimi.com/api/device/register"
|
|
337
|
-
self.chat_create_endpoint = "https://www.kimi.com/api/chat"
|
|
338
|
-
self.chat_completion_endpoint = "https://www.kimi.com/api/chat/{chat_id}/completion/stream"
|
|
339
|
-
|
|
340
|
-
# Initialize session
|
|
341
|
-
self.session = Session()
|
|
342
|
-
self.session.proxies = self.proxies
|
|
343
|
-
|
|
344
|
-
# Initialize LitAgent for browser fingerprinting
|
|
345
|
-
try:
|
|
346
|
-
self.agent = LitAgent()
|
|
347
|
-
self.fingerprint = self.agent.generate_fingerprint(browser)
|
|
348
|
-
except:
|
|
349
|
-
self.fingerprint = {
|
|
350
|
-
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
351
|
-
"accept_language": "en-US,en;q=0.9",
|
|
352
|
-
"sec_ch_ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
|
|
353
|
-
"platform": "Windows"
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
# Generate device ID
|
|
357
|
-
self.device_id = str(random.randint(1000000000000000, 9999999999999999))
|
|
358
|
-
|
|
359
|
-
# Headers for Kimi API
|
|
360
|
-
self.headers = {
|
|
361
|
-
"Accept": "text/event-stream",
|
|
362
|
-
"Accept-Language": self.fingerprint["accept_language"],
|
|
363
|
-
"Accept-Encoding": "gzip, deflate, br",
|
|
364
|
-
"Cache-Control": "no-cache",
|
|
365
|
-
"Connection": "keep-alive",
|
|
366
|
-
"Content-Type": "application/json",
|
|
367
|
-
"DNT": "1",
|
|
368
|
-
"Origin": "https://www.kimi.com",
|
|
369
|
-
"Pragma": "no-cache",
|
|
370
|
-
"Referer": "https://www.kimi.com/",
|
|
371
|
-
"Sec-CH-UA": self.fingerprint["sec_ch_ua"],
|
|
372
|
-
"Sec-CH-UA-Mobile": "?0",
|
|
373
|
-
"Sec-CH-UA-Platform": f'"{self.fingerprint["platform"]}"',
|
|
374
|
-
"User-Agent": self.fingerprint["user_agent"],
|
|
375
|
-
"x-msh-device-id": self.device_id,
|
|
376
|
-
"x-msh-platform": "web",
|
|
377
|
-
"x-traffic-id": self.device_id,
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
# Initialize authentication
|
|
381
|
-
self.access_token = None
|
|
382
|
-
self.chat_id = None
|
|
383
|
-
|
|
384
|
-
# Update session headers
|
|
385
|
-
self.session.headers.update(self.headers)
|
|
386
|
-
|
|
387
|
-
# Initialize chat and completions
|
|
388
|
-
self.chat = Chat(self)
|
|
389
|
-
self.completions = Completions(self)
|
|
390
|
-
|
|
391
|
-
@property
|
|
392
|
-
def models(self):
|
|
393
|
-
"""Property that returns an object with a .list() method returning available models."""
|
|
394
|
-
class _ModelList:
|
|
395
|
-
def list(inner_self):
|
|
396
|
-
return type(self).AVAILABLE_MODELS
|
|
397
|
-
return _ModelList()
|
|
398
|
-
|
|
399
|
-
def _authenticate(self) -> str:
|
|
400
|
-
"""Authenticate with Kimi API and get access token."""
|
|
401
|
-
if self.access_token:
|
|
402
|
-
return self.access_token
|
|
403
|
-
|
|
404
|
-
max_retries = 3
|
|
405
|
-
last_exception = None
|
|
406
|
-
|
|
407
|
-
for attempt in range(max_retries):
|
|
408
|
-
try:
|
|
409
|
-
response = self.session.post(
|
|
410
|
-
self.register_endpoint,
|
|
411
|
-
json={},
|
|
412
|
-
timeout=self.timeout,
|
|
413
|
-
impersonate="chrome110"
|
|
414
|
-
)
|
|
415
|
-
response.raise_for_status()
|
|
416
|
-
|
|
417
|
-
data = response.json()
|
|
418
|
-
if not data.get("access_token"):
|
|
419
|
-
raise exceptions.FailedToGenerateResponseError("No access token received")
|
|
420
|
-
|
|
421
|
-
self.access_token = data["access_token"]
|
|
422
|
-
self.session.headers["Authorization"] = f"Bearer {self.access_token}"
|
|
423
|
-
return self.access_token
|
|
424
|
-
|
|
425
|
-
except CurlError as e:
|
|
426
|
-
last_exception = e
|
|
427
|
-
if attempt < max_retries - 1:
|
|
428
|
-
continue
|
|
429
|
-
raise exceptions.FailedToGenerateResponseError(f"Authentication failed after {max_retries} attempts (CurlError): {e}")
|
|
430
|
-
except Exception as e:
|
|
431
|
-
last_exception = e
|
|
432
|
-
if attempt < max_retries - 1:
|
|
433
|
-
continue
|
|
434
|
-
raise exceptions.FailedToGenerateResponseError(f"Authentication failed after {max_retries} attempts: {e}")
|
|
435
|
-
|
|
436
|
-
def _create_chat(self) -> str:
|
|
437
|
-
"""Create a new chat session and return chat ID."""
|
|
438
|
-
if self.chat_id:
|
|
439
|
-
return self.chat_id
|
|
440
|
-
|
|
441
|
-
self._authenticate()
|
|
442
|
-
|
|
443
|
-
try:
|
|
444
|
-
response = self.session.post(
|
|
445
|
-
self.chat_create_endpoint,
|
|
446
|
-
json={
|
|
447
|
-
"name": "Unnamed Chat",
|
|
448
|
-
"born_from": "home",
|
|
449
|
-
"kimiplus_id": "kimi",
|
|
450
|
-
"is_example": False,
|
|
451
|
-
"source": "web",
|
|
452
|
-
"tags": []
|
|
453
|
-
},
|
|
454
|
-
timeout=self.timeout,
|
|
455
|
-
impersonate="chrome110"
|
|
456
|
-
)
|
|
457
|
-
response.raise_for_status()
|
|
458
|
-
|
|
459
|
-
data = response.json()
|
|
460
|
-
self.chat_id = data.get("id")
|
|
461
|
-
if not self.chat_id:
|
|
462
|
-
raise exceptions.FailedToGenerateResponseError("No chat ID received")
|
|
463
|
-
|
|
464
|
-
return self.chat_id
|
|
465
|
-
|
|
466
|
-
except CurlError as e:
|
|
467
|
-
raise exceptions.FailedToGenerateResponseError(f"Chat creation failed (CurlError): {e}")
|
|
468
|
-
except Exception as e:
|
|
469
|
-
raise exceptions.FailedToGenerateResponseError(f"Chat creation failed: {e}")
|