Spaces:
Sleeping
Sleeping
Prasham.Jain
feat(branch-a): A2 tool implementations — route 11 handlers to scenario.tool_outputs with cost charging
272a052 | """Shared helpers for Phase A2 tool implementations. | |
| - ``deterministic_rng(seed, step, tool_name)``: reproducible RNG seeded from the | |
| episode seed, the step index, and the tool name. Use in any handler that | |
| needs randomness (e.g. log line shuffling) so the same episode always | |
| produces the same outputs. | |
| - ``args_hash(args)``: short stable hash of an args dict, useful for keying | |
| tool-call repeats (the redundancy-penalty in the reward layer interprets | |
| identical hashes as the same call). | |
| - ``SchemaValidatedHandler``: ``ToolHandler`` mixin that validates ``args`` via | |
| ``jsonschema`` against the frozen ``MCPToolDef.args_schema`` from | |
| ``schemas/tools.py``. Concrete handlers implement ``call``. | |
| """ | |
| from __future__ import annotations | |
| import hashlib | |
| import json | |
| import random | |
| from typing import ClassVar | |
| import jsonschema | |
| from ci_triage_env.env.tools.base import ToolHandler | |
| from ci_triage_env.schemas.tools import ALL_TOOLS | |
| _TOOL_DEFS = {t.name: t for t in ALL_TOOLS} | |
| def deterministic_rng(seed: int, step: int, tool_name: str) -> random.Random: | |
| h = hashlib.sha256(f"{seed}:{step}:{tool_name}".encode()).digest() | |
| return random.Random(int.from_bytes(h[:8], "big")) | |
| def args_hash(args: dict) -> str: | |
| return hashlib.sha1( | |
| json.dumps(args or {}, sort_keys=True, default=str).encode() | |
| ).hexdigest()[:12] | |
| class SchemaValidatedHandler(ToolHandler): | |
| """Concrete-handler base that validates args against the MCP schema.""" | |
| name: ClassVar[str] = "" | |
| cost_unit: ClassVar[float] = 0.0 | |
| def validate_args(self, args: dict) -> None: | |
| spec = _TOOL_DEFS.get(self.name) | |
| if spec is None: | |
| raise ValueError(f"unknown tool: {self.name}") | |
| try: | |
| jsonschema.validate(instance=args or {}, schema=spec.args_schema) | |
| except jsonschema.ValidationError as exc: | |
| raise ValueError(f"invalid args for {self.name}: {exc.message}") from exc | |