evalsi-harness 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. evalsi_harness-0.1.0/.gitignore +30 -0
  2. evalsi_harness-0.1.0/PKG-INFO +41 -0
  3. evalsi_harness-0.1.0/README.md +26 -0
  4. evalsi_harness-0.1.0/pyproject.toml +34 -0
  5. evalsi_harness-0.1.0/src/evalsi_harness/__init__.py +39 -0
  6. evalsi_harness-0.1.0/src/evalsi_harness/_version.py +1 -0
  7. evalsi_harness-0.1.0/src/evalsi_harness/benchmarks/__init__.py +1 -0
  8. evalsi_harness-0.1.0/src/evalsi_harness/benchmarks/fixtures.py +111 -0
  9. evalsi_harness-0.1.0/src/evalsi_harness/benchmarks/harbor.py +698 -0
  10. evalsi_harness-0.1.0/src/evalsi_harness/cassette.py +181 -0
  11. evalsi_harness-0.1.0/src/evalsi_harness/checker.py +122 -0
  12. evalsi_harness-0.1.0/src/evalsi_harness/connectors.py +565 -0
  13. evalsi_harness-0.1.0/src/evalsi_harness/environment.py +225 -0
  14. evalsi_harness-0.1.0/src/evalsi_harness/events.py +61 -0
  15. evalsi_harness-0.1.0/src/evalsi_harness/formats.py +188 -0
  16. evalsi_harness-0.1.0/src/evalsi_harness/gym.py +190 -0
  17. evalsi_harness-0.1.0/src/evalsi_harness/harness.py +468 -0
  18. evalsi_harness-0.1.0/src/evalsi_harness/loop.py +237 -0
  19. evalsi_harness-0.1.0/src/evalsi_harness/mcp.py +232 -0
  20. evalsi_harness-0.1.0/src/evalsi_harness/models.py +282 -0
  21. evalsi_harness-0.1.0/src/evalsi_harness/otel.py +165 -0
  22. evalsi_harness-0.1.0/src/evalsi_harness/py.typed +0 -0
  23. evalsi_harness-0.1.0/src/evalsi_harness/runner.py +141 -0
  24. evalsi_harness-0.1.0/src/evalsi_harness/service.py +264 -0
  25. evalsi_harness-0.1.0/src/evalsi_harness/task.py +235 -0
  26. evalsi_harness-0.1.0/src/evalsi_harness/testing.py +293 -0
  27. evalsi_harness-0.1.0/src/evalsi_harness/tools.py +261 -0
  28. evalsi_harness-0.1.0/src/evalsi_harness/trust.py +64 -0
  29. evalsi_harness-0.1.0/src/evalsi_harness/user_sim.py +83 -0
  30. evalsi_harness-0.1.0/tests/__init__.py +0 -0
  31. evalsi_harness-0.1.0/tests/conftest.py +26 -0
  32. evalsi_harness-0.1.0/tests/fixtures/dsh-0.2.1-alpha.2-fix-calc.jsonl +11 -0
  33. evalsi_harness-0.1.0/tests/fixtures/dsh-0.2.1-alpha.2-no-credential.jsonl +6 -0
  34. evalsi_harness-0.1.0/tests/fixtures/dsh-0.2.1-alpha.2-tool-error.jsonl +11 -0
  35. evalsi_harness-0.1.0/tests/harness_support.py +59 -0
  36. evalsi_harness-0.1.0/tests/test_benchmarks_harbor.py +184 -0
  37. evalsi_harness-0.1.0/tests/test_formats.py +102 -0
  38. evalsi_harness-0.1.0/tests/test_gym.py +88 -0
  39. evalsi_harness-0.1.0/tests/test_harness_agent.py +484 -0
  40. evalsi_harness-0.1.0/tests/test_harness_connectors.py +264 -0
  41. evalsi_harness-0.1.0/tests/test_harness_parts.py +442 -0
  42. evalsi_harness-0.1.0/tests/test_harness_run.py +107 -0
@@ -0,0 +1,30 @@
1
+ # Go
2
+ /evalsid
3
+ /bin/
4
+ # `go build ./cmd/...` without -o drops a binary in the working directory
5
+ /evalsi-guest
6
+ /evalsi-operator
7
+ /evalsi-collector
8
+
9
+ # Python
10
+ __pycache__/
11
+ *.py[cod]
12
+ .venv/
13
+ *.egg-info/
14
+ dist/
15
+ build/
16
+ .mypy_cache/
17
+ .pytest_cache/
18
+ .ruff_cache/
19
+
20
+ # Editors and OS
21
+ .idea/
22
+ .vscode/
23
+ .DS_Store
24
+
25
+ # Server data directories (examples use .evalsi and .evalsi-auth-demo)
26
+ .evalsi*/
27
+ examples/demo/terminal-bench-2/
28
+ examples/demo/_local-*.yaml
29
+
30
+ node_modules/
@@ -0,0 +1,41 @@
1
+ Metadata-Version: 2.5
2
+ Name: evalsi-harness
3
+ Version: 0.1.0
4
+ Summary: The light built-in agent harness for Evals.si: tool loop, MCP tools, sandboxes, user simulator, record and replay.
5
+ Project-URL: Homepage, https://abhishek-rnjn.github.io/Evals.si/
6
+ Project-URL: Documentation, https://abhishek-rnjn.github.io/Evals.si/
7
+ Project-URL: Repository, https://github.com/Abhishek-Rnjn/Evals.si
8
+ Project-URL: Issues, https://github.com/Abhishek-Rnjn/Evals.si/issues
9
+ Project-URL: Changelog, https://github.com/Abhishek-Rnjn/Evals.si/blob/main/CHANGELOG.md
10
+ License-Expression: Apache-2.0
11
+ Requires-Python: >=3.11
12
+ Requires-Dist: evalsi[server]==0.1.0
13
+ Requires-Dist: httpx>=0.27
14
+ Description-Content-Type: text/markdown
15
+
16
+ # evalsi-harness
17
+
18
+ The light built-in agent harness for [Evals.si](https://github.com/Abhishek-Rnjn/Evals.si).
19
+ It drives an agent through a task in an Evals.si sandbox and grades the end state.
20
+
21
+ It runs either of these:
22
+ - the built-in tool-calling agent on any OpenAI-compatible or Anthropic model;
23
+ - a bring-your-own agent over A2A, MCP, OpenAI Responses or HTTP, or as a CLI run inside the sandbox.
24
+
25
+ ```bash
26
+ pip install evalsi-harness
27
+ evalsi run -f agent-run.yaml
28
+ ```
29
+
30
+ What it provides:
31
+ - **Sandbox tools:** `bash`, `read_file` and `write_file`, plus an escalation request the harness policy decides on.
32
+ - **Other tools:** MCP tools over streamable HTTP or stdio; mocked tools; deterministic fault injection.
33
+ - **Budgets:** steps, tokens, spend and wall-clock time.
34
+ - **Simulated user:** an LLM user for multi-turn tasks.
35
+ - **Record and replay:** model calls and tool I/O are captured, replay can branch from step N, and sandbox commands are re-executed so the environment is rebuilt.
36
+ - **Environment checkers:** exit code, JSON, JUnit or a Python function.
37
+ - **OTel spans:** every step becomes a span.
38
+ - **The agent's diff:** recorded for the `code-quality` evaluator when the workdir is a git repository.
39
+ - **Benchmark importers:** `harbor://` (Terminal-Bench 2 and other Harbor datasets) and `terminal-bench://` (Terminal-Bench 1) task directories, with their Dockerfiles translated into environments.
40
+
41
+ See [docs/guides/agent-runs.md](../../docs/guides/agent-runs.md).
@@ -0,0 +1,26 @@
1
+ # evalsi-harness
2
+
3
+ The light built-in agent harness for [Evals.si](https://github.com/Abhishek-Rnjn/Evals.si).
4
+ It drives an agent through a task in an Evals.si sandbox and grades the end state.
5
+
6
+ It runs either of these:
7
+ - the built-in tool-calling agent on any OpenAI-compatible or Anthropic model;
8
+ - a bring-your-own agent over A2A, MCP, OpenAI Responses or HTTP, or as a CLI run inside the sandbox.
9
+
10
+ ```bash
11
+ pip install evalsi-harness
12
+ evalsi run -f agent-run.yaml
13
+ ```
14
+
15
+ What it provides:
16
+ - **Sandbox tools:** `bash`, `read_file` and `write_file`, plus an escalation request the harness policy decides on.
17
+ - **Other tools:** MCP tools over streamable HTTP or stdio; mocked tools; deterministic fault injection.
18
+ - **Budgets:** steps, tokens, spend and wall-clock time.
19
+ - **Simulated user:** an LLM user for multi-turn tasks.
20
+ - **Record and replay:** model calls and tool I/O are captured, replay can branch from step N, and sandbox commands are re-executed so the environment is rebuilt.
21
+ - **Environment checkers:** exit code, JSON, JUnit or a Python function.
22
+ - **OTel spans:** every step becomes a span.
23
+ - **The agent's diff:** recorded for the `code-quality` evaluator when the workdir is a git repository.
24
+ - **Benchmark importers:** `harbor://` (Terminal-Bench 2 and other Harbor datasets) and `terminal-bench://` (Terminal-Bench 1) task directories, with their Dockerfiles translated into environments.
25
+
26
+ See [docs/guides/agent-runs.md](../../docs/guides/agent-runs.md).
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "evalsi-harness"
3
+ dynamic = ["version"]
4
+ description = "The light built-in agent harness for Evals.si: tool loop, MCP tools, sandboxes, user simulator, record and replay."
5
+ readme = "README.md"
6
+ license = "Apache-2.0"
7
+ requires-python = ">=3.11"
8
+ dependencies = [
9
+ # The harness speaks evalsi's protocol: the same release only. The
10
+ # release workflow sets this with the version.
11
+ "evalsi[server]==0.1.0",
12
+ "httpx>=0.27",
13
+ ]
14
+
15
+ [project.entry-points."evalsi.importers"]
16
+ harbor = "evalsi_harness.benchmarks.harbor:load_harbor"
17
+ terminal-bench = "evalsi_harness.benchmarks.harbor:load_terminal_bench"
18
+
19
+ [project.urls]
20
+ Homepage = "https://abhishek-rnjn.github.io/Evals.si/"
21
+ Documentation = "https://abhishek-rnjn.github.io/Evals.si/"
22
+ Repository = "https://github.com/Abhishek-Rnjn/Evals.si"
23
+ Issues = "https://github.com/Abhishek-Rnjn/Evals.si/issues"
24
+ Changelog = "https://github.com/Abhishek-Rnjn/Evals.si/blob/main/CHANGELOG.md"
25
+
26
+ [build-system]
27
+ requires = ["hatchling>=1.25"]
28
+ build-backend = "hatchling.build"
29
+
30
+ [tool.hatch.build.targets.wheel]
31
+ packages = ["src/evalsi_harness"]
32
+
33
+ [tool.hatch.version]
34
+ path = "src/evalsi_harness/_version.py"
@@ -0,0 +1,39 @@
1
+ """evalsi-harness: the light built-in agent harness for Evals.si (design §11).
2
+
3
+ It drives an agent through a task in an Evals.si sandbox: the built-in
4
+ tool-calling agent on any OpenAI-compatible or Anthropic model, or a
5
+ bring-your-own agent (A2A, MCP, OpenAI Responses, HTTP, or a CLI run in the
6
+ sandbox). It provides sandbox and MCP tools, budgets, a simulated user,
7
+ mocked and faulty tools, record and replay, sandbox policy events and OTel
8
+ spans, and grades the end state with the environment's checker.
9
+
10
+ Most users never import it: ``evalsi run`` and the server's worker call
11
+ :func:`run_task` for every record of an agent run.
12
+ """
13
+
14
+ from evalsi_harness._version import __version__
15
+ from evalsi_harness.events import FinalEvent, PolicyEvent, StepEvent
16
+ from evalsi_harness.harness import BuiltinHarness, Harness, HarnessContext, HarnessManifest
17
+ from evalsi_harness.runner import TaskOutcome, load_harness, run_task
18
+ from evalsi_harness.task import EnvironmentConfig, Task, TaskError
19
+ from evalsi_harness.tools import FunctionTool, Tool, ToolResult
20
+
21
+ __all__ = [
22
+ "BuiltinHarness",
23
+ "EnvironmentConfig",
24
+ "FinalEvent",
25
+ "FunctionTool",
26
+ "Harness",
27
+ "HarnessContext",
28
+ "HarnessManifest",
29
+ "PolicyEvent",
30
+ "StepEvent",
31
+ "Task",
32
+ "TaskError",
33
+ "TaskOutcome",
34
+ "Tool",
35
+ "ToolResult",
36
+ "__version__",
37
+ "load_harness",
38
+ "run_task",
39
+ ]
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ """Benchmark task formats as Evals.si agent tasks."""
@@ -0,0 +1,111 @@
1
+ """Tiny Harbor and Terminal-Bench 1 tasks, for tests and smoke runs: each
2
+ asks for /app/hello.txt on alpine:3.22, copies a binary file in, and grades
3
+ offline (no package installs), so they run in any sandbox that can pull the
4
+ image.
5
+
6
+ python -m evalsi_harness.benchmarks.fixtures <dir>
7
+
8
+ writes ``<dir>/harbor/hello`` and ``<dir>/terminal-bench/hello``.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from pathlib import Path
14
+
15
+ INSTRUCTION = 'Create a file called /app/hello.txt with "Hello, world!" as the content.'
16
+ BLOB = bytes(range(256)) * 4
17
+
18
+ DOCKERFILE = """\
19
+ FROM alpine:3.22
20
+ ARG GREETING_FILE=greeting.txt
21
+ ENV GREETING="Hello, world!"
22
+ WORKDIR /app
23
+ COPY blob.bin /opt/data/
24
+ RUN printf '%s' "$GREETING" > /opt/data/${GREETING_FILE} \\
25
+ && echo ready > state.txt
26
+ CMD ["sh"]
27
+ """
28
+
29
+ # Checks the agent's file, and that the image setup (ENV, ARG, RUN in the
30
+ # WORKDIR) and the binary copy came through intact.
31
+ CHECK = """\
32
+ test "$(cat /app/hello.txt)" = "$(cat /opt/data/greeting.txt)" && \\
33
+ test "$(cat /app/state.txt)" = ready && \\
34
+ cmp -s /opt/data/blob.bin /tests/blob.bin"""
35
+
36
+ TASK_TOML = """\
37
+ schema_version = "1.1"
38
+
39
+ [task]
40
+ name = "evalsi/hello"
41
+
42
+ [metadata]
43
+ difficulty = "easy"
44
+
45
+ [verifier]
46
+ timeout_sec = 60.0
47
+
48
+ [agent]
49
+ timeout_sec = 120.0
50
+
51
+ [environment]
52
+ network_mode = "no-network"
53
+ """
54
+
55
+ HARBOR_TEST = f"""#!/bin/sh
56
+ if {CHECK}; then
57
+ echo 1 > /logs/verifier/reward.txt
58
+ else
59
+ echo 0 > /logs/verifier/reward.txt
60
+ fi
61
+ """
62
+
63
+ TASK_YAML = f"""\
64
+ instruction: |-
65
+ {INSTRUCTION}
66
+ difficulty: easy
67
+ category: file-operations
68
+ parser_name: pytest
69
+ max_agent_timeout_sec: 120.0
70
+ max_test_timeout_sec: 60.0
71
+ """
72
+
73
+ # A pytest-shaped report without pytest, so the task needs no network.
74
+ RUN_TESTS = f"""#!/bin/sh
75
+ echo "============================= test session starts =============================="
76
+ if {CHECK}; then hello=PASSED; else hello=FAILED; fi
77
+ echo "=========================== short test summary info ============================"
78
+ echo "PASSED tests/test_outputs.py::test_setup"
79
+ echo "$hello tests/test_outputs.py::test_hello_file"
80
+ """
81
+
82
+
83
+ def write(directory: str | Path) -> Path:
84
+ root = Path(directory)
85
+ h = root / "harbor" / "hello"
86
+ (h / "environment").mkdir(parents=True, exist_ok=True)
87
+ (h / "tests").mkdir(exist_ok=True)
88
+ (h / "solution").mkdir(exist_ok=True)
89
+ (h / "task.toml").write_text(TASK_TOML)
90
+ (h / "instruction.md").write_text(INSTRUCTION + "\n")
91
+ (h / "environment" / "Dockerfile").write_text(DOCKERFILE)
92
+ (h / "environment" / "blob.bin").write_bytes(BLOB)
93
+ (h / "tests" / "test.sh").write_text(HARBOR_TEST)
94
+ (h / "tests" / "blob.bin").write_bytes(BLOB)
95
+ (h / "solution" / "solve.sh").write_text("#!/bin/sh\nprintf 'Hello, world!' > /app/hello.txt\n")
96
+
97
+ t = root / "terminal-bench" / "hello"
98
+ (t / "tests").mkdir(parents=True, exist_ok=True)
99
+ (t / "task.yaml").write_text(TASK_YAML)
100
+ (t / "Dockerfile").write_text(DOCKERFILE)
101
+ (t / "blob.bin").write_bytes(BLOB)
102
+ (t / "run-tests.sh").write_text(RUN_TESTS)
103
+ (t / "tests" / "blob.bin").write_bytes(BLOB)
104
+ (t / "solution.sh").write_text("#!/bin/sh\nprintf 'Hello, world!' > /app/hello.txt\n")
105
+ return root
106
+
107
+
108
+ if __name__ == "__main__": # pragma: no cover
109
+ import sys
110
+
111
+ write(sys.argv[1] if len(sys.argv) > 1 else "benchmark-fixtures")