2026-02-02 16:05:18 +05:30
|
|
|
from __future__ import annotations
|
|
|
|
|
|
2026-02-02 20:51:08 +05:30
|
|
|
import logging
|
2026-02-02 16:05:18 +05:30
|
|
|
import os
|
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
2026-02-02 20:51:08 +05:30
|
|
|
logger = logging.getLogger("app.openclaw")
|
|
|
|
|
|
2026-02-02 16:05:18 +05:30
|
|
|
|
|
|
|
|
class OpenClawClient:
|
|
|
|
|
def __init__(self, base_url: str, token: str):
|
|
|
|
|
self.base_url = base_url.rstrip("/")
|
|
|
|
|
self.token = token
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def from_env(cls) -> "OpenClawClient | None":
|
|
|
|
|
url = os.environ.get("OPENCLAW_GATEWAY_URL")
|
|
|
|
|
token = os.environ.get("OPENCLAW_GATEWAY_TOKEN")
|
|
|
|
|
if not url or not token:
|
|
|
|
|
return None
|
|
|
|
|
return cls(url, token)
|
|
|
|
|
|
2026-02-02 20:15:38 +05:30
|
|
|
def tools_invoke(
|
|
|
|
|
self,
|
|
|
|
|
tool: str,
|
|
|
|
|
args: dict[str, Any],
|
|
|
|
|
*,
|
|
|
|
|
session_key: str | None = None,
|
|
|
|
|
timeout_s: float = 5.0,
|
|
|
|
|
) -> dict[str, Any]:
|
2026-02-02 16:05:18 +05:30
|
|
|
payload: dict[str, Any] = {"tool": tool, "args": args}
|
2026-02-02 20:51:08 +05:30
|
|
|
logger.info(
|
|
|
|
|
"openclaw.tools_invoke", extra={"tool": tool, "has_session_key": bool(session_key)}
|
|
|
|
|
)
|
2026-02-02 16:05:18 +05:30
|
|
|
if session_key is not None:
|
|
|
|
|
payload["sessionKey"] = session_key
|
|
|
|
|
|
|
|
|
|
r = requests.post(
|
|
|
|
|
f"{self.base_url}/tools/invoke",
|
|
|
|
|
headers={"Authorization": f"Bearer {self.token}", "Content-Type": "application/json"},
|
|
|
|
|
json=payload,
|
|
|
|
|
timeout=timeout_s,
|
|
|
|
|
)
|
|
|
|
|
r.raise_for_status()
|
2026-02-02 20:51:08 +05:30
|
|
|
logger.info("openclaw.tools_invoke: ok", extra={"tool": tool, "status": r.status_code})
|
2026-02-02 16:05:18 +05:30
|
|
|
return r.json()
|