Skip to content

OpenCode V2 support: register the Berget Code seat logins as V2 OAuth methods #44

Description

@klovaaxel

Summary

OpenCode V2 (@opencode/cli 2.x) does not load V1 plugins, and its built-in berget integration only accepts an API key. Berget Code seat users on V2 therefore have no way to sign in, and a seat token expires with no refresh path.

I hit this myself, so I went ahead and built a port to make it work for me: one new file that registers the two existing Berget Code seat logins as OAuth methods on V2's built-in berget integration, reusing the current flows and refresh code unchanged.

The branch is public and ready — would you like me to open a PR? klovaaxel/opencode-berget-auth @ feat/opencode-v2

I would also genuinely like to know whether a plugin is the right layer for this at all (see the first question below) — if you'd rather handle V2 in the integration itself, the issue is still worth having and the work is disposable.

The problem

  • V2 ignores V1 plugins, so this package's server() entrypoint is never called.
  • V2's built-in Berget integration offers API-key auth only.
  • Seat tokens are short-lived. Without the plugin registering a refresh path, a seat user has to re-authenticate by hand.

What I built

One new file, src/v2.ts, that:

  • registers both seat methods (berget-code-browser, berget-code-device) on V2's built-in berget integration via context.integration.transform
  • hands V2 a refresh function, so V2 owns credential storage and refresh
  • reuses createPkceAuthorizeMethod and createDeviceAuthorizeMethod unchanged

index.ts gets a single default export that serves both runtimes: V2 reads id + setup, V1 reads server().

@opencode/plugin 2.0.16 is added as a devDependency, types only, so V1 installs pull in nothing new.

Nothing about the existing V1 flow, token handling or model logic changes.

Open questions

  1. Is a plugin-registered OAuth method the intended extension point here? If Berget would rather ship this inside the V2 integration itself, a PR from me is unnecessary — this issue is still worth tracking.

  2. baseURL handling. The port sets the provider baseURL to the Berget inference URL on every load, matching what the V1 plugin already does. In V2 that overwrites a user's own baseURL override. I left it as-is to keep this to a single concern, but it may deserve its own change.

  3. Lockfile growth. @opencode/plugin adds roughly 3,600 lines to package-lock.json. It is a dev-only types package, but flagging it in case that matters to you.

  4. Worth knowing if you do this in the integration: the V2 plugin API is thinly documented, and dev does not match 2.0.16. I worked from the @opencode/plugin 2.0.16 type definitions. If the plugin API is still moving, that may argue for waiting rather than for a plugin.

Testing

Full check suite run in a clean LF clone of the branch:

Check Result
npm ci pass
npx tsc --noEmit pass
npm test 75 passed, 7 files
npm run lint pass
npm run format:check pass

Nine of those are new tests in src/v2.test.ts, covering credential mapping, token refresh, V1-flow-to-V2-method adaptation, setup() registration, and the dual-runtime default export.

Manually on OpenCode 2.0.16 (Windows, vendored plugin):

  • Berget Code seat sign-in completes through the V2 plugin path. The issued token is a seat token (azp: berget-code, realm role berget_code_seat).
  • berget/zai-org/GLM-5.3-Flash answers prompts end to end, both against the background service and --standalone.
  • V2 stores the credential under this plugin's methodID (berget-code-browser) and persists the refreshed token, so a seat session survives the 15-minute access token without re-authenticating.
  • POST /v1/auth/refresh returns a new access token with expires_in: 900 and a rotated refresh token; the old refresh token still works on reuse, so the rotation is non-destructive. The plugin already carries the rotated token forward when the server sends one (src/plugin/token.ts).

Not tested by hand: the device/QR flow, which needs a second device. It shares the code path with the browser flow and is covered by the same unit tests, but I have not driven the QR flow.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions