mirror of
https://wget.la/https://github.com/leookun/cursor-byok
synced 2026-08-17 11:37:20 +08:00
feat(cursor): update model handling to use agentv1 responses and enhance CLI model details
- Refactored response handling in newProtoMessage to utilize agentv1 for GetUsableModelsResponse and GetDefaultModelForCliResponse. - Added new tests for buildCLIModelDetails and encodeCLIModels to ensure correct model details and encoding. - Updated buildUsableModelsPayload and buildDefaultModelForCliPayload to leverage buildCLIModelDetails for improved model data structure.
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"cursor/gen/agentv1"
|
||||||
"cursor/gen/aiserverv1"
|
"cursor/gen/aiserverv1"
|
||||||
"cursor/internal/logger"
|
"cursor/internal/logger"
|
||||||
"cursor/internal/netproxy"
|
"cursor/internal/netproxy"
|
||||||
@@ -433,9 +434,9 @@ func newProtoMessage(typeName string) (proto.Message, error) {
|
|||||||
case "aiserver.v1.ListMarketplacesResponse":
|
case "aiserver.v1.ListMarketplacesResponse":
|
||||||
return &aiserverv1.ListMarketplacesResponse{}, nil
|
return &aiserverv1.ListMarketplacesResponse{}, nil
|
||||||
case "aiserver.v1.GetUsableModelsResponse":
|
case "aiserver.v1.GetUsableModelsResponse":
|
||||||
return &aiserverv1.GetUsableModelsResponse{}, nil
|
return &agentv1.GetUsableModelsResponse{}, nil
|
||||||
case "aiserver.v1.GetDefaultModelForCliResponse":
|
case "aiserver.v1.GetDefaultModelForCliResponse":
|
||||||
return &aiserverv1.GetDefaultModelForCliResponse{}, nil
|
return &agentv1.GetDefaultModelForCliResponse{}, nil
|
||||||
case "aiserver.v1.GetDefaultModelResponse":
|
case "aiserver.v1.GetDefaultModelResponse":
|
||||||
return &aiserverv1.GetDefaultModelResponse{}, nil
|
return &aiserverv1.GetDefaultModelResponse{}, nil
|
||||||
case "aiserver.v1.GetGlobalCommandsResponse":
|
case "aiserver.v1.GetGlobalCommandsResponse":
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ func buildServerTimePayload(*RequestContext) (map[string]any, error) {
|
|||||||
func buildServerConfigPayload(*RequestContext) (map[string]any, error) {
|
func buildServerConfigPayload(*RequestContext) (map[string]any, error) {
|
||||||
return map[string]any{
|
return map[string]any{
|
||||||
"configVersion": "local_cli_sandbox_defaults_disabled_v2",
|
"configVersion": "local_cli_sandbox_defaults_disabled_v2",
|
||||||
// "http2Config": "HTTP2_CONFIG_FORCE_ALL_DISABLED",
|
"http2Config": "HTTP2_CONFIG_FORCE_ALL_DISABLED",
|
||||||
"cliSandboxDefaultEnabled": true,
|
"cliSandboxDefaultEnabled": true,
|
||||||
"indexingConfig": map[string]any{
|
"indexingConfig": map[string]any{
|
||||||
"defaultUserPathEncryptionKey": localPathEncryptionKey,
|
"defaultUserPathEncryptionKey": localPathEncryptionKey,
|
||||||
@@ -451,6 +451,7 @@ func buildAvailableModelsPayload(reqCtx *RequestContext) (map[string]any, error)
|
|||||||
if len(modelRefs) > 0 {
|
if len(modelRefs) > 0 {
|
||||||
defaultModel = modelRefs[0]
|
defaultModel = modelRefs[0]
|
||||||
}
|
}
|
||||||
|
modelEntries := buildAvailableModelEntries(adapters)
|
||||||
return map[string]any{
|
return map[string]any{
|
||||||
"backgroundComposerModelConfig": map[string]any{
|
"backgroundComposerModelConfig": map[string]any{
|
||||||
"bestOfNDefaultModels": append([]string(nil), modelRefs...),
|
"bestOfNDefaultModels": append([]string(nil), modelRefs...),
|
||||||
@@ -470,7 +471,7 @@ func buildAvailableModelsPayload(reqCtx *RequestContext) (map[string]any, error)
|
|||||||
"defaultModel": defaultModel,
|
"defaultModel": defaultModel,
|
||||||
},
|
},
|
||||||
"disableUnusedModelsAfterNHours": availableModelsDisableUnusedHours,
|
"disableUnusedModelsAfterNHours": availableModelsDisableUnusedHours,
|
||||||
"models": buildAvailableModelEntries(adapters),
|
"models": modelEntries,
|
||||||
"planExecutionModelConfig": map[string]any{
|
"planExecutionModelConfig": map[string]any{
|
||||||
"defaultModel": defaultModel,
|
"defaultModel": defaultModel,
|
||||||
"fallbackModels": append([]string(nil), modelRefs...),
|
"fallbackModels": append([]string(nil), modelRefs...),
|
||||||
@@ -502,12 +503,7 @@ func buildUsableModelsPayload(reqCtx *RequestContext) (map[string]any, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
refs := collectModelAdapterRefs(adapters)
|
return map[string]any{"models": buildCLIModelDetails(adapters)}, nil
|
||||||
models := make([]map[string]any, 0, len(refs))
|
|
||||||
for _, ref := range refs {
|
|
||||||
models = append(models, map[string]any{"modelName": ref})
|
|
||||||
}
|
|
||||||
return map[string]any{"models": models}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildDefaultModelForCliPayload(reqCtx *RequestContext) (map[string]any, error) {
|
func buildDefaultModelForCliPayload(reqCtx *RequestContext) (map[string]any, error) {
|
||||||
@@ -515,7 +511,11 @@ func buildDefaultModelForCliPayload(reqCtx *RequestContext) (map[string]any, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return map[string]any{"model": map[string]any{"modelName": firstModelAdapterRef(adapters)}}, nil
|
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) {
|
func buildDefaultModelPayload(reqCtx *RequestContext) (map[string]any, error) {
|
||||||
@@ -720,6 +720,25 @@ func buildAvailableModelEntries(adapters []legacyruntime.ModelAdapterConfig) []m
|
|||||||
return output
|
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,
|
||||||
|
"apiKeyCredentials": map[string]any{
|
||||||
|
"apiKey": strings.TrimSpace(adapter.APIKey),
|
||||||
|
"baseUrl": strings.TrimSpace(adapter.BaseURL),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return models
|
||||||
|
}
|
||||||
|
|
||||||
func buildThinkingEffortParameterDefinitions(adapterType string) []map[string]any {
|
func buildThinkingEffortParameterDefinitions(adapterType string) []map[string]any {
|
||||||
values := thinkingEffortValuesForAdapter(adapterType)
|
values := thinkingEffortValuesForAdapter(adapterType)
|
||||||
options := make([]map[string]any, 0, len(values))
|
options := make([]map[string]any, 0, len(values))
|
||||||
|
|||||||
@@ -2,9 +2,55 @@ package upstream
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"cursor/gen/agentv1"
|
||||||
|
legacyruntime "cursor/internal/runtime"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestBuildCLIModelDetailsPreservesChannelCredentials(t *testing.T) {
|
||||||
|
adapters := []legacyruntime.ModelAdapterConfig{
|
||||||
|
{ID: " channel-a ", ModelID: "model-a", APIKey: "provider-secret-a", BaseURL: "https://provider-a.example/v1"},
|
||||||
|
{ID: "channel-b", ModelID: "model-a"},
|
||||||
|
{ID: "", ModelID: "model-c"},
|
||||||
|
}
|
||||||
|
|
||||||
|
got := buildCLIModelDetails(adapters)
|
||||||
|
want := []map[string]any{
|
||||||
|
{"modelId": "channel-a", "displayModelId": "channel-a", "apiKeyCredentials": map[string]any{"apiKey": "provider-secret-a", "baseUrl": "https://provider-a.example/v1"}},
|
||||||
|
{"modelId": "channel-b", "displayModelId": "channel-b", "apiKeyCredentials": map[string]any{"apiKey": "", "baseUrl": ""}},
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("build CLI model details: got %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEncodeCLIModelsUsesAgentModelDetailsWireFormat(t *testing.T) {
|
||||||
|
payload := map[string]any{"models": buildCLIModelDetails([]legacyruntime.ModelAdapterConfig{{ID: "channel-a", APIKey: "provider-secret", BaseURL: "https://provider.example/v1"}})}
|
||||||
|
encoded, err := encodeMockProto("aiserver.v1.GetUsableModelsResponse", payload)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("encode CLI models: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &agentv1.GetUsableModelsResponse{}
|
||||||
|
if err := proto.Unmarshal(encoded, response); err != nil {
|
||||||
|
t.Fatalf("decode CLI models with agent proto: %v", err)
|
||||||
|
}
|
||||||
|
if len(response.Models) != 1 {
|
||||||
|
t.Fatalf("decoded model count: got %d, want 1", len(response.Models))
|
||||||
|
}
|
||||||
|
model := response.Models[0]
|
||||||
|
if model.GetModelId() != "channel-a" || model.GetDisplayModelId() != "channel-a" {
|
||||||
|
t.Fatalf("decoded channel IDs: model=%q display=%q", model.GetModelId(), model.GetDisplayModelId())
|
||||||
|
}
|
||||||
|
if credentials := model.GetApiKeyCredentials(); credentials == nil || credentials.GetApiKey() != "provider-secret" || credentials.GetBaseUrl() != "https://provider.example/v1" {
|
||||||
|
t.Fatalf("decoded relay credentials: %#v", credentials)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuildBootstrapStatsigConfigJSONDisablesAlwaysLocalDecompositionGate(t *testing.T) {
|
func TestBuildBootstrapStatsigConfigJSONDisablesAlwaysLocalDecompositionGate(t *testing.T) {
|
||||||
payload, err := buildBootstrapStatsigConfigJSON(12345, "test-auth-id")
|
payload, err := buildBootstrapStatsigConfigJSON(12345, "test-auth-id")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user