Skip to content

Commit 04955e9

Browse files
committed
add qq gateway
1 parent 5d77fbd commit 04955e9

1 file changed

Lines changed: 35 additions & 14 deletions

File tree

  • src/agentscope_runtime/engine/app/gateways

src/agentscope_runtime/engine/app/gateways/qq.py

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,15 @@
4747
QUICK_DISCONNECT_THRESHOLD = 5
4848
MAX_QUICK_DISCONNECT_COUNT = 3
4949

50-
API_BASE = "https://api.sgroup.qq.com"
50+
DEFAULT_API_BASE = "https://api.sgroup.qq.com"
5151
TOKEN_URL = "https://bots.qq.com/app/getAppAccessToken"
5252

53+
54+
def _get_api_base() -> str:
55+
"""API 根地址,可通过 QQ_API_BASE 覆盖(如沙箱: https://sandbox.api.sgroup.qq.com)。"""
56+
return os.getenv("QQ_API_BASE", DEFAULT_API_BASE).rstrip("/")
57+
58+
5359
_token_cache: Optional[Dict[str, Any]] = None
5460
_token_lock = threading.Lock()
5561

@@ -81,6 +87,8 @@ def _get_access_token_sync(app_id: str, client_secret: str) -> str:
8187
if not token:
8288
raise RuntimeError(f"No access_token in response: {data}")
8389
expires_in = data.get("expires_in", 7200)
90+
if isinstance(expires_in, str):
91+
expires_in = int(expires_in)
8492
with _token_lock:
8593
_token_cache = {
8694
"token": token,
@@ -96,20 +104,31 @@ def clear_token_cache() -> None:
96104

97105

98106
def _get_gateway_url_sync(access_token: str) -> str:
99-
try:
100-
import urllib.request
107+
import urllib.error
108+
import urllib.request
101109

102-
url = f"{API_BASE}/gateway"
103-
req = urllib.request.Request(
104-
url,
105-
headers={
106-
"Authorization": f"QQBot {access_token}",
107-
"Content-Type": "application/json",
108-
},
109-
method="GET",
110-
)
110+
url = f"{_get_api_base()}/gateway"
111+
req = urllib.request.Request(
112+
url,
113+
headers={
114+
"Authorization": f"QQBot {access_token}",
115+
"Content-Type": "application/json",
116+
},
117+
method="GET",
118+
)
119+
try:
111120
with urllib.request.urlopen(req, timeout=15) as resp:
112121
data = json.loads(resp.read().decode())
122+
except urllib.error.HTTPError as e:
123+
body = ""
124+
try:
125+
body = e.read().decode() if e.fp else ""
126+
except Exception:
127+
pass
128+
msg = f"HTTP {e.code}: {e.reason}"
129+
if body:
130+
msg += f" | body: {body[:500]}"
131+
raise RuntimeError(f"Failed to get gateway url: {msg}") from e
113132
except Exception as e:
114133
raise RuntimeError(f"Failed to get gateway url: {e}") from e
115134
gateway_url = data.get("url")
@@ -126,7 +145,7 @@ def _api_request_sync(
126145
) -> Dict[str, Any]:
127146
import urllib.request
128147

129-
url = f"{API_BASE}{path}"
148+
url = f"{_get_api_base()}{path}"
130149
data = None
131150
if body is not None:
132151
data = json.dumps(body).encode()
@@ -179,6 +198,8 @@ async def _get_access_token_async(app_id: str, client_secret: str) -> str:
179198
if not token:
180199
raise RuntimeError(f"No access_token: {data}")
181200
expires_in = data.get("expires_in", 7200)
201+
if isinstance(expires_in, str):
202+
expires_in = int(expires_in)
182203
with _token_lock:
183204
_token_cache = {
184205
"token": token,
@@ -193,7 +214,7 @@ async def _api_request_async(
193214
path: str,
194215
body: Optional[Dict[str, Any]] = None,
195216
) -> Dict[str, Any]:
196-
url = f"{API_BASE}{path}"
217+
url = f"{_get_api_base()}{path}"
197218
async with aiohttp.ClientSession() as session:
198219
kwargs = {
199220
"headers": {

0 commit comments

Comments
 (0)