TeLLMgramBot 3.13.4__tar.gz → 3.13.6__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 (26) hide show
  1. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/PKG-INFO +3 -3
  2. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/README.md +2 -2
  3. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/initialize.py +12 -9
  4. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/tools.py +27 -13
  5. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/PKG-INFO +3 -3
  6. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/setup.py +1 -1
  7. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/LICENSE +0 -0
  8. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/TeLLMgramBot.py +0 -0
  9. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/__init__.py +0 -0
  10. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/archive.py +0 -0
  11. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/conversation.py +0 -0
  12. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/database.py +0 -0
  13. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/message_handlers.py +0 -0
  14. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/models.py +0 -0
  15. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/__init__.py +0 -0
  16. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/anthropic_provider.py +0 -0
  17. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/base.py +0 -0
  18. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/factory.py +0 -0
  19. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/openai_provider.py +0 -0
  20. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/utils.py +0 -0
  21. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/web_utils.py +0 -0
  22. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/SOURCES.txt +0 -0
  23. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/dependency_links.txt +0 -0
  24. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/requires.txt +0 -0
  25. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/top_level.txt +0 -0
  26. {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TeLLMgramBot
3
- Version: 3.13.4
3
+ Version: 3.13.6
4
4
  Summary: LLM-powered Telegram bot (OpenAI + Anthropic)
5
5
  Home-page: https://github.com/Digital-Heresy/TeLLMgramBot
6
6
  Author: Digital Heresy
@@ -101,7 +101,7 @@ Override default directory locations by setting these environment variables (use
101
101
  If unset, all paths default to subdirectories of the execution directory (the directory containing your entry-point script).
102
102
 
103
103
  ## API Keys
104
- TeLLMgramBot supports four API keys. OpenAI, Anthropic, and VirusTotal keys load from environment variables or `.key` files. The Telegram key loads from its env var or the bot config field `telegram_api_key` (no `.key` file):
104
+ TeLLMgramBot supports four API keys. OpenAI, Anthropic, and VirusTotal keys load from environment variables or `.key` files. The Telegram key loads from the bot config field `telegram_api_key` or its env var (no `.key` file); config wins when explicitly set:
105
105
 
106
106
  | Key | Env Var | File/Config | When required |
107
107
  |-----|---------|-------------|---------------|
@@ -150,7 +150,7 @@ When the bot is triggered in a group and about to respond (not deferring to anot
150
150
  - `bot_owner`: Telegram username(s) with admin access (required, no `@`). Accepts a single string or a YAML list of usernames.
151
151
  - `chat_model`: LLM model for conversation (e.g. `gpt-4o-mini` or `claude-sonnet-4-6`)
152
152
  - `url_model`: LLM model for URL analysis (e.g. `gpt-4o` or `claude-haiku-4-5`)
153
- - `telegram_api_key`: Telegram bot API key (required). Lookup order: (1) `TELLMGRAMBOT_TELEGRAM_API_KEY` env var, (2) `telegram_api_key` in `config.yaml`. Exits on placeholder, missing, or malformed key.
153
+ - `telegram_api_key`: Telegram bot API key (required). Lookup order: (1) `telegram_api_key` in `config.yaml`, (2) `TELLMGRAMBOT_TELEGRAM_API_KEY` env var. Config wins when explicitly set. Exits on placeholder, missing, or malformed key.
154
154
  - `bot_nickname` / `bot_initials`: Names the bot responds to in groups
155
155
  - `instance_name`: Optional label for console prefix, log filename, and database name (e.g. `MyBot` produces `[MyBot] INFO: ...` on console, `MyBot_{timestamp}.log` logs, and `MyBot.db` database); omit to use bot's Telegram username for logging and `conversations.db` for database. Use distinct names when running multiple bot instances in the same directory.
156
156
  - `token_limit`: Max tokens (optional; defaults to model's maximum)
@@ -69,7 +69,7 @@ Override default directory locations by setting these environment variables (use
69
69
  If unset, all paths default to subdirectories of the execution directory (the directory containing your entry-point script).
70
70
 
71
71
  ## API Keys
72
- TeLLMgramBot supports four API keys. OpenAI, Anthropic, and VirusTotal keys load from environment variables or `.key` files. The Telegram key loads from its env var or the bot config field `telegram_api_key` (no `.key` file):
72
+ TeLLMgramBot supports four API keys. OpenAI, Anthropic, and VirusTotal keys load from environment variables or `.key` files. The Telegram key loads from the bot config field `telegram_api_key` or its env var (no `.key` file); config wins when explicitly set:
73
73
 
74
74
  | Key | Env Var | File/Config | When required |
75
75
  |-----|---------|-------------|---------------|
@@ -118,7 +118,7 @@ When the bot is triggered in a group and about to respond (not deferring to anot
118
118
  - `bot_owner`: Telegram username(s) with admin access (required, no `@`). Accepts a single string or a YAML list of usernames.
119
119
  - `chat_model`: LLM model for conversation (e.g. `gpt-4o-mini` or `claude-sonnet-4-6`)
120
120
  - `url_model`: LLM model for URL analysis (e.g. `gpt-4o` or `claude-haiku-4-5`)
121
- - `telegram_api_key`: Telegram bot API key (required). Lookup order: (1) `TELLMGRAMBOT_TELEGRAM_API_KEY` env var, (2) `telegram_api_key` in `config.yaml`. Exits on placeholder, missing, or malformed key.
121
+ - `telegram_api_key`: Telegram bot API key (required). Lookup order: (1) `telegram_api_key` in `config.yaml`, (2) `TELLMGRAMBOT_TELEGRAM_API_KEY` env var. Config wins when explicitly set. Exits on placeholder, missing, or malformed key.
122
122
  - `bot_nickname` / `bot_initials`: Names the bot responds to in groups
123
123
  - `instance_name`: Optional label for console prefix, log filename, and database name (e.g. `MyBot` produces `[MyBot] INFO: ...` on console, `MyBot_{timestamp}.log` logs, and `MyBot.db` database); omit to use bot's Telegram username for logging and `conversations.db` for database. Use distinct names when running multiple bot instances in the same directory.
124
124
  - `token_limit`: Max tokens (optional; defaults to model's maximum)
@@ -271,19 +271,22 @@ def _model_provider(model: str) -> str | None:
271
271
  def _load_telegram_key(config: dict):
272
272
  """
273
273
  Load and validate the Telegram API key into TELLMGRAMBOT_TELEGRAM_API_KEY.
274
- Lookup order: (1) TELLMGRAMBOT_TELEGRAM_API_KEY env var, (2) bot config
275
- telegram_api_key. Exits on placeholder, missing, or malformed key.
274
+ Lookup order: (1) bot config telegram_api_key, (2) TELLMGRAMBOT_TELEGRAM_API_KEY
275
+ env var. Config wins when explicitly set so each bot instance uses its own key
276
+ rather than being silently overridden by a global env var. Exits if the key is
277
+ missing, malformed, or still unresolved because the config value is a placeholder
278
+ and no env var fallback is set.
276
279
 
277
280
  Args:
278
281
  config: Parsed bot configuration dict from init_bot_config().
279
282
  """
280
283
  env_var = 'TELLMGRAMBOT_TELEGRAM_API_KEY'
281
- if not os.environ.get(env_var):
282
- config_val = (config.get('telegram_api_key') or '').strip()
283
- is_placeholder = config_val.startswith('<') and config_val.endswith('>')
284
- if config_val and not is_placeholder:
285
- os.environ[env_var] = config_val
286
- elif is_placeholder:
284
+ config_val = (config.get('telegram_api_key') or '').strip()
285
+ is_placeholder = config_val.startswith('<') and config_val.endswith('>')
286
+ if config_val and not is_placeholder:
287
+ os.environ[env_var] = config_val
288
+ elif not os.environ.get(env_var):
289
+ if is_placeholder:
287
290
  sys.exit("telegram_api_key in bot config is still a placeholder. Replace it with your Telegram bot API key. Exiting...")
288
291
  else:
289
292
  sys.exit(
@@ -416,7 +419,7 @@ def init_bot_config(file: str = 'config.yaml') -> dict:
416
419
  for parameter, value in INIT_BOT_CONFIG.items():
417
420
  if parameter != 'persona_prompt' and parameter not in config:
418
421
  config[parameter] = value
419
- if value is not None:
422
+ if value is not None and parameter != 'telegram_api_key':
420
423
  logger.warning(f"Configuration '{parameter}' not defined, set to '{value}'")
421
424
  return config
422
425
  except KeyError:
@@ -203,8 +203,8 @@ async def discover_mcp_tools(
203
203
  """
204
204
  Discover tools from MCP server(s) and return them ready to merge into the registry.
205
205
 
206
- For each entry with an 'mcp_server:' key, calls POST /tools/list to fetch the
207
- server's tool list, translates MCP inputSchema to provider-compatible parameters,
206
+ For each entry with an 'mcp_server:' key, sends a JSON-RPC 2.0 tools/list request
207
+ to the server base URL, translates MCP inputSchema to provider-compatible parameters,
208
208
  and returns (schemas, defs) for the discovered tools.
209
209
 
210
210
  Headers support $ENV_VAR expansion. Missing env vars disable the MCP source with a
@@ -215,7 +215,7 @@ async def discover_mcp_tools(
215
215
  it registers all tools. Name collisions with existing_names (or with each other across
216
216
  MCP sources) are skipped with a warning; first-registered wins.
217
217
 
218
- SSRF guard applies to the tools/list call: loopback and link-local addresses are blocked
218
+ SSRF guard applies to the discovery call: loopback and link-local addresses are blocked
219
219
  unless allow_local is True.
220
220
 
221
221
  Args:
@@ -287,16 +287,25 @@ async def discover_mcp_tools(
287
287
  continue
288
288
  include_set = set(include_filter)
289
289
 
290
- list_url = f"{server_url}/tools/list"
291
290
  try:
292
291
  async with httpx.AsyncClient(timeout=15.0) as client:
293
- resp = await client.post(list_url, headers=expanded_headers)
292
+ resp = await client.post(
293
+ server_url,
294
+ json={"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}},
295
+ headers=expanded_headers,
296
+ )
294
297
  if not (200 <= resp.status_code < 300):
295
298
  logger.warning(
296
299
  f"MCP server '{log_url}': tools/list returned HTTP {resp.status_code}; skipping source."
297
300
  )
298
301
  continue
299
- tools_data = resp.json().get('tools', [])
302
+ resp_data = resp.json()
303
+ if resp_data.get('error'):
304
+ err = resp_data['error']
305
+ err_summary = f"code={err.get('code')} {err.get('message', '')}" if isinstance(err, dict) else str(err)[:100]
306
+ logger.warning(f"MCP server '{log_url}': tools/list error {err_summary}; skipping source.")
307
+ continue
308
+ tools_data = resp_data.get('result', {}).get('tools', [])
300
309
  except httpx.TimeoutException:
301
310
  logger.warning(f"MCP server '{log_url}': tools/list timed out; skipping source.")
302
311
  continue
@@ -358,8 +367,8 @@ async def execute_mcp(tool_def: dict, arguments: dict) -> str:
358
367
  """
359
368
  Execute an MCP tool call and return a framed result string for LLM injection.
360
369
 
361
- Posts to {mcp_server}/tools/call with the tool name and arguments dict, parses
362
- the MCP content array from the response, and frames the result for LLM injection.
370
+ Sends a JSON-RPC 2.0 tools/call request to the server base URL, parses the MCP
371
+ content array from the result field, and frames the result for LLM injection.
363
372
 
364
373
  Applies the same SSRF guard as execute_webhook(). Request headers are never
365
374
  logged at any level. Response bodies are logged at DEBUG only, truncated to 200
@@ -390,15 +399,15 @@ async def execute_mcp(tool_def: dict, arguments: dict) -> str:
390
399
  f"Set allow_local_webhooks: true in bot config to permit local addresses.]"
391
400
  )
392
401
 
393
- call_url = f"{server_url}/tools/call"
394
- log_url = _safe_log_url(call_url)
402
+ log_url = _safe_log_url(server_url)
395
403
  logger.info(f"MCP '{name}': POST {log_url}")
396
404
 
397
405
  try:
398
406
  async with httpx.AsyncClient(timeout=15.0) as client:
399
407
  resp = await client.post(
400
- call_url,
401
- json={"name": name, "arguments": arguments},
408
+ server_url,
409
+ json={"jsonrpc": "2.0", "id": 1, "method": "tools/call",
410
+ "params": {"name": name, "arguments": arguments}},
402
411
  headers=headers,
403
412
  )
404
413
 
@@ -411,7 +420,12 @@ async def execute_mcp(tool_def: dict, arguments: dict) -> str:
411
420
 
412
421
  try:
413
422
  data = resp.json()
414
- content_items = data.get('content', [])
423
+ if data.get('error'):
424
+ err = data['error']
425
+ err_summary = f"code={err.get('code')} {err.get('message', '')}" if isinstance(err, dict) else str(err)[:100]
426
+ logger.warning(f"MCP '{name}': JSON-RPC error {err_summary}")
427
+ return f"[Tool error: '{name}' returned error: {err.get('message', err)}]"
428
+ content_items = data.get('result', {}).get('content', [])
415
429
  body = '\n'.join(
416
430
  item.get('text', '') for item in content_items
417
431
  if isinstance(item, dict) and item.get('type') == 'text'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TeLLMgramBot
3
- Version: 3.13.4
3
+ Version: 3.13.6
4
4
  Summary: LLM-powered Telegram bot (OpenAI + Anthropic)
5
5
  Home-page: https://github.com/Digital-Heresy/TeLLMgramBot
6
6
  Author: Digital Heresy
@@ -101,7 +101,7 @@ Override default directory locations by setting these environment variables (use
101
101
  If unset, all paths default to subdirectories of the execution directory (the directory containing your entry-point script).
102
102
 
103
103
  ## API Keys
104
- TeLLMgramBot supports four API keys. OpenAI, Anthropic, and VirusTotal keys load from environment variables or `.key` files. The Telegram key loads from its env var or the bot config field `telegram_api_key` (no `.key` file):
104
+ TeLLMgramBot supports four API keys. OpenAI, Anthropic, and VirusTotal keys load from environment variables or `.key` files. The Telegram key loads from the bot config field `telegram_api_key` or its env var (no `.key` file); config wins when explicitly set:
105
105
 
106
106
  | Key | Env Var | File/Config | When required |
107
107
  |-----|---------|-------------|---------------|
@@ -150,7 +150,7 @@ When the bot is triggered in a group and about to respond (not deferring to anot
150
150
  - `bot_owner`: Telegram username(s) with admin access (required, no `@`). Accepts a single string or a YAML list of usernames.
151
151
  - `chat_model`: LLM model for conversation (e.g. `gpt-4o-mini` or `claude-sonnet-4-6`)
152
152
  - `url_model`: LLM model for URL analysis (e.g. `gpt-4o` or `claude-haiku-4-5`)
153
- - `telegram_api_key`: Telegram bot API key (required). Lookup order: (1) `TELLMGRAMBOT_TELEGRAM_API_KEY` env var, (2) `telegram_api_key` in `config.yaml`. Exits on placeholder, missing, or malformed key.
153
+ - `telegram_api_key`: Telegram bot API key (required). Lookup order: (1) `telegram_api_key` in `config.yaml`, (2) `TELLMGRAMBOT_TELEGRAM_API_KEY` env var. Config wins when explicitly set. Exits on placeholder, missing, or malformed key.
154
154
  - `bot_nickname` / `bot_initials`: Names the bot responds to in groups
155
155
  - `instance_name`: Optional label for console prefix, log filename, and database name (e.g. `MyBot` produces `[MyBot] INFO: ...` on console, `MyBot_{timestamp}.log` logs, and `MyBot.db` database); omit to use bot's Telegram username for logging and `conversations.db` for database. Use distinct names when running multiple bot instances in the same directory.
156
156
  - `token_limit`: Max tokens (optional; defaults to model's maximum)
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name='TeLLMgramBot',
8
- version='3.13.4',
8
+ version='3.13.6',
9
9
  packages=find_packages(),
10
10
  license='MIT',
11
11
  author='Digital Heresy',
File without changes
File without changes