-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
adc37b6
commit 4f967e7
Showing
11 changed files
with
364 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,22 @@ | ||
package anthropic | ||
|
||
// CompletionEvent represents the data related to a completion event. | ||
type CompletionEvent struct { | ||
Completion string // The completion text from the model. | ||
} | ||
|
||
// ErrorEvent represents an error event that occurs during streaming. | ||
type ErrorEvent struct { | ||
Error string // A string description of the error. | ||
} | ||
|
||
// PingEvent is an empty struct representing a ping event. | ||
type PingEvent struct{} | ||
// Common types for different events | ||
type MessageEventType string | ||
|
||
// Define a separate type for completion events | ||
type CompletionEventType string | ||
|
||
const ( | ||
// Constants for message event types | ||
MessageEventTypeMessageStart MessageEventType = "message_start" | ||
MessageEventTypeContentBlockStart MessageEventType = "content_block_start" | ||
MessageEventTypePing MessageEventType = "ping" | ||
MessageEventTypeContentBlockDelta MessageEventType = "content_block_delta" | ||
MessageEventTypeContentBlockStop MessageEventType = "content_block_stop" | ||
MessageEventTypeMessageDelta MessageEventType = "message_delta" | ||
MessageEventTypeMessageStop MessageEventType = "message_stop" | ||
|
||
// Constants for completion event types | ||
CompletionEventTypeCompletion CompletionEventType = "completion" | ||
CompletionEventTypePing CompletionEventType = "ping" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
pkg/anthropic/integration_tests/message_integration_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package integration_tests | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
|
||
"github.com/madebywelch/anthropic-go/v2/pkg/anthropic" | ||
) | ||
|
||
func TestMessageIntegration(t *testing.T) { | ||
// Get the API key from the environment | ||
apiKey := os.Getenv("ANTHROPIC_API_KEY") | ||
if apiKey == "" { | ||
t.Skip("ANTHROPIC_API_KEY environment variable is not set, skipping integration test") | ||
} | ||
|
||
// Create a new client | ||
client, err := anthropic.NewClient(apiKey) | ||
if err != nil { | ||
t.Fatalf("Unexpected error: %v", err) | ||
} | ||
|
||
// Prepare a message request | ||
request := &anthropic.MessageRequest{ | ||
Model: anthropic.ClaudeV2_1, | ||
MaxTokensToSample: 10, | ||
Messages: []anthropic.MessagePartRequest{{Role: "user", Content: "Hello, Anthropics!"}}, | ||
} | ||
|
||
// Call the Message method | ||
response, err := client.Message(request) | ||
if err != nil { | ||
t.Fatalf("Unexpected error: %v", err) | ||
} | ||
|
||
// Basic assertion to check if a message response is returned | ||
if response == nil || len(response.Content) == 0 { | ||
t.Errorf("Expected a message response, got none or empty content") | ||
} | ||
|
||
// Ensure the response contains populated ID | ||
if response.ID == "" { | ||
t.Errorf("Expected a message response with a non-empty ID, got none") | ||
} | ||
} | ||
|
||
func TestMessageErrorHandlingIntegration(t *testing.T) { | ||
// Get the API key from the environment | ||
apiKey := os.Getenv("ANTHROPIC_API_KEY") | ||
if apiKey == "" { | ||
t.Skip("ANTHROPIC_API_KEY environment variable is not set, skipping integration test") | ||
} | ||
|
||
// Create a new client | ||
client, err := anthropic.NewClient(apiKey) | ||
if err != nil { | ||
t.Fatalf("Unexpected error: %v", err) | ||
} | ||
|
||
// Prepare a message request | ||
request := &anthropic.MessageRequest{ | ||
Model: anthropic.ClaudeV2_1, | ||
Messages: []anthropic.MessagePartRequest{{Role: "user", Content: "Hello, Anthropics!"}}, | ||
} | ||
|
||
// Call the Message method expecting an error | ||
_, err = client.Message(request) | ||
// We're expecting an error here because we didn't set the required field MaxTokensToSample | ||
if err == nil { | ||
t.Fatal("Expected an error, got none") | ||
} | ||
} | ||
|
||
// - TODO: TestMessageWithParametersIntegration: to test sending a message with various parameters | ||
// - TODO: TestMessageStreamIntegration: to ensure the function correctly handles streaming requests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package anthropic | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
func (c *Client) Message(req *MessageRequest) (*MessageResponse, error) { | ||
if req.Stream { | ||
return nil, fmt.Errorf("cannot use Message with streaming enabled, use MessageStream instead (not yet supported)") | ||
} | ||
|
||
return c.sendMessageRequest(req) | ||
} | ||
|
||
// MessageStream (NOT YET SUPPORTED) returns a channel of StreamResponse objects and a channel of errors. | ||
func (c *Client) MessageStream(req *MessageRequest) (<-chan StreamResponse, <-chan error) { | ||
return nil, nil | ||
} | ||
|
||
func (c *Client) sendMessageRequest(req *MessageRequest) (*MessageResponse, error) { | ||
// Marshal the request to JSON | ||
data, err := json.Marshal(req) | ||
if err != nil { | ||
return nil, fmt.Errorf("error marshalling completion request: %w", err) | ||
} | ||
|
||
// Create the HTTP request | ||
requestURL := fmt.Sprintf("%s/v1/messages", c.baseURL) | ||
request, err := http.NewRequest("POST", requestURL, bytes.NewBuffer(data)) | ||
if err != nil { | ||
return nil, fmt.Errorf("error creating new request: %w", err) | ||
} | ||
request.Header.Set("Content-Type", "application/json") | ||
request.Header.Set("X-Api-Key", c.apiKey) | ||
request.Header.Set("anthropic-beta", AnthropicAPIMessagesBeta) | ||
|
||
// Use the DoRequest method to send the HTTP request | ||
response, err := c.DoRequest(request) | ||
if err != nil { | ||
return nil, fmt.Errorf("error sending completion request: %w", err) | ||
} | ||
defer response.Body.Close() | ||
|
||
// Decode the response body to a MessageResponse object | ||
var messageResponse MessageResponse | ||
err = json.NewDecoder(response.Body).Decode(&messageResponse) | ||
if err != nil { | ||
return nil, fmt.Errorf("error decoding message response: %w", err) | ||
} | ||
|
||
return &messageResponse, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package anthropic | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
"net/http/httptest" | ||
"testing" | ||
) | ||
|
||
func TestMessage(t *testing.T) { | ||
// Mock server for successful message response | ||
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
resp := MessageResponse{ | ||
ID: "12345", | ||
Type: "testType", | ||
Model: "testModel", | ||
Role: "user", | ||
Content: []MessagePartResponse{{ | ||
Type: "text", | ||
Text: "Test message", | ||
}}, | ||
} | ||
json.NewEncoder(w).Encode(resp) | ||
})) | ||
defer testServer.Close() | ||
|
||
// Create a new client with the test server's URL | ||
client, err := NewClient("fake-api-key") | ||
if err != nil { | ||
t.Fatalf("Unexpected error: %v", err) | ||
} | ||
client.baseURL = testServer.URL // Override baseURL to point to the test server | ||
|
||
// Prepare a message request | ||
request := &MessageRequest{ | ||
Model: ClaudeV2_1, | ||
Messages: []MessagePartRequest{{Role: "user", Content: "Hello"}}, | ||
} | ||
|
||
// Call the Message method | ||
response, err := client.Message(request) | ||
if err != nil { | ||
t.Fatalf("Unexpected error: %v", err) | ||
} | ||
|
||
// Check the response | ||
expectedContent := "Test message" | ||
if len(response.Content) == 0 || response.Content[0].Text != expectedContent { | ||
t.Errorf("Expected message %q, got %q", expectedContent, response.Content[0].Text) | ||
} | ||
} | ||
|
||
func TestMessageErrorHandling(t *testing.T) { | ||
// Mock server for error response | ||
testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) | ||
})) | ||
defer testServer.Close() | ||
|
||
// Create a new client with the test server's URL | ||
client, err := NewClient("fake-api-key") | ||
if err != nil { | ||
t.Fatalf("Unexpected error: %v", err) | ||
} | ||
client.baseURL = testServer.URL // Override baseURL to point to the test server | ||
|
||
// Prepare a message request | ||
request := &MessageRequest{ | ||
Model: ClaudeV2_1, | ||
Messages: []MessagePartRequest{{Role: "user", Content: "Hello"}}, | ||
} | ||
|
||
// Call the Message method expecting an error | ||
_, err = client.Message(request) | ||
if err == nil { | ||
t.Fatal("Expected an error, got none") | ||
} | ||
} | ||
|
||
func TestMessageStreamNotSupported(t *testing.T) { | ||
// Create client | ||
client, err := NewClient("fake-api-key") | ||
if err != nil { | ||
t.Fatalf("Unexpected error: %v", err) | ||
} | ||
|
||
// Prepare a message request with streaming set to true | ||
request := &MessageRequest{ | ||
Model: ClaudeV2_1, | ||
Messages: []MessagePartRequest{{Role: "user", Content: "Hello"}}, | ||
Stream: true, | ||
} | ||
|
||
// Call the Message method expecting an error | ||
_, err = client.Message(request) | ||
if err == nil { | ||
t.Fatal("Expected an error for streaming not supported, got none") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
Oops, something went wrong.