From eefa449d547dd7bd102232f600df783c406cc3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Boschi?= Date: Tue, 14 Apr 2026 15:31:52 +0200 Subject: [PATCH 1/2] docs(opencode): drop misleading npm install step, document Hindsight Cloud OpenCode auto-installs plugins listed in the "plugin" array at startup via Bun; the prior instructions to `npm install` the package were misleading. Also add a dedicated Hindsight Cloud section with api.hindsight.vectorize.io and token guidance. --- hindsight-docs/docs-integrations/opencode.md | 38 ++++++++++++----- hindsight-integrations/opencode/README.md | 43 ++++++++++++++------ 2 files changed, 58 insertions(+), 23 deletions(-) diff --git a/hindsight-docs/docs-integrations/opencode.md b/hindsight-docs/docs-integrations/opencode.md index 1f307ddd6..66e9ada42 100644 --- a/hindsight-docs/docs-integrations/opencode.md +++ b/hindsight-docs/docs-integrations/opencode.md @@ -10,30 +10,48 @@ Persistent long-term memory plugin for [OpenCode](https://opencode.ai) using [Hi ## Quick Start -```bash -# 1. Install the plugin -npm install @vectorize-io/opencode-hindsight -``` - -Add to your `opencode.json`: +Add to your `opencode.json` (project) or `~/.config/opencode/opencode.json` (global): ```json { + "$schema": "https://opencode.ai/config.json", "plugin": ["@vectorize-io/opencode-hindsight"] } ``` +OpenCode auto-installs plugins in the `"plugin"` array on startup — no `npm install` required. + +Point the plugin at your Hindsight server and start OpenCode: + ```bash -# 2. Configure your Hindsight server export HINDSIGHT_API_URL="http://localhost:8888" +opencode +``` -# Optional: API key for Hindsight Cloud -export HINDSIGHT_API_TOKEN="your-api-key" +### Using Hindsight Cloud + +Get an API key at [ui.hindsight.vectorize.io/connect](https://ui.hindsight.vectorize.io/connect): -# 3. Start OpenCode — the plugin activates automatically +```bash +export HINDSIGHT_API_URL="https://api.hindsight.vectorize.io" +export HINDSIGHT_API_TOKEN="your-api-key" opencode ``` +Or configure inline via plugin options in `opencode.json`: + +```json +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [ + ["@vectorize-io/opencode-hindsight", { + "hindsightApiUrl": "https://api.hindsight.vectorize.io", + "hindsightApiToken": "your-api-key" + }] + ] +} +``` + ## Features ### Custom Tools diff --git a/hindsight-integrations/opencode/README.md b/hindsight-integrations/opencode/README.md index 0e6b377c6..4ed2be7cc 100644 --- a/hindsight-integrations/opencode/README.md +++ b/hindsight-integrations/opencode/README.md @@ -11,33 +11,50 @@ Hindsight memory plugin for [OpenCode](https://opencode.ai) — give your AI cod ## Quick Start -### 1. Install +### 1. Enable the plugin -```bash -npm install @vectorize-io/opencode-hindsight -``` - -### 2. Configure - -Add to your `opencode.json`: +Add to your `opencode.json` (project) or `~/.config/opencode/opencode.json` (global): ```json { + "$schema": "https://opencode.ai/config.json", "plugin": ["@vectorize-io/opencode-hindsight"] } ``` -### 3. Set Environment Variables +OpenCode auto-installs plugins listed here on startup — no `npm install` required. + +### 2. Point to your Hindsight server ```bash -# Required: Hindsight API URL +# Self-hosted export HINDSIGHT_API_URL="http://localhost:8888" -# Optional: API key for Hindsight Cloud +# Optional: override the memory bank ID +export HINDSIGHT_BANK_ID="my-project" +``` + +### Using Hindsight Cloud + +Get an API key at [ui.hindsight.vectorize.io/connect](https://ui.hindsight.vectorize.io/connect), then either export env vars: + +```bash +export HINDSIGHT_API_URL="https://api.hindsight.vectorize.io" export HINDSIGHT_API_TOKEN="your-api-key" +``` -# Optional: Override the memory bank ID -export HINDSIGHT_BANK_ID="my-project" +Or configure inline in `opencode.json`: + +```json +{ + "$schema": "https://opencode.ai/config.json", + "plugin": [ + ["@vectorize-io/opencode-hindsight", { + "hindsightApiUrl": "https://api.hindsight.vectorize.io", + "hindsightApiToken": "your-api-key" + }] + ] +} ``` ## Configuration From 87856fcc7eda396f37b548511eef644ca96ac57b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Boschi?= Date: Tue, 14 Apr 2026 15:37:55 +0200 Subject: [PATCH 2/2] fix(opencode): default-export the Plugin function directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenCode's plugin loader iterates Object.entries(mod) and invokes every export as a Plugin factory `(input) => Promise`, deduping by identity. Our prior default export was a PluginModule object (`{ id, server }`), which opencode tried to call as a function and crashed with `fn3 is not a function. (In 'fn3(input)', 'fn3' is an instance of Object)` at load time. Default-export the HindsightPlugin function itself so both default and named `HindsightPlugin` exports point to the same reference (dedupe suppresses a second call). Update the default-export smoke test to assert this invariant. Verified end-to-end against opencode 1.1.49 with the built dist — the plugin now initializes, registers tools/hooks, and processes session events without error. --- hindsight-integrations/opencode/src/index.ts | 12 ++++-------- hindsight-integrations/opencode/src/plugin.test.ts | 13 ++++++++----- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/hindsight-integrations/opencode/src/index.ts b/hindsight-integrations/opencode/src/index.ts index 82b3000a6..69ac783a6 100644 --- a/hindsight-integrations/opencode/src/index.ts +++ b/hindsight-integrations/opencode/src/index.ts @@ -17,7 +17,7 @@ * ``` */ -import type { Plugin, PluginModule } from '@opencode-ai/plugin'; +import type { Plugin } from '@opencode-ai/plugin'; import { HindsightClient } from '@vectorize-io/hindsight-client'; import { loadConfig } from './config.js'; import { deriveBankId } from './bank.js'; @@ -67,13 +67,9 @@ const HindsightPlugin: Plugin = async (input, options) => { // Named export for direct import export { HindsightPlugin }; -// Default export as PluginModule for OpenCode plugin loader -const module: PluginModule = { - id: 'hindsight', - server: HindsightPlugin, -}; - -export default module; +// Default export is the Plugin function itself — OpenCode's loader calls the +// default export directly. +export default HindsightPlugin; // Re-export types for consumers export type { HindsightConfig } from './config.js'; diff --git a/hindsight-integrations/opencode/src/plugin.test.ts b/hindsight-integrations/opencode/src/plugin.test.ts index 6790394e7..fc56521a4 100644 --- a/hindsight-integrations/opencode/src/plugin.test.ts +++ b/hindsight-integrations/opencode/src/plugin.test.ts @@ -127,11 +127,14 @@ describe('HindsightPlugin state sharing', () => { }); }); -describe('PluginModule default export', () => { - it('exports correct module shape', async () => { +describe('plugin default export', () => { + it('default-exports the Plugin function itself', async () => { const mod = await import('./index.js'); - expect(mod.default).toBeDefined(); - expect(mod.default.id).toBe('hindsight'); - expect(typeof mod.default.server).toBe('function'); + expect(typeof mod.default).toBe('function'); + // OpenCode iterates Object.entries(mod) and calls every export as a + // Plugin factory, deduping by reference. The default export must be + // the same reference as the named HindsightPlugin export to avoid + // running the factory twice. + expect(mod.default).toBe(mod.HindsightPlugin); }); });