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.
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/PKG-INFO +3 -3
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/README.md +2 -2
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/initialize.py +12 -9
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/tools.py +27 -13
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/PKG-INFO +3 -3
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/setup.py +1 -1
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/LICENSE +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/TeLLMgramBot.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/__init__.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/archive.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/conversation.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/database.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/message_handlers.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/models.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/__init__.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/anthropic_provider.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/base.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/factory.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/providers/openai_provider.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/utils.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot/web_utils.py +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/SOURCES.txt +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/dependency_links.txt +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/requires.txt +0 -0
- {tellmgrambot-3.13.4 → tellmgrambot-3.13.6}/TeLLMgramBot.egg-info/top_level.txt +0 -0
- {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.
|
|
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
|
|
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) `
|
|
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
|
|
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) `
|
|
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)
|
|
275
|
-
|
|
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
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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,
|
|
207
|
-
server
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
362
|
-
|
|
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
|
-
|
|
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
|
-
|
|
401
|
-
json={"
|
|
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
|
-
|
|
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.
|
|
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
|
|
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) `
|
|
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)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|