axio 0.2.1__tar.gz → 0.2.2__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.
- axio-0.2.2/PKG-INFO +214 -0
- {axio-0.2.1 → axio-0.2.2}/pyproject.toml +2 -1
- {axio-0.2.1 → axio-0.2.2}/uv.lock +1 -1
- axio-0.2.1/PKG-INFO +0 -8
- {axio-0.2.1 → axio-0.2.2}/.github/workflows/publish.yml +0 -0
- {axio-0.2.1 → axio-0.2.2}/.github/workflows/tests.yml +0 -0
- {axio-0.2.1 → axio-0.2.2}/LICENSE +0 -0
- {axio-0.2.1 → axio-0.2.2}/Makefile +0 -0
- {axio-0.2.1 → axio-0.2.2}/README.md +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/__init__.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/agent.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/blocks.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/context.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/events.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/exceptions.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/messages.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/models.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/permission.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/py.typed +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/selector.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/stream.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/testing.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/tool.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/transport.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/src/axio/types.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/conftest.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_agent_branch.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_agent_permission.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_agent_run.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_agent_stream.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_agent_tools.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_blocks.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_context.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_events.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_exceptions.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_permission.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_selector.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_stream.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_tool.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_transport.py +0 -0
- {axio-0.2.1 → axio-0.2.2}/tests/test_types.py +0 -0
axio-0.2.2/PKG-INFO
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: axio
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Minimal, streaming-first, protocol-driven foundation for LLM-powered agents
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.12
|
|
8
|
+
Requires-Dist: pydantic>=2
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# axio
|
|
12
|
+
|
|
13
|
+
[](https://pypi.org/project/axio/)
|
|
14
|
+
[](https://pypi.org/project/axio/)
|
|
15
|
+
[](LICENSE)
|
|
16
|
+
|
|
17
|
+
Minimal, streaming-first, protocol-driven foundation for LLM-powered agents.
|
|
18
|
+
|
|
19
|
+
One dependency (`pydantic`). Three protocols. An agent loop that just works.
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
|
|
23
|
+
- **Streaming agent loop** — `run_stream()` yields typed events as they arrive; no buffering, no polling
|
|
24
|
+
- **Three clean protocols** — `CompletionTransport`, `ContextStore`, `PermissionGuard`; swap any piece without touching the rest
|
|
25
|
+
- **Concurrent tool dispatch** — all tool calls in a turn run via `asyncio.gather` automatically
|
|
26
|
+
- **Context compaction** — `compact_context()` summarises old history to stay within token limits
|
|
27
|
+
- **Testing helpers** — `StubTransport`, `make_tool_use_response()`, `make_echo_tool()` ship in `axio.testing`
|
|
28
|
+
- **Plugin-ready** — entry-point groups (`axio.tools`, `axio.transport`, `axio.guards`) for drop-in extensions
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install axio
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick start
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import asyncio
|
|
40
|
+
from axio import Agent
|
|
41
|
+
from axio.context import MemoryContextStore
|
|
42
|
+
from axio.tool import Tool, ToolHandler
|
|
43
|
+
|
|
44
|
+
# 1. Define a tool
|
|
45
|
+
class Greet(ToolHandler):
|
|
46
|
+
"""Return a greeting for the given name."""
|
|
47
|
+
name: str
|
|
48
|
+
|
|
49
|
+
async def __call__(self) -> str:
|
|
50
|
+
return f"Hello, {self.name}!"
|
|
51
|
+
|
|
52
|
+
greet_tool = Tool(name="greet", description="Greet someone by name", handler=Greet)
|
|
53
|
+
|
|
54
|
+
# 2. Wire up the agent (transport comes from an axio-transport-* package)
|
|
55
|
+
from axio_transport_openai import OpenAITransport
|
|
56
|
+
|
|
57
|
+
transport = OpenAITransport(api_key="sk-...", model="gpt-4o-mini")
|
|
58
|
+
agent = Agent(system="You are helpful.", tools=[greet_tool], transport=transport)
|
|
59
|
+
|
|
60
|
+
# 3. Run
|
|
61
|
+
async def main() -> None:
|
|
62
|
+
ctx = MemoryContextStore()
|
|
63
|
+
async for event in agent.run_stream("Please greet Alice", ctx):
|
|
64
|
+
print(event)
|
|
65
|
+
|
|
66
|
+
asyncio.run(main())
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Architecture
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
User message
|
|
73
|
+
│
|
|
74
|
+
▼
|
|
75
|
+
┌─────────┐ stream() ┌─────────────────────┐
|
|
76
|
+
│ Agent │ ────────────▶ │ CompletionTransport │
|
|
77
|
+
│ loop │ ◀──────────── │ (OpenAI, Nebius, …) │
|
|
78
|
+
└─────────┘ StreamEvent └─────────────────────┘
|
|
79
|
+
│
|
|
80
|
+
│ tool_use?
|
|
81
|
+
▼
|
|
82
|
+
┌──────────┐ check() ┌─────────────────┐
|
|
83
|
+
│ Tool │ ──────────▶ │ PermissionGuard │
|
|
84
|
+
│ handler │ │ (path, LLM, …) │
|
|
85
|
+
└──────────┘ └─────────────────┘
|
|
86
|
+
│
|
|
87
|
+
▼
|
|
88
|
+
┌──────────────┐
|
|
89
|
+
│ ContextStore │ append() / get_history() / fork() / compact()
|
|
90
|
+
└──────────────┘
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Protocols
|
|
94
|
+
|
|
95
|
+
### CompletionTransport
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from typing import Protocol, runtime_checkable
|
|
99
|
+
from collections.abc import AsyncIterator
|
|
100
|
+
from axio.events import StreamEvent
|
|
101
|
+
from axio.messages import Message
|
|
102
|
+
from axio.tool import Tool
|
|
103
|
+
|
|
104
|
+
@runtime_checkable
|
|
105
|
+
class CompletionTransport(Protocol):
|
|
106
|
+
def stream(
|
|
107
|
+
self, messages: list[Message], tools: list[Tool], system: str
|
|
108
|
+
) -> AsyncIterator[StreamEvent]: ...
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### ContextStore
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
class ContextStore(ABC):
|
|
115
|
+
async def append(self, message: Message) -> None: ...
|
|
116
|
+
async def get_history(self) -> list[Message]: ...
|
|
117
|
+
async def fork(self) -> ContextStore: ... # branch conversation
|
|
118
|
+
async def clear(self) -> None: ...
|
|
119
|
+
async def close(self) -> None: ...
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### PermissionGuard
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
@runtime_checkable
|
|
126
|
+
class PermissionGuard(Protocol):
|
|
127
|
+
async def check(self, handler: ToolHandler) -> ToolHandler: ...
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Stream events
|
|
131
|
+
|
|
132
|
+
| Event | Description |
|
|
133
|
+
|---|---|
|
|
134
|
+
| `TextDelta` | Incremental assistant text chunk |
|
|
135
|
+
| `ToolUseStart` | Tool call begins (name + id) |
|
|
136
|
+
| `ToolInputDelta` | Streaming JSON fragment for tool arguments |
|
|
137
|
+
| `ToolResult` | Tool execution result |
|
|
138
|
+
| `IterationEnd` | One LLM round complete — carries `Usage` + `StopReason` |
|
|
139
|
+
| `Error` | Transport or tool exception |
|
|
140
|
+
| `SessionEndEvent` | Agent loop finished — carries total `Usage` |
|
|
141
|
+
|
|
142
|
+
## Tools
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from axio.tool import Tool, ToolHandler
|
|
146
|
+
|
|
147
|
+
class Summarise(ToolHandler):
|
|
148
|
+
"""Summarise the given text in one sentence."""
|
|
149
|
+
text: str
|
|
150
|
+
max_words: int = 20
|
|
151
|
+
|
|
152
|
+
async def __call__(self) -> str:
|
|
153
|
+
# your implementation
|
|
154
|
+
return "..."
|
|
155
|
+
|
|
156
|
+
tool = Tool(
|
|
157
|
+
name="summarise",
|
|
158
|
+
description="Summarise text", # overrides docstring if set
|
|
159
|
+
handler=Summarise,
|
|
160
|
+
concurrency=4, # max parallel executions
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Testing
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from axio.testing import (
|
|
168
|
+
StubTransport,
|
|
169
|
+
make_tool_use_response,
|
|
170
|
+
make_text_response,
|
|
171
|
+
make_ephemeral_context,
|
|
172
|
+
make_echo_tool,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
async def test_agent_calls_tool():
|
|
176
|
+
transport = StubTransport([
|
|
177
|
+
make_tool_use_response("echo", tool_input={"msg": "hi"}),
|
|
178
|
+
make_text_response("Done"),
|
|
179
|
+
])
|
|
180
|
+
agent = Agent(system="", tools=[make_echo_tool()], transport=transport)
|
|
181
|
+
result = await agent.run("say hi", make_ephemeral_context())
|
|
182
|
+
assert result == "Done"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Plugin entry points
|
|
186
|
+
|
|
187
|
+
```toml
|
|
188
|
+
[project.entry-points."axio.tools"]
|
|
189
|
+
my_tool = "my_package:MyHandler"
|
|
190
|
+
|
|
191
|
+
[project.entry-points."axio.transport"]
|
|
192
|
+
my_backend = "my_package:MyTransport"
|
|
193
|
+
|
|
194
|
+
[project.entry-points."axio.guards"]
|
|
195
|
+
my_guard = "my_package:MyGuard"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Ecosystem
|
|
199
|
+
|
|
200
|
+
| Package | Purpose |
|
|
201
|
+
|---|---|
|
|
202
|
+
| [axio-transport-openai](https://github.com/axio-agent/axio-transport-openai) | OpenAI-compatible transport |
|
|
203
|
+
| [axio-transport-nebius](https://github.com/axio-agent/axio-transport-nebius) | Nebius AI Studio transport |
|
|
204
|
+
| [axio-transport-codex](https://github.com/axio-agent/axio-transport-codex) | ChatGPT OAuth transport |
|
|
205
|
+
| [axio-tools-local](https://github.com/axio-agent/axio-tools-local) | Shell, file, Python tools |
|
|
206
|
+
| [axio-tools-mcp](https://github.com/axio-agent/axio-tools-mcp) | MCP server bridge |
|
|
207
|
+
| [axio-tools-docker](https://github.com/axio-agent/axio-tools-docker) | Docker sandbox tools |
|
|
208
|
+
| [axio-tui](https://github.com/axio-agent/axio-tui) | Textual TUI application |
|
|
209
|
+
| [axio-tui-rag](https://github.com/axio-agent/axio-tui-rag) | RAG / semantic search plugin |
|
|
210
|
+
| [axio-tui-guards](https://github.com/axio-agent/axio-tui-guards) | Permission guard plugins |
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "axio"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "Minimal, streaming-first, protocol-driven foundation for LLM-powered agents"
|
|
5
|
+
readme = "README.md"
|
|
5
6
|
requires-python = ">=3.12"
|
|
6
7
|
license = {text = "MIT"}
|
|
7
8
|
dependencies = ["pydantic>=2"]
|
axio-0.2.1/PKG-INFO
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|