Skip to content

Feat/bridge setup - #7

Merged
remdev merged 4 commits into
mainfrom
feat/bridge-setup
Jun 14, 2026
Merged

Feat/bridge setup#7
remdev merged 4 commits into
mainfrom
feat/bridge-setup

Conversation

@remdev

@remdev remdev commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • npm bridge 0.0.2: global bin points at dist/bin/cursor-sdk-bridge.js (fixes broken Homebrew/npm global install with shell wrapper); dev shell launcher kept for CURSOR_SDK_BRIDGE_ROOT.
  • go run ./cmd/setup: installs @cursor-go-sdk/cursor-sdk-bridge@0.0.2 globally or builds/links from a clone (--local).
  • SDK root-cause fixes:
    • dropEmpty: empty maps no longer leak into wire as cloud: {} (was triggering idempotency on local agents).
    • Idempotency keys only for cloud agents (opts.Cloud != nil / bc-* on Send).
    • Bridge subprocess no longer tied to caller context (exec.Command + startup-only ctx); fixes connection refused after tests/RPC cancel.
    • Bridge resolution: semver gate >= 0.0.2, launch via node + .js entrypoint, prefer dist/ in CURSOR_SDK_BRIDGE_ROOT.
  • Local e2e: opt-in suite (-tags=e2e, CURSOR_E2E=1, real CURSOR_API_KEY); ./scripts/run-e2e.sh.
  • examples/basic: CURSOR_MODEL env (default composer-2), explicit API key check.

Motivation

Global npm install -g @cursor-go-sdk/cursor-sdk-bridge@0.0.1 symlinked a shell script; when invoked via Homebrew, $0 resolved to /opt/homebrew/bin/... and the script looked for JS in /opt/homebrew/dist/MODULE_NOT_FOUND.

Separately, Go SDK had wire/lifecycle bugs: phantom cloud: {} caused spurious idempotency keys on local CreateAgent, and exec.CommandContext killed the bridge when the caller context was cancelled.

Test plan

  • go test ./...
  • go test -tags=e2e -parallel=1 ./e2e/... with CURSOR_E2E=1 and CURSOR_API_KEY (local only, not CI)
  • Publish @cursor-go-sdk/cursor-sdk-bridge@0.0.2 to npm before users rely on go run .../cmd/setup@latest
  • After publish: npm install -g @cursor-go-sdk/cursor-sdk-bridge@0.0.2 on a clean machine
  • go run ./examples/basic / ./scripts/run-e2e.sh

Post-merge

  1. Publish npm 0.0.2 (cd bridge && npm publish --access public).
  2. Tag optional: cursor-sdk-bridge-v0.0.2.

Files (high level)

Area Changes
bridge/ version 0.0.2, npm bin → JS, remove bin/ from published files
cmd/setup/, cursor/setup.go, internal/bridge/setup.go prerequisite installer
internal/bridge/ resolve, version gate, lifecycle fix, launch argv
cursor/ dropEmpty, idempotency, cloud detection
e2e/, scripts/run-e2e.sh local integration tests
docs README, CONTRIBUTING, AGENTS, references

remdev added 2 commits June 14, 2026 14:11
Point npm bin at dist/bin/cursor-sdk-bridge.js so global installs resolve the package correctly, bump bridge to 0.0.2, and add cmd/setup plus cursor.Setup for npm global or local clone installs.
Correct dropEmpty preserve logic that leaked empty cloud blocks, stop
sending idempotency keys for local agents, decouple bridge subprocess
lifetime from caller context, enforce bridge >=0.0.2, and add opt-in
e2e coverage with scripts/run-e2e.sh.
Copilot AI review requested due to automatic review settings June 14, 2026 11:54

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the bridge installation/launch workflow for local agents and adds opt-in local end-to-end tests, while fixing SDK wire/lifecycle behaviors that caused spurious cloud/idempotency behavior and flaky bridge subprocess shutdowns.

Changes:

  • Add go run .../cmd/setup prerequisite installer (global npm install or local clone build/link) and update docs accordingly.
  • Update bridge resolution/launching to support the npm 0.0.2 layout (JS entrypoint via node) and add minimum-version gating.
  • Fix local-vs-cloud wire shaping and idempotency behavior; add opt-in local e2e test suite + runner script.

Reviewed changes

Copilot reviewed 32 out of 34 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
scripts/run-e2e.sh Adds a guarded local e2e test runner wrapper.
references/bridge.md Updates bridge install/dev instructions and env var semantics.
README.md Documents setup command, local e2e usage, and config vars.
internal/bridge/version.go Adds bridge version detection + semver gating helpers.
internal/bridge/version_test.go Tests version comparison helper.
internal/bridge/setup.go Adds programmatic prerequisite install (global/local).
internal/bridge/setup_test.go Tests bridge-dir discovery helper.
internal/bridge/resolve.go Resolves launch argv (node + .js) vs direct exec.
internal/bridge/resolve_test.go Tests resolution for npm 0.0.2 layout and launch argv behavior.
internal/bridge/npm.go Pins minimum required npm bridge version.
internal/bridge/install.go Improves “not found” guidance and root entrypoint selection.
internal/bridge/bridge.go Decouples bridge process lifetime from caller ctx after startup; uses resolved argv.
internal/bridge/bridge_test.go Adds integration-ish launch tests for ctx-cancel survival.
examples/basic/main.go Adds explicit API key check and model env override.
e2e/sdk_test.go Adds opt-in real-API integration tests (bridge version, prompt, etc.).
e2e/harness_test.go Adds e2e harness helpers and environment gating.
e2e/examples_test.go Adds e2e tests for running examples/building quickstart.
e2e/doc.go Documents how to run the e2e suite.
cursor/wire.go Fixes dropEmpty behavior for empty maps; adds cloud-options detection helper.
cursor/wire_internal_test.go Adds tests for dropEmpty and cloud-options detection.
cursor/setup.go Adds public SDK Setup wrapper for bridge prerequisite install.
cursor/cursor_test.go Ensures local wire omits cloud entirely.
cursor/client.go Restricts idempotency key behavior to cloud; updates cloud-RPC detection logic.
cursor/client_internal_test.go Tests idempotency-key behavior for local vs cloud CreateAgent.
cursor/agent.go Restricts Send idempotency key to cloud agent IDs.
CONTRIBUTING.md Updates contributor workflow and adds local e2e instructions.
cmd/setup/main.go Adds cmd/setup CLI entrypoint for prerequisites.
bridge/src/constants.ts Bumps bridge version constant to 0.0.2.
bridge/README.md Documents install via Go setup and local clone workflow.
bridge/PUBLISHING.md Updates publishing notes for new bin layout and 0.0.2 install example.
bridge/package.json Bumps to 0.0.2; npm bin points directly to built JS; adjusts published files.
bridge/package-lock.json Lockfile updates to match 0.0.2 and bin entrypoint.
bridge/bin/cursor-sdk-bridge Improves dev/local shell launcher symlink resolution.
AGENTS.md Updates “before coding” workflow and documents e2e location.
Files not reviewed (1)
  • bridge/package-lock.json: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/bridge/setup.go Outdated
var ok bool
bridgeDir, ok = findBridgeDir("")
if !ok {
return fmt.Errorf("bridge/ not found; run from a cursor-go-sdk clone or pass --local with CURSOR_SDK_BRIDGE_ROOT")
Comment thread internal/bridge/version.go Outdated
Comment on lines +102 to +105
func parseSemver(version string) (major, minor, patch int, ok bool) {
version = strings.TrimPrefix(strings.TrimSpace(version), "v")
parts := strings.Split(version, ".")
if len(parts) < 3 {
Comment on lines +54 to +82
func bridgePackageRoot(entry string) (string, error) {
abs, err := filepath.Abs(entry)
if err != nil {
return "", err
}
jsSuffix := filepath.Join("dist", "bin", "cursor-sdk-bridge.js")
if strings.HasSuffix(abs, jsSuffix) {
return filepath.Dir(filepath.Dir(filepath.Dir(abs))), nil
}
binSuffix := filepath.Join("bin", launcherName())
if strings.HasSuffix(abs, binSuffix) {
return filepath.Dir(filepath.Dir(abs)), nil
}
if strings.Contains(abs, string(filepath.Separator)+"node_modules"+string(filepath.Separator)) {
dir := filepath.Dir(abs)
for {
pkgJSON := filepath.Join(dir, "package.json")
if isBridgePackage(pkgJSON) {
return dir, nil
}
parent := filepath.Dir(dir)
if parent == dir {
break
}
dir = parent
}
}
return "", fmt.Errorf("cannot locate bridge package root from %q", entry)
}
Comment thread README.md Outdated
| `CURSOR_E2E` | Set to `1` to enable local e2e tests in `e2e/` |
| `CURSOR_E2E_MODEL` | Model for e2e (default `auto`, falls back to `CURSOR_MODEL`) |
| `CURSOR_SDK_BRIDGE_BIN` | Override bridge launcher binary |
| `CURSOR_SDK_BRIDGE_ROOT` | Directory with `bin/cursor-sdk-bridge` |
Honor CURSOR_SDK_BRIDGE_ROOT in local setup, harden semver parsing and
package-root discovery, and align docs with the npm 0.0.2 layout.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 34 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • bridge/package-lock.json: Generated file

Comment thread internal/bridge/setup.go Outdated
Comment on lines +39 to +43
func setupGlobal(ctx context.Context, version string) error {
if version == "" {
version = BridgeNpmVersion
}
pkg := bridgePackage + "@" + version
Comment thread cmd/setup/main.go Outdated
func main() {
local := flag.Bool("local", false, "install from ./bridge in a repository clone (npm ci && npm run build && npm link)")
bridgeDir := flag.String("bridge-dir", "", "path to bridge/ (implies --local when set)")
version := flag.String("version", "", "npm version for global install (default: pinned release)")
Comment on lines +81 to +97
func semverAtLeast(version, min string) bool {
vMajor, vMinor, vPatch, ok := parseSemver(version)
if !ok {
return false
}
mMajor, mMinor, mPatch, ok := parseSemver(min)
if !ok {
return false
}
if vMajor != mMajor {
return vMajor > mMajor
}
if vMinor != mMinor {
return vMinor > mMinor
}
return vPatch >= mPatch
}
Comment on lines +21 to +23
{"0.0.2+meta", "0.0.2", true},
{"0.0.2-beta", "0.0.2", true},
{"0.0.1-rc1", "0.0.2", false},
Validate --version before global npm install, clarify setup errors when
version checks fail, and compare prereleases correctly while still
ignoring build metadata.
@remdev
remdev merged commit 4d78ff8 into main Jun 14, 2026
1 check passed
@remdev
remdev deleted the feat/bridge-setup branch June 14, 2026 14:00
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.

2 participants