MCPcopy Create free account
hub / github.com/CodeClash-ai/CodeClash / PolicyController

Class PolicyController

codeclash/arenas/scml/runtime/run_scml.py:223–321  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

221
222
223class PolicyController:
224 def __init__(self, player_name: str, path: str, *, timeout: float, max_errors: int):
225 self.player_name = player_name
226 self.path = path
227 self.timeout = max(float(timeout), 0.01)
228 self.max_errors = max(int(max_errors), 1)
229 self.disabled = False
230 self.decisions = 0
231 self.policy_errors = 0
232 self.invalid_decisions = 0
233 self.error_samples: list[dict[str, str]] = []
234 self.startup_error: str | None = None
235 self._next_request_id = 0
236 self._start_worker()
237
238 def _start_worker(self) -> None:
239 self.startup_error = None
240 ctx = mp.get_context("spawn")
241 self.command_queue = ctx.Queue()
242 self.result_queue = ctx.Queue()
243 self.startup_queue = ctx.Queue()
244 self.process = ctx.Process(
245 target=policy_worker,
246 args=(self.command_queue, self.result_queue, self.startup_queue, self.player_name, self.path),
247 )
248 self.process.start()
249 startup_timeout = max(self.timeout, 10.0)
250 try:
251 startup_message = self.startup_queue.get(timeout=startup_timeout)
252 except queue.Empty:
253 self.startup_error = f"policy import exceeded {startup_timeout}s timeout"
254 self.close()
255 return
256 if "error" in startup_message:
257 self.startup_error = startup_message["error"]
258 self.close()
259
260 def _record_error(self, event: str, error: str, *, invalid: bool = False) -> None:
261 self.policy_errors += 1
262 if invalid:
263 self.invalid_decisions += 1
264 if len(self.error_samples) < 5:
265 self.error_samples.append({"event": event, "error": error})
266 if self.policy_errors >= self.max_errors:
267 self.disabled = True
268 self.close()
269
270 def close(self) -> None:
271 with contextlib.suppress(Exception):
272 self.command_queue.put_nowait(None)
273 self.process.join(0.1)
274 if self.process.is_alive():
275 self.process.terminate()
276 self.process.join(0.1)
277 if self.process.is_alive():
278 self.process.kill()
279 self.process.join()
280

Callers 1

initMethod · 0.70

Calls

no outgoing calls

Tested by

no test coverage detected