项目文件夹

文件
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

139 行
4.0 KiB
Python

"""Credential resolution for scheduled task delivery.
Resolves provider credentials from the integration store and environment
rather than requiring them to be stored in task params.
"""
from __future__ import annotations
import logging
import os
from typing import Any
logger = logging.getLogger(__name__)
try:
from keyring.errors import KeyringError as _KeyringError
except ImportError:
class _KeyringError(Exception): # type: ignore[no-redef]
"""Fallback when keyring is not installed."""
def resolve_telegram_credentials(task_params: dict[str, str]) -> dict[str, str]:
"""Resolve Telegram bot_token from task params, integration store, env, or keyring.
Priority: task.params > integration store > environment variable > system keyring.
"""
token = task_params.get("bot_token", "").strip()
if token:
return {"bot_token": token}
token = _get_integration_credential("telegram", "bot_token")
if token:
return {"bot_token": token}
try:
from config.llm_credentials import resolve_env_credential
token = resolve_env_credential("TELEGRAM_BOT_TOKEN").strip()
except (ImportError, _KeyringError) as exc:
logger.debug("Failed to resolve Telegram credentials from keyring: %s", exc)
token = os.getenv("TELEGRAM_BOT_TOKEN", "").strip()
return {"bot_token": token} if token else {}
def resolve_slack_credentials(task_params: dict[str, str]) -> dict[str, str]:
"""Resolve Slack credentials from task params, integration store, or env.
Priority: task.params > integration store > environment variable.
"""
webhook_url = task_params.get("webhook_url", "")
if webhook_url:
return {"webhook_url": webhook_url}
access_token = task_params.get("access_token", "")
if access_token:
return {"access_token": access_token}
webhook = _resolve_credentials(
{},
service="slack",
credential_key="webhook_url",
env_vars=("SLACK_WEBHOOK_URL",),
)
if webhook:
return webhook
return _resolve_credentials(
{},
service="slack",
credential_key="access_token",
env_vars=("SLACK_BOT_TOKEN", "SLACK_ACCESS_TOKEN"),
)
def resolve_discord_credentials(task_params: dict[str, str]) -> dict[str, str]:
"""Resolve Discord bot_token from task params, integration store, or env.
Priority: task.params > integration store > environment variable.
"""
return _resolve_credentials(
task_params,
service="discord",
credential_key="bot_token",
env_vars=("DISCORD_BOT_TOKEN",),
)
def _resolve_credentials(
task_params: dict[str, str],
*,
service: str,
credential_key: str,
env_vars: tuple[str, ...],
) -> dict[str, str]:
"""Resolve a single credential from task params, integration store, or env."""
value = task_params.get(credential_key, "")
if value:
return {credential_key: value}
value = _get_integration_credential(service, credential_key)
if value:
return {credential_key: value}
for env_var in env_vars:
value = os.getenv(env_var, "")
if value:
return {credential_key: value}
return {}
def _get_integration_credential(service: str, key: str) -> str:
"""Look up a credential from the integration store."""
try:
from integrations.catalog import resolve_effective_integrations
integrations = resolve_effective_integrations()
integration: dict[str, Any] = integrations.get(service, {})
if not isinstance(integration, dict):
return ""
config = integration.get("config", {})
if not isinstance(config, dict):
return ""
value = config.get(key, "")
return str(value) if value else ""
except Exception:
logger.debug("Failed to resolve %s credential from integration store", service)
return ""
__all__ = [
"resolve_discord_credentials",
"resolve_slack_credentials",
"resolve_telegram_credentials",
]