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
6 changes: 5 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ AGENTFIELD_PUBLIC_URL=
NODE_ID=pr-af

# --- AI / harness config ---
PR_AF_PROVIDER=opencode
# AForge exec is the default. Set PR_AF_PROVIDER=opencode to roll back.
PR_AF_PROVIDER=aforge
# Read by the Go node's SDK adapter; the pinned Python SDK always runs `exec`.
AGENTFIELD_AFORGE_COMMAND=exec
PR_AF_MODEL=openrouter/moonshotai/kimi-k2.5
# Falls back to PR_AF_MODEL when unset
# PR_AF_AI_MODEL=
Expand All @@ -24,6 +27,7 @@ PR_AF_AI_MAX_RETRIES=3
PR_AF_AI_INITIAL_BACKOFF_SECONDS=2.0
PR_AF_AI_MAX_BACKOFF_SECONDS=8.0
PR_AF_OPENCODE_BIN=opencode
PR_AF_AFORGE_BIN=aforge
# Optional provider-agnostic harness executable override (leave unset to use provider defaults)
# PR_AF_HARNESS_BIN=
PR_AF_OPENCODE_SERVER=
Expand Down
39 changes: 37 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
# ---------------------------------------------------------------------------
# Stage 0 — aforge: fetch the released AForge CLI from the public download host
# and verify it against the release checksums (which hash the DECOMPRESSED
# binaries). Both ARGs are overridable so CI or a local mirror can serve the
# assets from somewhere else:
#
# docker build --build-arg AFORGE_BASE_URL=... --build-arg AFORGE_VERSION=... .
# ---------------------------------------------------------------------------
FROM debian:bookworm-slim AS aforge

ARG AFORGE_BASE_URL=https://agentfield.ai/downloads/aforge
ARG AFORGE_VERSION=v0.1.0
ARG TARGETARCH

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl && \
rm -rf /var/lib/apt/lists/*

WORKDIR /out
RUN set -eux; \
arch="${TARGETARCH:-$(dpkg --print-architecture)}"; \
curl -fsSL "${AFORGE_BASE_URL}/${AFORGE_VERSION}/aforge-linux-${arch}.gz" -o aforge.gz; \
gunzip -c aforge.gz > aforge; \
rm -f aforge.gz; \
curl -fsSL "${AFORGE_BASE_URL}/${AFORGE_VERSION}/checksums.txt" -o checksums.txt; \
grep " aforge-linux-${arch}$" checksums.txt | sed 's/ aforge-linux-.*/ aforge/' > aforge.sha256; \
test -s aforge.sha256; \
sha256sum -c aforge.sha256; \
rm -f checksums.txt aforge.sha256; \
chmod +x aforge


FROM python:3.11-slim AS builder

ENV PYTHONDONTWRITEBYTECODE=1 \
Expand All @@ -14,7 +47,7 @@ COPY pyproject.toml README.md ./
COPY src/ src/

RUN pip install --no-cache-dir --prefix=/install \
"agentfield==0.1.126" \
"agentfield>=0.1.130" \
"hax-sdk>=0.2.4" \
"pydantic>=2.0" \
"httpx>=0.27" \
Expand All @@ -32,7 +65,8 @@ ARG OPENCODE_VERSION=1.17.15
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
AGENTFIELD_SERVER=http://agentfield:8080 \
PR_AF_PROVIDER=opencode \
PR_AF_PROVIDER=aforge \
AGENTFIELD_AFORGE_COMMAND=exec \
PR_AF_MODEL=openrouter/moonshotai/kimi-k2.5 \
PORT=8004 \
HOME=/home/praf \
Expand All @@ -55,6 +89,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
rm -rf /var/lib/apt/lists/*

COPY --from=builder /install /usr/local
COPY --from=aforge /out/aforge /usr/local/bin/aforge
COPY src/ /app/src/
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
Expand Down
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,26 @@ The key knobs (see `.env.example` for the full list):
|-----------------------------|----------------------------------------------------------------|
| `OPENROUTER_API_KEY` | LLM provider key (OpenRouter) — required |
| `GH_TOKEN` | GitHub token (`repo` scope) for reading PRs and posting reviews |
| `PR_AF_PROVIDER` | Harness provider (default `opencode`) |
| `PR_AF_PROVIDER` | Harness provider (default `aforge`; use `opencode` to roll back) |
| `AGENTFIELD_AFORGE_COMMAND` | AForge headless command (default `exec`) — read by the Go node's SDK adapter; the pinned Python SDK always runs `exec` |
| `PR_AF_AFORGE_BIN` | Path to an aforge-v2 binary (default `aforge`) |
| `PR_AF_HARNESS_BIN` | Provider-agnostic executable override |
| `PR_AF_MODEL` | Harness model (default `openrouter/moonshotai/kimi-k2.5`) |
| `PR_AF_MAX_COST_USD` | Per-run cost ceiling in USD (default `2.0`) |
| `PR_AF_MAX_DURATION_SECONDS`| Per-run wall-clock ceiling in seconds (default `3600`) |
| `AGENTFIELD_HARNESS_IDLE_SECONDS` | Harness no-output watchdog window in seconds (default `360`) — harness CLIs in JSON mode emit events only at completion boundaries, so long single completions look silent |
| `PR_AF_WORKDIR` | Where PR checkouts live (default `/workspaces`); each PR gets its own `<repo>-pr<N>` workspace |

Both Docker images ship the released AForge CLI (fetched and checksum-verified
at build time from `https://agentfield.ai/downloads/aforge`) and run `exec` by
default. The Python node resolves the binary from `PR_AF_AFORGE_BIN` (or
`PR_AF_HARNESS_BIN`); the maintained Go node resolves it from
`PR_AF_HARNESS_BIN`. OpenCode stays installed in both images, so
`PR_AF_PROVIDER=opencode` is a configuration-only rollback — no rebuild.

The image's AForge version is pinned by the `AFORGE_VERSION` build arg;
`AFORGE_BASE_URL` points the fetch at a different host when needed.

## GitHub Actions Integration

The easiest way to use PR-AF is to drop it into your GitHub Actions. It requires **zero configuration** and runs securely using GitHub's built-in `GITHUB_TOKEN`.
Expand Down
9 changes: 7 additions & 2 deletions agentfield-package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,13 @@ user_environment:
type: secret
scope: global
- name: PR_AF_PROVIDER
description: Coding-agent harness provider
default: opencode
description: Coding-agent harness provider (aforge | claude-code | codex | gemini | opencode)
default: aforge
- name: AGENTFIELD_AFORGE_COMMAND
description: AForge headless command the SDK runs (exec | do); default exec on agentfield>=0.1.130
default: exec
- name: PR_AF_AFORGE_BIN
description: Optional path to the aforge-v2 binary (defaults to aforge on PATH)
- name: PR_AF_MODEL
description: Model the harness uses
default: openrouter/moonshotai/kimi-k2.5
Expand Down
3 changes: 2 additions & 1 deletion docker-compose.go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ services:
- NODE_ID=pr-af-go
- PORT=8007
- AGENT_CALLBACK_URL=http://pr-af-go:8007
- PR_AF_PROVIDER=${PR_AF_PROVIDER:-opencode}
- PR_AF_PROVIDER=${PR_AF_PROVIDER:-aforge}
- AGENTFIELD_AFORGE_COMMAND=${AGENTFIELD_AFORGE_COMMAND:-exec}
- PR_AF_MODEL=${PR_AF_MODEL:-openrouter/moonshotai/kimi-k2.5}
# Optional generic executable override; leave unset for provider defaults.
- PR_AF_HARNESS_BIN
Expand Down
3 changes: 2 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ services:
- AGENTFIELD_SERVER=http://agentfield:8080
- AGENTFIELD_API_KEY=${AGENTFIELD_API_KEY:-}
- AGENT_CALLBACK_URL=http://pr-af:8004
- PR_AF_PROVIDER=${PR_AF_PROVIDER:-opencode}
- PR_AF_PROVIDER=${PR_AF_PROVIDER:-aforge}
- AGENTFIELD_AFORGE_COMMAND=${AGENTFIELD_AFORGE_COMMAND:-exec}
- PR_AF_MODEL=${PR_AF_MODEL:-openrouter/moonshotai/kimi-k2.5}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
- GH_TOKEN=${GH_TOKEN:-}
Expand Down
44 changes: 42 additions & 2 deletions go/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,42 @@
# GOWORK=off, and no `replace` dance. `go mod download` pulls the SDK and every
# other dependency straight from the module proxy, cache-keyed on go.mod/go.sum.

# ---------------------------------------------------------------------------
# Stage 0 — aforge: fetch the released AForge CLI from the public download host
# and verify it against the release checksums (which hash the DECOMPRESSED
# binaries). Both ARGs are overridable so CI or a local mirror can serve the
# assets from somewhere else:
#
# docker build --build-arg AFORGE_BASE_URL=... --build-arg AFORGE_VERSION=... .
# ---------------------------------------------------------------------------
FROM debian:bookworm-slim AS aforge

ARG AFORGE_BASE_URL=https://agentfield.ai/downloads/aforge
ARG AFORGE_VERSION=v0.1.0
ARG TARGETARCH

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl && \
rm -rf /var/lib/apt/lists/*

WORKDIR /out
RUN set -eux; \
arch="${TARGETARCH:-$(dpkg --print-architecture)}"; \
curl -fsSL "${AFORGE_BASE_URL}/${AFORGE_VERSION}/aforge-linux-${arch}.gz" -o aforge.gz; \
gunzip -c aforge.gz > aforge; \
rm -f aforge.gz; \
curl -fsSL "${AFORGE_BASE_URL}/${AFORGE_VERSION}/checksums.txt" -o checksums.txt; \
grep " aforge-linux-${arch}$" checksums.txt | sed 's/ aforge-linux-.*/ aforge/' > aforge.sha256; \
test -s aforge.sha256; \
sha256sum -c aforge.sha256; \
rm -f checksums.txt aforge.sha256; \
chmod +x aforge


# ---------------------------------------------------------------------------
# Stage 1 — builder: fetch modules from the proxy, build the static binary.
# golang 1.23 satisfies go.mod's `go 1.21` directive.
# Go 1.23 satisfies go.mod's `go 1.21` directive.
# ---------------------------------------------------------------------------
FROM golang:1.23-bookworm AS builder

Expand Down Expand Up @@ -42,7 +75,8 @@ ARG OPENCODE_VERSION=1.17.15
# PR_AF_HARNESS_BIN remains unset by default; set it only to override every
# provider's executable path.
ENV AGENTFIELD_SERVER=http://agentfield:8080 \
PR_AF_PROVIDER=opencode \
PR_AF_PROVIDER=aforge \
AGENTFIELD_AFORGE_COMMAND=exec \
PR_AF_MODEL=openrouter/moonshotai/kimi-k2.5 \
PORT=8007 \
NODE_ID=pr-af \
Expand All @@ -67,10 +101,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
rm -rf /var/lib/apt/lists/*

COPY --from=builder /out/pr-af /usr/local/bin/pr-af
COPY --from=aforge /out/aforge /usr/local/bin/aforge
COPY go/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh

USER praf
# Cwd must be writable by praf: the AgentField Go SDK creates its schema
# output dir under the process cwd when a harness call carries no Cwd
# (planning/coverage/dedup/worthiness/intake-fallback do), and `/` is
# root-owned. /workspaces is praf-owned and is PR_AF_WORKDIR already.
WORKDIR /workspaces

EXPOSE 8007

Expand Down
10 changes: 8 additions & 2 deletions go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,24 @@ The node is configured entirely through the environment.
| `AGENTFIELD_API_KEY` | Control-plane API key (if the CP has auth enabled) |
| `NODE_ID` | Node ID (default `pr-af`) |
| `PORT` | Listen port (default `8007`) |
| `PR_AF_PROVIDER` | Harness provider (default `opencode`) |
| `PR_AF_PROVIDER` | Harness provider (default `aforge`; use `opencode` to roll back) |
| `AGENTFIELD_AFORGE_COMMAND` | AForge headless command — `exec` (default) or `do` |
| `PR_AF_MODEL` | Harness model (default `openrouter/moonshotai/kimi-k2.5`) |
| `PR_AF_LABEL` | Pull-request label that triggers a webhook review (default `pr-af`) |
| `PR_AF_MAX_CONCURRENT_REVIEWERS` | Optional webhook review concurrency cap (minimum `1`) |
| `PR_AF_MAX_REVIEW_DEPTH` | Optional webhook sub-review depth cap (minimum `0`) |
| `PR_AF_MAX_COVERAGE_ITERATIONS` | Optional webhook coverage iteration cap (minimum `1`) |
| `PR_AF_HARNESS_BIN` | Optional harness executable override for every provider; unset uses provider defaults |
| `PR_AF_HARNESS_BIN` | Optional harness executable override for every provider (point it at an `aforge` binary outside `PATH`); unset uses provider defaults |
| `PR_AF_MAX_COST_USD` | Per-run cost ceiling in USD (default `2.0`) |
| `PR_AF_MAX_DURATION_SECONDS`| Per-run wall-clock ceiling in seconds (default `3600`) |
| `AGENTFIELD_HARNESS_IDLE_SECONDS` | Harness no-output watchdog window in seconds (default `360`) — harness CLIs in JSON mode emit events only at completion boundaries, so long single completions look silent |
| `HAX_API_KEY` | Optional — enables the HITL review-approval gate when set |

The image ships the released AForge CLI (fetched and checksum-verified at build
time from `https://agentfield.ai/downloads/aforge`, pinned by the
`AFORGE_VERSION` build arg) and runs `exec` by default. OpenCode remains
installed and can be selected with `PR_AF_PROVIDER=opencode` without rebuilding.

Note: the code default model is `minimax/minimax-m2.5`, while the Docker image /
compose / manifest set `PR_AF_MODEL=openrouter/moonshotai/kimi-k2.5`. The env
var always wins; both defaults are intentional (they mirror the Python node).
Expand Down
9 changes: 6 additions & 3 deletions go/agentfield-package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ user_environment:
type: secret
scope: global
- name: PR_AF_PROVIDER
description: harness provider
default: opencode
description: harness provider (aforge | claude-code | codex | gemini | opencode)
default: aforge
- name: AGENTFIELD_AFORGE_COMMAND
description: AForge headless command (exec | do)
default: exec
- name: PR_AF_MODEL
description: harness model
default: openrouter/moonshotai/kimi-k2.5
Expand All @@ -56,7 +59,7 @@ user_environment:
- name: PR_AF_MAX_COVERAGE_ITERATIONS
description: optional coverage iteration cap for webhook-triggered reviews (minimum 1)
- name: PR_AF_HARNESS_BIN
description: optional executable override for every harness provider (unset uses provider defaults)
description: optional executable override for every harness provider (set to an aforge-v2 binary with PR_AF_PROVIDER=aforge)
- name: PR_AF_MAX_COST_USD
description: per-run cost ceiling
default: "2.0"
Expand Down
2 changes: 1 addition & 1 deletion go/cmd/pr-af/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// AGENT_CALLBACK_URL base URL the CP uses to reach this node (else localhost)
// NODE_ID node id (default pr-af)
// PORT listen port (default 8007)
// PR_AF_PROVIDER harness provider (default opencode)
// PR_AF_PROVIDER harness provider (default aforge; accepts opencode rollback)
// PR_AF_MODEL harness model (env wins over the code default)
// PR_AF_HARNESS_BIN optional executable override for every harness provider
// OPENROUTER_API_KEY LLM key — required for the .ai() gates; AIConfig is only
Expand Down
2 changes: 1 addition & 1 deletion go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module github.com/Agent-Field/pr-af/go
go 1.21

require (
github.com/Agent-Field/agentfield/sdk/go v0.0.0-20260714191100-2cc5fe2adcf4
github.com/Agent-Field/agentfield/sdk/go v0.1.130
github.com/golang-jwt/jwt/v5 v5.3.1
github.com/invopop/jsonschema v0.13.0
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
Expand Down
4 changes: 2 additions & 2 deletions go/go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
github.com/Agent-Field/agentfield/sdk/go v0.0.0-20260714191100-2cc5fe2adcf4 h1:B3uCMLZSa2rsRDRGuecBIXCgkYqBuScSK4CXKPDaCgk=
github.com/Agent-Field/agentfield/sdk/go v0.0.0-20260714191100-2cc5fe2adcf4/go.mod h1:08VZk14uw4GJH6a34psHkuLu+DcRr197Zi0IGmLlfrM=
github.com/Agent-Field/agentfield/sdk/go v0.1.130 h1:k6ATecElqx54AUGzmFnbJy/BrFY+2UhPV7VM3X8ByTw=
github.com/Agent-Field/agentfield/sdk/go v0.1.130/go.mod h1:08VZk14uw4GJH6a34psHkuLu+DcRr197Zi0IGmLlfrM=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
Expand Down
3 changes: 2 additions & 1 deletion go/internal/config/ai.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func AIConfigFromEnv() (AIIntegrationConfig, error) {
return AIIntegrationConfig{}, err
}
return AIIntegrationConfig{
Provider: strEnv("PR_AF_PROVIDER", "opencode"),
Provider: strEnv("PR_AF_PROVIDER", "aforge"),
HarnessModel: strEnv("PR_AF_MODEL", "minimax/minimax-m2.5"),
// AI_MODEL falls back to PR_AF_MODEL, then to the code default.
AIModel: strEnv("PR_AF_AI_MODEL", strEnv("PR_AF_MODEL", "minimax/minimax-m2.5")),
Expand Down Expand Up @@ -90,6 +90,7 @@ func (c AIIntegrationConfig) ProviderEnv() map[string]string {
}
_ = os.MkdirAll(xdg, 0o755)
env["XDG_DATA_HOME"] = xdg
env["AGENTFIELD_AFORGE_COMMAND"] = strEnv("AGENTFIELD_AFORGE_COMMAND", "exec")
return env
}

Expand Down
7 changes: 5 additions & 2 deletions go/internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ func TestResolveBudgetCapsCascade(t *testing.T) {
func TestAIConfigFromEnvDefaults(t *testing.T) {
clearConfigEnv(t)
c := mustAIConfig(t)
if c.Provider != "opencode" {
t.Errorf("Provider = %q, want opencode", c.Provider)
if c.Provider != "aforge" {
t.Errorf("Provider = %q, want aforge", c.Provider)
}
// The CODE default is minimax — NOT the manifest's kimi default. env wins,
// but with no env this must be minimax (design §B.6).
Expand Down Expand Up @@ -238,6 +238,9 @@ func TestProviderEnv(t *testing.T) {
if env["XDG_DATA_HOME"] != xdg {
t.Errorf("XDG_DATA_HOME = %q, want %q", env["XDG_DATA_HOME"], xdg)
}
if env["AGENTFIELD_AFORGE_COMMAND"] != "exec" {
t.Errorf("AGENTFIELD_AFORGE_COMMAND = %q, want exec", env["AGENTFIELD_AFORGE_COMMAND"])
}

// With XDG_DATA_HOME unset, ProviderEnv falls back to a tmp dir and creates
// it.
Expand Down
2 changes: 1 addition & 1 deletion go/internal/harnessx/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func seedDefaults[T any]() T {
// router.harness (system_prompt, schema, model, provider, tools, cwd, max_turns,
// permission_mode).
type RoleOptions struct {
// Provider is the harness ADAPTER string, e.g. "opencode" (PR-AF's default),
// Provider is the harness ADAPTER string, e.g. "aforge" (PR-AF's default) or "opencode",
// "claude-code", "codex".
Provider string

Expand Down
2 changes: 1 addition & 1 deletion go/internal/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func resolvedHarnessBin(c config.AIIntegrationConfig) string {
// - PORT default "8007" -> ListenAddress ":8007".
// - AGENT_CALLBACK_URL -> Config.PublicURL — the base URL the CP uses to reach
// this node; unset falls back to the SDK's http://localhost:<port>.
// - HarnessConfig / AIConfig — the harness (opencode) + LLM credentials the
// - HarnessConfig / AIConfig — the selected harness + LLM credentials the
// reasoners rely on. Every reasoner calls the harness with only Cwd set, so
// the agent's default HarnessConfig Provider/Model must be present, and the
// two .ai() gates (intake/coverage) need AIConfig. Mirrors app.py's
Expand Down
8 changes: 7 additions & 1 deletion go/internal/node/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ func TestHarnessConfigProviderAwareBinary(t *testing.T) {
}{
{"codex uses SDK default", config.AIIntegrationConfig{Provider: "codex", OpencodeBin: "C:/bin/opencode-custom"}, ""},
{"opencode uses configured binary", config.AIIntegrationConfig{Provider: "opencode", OpencodeBin: "C:/bin/opencode-custom"}, "C:/bin/opencode-custom"},
{"aforge uses SDK default", config.AIIntegrationConfig{Provider: "aforge", OpencodeBin: "C:/bin/opencode-custom"}, ""},
{"generic override selects aforge", config.AIIntegrationConfig{Provider: "aforge", HarnessBin: "C:/bin/aforge-custom"}, "C:/bin/aforge-custom"},
{"generic override wins", config.AIIntegrationConfig{Provider: "codex", OpencodeBin: "C:/bin/opencode-custom", HarnessBin: "C:/bin/provider-custom"}, "C:/bin/provider-custom"},
{"generic override wins for opencode", config.AIIntegrationConfig{Provider: "opencode", OpencodeBin: "C:/bin/opencode-custom", HarnessBin: "C:/bin/provider-custom"}, "C:/bin/provider-custom"},
}
Expand Down Expand Up @@ -43,7 +45,11 @@ func TestHarnessConfigPreservesExistingFields(t *testing.T) {
if got.Provider != conf.Provider || got.Model != conf.HarnessModel || got.MaxTurns != conf.MaxTurns || got.PermissionMode != "auto" || got.BinPath != conf.OpencodeBin {
t.Errorf("harnessConfig fields = %+v", got)
}
if want := map[string]string{"OPENAI_API_KEY": "openai-key", "XDG_DATA_HOME": xdg}; !reflect.DeepEqual(got.Env, want) {
if want := map[string]string{
"OPENAI_API_KEY": "openai-key",
"XDG_DATA_HOME": xdg,
"AGENTFIELD_AFORGE_COMMAND": "exec",
}; !reflect.DeepEqual(got.Env, want) {
t.Errorf("Env = %#v, want %#v", got.Env, want)
}
}
Expand Down
3 changes: 2 additions & 1 deletion go/test/functional/compose.functional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ services:
- NODE_ID=pr-af
- PORT=8007
- AGENT_CALLBACK_URL=http://pr-af:8007
- PR_AF_PROVIDER=${PR_AF_PROVIDER:-opencode}
- PR_AF_PROVIDER=${PR_AF_PROVIDER:-aforge}
- AGENTFIELD_AFORGE_COMMAND=${AGENTFIELD_AFORGE_COMMAND:-exec}
- PR_AF_MODEL=${PR_AF_MODEL:-openrouter/moonshotai/kimi-k2.5}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-}
- GH_TOKEN=${GH_TOKEN:-}
Expand Down
Loading
Loading