Files
xc_agent_platform_demo/src/build_config_client.py

61 lines
2.7 KiB
Python
Raw Normal View History

"""Explicit configuration generation; import performs no I/O.
Returns YAML on success, otherwise raises BuildConfigError with safe attribution
and HTTP/platform status. Server messages and transport details are never exposed.
"""
import json
import os
import urllib.error
import urllib.parse
import urllib.request
from src.task_add_client import resolve_token
class BuildConfigError(RuntimeError):
def __init__(self, reason, http_status=None, platform_code=None):
self.error_attribution = reason
self.http_status = http_status
self.platform_code = platform_code
super().__init__('build-config: ' + reason)
def build_config(gpu_type, framework='vllm', task_type='text-generation'):
try:
token = resolve_token()
except (ValueError, OSError):
raise BuildConfigError('missing/invalid credential') from None
if not isinstance(gpu_type, str) or not gpu_type.strip() or '<' in gpu_type:
raise BuildConfigError('gpu_type required (platform enum)')
query = urllib.parse.urlencode(dict(gpuType=gpu_type, framework=framework, taskType=task_type))
header = 'Authorization' if os.environ.get('BUILD_CONFIG_USE_AUTHORIZATION') == '1' else 'Xc-Token'
try:
request = urllib.request.Request(
os.environ.get('MODELHUB_API_BASE', 'https://www.modelhub.org.cn').rstrip('/')
+ '/api/adapt/task/build-config?' + query,
headers={header: token, 'Accept': 'application/json'}, method='POST')
with urllib.request.urlopen(request, timeout=30) as response:
status, raw = response.status, response.read()
except urllib.error.HTTPError as error:
status, raw = error.code, error.read()
except (OSError, urllib.error.URLError, ValueError):
raise BuildConfigError('transport/timeout') from None
try:
body = json.loads(raw)
except (ValueError, UnicodeError):
raise BuildConfigError('invalid JSON response', status) from None
if not isinstance(body, dict):
raise BuildConfigError('invalid response object', status)
code = body.get('code')
# Only numeric codes are retained; arbitrary server strings may echo secrets.
code = code if type(code) is int else None
if code in (40100, 40101):
raise BuildConfigError({40100: '40100 NOT_LOGIN_ERROR', 40101: '40101 NO_AUTH_ERROR'}[code], status, code)
if not 200 <= status < 300 or code != 0:
raise BuildConfigError('other HTTP/platform code', status, code)
data = body.get('data')
if not isinstance(data, str) or not data.strip():
raise BuildConfigError('empty/non-str data', status, code)
if token in data:
raise BuildConfigError('credential echoed in data', status, code)
return data