agenthub-python 0.4.6__tar.gz → 0.4.8__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 (37) hide show
  1. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/PKG-INFO +1 -1
  2. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/gemini3_7/client.py +26 -1
  3. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/glm5_3/client.py +20 -3
  4. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/integration/playground.py +2 -2
  5. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/registry.py +11 -0
  6. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/pyproject.toml +1 -1
  7. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/pyproject.toml.orig +1 -1
  8. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/README.md +0 -0
  9. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/__init__.py +0 -0
  10. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/abort_signal.py +0 -0
  11. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/ant_messages/__init__.py +0 -0
  12. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/ant_messages/client.py +0 -0
  13. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/auto_client.py +0 -0
  14. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/base_client.py +0 -0
  15. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/claude5/__init__.py +0 -0
  16. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/claude5/client.py +0 -0
  17. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/deepseek_v4/__init__.py +0 -0
  18. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/deepseek_v4/client.py +0 -0
  19. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/errors.py +0 -0
  20. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/gemini3_7/__init__.py +0 -0
  21. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/glm5_3/__init__.py +0 -0
  22. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/gpt5_6/__init__.py +0 -0
  23. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/gpt5_6/client.py +0 -0
  24. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/integration/__init__.py +0 -0
  25. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/integration/tracer.py +0 -0
  26. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/kimi_k3/__init__.py +0 -0
  27. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/kimi_k3/client.py +0 -0
  28. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/minimax_m3/__init__.py +0 -0
  29. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/minimax_m3/client.py +0 -0
  30. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/openai_chat/__init__.py +0 -0
  31. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/openai_chat/client.py +0 -0
  32. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/openai_embedding/__init__.py +0 -0
  33. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/openai_embedding/client.py +0 -0
  34. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/openai_responses/__init__.py +0 -0
  35. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/openai_responses/client.py +0 -0
  36. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/types.py +0 -0
  37. {agenthub_python-0.4.6 → agenthub_python-0.4.8}/agenthub/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agenthub-python
3
- Version: 0.4.6
3
+ Version: 0.4.8
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
@@ -43,6 +43,24 @@ from ..types import (
43
43
  from ..utils import is_debug_enabled
44
44
 
45
45
 
46
+ def _split_function_response_runs(parts: list[types.Part]) -> list[list[types.Part]]:
47
+ """Split parts into consecutive runs of function_response and other parts.
48
+
49
+ Vertex AI requires function responses to sit in a content of their own (see the call
50
+ site); order is preserved, and a message without function responses — or with nothing
51
+ else — comes back as one run.
52
+ """
53
+ runs: list[list[types.Part]] = []
54
+ last_is_response: bool | None = None
55
+ for part in parts:
56
+ is_response = part.function_response is not None
57
+ if is_response != last_is_response:
58
+ runs.append([])
59
+ last_is_response = is_response
60
+ runs[-1].append(part)
61
+ return runs if runs else [parts]
62
+
63
+
46
64
  class Gemini3_7Client(LLMClient):
47
65
  """Unified client for the Gemini family, named for the newest generation it serves (3.7).
48
66
 
@@ -377,7 +395,14 @@ class Gemini3_7Client(LLMClient):
377
395
  else:
378
396
  raise ValueError(f"Unknown item: {item}")
379
397
 
380
- contents.append(types.Content(role=mapping[msg["role"]], parts=parts))
398
+ # Vertex AI rejects a content that mixes function_response parts with any other
399
+ # part kind — the request fails with a misleading 400, "Requests ending with a
400
+ # model turn are not supported" (the Gemini API endpoint accepts the mix). Split
401
+ # such a message into consecutive same-role contents: each run of function
402
+ # responses becomes its own content, the surrounding parts keep theirs, and the
403
+ # part order is preserved. Homogeneous messages stay a single content.
404
+ for run_parts in _split_function_response_runs(parts):
405
+ contents.append(types.Content(role=mapping[msg["role"]], parts=run_parts))
381
406
 
382
407
  return contents
383
408
 
@@ -164,6 +164,12 @@ class GLM5_3Client(LLMClient):
164
164
  Returns:
165
165
  List of OpenAI message dictionaries
166
166
  """
167
+ # glm-5.3-flash is the natively multimodal GLM and the only one that reads image
168
+ # parts (https://docs.z.ai/guides/vlm/glm-5.3-flash); every other GLM answers a request
169
+ # carrying one with an error, so the item is refused here rather than dropped.
170
+ # Provider-hosted ids keep their own casing (e.g. z-ai/glm-5.3-flash), so the version
171
+ # match is case-insensitive.
172
+ supports_image = "glm-5.3-flash" in self._model.lower()
167
173
  openai_messages = []
168
174
 
169
175
  for msg in messages:
@@ -175,7 +181,10 @@ class GLM5_3Client(LLMClient):
175
181
  if item["type"] == "text":
176
182
  content_parts.append({"type": "text", "text": item["text"]})
177
183
  elif item["type"] == "image_url":
178
- raise ValueError("GLM-5 does not support image inputs.")
184
+ if not supports_image:
185
+ raise ValueError(f"GLM {self._model} does not support image inputs.")
186
+
187
+ content_parts.append({"type": "image_url", "image_url": {"url": item["image_url"]}})
179
188
  elif item["type"] == "thinking":
180
189
  thinking += item["thinking"]
181
190
  thinking_fields.add((item.get("fidelity") or {}).get("reasoning_field"))
@@ -194,15 +203,23 @@ class GLM5_3Client(LLMClient):
194
203
  if "tool_call_id" not in item:
195
204
  raise ValueError("tool_call_id is required for tool result.")
196
205
 
206
+ # a tool result without images stays a plain string, the only content shape
207
+ # the Chat Completion schema documents for a tool message
208
+ content = item["text"]
197
209
  if "images" in item and item["images"]:
198
- raise ValueError("GLM-5 does not support images in tool results.")
210
+ if not supports_image:
211
+ raise ValueError(f"GLM {self._model} does not support images in tool results.")
212
+
213
+ content = [{"type": "text", "text": item["text"]}]
214
+ for image_url in item["images"]:
215
+ content.append({"type": "image_url", "image_url": {"url": image_url}})
199
216
 
200
217
  # Tool results are sent as separate messages
201
218
  openai_messages.append(
202
219
  {
203
220
  "role": "tool",
204
221
  "tool_call_id": item["tool_call_id"],
205
- "content": item["text"],
222
+ "content": content,
206
223
  }
207
224
  )
208
225
  else:
@@ -225,8 +225,8 @@ def create_chat_app() -> Flask:
225
225
  <button type="button" role="option" aria-selected="false" class="w-full px-3 py-2 text-left hover:bg-gray-50 focus:bg-gray-50 focus:outline-none" data-combobox-option data-value="claude-sonnet-5" data-label="Claude Sonnet 5" data-description="claude-sonnet-5" onclick="selectComboboxOption('modelCombobox', this)">
226
226
  <span class="block truncate text-sm font-medium text-gray-900">Claude Sonnet 5</span>
227
227
  </button>
228
- <button type="button" role="option" aria-selected="false" class="w-full px-3 py-2 text-left hover:bg-gray-50 focus:bg-gray-50 focus:outline-none" data-combobox-option data-value="glm-5.3" data-label="GLM 5.3" data-description="glm-5.3" onclick="selectComboboxOption('modelCombobox', this)">
229
- <span class="block truncate text-sm font-medium text-gray-900">GLM 5.3</span>
228
+ <button type="button" role="option" aria-selected="false" class="w-full px-3 py-2 text-left hover:bg-gray-50 focus:bg-gray-50 focus:outline-none" data-combobox-option data-value="glm-5.3-flash" data-label="GLM 5.3 Flash" data-description="glm-5.3-flash" onclick="selectComboboxOption('modelCombobox', this)">
229
+ <span class="block truncate text-sm font-medium text-gray-900">GLM 5.3 Flash</span>
230
230
  </button>
231
231
  <button type="button" role="option" aria-selected="false" class="w-full px-3 py-2 text-left hover:bg-gray-50 focus:bg-gray-50 focus:outline-none" data-combobox-option data-value="kimi-k3" data-label="Kimi K3" data-description="kimi-k3" onclick="selectComboboxOption('modelCombobox', this)">
232
232
  <span class="block truncate text-sm font-medium text-gray-900">Kimi K3</span>
@@ -262,6 +262,17 @@ _SUPPORTED_MODELS: list[SupportedModel] = [
262
262
  "context_window": 1000000,
263
263
  "pricing": _usd(1.4, 4.4, cached=0.26),
264
264
  },
265
+ {
266
+ "model": "glm-5.3-flash",
267
+ "base_url": _ZAI,
268
+ "client": "glm-5.3",
269
+ "input_modalities": ["Text", "Image"],
270
+ "output_modalities": ["Text"],
271
+ "context_window": 1000000,
272
+ # official list price (verified 2026-08-26); a launch discount halves all three rates
273
+ # through 2026-09-09 (UTC+8)
274
+ "pricing": _usd(0.15, 0.5, cached=0.03),
275
+ },
265
276
  {
266
277
  "model": "glm-5.2",
267
278
  "base_url": _ZAI,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agenthub-python"
3
- version = "0.4.6"
3
+ version = "0.4.8"
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.6"
3
+ version = "0.4.8"
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"