hrns 0.0.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.
- hrns-0.0.1/.gitignore +17 -0
- hrns-0.0.1/LICENSE +21 -0
- hrns-0.0.1/PKG-INFO +262 -0
- hrns-0.0.1/README.md +182 -0
- hrns-0.0.1/pyproject.toml +103 -0
- hrns-0.0.1/src/hrns/__init__.py +13 -0
- hrns-0.0.1/src/hrns/client/__init__.py +120 -0
- hrns-0.0.1/src/hrns/client/__main__.py +10 -0
- hrns-0.0.1/src/hrns/client/_version.py +5 -0
- hrns-0.0.1/src/hrns/client/attachments.py +167 -0
- hrns-0.0.1/src/hrns/client/bridge.py +250 -0
- hrns-0.0.1/src/hrns/client/bus.py +58 -0
- hrns-0.0.1/src/hrns/client/catalog.py +275 -0
- hrns-0.0.1/src/hrns/client/clean.py +174 -0
- hrns-0.0.1/src/hrns/client/cli.py +947 -0
- hrns-0.0.1/src/hrns/client/client.py +432 -0
- hrns-0.0.1/src/hrns/client/connection.py +197 -0
- hrns-0.0.1/src/hrns/client/constants.py +47 -0
- hrns-0.0.1/src/hrns/client/errors.py +98 -0
- hrns-0.0.1/src/hrns/client/events.py +185 -0
- hrns-0.0.1/src/hrns/client/extension.py +299 -0
- hrns-0.0.1/src/hrns/client/extensions_api.py +242 -0
- hrns-0.0.1/src/hrns/client/headless.py +328 -0
- hrns-0.0.1/src/hrns/client/interactions.py +374 -0
- hrns-0.0.1/src/hrns/client/launch.py +159 -0
- hrns-0.0.1/src/hrns/client/local.py +187 -0
- hrns-0.0.1/src/hrns/client/payloads.py +129 -0
- hrns-0.0.1/src/hrns/client/profiles.py +301 -0
- hrns-0.0.1/src/hrns/client/renderers.py +100 -0
- hrns-0.0.1/src/hrns/client/session.py +377 -0
- hrns-0.0.1/src/hrns/client/transport.py +523 -0
- hrns-0.0.1/src/hrns/client/tui/__init__.py +1 -0
- hrns-0.0.1/src/hrns/client/tui/app.py +860 -0
- hrns-0.0.1/src/hrns/client/tui/approval.py +543 -0
- hrns-0.0.1/src/hrns/client/tui/blocks.py +305 -0
- hrns-0.0.1/src/hrns/client/tui/chat/__init__.py +1 -0
- hrns-0.0.1/src/hrns/client/tui/chat/actions.py +285 -0
- hrns-0.0.1/src/hrns/client/tui/chat/capabilities.py +470 -0
- hrns-0.0.1/src/hrns/client/tui/chat/chrome.py +157 -0
- hrns-0.0.1/src/hrns/client/tui/chat/commands.py +253 -0
- hrns-0.0.1/src/hrns/client/tui/chat/connection.py +93 -0
- hrns-0.0.1/src/hrns/client/tui/chat/model.py +464 -0
- hrns-0.0.1/src/hrns/client/tui/chat/prompts.py +645 -0
- hrns-0.0.1/src/hrns/client/tui/chat/screen.py +887 -0
- hrns-0.0.1/src/hrns/client/tui/chat/session.py +261 -0
- hrns-0.0.1/src/hrns/client/tui/choice_keys.py +55 -0
- hrns-0.0.1/src/hrns/client/tui/commands.py +96 -0
- hrns-0.0.1/src/hrns/client/tui/completion.py +97 -0
- hrns-0.0.1/src/hrns/client/tui/composer.py +247 -0
- hrns-0.0.1/src/hrns/client/tui/connection_screen.py +650 -0
- hrns-0.0.1/src/hrns/client/tui/dialogs.py +1002 -0
- hrns-0.0.1/src/hrns/client/tui/extensions.py +138 -0
- hrns-0.0.1/src/hrns/client/tui/formatting.py +77 -0
- hrns-0.0.1/src/hrns/client/tui/local.py +332 -0
- hrns-0.0.1/src/hrns/client/tui/messages.py +58 -0
- hrns-0.0.1/src/hrns/client/tui/panels/__init__.py +5 -0
- hrns-0.0.1/src/hrns/client/tui/panels/activity.py +57 -0
- hrns-0.0.1/src/hrns/client/tui/panels/capability.py +373 -0
- hrns-0.0.1/src/hrns/client/tui/panels/mcp.py +219 -0
- hrns-0.0.1/src/hrns/client/tui/panels/session.py +243 -0
- hrns-0.0.1/src/hrns/client/tui/panels/side.py +85 -0
- hrns-0.0.1/src/hrns/client/tui/panels/todo.py +62 -0
- hrns-0.0.1/src/hrns/client/tui/screen_base.py +23 -0
- hrns-0.0.1/src/hrns/client/tui/state.py +774 -0
- hrns-0.0.1/src/hrns/client/tui/status.py +277 -0
- hrns-0.0.1/src/hrns/client/tui/tool_views.py +404 -0
- hrns-0.0.1/src/hrns/client/tui/transcript.py +818 -0
- hrns-0.0.1/src/hrns/client/turn.py +169 -0
- hrns-0.0.1/src/hrns/client/updates.py +190 -0
- hrns-0.0.1/src/hrns/client/url_policy.py +57 -0
- hrns-0.0.1/src/hrns/config/__init__.py +30 -0
- hrns-0.0.1/src/hrns/config/mcp.py +288 -0
- hrns-0.0.1/src/hrns/config/settings.py +173 -0
- hrns-0.0.1/src/hrns/protocol/__init__.py +105 -0
- hrns-0.0.1/src/hrns/protocol/errors.py +11 -0
- hrns-0.0.1/src/hrns/protocol/extensions.py +161 -0
- hrns-0.0.1/src/hrns/protocol/models.py +166 -0
- hrns-0.0.1/src/hrns/protocol/py.typed +0 -0
- hrns-0.0.1/src/hrns/protocol/transport.py +145 -0
- hrns-0.0.1/src/hrns/py.typed +0 -0
- hrns-0.0.1/src/hrns/runtime/__init__.py +154 -0
- hrns-0.0.1/src/hrns/runtime/_model_usage.py +69 -0
- hrns-0.0.1/src/hrns/runtime/_unavailable_tools.py +103 -0
- hrns-0.0.1/src/hrns/runtime/_version.py +5 -0
- hrns-0.0.1/src/hrns/runtime/_warnings.py +9 -0
- hrns-0.0.1/src/hrns/runtime/acp.py +174 -0
- hrns-0.0.1/src/hrns/runtime/acp_store.py +398 -0
- hrns-0.0.1/src/hrns/runtime/ask_user.py +94 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/__init__.py +34 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/ask_user/__init__.py +60 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/ask_user/_capability.py +36 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/ask_user/config.py +22 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/__init__.py +60 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_capability.py +91 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_changes.py +208 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_ids.py +19 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_instructions.py +32 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_needs.py +11 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_presentation.py +52 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_search.py +434 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_tools.py +361 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/_workspace.py +107 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/coder/config.py +41 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/mcp/__init__.py +64 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/mcp/_capability.py +121 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/mcp/_status.py +92 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/mcp/config.py +11 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/skills/__init__.py +76 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/skills/_capability.py +85 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/skills/_catalog.py +144 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/skills/_invocation.py +73 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/skills/_needs.py +7 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/skills/config.py +57 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/todo/__init__.py +58 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/todo/_capability.py +57 -0
- hrns-0.0.1/src/hrns/runtime/capabilities/todo/config.py +23 -0
- hrns-0.0.1/src/hrns/runtime/cli.py +406 -0
- hrns-0.0.1/src/hrns/runtime/command_service.py +209 -0
- hrns-0.0.1/src/hrns/runtime/commands.py +170 -0
- hrns-0.0.1/src/hrns/runtime/composition.py +526 -0
- hrns-0.0.1/src/hrns/runtime/configuration_service.py +164 -0
- hrns-0.0.1/src/hrns/runtime/definitions.py +671 -0
- hrns-0.0.1/src/hrns/runtime/deps.py +89 -0
- hrns-0.0.1/src/hrns/runtime/extensions.py +234 -0
- hrns-0.0.1/src/hrns/runtime/host.py +485 -0
- hrns-0.0.1/src/hrns/runtime/host_support.py +250 -0
- hrns-0.0.1/src/hrns/runtime/local.py +366 -0
- hrns-0.0.1/src/hrns/runtime/policy/__init__.py +23 -0
- hrns-0.0.1/src/hrns/runtime/policy/binding.py +156 -0
- hrns-0.0.1/src/hrns/runtime/policy/catalog.py +439 -0
- hrns-0.0.1/src/hrns/runtime/policy/validation.py +468 -0
- hrns-0.0.1/src/hrns/runtime/postgres.py +354 -0
- hrns-0.0.1/src/hrns/runtime/presentation.py +256 -0
- hrns-0.0.1/src/hrns/runtime/registry.py +631 -0
- hrns-0.0.1/src/hrns/runtime/resources.py +488 -0
- hrns-0.0.1/src/hrns/runtime/session_service.py +446 -0
- hrns-0.0.1/src/hrns/runtime/steering.py +59 -0
- hrns-0.0.1/src/hrns/runtime/store.py +355 -0
- hrns-0.0.1/src/hrns/runtime/todo.py +160 -0
- hrns-0.0.1/src/hrns/server/__init__.py +18 -0
- hrns-0.0.1/src/hrns/server/_version.py +5 -0
- hrns-0.0.1/src/hrns/server/api.py +66 -0
- hrns-0.0.1/src/hrns/server/app.py +213 -0
- hrns-0.0.1/src/hrns/server/auth.py +64 -0
- hrns-0.0.1/src/hrns/server/catalog.py +162 -0
- hrns-0.0.1/src/hrns/server/errors.py +123 -0
- hrns-0.0.1/src/hrns/server/models.py +67 -0
- hrns-0.0.1/src/hrns/server/proxy.py +157 -0
hrns-0.0.1/.gitignore
ADDED
hrns-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 hrns contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
hrns-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: hrns
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Programmable Pydantic AI agents with an interoperable ACP terminal and hosting
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Requires-Dist: platformdirs>=4
|
|
9
|
+
Requires-Dist: pydantic-settings<3,>=2.10
|
|
10
|
+
Requires-Dist: pydantic<3,>=2.12
|
|
11
|
+
Requires-Dist: tomli-w<2,>=1.2
|
|
12
|
+
Provides-Extra: all
|
|
13
|
+
Requires-Dist: agent-client-protocol<0.12,>=0.11; extra == 'all'
|
|
14
|
+
Requires-Dist: fastapi<1,>=0.156; extra == 'all'
|
|
15
|
+
Requires-Dist: fastmcp-slim[client]<5,>=3.3; extra == 'all'
|
|
16
|
+
Requires-Dist: httpx<1,>=0.28; extra == 'all'
|
|
17
|
+
Requires-Dist: keyring>=25; extra == 'all'
|
|
18
|
+
Requires-Dist: packaging>=24; extra == 'all'
|
|
19
|
+
Requires-Dist: psycopg[binary]>=3.2; extra == 'all'
|
|
20
|
+
Requires-Dist: pydantic-ai-harness[acp]==0.57.0; extra == 'all'
|
|
21
|
+
Requires-Dist: pydantic-ai-skills<3,>=2.1; extra == 'all'
|
|
22
|
+
Requires-Dist: pydantic-ai-slim[anthropic]==2.57.0; extra == 'all'
|
|
23
|
+
Requires-Dist: pydantic-ai-slim[mcp]==2.57.0; extra == 'all'
|
|
24
|
+
Requires-Dist: pydantic-ai-slim[openai]==2.57.0; extra == 'all'
|
|
25
|
+
Requires-Dist: pyyaml<7,>=6; extra == 'all'
|
|
26
|
+
Requires-Dist: starlette<2,>=0.47; extra == 'all'
|
|
27
|
+
Requires-Dist: textual<9,>=8.2; extra == 'all'
|
|
28
|
+
Requires-Dist: uvicorn>=0.35; extra == 'all'
|
|
29
|
+
Requires-Dist: websockets<18,>=15; extra == 'all'
|
|
30
|
+
Provides-Extra: anthropic
|
|
31
|
+
Requires-Dist: keyring>=25; extra == 'anthropic'
|
|
32
|
+
Requires-Dist: packaging>=24; extra == 'anthropic'
|
|
33
|
+
Requires-Dist: pydantic-ai-harness[acp]==0.57.0; extra == 'anthropic'
|
|
34
|
+
Requires-Dist: pydantic-ai-skills<3,>=2.1; extra == 'anthropic'
|
|
35
|
+
Requires-Dist: pydantic-ai-slim[anthropic]==2.57.0; extra == 'anthropic'
|
|
36
|
+
Requires-Dist: pydantic-ai-slim[mcp]==2.57.0; extra == 'anthropic'
|
|
37
|
+
Requires-Dist: pyyaml<7,>=6; extra == 'anthropic'
|
|
38
|
+
Provides-Extra: client
|
|
39
|
+
Requires-Dist: agent-client-protocol<0.12,>=0.11; extra == 'client'
|
|
40
|
+
Requires-Dist: fastmcp-slim[client]<5,>=3.3; extra == 'client'
|
|
41
|
+
Requires-Dist: httpx<1,>=0.28; extra == 'client'
|
|
42
|
+
Requires-Dist: keyring>=25; extra == 'client'
|
|
43
|
+
Requires-Dist: textual<9,>=8.2; extra == 'client'
|
|
44
|
+
Requires-Dist: websockets<18,>=15; extra == 'client'
|
|
45
|
+
Provides-Extra: openai
|
|
46
|
+
Requires-Dist: keyring>=25; extra == 'openai'
|
|
47
|
+
Requires-Dist: packaging>=24; extra == 'openai'
|
|
48
|
+
Requires-Dist: pydantic-ai-harness[acp]==0.57.0; extra == 'openai'
|
|
49
|
+
Requires-Dist: pydantic-ai-skills<3,>=2.1; extra == 'openai'
|
|
50
|
+
Requires-Dist: pydantic-ai-slim[mcp]==2.57.0; extra == 'openai'
|
|
51
|
+
Requires-Dist: pydantic-ai-slim[openai]==2.57.0; extra == 'openai'
|
|
52
|
+
Requires-Dist: pyyaml<7,>=6; extra == 'openai'
|
|
53
|
+
Provides-Extra: postgres
|
|
54
|
+
Requires-Dist: keyring>=25; extra == 'postgres'
|
|
55
|
+
Requires-Dist: packaging>=24; extra == 'postgres'
|
|
56
|
+
Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres'
|
|
57
|
+
Requires-Dist: pydantic-ai-harness[acp]==0.57.0; extra == 'postgres'
|
|
58
|
+
Requires-Dist: pydantic-ai-skills<3,>=2.1; extra == 'postgres'
|
|
59
|
+
Requires-Dist: pydantic-ai-slim[mcp]==2.57.0; extra == 'postgres'
|
|
60
|
+
Requires-Dist: pyyaml<7,>=6; extra == 'postgres'
|
|
61
|
+
Provides-Extra: runtime
|
|
62
|
+
Requires-Dist: keyring>=25; extra == 'runtime'
|
|
63
|
+
Requires-Dist: packaging>=24; extra == 'runtime'
|
|
64
|
+
Requires-Dist: pydantic-ai-harness[acp]==0.57.0; extra == 'runtime'
|
|
65
|
+
Requires-Dist: pydantic-ai-skills<3,>=2.1; extra == 'runtime'
|
|
66
|
+
Requires-Dist: pydantic-ai-slim[mcp]==2.57.0; extra == 'runtime'
|
|
67
|
+
Requires-Dist: pyyaml<7,>=6; extra == 'runtime'
|
|
68
|
+
Provides-Extra: server
|
|
69
|
+
Requires-Dist: fastapi<1,>=0.156; extra == 'server'
|
|
70
|
+
Requires-Dist: keyring>=25; extra == 'server'
|
|
71
|
+
Requires-Dist: packaging>=24; extra == 'server'
|
|
72
|
+
Requires-Dist: pydantic-ai-harness[acp]==0.57.0; extra == 'server'
|
|
73
|
+
Requires-Dist: pydantic-ai-skills<3,>=2.1; extra == 'server'
|
|
74
|
+
Requires-Dist: pydantic-ai-slim[mcp]==2.57.0; extra == 'server'
|
|
75
|
+
Requires-Dist: pyyaml<7,>=6; extra == 'server'
|
|
76
|
+
Requires-Dist: starlette<2,>=0.47; extra == 'server'
|
|
77
|
+
Requires-Dist: uvicorn>=0.35; extra == 'server'
|
|
78
|
+
Requires-Dist: websockets<18,>=15; extra == 'server'
|
|
79
|
+
Description-Content-Type: text/markdown
|
|
80
|
+
|
|
81
|
+
# Benchmark results
|
|
82
|
+
|
|
83
|
+
Three runs per hrns on a benchmark task using **GPT-6-Luna with medium reasoning**.
|
|
84
|
+
|
|
85
|
+
| hrns | Tests pass | All quality gates pass | Model responses | Tool calls | Total cost | Average/run |
|
|
86
|
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
87
|
+
| Codex | 3/3 | 3/3 | 44 | 56 | $0.03658 | $0.01219 |
|
|
88
|
+
| OpenCode | 3/3 | 2/3 | 43 | 47 | $0.03578 | $0.01193 |
|
|
89
|
+
| **hrns** | **3/3** | **3/3** | **44** | **59** | **$0.03300** | **$0.01100** |
|
|
90
|
+
|
|
91
|
+
All runs pass **130/130 tests**. Quality gates cover Ruff lint, Ruff formatting,
|
|
92
|
+
and Pyrefly type checking.
|
|
93
|
+
|
|
94
|
+
Counts and costs are totals across three runs. Model responses include tool-only
|
|
95
|
+
responses and final answers. Tool calls count underlying attempts, including
|
|
96
|
+
failures; Codex's 41 orchestration calls contain 56 underlying attempts.
|
|
97
|
+
Costs are cache-aware **API equivalents in USD** using common Standard model pricing.
|
|
98
|
+
|
|
99
|
+
Skill loads: **Codex 0/3**, **OpenCode 1/3**, **hrns 3/3**. The loaded skill is
|
|
100
|
+
`incremental-implementation`, with relevant selection and partial adherence.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
# hrns
|
|
105
|
+
|
|
106
|
+
**Define an agent once. Run it in Python, open it in a terminal, or host it remotely.**
|
|
107
|
+
|
|
108
|
+
hrns combines native Pydantic AI capabilities with policy-controlled sessions, an independent ACP terminal, and authenticated remote hosting. Agent behavior stays in ordinary Python; the terminal can also connect to standard ACP agents that do not use this runtime.
|
|
109
|
+
|
|
110
|
+
## Start developing
|
|
111
|
+
|
|
112
|
+
Requires **Python 3.11+**, macOS or Linux, [uv](https://docs.astral.sh/uv/),
|
|
113
|
+
and [just](https://just.systems/).
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
just install
|
|
117
|
+
just check
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The checked-in lockfile pins the tested upstream versions. `just install` also
|
|
121
|
+
installs the [prek](https://prek.j178.dev/) Git hook, which runs `just check` before
|
|
122
|
+
each commit without applying automatic fixes. To install the hook after a manual
|
|
123
|
+
dependency sync, run `uv run prek install`.
|
|
124
|
+
|
|
125
|
+
## Use a local agent with your model
|
|
126
|
+
|
|
127
|
+
The local developer agent is the default connection mode. Install the provider
|
|
128
|
+
extra and set the API key for the provider you use:
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
uv sync --locked --extra client --extra runtime --extra openai
|
|
132
|
+
export DEEPSEEK_API_KEY='your-key'
|
|
133
|
+
uv run hrns
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Press **l** to configure a provider and model, type `/models` in a session, or create
|
|
137
|
+
`hrns.local.toml` in the project:
|
|
138
|
+
|
|
139
|
+
```toml
|
|
140
|
+
provider = "deepseek"
|
|
141
|
+
model = "deepseek-chat"
|
|
142
|
+
api_key_env = "DEEPSEEK_API_KEY"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`uv run hrns` starts a session in the current directory using that model. The bundled
|
|
146
|
+
`hrns.coder` capability gives it file tools, content search, and a shell in that
|
|
147
|
+
directory: reads are automatic, while writes, edits, and commands ask for approval first.
|
|
148
|
+
`hrns.ask_user` lets the model ask structured multiple-choice questions in the terminal;
|
|
149
|
+
disable it with `[capabilities] ask_user = false` for headless runs. `hrns.todo` gives
|
|
150
|
+
the model a session-scoped plan and shows it in the **Todos** tab of the right drawer.
|
|
151
|
+
Configuration uses pydantic-settings. See
|
|
152
|
+
[local setup](docs/LOCAL.md) for OpenAI-compatible endpoints, local inference, other
|
|
153
|
+
Pydantic AI providers, and headless execution.
|
|
154
|
+
|
|
155
|
+
Useful slash commands include `/connect` (switch or add a target), `/models`
|
|
156
|
+
(configure or select the local model), `/effort` (change reasoning effort live),
|
|
157
|
+
`/plugins` (toggle, configure, or add plugins), `/mcp` (list MCP servers and their
|
|
158
|
+
tools), `/skills` (browse Agent Skills), and `/todo` (open the session's plan).
|
|
159
|
+
Typing `/` shows an inline filtered list. Type `$` in the composer to find a skill and
|
|
160
|
+
insert a `$skill-name` reference, which runs that skill for the message. The older
|
|
161
|
+
`/model` and `/capabilities` names remain aliases.
|
|
162
|
+
|
|
163
|
+
Any independent ACP agent can still be launched explicitly:
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
uv run hrns connect --stdio -- /path/to/agent --acp
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
See [client usage](docs/CLIENT_API.md) for headless execution, profiles, approvals
|
|
170
|
+
and the bridge.
|
|
171
|
+
|
|
172
|
+
## Serve agents in your FastAPI app
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
from fastapi import FastAPI
|
|
176
|
+
from hrns.runtime import SQLiteSessionStore
|
|
177
|
+
from hrns.server import AgentServer
|
|
178
|
+
|
|
179
|
+
app = FastAPI()
|
|
180
|
+
agents = AgentServer(store=SQLiteSessionStore("./sessions.sqlite3"))
|
|
181
|
+
agents.add_agent(definition)
|
|
182
|
+
agents.mount(app)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`add_agent` binds and validates the definition's resource requirements at registration; pass
|
|
186
|
+
`resources=`, or a `definition.bind(...)` result, when a capability needs host values.
|
|
187
|
+
Install the `server` extra, register your `AgentDefinition` objects, and run the app
|
|
188
|
+
with Uvicorn. Connect using `hrns connect --url http://127.0.0.1:8080 --agent AGENT_ID`.
|
|
189
|
+
PostgreSQL and optional FastAPI authentication dependencies use the same API.
|
|
190
|
+
See [server embedding](docs/SERVER.md) and [the runnable example](examples/fastapi_app.py).
|
|
191
|
+
|
|
192
|
+
## Layout
|
|
193
|
+
|
|
194
|
+
hrns is one distribution with optional extras. Protocol and local settings
|
|
195
|
+
ship by default; the runtime, terminal, and server dependencies are opt-in.
|
|
196
|
+
|
|
197
|
+
| Module | Extra | Purpose |
|
|
198
|
+
| --- | --- | --- |
|
|
199
|
+
| `hrns.protocol` | base | Versioned extension schemas and transport contracts |
|
|
200
|
+
| `hrns.config` | base | Shared local settings using pydantic-settings |
|
|
201
|
+
| `hrns.runtime` | `runtime` | Native agent definitions, plugin management, sessions, `hrns-host` and `hrns-local` |
|
|
202
|
+
| `hrns.client` | `client` | Textual terminal, scripted ACP runner and stdio bridge |
|
|
203
|
+
| `hrns.server` | `server` | FastAPI agent registration and in-process WebSocket ACP |
|
|
204
|
+
|
|
205
|
+
Install only what you need, for example `pip install 'hrns[client]'`,
|
|
206
|
+
`pip install 'hrns[openai]'`, or `pip install 'hrns[all]'`.
|
|
207
|
+
|
|
208
|
+
The `hrns.client` module does not import Pydantic AI or installed agent
|
|
209
|
+
plugins, and installing `hrns[client]` alone does not install the runtime.
|
|
210
|
+
Local stdio agents run in a separate process. Network agents run inside an existing
|
|
211
|
+
FastAPI application through `AgentServer`, sharing an explicit SQLite or PostgreSQL store.
|
|
212
|
+
|
|
213
|
+
## Design essentials
|
|
214
|
+
|
|
215
|
+
- **Upstream ACP execution:** `PydanticAIACPAgent` owns prompts, streaming, approvals, cancellation, history, and transcript replay.
|
|
216
|
+
- **Native composition:** managed bindings contribute their complete Pydantic AI behavior—tools, instructions, hooks and settings—and are selected when a session is composed.
|
|
217
|
+
- **Live model and effort:** both use standard ACP configuration options and apply from the next request.
|
|
218
|
+
- **Host-owned state:** sessions pin their principal/deployment scope, retain history and metadata, and never silently retry an uncertain prompt.
|
|
219
|
+
- **Explicit resources:** workspace and provider bindings belong to the host. A local workspace is a path, not a sandbox.
|
|
220
|
+
- **Standard ACP first:** generic streaming content, tools and approvals work without project-specific extensions.
|
|
221
|
+
|
|
222
|
+
## Checks and distribution builds
|
|
223
|
+
|
|
224
|
+
```sh
|
|
225
|
+
just check
|
|
226
|
+
just lint
|
|
227
|
+
just build
|
|
228
|
+
just fix
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
`just check` runs the checks and builds the package. `just lint` runs formatting,
|
|
232
|
+
lint, and type checks; `just build` builds the package. `just fix` applies automatic
|
|
233
|
+
formatting and lint fixes. CI exercises the same non-mutating checks on
|
|
234
|
+
macOS/Linux and Python 3.11–3.13. A wheel and source distribution are written to `dist/`; optional dependencies are declared as extras.
|
|
235
|
+
|
|
236
|
+
External provider, sandbox and durability integrations need their upstream extras and credentials. See the coverage matrix for managed, locally verified and deployment-only distinctions.
|
|
237
|
+
|
|
238
|
+
## Releasing
|
|
239
|
+
|
|
240
|
+
The version comes from the git tag via hatch-vcs, so there is no version string to
|
|
241
|
+
edit. Publishing runs on release: create a GitHub release and
|
|
242
|
+
`.github/workflows/publish.yml` builds the distribution, runs `just check`, verifies
|
|
243
|
+
the tag, and uploads to PyPI.
|
|
244
|
+
|
|
245
|
+
```sh
|
|
246
|
+
git tag 0.1.0
|
|
247
|
+
git push origin 0.1.0
|
|
248
|
+
gh release create 0.1.0 --generate-notes
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The tag must match the version hatch-vcs derives, so `0.1.0` publishes `0.1.0`. A
|
|
252
|
+
mismatched tag fails the build instead of uploading an unintended version, and a
|
|
253
|
+
version that already exists on PyPI is rejected.
|
|
254
|
+
|
|
255
|
+
Uploads use PyPI Trusted Publishing, so no API token is stored in the repository.
|
|
256
|
+
Before the first release, configure a publisher on PyPI for the `hrns` project with
|
|
257
|
+
this repository's owner and name, workflow `publish.yml`, and environment `pypi`.
|
|
258
|
+
Because `hrns` does not exist on PyPI yet, use the pending publisher form.
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
MIT. See [LICENSE](LICENSE).
|
hrns-0.0.1/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Benchmark results
|
|
2
|
+
|
|
3
|
+
Three runs per hrns on a benchmark task using **GPT-6-Luna with medium reasoning**.
|
|
4
|
+
|
|
5
|
+
| hrns | Tests pass | All quality gates pass | Model responses | Tool calls | Total cost | Average/run |
|
|
6
|
+
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
7
|
+
| Codex | 3/3 | 3/3 | 44 | 56 | $0.03658 | $0.01219 |
|
|
8
|
+
| OpenCode | 3/3 | 2/3 | 43 | 47 | $0.03578 | $0.01193 |
|
|
9
|
+
| **hrns** | **3/3** | **3/3** | **44** | **59** | **$0.03300** | **$0.01100** |
|
|
10
|
+
|
|
11
|
+
All runs pass **130/130 tests**. Quality gates cover Ruff lint, Ruff formatting,
|
|
12
|
+
and Pyrefly type checking.
|
|
13
|
+
|
|
14
|
+
Counts and costs are totals across three runs. Model responses include tool-only
|
|
15
|
+
responses and final answers. Tool calls count underlying attempts, including
|
|
16
|
+
failures; Codex's 41 orchestration calls contain 56 underlying attempts.
|
|
17
|
+
Costs are cache-aware **API equivalents in USD** using common Standard model pricing.
|
|
18
|
+
|
|
19
|
+
Skill loads: **Codex 0/3**, **OpenCode 1/3**, **hrns 3/3**. The loaded skill is
|
|
20
|
+
`incremental-implementation`, with relevant selection and partial adherence.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# hrns
|
|
25
|
+
|
|
26
|
+
**Define an agent once. Run it in Python, open it in a terminal, or host it remotely.**
|
|
27
|
+
|
|
28
|
+
hrns combines native Pydantic AI capabilities with policy-controlled sessions, an independent ACP terminal, and authenticated remote hosting. Agent behavior stays in ordinary Python; the terminal can also connect to standard ACP agents that do not use this runtime.
|
|
29
|
+
|
|
30
|
+
## Start developing
|
|
31
|
+
|
|
32
|
+
Requires **Python 3.11+**, macOS or Linux, [uv](https://docs.astral.sh/uv/),
|
|
33
|
+
and [just](https://just.systems/).
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
just install
|
|
37
|
+
just check
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The checked-in lockfile pins the tested upstream versions. `just install` also
|
|
41
|
+
installs the [prek](https://prek.j178.dev/) Git hook, which runs `just check` before
|
|
42
|
+
each commit without applying automatic fixes. To install the hook after a manual
|
|
43
|
+
dependency sync, run `uv run prek install`.
|
|
44
|
+
|
|
45
|
+
## Use a local agent with your model
|
|
46
|
+
|
|
47
|
+
The local developer agent is the default connection mode. Install the provider
|
|
48
|
+
extra and set the API key for the provider you use:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
uv sync --locked --extra client --extra runtime --extra openai
|
|
52
|
+
export DEEPSEEK_API_KEY='your-key'
|
|
53
|
+
uv run hrns
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Press **l** to configure a provider and model, type `/models` in a session, or create
|
|
57
|
+
`hrns.local.toml` in the project:
|
|
58
|
+
|
|
59
|
+
```toml
|
|
60
|
+
provider = "deepseek"
|
|
61
|
+
model = "deepseek-chat"
|
|
62
|
+
api_key_env = "DEEPSEEK_API_KEY"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`uv run hrns` starts a session in the current directory using that model. The bundled
|
|
66
|
+
`hrns.coder` capability gives it file tools, content search, and a shell in that
|
|
67
|
+
directory: reads are automatic, while writes, edits, and commands ask for approval first.
|
|
68
|
+
`hrns.ask_user` lets the model ask structured multiple-choice questions in the terminal;
|
|
69
|
+
disable it with `[capabilities] ask_user = false` for headless runs. `hrns.todo` gives
|
|
70
|
+
the model a session-scoped plan and shows it in the **Todos** tab of the right drawer.
|
|
71
|
+
Configuration uses pydantic-settings. See
|
|
72
|
+
[local setup](docs/LOCAL.md) for OpenAI-compatible endpoints, local inference, other
|
|
73
|
+
Pydantic AI providers, and headless execution.
|
|
74
|
+
|
|
75
|
+
Useful slash commands include `/connect` (switch or add a target), `/models`
|
|
76
|
+
(configure or select the local model), `/effort` (change reasoning effort live),
|
|
77
|
+
`/plugins` (toggle, configure, or add plugins), `/mcp` (list MCP servers and their
|
|
78
|
+
tools), `/skills` (browse Agent Skills), and `/todo` (open the session's plan).
|
|
79
|
+
Typing `/` shows an inline filtered list. Type `$` in the composer to find a skill and
|
|
80
|
+
insert a `$skill-name` reference, which runs that skill for the message. The older
|
|
81
|
+
`/model` and `/capabilities` names remain aliases.
|
|
82
|
+
|
|
83
|
+
Any independent ACP agent can still be launched explicitly:
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
uv run hrns connect --stdio -- /path/to/agent --acp
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
See [client usage](docs/CLIENT_API.md) for headless execution, profiles, approvals
|
|
90
|
+
and the bridge.
|
|
91
|
+
|
|
92
|
+
## Serve agents in your FastAPI app
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from fastapi import FastAPI
|
|
96
|
+
from hrns.runtime import SQLiteSessionStore
|
|
97
|
+
from hrns.server import AgentServer
|
|
98
|
+
|
|
99
|
+
app = FastAPI()
|
|
100
|
+
agents = AgentServer(store=SQLiteSessionStore("./sessions.sqlite3"))
|
|
101
|
+
agents.add_agent(definition)
|
|
102
|
+
agents.mount(app)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`add_agent` binds and validates the definition's resource requirements at registration; pass
|
|
106
|
+
`resources=`, or a `definition.bind(...)` result, when a capability needs host values.
|
|
107
|
+
Install the `server` extra, register your `AgentDefinition` objects, and run the app
|
|
108
|
+
with Uvicorn. Connect using `hrns connect --url http://127.0.0.1:8080 --agent AGENT_ID`.
|
|
109
|
+
PostgreSQL and optional FastAPI authentication dependencies use the same API.
|
|
110
|
+
See [server embedding](docs/SERVER.md) and [the runnable example](examples/fastapi_app.py).
|
|
111
|
+
|
|
112
|
+
## Layout
|
|
113
|
+
|
|
114
|
+
hrns is one distribution with optional extras. Protocol and local settings
|
|
115
|
+
ship by default; the runtime, terminal, and server dependencies are opt-in.
|
|
116
|
+
|
|
117
|
+
| Module | Extra | Purpose |
|
|
118
|
+
| --- | --- | --- |
|
|
119
|
+
| `hrns.protocol` | base | Versioned extension schemas and transport contracts |
|
|
120
|
+
| `hrns.config` | base | Shared local settings using pydantic-settings |
|
|
121
|
+
| `hrns.runtime` | `runtime` | Native agent definitions, plugin management, sessions, `hrns-host` and `hrns-local` |
|
|
122
|
+
| `hrns.client` | `client` | Textual terminal, scripted ACP runner and stdio bridge |
|
|
123
|
+
| `hrns.server` | `server` | FastAPI agent registration and in-process WebSocket ACP |
|
|
124
|
+
|
|
125
|
+
Install only what you need, for example `pip install 'hrns[client]'`,
|
|
126
|
+
`pip install 'hrns[openai]'`, or `pip install 'hrns[all]'`.
|
|
127
|
+
|
|
128
|
+
The `hrns.client` module does not import Pydantic AI or installed agent
|
|
129
|
+
plugins, and installing `hrns[client]` alone does not install the runtime.
|
|
130
|
+
Local stdio agents run in a separate process. Network agents run inside an existing
|
|
131
|
+
FastAPI application through `AgentServer`, sharing an explicit SQLite or PostgreSQL store.
|
|
132
|
+
|
|
133
|
+
## Design essentials
|
|
134
|
+
|
|
135
|
+
- **Upstream ACP execution:** `PydanticAIACPAgent` owns prompts, streaming, approvals, cancellation, history, and transcript replay.
|
|
136
|
+
- **Native composition:** managed bindings contribute their complete Pydantic AI behavior—tools, instructions, hooks and settings—and are selected when a session is composed.
|
|
137
|
+
- **Live model and effort:** both use standard ACP configuration options and apply from the next request.
|
|
138
|
+
- **Host-owned state:** sessions pin their principal/deployment scope, retain history and metadata, and never silently retry an uncertain prompt.
|
|
139
|
+
- **Explicit resources:** workspace and provider bindings belong to the host. A local workspace is a path, not a sandbox.
|
|
140
|
+
- **Standard ACP first:** generic streaming content, tools and approvals work without project-specific extensions.
|
|
141
|
+
|
|
142
|
+
## Checks and distribution builds
|
|
143
|
+
|
|
144
|
+
```sh
|
|
145
|
+
just check
|
|
146
|
+
just lint
|
|
147
|
+
just build
|
|
148
|
+
just fix
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`just check` runs the checks and builds the package. `just lint` runs formatting,
|
|
152
|
+
lint, and type checks; `just build` builds the package. `just fix` applies automatic
|
|
153
|
+
formatting and lint fixes. CI exercises the same non-mutating checks on
|
|
154
|
+
macOS/Linux and Python 3.11–3.13. A wheel and source distribution are written to `dist/`; optional dependencies are declared as extras.
|
|
155
|
+
|
|
156
|
+
External provider, sandbox and durability integrations need their upstream extras and credentials. See the coverage matrix for managed, locally verified and deployment-only distinctions.
|
|
157
|
+
|
|
158
|
+
## Releasing
|
|
159
|
+
|
|
160
|
+
The version comes from the git tag via hatch-vcs, so there is no version string to
|
|
161
|
+
edit. Publishing runs on release: create a GitHub release and
|
|
162
|
+
`.github/workflows/publish.yml` builds the distribution, runs `just check`, verifies
|
|
163
|
+
the tag, and uploads to PyPI.
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
git tag 0.1.0
|
|
167
|
+
git push origin 0.1.0
|
|
168
|
+
gh release create 0.1.0 --generate-notes
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The tag must match the version hatch-vcs derives, so `0.1.0` publishes `0.1.0`. A
|
|
172
|
+
mismatched tag fails the build instead of uploading an unintended version, and a
|
|
173
|
+
version that already exists on PyPI is rejected.
|
|
174
|
+
|
|
175
|
+
Uploads use PyPI Trusted Publishing, so no API token is stored in the repository.
|
|
176
|
+
Before the first release, configure a publisher on PyPI for the `hrns` project with
|
|
177
|
+
this repository's owner and name, workflow `publish.yml`, and environment `pypi`.
|
|
178
|
+
Because `hrns` does not exist on PyPI yet, use the pending publisher form.
|
|
179
|
+
|
|
180
|
+
## License
|
|
181
|
+
|
|
182
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling", "hatch-vcs"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hrns"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Programmable Pydantic AI agents with an interoperable ACP terminal and hosting"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.11"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"pydantic>=2.12,<3",
|
|
14
|
+
"pydantic-settings>=2.10,<3",
|
|
15
|
+
"platformdirs>=4",
|
|
16
|
+
"tomli-w>=1.2,<2",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.optional-dependencies]
|
|
20
|
+
client = [
|
|
21
|
+
"agent-client-protocol>=0.11,<0.12",
|
|
22
|
+
"textual>=8.2,<9",
|
|
23
|
+
"httpx>=0.28,<1",
|
|
24
|
+
"websockets>=15,<18",
|
|
25
|
+
"keyring>=25",
|
|
26
|
+
"fastmcp-slim[client]>=3.3,<5",
|
|
27
|
+
]
|
|
28
|
+
runtime = [
|
|
29
|
+
"pydantic-ai-slim[mcp]==2.57.0",
|
|
30
|
+
"pydantic-ai-harness[acp]==0.57.0",
|
|
31
|
+
"PyYAML>=6,<7",
|
|
32
|
+
"packaging>=24",
|
|
33
|
+
"pydantic-ai-skills>=2.1,<3",
|
|
34
|
+
"keyring>=25",
|
|
35
|
+
]
|
|
36
|
+
server = [
|
|
37
|
+
"hrns[runtime]",
|
|
38
|
+
"fastapi>=0.156,<1",
|
|
39
|
+
"starlette>=0.47,<2",
|
|
40
|
+
"uvicorn>=0.35",
|
|
41
|
+
"websockets>=15,<18",
|
|
42
|
+
]
|
|
43
|
+
openai = [
|
|
44
|
+
"hrns[runtime]",
|
|
45
|
+
"pydantic-ai-slim[openai]==2.57.0",
|
|
46
|
+
]
|
|
47
|
+
anthropic = [
|
|
48
|
+
"hrns[runtime]",
|
|
49
|
+
"pydantic-ai-slim[anthropic]==2.57.0",
|
|
50
|
+
]
|
|
51
|
+
postgres = [
|
|
52
|
+
"hrns[runtime]",
|
|
53
|
+
"psycopg[binary]>=3.2",
|
|
54
|
+
]
|
|
55
|
+
all = [
|
|
56
|
+
"hrns[client,runtime,server,openai,anthropic,postgres]",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[project.scripts]
|
|
60
|
+
hrns = "hrns.client.cli:main"
|
|
61
|
+
hrns-host = "hrns.runtime.cli:main"
|
|
62
|
+
hrns-local = "hrns.runtime.local:main"
|
|
63
|
+
|
|
64
|
+
[dependency-groups]
|
|
65
|
+
dev = [
|
|
66
|
+
"ruff>=0.11",
|
|
67
|
+
"build>=1.2",
|
|
68
|
+
"httpx>=0.28",
|
|
69
|
+
"pyrefly>=1.4.0",
|
|
70
|
+
"types-pyyaml>=6",
|
|
71
|
+
"prek>=0.5.7",
|
|
72
|
+
]
|
|
73
|
+
docs = [
|
|
74
|
+
"mkdocstrings-python>=2.0.10",
|
|
75
|
+
"zensical>=0.0.67,<0.1",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[tool.hatch.version]
|
|
79
|
+
source = "vcs"
|
|
80
|
+
fallback-version = "0.0.1"
|
|
81
|
+
|
|
82
|
+
[tool.hatch.build.targets.wheel]
|
|
83
|
+
packages = ["src/hrns"]
|
|
84
|
+
|
|
85
|
+
[tool.hatch.build.targets.sdist]
|
|
86
|
+
include = ["/src", "/README.md", "/LICENSE"]
|
|
87
|
+
|
|
88
|
+
[tool.ruff]
|
|
89
|
+
target-version = "py311"
|
|
90
|
+
line-length = 100
|
|
91
|
+
src = ["src"]
|
|
92
|
+
|
|
93
|
+
[tool.ruff.lint]
|
|
94
|
+
select = ["E4", "E7", "E9", "F", "I"]
|
|
95
|
+
|
|
96
|
+
[tool.ruff.lint.isort]
|
|
97
|
+
known-first-party = ["hrns"]
|
|
98
|
+
|
|
99
|
+
[tool.pyrefly]
|
|
100
|
+
project-includes = [
|
|
101
|
+
"**/*.py*",
|
|
102
|
+
"**/*.ipynb",
|
|
103
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""hrns: programmable Pydantic AI agents with an ACP terminal and hosting.
|
|
2
|
+
|
|
3
|
+
The distribution exposes independent subpackages:
|
|
4
|
+
|
|
5
|
+
- ``hrns.protocol``: versioned contracts and transport framing.
|
|
6
|
+
- ``hrns.config``: shared local settings.
|
|
7
|
+
- ``hrns.runtime``: native agent definitions, sessions, and ACP hosting.
|
|
8
|
+
- ``hrns.client``: Textual terminal, headless runner, and stdio bridge.
|
|
9
|
+
- ``hrns.server``: authenticated deployment catalog and worker hosting.
|
|
10
|
+
|
|
11
|
+
Importing ``hrns`` does not import any subpackage, so the client and server
|
|
12
|
+
keep their independent dependency boundaries.
|
|
13
|
+
"""
|