"""Standard-library bounded job client. Caller owns the credential and budget."""
import json,time,urllib.request

def run_job(token,job,idempotency_key,origin='https://sandbox.agnt.gg'):
    if not token or not idempotency_key or type(job.get('maxChargeMicroUSD')) is not int:
        raise ValueError('Explicit credential, idempotency key and spending cap required')
    def request(path,body=None):
        headers={'Authorization':'Bearer '+token,'Content-Type':'application/json'}
        if body is not None:headers['Idempotency-Key']=idempotency_key
        request=urllib.request.Request(origin+'/sandbox/v1'+path,headers=headers,data=json.dumps(body).encode() if body is not None else None)
        with urllib.request.urlopen(request,timeout=20) as response:return json.load(response)
    submitted=request('/jobs',job);result=submitted;deadline=time.monotonic()+1200
    while result['state'] not in ('completed','failed','cancelled'):
        if time.monotonic()>deadline:raise TimeoutError('Resume polling job '+submitted['id'])
        time.sleep(2);result=request('/jobs/'+submitted['id'])
    if result['state']!='completed' or result.get('execution',{}).get('exit_code')!=0 or result.get('cleanupStatus')!='destroyed':
        raise RuntimeError('Job did not complete successfully: '+json.dumps(result))
    return result
