Skip to content

fix(opencode): define the v2 explore subagent inline and stop advertising phantom agents - #1188

Merged
catatafishen merged 1 commit into
catatafishen:masterfrom
BambinoSK:fix/opencode-v2-agent-surface
Oct 17, 2026
Merged

catatafishen merged 1 commit into
catatafishen:masterfrom
BambinoSK:fix/opencode-v2-agent-surface

Conversation

@BambinoSK

Copy link
Copy Markdown
Contributor

Fixes #1187.

Problem

On OpenCode v2 the connector advertises an Explore subagent that cannot work, and the Agent menu lists agents that do not exist. See #1187 for the full analysis: the IDE-integrated explore prompt never reaches a v2-readable location (it was written for v1's deploy-to-directory mechanism), and v2's built-in explore is toolless in this plugin's sessions because the plugin's own config denies the native tools while the built-in has no execute permission (the only reachability path for MCP tools in v2 Code Mode). The menu's built-in list is a v1-era snapshot (general and explore are Task-tool subagents on v2, scout does not exist), and user-level custom agents from the global agent directories never appear in the dropdown even though the agent advertises them as selectable modes.

What this PR does

  • Injects the explore subagent inline for v2+. When the probed OpenCode version is v2 or later, the launch config (OPENCODE_CONFIG_CONTENT) gains an agents.explore entry: mode: subagent, no model key (inherits the session model), the bundled prompt as a plain system string with its v1 frontmatter stripped, and permissions as a v2 Ruleset array: execute allowed first, the 18 read-only agentbridge_* MCP tools allowed, the 7 mutating ones denied, edit/write/patch/bash/shell denied. Config-agent rules merge after the built-in policy, last-match-wins, so the injected rules win for every action they cover and the built-in catch-all deny blocks uncovered MCP actions. The version probe result is cached and reused when building the config, so v1 and unknown versions keep the existing behavior.
  • Stops advertising phantom agents. On v2+ the built-in list is only build and plan (the primary session modes); general, explore, and scout are dropped from the menu. The explore subagent stays available to the model through the injected config. v1 and unknown versions keep the full list.
  • Lists user-level custom agents. The dropdown now also scans both global agent directories v2 reads, ~/.opencode/agents and ~/.config/opencode/agents, with OpenCode's own precedence: ~/.opencode wins over the XDG dir on slug collisions, a project agent wins over a same-slug global one, and built-ins are never shadowed (enforced in the merge itself). This also fixes the near-duplicate Mode and session-option sections that leaked into the menu whenever a global custom agent made the agent list and the advertised mode values diverge.

Notes for reviewers

  • The agent entry uses exactly the fields the v2 config schema defines for agents entries (description, mode, permissions, system; additionalProperties: false), and the ruleset is the documented ordered array of {action, resource, effect}.
  • The write/patch/bash denies duplicate edit/shell coverage under v2 action naming; they are kept as defense in depth and are normalized by the runtime.
  • write/patch/bash denies and the top-level v1-style permission map are accepted and normalized by v2.0.27 even though current docs prefer edit/shell and a top-level permissions array; the top-level map is pre-existing behavior left unchanged here.
  • Frontmatter stripping locates the closing fence by line scan (a --- inside the prompt body survives); an unclosed fence is treated as malformed and skips the injection rather than leaking YAML into the prompt.
  • 6 files, +653/-38.

Verification

  • :plugin-core:test batches run green on the squashed commit: OpenCodeInlineAgentConfigTest (8/8, including an exact 31-rule pin and a loop over all 7 mutating denies), OpenCodeClientStaticMethodsTest (30/30), ProjectAgentScannerDirectoryScanTest (4/4), OpenCodeClientBehaviorTest (11/11), plus OpenCodeVersionProbeTest and ProjectAgentScannerTest.
  • The injected config was fed to a real OpenCode v2.0.27 binary (opencode debug agents) and the merged permission chain inspected: agent rules appended last, execute allowed, mutating tools denied, uncovered actions blocked by the built-in catch-all deny.
  • The explore subagent was spawned in a live IDE session on OpenCode v2.0.27: the task completed and every tool call it made was read-only.

How to verify the interactive behavior

  1. In an OpenCode v2 session, ask the agent to research part of the project with the explore agent. Expected: the subagent task completes and reports findings.
  2. Ask it (via the explore subagent) to modify a file. Expected: refusal, the mutating tools are denied.
  3. Open the Agent menu. Expected on v2: Build, Plan, plus project and user-level custom agents only; no General, Explore, or Scout entries, and no duplicate Mode/session-mode sections.
  4. Add a <name>.md agent to ~/.config/opencode/agents and reopen the menu. Expected: it appears in the Agent section.

Closes #1187

…sing phantom agents

The advertised Explore subagent cannot work on OpenCode v2: the bundled
prompt was written for v1's deploy-to-directory mechanism and never
reaches a v2-readable location, and v2's built-in explore is toolless
in this plugin's sessions (no execute permission, native tools denied
by the plugin's own config). The client now injects the IDE explore
definition inline via OPENCODE_CONFIG_CONTENT when the probed version
is v2+: mode subagent (inherits the session model), a Ruleset
permissions array (execute allowed first, the 18 read-only
agentbridge_* tools allowed, the 7 mutating ones plus
edit/write/patch/bash/shell denied), and the bundled prompt as system
with the v1 frontmatter stripped. Config-agent rules merge after the
built-in policy, last-match-wins (verified via opencode debug agents
on v2.0.27); v1 and unknown versions keep the existing config.

The Agent menu's built-in list is also v1-era: on v2 only build and
plan are primary modes (general and explore are Task-tool subagents,
scout does not exist), so those three are dropped on v2+. Custom
agents are now also picked up from both user-level global directories
(~/.opencode/agents and ~/.config/opencode/agents, the former winning
on slug collisions; project agents override globals, built-ins are
never shadowed).
@github-actions

Copy link
Copy Markdown

⚠️ ClusterFuzzLite — Maintainer Security Review Required

A maintainer needs to approve the ClusterFuzzLite PR fuzzing workflow run for this fork PR.

Before approving, please review the code changes from BambinoSK/agentbridge@b6ba210d to confirm there is no code that could:

  • Exfiltrate the CFLITE_STORAGE_REPO_TOKEN CI secret
  • Abuse CI infrastructure or the fuzz corpus storage repository

The fuzz targets from the fork branch will be compiled and executed with access to repository secrets. Rubber-stamping this approval without reviewing the code is a security risk.

This comment is posted automatically whenever ClusterFuzzLite is triggered on a fork PR.

@codecov

codecov Bot commented Oct 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.27273% with 14 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...afishen/agentbridge/client/acp/OpenCodeClient.java 87.91% 8 Missing and 3 partials ⚠️
...en/agentbridge/client/acp/ProjectAgentScanner.java 84.21% 2 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@catatafishen
catatafishen merged commit 2fd2bb4 into catatafishen:master Oct 17, 2026
19 of 20 checks passed

This branch is waiting to be deployed

1 waiting deployment
fuzzing-gate — b6ba210d Waiting Oct 16, 2026 by BambinoSK via Maintainer approval gate (fork PR) #1639
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.

OpenCode v2: the advertised Explore agent cannot work and the Agent menu lists agents that do not exist

2 participants