Official

opencode-v2

OpenCode 2 agent provider: runs opencode serve (2.x) and talks to its /api over HTTP and server-sent events.

The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/opencode-v2@0.1.0

Permissions in 0.1.0

  • Provide agents agents.provideMediumAdds agents to the app.Provide the OpenCode 2 agent, and serve plugin tools to it through the host's loopback MCP server
  • Run named programs processMediumStarts the listed programs.Run the OpenCode 2 server (`opencode serve`, or the binary you choose in Settings) and read its versionPrograms: opencode${settings.binaryPath}
  • Network access netMediumConnects to the listed hosts.Talk to the OpenCode server it starts on this computer, at the port it picks for each launch, and to the external server you choose in SettingsHosts: localhost:*${settings.serverUrl}
  • Environment variables envMediumReads the listed environment variables.Read the user name and password of the OpenCode serverVariables: OPENCODE_SERVER_USERNAMEOPENCODE_SERVER_PASSWORDCONVERGENCE_OPENCODE_SERVER_PASSWORD

Files

main.ts2.3 KB
// The OpenCode 2 provider plugin: one agent, on the `opencode serve` this
// plugin starts or on a server the user runs (see agent.ts and NOTES.md).
import * as Effect from "effect/Effect";
import * as Scope from "effect/Scope";
import * as Stream from "effect/Stream";
import * as z from "zod";
import { Agents, Env, Settings, runPlugin } from "convergence/effect";
import { OpenCodeV2Agent } from "./agent.ts";
import type { Config } from "./agent.ts";

/// The login environment the agent reads: the server's credentials.
export const ENV_VARS = [
  "OPENCODE_SERVER_USERNAME",
  "OPENCODE_SERVER_PASSWORD",
  "CONVERGENCE_OPENCODE_SERVER_PASSWORD",
];

const loginEnv = Effect.fn("OpenCodeV2.loginEnv")(function* () {
  const env = yield* Env;
  const values: Record<string, string> = {};
  for (const name of ENV_VARS) {
    const value = yield* env.get(name);
    if (value) values[name] = value;
  }
  return values;
});

const setting = z.string().nullish();

/// The binary and server address chosen in Settings; empty means the
/// `opencode` on the login PATH and a server this plugin starts.
const readConfig = Effect.fn("OpenCodeV2.readConfig")(function* () {
  const settings = yield* Settings;
  const binaryPath = yield* settings.get("binaryPath", setting);
  const serverUrl = yield* settings.get("serverUrl", setting);
  return { binaryPath: binaryPath || null, serverUrl: serverUrl || null } satisfies Config;
});

/// Registers the agent and keeps it in step with its settings. `agents`
/// receives the agent, for lifecycle tests.
export const registerAgent = Effect.fn("OpenCodeV2.registerAgent")(function* (agents: OpenCodeV2Agent[] = []) {
  const scope = yield* Scope.Scope;
  const settings = yield* Settings;
  const agent = new OpenCodeV2Agent(scope, yield* readConfig(), yield* loginEnv());
  const registration = yield* (yield* Agents).register(agent.definition());
  agent.emit = registration.emit;
  agents.push(agent);
  yield* settings.changes.pipe(
    Stream.filter((change) => change.key === "binaryPath" || change.key === "serverUrl"),
    Stream.runForEach(() => readConfig().pipe(Effect.flatMap((config) => agent.reconfigure(config)))),
    Effect.forkIn(scope),
  );
  yield* Effect.addFinalizer(() => agent.shutdown());
});

export const activate = runPlugin(registerAgent());

Versions

VersionPublishedPlugin APISizePermissionsStatus
0.1.0latestOct 5, 2026>=2 <345.1 KB4 permissionsListed

Reviews and comments

0 threads · 0 reviews

No comments yet.