Repository navigation
Make CodeAF the default harness, installed automatically with AgentField - #1128
Merged
Merged
Conversation
…ed install CodeafProvider runs `codeaf exec --json --dir <root>` (or `do` via AGENTFIELD_CODEAF_COMMAND), parses CodeAF's current envelope and exit ladder, and isolates its state under $AGENTFIELD_HOME/codeaf. The binary is resolved lazily: explicit override, CODEAF_BIN, the managed $AGENTFIELD_HOME/bin/codeaf, a checksum-pinned download of CodeAF v0.8.2, PATH, and finally a legacy aforge binary. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…alias Provider-less calls now run CodeAF. `provider="aforge"` keeps working and runs CodeAF too, unless a legacy binary is pinned with AFORGE_BIN or aforge_bin, which keeps the original aforge adapter. Harness results carry the provider that actually ran so usage is attributed correctly. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…anaged install CodeafProvider runs CodeAF headless (`exec` by default, `do` via AGENTFIELD_CODEAF_COMMAND), parses the current envelope and exit ladder, and resolves the binary lazily, downloading the checksum-pinned v0.8.2 release into $AGENTFIELD_HOME/bin when it is missing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… an alias Provider-less calls run CodeAF. 'aforge' still works and runs CodeAF unless aforgeBin or AFORGE_BIN pins the legacy binary. Usage is attributed to the provider that actually ran. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nstall ProviderCodeAF runs CodeAF headless (`exec` by default, `do` via AGENTFIELD_CODEAF_COMMAND), maps its current envelope and exit ladder onto harness results, and resolves the binary lazily, downloading the checksum-pinned v0.8.2 release into $AGENTFIELD_HOME/bin when missing. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DefaultProvider is now ProviderCodeAF. ProviderAforge still works and runs CodeAF unless Options.BinPath or AFORGE_BIN pins the legacy binary, which keeps the original aforge adapter. Usage follows the provider that ran. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
internal/codeaf installs the CodeAF v0.8.2 release binary into $AGENTFIELD_HOME/bin, verified against embedded SHA-256 pins, with a lock, a version marker and the AGENTFIELD_SKIP_CODEAF / AGENTFIELD_SKIP_AFORGE opt-outs. `af aforge ensure` is unchanged. Both doctors gain a codeaf row. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…l and af run The skill catalog install now provisions CodeAF instead of aforge, and `af install` / `af run` repair a missing CodeAF best-effort, so upgrading af alone is enough to get the default harness. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
install.sh / install.ps1 provision CodeAF (opt out with --no-codeaf / -NoCodeaf; the old aforge opt-outs still work). The python, go and cloud images bake the pinned CodeAF binary and fail the build if it cannot be verified; the aforge stage stays as a rollback hatch. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e homes and proxies A failed lookup or download is no longer cached for the life of the process: later calls re-check every location and retry the download at most once a minute. CodeAF's state falls back to a private temp directory when $AGENTFIELD_HOME is read-only, the doctor honours CODEAF_BIN, and downloads go through HTTP(S)_PROXY with NO_PROXY support. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…empty env values Failed lookups and downloads are no longer cached for the life of the process; later calls re-check every location and retry the download at most once a minute. CodeAF's state falls back to a private temp directory when $AGENTFIELD_HOME is read-only, and an explicitly empty per-call variable (such as CODEAF_TELEMETRY_ENDPOINT="") now reaches the CodeAF child instead of being dropped. Legacy adapters keep their existing env handling. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… homes Failed lookups and downloads are no longer cached for the life of the process; later calls re-check every location and retry the download at most once a minute, and a truncated download now falls through to PATH and the legacy binary instead of raising. CodeAF's state falls back to a private temp directory when $AGENTFIELD_HOME is read-only, and the doctor honours CODEAF_BIN and the temp-managed binary in the same order as execution. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…install `af run` no longer waits: when CodeAF is missing it starts a detached `af codeaf ensure` in the background and launches the agent immediately. `af install` and skill installs honour the command context and give up on a busy install lock after 30 s. Downloads go through HTTP(S)_PROXY, and the doctors find CODEAF_BIN and the managed binaries in the same order as execution. `af codeaf ensure --bin-dir` installs beside a custom af. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… and custom installs The installers resolve a single managed home for the whole run (staging, explicit AGENTFIELD_HOME, or ~/.agentfield) and pass it to every child, so a staging install no longer downloads CodeAF twice, and a custom install directory gets CodeAF beside af. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ecked The temp-directory fallbacks for the binary and its state now live under <tmp>/agentfield-codeaf-<uid> and are only used when the directory is a real directory owned by the current user with mode 0700, so another local user cannot plant a binary or share the state directory. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The temp-directory fallbacks for the binary and its state now live under <tmp>/agentfield-codeaf-<uid> and are only used when the directory is a real directory owned by the current user with mode 0700, so another local user cannot plant a binary or share the state directory. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The temp-directory fallbacks for the binary and its state now live under <tmp>/agentfield-codeaf-<uid> and are only used when the directory is a real directory owned by the current user with mode 0700. An existing shared or world-writable directory is no longer accepted. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…per-user temp copies `af run` now takes a cross-process lease before starting the background `af codeaf ensure`, so many launches while a download is in flight start one installer, and a failed attempt is not retried automatically for ten minutes. The child is reaped instead of released. The doctors read the temp fallback only from an owner-checked per-user directory, and `--bin-dir` is gone: CodeAF always installs into $AGENTFIELD_HOME/bin. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Custom install directories no longer get a second copy beside af; the skill hook and the explicit ensure now target the same file, so a fresh install downloads CodeAF exactly once. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…before reading stdin A provider CLI that fails at startup (a missing key, a bad flag) can close its stdin before the prompt is written. The write error was unhandled and surfaced as an uncaught exception in the agent process; the exit code and stderr already report the failure, so the stream error is now ignored. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
| response.end(bytes); | ||
| } | ||
| if (kind === 'http') response.writeHead(404).end(); | ||
| if (kind === 'redirect-loop') response.writeHead(302, { location: request.url }).end(); |
Contributor
Performance
⚠ Regression detected:
|
Contributor
📊 Coverage gateThresholds from
✅ Gate passedNo surface regressed past the allowed threshold and the aggregate stayed above the floor. |
Contributor
📐 Patch coverage gateThreshold: 80% on lines this PR touches vs
✅ Patch gate passedEvery surface whose lines were touched by this PR has patch coverage at or above the threshold. |
Member
|
@AbirAbbas can we do a round of checks for sweaf and praf as well ? 🙏🏻 |
install.sh and install.ps1 are served from main but install the latest stable af. Until that release has `af codeaf`, `af codeaf ensure` fails and the machine ended up with no harness at all, while the released SDKs still default to aforge. Detect the command in `af --help` and, when it is missing, provision aforge exactly as earlier installers did. install.ps1 also stops changing AGENTFIELD_HOME and the skip variables in the caller's session (iwr | iex runs in that scope), keeps main's install directory, and drops the -Staging switch it never had before. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The classic (non-BuildKit) builder leaves TARGETARCH unset, which made the fail-closed CodeAF stage exit with "Unsupported architecture". Fall back to dpkg --print-architecture. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
af run no longer spawns a detached `af codeaf ensure` (and its lease and failure cooldown files); the curl installer, skill install, `af install`, Desktop and the SDKs' own lazy download already provision CodeAF, so af run is byte-identical to main again. The CLI lookup and doctors also stop consulting the per-user temp directory, which the SDKs no longer use. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Remove the per-user temp-directory fallback. An unwritable home bin directory is now an ordinary download failure (reported in the unavailable error, retried at most once a minute), and CODEAF_HOME is created best-effort without a temp fallback. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Same change as the Python SDK: no temp-directory fallback for the binary or for CODEAF_HOME. Without any home directory, CODEAF_HOME is left to CodeAF's own default instead of a cwd-relative path. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…fallback The downloader is a plain https.get with redirects again. When HTTPS_PROXY is set the SDK skips the download (a direct attempt would hang) and points at `af codeaf ensure`, which honors proxies. The per-user temp-directory fallback is removed as in the other SDKs. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An older af's `aforge ensure` fallback only knows AGENTFIELD_SKIP_AFORGE, so AGENTFIELD_SKIP_CODEAF=1 still downloaded aforge there. Treat either skip variable as CODEAF_MODE=none up front, as install.sh already does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… the timeout - No provider named + a legacy pin (AFORGE_BIN, aforge_bin) keeps the legacy aforge adapter, as on main, instead of switching to CodeAF. - AGENTFIELD_AFORGE_COMMAND and AFORGE_MODEL are honored when the CodeAF variables are unset (per-call env first), so the alias no longer replaces a chosen command or model with the defaults. - The harness timeout now covers waiting for the first-use download; a caller that runs out of time gets a timeout result while the shared download keeps going for later calls. Execution gets the remaining budget. - harness_doctor reports what provider 'aforge' would actually run. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…across downloads Same compatibility rules as the Python SDK (implicit default + AFORGE_BIN or Options.BinPath keeps the aforge adapter; legacy command/model fallbacks; timeout covers provisioning; doctor follows the alias). Explicit binaries no longer wait on the resolver lock, and callers waiting for a shared download honor their own context. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…g by the timeout Same compatibility rules as the Python and Go SDKs: implicit default + AFORGE_BIN or aforgeBin keeps the aforge adapter, legacy command/model fallbacks, the timeout covers first-use provisioning, and the doctor follows the alias. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Without AFORGE_BIN the aforge provider runs CodeAF, so the doctor checks CodeAF first and falls back to the legacy binary; with AFORGE_BIN it checks that binary. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…fig; doctor honors CODEAF_BIN A HarnessConfig whose provider was filled from AGENTFIELD_HARNESS_PROVIDER at construction keeps that provider (as on main) instead of being treated as the implicit default. The aforge doctor no longer falls back to the legacy binary when an explicit CODEAF_BIN is missing, matching execution. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…commands, doctor honors CODEAF_BIN Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s CODEAF_BIN Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The F3c tests compared two timestamps taken at different moments with 10-50 ms tolerances, which failed under load (seen locally with coverage on). Assert the ordering instead: at least the provisioning time is deducted from the budget, and the inner CodeAF timeout is the remaining budget minus five seconds, taken no later than the outer one. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
4 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CodeAF (the renamed aforge-v2, Agent-Field/CodeAF) becomes the default harness in the Python, Go and TypeScript SDKs, and it is installed automatically wherever AgentField is. A provider-less
app.harness(...)call runscodeaf exec --jsonheadless with nothing else to set up.New
codeafprovider in all three SDKs. It runscodeaf exec --json --dir <root>with the prompt on stdin (AGENTFIELD_CODEAF_COMMAND=doopts intocodeaf do). It reads CodeAF's current envelope (ok,stop,answer,spend_usd,tokens,model) and exit codes rather than the legacy aforge fields CodeAF keeps for one more release.Nothing a user already chose changes.
provider="aforge"(orAGENTFIELD_HARNESS_PROVIDER=aforge) is an alias that runs CodeAF.provider="aforge"and when no provider is named (as on main). The pins areAFORGE_BIN, Pythonaforge_bin, TSaforgeBin, and GoOptions.BinPathwith the default provider.AGENTFIELD_AFORGE_COMMANDandAFORGE_MODELare honored as fallbacks forAGENTFIELD_CODEAF_COMMANDandCODEAF_MODEL.Pinned, checksum-verified binary. CodeAF v0.8.2 is pinned, with all six release assets' SHA-256 embedded in each SDK and in
af. It installs only into$AGENTFIELD_HOME/bin/codeafand never touches a user's own CodeAF.Installed by every path that installs AgentField:
install.sh/install.ps1af skill install --allaf installaf codeaf ensure, the explicit commandThe installers are served from
mainbut install the latest stableaf. When thatafhas nocodeafcommand yet, they provision aforge exactly as before, so there is no gap between merging this and the next stable release. Opt out with--no-codeaf,-NoCodeaforAGENTFIELD_SKIP_CODEAF=1; the old aforge opt-outs still work.Quiet and isolated in automation.
$AGENTFIELD_HOME/codeaf.CI,DO_NOT_TRACKorAGENTFIELD_TELEMETRY_ENABLED=false.~deepseek/deepseek-v4-flash-latest.Behavior (validation contract)
harness=codeaf. An explicit provider orAGENTFIELD_HARNESS_PROVIDERstill wins, and a blank value is ignored.aforgewithout a pin runs CodeAF and logs one line. With a pin, it runs the legacy adapter unchanged.CODEAF_BIN, then the managed binary, then a pinned download, then PATH, then a legacy aforge binary (with a warning). If none is found, an "unavailable" error suggestsaf codeaf ensureand includes the download error.$AGENTFIELD_HOME/binis reported as a download failure.done→ successdeadline→ timeoutunchecked,budgetorturn-capwith an answer → success, logged as partialquestion,incomplete,errororprice→ failure carrying CodeAF's own error textaf doctor,af harness doctorand the SDK doctors) use the execution lookup order and never download. Foraforge, they report what would actually run.Rollback and compatibility
AFORGE_BIN=<path>to pin the old harness per process.af aforge ensureand its download mirror are unchanged.provider="aforge"without a pin, so after they pick up this SDK they run CodeAF through the alias. Follow-up PRs in each repo raise the SDK floor and ship CodeAF in their images.Testing
Every run below uses the real CodeAF v0.8.2 and aforge v0.1.0 binaries. The model was a local OpenAI-compatible endpoint (Ollama, qwen3:14b, via
CODEAF_BASE_URL), so no paid model was involved.codeaf.exeand completes the same run.app.harness()/agent.Harness()through the control plane, the result comes back through the execution API, andexecution_usagerecordsharness=codeafwith token counts.AFORGE_BIN(both run aforge v0.1.0)AFORGE_MODELalone selects the model;AGENTFIELD_AFORGE_COMMAND=dolaunchescodeaf dowith all seats pinnedHTTPS_PROXYset for TypeScript, a missingCODEAF_BINaf codeaf ensure: concurrent installs (one download), idempotent,--force, opt-outaf harness doctor/af doctoraf aforge ensureunchangedinstall.shwith stableafv0.1.142 → installs aforge; with this branch'saf→ installs CodeAF;--no-codeaf→ installs neitherinstall.ps1on Windows PowerShell 5.1 with main's and this branch'saf.exe: both paths work, the caller's session env is untouched, and the skip variables are honoredTARGETARCH; the cloud image is built and smoke-tested in CI.-raceon the new resolver testsNot covered or not fully covered:
codeaf do: launched correctly from the SDK, but a 14B local model does not converge ondowithin ten minutes, so it was not run to completion.TestDispatchAgentRequestStopsWaitingOnceTheNodeIsDemotedfails intermittently onmaintoo (2 of 10 runs).main's SDK behaves identically (tested with a fake harness binary). The status handler returns early on an already-terminal execution before ingesting usage, which is the likely cause. Go agents are not affected. Worth a separate fix.🤖 Generated with Claude Code