feat: Cursor SDK harness (cursor-sdk) alongside existing cursor CLI harness#569
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
ff16b30 to
ae943bd
Compare
…ite3 failure The static top-level import caused the entire daemon to crash at startup if sqlite3's native binary failed to load (ABI mismatch, wrong Node version, or unsupported platform). Replace with a lazy dynamic import via loadSdk() so that: - isInstalled() returns false when the SDK can't be loaded (harness hides gracefully instead of crashing the daemon) - listModels() and spawn() call loadSdk() at runtime and surface the error only to that specific operation - All other harnesses are unaffected when cursor-sdk native deps fail Ref: https://forum.cursor.com/t/cursor-sdk-in-public-beta/159285 (sqlite3 native dep known issue; Cursor team working on custom store alternative) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…DK check
BaseCLIAgentService.detectInstallationEffect() checks for a CLI binary named
after the service's command ('cursor-sdk'). No such binary exists — the SDK
harness authenticates via CURSOR_API_KEY, not a CLI tool. This caused the
harness to always appear as NotInstalled and never show in the UI.
Override detectInstallationEffect() to delegate to isInstalled() (checks
CURSOR_API_KEY presence + successful @cursor/sdk native module load), matching
the actual installation semantics of this SDK-based harness.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Lists all registered harnesses and their detection status on the current machine — useful for debugging why a harness is or isn't appearing in the UI without needing to inspect daemon logs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…resolution
Bun was inlining @cursor/sdk into the bundle. When bundled, the SDK's
internal require('sqlite3') resolved from dist/index.js's context, where
sqlite3 is not reachable due to pnpm's isolation. Marking @cursor/sdk as
external keeps it as a real runtime import so sqlite3 resolves correctly
from the SDK's own node_modules.
This fixes cursor-sdk showing "not installed" even when CURSOR_API_KEY is set.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…validation Moves the build flags from a long inline CLI command to a dedicated build.config.ts using the Bun.build() API. TypeScript's BuildConfig type from @types/bun provides compile-time schema validation — invalid options are caught by tsc before the build runs. The package.json build script is now a concise two-step: typecheck then run the config file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…calls - name: labels each agent as "role@chatroomId" in Agent.list() for observability - local.force: true on send() clears wedged runs left by crashed daemon processes - idempotencyKey: unique per spawn prevents double-execution on network retries Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Enables the SDK sandbox for local agents. The exact OS-level restrictions aren't documented in the SDK, but enabling it applies whatever policy Cursor loads — useful for limiting agent surface area during testing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The sandbox was too restrictive and caused the agent to stop working. Reverting to the previous state without sandbox until the SDK documents exactly what it restricts. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…wn across all harnesses AgentProcessManager.doStop() was directly calling kill(-pid, 'SIGTERM') and bypassing service.stop(pid). For CLI harnesses this worked, but for cursor-sdk the actual SDK run lives as an async IIFE in the daemon process — killing the keeper placeholder didn't stop the Cursor SDK run or call run.cancel()/agent.close(). Now doStop() delegates to the harness-registered service.stop(pid), which properly: - For CLI harnesses: sends SIGTERM to process group + polls (BaseCLIAgentService.stop) - For cursor-sdk: cancels SDK run, closes agent, then kills keeper (override in CursorSdkAgentService) Falls back to direct kill-and-poll when no service is registered for the harness. Also explicitly calls service.untrack(pid) after stop() since handleExit() returns early in 'stopping' state and won't untrack otherwise. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ces. Documents CLI-based and SDK-based harness patterns so future contributors can implement new runtimes without spelunking existing code. Co-authored-by: Cursor <cursoragent@cursor.com>
Guard run.wait() when session is aborted to avoid hanging the background IIFE for up to an hour. Pass SIGTERM on cancelled exits and use logPrefix for stderr error lines. Add test covering abort-during-stream path. Co-authored-by: Cursor <cursoragent@cursor.com>
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
cursor-sdkremote agent harness using@cursor/sdk(Agent.create+agent.send+run.stream()), mirroring the existingopencode/opencode-sdkdual-harness pattern.cursorCLI harness unchanged; both appear in the UI as Cursor (CLI) and Cursor (SDK).packages/cli/src/infrastructure/services/remote-agents/cursor-sdk/(service, stream adapter, tests).Changes
@cursor/sdkdependency,CursorSdkAgentService,CursorSdkStreamAdapter, registry registrationHARNESS_DISPLAY_NAMES,isCursorSdkHarness(), test updatescursor-sdkadded toAGENT_HARNESSESAuth / availability
CURSOR_API_KEY;isInstalled()returns false when missing so the harness auto-hides.Verification
pnpm typecheck— passpnpm test— passTest plan
CURSOR_API_KEYis set on the machineMade with Cursor