Skip to content

feat: support OpenCode V2 alongside V1 - #87

Merged
jumski merged 4 commits into
mainfrom
compat/opencode-v2
Oct 30, 2026
Merged

jumski merged 4 commits into
mainfrom
compat/opencode-v2

Conversation

@jumski

@jumski jumski commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Existing package entrypoints
├── ./server
│   ├── V1 server → existing local OAuth storage
│   └── V2 effect → native integration → current account → shared tools
└── ./tui
    ├── V1 tui → existing /supabase flow
    └── V2 setup → /supabase
        ├── disconnected → browser authorization → onboarding
        └── connected → Continue with current account / Disconnect current account

V2 native /connect → Supabase account management (add / switch / rename / remove)

Builds on Rafael Santos (@rafaelsnv) and his initial V2 migration in PR #79. Thanks for starting the migration. This maintainer follow-up completes the dual-host entrypoints, native V2 credential lifecycle and /supabase port; it does not merge #79 as-is.

  • Preserve V1 behavior and real Zod tool schemas; reuse the broker, Management API tools, bundled skills and onboarding message.
  • Resolve V2 tool auth through the active host connection, refresh the supplied account, and deduplicate concurrent refreshes without mixing accounts.
  • Scope OAuth cleanup to its attempt and Location; do not write a second V1 credential copy on V2.
  • Use V2's native selection component for the plugin-defined connected dialog. Limit it to Continue and confirmed Disconnect; defer the plugin-authored multi-account chooser because it extends compatibility scope without stakeholder review. V1 keeps its existing dialog. V2's /connect manages service integrations, including Supabase, not only model providers.
  • Add V2 2.0.27 to required packed-TUI CI, correct the plugins config key, prune V2's npm cache before diagnostic uploads, and document install/migration behavior with a minor changeset.

Evidence

  • Before: the published snapshot of feat: port to V2 plugin API with plugin-compat layer #79 (94edb4c) installs on OpenCode 2.0.27, but two isolated TUI runs select the legacy src/server/index.ts export and reject it with Plugin must export a default definition with an id and an effect or setup function. /supabase never registers.
    After: the current implementation tarball loads and renders /supabase confirmation plus the pending-browser dialog on V1 1.17.14 and V2 2.0.27. Both use the same artifact (SHA-256 2384c64bd9e155cf48b48934304859b883e42fa2c8e08f2a99935e1dc6c4b312). The V2 check disables ancestor project-config discovery and uses fresh HOME/XDG directories.
  • Local checks at 3324f53: bun run lint, bun run typecheck, bun run test (214 pass, 0 fail), and bun run verify:pack pass.
  • Current packed V2 connected-state check: an isolated profile with synthetic credentials renders exactly Continue/Disconnect. Cancelling disconnect preserves both connections; confirmation removes only the current credential, activates the host-selected replacement, and can remove the final connection. Native /connect lists Supabase, shows its account manager, and opens the existing rename input. No live credentials or provider API calls are used by this check.
  • Regression coverage: current-account auth versus local tokens, disconnected-host rejection, account-specific/concurrent refresh, Zod validation, cross-Location cleanup, per-attempt cancellation, no V2 local credential copy, the two-action menu, confirmed current-only removal, failure cleanup and TUI disposal.
  • Registry/live evidence for earlier snapshot 4df7906: opencode-supabase@0.6.0-pr87.20261014t072939z.sha.g4df7906cef32 under pr87 matches its prepared tarball byte-for-byte and passes V1 1.17.14 / V2 2.0.27 TUI smoke. User reports successful browser OAuth, organization/project calls through plugin tools, restart persistence without another login, and another successful login. This snapshot still contains the earlier four-action menu; it is not the current narrowed UI. latest and beta remain unchanged.

All CI checks for current head pass: build/source checks, changeset, the same packed artifact across V1 1.17.4, V1 1.17.14, and V2 2.0.27, Windows V1 install smoke, and the required core aggregate.

Still unchecked: live token refresh, live-account disconnect, Windows V2 behavior, and registry installation of the narrowed 3324f53 UI. Synthetic disconnect checks are not live OAuth lifecycle evidence. No stable release accompanies this PR.

Merge Danger

Door: two-way

Code can be reverted. V2 credentials live in the native host integration store by design; this is not a requirement for all V2 plugins. V1 project-local credentials are not imported automatically. Users must reconnect on V2. A rollback does not copy native V2 credentials into the V1 local store.

Blast Radius: integration

Both server and TUI entrypoints, OAuth lifecycle and host dependencies change. The active Supabase account is shared by projects using the same OpenCode profile, not bound to a repository. Disconnect removes only the named current credential and does not revoke Supabase authorization; OpenCode activates another saved account if one exists, and the confirmation warns about this. Removing our chooser does not disable native multi-account management or change credential scope.

Complete the remaining live lifecycle checks and final review before stable-release approval.

Refs #79.

jumski added a commit that referenced this pull request Oct 14, 2026
Remove Connect another account and Choose account from /supabase. Those plugin-defined actions expanded the compatibility migration into an account-management feature without stakeholder review.

Keep Continue with current account and confirmed Disconnect current account. OpenCode V2 already provides add, switch and rename in its native /connect integration UI; retain active-credential resolution, account-specific refresh and isolation safeguards.

Document native dialog ownership and global account scope. Disconnect names the credential and warns when the host will activate another saved account; regressions cover cancellation, current-only removal and the two-action menu.

Refs #87
@jumski

jumski commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator Author

Release plan — reference only

Use the single active acceptance checklist. This is not a second set of tests.

This older comment combined release policy, automated/synthetic evidence, test setup, Linux/Windows/V1 manual checks, and merge/release approvals. The newer walkthrough repeated the manual part.

The audit carries across the nine maintainer-checked Windows steps: install/login, plugin API calls, Continue, restart, cancellation, disconnect, disconnected rejection, and reconnect. Four formerly open Windows summary items and registry identity are now recorded complete below. Windows refresh remains open. The original five source/CI/synthetic/documentation checks stay complete at their named source; they do not need manual repetition.

The diagnostic publication actually used the separately approved beta route, not the original pr87-only route. The active checklist records the exact published version and tarball identity.

Outstanding work now appears only as R1–R5 in the active comment. Full Linux V2 acceptance, the preserved-profile upgrade, the focused live V1 check, configuration isolation, final-head CI, and explicit approvals remain required. Windows V2 CI, scheduled canaries, and automated callback/config-isolation checks remain deferred hardening, not extra manual gates.

Audited original plan — historical detail, not another checkbox list

Candidate references in this original plan describe its earlier snapshot. Use the active checklist's frozen package for remaining acceptance. Items below use status labels rather than duplicate editable checkboxes.

Release-readiness checklist — acceptance before merge

Candidate source: 3324f5377e11ca71921953086c9155424553e001 (3324f53). Keep PR #87 unmerged until the required manual checks and final review pass. Green CI is necessary but not sufficient. This checklist does not authorize any publication.

If the candidate changes, record its new commit/package identity and rerun affected checks. Results from another artifact must remain explicitly attributed to that artifact.

Agreed scope

V1 keeps its existing login/storage/dialog flow. V2 uses native integration credentials and OpenCode's selection component, with plugin-defined Continue with current account and Disconnect current account actions. Do not add a plugin-owned add/switch/rename UI. Advanced account management stays in V2's native /connect.

The V2 active credential is profile-global, not repository-specific. Disconnect removes a local credential without revoking Supabase authorization; another saved connection can become active. V1 credentials are not imported into V2, and rollback does not copy V2 credentials into V1 storage.

Already established at 3324f53

  • Recorded complete: Source/package checks: lint, typecheck, all 214 tests and package verification pass.
  • Recorded complete: Required host matrix: CI run 38560294009 passes real packed-TUI checks on V1 1.17.4, V1 1.17.14 and V2 2.0.27. Every cell consumes the same SHA-256-checked artifact; the required core aggregate gates their results. Windows V1 install smoke also passes.
  • Recorded complete: Synthetic connected-state checks: the packed V2 UI offers exactly Continue/Disconnect. Cancellation preserves credentials. Confirmation removes only the current credential, warns about a replacement when present, and also supports removal of the final connection. This is not live lifecycle evidence.
  • Recorded complete: Native V2 management: the real 2.0.27 TUI lists Supabase under /connect and opens its account manager/native rename input.
  • Recorded complete: Regression safeguards and documentation: host-selected auth, disconnected-host rejection despite V1 local tokens, account-specific/concurrent refresh, attempt/Location cleanup and no second V2 token copy are covered. Migration and UI ownership are documented.

Candidate preparation and safe test setup — required

The previously published version opencode-supabase@0.6.0-pr87.20261014t072939z.sha.g4df7906cef32 contains the old four-action menu. Its OAuth/API/restart results are supporting evidence only, not acceptance for the narrowed candidate.

  • Recorded complete: Approved diagnostic publication: the maintainer separately approved the beta route. The candidate is published as opencode-supabase@0.6.0-beta.20261021t094433z.sha.g703eb70248fa; latest remains 0.5.1. This supersedes the original pr87-only / unchanged-beta plan.
  • Recorded complete: Registry identity: the downloaded exact-version candidate matches the npm publish log's shasum and registry integrity; SHA-256 4c85076f3e81e5b82221e0d09f499bfbfa8339aacab658894e5a63e569d9c80e is recorded in the active checklist. This establishes artifact identity, not runtime correctness.
  • Pending — follow the active checklist: Prepare isolated profiles. Separate the normal profile, the preserved authenticated upgrade profile, disposable Linux V2 lifecycle profile, disposable Windows V2 lifecycle profile and V1 test profile. Isolate profile/config/cache roots and disable normal project-config discovery. Confirm logs do not load normal user configuration.
  • Pending — follow the active checklist: Preserve the existing authenticated profile during upgrade. After approval, change its exact plugin pin without wiping the credential store; restart only its test service/TUI. Check candidate loading, Continue and read-only plugin access after restart without another login. Do not use this profile for deliberate disconnect or forced-refresh experiments.

Linux V2 — exact registry candidate, required before merge

Use OpenCode 2.0.27. Restrict API checks to registered Supabase plugin tools. Do not credit direct shell/curl Management API requests as plugin evidence.

  • Pending — follow the active checklist: Installation and UI: use the real V2 installer, check loaded candidate identity, /supabase registration, disconnected browser-authorization dialog and the connected two-action menu.
  • Pending — follow the active checklist: OAuth/callback and API: complete real browser authorization in the disposable profile. Check that the callback completes and the connection persists; pending-dialog rendering alone is insufficient. While pending, the selected listener must remain reachable. Check read-only organization/project listing through plugin tools.
  • Pending — follow the active checklist: Continue and restart: Continue must not log in again, activate another account or remove credentials. Onboarding must not repeat within one chat session. Restart the same profile and list projects without reconnecting.
  • Pending — follow the active checklist: Actual refresh: start the natural expiry wait early. After the host refresh window is reached, check a successful refresh exchange using sanitized status/expiry evidence and a successful read-only plugin call. Restart and check that refreshed credentials persist. A pre-expiry API call does not satisfy this item.
  • Pending — follow the active checklist: Disconnect/reconnect: cancel first and check access remains. Confirm removal only in the disposable profile; check the named credential and replacement warning when applicable. With the final test credential removed, tools must reject access without falling back to V1 local tokens. Reconnect and check read-only plugin access again.

Windows V2 VM — full manual acceptance, required before merge

Use the same candidate version and OpenCode 2.0.27. The maintainer operates the VM and browser; the coordinator supplies commands, expected results and an evidence checklist. Do not defer these gates because Windows V2 CI is absent.

  • Recorded complete: Windows installation and real TUI (A1/A2/A4): the maintainer checked the exact-candidate isolated-profile startup, disconnected/connected dialogs, and two-action menu. The separate normal-config-discovery/log check remains part of R5; it is not inferred from successful login.
  • Recorded complete: OAuth/callback and API: complete real browser authorization in the Windows disposable profile. Check callback completion, saved connection and read-only organization/project listing through plugin tools.
  • Recorded complete: Continue and restart: check no new login/account change on Continue, no duplicate onboarding within one session, and plugin API access after a VM-profile/service/TUI restart without reconnecting.
  • Pending — follow the active checklist: Actual refresh and persistence: let the token reach the refresh window, check secret-safe evidence of a real refresh and successful plugin access, then check persistence after restart. Do not mark a timeout or a pre-expiry call as success.
  • Recorded complete: Disconnect/reconnect: check cancellation, current-only confirmed removal, replacement warning when applicable, disconnected rejection after the final test connection is removed, and successful reconnect/read-only access.

V1 regression and final approval — required before merge/release

  • Pending — follow the active checklist: Focused live V1 check on 1.17.14: install the exact registry candidate, complete browser login, list projects through plugin tools, restart without reconnecting and check disconnect in the separate V1 profile. Keep the minimum 1.17.4 covered by required CI; no full live V1 matrix is required.
  • Pending — follow the active checklist: Close acceptance/security failures: block install/load/render, OAuth/callback, account-binding, persistence, refresh, disconnect and V1 regression failures, plus credential exposure or unintended access. Rerun affected checks after fixes on the identified candidate. Track minor cosmetic defects separately.
  • Pending — follow the active checklist: Feature-merge approval: review complete Linux/Windows/V1 evidence and the final code changes; check all required CI jobs on the final head. Do not merge PR feat: support OpenCode V2 alongside V1 #87 before these acceptance gates pass.
  • Pending — follow the active checklist: Stable-release approval: after feature merge, review the Changesets release PR, combined pending changesets and final candidate differences. Recheck affected evidence for any code changes. Obtain explicit maintainer approval before stable publication; a diagnostic snapshot must not become latest by assumption.

Evidence and deferred hardening

For each manual check, record the candidate commit/version/hash, OpenCode version, platform, isolation, steps, expected/actual result and a sanitized pane/log excerpt. Never attach access/refresh tokens, authorization codes, service-role keys, credential databases or raw transcripts. Record failures and inconclusive results as such.

Keep source build/static/unit checks single-run and host-facing tests over one checked artifact. Defer Windows V2 CI, scheduled V1/V2 package canaries and automated callback/config-isolation checks to tracked follow-ups. Manual full Windows acceptance remains mandatory for this release.

OpenCode 2 rejects the legacy-only server export and uses a different
TUI and credential lifecycle. Expose both host hooks at the existing
entrypoints and port /supabase to native V2 integration APIs.

Resolve tools through the active host connection and refresh the supplied
account instead of borrowing V1 project-local tokens. Scope OAuth cleanup
to its attempt and Location; preserve V1 storage and real Zod schemas.

Add required V2 packed-TUI CI coverage and document reconnect on upgrade.
Lint, typecheck, 213 tests and package checks pass. The same tarball passes
/supabase render checks twice on V1 1.17.14 and V2 2.0.27.
Real-account browser authorization remains unchecked.

Builds on Rafael Santos (@rafaelsnv) and the initial migration in PR #79:
#79

Refs #79
Replace the native picker row "Continue Use Supabase" with "Continue with current account". The old description used the first stored credential, which need not be the active account.

Keep Continue on the existing account and cover the label and absence of credential activation in the TUI regression test.
Remove Connect another account and Choose account from /supabase. Those plugin-defined actions expanded the compatibility migration into an account-management feature without stakeholder review.

Keep Continue with current account and confirmed Disconnect current account. OpenCode V2 already provides add, switch and rename in its native /connect integration UI; retain active-credential resolution, account-specific refresh and isolation safeguards.

Document native dialog ownership and global account scope. Disconnect names the credential and warns when the host will activate another saved account; regressions cover cancellation, current-only removal and the two-action menu.

Refs #87
Store the V2 onboarding message as synthetic context, not a paused user prompt. OpenCode counts prompts admitted with resume=false as pending work, which left the session tab busy and delayed input after account continuation.

Retain the one-time onboarding notice without scheduling an assistant turn; use the session synthetic API with resume=false.
@jumski

jumski commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Acceptance checklist — one active list

Windows installation, OAuth, plugin API access, Continue, restart, and disconnect/reconnect are complete. Do not repeat them. Only Windows refresh remains. The nine checked steps below are maintainer-reported results for the package identified here.

The earlier release checklist duplicated this walkthrough. It is now reference only. Completed automated and synthetic checks are not extra manual work.

Remaining manual work

  • R1 — Windows: real token refresh and restart. Record only the active credential ID and expiry. Close OpenCode and stop this test profile's service. Wait past that expiry without reconnecting or changing the clock. Start the same profile and list organizations/projects through plugin tools. Pass: no OAuth, the same credential ID has a later expiry, and another service/TUI restart preserves working plugin access. A successful call alone does not prove refresh. A sanitized successful broker /refresh response is supporting evidence if available.

  • R2 — Linux V2: one full live lifecycle pass. Use this exact registry package and OpenCode 2.0.27 in a disposable isolated profile. Complete login, plugin organization/project calls, Continue, restart, actual refresh plus another restart, and disconnect/reconnect. Expected results appear in the details below. Earlier live results from the four-action build do not complete this gate.

  • R3 — Preserved Linux profile: credential-preserving upgrade. Obtain separate approval before changing its package pin. Keep its credential database. Check Continue, restart, and read-only plugin access without another login. Do not disconnect, wipe it, or use it for the deliberate refresh test.

  • R4 — V1 1.17.14: one focused live regression pass. Use this exact registry package in a separate profile. Complete browser login, list projects through plugin tools, restart without reconnecting, disconnect, and check that access stops. The V1 1.17.4 floor remains covered by CI; no additional live V1 matrix is needed.

Coordinator / maintainer gate — not another manual test suite

  • R5 — Merge readiness. Finish profile/config-isolation evidence, including disabled normal project-config discovery and no normal-user config in test logs. Reconcile the final PR source with the tested package, review the differences, and rerun only affected checks. Check required CI on the final head. Close acceptance/security failures and review all manual evidence before explicit merge approval. Minor cosmetic polish does not block acceptance.

GitHub currently reports PR head 3324f5377e11ca71921953086c9155424553e001; this published beta comes from 703eb70248fa26689052460e8523579c707fb15b. R5 remains open because these identities differ. A rebase, version change, or release-tooling-only change does not automatically erase unaffected evidence; record the comparison instead of restarting the entire checklist.

Stable release is separate: after feature merge, review the Changesets release PR, combined changesets, and any candidate differences. Obtain explicit approval before stable publication. Neither these checkboxes nor the diagnostic beta authorize a merge or stable release.

Candidate identity and safe test rules
Package: opencode-supabase@0.6.0-beta.20261021t094433z.sha.g703eb70248fa
Source commit: 703eb70248fa26689052460e8523579c707fb15b
Registry tarball SHA-256: 4c85076f3e81e5b82221e0d09f499bfbfa8339aacab658894e5a63e569d9c80e
V2 host: OpenCode 2.0.27
V1 regression host: OpenCode 1.17.14

The downloaded tarball matches the publish log's SHA-1 b6a1f6c7b979becbd20043a79cb237163dc60845; its npm integrity and SHA-256 were checked. Use the exact version, not a moving tag. @pr87 still identifies the older four-action build. latest remains 0.5.1.

Keep normal, preserved-upgrade, Windows V2, disposable Linux V2, and V1 profiles separate. Never wipe the preserved profile. Use fresh chats: old chats can retain the previous build's queued onboarding item. Do not reconnect while waiting for a refresh test.

Use only registered Supabase plugin tools for API evidence. Direct shell/curl requests and credential-file reads do not prove plugin access. Never post tokens, JWTs, authorization URLs/codes, credential databases, raw credential exports, or raw logs/transcripts. For failures, record platform, package/host version, step, exact error, and a cropped sanitized screenshot.

Do other isolated-profile work while tokens expire. Start each natural-expiry wait early; do not change either system clock.

R2 expected results — one Linux V2 run, not separate test suites
  1. Install, OAuth, API: the real V2 installer loads this candidate. Both disconnected and two-action connected dialogs render. Browser authorization completes its callback and saves the connection. The callback listener stays reachable while pending. Plugin tools list the correct organizations/projects.
  2. Continue: repeat it twice in the same chat. No new login, account switch, or duplicate onboarding occurs. Typing responds promptly, and the tab does not stay busy without a request.
  3. Restart: restart this profile's service/TUI. A plugin request succeeds before any new /supabase action or login.
  4. Refresh: wait past the recorded expiry without reconnecting. A plugin request succeeds with the same credential ID and a later expiry. Restart again and check working plugin access.
  5. Disconnect/reconnect: cancellation preserves access. Confirmation names and removes only the current credential without revoking Supabase authorization. It warns about another saved account when applicable. After the final test credential disappears, plugin tools reject access without V1-token fallback. Reconnect and check that access returns.
Completed evidence — no repeat needed

Automated / synthetic baseline at 3324f53

These are established results for that named source, not a claim that CI ran on a later head. Final-head CI remains R5.

  • Source/package checks: lint, typecheck, all 214 tests and package verification pass.
  • Required host matrix: CI run 38560294009 passes real packed-TUI checks on V1 1.17.4, V1 1.17.14 and V2 2.0.27. Every cell consumes the same SHA-256-checked artifact; the required core aggregate gates their results. Windows V1 install smoke also passes.
  • Synthetic connected-state checks: the packed V2 UI offers exactly Continue/Disconnect. Cancellation preserves credentials. Confirmation removes only the current credential, warns about a replacement when present, and also supports removal of the final connection. This is not live lifecycle evidence.
  • Native V2 management: the real 2.0.27 TUI lists Supabase under /connect and opens its account manager/native rename input.
  • Regression safeguards and documentation: host-selected auth, disconnected-host rejection despite V1 local tokens, account-specific/concurrent refresh, attempt/Location cleanup and no second V2 token copy are covered. Migration and UI ownership are documented.

Diagnostic artifact and spinner fix

  • Approved diagnostic publication: the maintainer separately approved the beta route. The exact candidate above is public under beta; latest remains 0.5.1. This supersedes the earlier plan to publish only under pr87 and leave beta unchanged.
  • Registry identity: the downloaded exact-version tarball matches the npm publish log's shasum, passes the registry integrity check, and has the SHA-256 recorded above. Matching hashes establish artifact identity, not runtime correctness.
  • Post-Continue fix validation at 50d2b1c: source checks and all 214 tests passed. Its packed artifact passed the OpenCode 2.0.27 idle/input probe twice and the 1.17.14 TUI smoke. These remain attributed to that earlier fixed artifact; the Windows results below cover the exact published candidate in this comment.

Maintainer-confirmed Windows checks on this candidate

A. Login and restart

  • A1. Start OpenCode in a fresh, isolated disposable test profile with the exact candidate installed. Enter /supabase.
    Pass: “Connect your Supabase account” appears.

  • A2. Approve login in the Windows VM’s browser. If it does not open, copy the dialog’s URL into that browser.
    Pass: OpenCode confirms connection; no callback connection error. After closing the success dialog, typing responds promptly and the tab does not stay busy without a request.

  • A3. Ask:

    List my Supabase organizations and projects using only Supabase plugin tools. Do not use shell, curl, or read credential files.

    Pass: correct results through plugin tools.

  • A4. Enter /supabase. Choose Continue with current account twice in the same fresh chat.
    Pass: exactly Continue/Disconnect; no new login, account switch, or repeated onboarding. Typing responds promptly; the tab does not stay busy without a request.

  • A5. Close OpenCode. Stop the test profile’s service, then start the same profile again. Repeat A3 before /supabase.
    Pass: results without another login.

C. Disconnect — disposable profile only

  • C1. /supabase → Disconnect → Cancel. Request projects.
    Pass: access remains.

  • C2. /supabase → Disconnect. Read the confirmation, then Confirm.
    Pass: confirmation names the credential and explains that Supabase authorization remains.

  • C3. With no saved connections remaining, request projects.
    Pass: reconnect guidance—not successful access from old credentials.

  • C4. Run /supabase, reconnect, and request projects.
    Pass: access returns.

If multiple connections exist: confirmation must warn about replacement; only the named connection disappears. Remove remaining disposable test connections before checking disconnected rejection.

@jumski
jumski force-pushed the compat/opencode-v2 branch from 3324f53 to 008c8d7 Compare October 29, 2026 23:59
@jumski
jumski merged commit 28c294a into main Oct 30, 2026
8 checks passed
@jumski
jumski deleted the compat/opencode-v2 branch October 30, 2026 07:25
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