Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions CodeyBox.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<Project Path="src/CodeyBox.Agents.DotNetOpencode/CodeyBox.Agents.DotNetOpencode.csproj" />
<Project Path="src/CodeyBox.Agents.Devin/CodeyBox.Agents.Devin.csproj" />
<Project Path="src/CodeyBox.Agents.CavemanCode/CodeyBox.Agents.CavemanCode.csproj" />
<Project Path="src/CodeyBox.Agents.Unreal/CodeyBox.Agents.Unreal.csproj" />
<Project Path="src/CodeyBox.Agents/CodeyBox.Agents.csproj" />
<Project Path="src/CodeyBox.AdminSeed/CodeyBox.AdminSeed.csproj" />
<Project Path="src/CodeyBox.Api/CodeyBox.Api.csproj" />
Expand Down
3 changes: 3 additions & 0 deletions docs/concepts/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ tooling, not in the agent runner contract.
| `cmd` | `cmd` | `OPENROUTER_API_KEY` (provider API key resolved through the seeded `~/.commandcode/providers.json` `$OPENROUTER_API_KEY` reference — the file never carries the raw key; the runner also seeds a non-credential `~/.commandcode/auth.json` placeholder for plan-less `--local-only` BYOK — see [Command Code quirks](../reference/agent-quirks.md#command-code-cmd)) | `CODEYBOX_CMD_API_KEY` |
| `crush` | `crush` | `OPENROUTER_API_KEY` (provider API key read directly from the environment — no config file is seeded; every dispatch also carries `CRUSH_DISABLE_METRICS=1` — see [Crush quirks](../reference/agent-quirks.md#crush-crush)) | `CODEYBOX_CRUSH_API_KEY` |
| `dotnet-opencode` | `dotnet-opencode` | `DOTNETOPENCODE_CONFIG_JSON` (global `opencode.json` provider config, written to `~/.config/opencode/opencode.json`; supports `{env:VAR}` indirection — see [dotnet-opencode quirks](../reference/agent-quirks.md#dotnet-opencode-honadotnet-opencode)) | `CODEYBOX_DOTNETOPENCODE_CONFIG_JSON` |
| `unreal` | `unreal-agent-runner` | `OPENROUTER_API_KEY` (provider API key read directly from environment — no guest config file; other providers use `OPENAI_API_KEY`, `FIREWORKS_API_KEY`, or `UNREAL_HARNESS_LLM_API_KEY` — see [Unreal quirks](../reference/agent-quirks.md#unreal-agent-unreal-agent-runner)) | `CODEYBOX_UNREAL_API_KEY` (+ `CODEYBOX_UNREAL_PROVIDER`, `CODEYBOX_UNREAL_OPENAI_API_KEY`, `CODEYBOX_UNREAL_FIREWORKS_API_KEY`) |

The sandbox-side env name is what the agent CLI reads. The host-side name is
what the orchestrator looks up when building the credential bundle — for most
Expand Down Expand Up @@ -80,6 +81,7 @@ the most common cause of fresh-class dispatch failures.
| `cmd` | `npm install -g command-code@1.54.2` | Needs Node.js on the image. Version-pinned for reproducible bakes — re-verify the headless contract (`-p --output-format json`), the `--yolo` autonomy flag, and the `~/.commandcode/` file layout (see below) before bumping. The base image should also pre-seed `~/.commandcode/providers.json` (openrouter entry with the `$OPENROUTER_API_KEY` reference — never a raw key) and `~/.commandcode/auth.json` (non-credential presence placeholder) so ad-hoc runs work; the runner re-seeds both at dispatch (see [Command Code quirks](../reference/agent-quirks.md#command-code-cmd) and [sandbox baselines](../reference/sandbox-baselines.md)). |
| `crush` | `npm install -g @charmland/crush@0.95.0` | Charm's agent CLI; needs Node.js on the image. Version-pinned for reproducible bakes — re-verify the headless contract (`run -q -m`, prompt on stdin, plain-text output, no `--yolo` on `run`) before bumping. See [Crush quirks](../reference/agent-quirks.md#crush-crush). |
| `dotnet-opencode` | `dotnet tool install --global dotnet-opencode --prerelease` (after the exact .NET 11 preview SDK `11.0.100-preview.7.26381.103` — roll-forward is disabled — plus ripgrep on PATH) | Heaviest agent baseline: preview SDK + prerelease tool + `rg`. Pinned version `0.1.0-ci.20260905083303.33955573552.1`. See [dotnet-opencode quirks](../reference/agent-quirks.md#dotnet-opencode-honadotnet-opencode) and [`sandbox-baselines.md`](../reference/sandbox-baselines.md). |
| `unreal` | `curl -fsSL -o /tmp/unreal.tar.gz https://github.com/unreallabsai/unreal-agent/releases/download/v0.1.1/unreal-agent-runner_0.1.1_linux_amd64.tar.gz && echo "fad9cb9e6e6272a8d16fb4b90f985abb3132572413588f96622c6b1a82e34fcd /tmp/unreal.tar.gz" \| sha256sum -c - && tar -xzf /tmp/unreal.tar.gz -C /usr/local/bin unreal-agent-runner && chmod +x /usr/local/bin/unreal-agent-runner && rm /tmp/unreal.tar.gz` (for arm64: `0e61571dc9b83b429aaf9c89d8af372ff39a7ef50313fa2fd0ef15c6fa527d02`) | Pinned release v0.1.1 (commit `b7c9bf1c5c`), SHA256 checksum-verified. Installs `unreal-agent-runner` binary on PATH. Self-contained Go executable (no runtime required). See [Unreal quirks](../reference/agent-quirks.md#unreal-agent-unreal-agent-runner). |

Verify each command against its upstream install docs at the time of baking —
versions and install URLs change. Multipass and Incus keep independent bake
Expand Down Expand Up @@ -206,6 +208,7 @@ credentials before they waste expensive compute.
| `omp` | *(no network call — omp fronts ~60 providers, so no single endpoint validates the credential)* — verifies the bundle carries `OPENROUTER_API_KEY`; real auth check happens on first CLI call | `OPENROUTER_API_KEY` |
| `continue` | *(no network call — Continue fronts hundreds of models, so no single endpoint validates the credential)* — verifies the bundle carries `OPENROUTER_API_KEY`; real auth check happens on first CLI call | `OPENROUTER_API_KEY` |
| `dotnet-opencode` | *(no network call — provider-agnostic BYOK front with an interactive-only device login; any provider call spends real quota)* — verifies the bundle carries `DOTNETOPENCODE_CONFIG_JSON`; real auth check happens on first CLI call | `DOTNETOPENCODE_CONFIG_JSON` |
| `unreal` | *(no network call — multi-provider front; any provider call spends real quota)* — verifies the bundle carries `OPENROUTER_API_KEY`, `OPENAI_API_KEY`, `FIREWORKS_API_KEY`, or `UNREAL_HARNESS_LLM_API_KEY` and rejects Codex subscription credentials; real auth check happens on first CLI call | `OPENROUTER_API_KEY` (or provider key) |

Each probe sends the minimal possible request (`max_tokens=1`). A 2xx response
means the credential is valid. 401/403 is classified as `"auth"` failure.
Expand Down
84 changes: 84 additions & 0 deletions docs/reference/agent-quirks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2412,3 +2412,87 @@ unknown model id is configuration, not quota — mirroring kilo's `Model not
found` exclusion), `Unknown flag` (dispatch construction, which the
runner's pinned argv cannot produce), and quota/401 prose from reviewed
repository content (patterns stay anchored to provider-shaped sentences).

### Unreal Agent (`unreal`)

**Install in the sandbox image** — add the install line to
`CodeyBox:MultipassExtraRuncmd` or `CodeyBox:Incus:ExtraRuncmd`, matching the
selected provider (verified against unreal-agent v0.1.1, commit `b7c9bf1c5c`, 2026-09-24):

```sh
UNREAL_AGENT_VERSION=v0.1.1
curl -fsSL -o /tmp/unreal-agent-runner "https://github.com/unreallabsai/unreal-agent/releases/download/${UNREAL_AGENT_VERSION}/unreal-agent-runner-linux-amd64"
printf '%s %s\n' "fad9cb9e6e6272a8d16fb4b90f985abb3132572413588f96622c6b1a82e34fcd" /tmp/unreal-agent-runner | sha256sum -c -
install -m 0755 /tmp/unreal-agent-runner /usr/local/bin/unreal-agent-runner
rm /tmp/unreal-agent-runner
```

Go-based autonomous agent runner ([repo](https://github.com/unreallabsai/unreal-agent), binary `unreal-agent-runner`).
The installer downloads the pinned release binary with its SHA256 checksum verified before execution
(`fad9cb9e6e6272a8d16fb4b90f985abb3132572413588f96622c6b1a82e34fcd` for `linux_amd64`,
`0e61571dc9b83b429aaf9c89d8af372ff39a7ef50313fa2fd0ef15c6fa527d02` for `linux_arm64`),
dropping `unreal-agent-runner` on PATH.

**Non-interactive invocation (Trap 1: JSON on stdin).** The runner does NOT use `-p`,
`--prompt`, or `/dev/stdin`. The CLI expects a non-interactive JSON request payload
piped directly to standard input:

```json
{"prompt":"<prompt>","model":"<model>","thinking_level":"<level>"}
```

This bypasses Linux's `MAX_ARG_STRLEN` (128 KiB per argv element) entirely, allowing
rework prompts and large contexts (> 128 KiB) to be delivered intact without truncation
or shell escape hazards.

**Session and log isolation (Trap 2: Directories outside workspace).** By default,
`unreal-agent-runner` attempts to create session and log directories inside the current
working directory (`.unreal/logs`, `.unreal/sessions`). In CodeyBox, git working trees must
remain clean and unpolluted by runner operational artifacts. The runner always supplies:

```sh
unreal-agent-runner -workspace <workingDirectory> -log-directory /tmp/codeybox-unreal/<runId>/logs -session-directory /tmp/codeybox-unreal/<runId>/sessions
```

This ensures session operations, scratchpad files, and internal operation logs remain
isolated outside the workspace worktree.

**Workspace `.env` quarantine (Trap 3: Preventing configuration injection).** Unreal agent
automatically parses `.env` files located in the workspace directory. A malicious or
compromised repository containing a `.env` file could override:
- `SANDBOX_EGRESS_PROXY` (hijacking outbound agent network traffic to an untrusted proxy)
- `UNREAL_HARNESS_LLM_PROVIDER` or `UNREAL_HARNESS_LLM_BASE_URL` (tampering with model endpoints)
- Provider API keys and credentials

To prevent configuration injection, `UnrealAgentRunner` probes for `.env` files in the workspace
prior to execution, moves them to a unique quarantine path (`.env.codeybox-quarantined-<runId>`),
and safely restores them in a `finally` block upon completion. If quarantine fails, the run is
aborted immediately to fail closed.

**Account safety: Codex subscription rejection.** Unreal agent supports pay-per-API providers
(OpenAI API, OpenRouter, etc.). It does NOT support OpenAI Codex web subscription tokens or
session credentials. Attempting to use subscription credentials with raw API endpoints risks
account suspension or billing errors. `UnrealAgentRunner` and `UnrealSmokeProbe` actively inspect
credentials and reject subscription tokens (`codex_subscription` kind or Bearer JWT subscription shapes)
before any dispatch occurs.

**Reasoning effort & model mapping.** `ReasoningMode` maps to `thinking_level` in the JSON request:
- `ReasoningMode.Low` -> `"low"`
- `ReasoningMode.Medium` -> `"medium"`
- `ReasoningMode.High` -> `"high"`
- `ReasoningMode.ExtraHigh` -> `"xhigh"`
- `ReasoningMode.Maximum` -> `"max"`

Supported catalog models include `gpt-6-astra` and `openrouter/nvidia/nemotron-3.5-lightning:free`.
Custom model IDs are passed verbatim with startup warnings if unrecognized.

**Exit codes & failure classification.**
- `0`: Success.
- `1`: Error (lifted to `TerminalDiagnostic` bounded to 500 chars via `UnrealTerminalDiagnoser`).
- `130`: Interrupted (SIGINT/SIGTERM), classified as `AgentFailureKind.Infrastructure` so the orchestrator retries or reschedules rather than treating it as an agent task failure.

**Cost attribution & stream parsing.** `UnrealStreamParser` parses NDJSON session items emitted to stdout:
- `model_response`: Extracts assistant text, tool calls, and token usage (`Usage.InputTokens`, `Usage.OutputTokens`, `Usage.CachedInputTokens`).
- `tool_call_status`: Tracks tool execution results and byte sizes from shell operations.
- `type: "error"`: Extracts terminal error messages.
`UnrealCostExtractor` attributes costs based on token usage reported in `model_response` frames.
19 changes: 19 additions & 0 deletions src/CodeyBox.Agents.Unreal/CodeyBox.Agents.Unreal.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<ProjectReference Include="..\CodeyBox.Agents\CodeyBox.Agents.csproj" />
<ProjectReference Include="..\CodeyBox.Core\CodeyBox.Core.csproj" />
<ProjectReference Include="..\CodeyBox.HostProcess\CodeyBox.HostProcess.csproj" />
</ItemGroup>

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<InternalsVisibleTo Include="CodeyBox.Tests" />
</ItemGroup>

</Project>
Loading
Loading