|
| 1 | +# Harbor adapter for Corbits Code |
| 2 | + |
| 3 | +Thin Harbor `BaseInstalledAgent` that runs headless product Corbits: |
| 4 | + |
| 5 | +```text |
| 6 | +corbits exec --cwd … --config … --provider … --model … |
| 7 | + --dangerously-skip-permissions --force <instruction> |
| 8 | +``` |
| 9 | + |
| 10 | +No second agent loop. Credentials are translated from Harbor kwargs/env into a |
| 11 | +temporary `settings.json` passed with `--config` — product Corbits still does |
| 12 | +not read API keys from the environment. |
| 13 | + |
| 14 | +## Layout |
| 15 | + |
| 16 | +| Path | Role | |
| 17 | +| -------------------- | ------------------------------------------------------ | |
| 18 | +| `argv.py` | Pure settings + argv builders (unit-tested, no Harbor) | |
| 19 | +| `agent.py` | `Corbits` installed agent (requires Harbor at import) | |
| 20 | +| `tasks/trivial/` | Minimal smoke task (`hello.txt`) | |
| 21 | +| `tests/test_argv.py` | Argv/settings unit tests | |
| 22 | + |
| 23 | +## Prerequisites |
| 24 | + |
| 25 | +1. **Harbor CLI** installed in the host Python env (`pip install harbor` / uv). |
| 26 | +2. **Linux ELF `corbits` binary** for the task container (Darwin host builds |
| 27 | + will not run inside Linux Docker). Acquire one of: |
| 28 | + - Build on Linux: `bun run build:bin` → `dist/corbits` |
| 29 | + - Release / CI tarball that unpacks a `corbits` binary |
| 30 | +3. **git** inside the task image (adapter also installs it via Harbor system |
| 31 | + packages). Corbits storage requires git — there is no git-less fallback. |
| 32 | +4. **Provider API key** for the model under test. |
| 33 | +5. **Provider `base_url`** (required — see below). The adapter fail-closes if |
| 34 | + none is resolved; it does not invent a default. |
| 35 | + |
| 36 | +## Secrets / credentials |
| 37 | + |
| 38 | +Pass a key through Harbor agent kwargs or env. The adapter writes it into the |
| 39 | +temp settings file only: |
| 40 | + |
| 41 | +| Source | Notes | |
| 42 | +| ----------------------- | ---------------------------------------- | |
| 43 | +| `api_key=` agent kwarg | Preferred for one-off runs | |
| 44 | +| `CORBITS_API_KEY` | Generic adapter env | |
| 45 | +| `{PROVIDER}_API_KEY` | e.g. `XAI_API_KEY`, `OPENAI_API_KEY` | |
| 46 | +| Harbor model connection | Falls back to `model_connection.api_key` | |
| 47 | + |
| 48 | +### Required base URL |
| 49 | + |
| 50 | +`providers.<provider>.baseURL` is always written. Resolve it via one of: |
| 51 | + |
| 52 | +| Source | Notes | |
| 53 | +| ------------------------------ | -------------------------------------------------- | |
| 54 | +| `base_url=` agent kwarg | Preferred for one-off runs | |
| 55 | +| `CORBITS_BASE_URL` | Adapter env | |
| 56 | +| Harbor model connection | `model_connection.configured_base_url` when set | |
| 57 | + |
| 58 | +If none are set, the adapter raises before writing settings. |
| 59 | + |
| 60 | +Example values: |
| 61 | + |
| 62 | +| Cell | Example `base_url` | |
| 63 | +| ---------------------------- | -------------------------------------- | |
| 64 | +| xAI API key | `https://api.x.ai/v1` | |
| 65 | +| Product OAuth / grok-cli path | `https://cli-chat-proxy.grok.com/v1` (`XAI_BASE_URL` in `src/auth/xai/constants.ts`) | |
| 66 | +| OpenAI-compatible | e.g. `https://api.openai.com/v1` or your cell's gateway | |
| 67 | + |
| 68 | +Optional: `shell_timeout_ms=` → `shell.timeoutMs` in settings. |
| 69 | + |
| 70 | +Default provider/model when Harbor does not pass `provider/model`: **xai** / |
| 71 | +**grok-4.5**. Codex cells typically use `--model openai/<id>` (or pass |
| 72 | +`provider=` / `model=` kwargs). |
| 73 | + |
| 74 | +## Linux binary acquisition |
| 75 | + |
| 76 | +The adapter installs the binary onto PATH from **one** of: |
| 77 | + |
| 78 | +| Kwarg | Behavior | |
| 79 | +| --------------------- | ------------------------------------------------- | |
| 80 | +| `corbits_binary_path` | Upload a host file into `/usr/local/bin/corbits` | |
| 81 | +| `corbits_binary_url` | `curl` a raw binary URL | |
| 82 | +| `corbits_tarball_url` | `curl` + extract; expects a `corbits` file inside | |
| 83 | + |
| 84 | +Archive vs raw binary is detected from the URL suffix (`.tar.gz`, `.tgz`, |
| 85 | +`.tar`) — the install script does not call `file(1)`. |
| 86 | + |
| 87 | +If none are set and `corbits` is not already on PATH in the environment, |
| 88 | +`install()` raises with this README pointer. |
| 89 | + |
| 90 | +## Invoke |
| 91 | + |
| 92 | +From the repo root (so `evals.harbor.agent` is importable): |
| 93 | + |
| 94 | +```bash |
| 95 | +# Unit tests (no Harbor package required; pytest may be absent) |
| 96 | +PYTHONPATH=. python3 -m unittest evals.harbor.tests.test_argv -v |
| 97 | + |
| 98 | +# Dry-run trivial task (needs Harbor CLI + Linux binary + API key + base URL) |
| 99 | +export CORBITS_API_KEY=… # or XAI_API_KEY=… |
| 100 | +export CORBITS_BASE_URL=https://api.x.ai/v1 |
| 101 | +harbor run \ |
| 102 | + -p evals/harbor/tasks/trivial \ |
| 103 | + -a evals.harbor.agent:Corbits \ |
| 104 | + -m xai/grok-4.5 \ |
| 105 | + --ae corbits_binary_path=/absolute/path/to/linux/corbits |
| 106 | +``` |
| 107 | + |
| 108 | +Equivalent kwargs via Harbor job config: |
| 109 | + |
| 110 | +```yaml |
| 111 | +agents: |
| 112 | + - name: evals.harbor.agent:Corbits |
| 113 | + kwargs: |
| 114 | + provider: xai |
| 115 | + model: grok-4.5 |
| 116 | + api_key: ${CORBITS_API_KEY} |
| 117 | + base_url: https://api.x.ai/v1 |
| 118 | + corbits_binary_path: /absolute/path/to/linux/corbits |
| 119 | + # or: corbits_tarball_url: https://…/corbits-linux.tar.gz |
| 120 | +``` |
| 121 | + |
| 122 | +## Known gaps (CL-6924) |
| 123 | + |
| 124 | +- Full Harbor dry-run + Terminal-Bench smoke are **not** claimed by this change. |
| 125 | + They need Harbor CLI, a Linux ELF binary, Docker, and provider credentials on |
| 126 | + a machine that can run the harness end-to-end — tracked as **CL-6924**. |
| 127 | +- This adapter does not parse Corbits trajectories into Harbor ATIF; exit |
| 128 | + metadata is limited to `context.metadata["exit_code"]` plus tee'd stdout in |
| 129 | + `/logs/agent/corbits.txt`. |
0 commit comments