cursor_api_sdk

package
v1.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2026 License: AGPL-3.0 Imports: 29 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CheckpointMiss    = "miss"    // no stored checkpoint for identity
	CheckpointHit     = "hit"     // system blob head matched; non-history merged
	CheckpointRebuild = "rebuild" // stored but system prompt changed
)

CheckpointMode describes how a prior sticky checkpoint was applied.

View Source
const (
	DefaultAPIBaseURL = "https://api2.cursor.sh"
	DefaultClientType = "cli"
)
View Source
const MaxToolResultChars = 8000

MaxToolResultChars caps OpenAI tool-result content before Cursor MCP submit / history rebuild.

Variables

View Source
var (
	ErrRateLimited      = errors.New("cursor rate limited")
	ErrUnauthorized     = errors.New("cursor unauthorized")
	ErrUpstream         = errors.New("cursor upstream error")
	ErrIncompleteRun    = errors.New("cursor run ended without turn_ended")
	ErrModelUnavailable = errors.New("cursor model unavailable for agent")
	ErrBadModelName     = errors.New("cursor bad model name")
	// ErrMissingBlob is a client payload bug (Structure bytes were not blob ids).
	// Account failover must not rotate — the same payload will fail again.
	ErrMissingBlob = errors.New("cursor missing blob")
)

Functions

func BuildConversationIdentity added in v1.4.0

func BuildConversationIdentity(id ConversationIdentity) string

BuildConversationIdentity returns otto-style "id:…" / "meta:…" or "" if none.

func BuildMcpToolDefinitions

func BuildMcpToolDefinitions(tools []OpenAIToolDef) ([]*cursorProto.McpToolDefinition, error)

BuildMcpToolDefinitions maps OpenAI tool defs to Cursor MCP descriptors.

func CapToolResult added in v1.5.0

func CapToolResult(content string) string

CapToolResult truncates oversized tool results on a UTF-8 safe boundary.

func ChecksumHeader

func ChecksumHeader(ids DeviceIDs, now time.Time) string

ChecksumHeader builds x-cursor-checksum for the given device ids.

func DecodeMcpArgsMap

func DecodeMcpArgsMap(args map[string][]byte) (string, error)

DecodeMcpArgsMap decodes Cursor MCP arg Value bytes into JSON object text.

func DeriveBridgeKey

func DeriveBridgeKey(modelID string, messages []ChatMessage) string

DeriveBridgeKey builds a stable key for parking/resuming a Run across tool turns.

func DeriveBridgeKeyWithIdentity added in v1.4.0

func DeriveBridgeKeyWithIdentity(modelID string, messages []ChatMessage, id ConversationIdentity) string

DeriveBridgeKeyWithIdentity prefers sticky identity for tool-park keys; falls back to DeriveBridgeKey (first-user hash) when identity is empty.

func DeriveConversationKey added in v1.4.0

func DeriveConversationKey(identity string) string

DeriveConversationKey hashes a non-empty identity seed (model-independent). Empty identity returns "".

func DeterministicConversationID added in v1.4.0

func DeterministicConversationID(convKey string) string

DeterministicConversationID builds a UUID-shaped id from a conversation key (otto deterministicConversationId) so Cursor can stick the conversation.

func EncodeMcpError

func EncodeMcpError(msg string) *cursorProto.McpResult

EncodeMcpError builds an mcpResult error payload.

func EncodeMcpSuccess

func EncodeMcpSuccess(text string) *cursorProto.McpResult

EncodeMcpSuccess builds a text mcpResult success payload.

func FormatModelParameters

func FormatModelParameters(params []ModelParameter) string

FormatModelParameters renders selection parameters as id=value pairs for logs/headers.

func FrameConnect

func FrameConnect(payload []byte, flags byte) []byte

FrameConnect wraps a protobuf payload in a Connect data frame.

func IsMissingBlob added in v1.3.0

func IsMissingBlob(err error) bool

IsMissingBlob reports whether err looks like Cursor "Blob not found" (inlined Structure bytes treated as sha256 ids).

func MergeCheckpointState added in v1.4.0

func MergeCheckpointState(checkpoint *cursorProto.ConversationStateStructure, root, turns [][]byte) *cursorProto.ConversationStateStructure

MergeCheckpointState keeps non-history fields from checkpoint and always replaces rootPromptMessagesJson + turns with freshly blobified history (oauth proxy.ts 819–824).

func ResolveModelID

func ResolveModelID(modelID string) string

ResolveModelID maps client-facing aliases to Cursor wire ids.

func SeedBlobStore added in v1.4.0

func SeedBlobStore(dst map[string][]byte, src map[string][]byte)

SeedBlobStore copies src blobs into dst without removing existing keys.

func StickyConversationID added in v1.4.0

func StickyConversationID(id ConversationIdentity) string

StickyConversationID returns a deterministic Cursor conversation_id when the client sent an OpenAI-like sticky id; otherwise "" (caller should use random). Deliberately skips weak first-user-hash fallback (support.md §4.9).

func SystemPromptCompatible added in v1.4.0

func SystemPromptCompatible(
	checkpoint *cursorProto.ConversationStateStructure,
	systemBlobIDs [][]byte,
	blobs map[string][]byte,
	systemPrompt string,
) bool

SystemPromptCompatible is true when blob IDs match (oauth) OR when the checkpoint's first root blob decodes to the same system prompt text. The text fallback covers server-echoed checkpoints that re-blobify root.

func SystemPromptMatches added in v1.4.0

func SystemPromptMatches(checkpoint *cursorProto.ConversationStateStructure, systemBlobIDs [][]byte) bool

SystemPromptMatches reports whether checkpoint root head equals systemBlobIDs (oauth proxy.ts 808–815).

func WithModelID

func WithModelID(err error, modelID string) error

WithModelID annotates an APIError with the requested model id when present.

Types

type APIError

type APIError struct {
	Status     int
	Code       string
	Message    string
	ModelID    string
	DebugError string // e.g. ERROR_BAD_MODEL_NAME from aiserver.v1.ErrorDetails
	Title      string
	Detail     string
	Err        error
}

APIError carries HTTP status and optional Connect error details.

func (*APIError) Error

func (e *APIError) Error() string

func (*APIError) Unwrap

func (e *APIError) Unwrap() error

type ChatMessage

type ChatMessage struct {
	Role       string           `json:"role"`
	Content    string           `json:"content"`
	ToolCallID string           `json:"tool_call_id,omitempty"`
	ToolCalls  []OpenAIToolCall `json:"tool_calls,omitempty"`
	// Images are decoded from multipart content (data/base64 only); not serialized.
	Images []Image `json:"-"`
}

ChatMessage is a minimal OpenAI chat message (tools-aware).

func (*ChatMessage) UnmarshalJSON added in v1.3.0

func (m *ChatMessage) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts OpenAI content as a string, null, or array of parts (OpenCode / Chat Completions multipart): flattens text and extracts images.

type CheckpointStore added in v1.4.0

type CheckpointStore struct {
	// contains filtered or unexported fields
}

CheckpointStore is an in-memory sticky checkpoint cache (TTL like tool bridges). Keys must come from DeriveConversationKey(identity); empty identity must not store.

func NewCheckpointStore added in v1.4.0

func NewCheckpointStore(ttl time.Duration) *CheckpointStore

NewCheckpointStore builds a TTL'd in-memory store.

func (*CheckpointStore) Get added in v1.4.0

Get returns a deep copy of the stored checkpoint, or nil on miss/expiry.

func (*CheckpointStore) Put added in v1.4.0

func (s *CheckpointStore) Put(key string, state *cursorProto.ConversationStateStructure, liveBlobs map[string][]byte)

Put captures/replaces checkpoint state for key, merging live blobs into the entry.

type Client

type Client struct {
	HTTP          *http.Client
	BaseURL       string // default api2.cursor.sh
	ClientVersion string // e.g. cli-YYYY.MM.DD-hash
	Device        DeviceIDs
	// contains filtered or unexported fields
}

Client is a Cursor upstream API client. Safe for concurrent use.

func (*Client) CachedModels added in v1.3.0

func (c *Client) CachedModels() []Model

CachedModels returns a copy of the in-process catalog when the TTL is still valid.

func (*Client) CollectText

func (c *Client) CollectText(ctx context.Context, accessToken string, payload *RunPayload) (string, error)

CollectText runs a chat and buffers the full assistant text (non-streaming helper).

func (*Client) ListModels

func (c *Client) ListModels(ctx context.Context, accessToken string) ([]Model, error)

ListModels calls AiService/AvailableModels; on failure returns a small fallback list.

func (*Client) ResolveAgentOrigin

func (c *Client) ResolveAgentOrigin(ctx context.Context, accessToken string) (string, error)

ResolveAgentOrigin returns the HTTPS origin for AgentService/Run. Uses GetServerConfig when possible; falls back to BaseURL / api2.

func (*Client) ResolveModelSelection

func (c *Client) ResolveModelSelection(ctx context.Context, accessToken, modelID string) (ModelSelection, error)

ResolveModelSelection maps an OpenAI model id onto Cursor ModelDetails/RequestedModel fields.

func (*Client) RunChat

func (c *Client) RunChat(ctx context.Context, accessToken string, payload *RunPayload) (<-chan StreamEvent, error)

RunChat opens AgentService/Run, handles KV/heartbeats, and emits text events. MCP tool calls without a bridge callback get an immediate error reply. The returned channel is closed when the run finishes.

func (*Client) StartRun

func (c *Client) StartRun(ctx context.Context, accessToken string, payload *RunPayload, bridgeTools bool) (*RunControl, error)

StartRun opens AgentService/Run. When bridgeTools is true, mcpArgs emit ToolCall events and the HTTP layer must park the RunControl and later SubmitMcpResults.

type ConversationIdentity added in v1.4.0

type ConversationIdentity struct {
	ConversationID string
	ThreadID       string
	SessionID      string
	User           string
	Metadata       map[string]any
}

ConversationIdentity carries OpenAI-like sticky ids (otto conversation/identity.ts). First non-empty wins: conversation_id → thread_id → session_id → user → metadata.*.

type ConversationTurn

type ConversationTurn struct {
	UserText      string
	AssistantText string
	// ToolResultTexts are inlined into history for ResumeAction rebuilds
	// (root role=user "[Tool Result]\n…"; turn steps as assistant messages).
	ToolResultTexts []string
}

ConversationTurn is a prior user/assistant pair, optionally with tool-result steps that followed a tool_calls assistant (oauth history kind:tool).

type DeviceIDs

type DeviceIDs struct {
	MachineID    string
	MacMachineID string // empty if no MAC
}

DeviceIDs are stable fingerprints embedded in x-cursor-checksum.

func GetDeviceIDs

func GetDeviceIDs() DeviceIDs

GetDeviceIDs returns process-cached stable device fingerprints.

type Image added in v1.3.0

type Image struct {
	Bytes    []byte
	MimeType string
	Filename string
}

Image is a decoded OpenAI/OpenCode image attachment (data-URL or raw base64 only).

type Model

type Model struct {
	ID               string           `json:"id"`
	Name             string           `json:"name,omitempty"`
	ServerModelName  string           `json:"server_model_name,omitempty"`
	LegacySlug       string           `json:"legacy_slug,omitempty"`
	Aliases          []string         `json:"aliases,omitempty"`
	SupportsThinking bool             `json:"supports_thinking,omitempty"`
	SupportsAgent    *bool            `json:"supports_agent,omitempty"`
	MaxMode          bool             `json:"max_mode,omitempty"`
	Parameters       []ModelParameter `json:"parameters,omitempty"`
}

Model is a Cursor picker catalog entry mapped for OpenAI /v1/models.

type ModelParameter

type ModelParameter struct {
	ID    string `json:"id"`
	Value string `json:"value"`
}

ModelParameter is a Cursor RequestedModel parameter (context, reasoning, …).

type ModelSelection

type ModelSelection struct {
	PublicID      string
	WireModelID   string
	DisplayName   string
	Parameters    []ModelParameter
	MaxMode       bool
	SupportsAgent *bool
}

ModelSelection is the wire identity used for AgentService/Run.

func LiteralModelSelection

func LiteralModelSelection(modelID string) ModelSelection

LiteralModelSelection is used when the catalog has no entry for modelID.

func SelectionFromModel

func SelectionFromModel(m Model) ModelSelection

SelectionFromModel builds a Run selection from a catalog entry. AgentService/Run validates ModelDetails.model_id against legacy slugs for some vendors (e.g. Anthropic), so WireModelID prefers variant legacySlug.

type OpenAIToolCall

type OpenAIToolCall struct {
	ID       string `json:"id"`
	Type     string `json:"type"`
	Function struct {
		Name      string `json:"name"`
		Arguments string `json:"arguments"`
	} `json:"function"`
}

OpenAIToolCall is an assistant tool_calls[] entry.

type OpenAIToolDef

type OpenAIToolDef struct {
	Type     string `json:"type"`
	Function struct {
		Name        string          `json:"name"`
		Description string          `json:"description"`
		Parameters  json.RawMessage `json:"parameters"`
	} `json:"function"`
}

OpenAIToolDef is the OpenAI tools[] entry we accept.

type ParsedChat

type ParsedChat struct {
	SystemPrompt string
	Turns        []ConversationTurn
	UserText     string
	// UserImages are action-turn attachments only (history stays text-only).
	UserImages  []Image
	ToolResults []ToolResultInfo
	// StickyConversationID, when set, is used as AgentRunRequest.conversation_id
	// instead of a random UUID (P2.1 identity keying).
	StickyConversationID string
}

ParsedChat is the OpenAI → Cursor mapping of a chat request.

func ParseChatMessages

func ParseChatMessages(messages []ChatMessage) ParsedChat

ParseChatMessages splits OpenAI messages into system / history / current user / tool results. Image parts on the action user are kept; prior user images are dropped (history text-only).

Empty trailing user (no pending user action) is left empty so BuildRunPayload can emit ResumeAction over reconstructed history — we deliberately do not replay the last user text as a fake action (oauth proxy.ts 665–667, 840–856).

type PendingExec

type PendingExec struct {
	ExecID      string
	ExecMsgID   uint32
	ToolCallID  string
	ToolName    string
	DecodedArgs string
}

PendingExec is a Cursor mcpArgs call waiting for an OpenAI tool result.

type RunControl

type RunControl struct {
	Events <-chan StreamEvent
	// contains filtered or unexported fields
}

RunControl owns a live AgentService/Run stream that can pause for tool results.

func (*RunControl) Close

func (r *RunControl) Close()

Close cancels the run and closes the request pipe.

func (*RunControl) Pending

func (r *RunControl) Pending() []PendingExec

Pending returns a copy of mcpArgs waiting for OpenAI tool results.

func (*RunControl) Recv

func (r *RunControl) Recv() (StreamEvent, bool)

Recv returns the next stream event, preferring any unread preface events.

func (*RunControl) SubmitMcpResults

func (r *RunControl) SubmitMcpResults(results []ToolResultInfo) error

SubmitMcpResults writes mcpResult frames for parked pending execs and clears them.

func (*RunControl) TryRecv

func (r *RunControl) TryRecv() (StreamEvent, bool)

TryRecv returns a buffered/preface event without blocking.

func (*RunControl) Unread

func (r *RunControl) Unread(ev StreamEvent)

Unread pushes an event so the next Recv observes it first (FIFO among unread).

func (*RunControl) Usage added in v1.3.0

func (r *RunControl) Usage() Usage

Usage returns the Path A token meter accumulated on this run so far.

type RunPayload

type RunPayload struct {
	RequestBytes []byte
	BlobStore    map[string][]byte // hex(blobID) → bytes
	Conversation string
	ModelID      string
	// Tools is echoed into exec request_context replies (may be empty).
	Tools []*cursorProto.McpToolDefinition
	// CheckpointMode is miss|hit|rebuild for sticky P2.2 logging.
	CheckpointMode string
	// CheckpointKey, when set, captures conversation_checkpoint_update into the store.
	CheckpointKey string
	// OnCheckpoint is invoked on each ConversationCheckpointUpdate (may be nil).
	OnCheckpoint func(state *cursorProto.ConversationStateStructure, blobs map[string][]byte)
}

RunPayload is a framed-ready AgentClientMessage plus local blob store for KV.

func BuildRunPayload

func BuildRunPayload(modelID string, parsed ParsedChat) (*RunPayload, error)

BuildRunPayload builds an AgentClientMessage run_request (blob system prompt strategy).

func BuildRunPayloadSelection

func BuildRunPayloadSelection(sel ModelSelection, parsed ParsedChat) (*RunPayload, error)

BuildRunPayloadSelection builds a run request using catalog-resolved model identity. ModelDetails.model_id and RequestedModel.model_id use the agent wire id (legacy slug when present). OpenAI response model id stays the public/catalog id.

Every ConversationState Structure `bytes` field is a 32-byte sha256 blob id; raw bytes live only in RunPayload.BlobStore (served by handleKV getBlob).

func BuildRunPayloadWithCheckpoint added in v1.4.0

func BuildRunPayloadWithCheckpoint(sel ModelSelection, parsed ParsedChat, prior *StoredCheckpoint) (*RunPayload, error)

BuildRunPayloadWithCheckpoint builds a run request, optionally merging a prior sticky checkpoint.

type StoredCheckpoint added in v1.4.0

type StoredCheckpoint struct {
	State *cursorProto.ConversationStateStructure
	Blobs map[string][]byte
}

StoredCheckpoint is an identity-keyed capture of ConversationStateStructure plus companion blobs referenced by that state (oauth proxy.ts 1477–1486).

type StreamEvent

type StreamEvent struct {
	Text       string
	Thinking   bool
	TurnEnded  bool
	ToolCall   *PendingExec
	Err        error
	HTTPStatus int
}

StreamEvent is a high-level event from AgentService/Run.

type ToolResultInfo

type ToolResultInfo struct {
	ToolCallID string
	Content    string
}

ToolResultInfo is a role=tool message payload.

type Usage added in v1.3.0

type Usage struct {
	PromptTokens     int
	CompletionTokens int
	TotalTokens      int
}

Usage is the OpenAI chat/completions token meter (Path A / otto). prompt = max(checkpoint.usedTokens); completion = Σ token_delta; total = sum.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL