Skip to content

Feat/bundle opencode cli - #3

Merged
ObsisMc merged 5 commits into
mainfrom
feat/bundle-opencode-cli
Aug 29, 2026
Merged

Feat/bundle opencode cli#3
ObsisMc merged 5 commits into
mainfrom
feat/bundle-opencode-cli

Conversation

@ObsisMc

@ObsisMc ObsisMc commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

The plugin no longer requires OpenCode to be installed on PATH. Each release
now ships one .orax per target triple with the CLI inside it at
assets/bin/opencode[.exe], and the host resolves that package-relative path
through the new `packageCommand` form of ora/childprocess/spawn.

A plugin cannot reliably compute a host path of its own: it is told none, and a
relative program combined with a cwd resolves against different directories per
platform while the child's cwd has to be the workspace anyway. Asking the host
to join the path is what removes that whole class of failure.

Because the CLI now ships with the package, "absent from this machine" stops
being a reachable state. AGENT_NOT_INSTALLED (-32001) therefore narrows to the
ORA_OPENCODE_BIN override only: a bundled binary that will not resolve means a
broken or wrong-target package, which fails identically on every retry and must
surface as a failing agent rather than be retried quietly forever.

handlers/models.ts stops shelling out through Deno.Command. It was already
bypassing host process management, and its not-found classification could never
match a Deno error, so the failure was silently degrading the model list to the
curated fallback. With a bundled CLI it would have broken outright.

Release packaging is split so the CI half stays reusable:

  bundle.config.ts    the only plugin-specific part: upstream repo + asset per target
  scripts/package.ts  generic engine; names no CLI, meant to be copied verbatim
  release.yml         checkout / build / package / release, nothing plugin-specific

scripts/package.ts reads and writes archives in-process (gh is the only external
tool) so a maintainer can produce and inspect real packages on any machine, not
just on a CI runner with zip and unzip.

src/services/bundled-binary.ts is the single source of truth for the in-package
binary path, shared by the runtime spawn and the packaging step so the two
cannot drift into a mismatch that would only surface as a broken install.

Requires @ora-space/plugin-sdk 0.5.0 for the packageCommand spawn form, and an
Ora build whose extractor preserves the execute bit and whose plugin install
budget admits a package this size.
Three follow-ups to the bundled-CLI change, none of which block on the SDK
release.

`deno.lock` carried a `links` block naming `@ora-space/plugin-sdk@0.5.0`. That
is local link state, written while overriding the unpublished SDK with a
checkout, and it has no business in the repository: CI's `deno.json` declares no
`links` at all. Both entries were `{}` besides, so it recorded no integrity hash
either. Removing it leaves the lockfile with no reference to the SDK, which is
the honest state until 0.5.0 is published and `deno install` can resolve it.

`host-simulator.ts` had no timeout on any step. A bundled binary that starts but
never speaks ACP — a wrong-target package, or anything that is not really the CLI
— left the run hanging forever with no output at all, which is a bad way to find
out. Each wait is now bounded and names the step it was waiting on:

  timed out after 90s waiting for ACP initialize; the CLI started but never
  answered

The bound is generous because a cold CLI start is genuinely slow; the point is
that it ends.

The README told readers `deno task simulate` verifies a build "against a locally
installed OpenCode CLI". That has been false since the CLI moved into the
package: the simulator resolves `packageCommand` against the repository root, so
it runs `assets/bin/` and never anything on PATH. It also omitted that the
binary has to be staged there first, so following it led straight into the hang
above. It now says which binary runs and how to put it there.
The repository had only a release workflow, so nothing validated a pull request
and `deno task check` / `deno task lint` were enforced by nobody but the person
running them locally.

The job runs the repository's own tasks rather than spelling out commands, for
the same reason `release.yml` delegates to `scripts/package.ts`: a plugin
scaffolded from this one gets working CI by copying the file, without inheriting
this plugin's file layout.

Type checking will fail until @ora-space/plugin-sdk 0.5.0 is published, because
resolving the module graph is what fetches it. That is left visible on purpose —
it is the same blocker that stops this branch from cutting a release, and a gate
that stayed green through it would be worth nothing. Lint resolves nothing and
passes today, so it keeps working in the meantime.
0.5.0 is published, so the specifier the repository already declared now
resolves and the lockfile can record it with a real integrity hash instead of
carrying no reference to the SDK at all.

This is the last thing that was blocking the branch: `deno task check`,
`deno task build`, and therefore the CI workflow and the release workflow all
run now.
@ObsisMc
ObsisMc merged commit 04bd61a into main Aug 29, 2026
1 check passed
@ObsisMc
ObsisMc deleted the feat/bundle-opencode-cli branch August 29, 2026 03:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant