Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions skills/evaluate-environments/references/REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,14 @@ Installs the Codex CLI into the runtime and runs `codex exec`.

#### `RLMHarnessConfig` — `id: "rlm"`

Installs the rlm CLI and runs it. Knobs map onto `RLM_*` env vars; base `HarnessConfig.env` passes any other `RLM_*` var through verbatim.
Installs rlm-harness and runs its ACP agent. MCP tools become pre-imported
IPython skills while the model-facing tool surface remains `ipython`. Knobs map
onto `RLM_*` env vars; base `HarnessConfig.env` passes any other `RLM_*` var
through verbatim.

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `version` | `str` | `"main"` | Git ref (branch/tag/commit) of rlm to install. |
| `version` | `str` | `"56218f33796ecbe465445bc43948886354fde196"` | Git ref (branch/tag/commit) of rlm-harness to install. |
| `max_depth` | `int` | `0` | Recursion depth rlm may spawn sub-harnesses to (`RLM_MAX_DEPTH`). |
| `skills` | `list["edit" \| "search"]` | `[]` | Built-in rlm skills to enable (`RLM_SKILLS`). Empty enables none. |
| `summarize_at_tokens` | `int \| (int, int) \| None` | `None` | Auto-compaction threshold (`RLM_SUMMARIZE_AT_TOKENS`): compact once context grows past this many tokens. An int is fixed; a `(lo, hi)` pair draws a per-group threshold (seeded by task index). `None` disables. Ints must be positive. |
Expand Down
1 change: 1 addition & 0 deletions tests/v1/fixtures/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ build-backend = "hatchling.build"
[tool.hatch.build]
include = [
"counter_tool_v1.py",
"echo_acp_resume_v1.py",
"echo_tool_v1.py",
"tool_response_image_v1.py",
"pyproject.toml",
Expand Down
3 changes: 3 additions & 0 deletions tests/v1/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def _pair(a: str, b: str, id: str, *extra_marks):
# retain MCP access after resuming. Cover every harness in the local container runtime,
# plus one remote placement for the sandbox/tunnel boundary.
ACP_RESUME_PLACEMENTS = [
_pair("rlm", "docker", "rlm-acp-in-docker"),
_pair("kimi-code", "docker", "kimi-code-acp-in-docker"),
_pair("pi", "docker", "pi-acp-in-docker"),
_pair("pool", "docker", "pool-acp-in-docker"),
Expand Down Expand Up @@ -205,6 +206,8 @@ async def test_acp_resume_with_tool(run_v1, harness, harness_runtime, tmp_path):
assert segments[1]["terminated"] is False
assert "tool" in segments[1]["roles"]
assert segments[1]["tool_outputs"]
if harness == "rlm":
assert "turns_since_last_compaction" in trace.metrics


@pytest.mark.e2e
Expand Down
79 changes: 77 additions & 2 deletions verifiers/v1/acp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import json
import secrets
from pathlib import Path
from pathlib import Path, PurePosixPath

from verifiers.v1.dialects.chat import message_to_wire
from verifiers.v1.harness import Harness
Expand Down Expand Up @@ -33,6 +33,7 @@ async def run(
mcp_urls: dict[str, str] | None = None,
system_prompt: str | None = None,
session_path: str | None = None,
sidecar_path: str | None = None,
) -> ProgramResult:
if prompt is None:
raise ValueError("ACP requires a prompt")
Expand All @@ -51,14 +52,88 @@ async def run(
program = await runtime.prepare_uv_script(
ACP_SOURCE, {**env, "UV_FROZEN": "false"}
)
sidecar_log = None
if sidecar_path is not None:
sidecar_dir = self._sidecar_dir(sidecar_path)
sidecar_log = f"{sidecar_dir}/acp.log"
exists = await runtime.run(["test", "-S", sidecar_path], {})
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
Outdated
if exists.exit_code != 0:
created = await runtime.run(
["mkdir", "-p", "-m", "700", sidecar_dir], {}
)
if created.exit_code != 0:
raise RuntimeError(
f"ACP sidecar directory failed: {created.stderr.strip()}"
)
await runtime.run_background(
[*program, "serve", sidecar_path],
env,
sidecar_log,
)
Comment thread
hallerite marked this conversation as resolved.
Outdated
directory = f".vf-acp-{secrets.token_hex(8)}"
created = await runtime.run(["mkdir", "-m", "700", directory], {})
if created.exit_code != 0:
raise RuntimeError(f"ACP config directory failed: {created.stderr.strip()}")
path = f"{directory}/config.json"
try:
await runtime.write(path, json.dumps(config).encode())
result = await runtime.run_program([*program, path], env)
command = (
[*program, "request", path, sidecar_path]
if sidecar_path is not None
else [*program, "once", path]
)
result = await runtime.run_program(command, env)
if sidecar_log is not None and result.exit_code != 0:
log = await runtime.run(["tail", "-c", "4000", sidecar_log], {})
if log.exit_code == 0 and log.stdout:
result = ProgramResult(
exit_code=result.exit_code,
stdout=result.stdout,
stderr=(
f"{result.stderr.rstrip()}\n\nACP sidecar log:\n"
f"{log.stdout.rstrip()}"
).lstrip(),
)
return result
finally:
await run_shielded(runtime.run(["rm", "-rf", directory], {}))

async def close(
self, runtime: Runtime, sidecar_path: str, *, remove: bool = True
) -> None:
"""Stop a persistent ACP session, optionally keeping its artifacts."""
sidecar_dir = self._sidecar_dir(sidecar_path)
exists = await runtime.run(["test", "-S", sidecar_path], {})
failure = ""
try:
if exists.exit_code == 0:
program = await runtime.prepare_uv_script(
ACP_SOURCE, {"UV_FROZEN": "false"}
)
result = await runtime.run([*program, "shutdown", sidecar_path], {})
if result.exit_code != 0:
log = await runtime.run(
["tail", "-c", "4000", f"{sidecar_dir}/acp.log"], {}
)
failure = (
result.stderr.strip()
or result.stdout.strip()
or "ACP sidecar shutdown failed"
)
if log.exit_code == 0 and log.stdout:
failure = (
f"{failure}\n\nACP sidecar log:\n{log.stdout.rstrip()}"
)
finally:
if remove:
await run_shielded(runtime.run(["rm", "-rf", sidecar_dir], {}))
if failure:
raise RuntimeError(failure)

@staticmethod
def _sidecar_dir(sidecar_path: str) -> str:
path = PurePosixPath(sidecar_path)
parent = str(path.parent)
if path.is_absolute() or ".." in path.parts or parent in ("", ".", "/"):
raise ValueError("ACP sidecar must live in a private subdirectory")
return parent
Loading
Loading