|
| 1 | +# Changelog |
| 2 | + |
| 3 | +All notable changes to this project will be documented in this file. |
| 4 | + |
| 5 | +## [0.1.0] — 2026-06-10 |
| 6 | + |
| 7 | +Initial public release. A complete opencode integration for Cursor built on the |
| 8 | +official `@cursor/sdk`: a streaming chat provider, an auth/config/model plugin, |
| 9 | +and a permission-gated delegation tool surface. |
| 10 | + |
| 11 | +### Provider |
| 12 | + |
| 13 | +- **Cursor provider** backed by the official `@cursor/sdk` — drives a local |
| 14 | + Cursor agent (`Agent.create` / `agent.send`) and translates its `onDelta` |
| 15 | + callbacks into AI SDK `LanguageModelV3` stream parts (text, reasoning, |
| 16 | + tool activity, usage). Implements both `doStream()` and `doGenerate()`. |
| 17 | +- **Per-request controls** via `providerOptions.cursor` — `mode` (agent/plan), |
| 18 | + `params`, and `thinking` level; works with opencode's model variant picker. |
| 19 | +- **Model variants** auto-generated from `Cursor.models.list` parameters: a |
| 20 | + `plan` variant plus one per reasoning level a model advertises. |
| 21 | +- **Session reuse** (`session: true`) — keeps one Cursor agent per opencode |
| 22 | + session via `Agent.resume()` across turns, with automatic fallback to a fresh |
| 23 | + agent. A run wedged by a crashed/duplicate process is recovered by retrying |
| 24 | + the send once with the SDK's `local.force` escape hatch. |
| 25 | +- **`toolDisplay` provider option** (`"reasoning"` default | `"blocks"`): |
| 26 | + - `"reasoning"` renders Cursor's internal tool activity (including the real |
| 27 | + MCP tool name) as concise `[tool] …` reasoning lines. Always safe — tool |
| 28 | + calls never cross opencode's tool-execution boundary. |
| 29 | + - `"blocks"` emits structured, provider-executed **dynamic** `tool-call` / |
| 30 | + `tool-result` parts so opencode renders native tool blocks. Names are |
| 31 | + `cursor_`-prefixed and sanitized (`shell` → `cursor_shell`, |
| 32 | + `serena/find_symbol` → `cursor_serena_find_symbol`) so they can't collide |
| 33 | + with opencode-registered tools, and carry `providerExecuted: true` + |
| 34 | + `dynamic: true` so ai v6's `parseToolCall` accepts them without |
| 35 | + registered-tool validation. Tool-results use the V3-spec `result` + |
| 36 | + `isError` fields. A tool call whose completion never arrives (run |
| 37 | + errored/cancelled mid-tool) is closed with a synthetic error result so the |
| 38 | + block never dangles as "Tool execution aborted", and a run that ends with |
| 39 | + status `error` surfaces the failure instead of finishing silently. |
| 40 | + |
| 41 | +### Node sidecar (Bun compatibility) |
| 42 | + |
| 43 | +- **Automatic Node sidecar** — opencode runs on Bun, whose `node:http2` client |
| 44 | + is incompatible with the Cursor SDK's long-lived streaming RPC |
| 45 | + (`NGHTTP2_FRAME_SIZE_ERROR`), causing native tool calls to execute but never |
| 46 | + report completion. When Bun is detected and `node` is on `PATH`, the SDK |
| 47 | + agent is hosted in a Node child process and driven over a JSON-lines stdio |
| 48 | + protocol; the provider is otherwise unchanged. Under Node the SDK runs |
| 49 | + in-process. Override with `OPENCODE_CURSOR_SIDECAR=1` (force on) or |
| 50 | + `OPENCODE_CURSOR_SIDECAR=0` (force in-process / silence the Bun warning). |
| 51 | + |
| 52 | +### Plugin |
| 53 | + |
| 54 | +- **opencode plugin** (`@stablekernel/opencode-cursor/plugin`): auth hook (API-key login; |
| 55 | + the key is validated on first use rather than at login), config hook |
| 56 | + (auto-injects `provider.cursor`), |
| 57 | + `provider.models()` (live catalog via `Cursor.models.list`), and the |
| 58 | + `cursor_refresh_models` tool. The auth loader warms a key-independent catalog |
| 59 | + cache so the model picker is populated on first authed load (and restart) |
| 60 | + rather than showing only the fallback snapshot. |
| 61 | +- **MCP server forwarding** — opencode's configured `config.mcp` entries are |
| 62 | + translated to Cursor `McpServerConfig` and passed to the local agent so it can |
| 63 | + use the same servers (e.g. Serena). Opt out with `provider.cursor.options.forwardMcp`. |
| 64 | +- **Model discovery** with a 24-hour cache (keyed by key fingerprint) and a |
| 65 | + built-in fallback snapshot (composer-2.5, claude-opus-4-8, claude-sonnet-4-6, |
| 66 | + gpt-5.5) for use without an API key. |
| 67 | + |
| 68 | +### Delegation tools |
| 69 | + |
| 70 | +- **`cursor_cloud_agent`** — launch a Cursor cloud (background) agent on a |
| 71 | + remote repo via `Agent.create({ cloud: { repos, autoCreatePR } })`; returns |
| 72 | + the agent id, terminal status, result, and PR url. Progress is collected from |
| 73 | + `run.onDidChangeStatus`, `onStep`, and `onDelta`. |
| 74 | +- **`cursor_delegate`** — run a single local Cursor turn as a permission-gated, |
| 75 | + auditable opencode tool call (reuses the provider's `acquireAgent` + |
| 76 | + `streamAgentTurn` plumbing). Both tools honor opencode's `permission` config |
| 77 | + via `ToolContext.ask` and are fail-closed when no permission gate is present. |
| 78 | + |
| 79 | +### Tooling |
| 80 | + |
| 81 | +- **Provider debug tracing** — opt-in via `OPENCODE_CURSOR_DEBUG=1`. |
| 82 | +- End-to-end CI: unit tests on two Node versions plus a full integration test |
| 83 | + (opencode loads the plugin, lists models, optionally runs a live chat turn). |
0 commit comments