Skip to content

fix(cursor): the server runs without @cursor/sdk installed - #162

Merged
Nurozen merged 2 commits into
mainfrom
fix/cursor-sdk-optional
Oct 30, 2026
Merged

Nurozen merged 2 commits into
mainfrom
fix/cursor-sdk-optional

Conversation

@Nurozen

@Nurozen Nurozen commented Oct 30, 2026 •

Copy link
Copy Markdown
Owner

packages/provider-cursor/src/server/sdk.ts required @cursor/sdk when the module loaded, and the server imports it statically, so the server crashed at startup whenever the package was missing. @cursor/sdk is proprietary ("All rights reserved", use subject to Cursor's ToS), so apps that bundle the Lecturn server, such as RocketWright's sidecar, need to be able to leave it out of their release builds.

Fix

  • The CursorSdk service now exposes load, which requires the SDK the first time Cursor is actually used and caches it. sdk.ts is gone; type-only imports are unchanged.
  • Only MODULE_NOT_FOUND for @cursor/sdk itself becomes CursorSdkNotInstalledError. A missing dependency inside an installed SDK, or any other load failure, still surfaces as a defect.
  • checkCursorProviderStatus reports Cursor as installed: false, status: "error" with "Cursor SDK (@cursor/sdk) is not installed with this Lecturn server.", the same way a provider with a missing CLI reports. The runner, text generation, browser sign-in and catalog fail with that message instead of crashing.
  • The adapter's runner-failure classifier unwraps the missing-SDK error so turn start records that message, and matches the SDK's ConfigurationError by the name the SDK sets, because the class is no longer imported up front. Sign-in and text generation use the same fixed text for detail.

Lecturn still depends on and ships @cursor/sdk, so nothing changes when it is installed. There is no feature flag.

Verification

  • New: a subprocess test in CursorSdk.test.ts makes @cursor/sdk unresolvable before the provider loads, imports the provider entry, and checks that the real loader reports not installed. It fails if an eager require or import comes back. adapter.test.ts checks that a turn start without the SDK records the not-installed message. CursorSdk.test.ts also checks that only a missing @cursor/sdk counts as not installed and a missing nested dependency dies. status.test.ts checks that the provider reports not installed through an injected loader that throws MODULE_NOT_FOUND. ProviderInstanceRegistry.test.ts checks that with the SDK absent, Cursor reports not installed while a Codex instance beside it still probes ready.
  • Provider-cursor suite: 141/141 pass (from the package dir; four probe tests in CursorSdk.test.ts need that cwd, unchanged by this PR). ProviderInstanceRegistry.test.ts 11/11 and scripts/lib/cursor-sdk-packaging.test.ts pass. The packaging test's probe now loads through CursorSdk.layer.
  • tsc-rs --noEmit is clean for packages/provider-cursor, apps/server and scripts. vp lint on the touched files raises no new warnings. knip --exports for provider-cursor and apps/server is clean.
  • Real Node: I temporarily renamed packages/provider-cursor/node_modules/@cursor/sdk. apps/server/src/server.ts then imports cleanly, and the live CursorSdk.layer returns CursorSdkNotInstalledError using Node's real Cannot find module '@cursor/sdk' error. With the same setup, origin/main's sdk.ts throws on import.

Written by Claude Opus 5.5 (claude-opus-5-5) in Claude Code.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5 Tier: apex

The PR appears safe to merge; all previous findings are addressed and no new actionable issues remain.

Summary

Defers loading @cursor/sdk until Cursor is used, so leaving it out no longer breaks server imports.

  • The server can load Cursor without loading its SDK.
  • Cursor status names the SDK when it is missing.
  • Cursor actions show a clear error when the SDK is missing.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A["Import Cursor provider"] --> B["Define services without loading SDK"]
  C["Use Cursor"] --> D["CursorSdk.load"]
  D --> E{"Load result"}
  E -->|Installed| F["Cache SDK and continue"]
  E -->|SDK package missing| G["Return CursorSdkNotInstalledError"]
  E -->|Other load failure| H["Keep original defect"]
Loading

Reviews (2) · Last reviewed commit: "fix(cursor): keep the missing-SDK messag..." · Reviewed by Greptile

@cursor/sdk is proprietary ("All rights reserved"), so apps that bundle
the Lecturn server need to be able to leave it out. sdk.ts required it at
module load, so the server crashed at startup when it was missing.

The CursorSdk service now loads the SDK on first use. Only
MODULE_NOT_FOUND for @cursor/sdk itself becomes CursorSdkNotInstalledError;
any other load failure still surfaces as a defect. The status check reports
Cursor as not installed through the normal provider status path, and the
runner, text generation, sign-in and catalog fail with the same message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The runner wrapped CursorSdkNotInstalledError in its generic "agent.create
failed" error, and turn start recorded that instead of the reason. The
adapter now unwraps it, so the recorded message names the missing SDK.

Sign-in and text generation use the fixed not-installed text for `detail`
instead of copying cause.message.

A subprocess test makes @cursor/sdk unresolvable before the provider loads,
so an eager SDK import or require anywhere in the provider fails it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nurozen
Nurozen merged commit 847fc19 into main Oct 30, 2026
15 checks passed
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