agenthub-python 0.4.10__tar.gz → 0.4.11__tar.gz

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 (39) hide show
  1. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/PKG-INFO +1 -1
  2. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/auto_client.py +6 -4
  3. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/deepseek_v4/client.py +12 -4
  4. {agenthub_python-0.4.10/agenthub/gpt5_6 → agenthub_python-0.4.11/agenthub/gpt6}/__init__.py +2 -2
  5. {agenthub_python-0.4.10/agenthub/gpt5_6 → agenthub_python-0.4.11/agenthub/gpt6}/client.py +18 -6
  6. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/openai_chat/client.py +7 -2
  7. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/openai_responses/client.py +16 -3
  8. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/registry.py +49 -9
  9. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/pyproject.toml +1 -1
  10. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/pyproject.toml.orig +1 -1
  11. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/README.md +0 -0
  12. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/__init__.py +0 -0
  13. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/abort_signal.py +0 -0
  14. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/ant_messages/__init__.py +0 -0
  15. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/ant_messages/client.py +0 -0
  16. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/base_client.py +0 -0
  17. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/claude5/__init__.py +0 -0
  18. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/claude5/client.py +0 -0
  19. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/deepseek_v4/__init__.py +0 -0
  20. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/errors.py +0 -0
  21. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/gemini3_8/__init__.py +0 -0
  22. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/gemini3_8/client.py +0 -0
  23. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/glm5_3/__init__.py +0 -0
  24. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/glm5_3/client.py +0 -0
  25. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/integration/__init__.py +0 -0
  26. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/integration/playground.py +0 -0
  27. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/integration/tracer.py +0 -0
  28. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/kimi_k3/__init__.py +0 -0
  29. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/kimi_k3/client.py +0 -0
  30. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/minimax_m3/__init__.py +0 -0
  31. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/minimax_m3/client.py +0 -0
  32. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/openai_chat/__init__.py +0 -0
  33. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/openai_chat_vllm_adapter/__init__.py +0 -0
  34. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/openai_chat_vllm_adapter/client.py +0 -0
  35. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/openai_embedding/__init__.py +0 -0
  36. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/openai_embedding/client.py +0 -0
  37. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/openai_responses/__init__.py +0 -0
  38. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/types.py +0 -0
  39. {agenthub_python-0.4.10 → agenthub_python-0.4.11}/agenthub/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agenthub-python
3
- Version: 0.4.10
3
+ Version: 0.4.11
4
4
  Summary: AgentHub is the LLM API Hub for the Agent era, built for high-precision autonomous agents.
5
5
  Keywords: agent,llm,gemini,claude,gpt
6
6
  Author: PrismShadow
@@ -84,10 +84,12 @@ class AutoLLMClient(LLMClient):
84
84
  from .claude5 import Claude5Client
85
85
 
86
86
  return Claude5Client
87
- elif "gpt-5.4" in client_type or "gpt-5.5" in client_type or "gpt-5.6" in client_type: # e.g., gpt-5.6
88
- from .gpt5_6 import GPT5_6Client
87
+ elif (
88
+ "gpt-5.4" in client_type or "gpt-5.5" in client_type or "gpt-5.6" in client_type or "gpt-6" in client_type
89
+ ): # e.g., gpt-6-astra
90
+ from .gpt6 import GPT6Client
89
91
 
90
- return GPT5_6Client
92
+ return GPT6Client
91
93
  elif "glm-5" in client_type: # the whole GLM series shares the unified client
92
94
  from .glm5_3 import GLM5_3Client
93
95
 
@@ -144,7 +146,7 @@ class AutoLLMClient(LLMClient):
144
146
  raise ValueError(
145
147
  f"{client_type} is not supported. "
146
148
  "Supported client types: minimax-m3, gemini-3.8, gemini-3.7, gemini-3.6, gemini-3, "
147
- "claude-5, claude-4-8, claude-4-7, claude-4-6, gpt-5.6, gpt-5.5, gpt-5.4, "
149
+ "claude-5, claude-4-8, claude-4-7, claude-4-6, gpt-6, gpt-5.6, gpt-5.5, gpt-5.4, "
148
150
  "glm-5.3, glm-5.2, glm-5.1, kimi-k3, kimi-k2.6, kimi-k2.5, deepseek-v4, "
149
151
  "openai-chat-vllm-adapter, openai-embedding, ant-messages, openai-responses, openai-chat."
150
152
  )
@@ -14,6 +14,7 @@
14
14
 
15
15
  import json
16
16
  import os
17
+ import re
17
18
  from typing import Any, AsyncIterator
18
19
 
19
20
  from openai import AsyncOpenAI
@@ -36,6 +37,13 @@ from ..types import (
36
37
  from ..utils import is_debug_enabled
37
38
 
38
39
 
40
+ # The DeepSeek ids that read no image: the current V4 Flash and V4 Pro, bare or with a dated
41
+ # snapshot suffix (deepseek-v4-flash-0731). Every other id forwards its images. Matched against
42
+ # the bare id — the part after the last "/", lowercased — so a gateway prefix (deepseek/,
43
+ # deepseek-ai/) and the spelling a platform uses do not change the verdict.
44
+ _TEXT_ONLY_MODELS = re.compile(r"deepseek-v4-(flash|pro)(-\d{4})?")
45
+
46
+
39
47
  class DeepSeekV4Client(LLMClient):
40
48
  """DeepSeek V4-specific LLM client implementation using the OpenAI-compatible Responses API."""
41
49
 
@@ -142,10 +150,10 @@ class DeepSeekV4Client(LLMClient):
142
150
  Returns:
143
151
  List of input items for the Responses API
144
152
  """
145
- # only a vision model reads image parts; every other DeepSeek model answers from a
146
- # placeholder instead of failing (llmsdk_docs/deepseek_v4/docs/responses-api.md), so an
147
- # image is refused here rather than silently dropped
148
- supports_image = "vision" in self._model.lower()
153
+ # a text-only model answers from a placeholder instead of failing
154
+ # (llmsdk_docs/deepseek_v4/docs/responses-api.md), so an image is refused here rather
155
+ # than silently dropped
156
+ supports_image = not _TEXT_ONLY_MODELS.fullmatch(self._model.lower().rsplit("/", 1)[-1])
149
157
  input_list: list[ResponseInputParam] = []
150
158
 
151
159
  for msg in messages:
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from .client import GPT5_6Client
15
+ from .client import GPT6Client
16
16
 
17
17
 
18
- __all__ = ["GPT5_6Client"]
18
+ __all__ = ["GPT6Client"]
@@ -36,8 +36,8 @@ from ..types import (
36
36
  from ..utils import is_debug_enabled, openai_image_detail
37
37
 
38
38
 
39
- class GPT5_6Client(LLMClient):
40
- """GPT-5.6-specific LLM client implementation (also serves GPT-5.4 and GPT-5.5)."""
39
+ class GPT6Client(LLMClient):
40
+ """GPT-6-specific LLM client implementation (also serves GPT-5.6, GPT-5.5 and GPT-5.4)."""
41
41
 
42
42
  def __init__(
43
43
  self,
@@ -46,7 +46,7 @@ class GPT5_6Client(LLMClient):
46
46
  base_url: str | None = None,
47
47
  default_headers: dict[str, str] | None = None,
48
48
  ):
49
- """Initialize GPT-5.6 client with model and API key."""
49
+ """Initialize GPT-6 client with model and API key."""
50
50
  self._model = model
51
51
  api_key = api_key or os.getenv("OPENAI_API_KEY")
52
52
  base_url = base_url or os.getenv("OPENAI_BASE_URL")
@@ -55,6 +55,13 @@ class GPT5_6Client(LLMClient):
55
55
 
56
56
  def _convert_thinking_level_to_effort(self, thinking_level: ThinkingLevel) -> str:
57
57
  """Convert ThinkingLevel enum to OpenAI's reasoning effort."""
58
+ if thinking_level == ThinkingLevel.NONE and "gpt-6" in self._model:
59
+ # GPT-6 rejects both "none" and "minimal" with a 400 (verified live 2026-09-09:
60
+ # "Unsupported value: 'none' is not supported with the 'gpt-6-astra' model.
61
+ # Supported values are: 'low', 'medium', 'high', 'xhigh', and 'max'."), so NONE
62
+ # degrades to the lowest effort the generation accepts.
63
+ return "low"
64
+
58
65
  mapping = {
59
66
  ThinkingLevel.NONE: "none",
60
67
  ThinkingLevel.LOW: "low",
@@ -101,7 +108,7 @@ class GPT5_6Client(LLMClient):
101
108
 
102
109
  if config.get("temperature") is not None and config["temperature"] != 1.0:
103
110
  raise UnsupportedParameterError(
104
- self.__class__.__name__, "temperature", "GPT-5.6 does not support setting temperature."
111
+ self.__class__.__name__, "temperature", "GPT-6 does not support setting temperature."
105
112
  )
106
113
 
107
114
  if config.get("thinking_level") is not None:
@@ -124,7 +131,7 @@ class GPT5_6Client(LLMClient):
124
131
 
125
132
  if config.get("prompt_caching") is not None and config["prompt_caching"] != PromptCaching.ENABLE:
126
133
  raise UnsupportedParameterError(
127
- self.__class__.__name__, "prompt_caching", "prompt_caching must be ENABLE for GPT-5.6."
134
+ self.__class__.__name__, "prompt_caching", "prompt_caching must be ENABLE for GPT-6."
128
135
  )
129
136
 
130
137
  return openai_config
@@ -306,7 +313,12 @@ class GPT5_6Client(LLMClient):
306
313
  # the completed item carries the canonical wire fields to send back on the
307
314
  # next turn (identical to the response.completed copy, but adjacent to the
308
315
  # thinking deltas so the fidelity lands on the item that carried the text);
309
- # record the channel plus the fields the server demands back
316
+ # record the channel plus the fields the server demands back. This event is the
317
+ # only source of encrypted_content, because the streaming-events reference says
318
+ # of response.output_item.added: "For reasoning items, encrypted_content may be
319
+ # incomplete while the item is in progress. Use the reasoning item from the
320
+ # corresponding response.output_item.done event when passing it as input to a
321
+ # subsequent request."
310
322
  event_type = "delta"
311
323
  fidelity = {}
312
324
  if getattr(model_output.item, "summary", None):
@@ -173,7 +173,7 @@ class OpenaiChatClient(LLMClient):
173
173
  if "tool_call_id" not in item:
174
174
  raise ValueError("tool_call_id is required for tool result.")
175
175
 
176
- content = [{"type": "text", "text": item["text"]}]
176
+ image_parts = []
177
177
 
178
178
  if "images" in item and item["images"]:
179
179
  for image_url in item["images"]:
@@ -182,7 +182,12 @@ class OpenaiChatClient(LLMClient):
182
182
  # siliconflow does not support image_url in tool result
183
183
  content_parts.append(part)
184
184
  else:
185
- content.append(part)
185
+ image_parts.append(part)
186
+
187
+ # a plain string is the form every OpenAI-compatible server accepts for a text
188
+ # result; the content-part list is reserved for results carrying images, which
189
+ # only servers with multimodal tool messages take
190
+ content = [{"type": "text", "text": item["text"]}, *image_parts] if image_parts else item["text"]
186
191
 
187
192
  # Tool results are sent as separate messages
188
193
  openai_messages.append(
@@ -55,6 +55,12 @@ class OpenaiResponsesClient(LLMClient):
55
55
 
56
56
  def _convert_thinking_level_to_effort(self, thinking_level: ThinkingLevel) -> str:
57
57
  """Convert ThinkingLevel enum to the Responses API reasoning effort."""
58
+ if thinking_level == ThinkingLevel.NONE and "gpt-6" in self._model:
59
+ # a gateway serving GPT-6 forwards the effort to OpenAI, which rejects "none" and
60
+ # "minimal" with a 400 (verified live 2026-09-09 against api.openai.com), so NONE
61
+ # degrades to the lowest effort the generation accepts.
62
+ return "low"
63
+
58
64
  mapping = {
59
65
  ThinkingLevel.NONE: "none",
60
66
  ThinkingLevel.LOW: "low",
@@ -202,13 +208,20 @@ class OpenaiResponsesClient(LLMClient):
202
208
  raise ValueError("tool_call_id is required for tool result.")
203
209
 
204
210
  # NOTE: tool results are input items
205
- tool_result = [{"type": "input_text", "text": item["text"]}]
211
+ image_parts = []
206
212
  if "images" in item:
207
213
  for image_url in item["images"]:
208
- tool_result.append(self._convert_image_url(image_url))
214
+ image_parts.append(self._convert_image_url(image_url))
215
+
216
+ # a plain string is the form every OpenAI-compatible server accepts for a text
217
+ # result; the content-part list is reserved for results carrying images, which
218
+ # only servers with multimodal tool messages take
219
+ output = (
220
+ [{"type": "input_text", "text": item["text"]}, *image_parts] if image_parts else item["text"]
221
+ )
209
222
 
210
223
  input_list.append(
211
- {"type": "function_call_output", "call_id": item["tool_call_id"], "output": tool_result}
224
+ {"type": "function_call_output", "call_id": item["tool_call_id"], "output": output}
212
225
  )
213
226
  else:
214
227
  raise ValueError(f"Unknown item: {item}")
@@ -212,11 +212,24 @@ _SUPPORTED_MODELS: list[SupportedModel] = [
212
212
  "context_window": 1000000,
213
213
  "pricing": _usd(3.0, 15.0, cached=0.3),
214
214
  },
215
+ {
216
+ # official list price per 1M tokens: $1 cached input, $10 uncached input, $12.5 cache
217
+ # writes, $50 output, all doubled above 272K input tokens except output, which is 1.5x.
218
+ # The prompt bucket carries the cache-write rate: the usage buckets do not separate
219
+ # cache-written input from plain input.
220
+ "model": "gpt-6-astra",
221
+ "base_url": _OPENAI,
222
+ "client": "gpt-6",
223
+ "input_modalities": ["Text", "Image"],
224
+ "output_modalities": ["Text"],
225
+ "context_window": 1050000,
226
+ "pricing": _usd(12.5, 50.0, cached=1.0),
227
+ },
215
228
  {
216
229
  # official standard-tier list price; the bare gpt-5.6 alias also routes here
217
230
  "model": "gpt-5.6-sol",
218
231
  "base_url": _OPENAI,
219
- "client": "gpt-5.6",
232
+ "client": "gpt-6",
220
233
  "input_modalities": ["Text", "Image"],
221
234
  "output_modalities": ["Text"],
222
235
  "context_window": 1050000,
@@ -225,7 +238,7 @@ _SUPPORTED_MODELS: list[SupportedModel] = [
225
238
  {
226
239
  "model": "gpt-5.6-terra",
227
240
  "base_url": _OPENAI,
228
- "client": "gpt-5.6",
241
+ "client": "gpt-6",
229
242
  "input_modalities": ["Text", "Image"],
230
243
  "output_modalities": ["Text"],
231
244
  "context_window": 1050000,
@@ -234,7 +247,7 @@ _SUPPORTED_MODELS: list[SupportedModel] = [
234
247
  {
235
248
  "model": "gpt-5.6-luna",
236
249
  "base_url": _OPENAI,
237
- "client": "gpt-5.6",
250
+ "client": "gpt-6",
238
251
  "input_modalities": ["Text", "Image"],
239
252
  "output_modalities": ["Text"],
240
253
  "context_window": 1050000,
@@ -323,6 +336,20 @@ _SUPPORTED_MODELS: list[SupportedModel] = [
323
336
  "context_window": 262144,
324
337
  "pricing": _cny(6.5, 27.0, cached=1.1),
325
338
  },
339
+ {
340
+ "model": "deepseek-v4.1-flash",
341
+ "base_url": _DEEPSEEK,
342
+ "client": "deepseek-v4",
343
+ # announced by DeepSeek for release after 2026-09-10 and not yet served on
344
+ # 2026-09-09; multimodal per the announcement
345
+ "input_modalities": ["Text", "Image"],
346
+ "output_modalities": ["Text"],
347
+ # assumed equal to deepseek-v4-flash until the official model page lists it
348
+ "context_window": 1000000,
349
+ # priced as the V4 Flash series: official off-peak list price effective 2026-09-10,
350
+ # and peak-hour rates (Beijing 9:00-12:00, 14:00-18:00) are double
351
+ "pricing": _cny(1.0, 4.0, cached=0.02),
352
+ },
326
353
  {
327
354
  "model": "deepseek-v4-flash",
328
355
  "base_url": _DEEPSEEK,
@@ -330,9 +357,10 @@ _SUPPORTED_MODELS: list[SupportedModel] = [
330
357
  "input_modalities": ["Text"],
331
358
  "output_modalities": ["Text"],
332
359
  "context_window": 1000000,
333
- # official off-peak list price (verified 2026-08-18); peak-hour rates
334
- # (Beijing 9:00-12:00, 14:00-18:00) are double
335
- "pricing": _cny(1.5, 4.5, cached=0.05),
360
+ # official off-peak list price effective 2026-09-10 (verified 2026-09-08 against
361
+ # the official adjustment); peak-hour rates (Beijing 9:00-12:00, 14:00-18:00) are
362
+ # double
363
+ "pricing": _cny(1.0, 4.0, cached=0.02),
336
364
  },
337
365
  {
338
366
  "model": "deepseek-v4-flash-vision-exp",
@@ -341,9 +369,10 @@ _SUPPORTED_MODELS: list[SupportedModel] = [
341
369
  "input_modalities": ["Text", "Image"],
342
370
  "output_modalities": ["Text"],
343
371
  "context_window": 1000000,
344
- # priced as deepseek-v4-flash; official off-peak list price (verified 2026-08-21), and
345
- # peak-hour rates (Beijing 9:00-12:00, 14:00-18:00) are double
346
- "pricing": _cny(1.5, 4.5, cached=0.05),
372
+ # priced as deepseek-v4-flash; official off-peak list price effective 2026-09-10
373
+ # (verified 2026-09-08 against the official adjustment), and peak-hour rates
374
+ # (Beijing 9:00-12:00, 14:00-18:00) are double
375
+ "pricing": _cny(1.0, 4.0, cached=0.02),
347
376
  },
348
377
  {
349
378
  "model": "deepseek-v4-pro",
@@ -465,6 +494,17 @@ _SUPPORTED_MODELS: list[SupportedModel] = [
465
494
  "context_window": 1000000,
466
495
  "pricing": _usd(0.0, 0.0),
467
496
  },
497
+ {
498
+ # models API 2026-09-09, default OpenAI endpoint, no discount: $10 input, $50 output,
499
+ # $1 cache read, $12.5 cache write per 1M tokens
500
+ "model": "openai/gpt-6-astra",
501
+ "base_url": _OPENROUTER,
502
+ "client": "openai-responses",
503
+ "input_modalities": ["Text", "Image"],
504
+ "output_modalities": ["Text"],
505
+ "context_window": 1050000,
506
+ "pricing": _usd(12.5, 50.0, cached=1.0),
507
+ },
468
508
  {
469
509
  "model": "openai/gpt-5.6-sol",
470
510
  "base_url": _OPENROUTER,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agenthub-python"
3
- version = "0.4.10"
3
+ version = "0.4.11"
4
4
  description = "AgentHub is the LLM API Hub for the Agent era, built for high-precision autonomous agents."
5
5
  keywords = [
6
6
  "agent",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agenthub-python"
3
- version = "0.4.10"
3
+ version = "0.4.11"
4
4
  description = "AgentHub is the LLM API Hub for the Agent era, built for high-precision autonomous agents."
5
5
  keywords = ["agent", "llm", "gemini", "claude", "gpt"]
6
6
  readme = "README.md"