local HttpClient = require("httpclient") local json = require("dkjson") local os = require 'os' local GymClient = {} local m = {} function m.new(remote_base) local self = {} self.remote_base = remote_base self.http = HttpClient.new() setmetatable(self, {__index = GymClient}) return self end function GymClient:parse_server_error_or_raise_for_status(resp) local resp_data, pos, err = {} if resp.err then err = resp.err -- print('Response error: ' .. err) else if resp.code ~= 200 then err = resp.status_line -- Descriptive message from the server side -- print('Response: ' .. err) end resp_data, pos, err = json.decode(resp.body) end return resp_data, pos, err end function GymClient:get_request(route) url = self.remote_base .. route options = {} options.content_type = 'application/json' resp = self.http:get(url, options) return self:parse_server_error_or_raise_for_status(resp) end function GymClient:post_request(route, req_data) url = self.remote_base .. route options = {} options.content_type = 'application/json' json_str = json.encode(req_data) resp = self.http:post(url, json_str, options) return self:parse_server_error_or_raise_for_status(resp) end function GymClient:env_create(env_id) route = '/v1/envs/' req_data = {env_id = env_id} resp_data = self:post_request(route, req_data) return resp_data['instance_id'] end function GymClient:env_list_all() route = '/v1/envs/' resp_data = self:get_request(route) return resp_data['all_envs'] end function GymClient:env_reset(instance_id) route = '/v1/envs/'..instance_id..'/reset/' resp_data = self:post_request(route, '') return resp_data['observation'] end function GymClient:env_step(instance_id, action, render, video_callable) render = render or false video_callable = video_callable or false route = '/v1/envs/'..instance_id..'/step/' req_data = {action = action, render = render, video_callable = video_callable} resp_data = self:post_request(route, req_data) obs = resp_data['observation'] reward = resp_data['reward'] done = resp_data['done'] info = resp_data['info'] return obs, reward, done, info end function GymClient:env_action_space_info(instance_id) route = '/v1/envs/'..instance_id..'/action_space/' resp_data = self:get_request(route) return resp_data['info'] end function GymClient:env_action_space_sample(instance_id) route = '/v1/envs/'..instance_id..'/action_space/sample' resp_data = self:get_request(route) action = resp_data['action'] return action end function GymClient:env_action_space_contains(instance_id) route = '/v1/envs/'..instance_id..'/action_space/contains' resp_data = self:get_request(route) member = resp['member'] return member end function GymClient:env_observation_space_info(instance_id) route = '/v1/envs/'..instance_id..'/observation_space/' resp_data = self:get_request(route) return resp_data['info'] end function GymClient:env_monitor_start(instance_id, directory, force, resume, video_callable) if not force then force = false end if not resume then resume = false end req_data = {directory = directory, force = tostring(force), resume = tostring(resume), video_callable = video_callable} route = '/v1/envs/'..instance_id..'/monitor/start/' resp_data = self:post_request(route, req_data) end function GymClient:env_monitor_close(instance_id) route = '/v1/envs/'..instance_id..'/monitor/close/' resp_data = self:post_request(route, '') end function GymClient:upload(training_dir, algorithm_id, api_key) if not api_key then api_key = os.getenv('OPENAI_GYM_API_KEY') end if not algorithm_id then algorithm_id = '' end req_data = {training_dir = training_dir, algorithm_id = algorithm_id, api_key = api_key} route = '/v1/upload/' resp = self:post_request(route, req_data) return resp end function GymClient:shutdown_server() route = '/v1/shutdown/' self:post_request(route, '') end return m