telegram-opencode-bridge-bot 0.1.3__tar.gz → 0.1.5__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 (28) hide show
  1. {telegram_opencode_bridge_bot-0.1.3/telegram_opencode_bridge_bot.egg-info → telegram_opencode_bridge_bot-0.1.5}/PKG-INFO +9 -10
  2. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/README.md +8 -9
  3. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/bot.py +66 -19
  4. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/handlers/commands.py +578 -319
  5. telegram_opencode_bridge_bot-0.1.5/handlers/messages.py +818 -0
  6. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/opencode/client.py +48 -0
  7. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/pyproject.toml +1 -1
  8. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5/telegram_opencode_bridge_bot.egg-info}/PKG-INFO +9 -10
  9. telegram_opencode_bridge_bot-0.1.3/handlers/messages.py +0 -482
  10. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/.env.example +0 -0
  11. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/MANIFEST.in +0 -0
  12. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/config.py +0 -0
  13. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/handlers/__init__.py +0 -0
  14. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/list_session_models.py +0 -0
  15. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/opencode/__init__.py +0 -0
  16. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/opencode/server.py +0 -0
  17. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/requirements.txt +0 -0
  18. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/sessions/__init__.py +0 -0
  19. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/sessions/manager.py +0 -0
  20. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/setup.cfg +0 -0
  21. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/telegram_opencode_bridge_bot.egg-info/SOURCES.txt +0 -0
  22. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/telegram_opencode_bridge_bot.egg-info/dependency_links.txt +0 -0
  23. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/telegram_opencode_bridge_bot.egg-info/entry_points.txt +0 -0
  24. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/telegram_opencode_bridge_bot.egg-info/requires.txt +0 -0
  25. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/telegram_opencode_bridge_bot.egg-info/top_level.txt +0 -0
  26. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/utils/__init__.py +0 -0
  27. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/utils/formatting.py +0 -0
  28. {telegram_opencode_bridge_bot-0.1.3 → telegram_opencode_bridge_bot-0.1.5}/utils/security.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: telegram-opencode-bridge-bot
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: A Telegram bot that bridges messages directly to OpenCode — an AI coding agent running on your machine
5
5
  Author-email: MaheshNagabhairava <maheshnagabhirava12345@gmail.com>
6
6
  License-Expression: MIT
@@ -30,6 +30,7 @@ A lightweight Python bot that bridges your Telegram messages directly to [OpenCo
30
30
  - **Auto message splitting** — handles responses longer than Telegram's 4096 char limit
31
31
  - **Security** — whitelist-based access control + rate limiting
32
32
  - **Workspace Switching** — Switching from one workspace to another
33
+ - **Uploading from Mobile to WorkSpace** - U can upload the documents/images from your mobile to the opencode agent workspace
33
34
 
34
35
  ## 📋 Prerequisites
35
36
 
@@ -45,7 +46,7 @@ A lightweight Python bot that bridges your Telegram messages directly to [OpenCo
45
46
 
46
47
  ### Quick Installation:
47
48
  ```bash
48
- pip install telegram-opencode-bridge-bot==0.1.2
49
+ pip install telegram-opencode-bridge-bot==0.1.5
49
50
  telegram-opencode-bot
50
51
  telegram-opencode-bot --env (use --env flag if u want to re-configure later anytime)
51
52
  ```
@@ -76,17 +77,15 @@ Open Telegram, find your bot, and start asking! 🎉
76
77
  | `/start` | Welcome message & connection check |
77
78
  | `/help` | Show all commands |
78
79
  | `/new` | Start a fresh conversation |
79
- | `/sessions` | List your recent sessions |
80
- | `/switch <id>` | Switch to a different session |
81
- | `/model <name>` | Change AI model(ex: /model opencode/deepseek-v4-flash-free) |
82
- | `/mode <plan\|build>` | Toggle plan/build mode |
83
- | `/share` | Share current session (public URL) |
80
+ | `/sessions` | List your recent sessions/conversations and to select a session/conversation |
81
+ | `/plan` | plan mode |
82
+ | `/build` | build mode |
83
+ | `/share` | Share current session/conversation (public URL) |
84
84
  | `/status` | Check connection & session details |
85
85
  | `/id` | Show your Telegram user ID |
86
86
  | `/stop` | Abort active model processing |
87
- | `/models` | List all available models |
88
- | `/project` | To view the current workspace, sub folder workspaces and to change the workspace (ex: /project 2)|
89
- | `/project depth <1to5>` | Depth level recursive check for subfolders (ex: if u give depth 2, only 2 sub folders it will show from root) |
87
+ | `/models` | List all available providers, models and to select the model |
88
+ | `/project` | To view the current workspace, sub folder workspaces and to change the workspace |
90
89
  | `/enable` | To enable the streaming |
91
90
  | `/disable` | To disable the streaming |
92
91
 
@@ -13,6 +13,7 @@ A lightweight Python bot that bridges your Telegram messages directly to [OpenCo
13
13
  - **Auto message splitting** — handles responses longer than Telegram's 4096 char limit
14
14
  - **Security** — whitelist-based access control + rate limiting
15
15
  - **Workspace Switching** — Switching from one workspace to another
16
+ - **Uploading from Mobile to WorkSpace** - U can upload the documents/images from your mobile to the opencode agent workspace
16
17
 
17
18
  ## 📋 Prerequisites
18
19
 
@@ -28,7 +29,7 @@ A lightweight Python bot that bridges your Telegram messages directly to [OpenCo
28
29
 
29
30
  ### Quick Installation:
30
31
  ```bash
31
- pip install telegram-opencode-bridge-bot==0.1.2
32
+ pip install telegram-opencode-bridge-bot==0.1.5
32
33
  telegram-opencode-bot
33
34
  telegram-opencode-bot --env (use --env flag if u want to re-configure later anytime)
34
35
  ```
@@ -59,17 +60,15 @@ Open Telegram, find your bot, and start asking! 🎉
59
60
  | `/start` | Welcome message & connection check |
60
61
  | `/help` | Show all commands |
61
62
  | `/new` | Start a fresh conversation |
62
- | `/sessions` | List your recent sessions |
63
- | `/switch <id>` | Switch to a different session |
64
- | `/model <name>` | Change AI model(ex: /model opencode/deepseek-v4-flash-free) |
65
- | `/mode <plan\|build>` | Toggle plan/build mode |
66
- | `/share` | Share current session (public URL) |
63
+ | `/sessions` | List your recent sessions/conversations and to select a session/conversation |
64
+ | `/plan` | plan mode |
65
+ | `/build` | build mode |
66
+ | `/share` | Share current session/conversation (public URL) |
67
67
  | `/status` | Check connection & session details |
68
68
  | `/id` | Show your Telegram user ID |
69
69
  | `/stop` | Abort active model processing |
70
- | `/models` | List all available models |
71
- | `/project` | To view the current workspace, sub folder workspaces and to change the workspace (ex: /project 2)|
72
- | `/project depth <1to5>` | Depth level recursive check for subfolders (ex: if u give depth 2, only 2 sub folders it will show from root) |
70
+ | `/models` | List all available providers, models and to select the model |
71
+ | `/project` | To view the current workspace, sub folder workspaces and to change the workspace |
73
72
  | `/enable` | To enable the streaming |
74
73
  | `/disable` | To disable the streaming |
75
74
 
@@ -24,9 +24,12 @@ from telegram.ext import (
24
24
  ApplicationBuilder,
25
25
  CommandHandler,
26
26
  MessageHandler,
27
+ CallbackQueryHandler,
27
28
  filters,
28
29
  ContextTypes,
29
30
  )
31
+ from telegram.request import HTTPXRequest
32
+ from telegram.error import TimedOut, NetworkError
30
33
  from utils.formatting import format_error
31
34
 
32
35
  from config import config
@@ -38,9 +41,8 @@ from handlers.commands import (
38
41
  help_command,
39
42
  new_command,
40
43
  sessions_command,
41
- switch_command,
42
- model_command,
43
- mode_command,
44
+ plan_command,
45
+ build_command,
44
46
  share_command,
45
47
  status_command,
46
48
  id_command,
@@ -50,8 +52,9 @@ from handlers.commands import (
50
52
  enable_command,
51
53
  disable_command,
52
54
  set_bot_commands,
55
+ callback_handler,
53
56
  )
54
- from handlers.messages import handle_message
57
+ from handlers.messages import handle_message, handle_document
55
58
 
56
59
  # ── Logging Setup ──────────────────────────────────────────
57
60
  logging.basicConfig(
@@ -62,6 +65,25 @@ logging.basicConfig(
62
65
  logger = logging.getLogger("opencode-telegram-bot")
63
66
 
64
67
 
68
+ class RetryingHTTPXRequest(HTTPXRequest):
69
+ """Custom HTTPXRequest that automatically retries failed requests on connection timeouts/errors."""
70
+ async def do_request(self, *args, **kwargs) -> tuple[int, bytes]:
71
+ max_retries = 3
72
+ for attempt in range(max_retries):
73
+ try:
74
+ return await super().do_request(*args, **kwargs)
75
+ except (TimedOut, NetworkError) as e:
76
+ # Do not retry on Pool timeout errors
77
+ if "Pool timeout" in str(e) or attempt == max_retries - 1:
78
+ raise
79
+
80
+ logger.warning(
81
+ f"⚠️ Telegram request failed (attempt {attempt + 1}/{max_retries}): {e}. "
82
+ f"Retrying in {1.0 * (attempt + 1)}s..."
83
+ )
84
+ await asyncio.sleep(1.0 * (attempt + 1))
85
+
86
+
65
87
  # ── Wrap handlers with auth decorator ──────────────────────
66
88
 
67
89
  def build_authorized_handlers(authorizer: UserAuthorizer, rate_limiter: RateLimiter):
@@ -84,16 +106,12 @@ def build_authorized_handlers(authorizer: UserAuthorizer, rate_limiter: RateLimi
84
106
  await sessions_command(update, context)
85
107
 
86
108
  @authorized(authorizer, rate_limiter)
87
- async def _switch(update, context):
88
- await switch_command(update, context)
109
+ async def _plan(update, context):
110
+ await plan_command(update, context)
89
111
 
90
112
  @authorized(authorizer, rate_limiter)
91
- async def _model(update, context):
92
- await model_command(update, context)
93
-
94
- @authorized(authorizer, rate_limiter)
95
- async def _mode(update, context):
96
- await mode_command(update, context)
113
+ async def _build(update, context):
114
+ await build_command(update, context)
97
115
 
98
116
  @authorized(authorizer, rate_limiter)
99
117
  async def _share(update, context):
@@ -127,27 +145,36 @@ def build_authorized_handlers(authorizer: UserAuthorizer, rate_limiter: RateLimi
127
145
  async def _disable(update, context):
128
146
  await disable_command(update, context)
129
147
 
148
+ @authorized(authorizer)
149
+ async def _callback(update, context):
150
+ await callback_handler(update, context)
151
+
130
152
  @authorized(authorizer, rate_limiter)
131
153
  async def _message(update, context):
132
154
  await handle_message(update, context)
133
155
 
156
+ @authorized(authorizer, rate_limiter)
157
+ async def _document(update, context):
158
+ await handle_document(update, context)
159
+
134
160
  return {
135
161
  "start": _start,
136
162
  "help": _help,
137
163
  "new": _new,
138
164
  "sessions": _sessions,
139
- "switch": _switch,
140
- "model": _model,
141
165
  "models": _models,
142
166
  "stop": _stop,
143
167
  "project": _project,
144
168
  "enable": _enable,
145
169
  "disable": _disable,
146
- "mode": _mode,
170
+ "plan": _plan,
171
+ "build": _build,
147
172
  "share": _share,
148
173
  "status": _status,
149
174
  "id": _id,
175
+ "callback": _callback,
150
176
  "message": _message,
177
+ "document": _document,
151
178
  }
152
179
 
153
180
 
@@ -390,9 +417,18 @@ def main():
390
417
  session_mgr = SessionManager(db_path=config.db_path)
391
418
 
392
419
  # ── Build Telegram application ────────────────────────
420
+ request = RetryingHTTPXRequest(
421
+ connect_timeout=15.0,
422
+ read_timeout=20.0,
423
+ write_timeout=20.0,
424
+ pool_timeout=5.0,
425
+ connection_pool_size=512,
426
+ )
427
+
393
428
  application = (
394
429
  ApplicationBuilder()
395
430
  .token(config.telegram_bot_token)
431
+ .request(request)
396
432
  .post_init(post_init)
397
433
  .post_shutdown(post_shutdown)
398
434
  .build()
@@ -415,18 +451,20 @@ def main():
415
451
  application.add_handler(CommandHandler("help", handlers["help"], block=False))
416
452
  application.add_handler(CommandHandler("new", handlers["new"], block=False))
417
453
  application.add_handler(CommandHandler("sessions", handlers["sessions"], block=False))
418
- application.add_handler(CommandHandler("switch", handlers["switch"], block=False))
419
- application.add_handler(CommandHandler("model", handlers["model"], block=False))
420
454
  application.add_handler(CommandHandler("models", handlers["models"], block=False))
421
455
  application.add_handler(CommandHandler("stop", handlers["stop"], block=False))
422
456
  application.add_handler(CommandHandler("project", handlers["project"], block=False))
423
457
  application.add_handler(CommandHandler("enable", handlers["enable"], block=False))
424
458
  application.add_handler(CommandHandler("disable", handlers["disable"], block=False))
425
- application.add_handler(CommandHandler("mode", handlers["mode"], block=False))
459
+ application.add_handler(CommandHandler("plan", handlers["plan"], block=False))
460
+ application.add_handler(CommandHandler("build", handlers["build"], block=False))
426
461
  application.add_handler(CommandHandler("share", handlers["share"], block=False))
427
462
  application.add_handler(CommandHandler("status", handlers["status"], block=False))
428
463
  application.add_handler(CommandHandler("id", handlers["id"], block=False))
429
464
 
465
+ # ── Register callback query handler ───────────────────
466
+ application.add_handler(CallbackQueryHandler(handlers["callback"], block=False))
467
+
430
468
  # ── Register message handler (catches all text) ───────
431
469
  application.add_handler(
432
470
  MessageHandler(
@@ -436,11 +474,20 @@ def main():
436
474
  )
437
475
  )
438
476
 
477
+ # ── Register document handler (catches file uploads) ──
478
+ application.add_handler(
479
+ MessageHandler(
480
+ (filters.Document.ALL | filters.PHOTO) & ~filters.COMMAND,
481
+ handlers["document"],
482
+ block=False,
483
+ )
484
+ )
485
+
439
486
  # ── Start polling ─────────────────────────────────────
440
487
  logger.info("Starting bot with long polling...")
441
488
  application.run_polling(
442
489
  drop_pending_updates=True,
443
- allowed_updates=["message"],
490
+ allowed_updates=["message", "callback_query"],
444
491
  )
445
492
 
446
493