a2a-lite 0.1.0__py3-none-any.whl → 0.2.1__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.
a2a_lite/testing.py CHANGED
@@ -3,21 +3,61 @@ Testing utilities for A2A Lite agents.
3
3
 
4
4
  Makes testing agents as simple as:
5
5
 
6
- from a2a_lite.testing import TestClient
6
+ from a2a_lite.testing import AgentTestClient
7
7
 
8
8
  def test_my_agent():
9
- client = TestClient(agent)
9
+ client = AgentTestClient(agent)
10
10
  result = client.call("greet", name="World")
11
11
  assert result == "Hello, World!"
12
12
  """
13
13
  from __future__ import annotations
14
14
 
15
15
  import json
16
+ from dataclasses import dataclass
16
17
  from typing import Any, Dict, Optional
17
18
  from uuid import uuid4
18
19
 
19
20
 
20
- class TestClient:
21
+ @dataclass
22
+ class TestResult:
23
+ """
24
+ Structured result from a test client call.
25
+
26
+ Provides multiple ways to access the result:
27
+ - .data — parsed Python object (dict, list, int, str, etc.)
28
+ - .text — raw text string
29
+ - .json() — parse text as JSON (raises on invalid JSON)
30
+ - .raw_response — the full A2A response dict
31
+ """
32
+ _data: Any
33
+ _text: str
34
+ raw_response: Dict[str, Any]
35
+
36
+ @property
37
+ def data(self) -> Any:
38
+ """The parsed result value."""
39
+ return self._data
40
+
41
+ @property
42
+ def text(self) -> str:
43
+ """The raw text representation."""
44
+ return self._text
45
+
46
+ def json(self) -> Any:
47
+ """Parse the text as JSON."""
48
+ return json.loads(self._text)
49
+
50
+ def __eq__(self, other: Any) -> bool:
51
+ """Allow direct comparison with the data value for convenience."""
52
+ if isinstance(other, TestResult):
53
+ return self._data == other._data
54
+ return self._data == other
55
+
56
+ def __repr__(self) -> str:
57
+ return f"TestResult(data={self._data!r})"
58
+
59
+
60
+ class AgentTestClient:
21
61
  """
22
62
  Simple test client for A2A Lite agents.
23
63
 
@@ -29,7 +69,7 @@ class TestClient:
29
69
  return a + b
30
70
 
31
71
  # In your test
32
- client = TestClient(agent)
72
+ client = AgentTestClient(agent)
33
73
  assert client.call("add", a=2, b=3) == 5
34
74
  """
35
75
 
@@ -89,7 +129,7 @@ class TestClient:
89
129
  # Extract the actual result from A2A response
90
130
  return self._extract_result(data)
91
131
 
92
- def _extract_result(self, response: Dict) -> Any:
132
+ def _extract_result(self, response: Dict) -> TestResult:
93
133
  """Extract the skill result from A2A response."""
94
134
  if "error" in response:
95
135
  raise TestClientError(response["error"])
@@ -103,11 +143,12 @@ class TestClient:
103
143
  text = part.get("text", "")
104
144
  # Try to parse as JSON
105
145
  try:
106
- return json.loads(text)
146
+ data = json.loads(text)
107
147
  except json.JSONDecodeError:
108
- return text
148
+ data = text
149
+ return TestResult(_data=data, _text=text, raw_response=response)
109
150
 
110
- return result
151
+ return TestResult(_data=result, _text=json.dumps(result), raw_response=response)
111
152
 
112
153
  def get_agent_card(self) -> Dict[str, Any]:
113
154
  """
@@ -173,7 +214,7 @@ class TestClient:
173
214
  result = await gen
174
215
  results.append(result)
175
216
 
176
- asyncio.get_event_loop().run_until_complete(run_handler())
217
+ asyncio.run(run_handler())
177
218
  return results
178
219
 
179
220
 
@@ -183,13 +224,13 @@ class TestClientError(Exception):
183
224
 
184
225
 
185
226
  # Async version for async tests
186
- class AsyncTestClient:
227
+ class AsyncAgentTestClient:
187
228
  """
188
229
  Async test client for A2A Lite agents.
189
230
 
190
231
  Example:
191
232
  async def test_my_agent():
192
- client = AsyncTestClient(agent)
233
+ client = AsyncAgentTestClient(agent)
193
234
  result = await client.call("greet", name="World")
194
235
  assert result == "Hello, World!"
195
236
  """
@@ -243,7 +284,7 @@ class AsyncTestClient:
243
284
 
244
285
  return self._extract_result(data)
245
286
 
246
- def _extract_result(self, response: Dict) -> Any:
287
+ def _extract_result(self, response: Dict) -> TestResult:
247
288
  """Extract the skill result from A2A response."""
248
289
  if "error" in response:
249
290
  raise TestClientError(response["error"])
@@ -255,11 +296,12 @@ class AsyncTestClient:
255
296
  if part.get("kind") == "text" or part.get("type") == "text":
256
297
  text = part.get("text", "")
257
298
  try:
258
- return json.loads(text)
299
+ data = json.loads(text)
259
300
  except json.JSONDecodeError:
260
- return text
301
+ data = text
302
+ return TestResult(_data=data, _text=text, raw_response=response)
261
303
 
262
- return result
304
+ return TestResult(_data=result, _text=json.dumps(result), raw_response=response)
263
305
 
264
306
  async def close(self):
265
307
  """Close the client."""
a2a_lite/utils.py CHANGED
@@ -5,6 +5,22 @@ from typing import Any, Dict, Type, get_origin, get_args, Union
5
5
  import inspect
6
6
 
7
7
 
8
+ def _is_or_subclass(hint: Any, target_class: Type) -> bool:
9
+ """
10
+ Check if a type hint is, or is a subclass of, the target class.
11
+
12
+ Works with raw classes and string annotations.
13
+ """
14
+ try:
15
+ if hint is target_class:
16
+ return True
17
+ if isinstance(hint, type) and issubclass(hint, target_class):
18
+ return True
19
+ except TypeError:
20
+ pass
21
+ return False
22
+
23
+
8
24
  def type_to_json_schema(python_type: Type) -> Dict[str, Any]:
9
25
  """
10
26
  Convert Python type to JSON Schema.
@@ -0,0 +1,526 @@
1
+ Metadata-Version: 2.4
2
+ Name: a2a-lite
3
+ Version: 0.2.1
4
+ Summary: Simplified wrapper for Google's A2A Protocol SDK
5
+ Author: A2A Lite Contributors
6
+ License-Expression: Apache-2.0
7
+ Keywords: a2a,agents,ai,protocol,sdk
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: a2a-sdk[http-server]>=0.2.6
18
+ Requires-Dist: httpx>=0.25.0
19
+ Requires-Dist: pydantic>=2.0
20
+ Requires-Dist: rich>=13.0
21
+ Requires-Dist: starlette>=0.40.0
22
+ Requires-Dist: typer>=0.9.0
23
+ Requires-Dist: uvicorn>=0.30.0
24
+ Requires-Dist: watchfiles>=0.20.0
25
+ Requires-Dist: zeroconf>=0.80.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: httpx>=0.25; extra == 'dev'
28
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
29
+ Requires-Dist: pytest>=7.0; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # A2A Lite - Python
33
+
34
+ **Build A2A agents in 8 lines. Add enterprise features when you need them.**
35
+
36
+ Wraps the official [A2A Python SDK](https://github.com/a2aproject/a2a-python) with a simple, intuitive API.
37
+
38
+ ```python
39
+ from a2a_lite import Agent
40
+
41
+ agent = Agent(name="Bot", description="My bot")
42
+
43
+ @agent.skill("greet")
44
+ async def greet(name: str) -> str:
45
+ return f"Hello, {name}!"
46
+
47
+ agent.run()
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ pip install a2a-lite
56
+ # or
57
+ uv add a2a-lite
58
+ ```
59
+
60
+ **Requirements:** Python 3.10+
61
+
62
+ ---
63
+
64
+ ## Quick Start
65
+
66
+ ### 1. Create an agent
67
+
68
+ ```python
69
+ from a2a_lite import Agent
70
+
71
+ agent = Agent(name="Calculator", description="Does math")
72
+
73
+ @agent.skill("add")
74
+ async def add(a: int, b: int) -> int:
75
+ return a + b
76
+
77
+ @agent.skill("multiply")
78
+ async def multiply(a: int, b: int) -> int:
79
+ return a * b
80
+
81
+ agent.run(port=8787)
82
+ ```
83
+
84
+ ### 2. Test it
85
+
86
+ ```python
87
+ from a2a_lite import Agent, AgentTestClient
88
+
89
+ agent = Agent(name="Calculator", description="Does math")
90
+
91
+ @agent.skill("add")
92
+ async def add(a: int, b: int) -> int:
93
+ return a + b
94
+
95
+ client = AgentTestClient(agent)
96
+ result = client.call("add", a=2, b=3)
97
+ assert result == 5
98
+ ```
99
+
100
+ ### 3. Call it
101
+
102
+ ```bash
103
+ curl -X POST http://localhost:8787/ \
104
+ -H "Content-Type: application/json" \
105
+ -d '{
106
+ "jsonrpc": "2.0",
107
+ "method": "message/send",
108
+ "id": "1",
109
+ "params": {
110
+ "message": {
111
+ "role": "user",
112
+ "parts": [{"type": "text", "text": "{\"skill\": \"add\", \"params\": {\"a\": 2, \"b\": 3}}"}],
113
+ "messageId": "msg-1"
114
+ }
115
+ }
116
+ }'
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Progressive Complexity
122
+
123
+ ### Level 1: Basic Skills
124
+
125
+ ```python
126
+ from a2a_lite import Agent
127
+
128
+ agent = Agent(name="Bot", description="A bot")
129
+
130
+ @agent.skill("greet")
131
+ async def greet(name: str) -> str:
132
+ return f"Hello, {name}!"
133
+
134
+ agent.run()
135
+ ```
136
+
137
+ ### Level 2: Pydantic Models (Just Works)
138
+
139
+ Pass dicts from callers — they're auto-converted to Pydantic models:
140
+
141
+ ```python
142
+ from pydantic import BaseModel
143
+
144
+ class User(BaseModel):
145
+ name: str
146
+ email: str
147
+
148
+ @agent.skill("create_user")
149
+ async def create_user(user: User) -> dict:
150
+ # 'user' is already a User instance — auto-converted from dict!
151
+ return {"id": 1, "name": user.name}
152
+ ```
153
+
154
+ Lists of models work too:
155
+
156
+ ```python
157
+ from typing import List
158
+
159
+ @agent.skill("count_users")
160
+ async def count_users(users: List[User]) -> int:
161
+ return len(users)
162
+ ```
163
+
164
+ ### Level 3: Streaming (Just Yield)
165
+
166
+ ```python
167
+ @agent.skill("chat", streaming=True)
168
+ async def chat(message: str):
169
+ for word in message.split():
170
+ yield word + " "
171
+ ```
172
+
173
+ ### Level 4: Middleware
174
+
175
+ ```python
176
+ @agent.middleware
177
+ async def log_requests(ctx, next):
178
+ print(f"Calling: {ctx.skill}")
179
+ result = await next()
180
+ print(f"Result: {result}")
181
+ return result
182
+ ```
183
+
184
+ Built-in middleware:
185
+
186
+ ```python
187
+ from a2a_lite import logging_middleware, timing_middleware, retry_middleware, rate_limit_middleware
188
+
189
+ agent.use(logging_middleware)
190
+ agent.use(timing_middleware)
191
+ agent.use(rate_limit_middleware(max_per_minute=60))
192
+ agent.use(retry_middleware(max_retries=3))
193
+ ```
194
+
195
+ ### Level 5: Human-in-the-Loop
196
+
197
+ ```python
198
+ from a2a_lite import InteractionContext
199
+
200
+ @agent.skill("wizard")
201
+ async def wizard(ctx: InteractionContext) -> dict:
202
+ name = await ctx.ask("What's your name?")
203
+ role = await ctx.ask("Role?", options=["Dev", "Manager"])
204
+
205
+ if await ctx.confirm(f"Create {name} as {role}?"):
206
+ return {"created": name}
207
+ return {"cancelled": True}
208
+ ```
209
+
210
+ ### Level 6: File Handling
211
+
212
+ ```python
213
+ from a2a_lite import FilePart
214
+
215
+ @agent.skill("summarize")
216
+ async def summarize(doc: FilePart) -> str:
217
+ content = await doc.read_text()
218
+ return f"Summary: {content[:100]}..."
219
+ ```
220
+
221
+ ### Level 7: Task Tracking
222
+
223
+ ```python
224
+ from a2a_lite import TaskContext
225
+
226
+ agent = Agent(name="Bot", description="A bot", task_store="memory")
227
+
228
+ @agent.skill("process")
229
+ async def process(data: str, task: TaskContext) -> str:
230
+ await task.update("working", "Starting...", progress=0.0)
231
+
232
+ for i in range(10):
233
+ await task.update("working", f"Step {i}/10", progress=i/10)
234
+
235
+ return "Done!"
236
+ ```
237
+
238
+ ### Level 8: Authentication
239
+
240
+ ```python
241
+ from a2a_lite import Agent, APIKeyAuth
242
+
243
+ agent = Agent(
244
+ name="SecureBot",
245
+ description="A secure bot",
246
+ auth=APIKeyAuth(keys=["secret-key-1", "secret-key-2"]),
247
+ )
248
+ ```
249
+
250
+ API keys are hashed in memory using SHA-256 — plaintext keys are never stored.
251
+
252
+ Other auth providers:
253
+
254
+ ```python
255
+ from a2a_lite.auth import BearerAuth, OAuth2Auth
256
+
257
+ # Bearer/JWT
258
+ agent = Agent(
259
+ name="Bot", description="A bot",
260
+ auth=BearerAuth(secret="your-jwt-secret"),
261
+ )
262
+
263
+ # OAuth2
264
+ agent = Agent(
265
+ name="Bot", description="A bot",
266
+ auth=OAuth2Auth(issuer="https://auth.example.com", audience="my-api"),
267
+ )
268
+ ```
269
+
270
+ ### Level 9: CORS and Production Mode
271
+
272
+ ```python
273
+ agent = Agent(
274
+ name="Bot",
275
+ description="A bot",
276
+ cors_origins=["https://myapp.com", "https://admin.myapp.com"],
277
+ production=True, # Warns if running over HTTP
278
+ )
279
+ ```
280
+
281
+ ### Level 10: Webhooks
282
+
283
+ ```python
284
+ @agent.on_complete
285
+ async def notify(skill_name, result):
286
+ print(f"Skill {skill_name} completed with: {result}")
287
+ ```
288
+
289
+ ---
290
+
291
+ ## Testing
292
+
293
+ ### AgentTestClient
294
+
295
+ The synchronous test client for use with pytest:
296
+
297
+ ```python
298
+ from a2a_lite import Agent, AgentTestClient
299
+
300
+ agent = Agent(name="Bot", description="Test")
301
+
302
+ @agent.skill("greet")
303
+ async def greet(name: str) -> str:
304
+ return f"Hello, {name}!"
305
+
306
+ @agent.skill("info")
307
+ async def info(name: str, age: int) -> dict:
308
+ return {"name": name, "age": age}
309
+
310
+
311
+ def test_simple_result():
312
+ client = AgentTestClient(agent)
313
+ result = client.call("greet", name="World")
314
+ # Simple values support direct equality
315
+ assert result == "Hello, World!"
316
+
317
+
318
+ def test_dict_result():
319
+ client = AgentTestClient(agent)
320
+ result = client.call("info", name="Alice", age=30)
321
+ # Access dict results via .data
322
+ assert result.data["name"] == "Alice"
323
+ assert result.data["age"] == 30
324
+
325
+
326
+ def test_text_access():
327
+ client = AgentTestClient(agent)
328
+ result = client.call("greet", name="World")
329
+ # .text gives the raw string
330
+ assert result.text == '"Hello, World!"'
331
+
332
+
333
+ def test_list_skills():
334
+ client = AgentTestClient(agent)
335
+ skills = client.list_skills()
336
+ assert "greet" in skills
337
+ assert "info" in skills
338
+ ```
339
+
340
+ ### TestResult
341
+
342
+ Every `client.call()` returns a `TestResult` with:
343
+
344
+ | Property | Description |
345
+ |----------|-------------|
346
+ | `.data` | Parsed Python object (dict, list, int, str, etc.) |
347
+ | `.text` | Raw text string from the response |
348
+ | `.json()` | Parse text as JSON (raises on invalid JSON) |
349
+ | `.raw_response` | Full A2A response dict |
350
+
351
+ `TestResult` supports direct equality comparison for simple values (`result == 5`), but use `.data` for subscripting (`result.data["key"]`).
352
+
353
+ ### AsyncAgentTestClient
354
+
355
+ For async test frameworks:
356
+
357
+ ```python
358
+ import pytest
359
+ from a2a_lite import AsyncAgentTestClient
360
+
361
+ @pytest.mark.asyncio
362
+ async def test_async():
363
+ client = AsyncAgentTestClient(agent)
364
+ result = await client.call("greet", name="World")
365
+ assert result == "Hello, World!"
366
+ await client.close()
367
+ ```
368
+
369
+ ### Streaming Tests
370
+
371
+ ```python
372
+ def test_streaming():
373
+ client = AgentTestClient(agent)
374
+ results = client.stream("chat", message="hello world")
375
+ assert len(results) == 2
376
+ ```
377
+
378
+ ---
379
+
380
+ ## Task Store
381
+
382
+ The `TaskStore` provides async-safe task lifecycle management:
383
+
384
+ ```python
385
+ from a2a_lite.tasks import TaskStore, TaskStatus
386
+
387
+ store = TaskStore()
388
+
389
+ # All operations are async and thread-safe
390
+ task = await store.create(task_id="task-1", skill="process")
391
+ task = await store.get("task-1")
392
+ await store.update("task-1", status=TaskStatus.WORKING, progress=0.5)
393
+ tasks = await store.list()
394
+ await store.delete("task-1")
395
+ ```
396
+
397
+ ---
398
+
399
+ ## Agent Discovery
400
+
401
+ Find agents on your local network via mDNS:
402
+
403
+ ```python
404
+ from a2a_lite import AgentDiscovery
405
+
406
+ # Advertise your agent
407
+ agent.run(port=8787, enable_discovery=True)
408
+
409
+ # Discover other agents
410
+ discovery = AgentDiscovery()
411
+ agents = await discovery.discover(timeout=5.0)
412
+ for a in agents:
413
+ print(f"{a.name} at {a.url}")
414
+ ```
415
+
416
+ ---
417
+
418
+ ## CLI
419
+
420
+ ```bash
421
+ a2a-lite init my-agent # Create new project
422
+ a2a-lite serve agent.py # Run agent from file
423
+ a2a-lite serve agent.py -r # Run with hot reload
424
+ a2a-lite inspect http://... # View agent capabilities
425
+ a2a-lite test http://... skill # Test a skill
426
+ a2a-lite discover # Find local agents
427
+ a2a-lite version # Show version
428
+ ```
429
+
430
+ ---
431
+
432
+ ## Full API Reference
433
+
434
+ ### Agent
435
+
436
+ ```python
437
+ Agent(
438
+ name: str, # Required
439
+ description: str, # Required
440
+ version: str = "1.0.0",
441
+ url: str = None, # Override auto-detected URL
442
+ auth: AuthProvider = None, # Authentication provider
443
+ task_store: str | TaskStore = None, # "memory" or custom TaskStore
444
+ cors_origins: List[str] = None, # CORS allowed origins
445
+ production: bool = False, # Enable production warnings
446
+ enable_discovery: bool = False, # mDNS discovery
447
+ )
448
+ ```
449
+
450
+ **Methods:**
451
+
452
+ | Method | Description |
453
+ |--------|-------------|
454
+ | `@agent.skill(name, **config)` | Register a skill via decorator |
455
+ | `@agent.middleware` | Register middleware via decorator |
456
+ | `agent.use(middleware)` | Register middleware function |
457
+ | `@agent.on_complete` | Register completion hook |
458
+ | `agent.run(port=8787)` | Start the server |
459
+ | `agent.get_app()` | Get the ASGI app (for custom deployment) |
460
+
461
+ ### Skill Decorator
462
+
463
+ ```python
464
+ @agent.skill(
465
+ name: str, # Skill name (required)
466
+ description: str = None, # Human-readable description
467
+ tags: List[str] = None, # Categorization tags
468
+ streaming: bool = False, # Enable streaming
469
+ )
470
+ ```
471
+
472
+ ### Auth Providers
473
+
474
+ | Provider | Usage |
475
+ |----------|-------|
476
+ | `APIKeyAuth(keys=[...])` | API key auth (keys hashed with SHA-256) |
477
+ | `BearerAuth(secret=...)` | JWT/Bearer token auth |
478
+ | `OAuth2Auth(issuer=..., audience=...)` | OAuth2 auth |
479
+ | `NoAuth()` | No auth (default) |
480
+
481
+ ### Special Parameter Types
482
+
483
+ These are auto-injected when detected in skill signatures:
484
+
485
+ | Type | Description |
486
+ |------|-------------|
487
+ | `TaskContext` | Task lifecycle management (requires `task_store`) |
488
+ | `InteractionContext` | Human-in-the-loop interactions |
489
+ | `FilePart` | File upload handling |
490
+
491
+ ---
492
+
493
+ ## Examples
494
+
495
+ | Example | What it shows |
496
+ |---------|---------------|
497
+ | [01_hello_world.py](examples/01_hello_world.py) | Simplest agent (8 lines) |
498
+ | [02_calculator.py](examples/02_calculator.py) | Multiple skills |
499
+ | [06_pydantic_models.py](examples/06_pydantic_models.py) | Auto Pydantic conversion |
500
+ | [08_streaming.py](examples/08_streaming.py) | Streaming responses |
501
+ | [09_testing.py](examples/09_testing.py) | Testing your agents |
502
+ | [11_human_in_the_loop.py](examples/11_human_in_the_loop.py) | Ask user questions |
503
+ | [12_file_handling.py](examples/12_file_handling.py) | Handle files |
504
+ | [13_task_tracking.py](examples/13_task_tracking.py) | Progress updates |
505
+ | [14_with_auth.py](examples/14_with_auth.py) | Authentication |
506
+
507
+ ---
508
+
509
+ ## 100% A2A Protocol Compatible
510
+
511
+ A2A Lite wraps the official A2A Python SDK. Every feature maps to real A2A protocol concepts:
512
+
513
+ | A2A Lite | A2A Protocol |
514
+ |----------|--------------|
515
+ | `@agent.skill()` | Agent Skills |
516
+ | `streaming=True` | SSE Streaming |
517
+ | `InteractionContext.ask()` | `input-required` state |
518
+ | `TaskContext.update()` | Task lifecycle states |
519
+ | `FilePart` | A2A File parts |
520
+ | `APIKeyAuth` / `BearerAuth` | Security schemes |
521
+
522
+ ---
523
+
524
+ ## License
525
+
526
+ Apache 2.0
@@ -0,0 +1,19 @@
1
+ a2a_lite/__init__.py,sha256=5bFZw7LapphdqfvMvyKfyEthe_kH4iigeGChd5h3TI4,3520
2
+ a2a_lite/agent.py,sha256=WyHe9aA_BYkzIXRjN5byoRc-vItCyL6YLDiyfX5gfPU,17053
3
+ a2a_lite/auth.py,sha256=bjPu_xnAxmfK5_dkqYz5mHouAjHqJFWlfYMqn-S1-A4,10177
4
+ a2a_lite/cli.py,sha256=D46mGduJb8AcZz8WRczNx5OzvIGxqZ7H-4fLCy2LpX8,9043
5
+ a2a_lite/decorators.py,sha256=VdinkddmF61IS8TkjdSfHGdn3nDKwepcIjWZPZBKg3w,1050
6
+ a2a_lite/discovery.py,sha256=BxpiJAUDxIyI2gvsLhjmHte5c9ax5Qf1hbBQnyAmxLQ,4508
7
+ a2a_lite/executor.py,sha256=zkTotenRNa7wlHh6pnIcS546fx5laSgoVIxZizE7SQI,13218
8
+ a2a_lite/human_loop.py,sha256=XAqxp-k8I7TNyuLqqNmLEqABHqcAUiKYCL8n3W5StaY,8685
9
+ a2a_lite/middleware.py,sha256=c6jb9aFfyTf-JY6KjqaSgFJmpzqbHLC6Q1h9NNteqzo,5545
10
+ a2a_lite/parts.py,sha256=qVRiD-H9_NlMPk-R0gTUiGVQ77E2poiuBWAUyAyAoTI,6177
11
+ a2a_lite/streaming.py,sha256=RFv9EJYnhwkT0h1Wovkj4EXwFzCgHdaA-h7WpPaaONo,2329
12
+ a2a_lite/tasks.py,sha256=UpmDP-VGIQ1LodBNq4zx2pJElQ31gOJOAduHFBVyxOA,7039
13
+ a2a_lite/testing.py,sha256=blugOpPKNThlbFTTSCyBVHb7tgQH79RH8z7Vo45hGbg,8953
14
+ a2a_lite/utils.py,sha256=CnkO6HH9oKEXymbJG2ohdt1ESxldQ3fkmcYVO-o9R_k,3841
15
+ a2a_lite/webhooks.py,sha256=t6ebT3jVBEKFpjhBnPI-nuQWIUKQUbJm24phXOBnNKA,6158
16
+ a2a_lite-0.2.1.dist-info/METADATA,sha256=5QLYvcVJh3qwri1zR3Gg-so5YLaAXXAIr-TvvhAg9UM,12583
17
+ a2a_lite-0.2.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
18
+ a2a_lite-0.2.1.dist-info/entry_points.txt,sha256=BONfFqZbCntNal2iwlTJAE09gCUvurfvqslMYVYh4is,46
19
+ a2a_lite-0.2.1.dist-info/RECORD,,