tether-ai 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 (128) hide show
  1. tether_ai-0.2.0/MANIFEST.in +3 -0
  2. tether_ai-0.2.0/PKG-INFO +302 -0
  3. tether_ai-0.2.0/README.md +246 -0
  4. tether_ai-0.2.0/pyproject.toml +114 -0
  5. tether_ai-0.2.0/setup.cfg +4 -0
  6. tether_ai-0.2.0/tests/test_api.py +592 -0
  7. tether_ai-0.2.0/tests/test_bridge_base.py +516 -0
  8. tether_ai-0.2.0/tests/test_claude_sdk_worker.py +376 -0
  9. tether_ai-0.2.0/tests/test_claude_subprocess.py +914 -0
  10. tether_ai-0.2.0/tests/test_cli.py +121 -0
  11. tether_ai-0.2.0/tests/test_codex_discovery.py +85 -0
  12. tether_ai-0.2.0/tests/test_config.py +157 -0
  13. tether_ai-0.2.0/tests/test_discord_bridge.py +561 -0
  14. tether_ai-0.2.0/tests/test_external_agent_api.py +434 -0
  15. tether_ai-0.2.0/tests/test_external_agent_integration.py +620 -0
  16. tether_ai-0.2.0/tests/test_external_sessions_api.py +21 -0
  17. tether_ai-0.2.0/tests/test_external_sessions_codex.py +157 -0
  18. tether_ai-0.2.0/tests/test_external_to_telegram.py +137 -0
  19. tether_ai-0.2.0/tests/test_formatting.py +197 -0
  20. tether_ai-0.2.0/tests/test_git.py +52 -0
  21. tether_ai-0.2.0/tests/test_init_wizard.py +58 -0
  22. tether_ai-0.2.0/tests/test_log_redaction.py +23 -0
  23. tether_ai-0.2.0/tests/test_mcp_server.py +110 -0
  24. tether_ai-0.2.0/tests/test_middleware.py +130 -0
  25. tether_ai-0.2.0/tests/test_multi_adapter_sessions.py +285 -0
  26. tether_ai-0.2.0/tests/test_pi_discovery.py +220 -0
  27. tether_ai-0.2.0/tests/test_pi_integration.py +68 -0
  28. tether_ai-0.2.0/tests/test_pi_runner.py +360 -0
  29. tether_ai-0.2.0/tests/test_runner_events.py +401 -0
  30. tether_ai-0.2.0/tests/test_runner_registry.py +164 -0
  31. tether_ai-0.2.0/tests/test_session_usage.py +112 -0
  32. tether_ai-0.2.0/tests/test_settings.py +184 -0
  33. tether_ai-0.2.0/tests/test_sidecar_unavailable_error.py +37 -0
  34. tether_ai-0.2.0/tests/test_slack_bridge.py +380 -0
  35. tether_ai-0.2.0/tests/test_slack_discord_list_search.py +46 -0
  36. tether_ai-0.2.0/tests/test_state.py +263 -0
  37. tether_ai-0.2.0/tests/test_status_api.py +134 -0
  38. tether_ai-0.2.0/tests/test_store.py +270 -0
  39. tether_ai-0.2.0/tests/test_subscriber.py +316 -0
  40. tether_ai-0.2.0/tests/test_telegram_bridge.py +207 -0
  41. tether_ai-0.2.0/tests/test_telegram_external_pagination.py +83 -0
  42. tether_ai-0.2.0/tether/__init__.py +5 -0
  43. tether_ai-0.2.0/tether/api/__init__.py +8 -0
  44. tether_ai-0.2.0/tether/api/debug.py +38 -0
  45. tether_ai-0.2.0/tether/api/deps.py +28 -0
  46. tether_ai-0.2.0/tether/api/diff.py +42 -0
  47. tether_ai-0.2.0/tether/api/directories.py +57 -0
  48. tether_ai-0.2.0/tether/api/emit.py +397 -0
  49. tether_ai-0.2.0/tether/api/errors.py +23 -0
  50. tether_ai-0.2.0/tether/api/events.py +26 -0
  51. tether_ai-0.2.0/tether/api/external_sessions.py +378 -0
  52. tether_ai-0.2.0/tether/api/health.py +15 -0
  53. tether_ai-0.2.0/tether/api/router.py +26 -0
  54. tether_ai-0.2.0/tether/api/runner_events.py +221 -0
  55. tether_ai-0.2.0/tether/api/runner_registry.py +83 -0
  56. tether_ai-0.2.0/tether/api/schemas.py +225 -0
  57. tether_ai-0.2.0/tether/api/sessions.py +729 -0
  58. tether_ai-0.2.0/tether/api/spa.py +29 -0
  59. tether_ai-0.2.0/tether/api/state.py +101 -0
  60. tether_ai-0.2.0/tether/api/status.py +134 -0
  61. tether_ai-0.2.0/tether/bridges/__init__.py +5 -0
  62. tether_ai-0.2.0/tether/bridges/base.py +19 -0
  63. tether_ai-0.2.0/tether/bridges/discord/__init__.py +1 -0
  64. tether_ai-0.2.0/tether/bridges/discord/bot.py +3 -0
  65. tether_ai-0.2.0/tether/bridges/discord/pairing_state.py +7 -0
  66. tether_ai-0.2.0/tether/bridges/glue.py +307 -0
  67. tether_ai-0.2.0/tether/bridges/manager.py +4 -0
  68. tether_ai-0.2.0/tether/bridges/slack/__init__.py +1 -0
  69. tether_ai-0.2.0/tether/bridges/slack/bot.py +3 -0
  70. tether_ai-0.2.0/tether/bridges/subscriber.py +41 -0
  71. tether_ai-0.2.0/tether/bridges/telegram/__init__.py +1 -0
  72. tether_ai-0.2.0/tether/bridges/telegram/bot.py +3 -0
  73. tether_ai-0.2.0/tether/bridges/telegram/formatting.py +10 -0
  74. tether_ai-0.2.0/tether/bridges/telegram/state.py +3 -0
  75. tether_ai-0.2.0/tether/bridges/thread_state.py +3 -0
  76. tether_ai-0.2.0/tether/cli.py +89 -0
  77. tether_ai-0.2.0/tether/config.py +105 -0
  78. tether_ai-0.2.0/tether/db/__init__.py +122 -0
  79. tether_ai-0.2.0/tether/diff.py +47 -0
  80. tether_ai-0.2.0/tether/discovery/__init__.py +29 -0
  81. tether_ai-0.2.0/tether/discovery/claude_code.py +8 -0
  82. tether_ai-0.2.0/tether/discovery/codex_sessions.py +6 -0
  83. tether_ai-0.2.0/tether/discovery/pi_sessions.py +9 -0
  84. tether_ai-0.2.0/tether/discovery/running.py +10 -0
  85. tether_ai-0.2.0/tether/git.py +25 -0
  86. tether_ai-0.2.0/tether/init_wizard.py +139 -0
  87. tether_ai-0.2.0/tether/log_config.py +123 -0
  88. tether_ai-0.2.0/tether/log_redaction.py +154 -0
  89. tether_ai-0.2.0/tether/main.py +184 -0
  90. tether_ai-0.2.0/tether/maintenance.py +76 -0
  91. tether_ai-0.2.0/tether/mcp_server/__init__.py +5 -0
  92. tether_ai-0.2.0/tether/mcp_server/server.py +129 -0
  93. tether_ai-0.2.0/tether/mcp_server/tools.py +219 -0
  94. tether_ai-0.2.0/tether/middleware.py +87 -0
  95. tether_ai-0.2.0/tether/models.py +109 -0
  96. tether_ai-0.2.0/tether/prompts.py +12 -0
  97. tether_ai-0.2.0/tether/py.typed +0 -0
  98. tether_ai-0.2.0/tether/runner/__init__.py +153 -0
  99. tether_ai-0.2.0/tether/runner/api_runner_base.py +253 -0
  100. tether_ai-0.2.0/tether/runner/base.py +7 -0
  101. tether_ai-0.2.0/tether/runner/claude_api.py +165 -0
  102. tether_ai-0.2.0/tether/runner/claude_sdk_worker.py +373 -0
  103. tether_ai-0.2.0/tether/runner/claude_subprocess.py +532 -0
  104. tether_ai-0.2.0/tether/runner/codex_sdk_sidecar.py +301 -0
  105. tether_ai-0.2.0/tether/runner/litellm_runner.py +290 -0
  106. tether_ai-0.2.0/tether/runner/pi_rpc.py +649 -0
  107. tether_ai-0.2.0/tether/settings.py +383 -0
  108. tether_ai-0.2.0/tether/sse.py +92 -0
  109. tether_ai-0.2.0/tether/startup.py +30 -0
  110. tether_ai-0.2.0/tether/static_ui/assets/index-D-8yNyFt.js +382 -0
  111. tether_ai-0.2.0/tether/static_ui/assets/index-DobFHZ7L.css +1 -0
  112. tether_ai-0.2.0/tether/static_ui/favicon.ico +0 -0
  113. tether_ai-0.2.0/tether/static_ui/index.html +14 -0
  114. tether_ai-0.2.0/tether/static_ui/logo.png +0 -0
  115. tether_ai-0.2.0/tether/static_ui/manifest.webmanifest +1 -0
  116. tether_ai-0.2.0/tether/static_ui/registerSW.js +1 -0
  117. tether_ai-0.2.0/tether/static_ui/sw.js +1 -0
  118. tether_ai-0.2.0/tether/static_ui/workbox-8c29f6e4.js +1 -0
  119. tether_ai-0.2.0/tether/store.py +910 -0
  120. tether_ai-0.2.0/tether/tools/__init__.py +6 -0
  121. tether_ai-0.2.0/tether/tools/definitions.py +82 -0
  122. tether_ai-0.2.0/tether/tools/executor.py +190 -0
  123. tether_ai-0.2.0/tether_ai.egg-info/PKG-INFO +302 -0
  124. tether_ai-0.2.0/tether_ai.egg-info/SOURCES.txt +126 -0
  125. tether_ai-0.2.0/tether_ai.egg-info/dependency_links.txt +1 -0
  126. tether_ai-0.2.0/tether_ai.egg-info/entry_points.txt +4 -0
  127. tether_ai-0.2.0/tether_ai.egg-info/requires.txt +34 -0
  128. tether_ai-0.2.0/tether_ai.egg-info/top_level.txt +1 -0
@@ -0,0 +1,3 @@
1
+ include README.md
2
+ recursive-include tether/static_ui *
3
+ include tether/py.typed
@@ -0,0 +1,302 @@
1
+ Metadata-Version: 2.4
2
+ Name: tether-ai
3
+ Version: 0.2.0
4
+ Summary: Control your AI coding agents from your phone when you're away from your desk
5
+ Author-email: Lars de Ridder <lars@xithing.io>
6
+ Maintainer-email: Lars de Ridder <lars@xithing.io>
7
+ License-Expression: Apache-2.0
8
+ Project-URL: Homepage, https://gettether.dev
9
+ Project-URL: Documentation, https://github.com/larsderidder/tether#readme
10
+ Project-URL: Repository, https://github.com/larsderidder/tether
11
+ Project-URL: Issues, https://github.com/larsderidder/tether/issues
12
+ Project-URL: Changelog, https://github.com/larsderidder/tether/releases
13
+ Keywords: ai,agent,claude,codex,remote,mobile,coding-assistant
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Environment :: Web Environment
16
+ Classifier: Framework :: FastAPI
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development
24
+ Classifier: Topic :: Software Development :: Quality Assurance
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/markdown
28
+ Requires-Dist: agent-tether[all]>=0.3.0
29
+ Requires-Dist: agent-sessions>=0.1.0
30
+ Requires-Dist: fastapi==0.110.0
31
+ Requires-Dist: uvicorn==0.27.1
32
+ Requires-Dist: pydantic==2.7.4
33
+ Requires-Dist: structlog==24.4.0
34
+ Requires-Dist: payload-redactor>=0.3.0
35
+ Requires-Dist: anthropic>=0.39.0
36
+ Requires-Dist: sqlmodel>=0.0.22
37
+ Requires-Dist: alembic>=1.13
38
+ Requires-Dist: claude-agent-sdk>=0.1.0
39
+ Provides-Extra: dev
40
+ Requires-Dist: black==24.4.2; extra == "dev"
41
+ Requires-Dist: httpx==0.27.0; extra == "dev"
42
+ Requires-Dist: pytest==8.2.2; extra == "dev"
43
+ Requires-Dist: pytest-cov==5.0.0; extra == "dev"
44
+ Requires-Dist: anyio[trio]>=4.0.0; extra == "dev"
45
+ Requires-Dist: pytest-anyio>=0.0.0; extra == "dev"
46
+ Provides-Extra: telegram
47
+ Requires-Dist: python-telegram-bot>=20.0; extra == "telegram"
48
+ Provides-Extra: slack
49
+ Requires-Dist: slack-sdk>=3.27.0; extra == "slack"
50
+ Provides-Extra: discord
51
+ Requires-Dist: discord.py>=2.3.0; extra == "discord"
52
+ Provides-Extra: litellm
53
+ Requires-Dist: litellm>=1.0; extra == "litellm"
54
+ Provides-Extra: mcp
55
+ Requires-Dist: mcp>=0.1.0; extra == "mcp"
56
+
57
+ # Tether Agent
58
+
59
+ Control your AI coding agents from your phone when you're away from your desk.
60
+
61
+ You start a coding agent, walk away for lunch, and come back to find it stuck waiting for input for an hour. Tether fixes that. Get notified when your agent needs you, respond from anywhere.
62
+
63
+ ## Features
64
+
65
+ - **Local-first** — Runs on your machine, your data stays yours
66
+ - **Multi-agent** — Supports Claude and Codex, more to come
67
+ - **Web UI** — Monitor sessions from your phone or desktop
68
+ - **External Agent API** — WebSocket and REST API for connecting any AI agent
69
+ - **Messaging Platform Integrations** — Telegram, Slack, and Discord bridges
70
+ - **MCP Server** — Model Context Protocol server for Claude Desktop and other MCP clients
71
+ - **No API keys required** — Uses Claude / Codex local OAuth by default
72
+
73
+ ## Installation
74
+
75
+ ```bash
76
+ pip install tether-ai
77
+ ```
78
+
79
+ ### Optional Platform Integrations
80
+
81
+ Install platform-specific dependencies as needed:
82
+
83
+ ```bash
84
+ # Telegram bridge
85
+ pip install tether-ai[telegram]
86
+
87
+ # Slack bridge
88
+ pip install tether-ai[slack]
89
+
90
+ # Discord bridge
91
+ pip install tether-ai[discord]
92
+
93
+ # All bridges
94
+ pip install tether-ai[telegram,slack,discord]
95
+
96
+ # Development tools
97
+ pip install tether-ai[dev]
98
+ ```
99
+
100
+ ## Quick Start
101
+
102
+ ### Run the Agent Server
103
+
104
+ ```bash
105
+ # Start the agent server
106
+ tether-agent
107
+ ```
108
+
109
+ Then open http://localhost:8787 in your browser.
110
+
111
+ ### Use with MCP (Claude Desktop)
112
+
113
+ Add Tether as an MCP server in your Claude Desktop config:
114
+
115
+ ```json
116
+ {
117
+ "mcpServers": {
118
+ "tether": {
119
+ "command": "python",
120
+ "args": ["-m", "tether.mcp_server.server"],
121
+ "env": {
122
+ "TETHER_API_URL": "http://localhost:8787"
123
+ }
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ ## Configuration
130
+
131
+ Set environment variables to configure:
132
+
133
+ | Variable | Description | Default |
134
+ |----------|-------------|---------|
135
+ | `TETHER_AGENT_HOST` | Host to bind to | `0.0.0.0` |
136
+ | `TETHER_AGENT_PORT` | Port to listen on | `8787` |
137
+ | `TETHER_AGENT_TOKEN` | Auth token (optional; if set, API/UI/MCP require bearer auth) | — |
138
+ | `TETHER_AGENT_DEV_MODE` | Enable dev mode (no token required) | `0` |
139
+ | `TETHER_AGENT_ADAPTER` | AI adapter to use | `claude_auto` |
140
+ | `TETHER_AGENT_DATA_DIR` | Data storage directory | `./data` |
141
+
142
+ ### AI Adapters
143
+
144
+ | Adapter | Description |
145
+ |---------|-------------|
146
+ | `claude_auto` | Auto-detect (prefer OAuth, fallback to API key) |
147
+ | `claude_subprocess` | Claude via Agent SDK in subprocess (CLI OAuth) |
148
+ | `claude_api` | Claude via API key (set `ANTHROPIC_API_KEY`) |
149
+ | `codex_sdk_sidecar` | Codex via sidecar |
150
+
151
+ ### Messaging Platform Bridges
152
+
153
+ Configure bridges to get notifications on your preferred platform:
154
+
155
+ #### Telegram
156
+
157
+ ```bash
158
+ export TELEGRAM_BOT_TOKEN="your_bot_token"
159
+ export TELEGRAM_FORUM_GROUP_ID="your_group_id"
160
+ ```
161
+
162
+ #### Slack
163
+
164
+ ```bash
165
+ export SLACK_BOT_TOKEN="xoxb-your-token"
166
+ export SLACK_CHANNEL_ID="C01234567"
167
+ ```
168
+
169
+ #### Discord
170
+
171
+ ```bash
172
+ export DISCORD_BOT_TOKEN="your_bot_token"
173
+ export DISCORD_CHANNEL_ID="1234567890"
174
+ ```
175
+
176
+ ## External Agent API
177
+
178
+ Tether exposes a WebSocket and REST API for external agents to connect and interact with users through messaging platforms.
179
+
180
+ ### REST API Endpoints
181
+
182
+ #### Create a Session
183
+
184
+ ```bash
185
+ POST /external/sessions
186
+ Content-Type: application/json
187
+
188
+ {
189
+ "agent_metadata": {
190
+ "name": "My Custom Agent",
191
+ "type": "custom",
192
+ "icon": "🤖",
193
+ "workspace": "my-workspace"
194
+ },
195
+ "session_name": "Code Review Task",
196
+ "platform": "telegram"
197
+ }
198
+ ```
199
+
200
+ Response:
201
+ ```json
202
+ {
203
+ "session_id": "sess_abc123",
204
+ "platform": "telegram",
205
+ "thread_info": {
206
+ "thread_id": "123456",
207
+ "platform": "telegram"
208
+ }
209
+ }
210
+ ```
211
+
212
+ #### Send Output
213
+
214
+ ```bash
215
+ POST /external/sessions/{session_id}/output
216
+ Content-Type: application/json
217
+
218
+ {
219
+ "text": "Agent output text here",
220
+ "metadata": {}
221
+ }
222
+ ```
223
+
224
+ #### Request Approval
225
+
226
+ ```bash
227
+ POST /external/sessions/{session_id}/approval
228
+ Content-Type: application/json
229
+
230
+ {
231
+ "title": "Approve Changes?",
232
+ "description": "Ready to commit these changes",
233
+ "options": ["Approve", "Reject", "Review"]
234
+ }
235
+ ```
236
+
237
+ #### Check for Input
238
+
239
+ ```bash
240
+ GET /external/sessions/{session_id}/input?timeout=30
241
+ ```
242
+
243
+ Response:
244
+ ```json
245
+ {
246
+ "type": "human_input",
247
+ "data": {
248
+ "text": "User's message",
249
+ "timestamp": "2025-01-01T12:00:00Z"
250
+ }
251
+ }
252
+ ```
253
+
254
+ ### WebSocket API
255
+
256
+ Connect to `/external/sessions/{session_id}/ws` for bidirectional communication:
257
+
258
+ **Agent → Tether events:**
259
+ - `output`: Send text output to user
260
+ - `approval_request`: Request user approval
261
+ - `status`: Update agent status (thinking, executing, done, error)
262
+
263
+ **Tether → Agent events:**
264
+ - `human_input`: User sent a message
265
+ - `approval_response`: User responded to approval request
266
+
267
+ Example WebSocket message:
268
+ ```json
269
+ {
270
+ "type": "output",
271
+ "data": {
272
+ "text": "Processing your request...",
273
+ "metadata": {}
274
+ }
275
+ }
276
+ ```
277
+
278
+ ## Development
279
+
280
+ ### Run Tests
281
+
282
+ ```bash
283
+ pytest tests/
284
+ ```
285
+
286
+ ### Database Migrations
287
+
288
+ ```bash
289
+ # Create a new migration
290
+ alembic revision --autogenerate -m "description"
291
+
292
+ # Apply migrations
293
+ alembic upgrade head
294
+ ```
295
+
296
+ ## Documentation
297
+
298
+ For full documentation, see [github.com/larsderidder/tether](https://github.com/larsderidder/tether).
299
+
300
+ ## License
301
+
302
+ Apache 2.0. See [LICENSE](https://github.com/larsderidder/tether/blob/main/LICENSE) for details.
@@ -0,0 +1,246 @@
1
+ # Tether Agent
2
+
3
+ Control your AI coding agents from your phone when you're away from your desk.
4
+
5
+ You start a coding agent, walk away for lunch, and come back to find it stuck waiting for input for an hour. Tether fixes that. Get notified when your agent needs you, respond from anywhere.
6
+
7
+ ## Features
8
+
9
+ - **Local-first** — Runs on your machine, your data stays yours
10
+ - **Multi-agent** — Supports Claude and Codex, more to come
11
+ - **Web UI** — Monitor sessions from your phone or desktop
12
+ - **External Agent API** — WebSocket and REST API for connecting any AI agent
13
+ - **Messaging Platform Integrations** — Telegram, Slack, and Discord bridges
14
+ - **MCP Server** — Model Context Protocol server for Claude Desktop and other MCP clients
15
+ - **No API keys required** — Uses Claude / Codex local OAuth by default
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install tether-ai
21
+ ```
22
+
23
+ ### Optional Platform Integrations
24
+
25
+ Install platform-specific dependencies as needed:
26
+
27
+ ```bash
28
+ # Telegram bridge
29
+ pip install tether-ai[telegram]
30
+
31
+ # Slack bridge
32
+ pip install tether-ai[slack]
33
+
34
+ # Discord bridge
35
+ pip install tether-ai[discord]
36
+
37
+ # All bridges
38
+ pip install tether-ai[telegram,slack,discord]
39
+
40
+ # Development tools
41
+ pip install tether-ai[dev]
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ### Run the Agent Server
47
+
48
+ ```bash
49
+ # Start the agent server
50
+ tether-agent
51
+ ```
52
+
53
+ Then open http://localhost:8787 in your browser.
54
+
55
+ ### Use with MCP (Claude Desktop)
56
+
57
+ Add Tether as an MCP server in your Claude Desktop config:
58
+
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "tether": {
63
+ "command": "python",
64
+ "args": ["-m", "tether.mcp_server.server"],
65
+ "env": {
66
+ "TETHER_API_URL": "http://localhost:8787"
67
+ }
68
+ }
69
+ }
70
+ }
71
+ ```
72
+
73
+ ## Configuration
74
+
75
+ Set environment variables to configure:
76
+
77
+ | Variable | Description | Default |
78
+ |----------|-------------|---------|
79
+ | `TETHER_AGENT_HOST` | Host to bind to | `0.0.0.0` |
80
+ | `TETHER_AGENT_PORT` | Port to listen on | `8787` |
81
+ | `TETHER_AGENT_TOKEN` | Auth token (optional; if set, API/UI/MCP require bearer auth) | — |
82
+ | `TETHER_AGENT_DEV_MODE` | Enable dev mode (no token required) | `0` |
83
+ | `TETHER_AGENT_ADAPTER` | AI adapter to use | `claude_auto` |
84
+ | `TETHER_AGENT_DATA_DIR` | Data storage directory | `./data` |
85
+
86
+ ### AI Adapters
87
+
88
+ | Adapter | Description |
89
+ |---------|-------------|
90
+ | `claude_auto` | Auto-detect (prefer OAuth, fallback to API key) |
91
+ | `claude_subprocess` | Claude via Agent SDK in subprocess (CLI OAuth) |
92
+ | `claude_api` | Claude via API key (set `ANTHROPIC_API_KEY`) |
93
+ | `codex_sdk_sidecar` | Codex via sidecar |
94
+
95
+ ### Messaging Platform Bridges
96
+
97
+ Configure bridges to get notifications on your preferred platform:
98
+
99
+ #### Telegram
100
+
101
+ ```bash
102
+ export TELEGRAM_BOT_TOKEN="your_bot_token"
103
+ export TELEGRAM_FORUM_GROUP_ID="your_group_id"
104
+ ```
105
+
106
+ #### Slack
107
+
108
+ ```bash
109
+ export SLACK_BOT_TOKEN="xoxb-your-token"
110
+ export SLACK_CHANNEL_ID="C01234567"
111
+ ```
112
+
113
+ #### Discord
114
+
115
+ ```bash
116
+ export DISCORD_BOT_TOKEN="your_bot_token"
117
+ export DISCORD_CHANNEL_ID="1234567890"
118
+ ```
119
+
120
+ ## External Agent API
121
+
122
+ Tether exposes a WebSocket and REST API for external agents to connect and interact with users through messaging platforms.
123
+
124
+ ### REST API Endpoints
125
+
126
+ #### Create a Session
127
+
128
+ ```bash
129
+ POST /external/sessions
130
+ Content-Type: application/json
131
+
132
+ {
133
+ "agent_metadata": {
134
+ "name": "My Custom Agent",
135
+ "type": "custom",
136
+ "icon": "🤖",
137
+ "workspace": "my-workspace"
138
+ },
139
+ "session_name": "Code Review Task",
140
+ "platform": "telegram"
141
+ }
142
+ ```
143
+
144
+ Response:
145
+ ```json
146
+ {
147
+ "session_id": "sess_abc123",
148
+ "platform": "telegram",
149
+ "thread_info": {
150
+ "thread_id": "123456",
151
+ "platform": "telegram"
152
+ }
153
+ }
154
+ ```
155
+
156
+ #### Send Output
157
+
158
+ ```bash
159
+ POST /external/sessions/{session_id}/output
160
+ Content-Type: application/json
161
+
162
+ {
163
+ "text": "Agent output text here",
164
+ "metadata": {}
165
+ }
166
+ ```
167
+
168
+ #### Request Approval
169
+
170
+ ```bash
171
+ POST /external/sessions/{session_id}/approval
172
+ Content-Type: application/json
173
+
174
+ {
175
+ "title": "Approve Changes?",
176
+ "description": "Ready to commit these changes",
177
+ "options": ["Approve", "Reject", "Review"]
178
+ }
179
+ ```
180
+
181
+ #### Check for Input
182
+
183
+ ```bash
184
+ GET /external/sessions/{session_id}/input?timeout=30
185
+ ```
186
+
187
+ Response:
188
+ ```json
189
+ {
190
+ "type": "human_input",
191
+ "data": {
192
+ "text": "User's message",
193
+ "timestamp": "2025-01-01T12:00:00Z"
194
+ }
195
+ }
196
+ ```
197
+
198
+ ### WebSocket API
199
+
200
+ Connect to `/external/sessions/{session_id}/ws` for bidirectional communication:
201
+
202
+ **Agent → Tether events:**
203
+ - `output`: Send text output to user
204
+ - `approval_request`: Request user approval
205
+ - `status`: Update agent status (thinking, executing, done, error)
206
+
207
+ **Tether → Agent events:**
208
+ - `human_input`: User sent a message
209
+ - `approval_response`: User responded to approval request
210
+
211
+ Example WebSocket message:
212
+ ```json
213
+ {
214
+ "type": "output",
215
+ "data": {
216
+ "text": "Processing your request...",
217
+ "metadata": {}
218
+ }
219
+ }
220
+ ```
221
+
222
+ ## Development
223
+
224
+ ### Run Tests
225
+
226
+ ```bash
227
+ pytest tests/
228
+ ```
229
+
230
+ ### Database Migrations
231
+
232
+ ```bash
233
+ # Create a new migration
234
+ alembic revision --autogenerate -m "description"
235
+
236
+ # Apply migrations
237
+ alembic upgrade head
238
+ ```
239
+
240
+ ## Documentation
241
+
242
+ For full documentation, see [github.com/larsderidder/tether](https://github.com/larsderidder/tether).
243
+
244
+ ## License
245
+
246
+ Apache 2.0. See [LICENSE](https://github.com/larsderidder/tether/blob/main/LICENSE) for details.
@@ -0,0 +1,114 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tether-ai"
7
+ version = "0.2.0"
8
+ description = "Control your AI coding agents from your phone when you're away from your desk"
9
+ readme = "README.md"
10
+ license = "Apache-2.0"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Lars de Ridder", email = "lars@xithing.io" },
14
+ ]
15
+ maintainers = [
16
+ { name = "Lars de Ridder", email = "lars@xithing.io" },
17
+ ]
18
+ keywords = [
19
+ "ai",
20
+ "agent",
21
+ "claude",
22
+ "codex",
23
+ "remote",
24
+ "mobile",
25
+ "coding-assistant",
26
+ ]
27
+ classifiers = [
28
+ "Development Status :: 3 - Alpha",
29
+ "Environment :: Web Environment",
30
+ "Framework :: FastAPI",
31
+ "Intended Audience :: Developers",
32
+ "Operating System :: OS Independent",
33
+ "Programming Language :: Python :: 3",
34
+ "Programming Language :: Python :: 3.10",
35
+ "Programming Language :: Python :: 3.11",
36
+ "Programming Language :: Python :: 3.12",
37
+ "Topic :: Software Development",
38
+ "Topic :: Software Development :: Quality Assurance",
39
+ "Typing :: Typed",
40
+ ]
41
+ dependencies = [
42
+ "agent-tether[all]>=0.3.0",
43
+ "agent-sessions>=0.1.0",
44
+ "fastapi==0.110.0",
45
+ "uvicorn==0.27.1",
46
+ "pydantic==2.7.4",
47
+ "structlog==24.4.0",
48
+ "payload-redactor>=0.3.0",
49
+ "anthropic>=0.39.0",
50
+ "sqlmodel>=0.0.22",
51
+ "alembic>=1.13",
52
+ "claude-agent-sdk>=0.1.0",
53
+ ]
54
+
55
+ [project.optional-dependencies]
56
+ dev = [
57
+ "black==24.4.2",
58
+ "httpx==0.27.0",
59
+ "pytest==8.2.2",
60
+ "pytest-cov==5.0.0",
61
+ "anyio[trio]>=4.0.0",
62
+ "pytest-anyio>=0.0.0",
63
+ ]
64
+ telegram = [
65
+ "python-telegram-bot>=20.0",
66
+ ]
67
+ slack = [
68
+ "slack-sdk>=3.27.0",
69
+ ]
70
+ discord = [
71
+ "discord.py>=2.3.0",
72
+ ]
73
+ litellm = [
74
+ "litellm>=1.0",
75
+ ]
76
+ mcp = [
77
+ "mcp>=0.1.0",
78
+ ]
79
+
80
+ [project.urls]
81
+ Homepage = "https://gettether.dev"
82
+ Documentation = "https://github.com/larsderidder/tether#readme"
83
+ Repository = "https://github.com/larsderidder/tether"
84
+ Issues = "https://github.com/larsderidder/tether/issues"
85
+ Changelog = "https://github.com/larsderidder/tether/releases"
86
+
87
+ [project.scripts]
88
+ tether = "tether.cli:main"
89
+ tether-agent = "tether.cli:_start_compat"
90
+ tether-mcp = "tether.mcp_server.server:main"
91
+
92
+ [tool.setuptools.packages.find]
93
+ include = ["tether*"]
94
+
95
+ [tool.setuptools.package-data]
96
+ tether = ["static_ui/**/*", "py.typed"]
97
+
98
+ [tool.pytest.ini_options]
99
+ testpaths = ["tests"]
100
+
101
+ [tool.coverage.run]
102
+ source = ["tether"]
103
+ omit = ["*/tests/*"]
104
+
105
+ [tool.coverage.report]
106
+ exclude_lines = [
107
+ "pragma: no cover",
108
+ "if TYPE_CHECKING:",
109
+ "raise NotImplementedError",
110
+ ]
111
+
112
+ [tool.black]
113
+ line-length = 88
114
+ target-version = ["py310"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+