Skip to content

fix(agents): upgrade opencode to 2.2.3 - #2779

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
gardener/upstream/opencode-2.2.3
Open

github-actions[bot] wants to merge 1 commit into
mainfrom
gardener/upstream/opencode-2.2.3

Conversation

@github-actions

@github-actions github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Moves agents/harness/opencode and agents/models/opencode from opencode 2.0.24 to 2.2.3, and switches the Cloudflare provider to OpenCode's sdk hook.

Package From To
@opencode/sdk (dev, example) 2.0.24 2.2.3
@opencode/plugin (dev, example) 2.0.24 2.2.3
@opencode/sdk peer range ^2.0.24 ^2.2.3
@opencode/plugin peer range ^2.0.24 ^2.2.3

There have been 16 opencode v2 releases since 2.0.24 (2.0.25 to 2.2.3). All of them already install under our ^2.0.24 peer range, and on 2.2.1 and 2.2.2 agents/models/opencode is broken: every turn fails, because OpenCode no longer bundles @ai-sdk/vercel, the package our provider borrowed (see #2776 and #2777). 2.2.3 is the first release with what #2777 asks for: OpenCode now runs its npm loader after plugin sdk hooks, so a plugin can supply the AI SDK provider itself. This PR does that and moves the floor to 2.2.3.

What changed upstream that affects us

  • high · breaking: "chore(core): remove bundled cohere, vercel and perplexity AI SDK packages (#59771)" (fc6922f, @opencode/core 2.2.1, a dependency of @opencode/sdk). packages/agents/src/models/opencode/index.ts:60 named aisdk:@ai-sdk/vercel as the provider's package so that OpenCode's sdk step would load something in-process before our language hook replaced the model. On 2.2.x that package goes to OpenCode's npm installer, which cannot run in workerd. With 2.2.3 and the old code, 14 of 31 harness tests fail with Cannot initialize cloudflare/@cf/moonshotai/kimi-k2.7-code: Npm.add is unavailable in the workerd profile. The fix uses the next item.
  • high · workaround: "fix(core): run dynamic provider npm fallback after external sdk hooks (#60380)" (b5c2231, @opencode/core 2.2.3). DynamicProviderPlugin now registers after external plugins and returns early when evt.sdk is already set. Our plugin now answers the sdk hook for its own provider, so it doesn't need a carrier package or the unreachable Vercel base URL any more. This is the approach proposed in fix(agents): upgrade opencode to 2.2.1 #2776.
    -const CARRIER_PACKAGE = "aisdk:@ai-sdk/vercel";
    -const UNREACHABLE_BASE_URL = "https://workers-ai.binding.invalid/v1";
    +const CARRIER_PACKAGE = "aisdk:agents/models/opencode";
    ...
    -            package: CARRIER_PACKAGE,
    -            settings: { baseURL: UNREACHABLE_BASE_URL, apiKey: "binding" }
    +            package: CARRIER_PACKAGE
    ...
    +      const sdk = await ctx.aisdk.hook(
    +        "sdk",
    +        (event) => {
    +          event.sdk = { provider: CLOUDFLARE_PROVIDER_ID };
    +        },
    +        { providerID }
    +      );
    The existing language hook (index.ts:149) still builds the model from agents/models/ai-sdk, and the sdk hook's registration is disposed with the others.
  • medium · breaking: "refactor(client): group experimental SDK methods under client.experimental (#59072)" (9a9386e, 2.2.1). sessions.wait and sessions.log are now @deprecated Use client.experimental.session.wait/log. Removed in the next minor. The harness calls them at packages/agents/src/harness/opencode/harness.ts:536, :670 and :1242, and OpenCodeLogEvent is derived from sessions.log (types.ts:45). Both have moved to the new names:
    -              opencode.sessions.wait(
    +              opencode.experimental.session.wait(
    ...
    -      yield* opencode.sessions.log(
    +      yield* opencode.experimental.session.log(
    ...
    -  ReturnType<OpenCode["sessions"]["log"]> extends AsyncIterable<infer E>
    +  ReturnType<OpenCode["experimental"]["session"]["log"]> extends AsyncIterable<
  • medium · breaking (tests and example dev server): "chore: upgrade Effect to rc.118 (#50231)" (1aae67e, 2.0.27). effect/unstable/httpapi moved to effect/http-api, so the Vite stub for Scalar's UI no longer matched anything. It's fixed in packages/agents/src/harness/opencode/tests/vitest.config.ts:16 and examples/next/harnesses/opencode/vite.config.ts:16:
    -        id.includes("/effect/dist/unstable/httpapi/internal/httpApiScalar.js")
    +        id.includes("/effect/dist/http-api/internal/httpApiScalar.js")
  • medium · breaking (tests): @opencode/core 2.2.3 inlines models.dev's catalog as one 8.2 MB string (dist/chunks/usage-limits-*.js; in 2.0.24 the largest chunk was 5.3 MB). It is too large for the WebSocket message that carries a module into the vitest-pool-workers runtime (WebSocket protocol error; statusCode = 1009; Message is too large), and the harness-opencode pool crashed after 5 of 14 tests. vitest.config.ts:20 adds the empty-models-dev-snapshot transform from fix(agents): upgrade opencode to 2.2.1 #2767, which swaps in an empty catalog. These tests already set models: { fetch: false } and use only the Cloudflare provider.
No effect on us (76)
  • "release: v2.2.3" (082ac62): version bump only.
  • "feat(core): add Claude Agent provider (#58782)" (f29e281): adds plugin session types for a provider we don't use.
  • "feat(app): fit the session header at narrow timeline widths (#59512)" (8fdf2e5): GUI plugin surface.
  • "chore(tui): use OpenTUI 0.8.0 (#60385)" (13e8186): TUI peer dependency only.
  • "fix(app): match own server loopback port before treating http servers as local (#60460)" (a88d3ca): desktop app.
  • "refactor(ai): one tool() for both clients (#60407)" (7a82f3a): touches only sdk tests.
  • "release: v2.2.2 (#60337)" (4efad23): version bump only.
  • "release: v2.2.1 (#60113)" (f74b141): version bump only.
  • "feat(app): unify quote comments and browser annotations (#60164)" (2fc3716): GUI plugin surface.
  • "feat(core): add image_generate tool (#59939)" (89f3ac1): plugin session types for a tool we neither offer nor remove.
  • "feat(core): add /goal with a client-side done check (#59437)" (8de0323): adds an experimental.idle session hook; we don't register one.
  • "chore(plugin): remove unused @tsconfig/node22 (#59718)" (1dab9ae): dev dependency.
  • "feat(app): refine artifact previews and file actions (#59657)" (b3de41a): GUI.
  • "feat(app): add session location menu actions (#59607)" (4ba064f): GUI.
  • "release: v2.2.0 (#59558)" (8697644): version bump only.
  • "feat(protocol): define experimental image and decision generation endpoints (#59190)" (2a0639a): additive plugin context API.
  • "feat(app): manage desktop plugins in Extensions › Plugins (#59489)" (5792c3e): desktop app.
  • "fix(app): list What's new with About in settings (#59471)" (19d87a7): desktop app.
  • "feat(plugin): add toasts, dialogs, notifications, UI, tabs and composer APIs to GUI plugins (#59469)" (758cf5a): GUI plugins only.
  • "feat(plugin): add OpenCode Desktop GUI plugins (#55246)" (dae4077): GUI plugins only.
  • "Revert "fix(tui): identify config-defined providers (#57007)" (#59439)" (cd15a6a): reverts the TUI change below; net zero.
  • "fix(release): add repository to ai, plugin and cli package.json (#59422)" (fa5b4bd): package metadata.
  • "fix(tui): identify config-defined providers (#57007)" (cc4faf4): TUI; reverted above.
  • "ci: separate release builds from signing and publishing (#59046)" (6996bbc): CI.
  • "chore: upgrade opentui v0.7.0 (#59295)" (ab4d1f3): TUI peer dependency.
  • "feat(plugin): filter event subscriptions by type (#58864)" (1434464): adds an optional filter to the plugin event.subscribe; the harness subscribes through the SDK client, unfiltered.
  • "chore: merge beta into dev" (be315b1): merge; brings additive plugin session/vcs API.
  • "fix(server): stop form polling from booting idle locations (#59083)" (c8cf3a5): instances option, which we don't use.
  • "chore: merge dev into beta" (4b83402): merge; versions and the @opencode/ai/effect import move.
  • "refactor(ai): make Promise the root entry and move Effect to @opencode/ai/effect (#58847)" (dad29a8): internal type imports; we import nothing from @opencode/ai.
  • "refactor(core): keep Go allowance out of messages and sessions (#58765)" (de284dc): TUI context.
  • "feat(core): record reported cost and Go allowance (#58562)" (4cba1b7): TUI context.
  • "sync release versions for v2.1.4 [skip ci]" (2a3e7c0): versions.
  • "chore: upgrade opentui v0.6.8 (#58380)" (c9c1dc0): TUI.
  • "chore: merge dev into beta" (fd0efe3): merge; same content as 7a62a46 below.
  • "refactor: remove redundant casts and duplicate helpers across sdk, plugin, codemode, and schema (#57996)" (7a62a46): internal; public types unchanged (typecheck passes).
  • "chore: merge dev into beta" (bcd713e): merge; package metadata and publish script.
  • "chore: use bun check for local typechecks and TypeScript 7.1 in CI (#58253)" (84578e1): tooling.
  • "sync release versions for v2.1.3 [skip ci]" (e965774): versions.
  • "chore: merge dev into beta" (316a688): merge; versions and plugin session types.
  • "fix(app,server): stop subagent form polling from stalling sends (#57684)" (946c331): instances option, which we don't use.
  • "feat(plugin): expose session instruction entries to plugins (#56550)" (6c74e11): additive plugin API.
  • "sync release versions for v2.1.2 [skip ci]" (4b50f5c): versions.
  • "fix(app): show untracked folders as one review row (#57527)" (21ed6e4): GUI.
  • "sync release versions for v2.1.1 [skip ci]" (133b1eb): versions.
  • "sync release versions for v2.1.0 [skip ci]" (d30e990): versions.
  • "refactor: v2.1 minor breaking changes (#57260)" (acdcdb8): renames SessionCompactionResult.providerState to native; we register no compaction hook.
  • "chore: OpenTUI 0.6.5 (#55339)" (c7ddff7): TUI.
  • "Merge remote-tracking branch 'origin/dev' into beta" (15d4afd): merge; versions, tsconfig, additive plugin API.
  • "chore: upgrade typecheck to TypeScript 7.0.2 (#56300)" (23359e9): tooling.
  • "feat(plugin): expose session list (#56264)" (bc5fa1c): additive plugin API.
  • "sync release versions for v2.0.32 [skip ci]" (4e95dac): versions.
  • "Merge branch 'dev' into beta" (3a58a0c): merge; versions.
  • "sync release versions for v2.0.31 [skip ci]" (83c5abb): versions.
  • "feat(app): add generative UI to the GUI (#54747)" (f232362): GUI.
  • "chore(ci): speed up and stabilize the test workflow (#55866)" (17229d2): CI and tests.
  • "sync release versions for v2.0.30 [skip ci]" (f40dc43): versions.
  • "sync release versions for v2.0.29 [skip ci]" (34d8ded): versions.
  • "chore(tui): revert OpenTUI 0.6 upgrade (#55300)" (def5d94): TUI.
  • "feat(plugin): let plugins assert permissions (#54930)" (6a7cedc): additive plugin API.
  • "fix(plugin): keep each Promise hook rejection on its own tool call (#55263)" (7351718): Promise-adapter fix; our hooks don't reject.
  • "feat(tui): report pending session status to the terminal (#55172)" (d0a2ce3): TUI.
  • "chore(tui): upgrade OpenTUI to 0.6.2 (#55083)" (65f8907): TUI.
  • "sync release versions for v2.0.28 [skip ci]" (c5aabae): versions.
  • "feat(plugin): expose credential.activate to server plugins (#52797)" (d782675): additive plugin API.
  • "fix(plugin): return Promise tool throws as tool failures (#54913)" (1438073): the example's workspace tools throw on isError (examples/next/harnesses/opencode/src/workspace.ts:143) and its comment already says that becomes a tool error. This change makes that true; no code change.
  • "sync release versions for v2.0.27 [skip ci]" (03cb9b9): versions.
  • "chore: upgrade Effect to 4.0.1 (#54198)" (41b03de): plugin README wording; we don't import effect.
  • "feat(sdk): seed host plugins before recovery and harden workerd defaults (#54219)" (55dde88): OpenCodeWorkerd.create({ plugins }) now registers plugins before suspended sessions resume, so a resumed turn finds our provider; we have no code working around the old order.
  • "chore: upgrade Effect to rc.118 (#50231)": covered above.
  • "fix(core): route file overrides through Workspace.connect (#54089)" (c50e39b): adds Effect-entry exports we don't import.
  • "sync release versions for v2.0.26 [skip ci]" (8059cdc): versions.
  • "sync release versions for v2.0.25 [skip ci]" (62e087f): versions.
  • "chore: upgrade opentui v0.5.17 (#53904)" (da40b8f): TUI.
  • "fix(cli): give plugins the host's Effect (#53422)" (c28e9ec): CLI plugin loader; we pass plugin objects in-process.
  • "chore: upgrade opentui v0.5.16 (#53805)" (fcad131): TUI.
  • "feat(integration): add declarative external connection method (#53672)" (70c6c8c): additive plugin integration API.
  • "fix(sdk): release completed embedded request signals (#53613)" (9ee97d8): internal fix that stops completed requests holding abort listeners; no API change.
  • "chore: remove unused dependencies from V2 packages (#53482)" (50ae4bd): drops zod and @standard-schema/spec from @opencode/plugin; we don't rely on them through it.
  • "sync release versions for v2.0.24 [skip ci]" (bd55d48): versions.

Decisions

  • Answer the sdk hook instead of finding another bundled carrier. fix(agents): upgrade opencode to 2.2.1 #2767 used gitlab-ai-provider as the carrier, and fix(agents): upgrade opencode to 2.2.1 #2776 held off because that depends on OpenCode internals. With 2.2.3 a plugin's sdk hook runs before the npm fallback (dynamic.ts: if (evt.sdk) return), so the provider names aisdk:agents/models/opencode, a package that doesn't exist, and our hook supplies a placeholder SDK. The model still comes from the existing language hook, so agents/models/ai-sdk builds it as before. The package name is the one fix(agents): upgrade opencode to 2.2.1 #2776 proposed.
  • Raise the peer floor to ^2.2.3. The new provider needs 2.2.3's hook order. On 2.0.24 to 2.2.2 OpenCode's npm loader would claim agents/models/opencode before our hook runs. On 2.2.1 and 2.2.2 the old carrier was already broken anyway. The harness also now calls experimental.session.*, which exists from 2.2.1.
  • Move off sessions.wait and sessions.log now. They still work on 2.2.3 but are marked "Removed in the next minor". The floor already guarantees the replacements, so moving now means the next minor needs no harness change.
  • Changeset: patch. Only source changed, and the peer floor moves within major 2. The changeset states the new floor and the one-way door.
  • Stub the models.dev snapshot only in the harness test config. The Worker build and the example dev server are unchanged; the stub exists only because of vitest-pool-workers' module-transfer limit.

Needs a maintainer

  • Rollback across 2.2.0 for sessions with media. opencode 2.2.0 added a blob table and stores file attachments and file tool results as media:<hash> refs (70c69f0, migration 20261025123711_blob). opencode before 2.2.0 can't read those messages. Options: accept it (users on ^2.0.24 could already have installed 2.2.x), or document a rollback caveat in the harness example. Recommendation: accept it and rely on the changeset note, because the harness is @experimental and the migration is upstream's.

Affected open PRs

Other changes

  • packages/agents/package.json: dev pins 2.0.24 → 2.2.3 and peer ranges ^2.0.24 → ^2.2.3 for @opencode/sdk and @opencode/plugin.
  • examples/next/harnesses/opencode/package.json: pins 2.0.24 → 2.2.3.
  • examples/next/harnesses/opencode/vite.config.ts: the effect path fix above.
  • packages/agents/src/harness/opencode/tests/vitest.config.ts: the effect path fix and the empty-models-dev-snapshot transform above.
  • packages/agents/src/harness/opencode/harness.ts, packages/agents/src/harness/opencode/types.ts: the experimental.session move above.
  • packages/agents/src/models/opencode/index.ts: the sdk hook, the new carrier name, and the removed Vercel settings above; the comment on CARRIER_PACKAGE now says why the name is safe.
  • .changeset/opencode-2-2-3.md: agents patch: the new floor, why, and the one-way door.
  • pnpm-lock.yaml: regenerated by pnpm install; both importers resolve only @opencode/*@2.2.3 (no 2.0.24 left), plus the transitive moves that come with it (for example OpenTUI 0.8.0, effect 4.0.6).

Evidence

  • Before: on 2.0.24, harness-opencode passed 31/31 and the workers project's models/opencode tests passed 5/5. On 2.2.3 with the old code, the harness-opencode pool crashed (Message is too large, 5 of 14 tests run). With only the test config fixed, 14 of 31 tests failed (Npm.add is unavailable in the workerd profile).
  • After: harness-opencode 31/31, workers models/opencode (provider.test.ts, language-v3.test.ts) 5/5. pnpm run build passes, and so does pnpm run check (sherif, exports check, oxfmt, oxlint, typecheck of all 133 projects).

Merge Danger

Door: one-way

Blast Radius: OpenCode harness users

Anyone on @opencode/sdk or @opencode/plugin below 2.2.3 gets a peer-dependency warning and should upgrade both to 2.2.3. If they don't, agents/models/opencode fails to initialize its model (on 2.2.1 and 2.2.2 it already does). The door is one-way because of OpenCode itself: once 2.2.0 or later has run on a Durable Object, OpenCode keeps file attachments and file tool results in its new blob table, and pinning back below 2.2.0 makes those messages unreadable. Everything else OpenCode migrated between 2.0.24 and 2.2.3 is additive, and the dropped session_pending table was unused.


Opened by Gardener's opencode-upgrade task. Commits pushed by Gardener don't start CI: close and reopen this pull request, or push to it, to run it. Review comments are handled by Gardener's pr-review-fix task.


Devin Review

Move @opencode/sdk and @opencode/plugin to 2.2.3 (peer range ^2.2.3).
OpenCode 2.2.1 stopped bundling @ai-sdk/vercel, which agents/models/opencode
named as its carrier package; 2.2.3 runs OpenCode's npm loader after plugin
sdk hooks, so the provider now answers the sdk hook itself. Move the harness
off the deprecated sessions.wait/sessions.log to experimental.session, and
adapt the test and example Vite configs to OpenCode's new effect paths and
its 8 MB models.dev snapshot.

Gardener-Operation: op_08d8b01a60d488c0d0dab49550a501301bb3571c3d7ba31a7751f667ff2a7d7d:f6e1e8ca99b3b04db9231838a0897c2d0e0de8f444525634e905fc6df1d1e77d
@github-actions github-actions Bot added the dependencies Pull requests that update a dependency file label Oct 30, 2026
@changeset-bot

changeset-bot Bot commented Oct 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0c6ada2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
agents Patch
@cloudflare/agent-think Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

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

Labels

dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants