diff --git a/src/plugin/v2.ts b/src/plugin/v2.ts index e7e2d24..140fd44 100644 --- a/src/plugin/v2.ts +++ b/src/plugin/v2.ts @@ -487,6 +487,12 @@ async function reconcileProviderSources( const definition = Plugin.define({ id: 'opencode-litellm', async setup(context) { + // OpenCode 1.18.x embeds a v2 plugin host whose context has no `provider` + // domain. It still calls `setup` on any plugin that exports one, but those + // versions are served by the `server()` entrypoint below. Bail out before + // touching the logger so `server()`'s client-backed logging stays intact. + if (!context.provider) return + initV2Logging() const pluginOptions = asRecord(context.options) diff --git a/test/plugin-v2.test.ts b/test/plugin-v2.test.ts index f4381d5..db4bfb4 100644 --- a/test/plugin-v2.test.ts +++ b/test/plugin-v2.test.ts @@ -57,6 +57,25 @@ describe('OpenCode 2 plugin entrypoint', () => { expect(legacy.event).toEqual(expect.any(Function)) }) + it('does nothing when the host context has no provider API', async () => { + const log = vi.spyOn(console, 'log').mockImplementation(() => {}) + globalThis.fetch = vi.fn(async () => { + throw new Error('setup must not probe the network without a provider API') + }) + // OpenCode 1.18.x embeds a v2 plugin host whose context exposes `catalog` + // instead of `provider`; the legacy `server()` entrypoint serves that host. + const context = { + options: {}, + catalog: { transform: vi.fn(), reload: vi.fn() }, + } as unknown as Context + + const cleanup = await plugin.setup(context) + + expect(cleanup).toBeUndefined() + expect(log).not.toHaveBeenCalled() + expect(globalThis.fetch).not.toHaveBeenCalled() + }) + it('registers discovered LiteLLM models through the provider transform', async () => { cacheDirectory = mkdtempSync(join(tmpdir(), 'opencode-litellm-test-')) process.env.XDG_CACHE_HOME = cacheDirectory