Fix sandbox integration tests for claude-proxy architecture
- Update TestClaudeCommandBuilding to expect new command format - Rename TestClaudeCCRConfigBuilding to TestClaudeProxyConfigBuilding - Update assertions for claude-proxy env vars instead of CCR - Apply gofmt formatting to proxy/types.go Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
4e88c7ae78
commit
019b606b13
2 changed files with 62 additions and 60 deletions
|
|
@ -78,28 +78,30 @@ func TestClaudeCommandBuilding(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
|
||||
// Verify command structure
|
||||
// Command is now: ["bash", "-c", "nohup ccr start ... && ccr code ..."]
|
||||
// Command is now: ["bash", "-c", "cat << 'INPUTEOF' | claude -p ... INPUTEOF"]
|
||||
assert.NotEmpty(t, cmd)
|
||||
assert.Equal(t, "bash", cmd[0], "Command should start with bash")
|
||||
assert.Equal(t, "-c", cmd[1], "Second arg should be -c")
|
||||
assert.Contains(t, cmd[2], "ccr code", "Bash command should contain ccr code")
|
||||
assert.Contains(t, cmd[2], "claude -p", "Bash command should contain claude -p")
|
||||
assert.Contains(t, cmd[2], "--permission-mode", "Should include permission mode")
|
||||
assert.Contains(t, cmd[2], "--input-format", "Should include input-format flag")
|
||||
assert.Contains(t, cmd[2], "--output-format", "Should include output-format flag")
|
||||
assert.Contains(t, cmd[2], "--verbose", "Should include verbose flag")
|
||||
assert.Contains(t, cmd[2], "stream-json", "Should use stream-json format")
|
||||
assert.Contains(t, cmd[2], "INPUTEOF", "Should use heredoc for input")
|
||||
t.Logf("Built command: %v", cmd)
|
||||
|
||||
// Verify environment variables
|
||||
// Verify environment variables (claude-proxy mode)
|
||||
assert.NotEmpty(t, env)
|
||||
assert.Equal(t, "https://ark.cn-beijing.volces.com/api/v3", env["CCR_API_BASE"])
|
||||
assert.Equal(t, "test-api-key", env["CCR_API_KEY"])
|
||||
assert.Equal(t, "ep-xxxxx", env["CCR_MODEL"])
|
||||
assert.Equal(t, "http://127.0.0.1:3456", env["ANTHROPIC_BASE_URL"], "Should set proxy base URL")
|
||||
assert.Equal(t, "dummy", env["ANTHROPIC_API_KEY"], "Should set dummy API key for proxy")
|
||||
assert.Equal(t, "10", env["CLAUDE_MAX_TURNS"])
|
||||
assert.Equal(t, "acceptEdits", env["CLAUDE_PERMISSION_MODE"])
|
||||
assert.Equal(t, "stream-json", env["CLAUDE_OUTPUT_FORMAT"])
|
||||
assert.Contains(t, env["CLAUDE_SYSTEM_PROMPT"], "You are a helpful coding assistant")
|
||||
t.Logf("Built environment: %v", env)
|
||||
}
|
||||
|
||||
// TestClaudeCCRConfigBuilding tests that CCR config is correctly built
|
||||
func TestClaudeCCRConfigBuilding(t *testing.T) {
|
||||
// TestClaudeProxyConfigBuilding tests that claude-proxy config is correctly built
|
||||
func TestClaudeProxyConfigBuilding(t *testing.T) {
|
||||
test.Prepare(t, config.Conf)
|
||||
defer test.Clean()
|
||||
|
||||
|
|
@ -109,20 +111,20 @@ func TestClaudeCCRConfigBuilding(t *testing.T) {
|
|||
Model: "ep-xxxxx",
|
||||
}
|
||||
|
||||
configJSON, err := claude.BuildCCRConfig(opts)
|
||||
configJSON, err := claude.BuildProxyConfig(opts)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, configJSON)
|
||||
|
||||
t.Logf("CCR config: %s", string(configJSON))
|
||||
t.Logf("Proxy config: %s", string(configJSON))
|
||||
|
||||
// Verify the JSON contains expected fields (CCR uses snake_case)
|
||||
assert.Contains(t, string(configJSON), "api_base_url")
|
||||
// Verify the JSON contains expected fields for claude-proxy
|
||||
assert.Contains(t, string(configJSON), "backend")
|
||||
assert.Contains(t, string(configJSON), "api_key")
|
||||
assert.Contains(t, string(configJSON), "models")
|
||||
// Verify CCR format fields
|
||||
assert.Contains(t, string(configJSON), "Providers")
|
||||
assert.Contains(t, string(configJSON), "Router")
|
||||
assert.Contains(t, string(configJSON), "volcengine")
|
||||
assert.Contains(t, string(configJSON), "model")
|
||||
assert.Contains(t, string(configJSON), "test-api-key")
|
||||
assert.Contains(t, string(configJSON), "ep-xxxxx")
|
||||
// Backend URL should end with /chat/completions
|
||||
assert.Contains(t, string(configJSON), "/chat/completions")
|
||||
}
|
||||
|
||||
// TestDefaultImageSelection tests that default images are correctly selected
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@ package proxy
|
|||
|
||||
// AnthropicRequest represents a request to the Anthropic Messages API
|
||||
type AnthropicRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []AnthropicMsg `json:"messages"`
|
||||
System interface{} `json:"system,omitempty"` // string or []SystemBlock
|
||||
MaxTokens int `json:"max_tokens"`
|
||||
Stream bool `json:"stream,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
TopK *int `json:"top_k,omitempty"`
|
||||
StopSequences []string `json:"stop_sequences,omitempty"`
|
||||
Tools []AnthropicTool `json:"tools,omitempty"`
|
||||
Model string `json:"model"`
|
||||
Messages []AnthropicMsg `json:"messages"`
|
||||
System interface{} `json:"system,omitempty"` // string or []SystemBlock
|
||||
MaxTokens int `json:"max_tokens"`
|
||||
Stream bool `json:"stream,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
TopK *int `json:"top_k,omitempty"`
|
||||
StopSequences []string `json:"stop_sequences,omitempty"`
|
||||
Tools []AnthropicTool `json:"tools,omitempty"`
|
||||
ToolChoice *AnthropicToolChoice `json:"tool_choice,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
// AnthropicMsg represents a message in Anthropic format
|
||||
|
|
@ -42,14 +42,14 @@ type ContentBlock struct {
|
|||
Input interface{} `json:"input,omitempty"`
|
||||
|
||||
// For tool_result blocks
|
||||
ToolUseID string `json:"tool_use_id,omitempty"`
|
||||
ToolUseID string `json:"tool_use_id,omitempty"`
|
||||
Content interface{} `json:"content,omitempty"` // string or []ContentBlock
|
||||
IsError bool `json:"is_error,omitempty"`
|
||||
IsError bool `json:"is_error,omitempty"`
|
||||
}
|
||||
|
||||
// ImageSource represents an image source in Anthropic format
|
||||
type ImageSource struct {
|
||||
Type string `json:"type"` // "base64" or "url"
|
||||
Type string `json:"type"` // "base64" or "url"
|
||||
MediaType string `json:"media_type,omitempty"` // e.g., "image/jpeg"
|
||||
Data string `json:"data,omitempty"` // base64 encoded data
|
||||
URL string `json:"url,omitempty"` // URL for url type
|
||||
|
|
@ -94,12 +94,12 @@ type Usage struct {
|
|||
|
||||
// AnthropicStreamEvent represents an SSE event in Anthropic format
|
||||
type AnthropicStreamEvent struct {
|
||||
Type string `json:"type"`
|
||||
Index int `json:"index,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Index int `json:"index,omitempty"`
|
||||
Message *AnthropicResponse `json:"message,omitempty"`
|
||||
ContentBlock *ContentBlock `json:"content_block,omitempty"`
|
||||
Delta *DeltaContent `json:"delta,omitempty"`
|
||||
Usage *Usage `json:"usage,omitempty"`
|
||||
ContentBlock *ContentBlock `json:"content_block,omitempty"`
|
||||
Delta *DeltaContent `json:"delta,omitempty"`
|
||||
Usage *Usage `json:"usage,omitempty"`
|
||||
}
|
||||
|
||||
// DeltaContent represents delta content in streaming
|
||||
|
|
@ -116,16 +116,16 @@ type DeltaContent struct {
|
|||
|
||||
// OpenAIRequest represents a request to OpenAI Chat Completions API
|
||||
type OpenAIRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []OpenAIMsg `json:"messages"`
|
||||
MaxTokens int `json:"max_tokens,omitempty"`
|
||||
Stream bool `json:"stream,omitempty"`
|
||||
StreamOptions *StreamOptions `json:"stream_options,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
Stop []string `json:"stop,omitempty"`
|
||||
Tools []OpenAITool `json:"tools,omitempty"`
|
||||
ToolChoice interface{} `json:"tool_choice,omitempty"` // "auto", "none", "required", or object
|
||||
Model string `json:"model"`
|
||||
Messages []OpenAIMsg `json:"messages"`
|
||||
MaxTokens int `json:"max_tokens,omitempty"`
|
||||
Stream bool `json:"stream,omitempty"`
|
||||
StreamOptions *StreamOptions `json:"stream_options,omitempty"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
Stop []string `json:"stop,omitempty"`
|
||||
Tools []OpenAITool `json:"tools,omitempty"`
|
||||
ToolChoice interface{} `json:"tool_choice,omitempty"` // "auto", "none", "required", or object
|
||||
}
|
||||
|
||||
// StreamOptions represents stream options in OpenAI format
|
||||
|
|
@ -144,8 +144,8 @@ type OpenAIMsg struct {
|
|||
|
||||
// OpenAIContent represents content in OpenAI messages (for multimodal)
|
||||
type OpenAIContent struct {
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Type string `json:"type"`
|
||||
Text string `json:"text,omitempty"`
|
||||
ImageURL *OpenAIImageURL `json:"image_url,omitempty"`
|
||||
}
|
||||
|
||||
|
|
@ -170,10 +170,10 @@ type OpenAIFunction struct {
|
|||
|
||||
// OpenAIToolCall represents a tool call in OpenAI format
|
||||
type OpenAIToolCall struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Function OpenAIFunctionCall `json:"function"`
|
||||
Index *int `json:"index,omitempty"` // For streaming
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Function OpenAIFunctionCall `json:"function"`
|
||||
Index *int `json:"index,omitempty"` // For streaming
|
||||
}
|
||||
|
||||
// OpenAIFunctionCall represents a function call in OpenAI format
|
||||
|
|
@ -194,9 +194,9 @@ type OpenAIResponse struct {
|
|||
|
||||
// OpenAIChoice represents a choice in OpenAI response
|
||||
type OpenAIChoice struct {
|
||||
Index int `json:"index"`
|
||||
Message OpenAIMsg `json:"message"`
|
||||
FinishReason string `json:"finish_reason"`
|
||||
Index int `json:"index"`
|
||||
Message OpenAIMsg `json:"message"`
|
||||
FinishReason string `json:"finish_reason"`
|
||||
}
|
||||
|
||||
// OpenAIUsage represents usage statistics in OpenAI format
|
||||
|
|
@ -218,9 +218,9 @@ type OpenAIStreamChunk struct {
|
|||
|
||||
// OpenAIStreamChoice represents a choice in OpenAI streaming response
|
||||
type OpenAIStreamChoice struct {
|
||||
Index int `json:"index"`
|
||||
Delta OpenAIStreamDelta `json:"delta"`
|
||||
FinishReason string `json:"finish_reason,omitempty"`
|
||||
Index int `json:"index"`
|
||||
Delta OpenAIStreamDelta `json:"delta"`
|
||||
FinishReason string `json:"finish_reason,omitempty"`
|
||||
}
|
||||
|
||||
// OpenAIStreamDelta represents delta content in OpenAI streaming
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue