Skip to content

Commit 8595216

Browse files
authored
feat: add request source header X-Custom-Request-Context (#32)
2 parents 8b1aac4 + a9adcb4 commit 8595216

File tree

3 files changed

+79
-5
lines changed

3 files changed

+79
-5
lines changed

agentkit/client/base_service_client.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
from volcengine.Credentials import Credentials
2727
from volcengine.ServiceInfo import ServiceInfo
2828

29-
from agentkit.utils.ve_sign import get_volc_ak_sk_region
29+
from agentkit.utils.ve_sign import (
30+
get_volc_ak_sk_region,
31+
ensure_x_custom_source_header,
32+
)
3033

3134
T = TypeVar("T")
3235

@@ -73,7 +76,7 @@ def __init__(
7376
session_token: str = "",
7477
service_name: str = "",
7578
credential_env_prefix: str = "",
76-
header: Optional[Dict[str, Any]] = {"Accept": "application/json"},
79+
header: Optional[Dict[str, Any]] = None,
7780
) -> None:
7881
"""
7982
Initialize the service client.
@@ -105,6 +108,15 @@ def __init__(
105108
self.session_token = session_token
106109
self.service_name = service_name
107110

111+
if header is None:
112+
effective_header: Dict[str, Any] = {"Accept": "application/json"}
113+
else:
114+
effective_header = header.copy()
115+
if "Accept" not in effective_header:
116+
effective_header = {"Accept": "application/json", **effective_header}
117+
118+
effective_header = ensure_x_custom_source_header(effective_header)
119+
108120
# Get service-specific configuration from subclass
109121
config = self._get_service_config()
110122
self.host = config["host"]
@@ -115,7 +127,7 @@ def __init__(
115127
# Create ServiceInfo
116128
self.service_info = ServiceInfo(
117129
host=self.host,
118-
header=header,
130+
header=effective_header,
119131
credentials=Credentials(
120132
ak=self.access_key,
121133
sk=self.secret_key,

agentkit/toolkit/cli/cli.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
"""AgentKit CLI - Main entry point for AgentKit Starter Toolkit."""
1616

17+
import os
18+
1719
import typer
1820
from rich.panel import Panel
1921
from rich.console import Console
@@ -77,6 +79,7 @@ def main(
7779
),
7880
):
7981
"""AgentKit CLI - Deploy AI agents with ease."""
82+
os.environ.setdefault("AGENTKIT_CLIENT_TYPE", "cli")
8083
# If no subcommand is provided, show logo
8184
if ctx.invoked_subcommand is None:
8285
show_logo()

agentkit/utils/ve_sign.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import hashlib
1717
import hmac
1818
import os
19+
import platform
1920
import requests
2021
from urllib.parse import quote
2122
from agentkit.utils.global_config_io import get_global_config_str
@@ -29,6 +30,63 @@
2930
Scheme = "https"
3031

3132

33+
MAX_X_CUSTOM_SOURCE_LENGTH = 256
34+
35+
36+
def _get_os_tag() -> str:
37+
system = platform.system().lower()
38+
if "linux" in system:
39+
return "linux"
40+
if "windows" in system:
41+
return "windows"
42+
if "darwin" in system or "mac" in system:
43+
return "macos"
44+
return "unknown"
45+
46+
47+
def _get_entry() -> str:
48+
value = os.getenv("AGENTKIT_CLIENT_TYPE", "").strip().lower()
49+
if value in ("cli", "sdk"):
50+
return value
51+
return "sdk"
52+
53+
54+
def _get_sdk_version() -> str:
55+
try:
56+
from agentkit.version import VERSION
57+
58+
if VERSION:
59+
return VERSION
60+
except Exception:
61+
pass
62+
return "unknown"
63+
64+
65+
def build_x_custom_source_header() -> str:
66+
sdk_name = "agentkit-sdk-python"
67+
version = _get_sdk_version()
68+
entry = _get_entry()
69+
os_tag = _get_os_tag()
70+
product = f"{sdk_name}/{version}"
71+
parts = ["schema=v1", f"entry={entry}", f"os={os_tag}"]
72+
inner = "; ".join(parts)
73+
value = product
74+
if inner:
75+
value = f"{product} ({inner})"
76+
if len(value) <= MAX_X_CUSTOM_SOURCE_LENGTH:
77+
return value
78+
if len(product) <= MAX_X_CUSTOM_SOURCE_LENGTH:
79+
return product
80+
return value[:MAX_X_CUSTOM_SOURCE_LENGTH]
81+
82+
83+
def ensure_x_custom_source_header(header: dict | None) -> dict:
84+
base = header.copy() if header is not None else {}
85+
if "X-Custom-Request-Context" not in base:
86+
base["X-Custom-Request-Context"] = build_x_custom_source_header()
87+
return base
88+
89+
3290
def norm_query(params):
3391
query = ""
3492
for key in sorted(params.keys()):
@@ -146,6 +204,7 @@ def request(method, date, query, header, ak, sk, action, body):
146204
signature,
147205
)
148206
)
207+
header = ensure_x_custom_source_header(header)
149208
header = {**header, **sign_result}
150209
# header = {**header, **{"X-Security-Token": SessionToken}}
151210
# 第六步:将 Signature 签名写入 HTTP Header 中,并发送 HTTP 请求。
@@ -168,7 +227,7 @@ def ve_request(
168227
version: str,
169228
region: str,
170229
host: str,
171-
header: dict = {},
230+
header: dict | None = None,
172231
content_type: str = "application/json",
173232
scheme: str = "https",
174233
):
@@ -199,7 +258,7 @@ def ve_request(
199258

200259
try:
201260
response_body = request(
202-
"POST", now, {}, header, AK, SK, action, json.dumps(request_body)
261+
"POST", now, {}, header or {}, AK, SK, action, json.dumps(request_body)
203262
)
204263
check_error(response_body)
205264
return response_body

0 commit comments

Comments
 (0)