agent-tether 0.2.0__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 (38) hide show
  1. agent_tether-0.2.0/.github/workflows/publish.yml +31 -0
  2. agent_tether-0.2.0/.github/workflows/test.yml +33 -0
  3. agent_tether-0.2.0/.gitignore +15 -0
  4. agent_tether-0.2.0/CHANGELOG.md +42 -0
  5. agent_tether-0.2.0/LICENSE +21 -0
  6. agent_tether-0.2.0/PKG-INFO +178 -0
  7. agent_tether-0.2.0/README.md +131 -0
  8. agent_tether-0.2.0/pyproject.toml +76 -0
  9. agent_tether-0.2.0/src/agent_tether/__init__.py +64 -0
  10. agent_tether-0.2.0/src/agent_tether/approval.py +142 -0
  11. agent_tether-0.2.0/src/agent_tether/batching.py +62 -0
  12. agent_tether-0.2.0/src/agent_tether/debounce.py +40 -0
  13. agent_tether-0.2.0/src/agent_tether/formatting.py +176 -0
  14. agent_tether-0.2.0/src/agent_tether/models.py +108 -0
  15. agent_tether-0.2.0/src/agent_tether/platforms/__init__.py +0 -0
  16. agent_tether-0.2.0/src/agent_tether/platforms/base.py +598 -0
  17. agent_tether-0.2.0/src/agent_tether/platforms/discord/__init__.py +0 -0
  18. agent_tether-0.2.0/src/agent_tether/platforms/discord/bridge.py +403 -0
  19. agent_tether-0.2.0/src/agent_tether/platforms/discord/pairing.py +90 -0
  20. agent_tether-0.2.0/src/agent_tether/platforms/slack/__init__.py +0 -0
  21. agent_tether-0.2.0/src/agent_tether/platforms/slack/bridge.py +287 -0
  22. agent_tether-0.2.0/src/agent_tether/platforms/telegram/__init__.py +0 -0
  23. agent_tether-0.2.0/src/agent_tether/platforms/telegram/bridge.py +619 -0
  24. agent_tether-0.2.0/src/agent_tether/platforms/telegram/formatting.py +197 -0
  25. agent_tether-0.2.0/src/agent_tether/py.typed +0 -0
  26. agent_tether-0.2.0/src/agent_tether/router.py +55 -0
  27. agent_tether-0.2.0/src/agent_tether/runner/__init__.py +14 -0
  28. agent_tether-0.2.0/src/agent_tether/runner/adapters/__init__.py +18 -0
  29. agent_tether-0.2.0/src/agent_tether/runner/protocol.py +192 -0
  30. agent_tether-0.2.0/src/agent_tether/runner/registry.py +81 -0
  31. agent_tether-0.2.0/src/agent_tether/state.py +105 -0
  32. agent_tether-0.2.0/src/agent_tether/subscriber.py +205 -0
  33. agent_tether-0.2.0/tests/__init__.py +0 -0
  34. agent_tether-0.2.0/tests/test_approval.py +86 -0
  35. agent_tether-0.2.0/tests/test_base.py +197 -0
  36. agent_tether-0.2.0/tests/test_formatting.py +61 -0
  37. agent_tether-0.2.0/tests/test_runner.py +351 -0
  38. agent_tether-0.2.0/tests/test_subscriber.py +177 -0
@@ -0,0 +1,31 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ pypi-publish:
12
+ name: Upload release to PyPI
13
+ runs-on: ubuntu-latest
14
+ environment: pypi
15
+ permissions:
16
+ id-token: write # REQUIRED for trusted publishing
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - uses: actions/setup-python@v5
21
+ with:
22
+ python-version: "3.11"
23
+
24
+ - name: Install build tools
25
+ run: python -m pip install --upgrade build
26
+
27
+ - name: Build package
28
+ run: python -m build
29
+
30
+ - name: Publish to PyPI
31
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,33 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install -e ".[dev,all]"
28
+
29
+ - name: Run tests
30
+ run: pytest tests/ -v
31
+
32
+ - name: Check code formatting
33
+ run: black --check src/ tests/
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ *.egg
9
+ .mypy_cache/
10
+ .pytest_cache/
11
+ .venv/
12
+ venv/
13
+ *.so
14
+ .coverage
15
+ htmlcov/
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to agent-tether will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] - 2026-02-12
9
+
10
+ ### Added
11
+ - Runner protocol and registry framework
12
+ - `Runner` protocol for agent backends
13
+ - `RunnerEvents` protocol with 10 event callbacks
14
+ - `RunnerRegistry` for factory-based runner creation
15
+ - `RunnerUnavailableError` exception
16
+ - Comprehensive test suite (41 tests)
17
+ - Full documentation in README.md
18
+
19
+ ### Changed
20
+ - Simplified package scope to bridges + runner protocol only
21
+ - Updated documentation to reflect focused scope
22
+ - Improved example code in README
23
+
24
+ ## [0.1.0] - 2026-02-11
25
+
26
+ ### Added
27
+ - Initial release with chat platform bridges
28
+ - Telegram bridge with forum topics and inline keyboards
29
+ - Slack bridge with socket mode and threaded conversations
30
+ - Discord bridge with pairing system and thread management
31
+ - Auto-approve engine with per-thread, per-tool, and per-directory timers
32
+ - Command handling with built-in commands and custom registry
33
+ - Message formatting utilities (markdown, chunking, tool inputs)
34
+ - Thread state management with JSON persistence
35
+ - Notification batching and error debouncing
36
+ - Event subscriber system for bridge events
37
+ - Comprehensive test coverage
38
+ - MIT License
39
+ - Full documentation
40
+
41
+ [0.2.0]: https://github.com/xithing/agent-tether/releases/tag/v0.2.0
42
+ [0.1.0]: https://github.com/xithing/agent-tether/releases/tag/v0.1.0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 xithing
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.
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.4
2
+ Name: agent-tether
3
+ Version: 0.2.0
4
+ Summary: Tether your AI agents to human oversight through Telegram, Slack, and Discord
5
+ Project-URL: Homepage, https://github.com/xithing/agent-tether
6
+ Project-URL: Repository, https://github.com/xithing/agent-tether
7
+ Project-URL: Issues, https://github.com/xithing/agent-tether/issues
8
+ Author: xithing
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent,ai,approval,discord,human-in-the-loop,slack,telegram
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Communications :: Chat
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: pydantic>=2.0
24
+ Provides-Extra: all
25
+ Requires-Dist: discord-py>=2.0; extra == 'all'
26
+ Requires-Dist: python-telegram-bot>=21.0; extra == 'all'
27
+ Requires-Dist: slack-bolt>=1.0; extra == 'all'
28
+ Requires-Dist: slack-sdk>=3.0; extra == 'all'
29
+ Provides-Extra: bridges
30
+ Requires-Dist: discord-py>=2.0; extra == 'bridges'
31
+ Requires-Dist: python-telegram-bot>=21.0; extra == 'bridges'
32
+ Requires-Dist: slack-bolt>=1.0; extra == 'bridges'
33
+ Requires-Dist: slack-sdk>=3.0; extra == 'bridges'
34
+ Provides-Extra: dev
35
+ Requires-Dist: black; extra == 'dev'
36
+ Requires-Dist: mypy; extra == 'dev'
37
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
38
+ Requires-Dist: pytest>=8.0; extra == 'dev'
39
+ Provides-Extra: discord
40
+ Requires-Dist: discord-py>=2.0; extra == 'discord'
41
+ Provides-Extra: slack
42
+ Requires-Dist: slack-bolt>=1.0; extra == 'slack'
43
+ Requires-Dist: slack-sdk>=3.0; extra == 'slack'
44
+ Provides-Extra: telegram
45
+ Requires-Dist: python-telegram-bot>=21.0; extra == 'telegram'
46
+ Description-Content-Type: text/markdown
47
+
48
+ # agent-tether
49
+
50
+ Connect to your AI coding agents through Telegram, Slack, and Discord. Control them from your phone while they work on your laptop.
51
+
52
+ A Python library that handles the chat-platform integration for AI agent supervision: thread management, approval flows with inline buttons, auto-approve timers, message formatting, and command handling. You provide callbacks for your application logic.
53
+
54
+ **Use Cases:**
55
+ - Monitor Claude/Codex/Aider from your phone while agents run locally
56
+ - Get approval requests as Telegram notifications with one-tap approve/deny
57
+ - Set auto-approve timers for trusted operations
58
+ - Send additional input or stop agents remotely
59
+
60
+ ## Install
61
+
62
+ ```bash
63
+ pip install agent-tether[telegram] # Telegram support
64
+ pip install agent-tether[slack] # Slack support
65
+ pip install agent-tether[discord] # Discord support
66
+ pip install agent-tether[all] # All platforms
67
+ ```
68
+
69
+ ## Quick Start
70
+
71
+ ```python
72
+ import asyncio
73
+ from agent_tether import TelegramBridge, Handlers
74
+
75
+ async def on_input(thread_id: str, text: str, username: str | None):
76
+ print(f"[{thread_id}] {username}: {text}")
77
+
78
+ async def on_approval_response(thread_id: str, request_id: str, approved: bool, **kwargs):
79
+ print(f"[{thread_id}] {'Approved' if approved else 'Denied'} {request_id}")
80
+
81
+ bridge = TelegramBridge(
82
+ token="BOT_TOKEN",
83
+ forum_group_id=123456,
84
+ handlers=Handlers(
85
+ on_input=on_input,
86
+ on_approval_response=on_approval_response,
87
+ ),
88
+ )
89
+
90
+ async def main():
91
+ await bridge.start()
92
+
93
+ thread_id = await bridge.create_thread("My Agent Task")
94
+ await bridge.send_output(thread_id, "Starting work on your request...")
95
+
96
+ await bridge.send_approval_request(
97
+ thread_id,
98
+ request_id="req_123",
99
+ tool_name="Bash",
100
+ description='{"command": "rm -rf /tmp/cache"}',
101
+ )
102
+
103
+ await bridge.wait_until_stopped()
104
+
105
+ asyncio.run(main())
106
+ ```
107
+
108
+ ### Runner Protocol Example
109
+
110
+ ```python
111
+ from agent_tether.runner import Runner, RunnerEvents, RunnerRegistry
112
+
113
+ # Implement event callbacks
114
+ class MyEventHandler:
115
+ async def on_output(self, session_id, stream, text, **kwargs):
116
+ print(f"[{session_id}] {text}", end="")
117
+
118
+ async def on_error(self, session_id, code, message):
119
+ print(f"ERROR: {message}")
120
+
121
+ async def on_exit(self, session_id, exit_code):
122
+ print(f"Session {session_id} exited with code {exit_code}")
123
+
124
+ async def on_permission_request(self, session_id, request_id, tool_name, tool_input, **kwargs):
125
+ print(f"Permission requested for {tool_name}")
126
+
127
+ # ... other event callbacks
128
+
129
+ # Register runners
130
+ registry = RunnerRegistry()
131
+
132
+ def my_runner_factory(events, config):
133
+ # Return a Runner implementation
134
+ return MyCustomRunner(events, **config)
135
+
136
+ registry.register("my-runner", my_runner_factory)
137
+
138
+ # Create and use runner
139
+ events = MyEventHandler()
140
+ runner = registry.create("my-runner", events, api_key="...", model="...")
141
+
142
+ await runner.start("sess_1", "Build a web app", approval_choice=1)
143
+ await runner.send_input("sess_1", "Add a login page")
144
+ await runner.stop("sess_1")
145
+ ```
146
+
147
+ ## Features
148
+
149
+ ### Chat Platform Bridges
150
+ - **Telegram** — Forum topics, inline keyboard approval buttons, typing indicators, HTML formatting
151
+ - **Slack** — Socket mode, threaded conversations, text-based approval commands
152
+ - **Discord** — Channel threads, pairing/authorization system, text-based approvals
153
+ - **Approval engine** — Auto-approve timers (per-thread, per-tool, per-directory), batched notifications
154
+ - **Commands** — Built-in `/help`, `/stop`, `/status`, `/usage` + custom command registry
155
+ - **Formatting** — Tool input JSON → readable text, markdown conversion, message chunking
156
+
157
+ ### Runner Protocol
158
+ - **Protocol definitions** — `Runner` and `RunnerEvents` interfaces for agent backends
159
+ - **RunnerRegistry** — Factory pattern for discovering and creating runners
160
+ - **Pluggable adapters** — Clean protocol for implementing custom agent backends
161
+ - **Event-driven** — Runners report progress via callbacks (output, errors, permissions, etc.)
162
+
163
+ ## Documentation
164
+
165
+ - **[CHANGELOG.md](CHANGELOG.md)** — Version history and changes
166
+
167
+ ## Contributing
168
+
169
+ Contributions welcome! Please feel free to submit a Pull Request.
170
+
171
+ ## Related Projects
172
+
173
+ This library is extracted from [Tether](https://github.com/xithing/tether), a full-featured control plane for supervising AI coding agents.
174
+
175
+ ## License
176
+
177
+ MIT - see [LICENSE](LICENSE) for details
178
+
@@ -0,0 +1,131 @@
1
+ # agent-tether
2
+
3
+ Connect to your AI coding agents through Telegram, Slack, and Discord. Control them from your phone while they work on your laptop.
4
+
5
+ A Python library that handles the chat-platform integration for AI agent supervision: thread management, approval flows with inline buttons, auto-approve timers, message formatting, and command handling. You provide callbacks for your application logic.
6
+
7
+ **Use Cases:**
8
+ - Monitor Claude/Codex/Aider from your phone while agents run locally
9
+ - Get approval requests as Telegram notifications with one-tap approve/deny
10
+ - Set auto-approve timers for trusted operations
11
+ - Send additional input or stop agents remotely
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pip install agent-tether[telegram] # Telegram support
17
+ pip install agent-tether[slack] # Slack support
18
+ pip install agent-tether[discord] # Discord support
19
+ pip install agent-tether[all] # All platforms
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ```python
25
+ import asyncio
26
+ from agent_tether import TelegramBridge, Handlers
27
+
28
+ async def on_input(thread_id: str, text: str, username: str | None):
29
+ print(f"[{thread_id}] {username}: {text}")
30
+
31
+ async def on_approval_response(thread_id: str, request_id: str, approved: bool, **kwargs):
32
+ print(f"[{thread_id}] {'Approved' if approved else 'Denied'} {request_id}")
33
+
34
+ bridge = TelegramBridge(
35
+ token="BOT_TOKEN",
36
+ forum_group_id=123456,
37
+ handlers=Handlers(
38
+ on_input=on_input,
39
+ on_approval_response=on_approval_response,
40
+ ),
41
+ )
42
+
43
+ async def main():
44
+ await bridge.start()
45
+
46
+ thread_id = await bridge.create_thread("My Agent Task")
47
+ await bridge.send_output(thread_id, "Starting work on your request...")
48
+
49
+ await bridge.send_approval_request(
50
+ thread_id,
51
+ request_id="req_123",
52
+ tool_name="Bash",
53
+ description='{"command": "rm -rf /tmp/cache"}',
54
+ )
55
+
56
+ await bridge.wait_until_stopped()
57
+
58
+ asyncio.run(main())
59
+ ```
60
+
61
+ ### Runner Protocol Example
62
+
63
+ ```python
64
+ from agent_tether.runner import Runner, RunnerEvents, RunnerRegistry
65
+
66
+ # Implement event callbacks
67
+ class MyEventHandler:
68
+ async def on_output(self, session_id, stream, text, **kwargs):
69
+ print(f"[{session_id}] {text}", end="")
70
+
71
+ async def on_error(self, session_id, code, message):
72
+ print(f"ERROR: {message}")
73
+
74
+ async def on_exit(self, session_id, exit_code):
75
+ print(f"Session {session_id} exited with code {exit_code}")
76
+
77
+ async def on_permission_request(self, session_id, request_id, tool_name, tool_input, **kwargs):
78
+ print(f"Permission requested for {tool_name}")
79
+
80
+ # ... other event callbacks
81
+
82
+ # Register runners
83
+ registry = RunnerRegistry()
84
+
85
+ def my_runner_factory(events, config):
86
+ # Return a Runner implementation
87
+ return MyCustomRunner(events, **config)
88
+
89
+ registry.register("my-runner", my_runner_factory)
90
+
91
+ # Create and use runner
92
+ events = MyEventHandler()
93
+ runner = registry.create("my-runner", events, api_key="...", model="...")
94
+
95
+ await runner.start("sess_1", "Build a web app", approval_choice=1)
96
+ await runner.send_input("sess_1", "Add a login page")
97
+ await runner.stop("sess_1")
98
+ ```
99
+
100
+ ## Features
101
+
102
+ ### Chat Platform Bridges
103
+ - **Telegram** — Forum topics, inline keyboard approval buttons, typing indicators, HTML formatting
104
+ - **Slack** — Socket mode, threaded conversations, text-based approval commands
105
+ - **Discord** — Channel threads, pairing/authorization system, text-based approvals
106
+ - **Approval engine** — Auto-approve timers (per-thread, per-tool, per-directory), batched notifications
107
+ - **Commands** — Built-in `/help`, `/stop`, `/status`, `/usage` + custom command registry
108
+ - **Formatting** — Tool input JSON → readable text, markdown conversion, message chunking
109
+
110
+ ### Runner Protocol
111
+ - **Protocol definitions** — `Runner` and `RunnerEvents` interfaces for agent backends
112
+ - **RunnerRegistry** — Factory pattern for discovering and creating runners
113
+ - **Pluggable adapters** — Clean protocol for implementing custom agent backends
114
+ - **Event-driven** — Runners report progress via callbacks (output, errors, permissions, etc.)
115
+
116
+ ## Documentation
117
+
118
+ - **[CHANGELOG.md](CHANGELOG.md)** — Version history and changes
119
+
120
+ ## Contributing
121
+
122
+ Contributions welcome! Please feel free to submit a Pull Request.
123
+
124
+ ## Related Projects
125
+
126
+ This library is extracted from [Tether](https://github.com/xithing/tether), a full-featured control plane for supervising AI coding agents.
127
+
128
+ ## License
129
+
130
+ MIT - see [LICENSE](LICENSE) for details
131
+
@@ -0,0 +1,76 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "agent-tether"
7
+ version = "0.2.0"
8
+ description = "Tether your AI agents to human oversight through Telegram, Slack, and Discord"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ authors = [
13
+ { name = "xithing" },
14
+ ]
15
+ keywords = ["ai", "agent", "telegram", "slack", "discord", "approval", "human-in-the-loop"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Communications :: Chat",
25
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
26
+ "Typing :: Typed",
27
+ ]
28
+ dependencies = [
29
+ "pydantic>=2.0",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ # Bridges
34
+ telegram = ["python-telegram-bot>=21.0"]
35
+ slack = ["slack-sdk>=3.0", "slack-bolt>=1.0"]
36
+ discord = ["discord.py>=2.0"]
37
+ bridges = [
38
+ "python-telegram-bot>=21.0",
39
+ "slack-sdk>=3.0",
40
+ "slack-bolt>=1.0",
41
+ "discord.py>=2.0",
42
+ ]
43
+ # All features (currently just bridges)
44
+ all = [
45
+ "python-telegram-bot>=21.0",
46
+ "slack-sdk>=3.0",
47
+ "slack-bolt>=1.0",
48
+ "discord.py>=2.0",
49
+ ]
50
+ # Development
51
+ dev = [
52
+ "pytest>=8.0",
53
+ "pytest-asyncio>=0.24",
54
+ "black",
55
+ "mypy",
56
+ ]
57
+
58
+ [project.urls]
59
+ Homepage = "https://github.com/xithing/agent-tether"
60
+ Repository = "https://github.com/xithing/agent-tether"
61
+ Issues = "https://github.com/xithing/agent-tether/issues"
62
+
63
+ [tool.hatch.build.targets.wheel]
64
+ packages = ["src/agent_tether"]
65
+
66
+ [tool.pytest.ini_options]
67
+ testpaths = ["tests"]
68
+ asyncio_mode = "auto"
69
+
70
+ [tool.black]
71
+ line-length = 99
72
+ target-version = ["py311"]
73
+
74
+ [tool.mypy]
75
+ python_version = "3.11"
76
+ strict = true
@@ -0,0 +1,64 @@
1
+ """agent-tether: Tether your AI agents to human oversight through chat platforms."""
2
+
3
+ from agent_tether.formatting import format_tool_input, humanize_key, humanize_enum_value
4
+ from agent_tether.models import ApprovalRequest, CommandDef, Handlers
5
+ from agent_tether.router import BridgeRouter
6
+ from agent_tether.subscriber import EventSubscriber
7
+
8
+ __all__ = [
9
+ # Core bridge components
10
+ "ApprovalRequest",
11
+ "CommandDef",
12
+ "EventSubscriber",
13
+ "Handlers",
14
+ "BridgeRouter",
15
+ # Platform bridges (lazy loaded)
16
+ "TelegramBridge",
17
+ "SlackBridge",
18
+ "DiscordBridge",
19
+ # Formatting utilities
20
+ "format_tool_input",
21
+ "humanize_key",
22
+ "humanize_enum_value",
23
+ # Runner module (lazy loaded)
24
+ "runner",
25
+ ]
26
+
27
+
28
+ def __getattr__(name: str):
29
+ """Lazy imports for platform bridges and session module — avoids requiring optional deps at import time."""
30
+ if name == "TelegramBridge":
31
+ try:
32
+ from agent_tether.platforms.telegram.bridge import TelegramBridge
33
+
34
+ return TelegramBridge
35
+ except ImportError:
36
+ raise ImportError(
37
+ "TelegramBridge requires python-telegram-bot. "
38
+ "Install with: pip install agent-tether[telegram]"
39
+ ) from None
40
+ if name == "SlackBridge":
41
+ try:
42
+ from agent_tether.platforms.slack.bridge import SlackBridge
43
+
44
+ return SlackBridge
45
+ except ImportError:
46
+ raise ImportError(
47
+ "SlackBridge requires slack-sdk and slack-bolt. "
48
+ "Install with: pip install agent-tether[slack]"
49
+ ) from None
50
+ if name == "DiscordBridge":
51
+ try:
52
+ from agent_tether.platforms.discord.bridge import DiscordBridge
53
+
54
+ return DiscordBridge
55
+ except ImportError:
56
+ raise ImportError(
57
+ "DiscordBridge requires discord.py. "
58
+ "Install with: pip install agent-tether[discord]"
59
+ ) from None
60
+ if name == "runner":
61
+ from agent_tether import runner as runner_module
62
+
63
+ return runner_module
64
+ raise AttributeError(f"module 'agent_tether' has no attribute {name!r}")