Skip to content

Simplify OpenCode provider once upstream fixes headless mode (opencode#13851) #221

@santoshkumarradha

Description

@santoshkumarradha

Context

The OpenCode harness provider (sdk/python/agentfield/harness/providers/opencode.py) currently uses a serve+attach workaround to bypass a "Session not found" bug in opencode run headless mode (opencode#13851, affects v1.2.10–v1.2.16).

This workaround auto-spawns a long-lived opencode serve process on a random port and routes all calls through opencode run --attach <url>. This is architecturally problematic because:

  1. Process lifecycle in a request handler — each harness call runs inside a FastAPI reasoner endpoint. Having the provider auto-spawn and manage background server processes within a web server process introduces fragile process coupling.
  2. Port conflicts — random port allocation can collide in multi-process deployments (e.g., multiple Uvicorn workers).
  3. Cleanup edge casesatexit hooks don't fire on SIGKILL, leaving orphan opencode serve processes.
  4. Singleton shared state — class-level _serve_proc / _serve_url / _serve_lock are shared across all provider instances within a process, making the provider non-isolatable for testing and multi-tenant scenarios.
  5. ~160 lines of workaround code — vs. ~45 lines for a normal CLI provider (Codex/Gemini pattern).

Blocked on

  • opencode#13851opencode run "Session not found" in headless mode

Changes needed once upstream is fixed

1. Replace serve+attach with simple opencode run (~120 lines deleted)

Remove:

  • _find_free_port() helper
  • _serve_proc / _serve_url / _serve_lock class-level state
  • _get_lock() classmethod
  • _cleanup_serve() classmethod + atexit registration
  • _ensure_serve() async method (49 lines of serve lifecycle)
  • --attach flag construction in execute()
  • Extra imports: atexit, signal, socket, subprocess

Replace with:

cmd = [self._bin, "run"]
if options.get("model"):
    cmd.extend(["--model", str(options["model"])])
cmd.append(prompt)

This brings opencode.py from ~205 lines down to ~75 (matching Gemini/Codex pattern).

2. Evaluate project_dir necessity

The project_dir field on HarnessConfig was added because OpenCode's sandboxed Write tool couldn't reach files outside --dir. Once the provider simplifies:

  • Check if opencode run --dir <path> + cwd for output placement works without the temp subdir hack
  • If yes: remove the project_dir routing block from _runner.py (lines 148–158, 195–198) and the field from types.py
  • If --dir is still useful as a generic concept: keep it but document it as provider-agnostic

3. Remove opencode_server config field

The opencode_server field on HarnessConfig and OPENCODE_SERVER env var exist solely for the serve+attach pattern. Remove:

  • opencode_server field from types.py
  • "opencode_server" from _runner.py options list
  • server_url parameter from OpenCodeProvider.__init__
  • server_url passthrough from _factory.py

4. Re-evaluate system prompt injection

OpenCode doesn't support a native --system-prompt flag, so the provider currently prepends system instructions to the user prompt. Check if upstream adds system prompt support — if so, use the native flag instead.

5. Update tests

  • Remove/update any serve+attach specific test fixtures
  • Add simple opencode run subprocess mock tests matching Codex/Gemini pattern
  • Verify debug_complex_json.py works with the simplified provider

Expected outcome

After these changes, the OpenCode provider should be a ~75-line file matching the Codex/Gemini pattern — simple CLI subprocess invocation with no process lifecycle management. The ~160 lines of workaround code and ~38 lines of supporting config/routing would be removed.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:harnessCoding agent harness integrationenhancementNew feature or requestsdk:pythonPython SDK related

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions