mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-17 03:27:02 +08:00
- Renamed test function to better reflect its purpose. - Enhanced model details structure by adding DisplayName and DisplayNameShort fields in buildCLIModelDetails. - Updated test cases to validate the new fields and ensure correct functionality.
963 lines
38 KiB
Go
963 lines
38 KiB
Go
package upstream
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"html"
|
|
"strings"
|
|
"time"
|
|
|
|
legacyruntime "cursor/internal/runtime"
|
|
)
|
|
|
|
const (
|
|
availableModelsDisableUnusedHours = 2400000
|
|
availableModelsUpgradeHours = 2
|
|
|
|
modelRuntimeThinkingEffortParameterID = "thinking_effort"
|
|
|
|
// localPathEncryptionKey — стабильный ключ шифрования путей для индексации
|
|
// репозитория, который cursor-agent CLI запрашивает через GetServerConfig
|
|
// (indexingConfig.default{User,Team}PathEncryptionKey). Без него CLI
|
|
// не может инициализировать repo identity в git-воркспейсе и вызовы
|
|
// файловых инструментов падают с "[unimplemented] HTTP 404".
|
|
localPathEncryptionKey = "6f6e63652d6c6f63616c2d706174682d656e6372797074696f6e2d6b6579"
|
|
|
|
localUltraMembershipType = "ultra"
|
|
localUltraPaymentID = "local_ultra"
|
|
localUltraSubscriptionStatus = "active"
|
|
localUltraPlanIncludedCents = 20000
|
|
localUltraDashboardUserID = 1
|
|
localUltraBillingCycleDuration = 30 * 24 * time.Hour
|
|
|
|
bootstrapStatsigGlassModeAvailableGate = "glass_mode_available"
|
|
bootstrapStatsigGlassOpenAgentInWindowGate = "glass.enable_open_agent_in_window"
|
|
bootstrapStatsigOpenAgentsTitlebarGate = "glass_open_agents_titlebar_button"
|
|
bootstrapStatsigOpenAgentWindowTopGate = "open_agent_window_top"
|
|
bootstrapStatsigOpenAgentWindowBottomGate = "open_agent_window_bottom_convo"
|
|
bootstrapStatsigNALAgentRetriesGate = "nal_agent_retries"
|
|
bootstrapStatsigNALFreshRetryIDsGate = "nal_fresh_retry_ids"
|
|
bootstrapStatsigUseModelParametersGate = "use_model_parameters"
|
|
bootstrapStatsigUseReactModelPickerGate = "use_react_model_picker"
|
|
bootstrapStatsigIDECmdEnterSubmitGate = "ide_cmd_enter_submit"
|
|
bootstrapStatsigContextVisualizerGate = "context_visualizer"
|
|
bootstrapStatsigWysiwygMarkdownGate = "wysiwyg_markdown"
|
|
bootstrapStatsigWysiwygMarkdownDefaultGate = "wysiwyg_markdown_default"
|
|
bootstrapStatsigSubagentSupportInterrupt = "subagent_support_interrupt"
|
|
bootstrapStatsigExplicitSubagentModels = "explicit_subagent_models"
|
|
bootstrapStatsigMcpDirectClientToolFetch = "mcp_direct_client_tool_fetch"
|
|
bootstrapStatsigGlassCustomThemeSupport = "glass_custom_theme_support"
|
|
bootstrapStatsigGlassAutomationsUI = "glass_automations_ui"
|
|
bootstrapStatsigTerminalUI2 = "terminal_ui_2"
|
|
bootstrapStatsigDisableTerminalOutputUIStreaming = "disable_terminal_output_ui_streaming"
|
|
bootstrapStatsigBrowserCanvas = "browser_canvas"
|
|
bootstrapStatsigEnableMultitaskMode = "enable_multitask_mode"
|
|
bootstrapStatsigDecomposeAlwaysLocalExtHostGate = "decompose_always_local_ext_host"
|
|
bootstrapStatsigCursorExtensionsIsolationV2Gate = "cursor_extensions_isolation_v2"
|
|
bootstrapStatsigCursorAgentWorkerExtension = "enable_cursor_agent_worker_extension"
|
|
bootstrapStatsigExperimentName = "free_user_model_picker"
|
|
bootstrapStatsigVariantParam = "variant"
|
|
bootstrapStatsigVariantControl = "control"
|
|
bootstrapStatsigVariantLockedPicker = "locked_picker"
|
|
bootstrapStatsigVariantGrayedModels = "grayed_models"
|
|
bootstrapStatsigProductTipsConfigName = "product_tips_config"
|
|
bootstrapStatsigIdleExtensionHostKiller = "idle_extension_host_killer_config"
|
|
bootstrapStatsigIdleMinutesToKill = "idleMinutesToKillExtensionHost"
|
|
bootstrapStatsigFreeMemoryPercentageToKill = "freeMemoryPercentageToKillExtensionHost"
|
|
bootstrapStatsigHTTP2PingConfig = "http2_ping_config"
|
|
bootstrapStatsigHTTP1KeepaliveConfig = "http1_keepalive_config"
|
|
bootstrapStatsigHTTP2AgentPoolConfig = "http2_agent_connection_pool_config"
|
|
bootstrapStatsigCanvasPromptTextConfig = "canvas_prompt_text_config"
|
|
bootstrapStatsigEditorBugbotConfig = "editor_bugbot_config"
|
|
bootstrapStatsigExtensionMonitorControl = "extension_monitor_control"
|
|
bootstrapStatsigExtensionSignatureBypass = "extension_signature_verification_bypass_list"
|
|
bootstrapStatsigGCTraceControl = "gc_trace_control"
|
|
bootstrapStatsigInlineDiffPerformance = "inline_diff_performance_config"
|
|
bootstrapStatsigLeakedDisposablesTracker = "leaked_disposables_tracker"
|
|
bootstrapStatsigMcpIPCTimeouts = "mcp_ipc_timeouts"
|
|
bootstrapStatsigMcpWakeProbeConfig = "mcp_wake_probe_config"
|
|
bootstrapStatsigNALStallDetectorTimeout = "nal_stall_detector_timeout_config"
|
|
bootstrapStatsigSimulatedThinkingErrorTimeout = "simulated_thinking_error_timeout"
|
|
bootstrapStatsigPlaywrightLogConfigs = "playwright_log_configs"
|
|
bootstrapStatsigRetryInterceptorParams = "retry_interceptor_params_config"
|
|
bootstrapStatsigSandboxNetworkAllowlist = "sandbox_default_network_allowlist"
|
|
bootstrapStatsigUpdatePromptConfig = "update_prompt_config"
|
|
bootstrapStatsigLocalDefaultRule = "local_default"
|
|
)
|
|
|
|
type statsigSecondaryExposure struct {
|
|
Gate string `json:"gate,omitempty"`
|
|
GateValue string `json:"gateValue,omitempty"`
|
|
GateValueSnake string `json:"gate_value,omitempty"`
|
|
RuleID string `json:"ruleID,omitempty"`
|
|
RuleIDSnake string `json:"rule_id,omitempty"`
|
|
}
|
|
|
|
type statsigDynamicConfigTemplate struct {
|
|
Name string `json:"name"`
|
|
Value map[string]any `json:"value"`
|
|
RuleID string `json:"rule_id"`
|
|
RuleIDCamel string `json:"ruleID"`
|
|
GroupName string `json:"group_name"`
|
|
GroupNameCamel string `json:"groupName"`
|
|
SecondaryExposures []statsigSecondaryExposure `json:"secondary_exposures"`
|
|
SecondaryExposuresCamel []statsigSecondaryExposure `json:"secondaryExposures"`
|
|
UndelegatedSecondaryExposures []statsigSecondaryExposure `json:"undelegated_secondary_exposures"`
|
|
UndelegatedSecondaryExposuresCamel []statsigSecondaryExposure `json:"undelegatedSecondaryExposures"`
|
|
IsDeviceBased bool `json:"is_device_based"`
|
|
IsDeviceBasedCamel bool `json:"isDeviceBased"`
|
|
IsExperimentActive bool `json:"is_experiment_active"`
|
|
IsExperimentActiveCamel bool `json:"isExperimentActive"`
|
|
IsUserInExperiment bool `json:"is_user_in_experiment"`
|
|
IsUserInExperimentCamel bool `json:"isUserInExperiment"`
|
|
}
|
|
|
|
type statsigBootstrapTemplate struct {
|
|
FeatureGates map[string]map[string]any `json:"feature_gates"`
|
|
DynamicConfigs map[string]statsigDynamicConfigTemplate `json:"dynamic_configs"`
|
|
LayerConfigs map[string]map[string]any `json:"layer_configs"`
|
|
User map[string]any `json:"user"`
|
|
HasUpdates bool `json:"has_updates"`
|
|
HashUsed string `json:"hash_used"`
|
|
SDKParams map[string]any `json:"sdkParams"`
|
|
Time int64 `json:"time"`
|
|
}
|
|
|
|
var bootstrapStatsigTemplate = statsigBootstrapTemplate{
|
|
FeatureGates: map[string]map[string]any{
|
|
bootstrapStatsigGlassModeAvailableGate: buildEnabledStatsigGate(bootstrapStatsigGlassModeAvailableGate),
|
|
bootstrapStatsigGlassOpenAgentInWindowGate: buildEnabledStatsigGate(bootstrapStatsigGlassOpenAgentInWindowGate),
|
|
bootstrapStatsigOpenAgentsTitlebarGate: buildEnabledStatsigGate(bootstrapStatsigOpenAgentsTitlebarGate),
|
|
bootstrapStatsigOpenAgentWindowTopGate: buildEnabledStatsigGate(bootstrapStatsigOpenAgentWindowTopGate),
|
|
bootstrapStatsigOpenAgentWindowBottomGate: buildEnabledStatsigGate(bootstrapStatsigOpenAgentWindowBottomGate),
|
|
bootstrapStatsigNALAgentRetriesGate: buildEnabledStatsigGate(bootstrapStatsigNALAgentRetriesGate),
|
|
bootstrapStatsigNALFreshRetryIDsGate: buildEnabledStatsigGate(bootstrapStatsigNALFreshRetryIDsGate),
|
|
bootstrapStatsigUseModelParametersGate: buildEnabledStatsigGate(bootstrapStatsigUseModelParametersGate),
|
|
bootstrapStatsigUseReactModelPickerGate: buildEnabledStatsigGate(bootstrapStatsigUseReactModelPickerGate),
|
|
bootstrapStatsigIDECmdEnterSubmitGate: buildEnabledStatsigGate(bootstrapStatsigIDECmdEnterSubmitGate),
|
|
bootstrapStatsigContextVisualizerGate: buildEnabledStatsigGate(bootstrapStatsigContextVisualizerGate),
|
|
bootstrapStatsigWysiwygMarkdownGate: buildEnabledStatsigGate(bootstrapStatsigWysiwygMarkdownGate),
|
|
bootstrapStatsigWysiwygMarkdownDefaultGate: buildEnabledStatsigGate(bootstrapStatsigWysiwygMarkdownDefaultGate),
|
|
bootstrapStatsigSubagentSupportInterrupt: buildEnabledStatsigGate(bootstrapStatsigSubagentSupportInterrupt),
|
|
bootstrapStatsigExplicitSubagentModels: buildEnabledStatsigGate(bootstrapStatsigExplicitSubagentModels),
|
|
bootstrapStatsigMcpDirectClientToolFetch: buildEnabledStatsigGate(bootstrapStatsigMcpDirectClientToolFetch),
|
|
bootstrapStatsigGlassCustomThemeSupport: buildEnabledStatsigGate(bootstrapStatsigGlassCustomThemeSupport),
|
|
bootstrapStatsigGlassAutomationsUI: buildEnabledStatsigGate(bootstrapStatsigGlassAutomationsUI),
|
|
bootstrapStatsigTerminalUI2: buildEnabledStatsigGate(bootstrapStatsigTerminalUI2),
|
|
bootstrapStatsigDisableTerminalOutputUIStreaming: buildDisabledStatsigGate(bootstrapStatsigDisableTerminalOutputUIStreaming),
|
|
bootstrapStatsigBrowserCanvas: buildEnabledStatsigGate(bootstrapStatsigBrowserCanvas),
|
|
bootstrapStatsigEnableMultitaskMode: buildEnabledStatsigGate(bootstrapStatsigEnableMultitaskMode),
|
|
bootstrapStatsigDecomposeAlwaysLocalExtHostGate: buildDisabledStatsigGate(bootstrapStatsigDecomposeAlwaysLocalExtHostGate),
|
|
bootstrapStatsigCursorExtensionsIsolationV2Gate: buildDisabledStatsigGate(bootstrapStatsigCursorExtensionsIsolationV2Gate),
|
|
bootstrapStatsigCursorAgentWorkerExtension: buildDisabledStatsigGate(bootstrapStatsigCursorAgentWorkerExtension),
|
|
},
|
|
DynamicConfigs: map[string]statsigDynamicConfigTemplate{
|
|
bootstrapStatsigExperimentName: buildStatsigDynamicConfig(
|
|
bootstrapStatsigExperimentName,
|
|
map[string]any{bootstrapStatsigVariantParam: bootstrapStatsigVariantControl},
|
|
bootstrapStatsigVariantControl,
|
|
),
|
|
bootstrapStatsigProductTipsConfigName: buildStatsigDynamicConfig(
|
|
bootstrapStatsigProductTipsConfigName,
|
|
map[string]any{
|
|
"tips": []map[string]any{},
|
|
"config": map[string]any{
|
|
"intervalMs": 8000,
|
|
"minClientVersion": "",
|
|
},
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigIdleExtensionHostKiller: buildStatsigDynamicConfig(
|
|
bootstrapStatsigIdleExtensionHostKiller,
|
|
map[string]any{
|
|
bootstrapStatsigIdleMinutesToKill: 0,
|
|
bootstrapStatsigFreeMemoryPercentageToKill: 0,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigCanvasPromptTextConfig: buildStatsigDynamicConfig(
|
|
bootstrapStatsigCanvasPromptTextConfig,
|
|
buildCanvasPromptTextConfigValue(),
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigEditorBugbotConfig: buildStatsigDynamicConfig(
|
|
bootstrapStatsigEditorBugbotConfig,
|
|
map[string]any{
|
|
"model": "claude-4-5-sonnet-20250929",
|
|
"iterations": 0,
|
|
"agentic_iterations": 1,
|
|
"agentic_model": "claude-4.5-haiku",
|
|
"context_lines": 10,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigExtensionMonitorControl: buildStatsigDynamicConfig(
|
|
bootstrapStatsigExtensionMonitorControl,
|
|
map[string]any{
|
|
"local_enabled": false,
|
|
"backend_reporting_enabled": false,
|
|
"subsample_polling_rate_sec": 0,
|
|
"sample_polling_rate_min": 0,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigExtensionSignatureBypass: buildStatsigDynamicConfig(
|
|
bootstrapStatsigExtensionSignatureBypass,
|
|
map[string]any{
|
|
"extensionIds": []string{
|
|
"nromanov.dotrush",
|
|
"ms-python.python",
|
|
"typescriptteam.native-preview",
|
|
"typespec.typespec-vscode",
|
|
"ms-toolsai.jupyter",
|
|
"k3ndr1ckfu.tcl-language-support-for-vscode",
|
|
"amiq.dvt",
|
|
},
|
|
"remoteVerificationMinVersion": "2.25.0",
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigGCTraceControl: buildStatsigDynamicConfig(
|
|
bootstrapStatsigGCTraceControl,
|
|
map[string]any{
|
|
"enabled": false,
|
|
"drain_interval_sec": 120,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigInlineDiffPerformance: buildStatsigDynamicConfig(
|
|
bootstrapStatsigInlineDiffPerformance,
|
|
map[string]any{
|
|
"maxDecorations": 100,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigLeakedDisposablesTracker: buildStatsigDynamicConfig(
|
|
bootstrapStatsigLeakedDisposablesTracker,
|
|
map[string]any{
|
|
"enabled": false,
|
|
"reportIntervalMs": 60000,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigMcpIPCTimeouts: buildStatsigDynamicConfig(
|
|
bootstrapStatsigMcpIPCTimeouts,
|
|
map[string]any{
|
|
"metadata_timeout_ms": 10000,
|
|
"lifecycle_timeout_ms": 10000,
|
|
"dashboard_timeout_ms": 10000,
|
|
"recovery_per_retry_timeout_ms": 10000,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigMcpWakeProbeConfig: buildStatsigDynamicConfig(
|
|
bootstrapStatsigMcpWakeProbeConfig,
|
|
map[string]any{
|
|
"probeOnFocus": true,
|
|
"probeOnBrowserOnline": true,
|
|
"probeOnElapsedTimeGap": true,
|
|
"elapsedTimeGapThresholdMs": 300000,
|
|
"focusProbeDebounceMs": 60000,
|
|
"onlineProbeDebounceMs": 5000,
|
|
"resumeProbeDebounceMs": 5000,
|
|
"startupGraceMs": 15000,
|
|
"minProbeIntervalMs": 30000,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigNALStallDetectorTimeout: buildStatsigDynamicConfig(
|
|
bootstrapStatsigNALStallDetectorTimeout,
|
|
map[string]any{
|
|
"advisoryTimeoutMs": 20000,
|
|
"failTimeoutMs": 30000,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigSimulatedThinkingErrorTimeout: buildStatsigDynamicConfig(
|
|
bootstrapStatsigSimulatedThinkingErrorTimeout,
|
|
map[string]any{
|
|
"timeout_ms": 120000,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigPlaywrightLogConfigs: buildStatsigDynamicConfig(
|
|
bootstrapStatsigPlaywrightLogConfigs,
|
|
map[string]any{
|
|
"logSizeThreshold": 25000,
|
|
"logPreviewLines": 25,
|
|
"logPreviewChars": 25000,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigRetryInterceptorParams: buildStatsigDynamicConfig(
|
|
bootstrapStatsigRetryInterceptorParams,
|
|
map[string]any{},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigUpdatePromptConfig: buildStatsigDynamicConfig(
|
|
bootstrapStatsigUpdatePromptConfig,
|
|
map[string]any{
|
|
"min_hours_between_prompts": 48,
|
|
"max_prompts_per_version": 3,
|
|
"max_prompts_per_day": 1,
|
|
"snooze_duration_hours": 72,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigHTTP2PingConfig: buildStatsigDynamicConfig(
|
|
bootstrapStatsigHTTP2PingConfig,
|
|
map[string]any{
|
|
"enabled": []string{},
|
|
"pingIdleConnection": nil,
|
|
"pingIntervalMs": nil,
|
|
"pingTimeoutMs": nil,
|
|
"idleConnectionTimeoutMs": nil,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigHTTP1KeepaliveConfig: buildStatsigDynamicConfig(
|
|
bootstrapStatsigHTTP1KeepaliveConfig,
|
|
map[string]any{
|
|
"keepAliveInitialDelayMs": nil,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
bootstrapStatsigHTTP2AgentPoolConfig: buildStatsigDynamicConfig(
|
|
bootstrapStatsigHTTP2AgentPoolConfig,
|
|
map[string]any{
|
|
"poolSize": 4,
|
|
},
|
|
bootstrapStatsigLocalDefaultRule,
|
|
),
|
|
},
|
|
LayerConfigs: map[string]map[string]any{},
|
|
User: map[string]any{
|
|
"userID": localUltraPaymentID,
|
|
"email": legacyruntime.InjectAccountEmail,
|
|
"customIDs": map[string]string{
|
|
"localUserID": localUltraPaymentID,
|
|
},
|
|
},
|
|
HasUpdates: true,
|
|
HashUsed: "none",
|
|
SDKParams: map[string]any{
|
|
"stableID": localUltraPaymentID,
|
|
"disableDiagnosticsLogging": true,
|
|
},
|
|
}
|
|
|
|
func buildStatsigDynamicConfig(name string, value map[string]any, ruleID string) statsigDynamicConfigTemplate {
|
|
name = strings.TrimSpace(name)
|
|
ruleID = strings.TrimSpace(ruleID)
|
|
if ruleID == "" {
|
|
ruleID = bootstrapStatsigLocalDefaultRule
|
|
}
|
|
exposures := []statsigSecondaryExposure{}
|
|
return statsigDynamicConfigTemplate{
|
|
Name: name,
|
|
Value: value,
|
|
RuleID: ruleID,
|
|
RuleIDCamel: ruleID,
|
|
GroupName: ruleID,
|
|
GroupNameCamel: ruleID,
|
|
SecondaryExposures: exposures,
|
|
SecondaryExposuresCamel: exposures,
|
|
UndelegatedSecondaryExposures: exposures,
|
|
UndelegatedSecondaryExposuresCamel: exposures,
|
|
IsDeviceBased: false,
|
|
IsDeviceBasedCamel: false,
|
|
IsExperimentActive: false,
|
|
IsExperimentActiveCamel: false,
|
|
IsUserInExperiment: false,
|
|
IsUserInExperimentCamel: false,
|
|
}
|
|
}
|
|
|
|
func buildCanvasPromptTextConfigValue() map[string]any {
|
|
return map[string]any{
|
|
"skillDescription": "A Cursor Canvas is a live React app that the user can open beside the chat. You MUST use a canvas when the agent produces a standalone analytical artifact \u2014 quantitative analyses, billing investigations, security audits, architecture reviews, data-heavy content, timelines, charts, tables, interactive explorations, repeatable tools, or any response that benefits from visual layout. Especially prefer a canvas when presenting results from MCP tools (Datadog, Databricks, Linear, Sentry, Slack, etc.) where the data is the deliverable \u2014 render it in a rich canvas rather than dumping it into a markdown table or code block. If you catch yourself about to write a markdown table, stop and use a canvas instead. You MUST also read this skill whenever you create, edit, or debug any .canvas.tsx file.",
|
|
"errorFixPromptTemplate": strings.Join([]string{
|
|
"The canvas at `{canvasPath}` has the following error:",
|
|
"",
|
|
`"""`,
|
|
"{errorMessage}",
|
|
`"""`,
|
|
"",
|
|
"Check if the canvas SDK has changed since this canvas was created.",
|
|
"Update the canvas to use the latest SDK components according to the supplied documentation in the canvas skill.",
|
|
}, "\n"),
|
|
"welcomePageEnabled": true,
|
|
"marketplaceCategoryKey": "canvas-featured",
|
|
"marketplaceMaxCards": 4,
|
|
}
|
|
}
|
|
|
|
func buildEnabledStatsigGate(name string) map[string]any {
|
|
return buildStatsigGate(name, true, "local_enabled")
|
|
}
|
|
|
|
func buildDisabledStatsigGate(name string) map[string]any {
|
|
return buildStatsigGate(name, false, "local_disabled")
|
|
}
|
|
|
|
func buildStatsigGate(name string, value bool, ruleID string) map[string]any {
|
|
return map[string]any{
|
|
"name": name,
|
|
"value": value,
|
|
"rule_id": ruleID,
|
|
"ruleID": ruleID,
|
|
"group_name": ruleID,
|
|
"groupName": ruleID,
|
|
"secondary_exposures": []statsigSecondaryExposure{},
|
|
"secondaryExposures": []statsigSecondaryExposure{},
|
|
"undelegated_secondary_exposures": []statsigSecondaryExposure{},
|
|
"undelegatedSecondaryExposures": []statsigSecondaryExposure{},
|
|
"is_device_based": false,
|
|
"isDeviceBased": false,
|
|
"id_type": "userID",
|
|
"idType": "userID",
|
|
}
|
|
}
|
|
|
|
func buildServerTimePayload(*RequestContext) (map[string]any, error) {
|
|
now := float64(time.Now().UnixMilli())
|
|
return map[string]any{
|
|
"receiveTimestamp": now,
|
|
"transmitTimestamp": now,
|
|
}, nil
|
|
}
|
|
|
|
func buildServerConfigPayload(*RequestContext) (map[string]any, error) {
|
|
return map[string]any{
|
|
"configVersion": "local_cli_sandbox_defaults_disabled_v2",
|
|
"http2Config": "HTTP2_CONFIG_FORCE_ALL_DISABLED",
|
|
"cliSandboxDefaultEnabled": true,
|
|
"indexingConfig": map[string]any{
|
|
"defaultUserPathEncryptionKey": localPathEncryptionKey,
|
|
"defaultTeamPathEncryptionKey": localPathEncryptionKey,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func buildAvailableModelsPayload(reqCtx *RequestContext) (map[string]any, error) {
|
|
adapters, err := loadConfiguredModelAdapters(reqCtx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
modelRefs := collectModelAdapterRefs(adapters)
|
|
defaultModel := ""
|
|
if len(modelRefs) > 0 {
|
|
defaultModel = modelRefs[0]
|
|
}
|
|
modelEntries := buildAvailableModelEntries(adapters)
|
|
return map[string]any{
|
|
"backgroundComposerModelConfig": map[string]any{
|
|
"bestOfNDefaultModels": append([]string(nil), modelRefs...),
|
|
"defaultModel": defaultModel,
|
|
"fallbackModels": append([]string(nil), modelRefs...),
|
|
},
|
|
"cmdKModelConfig": map[string]any{
|
|
"defaultModel": defaultModel,
|
|
"fallbackModels": append([]string(nil), modelRefs...),
|
|
},
|
|
"composerModelConfig": map[string]any{
|
|
"bestOfNDefaultModels": append([]string(nil), modelRefs...),
|
|
"defaultModel": defaultModel,
|
|
"fallbackModels": append([]string(nil), modelRefs...),
|
|
},
|
|
"deepSearchModelConfig": map[string]any{
|
|
"defaultModel": defaultModel,
|
|
},
|
|
"disableUnusedModelsAfterNHours": availableModelsDisableUnusedHours,
|
|
"models": modelEntries,
|
|
"planExecutionModelConfig": map[string]any{
|
|
"defaultModel": defaultModel,
|
|
"fallbackModels": append([]string(nil), modelRefs...),
|
|
},
|
|
"quickAgentModelConfig": map[string]any{
|
|
"defaultModel": defaultModel,
|
|
},
|
|
"specModelConfig": map[string]any{
|
|
"defaultModel": defaultModel,
|
|
},
|
|
"useModelParameters": true,
|
|
"upgradeUnchangedModelsAfterNHours": availableModelsUpgradeHours,
|
|
}, nil
|
|
}
|
|
|
|
func buildDefaultModelNudgeDataPayload(reqCtx *RequestContext) (map[string]any, error) {
|
|
adapters, err := loadConfiguredModelAdapters(reqCtx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return map[string]any{
|
|
"modelsWithNoDefaultSwitch": collectModelAdapterRefs(adapters),
|
|
"nudgeDate": "0",
|
|
}, nil
|
|
}
|
|
|
|
func buildUsableModelsPayload(reqCtx *RequestContext) (map[string]any, error) {
|
|
adapters, err := loadConfiguredModelAdapters(reqCtx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return map[string]any{"models": buildCLIModelDetails(adapters)}, nil
|
|
}
|
|
|
|
func buildDefaultModelForCliPayload(reqCtx *RequestContext) (map[string]any, error) {
|
|
adapters, err := loadConfiguredModelAdapters(reqCtx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
models := buildCLIModelDetails(adapters)
|
|
if len(models) == 0 {
|
|
return map[string]any{"model": map[string]any{}}, nil
|
|
}
|
|
return map[string]any{"model": models[0]}, nil
|
|
}
|
|
|
|
func buildDefaultModelPayload(reqCtx *RequestContext) (map[string]any, error) {
|
|
adapters, err := loadConfiguredModelAdapters(reqCtx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defaultModel := firstModelAdapterRef(adapters)
|
|
return map[string]any{"model": defaultModel, "thinkingModel": defaultModel}, nil
|
|
}
|
|
|
|
func buildBootstrapStatsigPayload(reqCtx *RequestContext) (map[string]any, error) {
|
|
generatedAtMs := uint64(time.Now().UnixMilli())
|
|
authID := resolveBootstrapStatsigAuthID(reqCtx)
|
|
configJSON, err := buildBootstrapStatsigConfigJSON(int64(generatedAtMs), authID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return map[string]any{
|
|
"config": string(configJSON),
|
|
"generatedAtMs": generatedAtMs,
|
|
}, nil
|
|
}
|
|
|
|
func buildFirstWindowStatsigDecisionPayload(*RequestContext) (map[string]any, error) {
|
|
return map[string]any{
|
|
"variant": bootstrapStatsigVariantControl,
|
|
"reason": bootstrapStatsigLocalDefaultRule,
|
|
}, nil
|
|
}
|
|
|
|
func buildDashboardCurrentPeriodUsagePayload(*RequestContext) (map[string]any, error) {
|
|
billingCycleStart := time.Now().Add(-localUltraBillingCycleDuration).UnixMilli()
|
|
billingCycleEnd := time.Now().Add(10 * 365 * 24 * time.Hour).UnixMilli()
|
|
return map[string]any{
|
|
"autoModelSelectedDisplayMessage": "Ultra plan active",
|
|
"billingCycleEnd": billingCycleEnd,
|
|
"billingCycleStart": billingCycleStart,
|
|
"displayMessage": "Ultra plan active",
|
|
"displayThreshold": 99999999,
|
|
"enabled": true,
|
|
"namedModelSelectedDisplayMessage": "Ultra plan active",
|
|
"planUsage": map[string]any{
|
|
"apiPercentUsed": 0,
|
|
"apiSpend": 0,
|
|
"autoPercentUsed": 0,
|
|
"autoSpend": 0,
|
|
"bonusTooltip": "Ultra local account mock is active.",
|
|
"includedSpend": localUltraPlanIncludedCents,
|
|
"limit": localUltraPlanIncludedCents,
|
|
"remaining": localUltraPlanIncludedCents,
|
|
"remainingBonus": false,
|
|
"totalPercentUsed": 0,
|
|
"totalSpend": 0,
|
|
},
|
|
"spendLimitUsage": map[string]any{
|
|
"limitType": "user",
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func buildDashboardTeamsPayload(*RequestContext) (map[string]any, error) {
|
|
return map[string]any{
|
|
"teams": []map[string]any{},
|
|
}, nil
|
|
}
|
|
|
|
func buildDashboardManagedSkillsPayload(*RequestContext) (map[string]any, error) {
|
|
return map[string]any{
|
|
"skills": []map[string]any{},
|
|
}, nil
|
|
}
|
|
|
|
func buildDashboardGetMePayload(reqCtx *RequestContext) (map[string]any, error) {
|
|
authID := ""
|
|
if reqCtx != nil {
|
|
authID = authIDFromBearer(reqCtx.Headers.Get("authorization"))
|
|
}
|
|
if authID == "" {
|
|
authID = authIDFromJWT(legacyruntime.InjectAuthToken)
|
|
}
|
|
if authID == "" {
|
|
authID = localUltraPaymentID
|
|
}
|
|
|
|
return map[string]any{
|
|
"authId": authID,
|
|
"userId": localUltraDashboardUserID,
|
|
"email": legacyruntime.InjectAccountEmail,
|
|
"firstName": "Cursor",
|
|
"lastName": "Local",
|
|
"createdAt": time.Now().UTC().Format(time.RFC3339),
|
|
"isEnterpriseUser": false,
|
|
"teamName": "",
|
|
"emailDomainType": "personal",
|
|
"country": "US",
|
|
"profilePictureUrl": "",
|
|
}, nil
|
|
}
|
|
|
|
func buildDashboardUserPrivacyModePayload(*RequestContext) (map[string]any, error) {
|
|
return map[string]any{
|
|
"privacyMode": "PRIVACY_MODE_NO_STORAGE",
|
|
"hoursRemainingInGracePeriod": 0,
|
|
"isEnforcedByTeam": false,
|
|
"isNotMigratedToServerSourceOfTruth": false,
|
|
"partnerDataShare": false,
|
|
"hasAcknowledgedGracePeriodDisclaimer": true,
|
|
}, nil
|
|
}
|
|
|
|
func buildDashboardPlanInfoPayload(*RequestContext) (map[string]any, error) {
|
|
return map[string]any{
|
|
"planInfo": map[string]any{
|
|
"planName": "Ultra Plan",
|
|
"includedAmountCents": localUltraPlanIncludedCents,
|
|
"price": "$200/mo",
|
|
"billingCycleEnd": time.Now().Add(10 * 365 * 24 * time.Hour).UnixMilli(),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func buildDashboardUsageLimitStatusAndActiveGrantsPayload(*RequestContext) (map[string]any, error) {
|
|
return map[string]any{
|
|
"usageLimitPolicyStatus": map[string]any{
|
|
"isInSlowPool": false,
|
|
"features": map[string]string{},
|
|
"canConfigureSpendLimit": true,
|
|
"hasPendingRequest": false,
|
|
"allowedModelIds": []string{},
|
|
"allowedModelTags": []string{},
|
|
},
|
|
"activeGrants": []map[string]any{},
|
|
}, nil
|
|
}
|
|
|
|
func buildDashboardIsOnNewPricingPayload(*RequestContext) (map[string]any, error) {
|
|
return map[string]any{
|
|
"isOnNewPricing": true,
|
|
"isOptedOut": false,
|
|
"hasAutoSpillover": true,
|
|
"dashboardUserId": localUltraDashboardUserID,
|
|
}, nil
|
|
}
|
|
|
|
func loadConfiguredModelAdapters(reqCtx *RequestContext) ([]legacyruntime.ModelAdapterConfig, error) {
|
|
if reqCtx == nil || reqCtx.Deps == nil || reqCtx.Deps.SystemSettingService == nil {
|
|
return []legacyruntime.ModelAdapterConfig{}, nil
|
|
}
|
|
ctx := context.Background()
|
|
if reqCtx.Request != nil {
|
|
ctx = reqCtx.Request.Context()
|
|
}
|
|
return reqCtx.Deps.SystemSettingService.ResolveModelAdapters(ctx)
|
|
}
|
|
|
|
func buildAvailableModelEntries(adapters []legacyruntime.ModelAdapterConfig) []map[string]any {
|
|
if len(adapters) == 0 {
|
|
return []map[string]any{}
|
|
}
|
|
output := make([]map[string]any, 0, len(adapters))
|
|
for _, adapter := range adapters {
|
|
channelID := strings.TrimSpace(adapter.ID)
|
|
displayName := strings.TrimSpace(adapter.DisplayName)
|
|
modelID := strings.TrimSpace(adapter.ModelID)
|
|
tooltipData := strings.TrimSpace(adapter.TooltipData)
|
|
if channelID == "" || modelID == "" {
|
|
continue
|
|
}
|
|
modelDisplayName := displayName
|
|
if modelDisplayName == "" {
|
|
modelDisplayName = modelID
|
|
}
|
|
defaultThinkingEffort := defaultThinkingEffortForAdapter(adapter)
|
|
output = append(output, map[string]any{
|
|
"clientDisplayName": displayName,
|
|
"defaultOn": true,
|
|
"degradationStatus": "DEGRADATION_STATUS_UNSPECIFIED",
|
|
"inputboxShortModelName": displayName,
|
|
"isRecommendedForBackgroundComposer": false,
|
|
"name": channelID,
|
|
"namedModelSectionIndex": 1,
|
|
"parameterDefinitions": buildThinkingEffortParameterDefinitions(adapter.Type),
|
|
"serverModelName": channelID,
|
|
"supportsAgent": true,
|
|
"supportsImages": true,
|
|
"supportsMaxMode": false,
|
|
"supportsNonMaxMode": true,
|
|
"supportsPlanMode": true,
|
|
"supportsSandboxing": true,
|
|
"supportsThinking": true,
|
|
"tagline": thinkingEffortDisplayName(defaultThinkingEffort),
|
|
"tooltipData": map[string]any{
|
|
"markdownContent": tooltipData,
|
|
},
|
|
"tooltipDataForMaxMode": map[string]any{
|
|
"markdownContent": tooltipData,
|
|
},
|
|
"variants": buildThinkingEffortVariants(adapter.Type, channelID, modelDisplayName, tooltipData, defaultThinkingEffort),
|
|
})
|
|
}
|
|
return output
|
|
}
|
|
|
|
func buildCLIModelDetails(adapters []legacyruntime.ModelAdapterConfig) []map[string]any {
|
|
models := make([]map[string]any, 0, len(adapters))
|
|
for _, adapter := range adapters {
|
|
channelID := strings.TrimSpace(adapter.ID)
|
|
if channelID == "" {
|
|
continue
|
|
}
|
|
models = append(models, map[string]any{
|
|
"modelId": channelID,
|
|
"displayModelId": channelID,
|
|
"displayName": strings.TrimSpace(adapter.DisplayName),
|
|
"displayNameShort": strings.TrimSpace(adapter.DisplayName),
|
|
"apiKeyCredentials": map[string]any{
|
|
"apiKey": strings.TrimSpace(adapter.APIKey),
|
|
"baseUrl": strings.TrimSpace(adapter.BaseURL),
|
|
},
|
|
})
|
|
}
|
|
return models
|
|
}
|
|
|
|
func buildThinkingEffortParameterDefinitions(adapterType string) []map[string]any {
|
|
values := thinkingEffortValuesForAdapter(adapterType)
|
|
options := make([]map[string]any, 0, len(values))
|
|
for _, value := range values {
|
|
options = append(options, map[string]any{
|
|
"displayName": thinkingEffortDisplayName(value),
|
|
"increasesModelCost": value == "xhigh" || value == "max",
|
|
"value": value,
|
|
})
|
|
}
|
|
return []map[string]any{{
|
|
"id": modelRuntimeThinkingEffortParameterID,
|
|
"isCycleableByHotkey": true,
|
|
"markdownTooltip": "Controls the model thinking intensity for this run.",
|
|
"name": "Thinking intensity",
|
|
"parameterType": map[string]any{
|
|
"enumParameter": map[string]any{
|
|
"values": options,
|
|
},
|
|
},
|
|
}}
|
|
}
|
|
|
|
func buildThinkingEffortVariants(adapterType string, channelID string, modelDisplayName string, tooltipData string, defaultThinkingEffort string) []map[string]any {
|
|
values := orderThinkingEffortValues(thinkingEffortValuesForAdapter(adapterType), defaultThinkingEffort)
|
|
channelID = strings.TrimSpace(channelID)
|
|
modelDisplayName = strings.TrimSpace(modelDisplayName)
|
|
variants := make([]map[string]any, 0, len(values))
|
|
for _, value := range values {
|
|
effortDisplayName := thinkingEffortDisplayName(value)
|
|
variantDisplayName := buildThinkingEffortVariantDisplayName(modelDisplayName, value)
|
|
variant := map[string]any{
|
|
"displayName": variantDisplayName,
|
|
"displayNameOutsidePicker": variantDisplayName,
|
|
"isDefaultNonMaxConfig": value == defaultThinkingEffort,
|
|
"isMaxMode": false,
|
|
"parameterValues": []map[string]any{{"id": modelRuntimeThinkingEffortParameterID, "value": value}},
|
|
}
|
|
if normalizeAvailableModelThinkingEffort(value, true, "") != "disabled" {
|
|
variant["tagline"] = effortDisplayName
|
|
}
|
|
if channelID != "" {
|
|
variant["variantStringRepresentation"] = channelID + ":" + value
|
|
}
|
|
if strings.TrimSpace(tooltipData) != "" {
|
|
variant["tooltipData"] = map[string]any{"markdownContent": tooltipData}
|
|
}
|
|
variants = append(variants, variant)
|
|
}
|
|
return variants
|
|
}
|
|
|
|
func buildThinkingEffortVariantDisplayName(modelDisplayName string, effortValue string) string {
|
|
modelDisplayName = html.EscapeString(strings.TrimSpace(modelDisplayName))
|
|
if normalizeAvailableModelThinkingEffort(effortValue, true, "") == "disabled" {
|
|
return modelDisplayName
|
|
}
|
|
effortDisplayName := thinkingEffortDisplayName(effortValue)
|
|
effortDisplayName = html.EscapeString(strings.TrimSpace(effortDisplayName))
|
|
if modelDisplayName == "" {
|
|
return `<span class="ui-model-picker__item-tagline" style="color: var(--cursor-text-secondary); white-space: nowrap;">:icon-brain: ` + effortDisplayName + `</span>`
|
|
}
|
|
return modelDisplayName + ` <span class="ui-model-picker__item-tagline" style="color: var(--cursor-text-secondary); white-space: nowrap;">:icon-brain: ` + effortDisplayName + `</span>`
|
|
}
|
|
|
|
func thinkingEffortValuesForAdapter(adapterType string) []string {
|
|
values := []string{"disabled", "low", "medium", "high", "xhigh"}
|
|
if adapterType := strings.ToLower(strings.TrimSpace(adapterType)); adapterType == "openai" || adapterType == "anthropic" {
|
|
values = append(values, "max")
|
|
}
|
|
return values
|
|
}
|
|
|
|
func orderThinkingEffortValues(values []string, defaultValue string) []string {
|
|
defaultValue = strings.ToLower(strings.TrimSpace(defaultValue))
|
|
output := make([]string, 0, len(values))
|
|
for _, value := range values {
|
|
if strings.EqualFold(value, defaultValue) {
|
|
output = append(output, value)
|
|
break
|
|
}
|
|
}
|
|
for _, value := range values {
|
|
if !strings.EqualFold(value, defaultValue) {
|
|
output = append(output, value)
|
|
}
|
|
}
|
|
return output
|
|
}
|
|
|
|
func defaultThinkingEffortForAdapter(adapter legacyruntime.ModelAdapterConfig) string {
|
|
if strings.EqualFold(strings.TrimSpace(adapter.Type), "anthropic") {
|
|
return normalizeAvailableModelThinkingEffort(adapter.AnthropicThinkingEffort, true, "xhigh")
|
|
}
|
|
return normalizeAvailableModelThinkingEffort(adapter.ReasoningEffort, true, "medium")
|
|
}
|
|
|
|
func normalizeAvailableModelThinkingEffort(raw string, allowMax bool, fallback string) string {
|
|
switch strings.ToLower(strings.TrimSpace(raw)) {
|
|
case "disabled", "low", "medium", "high", "xhigh":
|
|
return strings.ToLower(strings.TrimSpace(raw))
|
|
case "disable", "off", "none", "false", "no", "0":
|
|
return "disabled"
|
|
case "max":
|
|
if allowMax {
|
|
return "max"
|
|
}
|
|
return fallback
|
|
default:
|
|
return fallback
|
|
}
|
|
}
|
|
|
|
func thinkingEffortDisplayName(value string) string {
|
|
switch strings.ToLower(strings.TrimSpace(value)) {
|
|
case "disabled":
|
|
return "Disabled"
|
|
case "low":
|
|
return "Low"
|
|
case "medium":
|
|
return "Medium"
|
|
case "high":
|
|
return "High"
|
|
case "xhigh":
|
|
return "XHigh"
|
|
case "max":
|
|
return "Max"
|
|
default:
|
|
return strings.TrimSpace(value)
|
|
}
|
|
}
|
|
|
|
func collectModelAdapterRefs(adapters []legacyruntime.ModelAdapterConfig) []string {
|
|
output := make([]string, 0, len(adapters))
|
|
for _, adapter := range adapters {
|
|
channelID := strings.TrimSpace(adapter.ID)
|
|
if channelID == "" {
|
|
continue
|
|
}
|
|
output = append(output, channelID)
|
|
}
|
|
return output
|
|
}
|
|
|
|
// firstModelAdapterRef возвращает канал первого адаптера или пустую строку,
|
|
// если ни один адаптер не сконфигурирован.
|
|
func firstModelAdapterRef(adapters []legacyruntime.ModelAdapterConfig) string {
|
|
refs := collectModelAdapterRefs(adapters)
|
|
if len(refs) == 0 {
|
|
return ""
|
|
}
|
|
return refs[0]
|
|
}
|
|
|
|
func resolveBootstrapStatsigAuthID(reqCtx *RequestContext) string {
|
|
if reqCtx != nil {
|
|
if authID := authIDFromBearer(reqCtx.Headers.Get("authorization")); authID != "" {
|
|
return authID
|
|
}
|
|
}
|
|
if authID := authIDFromJWT(legacyruntime.InjectAuthToken); authID != "" {
|
|
return authID
|
|
}
|
|
return localUltraPaymentID
|
|
}
|
|
|
|
func authIDFromBearer(authorization string) string {
|
|
authorization = strings.TrimSpace(authorization)
|
|
if len(authorization) >= len("Bearer ") && strings.EqualFold(authorization[:len("Bearer ")], "Bearer ") {
|
|
authorization = strings.TrimSpace(authorization[len("Bearer "):])
|
|
}
|
|
return authIDFromJWT(authorization)
|
|
}
|
|
|
|
func authIDFromJWT(token string) string {
|
|
parts := strings.Split(strings.TrimSpace(token), ".")
|
|
if len(parts) < 2 {
|
|
return ""
|
|
}
|
|
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
|
|
if err != nil {
|
|
payload, err = base64.URLEncoding.DecodeString(parts[1])
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
}
|
|
var claims struct {
|
|
Sub string `json:"sub"`
|
|
}
|
|
if err := json.Unmarshal(payload, &claims); err != nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(claims.Sub)
|
|
}
|
|
|
|
func buildBootstrapStatsigConfigJSON(nowMs int64, authID string) ([]byte, error) {
|
|
authID = strings.TrimSpace(authID)
|
|
if authID == "" {
|
|
authID = localUltraPaymentID
|
|
}
|
|
template := bootstrapStatsigTemplate
|
|
template.Time = nowMs
|
|
template.User = map[string]any{
|
|
"userID": authID,
|
|
"email": legacyruntime.InjectAccountEmail,
|
|
"customIDs": map[string]string{
|
|
"localUserID": authID,
|
|
},
|
|
}
|
|
|
|
// This template mirrors the Statsig initialize/bootstrap response shape that
|
|
// the bundled client reads for experiments. hash_used stays "none" so the
|
|
// experiment can be looked up by its plain name without spec hashing.
|
|
//
|
|
// Cursor currently branches on free_user_model_picker.variant. Known values
|
|
// are "control", "locked_picker", and "grayed_models". Keep this template
|
|
// centralized and update it first if the bundled Statsig bootstrap shape changes.
|
|
return json.Marshal(template)
|
|
}
|