forked from luopingyi/xc_agent_platform_demo
Phase2 dry-run: pending A, probe, build-config client, gated task/add
Still default dry-run; ALLOW_LIVE_SUBMIT=0. Live gates closed.
This commit is contained in:
60
src/build_config_client.py
Normal file
60
src/build_config_client.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user