agenthub-python 0.2.0__tar.gz → 0.3.1__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 (27) hide show
  1. agenthub_python-0.3.1/PKG-INFO +347 -0
  2. agenthub_python-0.3.1/README.md +326 -0
  3. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/auto_client.py +26 -11
  4. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/base_client.py +94 -15
  5. {agenthub_python-0.2.0/agenthub/claude4_5 → agenthub_python-0.3.1/agenthub/claude4_6}/__init__.py +2 -2
  6. agenthub_python-0.3.1/agenthub/claude4_6/client.py +426 -0
  7. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/gemini3/client.py +170 -45
  8. {agenthub_python-0.2.0/agenthub/gpt5_2 → agenthub_python-0.3.1/agenthub/glm5}/__init__.py +2 -2
  9. {agenthub_python-0.2.0/agenthub/glm4_7 → agenthub_python-0.3.1/agenthub/glm5}/client.py +114 -62
  10. {agenthub_python-0.2.0/agenthub/glm4_7 → agenthub_python-0.3.1/agenthub/gpt5_5}/__init__.py +2 -2
  11. {agenthub_python-0.2.0/agenthub/gpt5_2 → agenthub_python-0.3.1/agenthub/gpt5_5}/client.py +59 -21
  12. agenthub_python-0.3.1/agenthub/integration/playground.py +762 -0
  13. agenthub_python-0.3.1/agenthub/integration/tracer.py +746 -0
  14. agenthub_python-0.3.1/agenthub/kimi_k2_5/__init__.py +18 -0
  15. agenthub_python-0.3.1/agenthub/kimi_k2_5/client.py +388 -0
  16. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/qwen3/client.py +106 -60
  17. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/types.py +48 -4
  18. agenthub_python-0.3.1/agenthub/utils.py +35 -0
  19. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/pyproject.toml +11 -5
  20. agenthub_python-0.2.0/PKG-INFO +0 -9
  21. agenthub_python-0.2.0/agenthub/claude4_5/client.py +0 -347
  22. agenthub_python-0.2.0/agenthub/integration/playground.py +0 -771
  23. agenthub_python-0.2.0/agenthub/integration/tracer.py +0 -750
  24. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/__init__.py +0 -0
  25. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/gemini3/__init__.py +0 -0
  26. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/integration/__init__.py +0 -0
  27. {agenthub_python-0.2.0 → agenthub_python-0.3.1}/agenthub/qwen3/__init__.py +0 -0
@@ -0,0 +1,347 @@
1
+ Metadata-Version: 2.4
2
+ Name: agenthub-python
3
+ Version: 0.3.1
4
+ Summary: AgentHub is the LLM API Hub for the Agent era, built for high-precision autonomous agents.
5
+ Keywords: agent,llm,gemini,claude,gpt
6
+ Author: PrismShadow
7
+ License-Expression: Apache-2.0
8
+ Requires-Dist: google-genai>=1.70.0
9
+ Requires-Dist: anthropic[bedrock]>=0.87.0
10
+ Requires-Dist: flask>=3.0.0
11
+ Requires-Dist: openai>=2.30.0
12
+ Requires-Dist: httpx>=0.27.0
13
+ Requires-Dist: httpx[socks] ; extra == 'dev'
14
+ Requires-Dist: pytest>=8.4.2 ; extra == 'dev'
15
+ Requires-Dist: pytest-asyncio>=0.23.0 ; extra == 'dev'
16
+ Requires-Dist: ruff>=0.14.3 ; extra == 'dev'
17
+ Requires-Dist: pillow>=10.0.0 ; extra == 'dev'
18
+ Requires-Python: >=3.11
19
+ Provides-Extra: dev
20
+ Description-Content-Type: text/markdown
21
+
22
+ # AgentHub Python Implementation
23
+
24
+ This document demonstrates how to use `AutoLLMClient` for unified LLM interactions in AgentHub.
25
+
26
+ ## Building
27
+
28
+ ```bash
29
+ make install # Install dependencies
30
+ make build # Build Python package
31
+ make lint # Run ruff linter
32
+ make test # Run tests
33
+ ```
34
+
35
+ ## AutoLLMClient Overview
36
+
37
+ `AutoLLMClient` is a stateful client that automatically routes requests to the appropriate model-specific implementation. It maintains conversation history and provides a unified interface for different LLM providers.
38
+
39
+ ### Initialization
40
+
41
+ Create a client by specifying the model name:
42
+
43
+ ```python
44
+ from agenthub import AutoLLMClient
45
+
46
+ # Initialize with model name
47
+ client = AutoLLMClient(model="gpt-5.5")
48
+
49
+ # Optionally specify API key (if not using environment variables)
50
+ client = AutoLLMClient(model="gpt-5.5", api_key="your-openai-api-key")
51
+ ```
52
+
53
+ The client automatically selects the appropriate client based on the model name.
54
+
55
+ ## Core Methods
56
+
57
+ ### streaming_response
58
+
59
+ Stateless method that requires passing the full message history on each call:
60
+
61
+ ```python
62
+ import asyncio
63
+ from agenthub import AutoLLMClient
64
+
65
+ async def main():
66
+ client = AutoLLMClient(model="gpt-5.5")
67
+
68
+ async for event in client.streaming_response(
69
+ messages=[
70
+ {
71
+ "role": "user",
72
+ "content_items": [{"type": "text", "text": "Hello!"}]
73
+ }
74
+ ],
75
+ config={}
76
+ ):
77
+ print(event)
78
+
79
+ asyncio.run(main())
80
+ ```
81
+
82
+ ### streaming_response_stateful
83
+
84
+ Stateful method that maintains conversation history internally:
85
+
86
+ ```python
87
+ import asyncio
88
+ from agenthub import AutoLLMClient
89
+
90
+ async def main():
91
+ client = AutoLLMClient(model="gpt-5.5")
92
+
93
+ # First message
94
+ async for event in client.streaming_response_stateful(
95
+ message={
96
+ "role": "user",
97
+ "content_items": [{"type": "text", "text": "My name is Alice"}]
98
+ },
99
+ config={}
100
+ ):
101
+ print(event)
102
+
103
+ # Second message - history is maintained automatically
104
+ async for event in client.streaming_response_stateful(
105
+ message={
106
+ "role": "user",
107
+ "content_items": [{"type": "text", "text": "What's my name?"}]
108
+ },
109
+ config={}
110
+ ):
111
+ print(event)
112
+
113
+ asyncio.run(main())
114
+ ```
115
+
116
+ ### get_history
117
+
118
+ Retrieve the conversation history:
119
+
120
+ ```python
121
+ # Get all messages in the conversation
122
+ history = client.get_history()
123
+ print(f"Total messages: {len(history)}")
124
+
125
+ for msg in history:
126
+ print(f"Role: {msg['role']}")
127
+ print(f"Content: {msg['content_items']}")
128
+ ```
129
+
130
+ ### clear_history
131
+
132
+ Clear the conversation history:
133
+
134
+ ```python
135
+ # Clear all conversation history
136
+ client.clear_history()
137
+
138
+ # Verify history is empty
139
+ assert len(client.get_history()) == 0
140
+ ```
141
+
142
+ ### set_history
143
+
144
+ Replace the conversation history with a copy of the provided list:
145
+
146
+ ```python
147
+ # Save current history
148
+ saved_history = client.get_history()
149
+
150
+ # ... do other things, then restore
151
+ client.set_history(saved_history)
152
+
153
+ # Verify history was replaced
154
+ assert len(client.get_history()) == len(saved_history)
155
+ ```
156
+
157
+ ## Tool Calling
158
+
159
+ When using tools, you must handle `tool_call_id` correctly:
160
+
161
+ ```python
162
+ import asyncio
163
+ import json
164
+ from agenthub import AutoLLMClient
165
+
166
+ def get_weather(location: str) -> str:
167
+ """Mock function to get weather."""
168
+ return f"Temperature in {location}: 22°C"
169
+
170
+ async def main():
171
+ # Define tool
172
+ weather_function = {
173
+ "name": "get_weather",
174
+ "description": "Gets the current weather for a given location.",
175
+ "parameters": {
176
+ "type": "object",
177
+ "properties": {
178
+ "location": {
179
+ "type": "string",
180
+ "description": "The city name"
181
+ }
182
+ },
183
+ "required": ["location"]
184
+ }
185
+ }
186
+
187
+ client = AutoLLMClient(model="gpt-5.5")
188
+ config = {"tools": [weather_function]}
189
+
190
+ # User asks about weather
191
+ events = []
192
+ async for event in client.streaming_response_stateful(
193
+ message={
194
+ "role": "user",
195
+ "content_items": [{"type": "text", "text": "What's the weather in London?"}]
196
+ },
197
+ config=config
198
+ ):
199
+ events.append(event)
200
+
201
+ # Extract function call and tool_call_id
202
+ tool_call = None
203
+ for event in events:
204
+ for item in event["content_items"]:
205
+ if item["type"] == "tool_call":
206
+ tool_call = item
207
+ break
208
+
209
+ if tool_call:
210
+ break
211
+
212
+ # Execute function and send result back with tool_call_id
213
+ if tool_call:
214
+ result = get_weather(**tool_call["argument"])
215
+
216
+ # IMPORTANT: Include tool_call_id in the tool response
217
+ async for event in client.streaming_response_stateful(
218
+ message={
219
+ "role": "user",
220
+ "content_items": [
221
+ {
222
+ "type": "tool_result",
223
+ "text": result,
224
+ "tool_call_id": tool_call["tool_call_id"] # Required for tool responses
225
+ }
226
+ ]
227
+ },
228
+ config=config
229
+ ):
230
+ print(event)
231
+
232
+ asyncio.run(main())
233
+ ```
234
+
235
+ ## Message Format
236
+
237
+ ### UniMessage Structure
238
+
239
+ ```python
240
+ {
241
+ "role": "user" | "assistant",
242
+ "content_items": [
243
+ {"type": "text", "text": "Hello"},
244
+ {"type": "image_url", "image_url": "https://..."},
245
+ {"type": "tool_call", "name": "get_weather", "argument": {"location": "London"}, "tool_call_id": "call_abc123"}
246
+ ]
247
+ }
248
+ ```
249
+
250
+ ### Tool Response with tool_call_id
251
+
252
+ When responding to a tool call, include the `tool_call_id` in the result content item:
253
+
254
+ ```python
255
+ {
256
+ "role": "user",
257
+ "content_items": [
258
+ {
259
+ "type": "tool_result",
260
+ "text": "London is 22°C today.",
261
+ "tool_call_id": "call_abc123" # From tool_call event
262
+ }
263
+ ]
264
+ }
265
+ ```
266
+
267
+ ## Configuration Options
268
+
269
+ ```python
270
+ from agenthub import PromptCaching, ThinkingLevel
271
+
272
+ config = {
273
+ "max_tokens": 500,
274
+ "temperature": 1.0,
275
+ "tools": [tool_definition],
276
+ "thinking_summary": True,
277
+ "thinking_level": ThinkingLevel.HIGH,
278
+ "tool_choice": "auto", # "auto", "required", "none", or ["tool_name"]
279
+ "system_prompt": "You are a helpful assistant",
280
+ "prompt_caching": PromptCaching.ENABLE,
281
+ "trace_id": "agent1/conversation_001" # Optional: save conversation trace
282
+ }
283
+ ```
284
+
285
+ ## Conversation Tracing
286
+
287
+ AgentHub provides a built-in `Tracer` to save and browse conversation history. When you specify a `trace_id` in the config, conversations are automatically saved to both JSON and TXT formats.
288
+
289
+ ### Basic Usage
290
+
291
+ ```python
292
+ from agenthub import AutoLLMClient
293
+
294
+ client = AutoLLMClient(model="gpt-5.5")
295
+
296
+ # Add trace_id to config
297
+ config = {"trace_id": "agent1/conversation_001"}
298
+
299
+ async for event in client.streaming_response_stateful(
300
+ message={"role": "user", "content_items": [{"type": "text", "text": "Hello"}]},
301
+ config=config
302
+ ):
303
+ pass # Conversation is automatically saved
304
+ ```
305
+
306
+ The default cache directory is `cache`, you can change it by setting `AGENTHUB_CACHE_DIR` environment variable.
307
+
308
+ This creates two files in the `cache` directory:
309
+ - `cache/agent1/conversation_001.json` - Structured data with full history and config
310
+ - `cache/agent1/conversation_001.txt` - Human-readable conversation format
311
+
312
+ ### Browsing Traces with Web Interface
313
+
314
+ Start a web server to browse and view saved conversations:
315
+
316
+ ```python
317
+ from agenthub.integration.tracer import Tracer
318
+
319
+ # Start web server
320
+ Tracer("path/to/cache").start_web_server(host="127.0.0.1", port=25750)
321
+ ```
322
+
323
+ Or use the CLI:
324
+
325
+ ```bash
326
+ python -m agenthub.integration.tracer --cache_dir ./cache --host 127.0.0.1 --port 25750
327
+ ```
328
+
329
+ Then visit `http://127.0.0.1:25750` in your browser to browse saved conversations.
330
+
331
+ ### Test with Playground
332
+
333
+ Start a web server to test with the playground:
334
+
335
+ ```python
336
+ from agenthub.integration.playground import start_playground_server
337
+
338
+ start_playground_server()
339
+ ```
340
+
341
+ Or use the CLI:
342
+
343
+ ```bash
344
+ python -m agenthub.integration.playground --host 127.0.0.1 --port 25751
345
+ ```
346
+
347
+ Then visit `http://127.0.0.1:25751` in your browser to test with the playground.
@@ -0,0 +1,326 @@
1
+ # AgentHub Python Implementation
2
+
3
+ This document demonstrates how to use `AutoLLMClient` for unified LLM interactions in AgentHub.
4
+
5
+ ## Building
6
+
7
+ ```bash
8
+ make install # Install dependencies
9
+ make build # Build Python package
10
+ make lint # Run ruff linter
11
+ make test # Run tests
12
+ ```
13
+
14
+ ## AutoLLMClient Overview
15
+
16
+ `AutoLLMClient` is a stateful client that automatically routes requests to the appropriate model-specific implementation. It maintains conversation history and provides a unified interface for different LLM providers.
17
+
18
+ ### Initialization
19
+
20
+ Create a client by specifying the model name:
21
+
22
+ ```python
23
+ from agenthub import AutoLLMClient
24
+
25
+ # Initialize with model name
26
+ client = AutoLLMClient(model="gpt-5.5")
27
+
28
+ # Optionally specify API key (if not using environment variables)
29
+ client = AutoLLMClient(model="gpt-5.5", api_key="your-openai-api-key")
30
+ ```
31
+
32
+ The client automatically selects the appropriate client based on the model name.
33
+
34
+ ## Core Methods
35
+
36
+ ### streaming_response
37
+
38
+ Stateless method that requires passing the full message history on each call:
39
+
40
+ ```python
41
+ import asyncio
42
+ from agenthub import AutoLLMClient
43
+
44
+ async def main():
45
+ client = AutoLLMClient(model="gpt-5.5")
46
+
47
+ async for event in client.streaming_response(
48
+ messages=[
49
+ {
50
+ "role": "user",
51
+ "content_items": [{"type": "text", "text": "Hello!"}]
52
+ }
53
+ ],
54
+ config={}
55
+ ):
56
+ print(event)
57
+
58
+ asyncio.run(main())
59
+ ```
60
+
61
+ ### streaming_response_stateful
62
+
63
+ Stateful method that maintains conversation history internally:
64
+
65
+ ```python
66
+ import asyncio
67
+ from agenthub import AutoLLMClient
68
+
69
+ async def main():
70
+ client = AutoLLMClient(model="gpt-5.5")
71
+
72
+ # First message
73
+ async for event in client.streaming_response_stateful(
74
+ message={
75
+ "role": "user",
76
+ "content_items": [{"type": "text", "text": "My name is Alice"}]
77
+ },
78
+ config={}
79
+ ):
80
+ print(event)
81
+
82
+ # Second message - history is maintained automatically
83
+ async for event in client.streaming_response_stateful(
84
+ message={
85
+ "role": "user",
86
+ "content_items": [{"type": "text", "text": "What's my name?"}]
87
+ },
88
+ config={}
89
+ ):
90
+ print(event)
91
+
92
+ asyncio.run(main())
93
+ ```
94
+
95
+ ### get_history
96
+
97
+ Retrieve the conversation history:
98
+
99
+ ```python
100
+ # Get all messages in the conversation
101
+ history = client.get_history()
102
+ print(f"Total messages: {len(history)}")
103
+
104
+ for msg in history:
105
+ print(f"Role: {msg['role']}")
106
+ print(f"Content: {msg['content_items']}")
107
+ ```
108
+
109
+ ### clear_history
110
+
111
+ Clear the conversation history:
112
+
113
+ ```python
114
+ # Clear all conversation history
115
+ client.clear_history()
116
+
117
+ # Verify history is empty
118
+ assert len(client.get_history()) == 0
119
+ ```
120
+
121
+ ### set_history
122
+
123
+ Replace the conversation history with a copy of the provided list:
124
+
125
+ ```python
126
+ # Save current history
127
+ saved_history = client.get_history()
128
+
129
+ # ... do other things, then restore
130
+ client.set_history(saved_history)
131
+
132
+ # Verify history was replaced
133
+ assert len(client.get_history()) == len(saved_history)
134
+ ```
135
+
136
+ ## Tool Calling
137
+
138
+ When using tools, you must handle `tool_call_id` correctly:
139
+
140
+ ```python
141
+ import asyncio
142
+ import json
143
+ from agenthub import AutoLLMClient
144
+
145
+ def get_weather(location: str) -> str:
146
+ """Mock function to get weather."""
147
+ return f"Temperature in {location}: 22°C"
148
+
149
+ async def main():
150
+ # Define tool
151
+ weather_function = {
152
+ "name": "get_weather",
153
+ "description": "Gets the current weather for a given location.",
154
+ "parameters": {
155
+ "type": "object",
156
+ "properties": {
157
+ "location": {
158
+ "type": "string",
159
+ "description": "The city name"
160
+ }
161
+ },
162
+ "required": ["location"]
163
+ }
164
+ }
165
+
166
+ client = AutoLLMClient(model="gpt-5.5")
167
+ config = {"tools": [weather_function]}
168
+
169
+ # User asks about weather
170
+ events = []
171
+ async for event in client.streaming_response_stateful(
172
+ message={
173
+ "role": "user",
174
+ "content_items": [{"type": "text", "text": "What's the weather in London?"}]
175
+ },
176
+ config=config
177
+ ):
178
+ events.append(event)
179
+
180
+ # Extract function call and tool_call_id
181
+ tool_call = None
182
+ for event in events:
183
+ for item in event["content_items"]:
184
+ if item["type"] == "tool_call":
185
+ tool_call = item
186
+ break
187
+
188
+ if tool_call:
189
+ break
190
+
191
+ # Execute function and send result back with tool_call_id
192
+ if tool_call:
193
+ result = get_weather(**tool_call["argument"])
194
+
195
+ # IMPORTANT: Include tool_call_id in the tool response
196
+ async for event in client.streaming_response_stateful(
197
+ message={
198
+ "role": "user",
199
+ "content_items": [
200
+ {
201
+ "type": "tool_result",
202
+ "text": result,
203
+ "tool_call_id": tool_call["tool_call_id"] # Required for tool responses
204
+ }
205
+ ]
206
+ },
207
+ config=config
208
+ ):
209
+ print(event)
210
+
211
+ asyncio.run(main())
212
+ ```
213
+
214
+ ## Message Format
215
+
216
+ ### UniMessage Structure
217
+
218
+ ```python
219
+ {
220
+ "role": "user" | "assistant",
221
+ "content_items": [
222
+ {"type": "text", "text": "Hello"},
223
+ {"type": "image_url", "image_url": "https://..."},
224
+ {"type": "tool_call", "name": "get_weather", "argument": {"location": "London"}, "tool_call_id": "call_abc123"}
225
+ ]
226
+ }
227
+ ```
228
+
229
+ ### Tool Response with tool_call_id
230
+
231
+ When responding to a tool call, include the `tool_call_id` in the result content item:
232
+
233
+ ```python
234
+ {
235
+ "role": "user",
236
+ "content_items": [
237
+ {
238
+ "type": "tool_result",
239
+ "text": "London is 22°C today.",
240
+ "tool_call_id": "call_abc123" # From tool_call event
241
+ }
242
+ ]
243
+ }
244
+ ```
245
+
246
+ ## Configuration Options
247
+
248
+ ```python
249
+ from agenthub import PromptCaching, ThinkingLevel
250
+
251
+ config = {
252
+ "max_tokens": 500,
253
+ "temperature": 1.0,
254
+ "tools": [tool_definition],
255
+ "thinking_summary": True,
256
+ "thinking_level": ThinkingLevel.HIGH,
257
+ "tool_choice": "auto", # "auto", "required", "none", or ["tool_name"]
258
+ "system_prompt": "You are a helpful assistant",
259
+ "prompt_caching": PromptCaching.ENABLE,
260
+ "trace_id": "agent1/conversation_001" # Optional: save conversation trace
261
+ }
262
+ ```
263
+
264
+ ## Conversation Tracing
265
+
266
+ AgentHub provides a built-in `Tracer` to save and browse conversation history. When you specify a `trace_id` in the config, conversations are automatically saved to both JSON and TXT formats.
267
+
268
+ ### Basic Usage
269
+
270
+ ```python
271
+ from agenthub import AutoLLMClient
272
+
273
+ client = AutoLLMClient(model="gpt-5.5")
274
+
275
+ # Add trace_id to config
276
+ config = {"trace_id": "agent1/conversation_001"}
277
+
278
+ async for event in client.streaming_response_stateful(
279
+ message={"role": "user", "content_items": [{"type": "text", "text": "Hello"}]},
280
+ config=config
281
+ ):
282
+ pass # Conversation is automatically saved
283
+ ```
284
+
285
+ The default cache directory is `cache`, you can change it by setting `AGENTHUB_CACHE_DIR` environment variable.
286
+
287
+ This creates two files in the `cache` directory:
288
+ - `cache/agent1/conversation_001.json` - Structured data with full history and config
289
+ - `cache/agent1/conversation_001.txt` - Human-readable conversation format
290
+
291
+ ### Browsing Traces with Web Interface
292
+
293
+ Start a web server to browse and view saved conversations:
294
+
295
+ ```python
296
+ from agenthub.integration.tracer import Tracer
297
+
298
+ # Start web server
299
+ Tracer("path/to/cache").start_web_server(host="127.0.0.1", port=25750)
300
+ ```
301
+
302
+ Or use the CLI:
303
+
304
+ ```bash
305
+ python -m agenthub.integration.tracer --cache_dir ./cache --host 127.0.0.1 --port 25750
306
+ ```
307
+
308
+ Then visit `http://127.0.0.1:25750` in your browser to browse saved conversations.
309
+
310
+ ### Test with Playground
311
+
312
+ Start a web server to test with the playground:
313
+
314
+ ```python
315
+ from agenthub.integration.playground import start_playground_server
316
+
317
+ start_playground_server()
318
+ ```
319
+
320
+ Or use the CLI:
321
+
322
+ ```bash
323
+ python -m agenthub.integration.playground --host 127.0.0.1 --port 25751
324
+ ```
325
+
326
+ Then visit `http://127.0.0.1:25751` in your browser to test with the playground.