Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# aisdk-go

[![GitHub Release](https://img.shields.io/github/v/release/kylecarbs/aisdk-go?color=6b9ded&sort=semver)](https://github.com/kylecarbs/aisdk-go/releases)
[![GoDoc](https://godoc.org/github.com/kylecarbs/aisdk-go?status.svg)](https://godoc.org/github.com/kylecarbs/aisdk-go)
[![CI Status](https://github.com/kylecarbs/aisdk-go/workflows/ci/badge.svg)](https://github.com/kylecarbs/aisdk-go/actions)
[![GitHub Release](https://img.shields.io/github/v/release/coder/aisdk-go?color=6b9ded&sort=semver)](https://github.com/coder/aisdk-go/releases)
[![GoDoc](https://godoc.org/github.com/coder/aisdk-go?status.svg)](https://godoc.org/github.com/coder/aisdk-go)
[![CI Status](https://github.com/coder/aisdk-go/workflows/ci/badge.svg)](https://github.com/coder/aisdk-go/actions)

> [!WARNING]
> This library is super new and may change a lot.
Expand Down
22 changes: 11 additions & 11 deletions anthropic.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func MessagesToAnthropic(messages []Message) ([]anthropic.MessageParam, []anthro
switch part.Type {
case PartTypeText:
content = append(content, anthropic.ContentBlockParamUnion{
OfRequestTextBlock: &anthropic.TextBlockParam{
OfText: &anthropic.TextBlockParam{
Text: part.Text,
},
})
Expand All @@ -88,7 +88,7 @@ func MessagesToAnthropic(messages []Message) ([]anthropic.MessageParam, []anthro
return nil, nil, fmt.Errorf("marshalling tool input for call %s: %w", part.ToolInvocation.ToolCallID, err)
}
content = append(content, anthropic.ContentBlockParamUnion{
OfRequestToolUseBlock: &anthropic.ToolUseBlockParam{
OfToolUse: &anthropic.ToolUseBlockParam{
ID: part.ToolInvocation.ToolCallID,
Input: json.RawMessage(argsJSON),
Name: part.ToolInvocation.ToolName,
Expand All @@ -115,13 +115,13 @@ func MessagesToAnthropic(messages []Message) ([]anthropic.MessageParam, []anthro
switch resultPart.Type {
case PartTypeText:
resultContent = append(resultContent, anthropic.ToolResultBlockParamContentUnion{
OfRequestTextBlock: &anthropic.TextBlockParam{Text: resultPart.Text},
OfText: &anthropic.TextBlockParam{Text: resultPart.Text},
})
case PartTypeFile:
resultContent = append(resultContent, anthropic.ToolResultBlockParamContentUnion{
OfRequestImageBlock: &anthropic.ImageBlockParam{
OfImage: &anthropic.ImageBlockParam{
Source: anthropic.ImageBlockParamSourceUnion{
OfBase64ImageSource: &anthropic.Base64ImageSourceParam{
OfBase64: &anthropic.Base64ImageSourceParam{
Data: base64.StdEncoding.EncodeToString(resultPart.Data),
MediaType: anthropic.Base64ImageSourceMediaType(resultPart.MimeType),
},
Expand All @@ -136,7 +136,7 @@ func MessagesToAnthropic(messages []Message) ([]anthropic.MessageParam, []anthro
Role: anthropic.MessageParamRoleUser,
Content: []anthropic.ContentBlockParamUnion{
{
OfRequestToolResultBlock: &anthropic.ToolResultBlockParam{
OfToolResult: &anthropic.ToolResultBlockParam{
ToolUseID: part.ToolInvocation.ToolCallID,
Content: resultContent,
},
Expand All @@ -152,13 +152,13 @@ func MessagesToAnthropic(messages []Message) ([]anthropic.MessageParam, []anthro
switch part.Type {
case PartTypeText:
content = append(content, anthropic.ContentBlockParamUnion{
OfRequestTextBlock: &anthropic.TextBlockParam{Text: part.Text},
OfText: &anthropic.TextBlockParam{Text: part.Text},
})
case PartTypeFile:
content = append(content, anthropic.ContentBlockParamUnion{
OfRequestImageBlock: &anthropic.ImageBlockParam{
OfImage: &anthropic.ImageBlockParam{
Source: anthropic.ImageBlockParamSourceUnion{
OfBase64ImageSource: &anthropic.Base64ImageSourceParam{
OfBase64: &anthropic.Base64ImageSourceParam{
Data: base64.StdEncoding.EncodeToString(part.Data),
MediaType: anthropic.Base64ImageSourceMediaType(part.MimeType),
},
Expand All @@ -181,9 +181,9 @@ func MessagesToAnthropic(messages []Message) ([]anthropic.MessageParam, []anthro
return nil, nil, fmt.Errorf("invalid attachment URL: %s", attachment.URL)
}
content = append(content, anthropic.ContentBlockParamUnion{
OfRequestImageBlock: &anthropic.ImageBlockParam{
OfImage: &anthropic.ImageBlockParam{
Source: anthropic.ImageBlockParamSourceUnion{
OfBase64ImageSource: &anthropic.Base64ImageSourceParam{
OfBase64: &anthropic.Base64ImageSourceParam{
Data: parts[1],
MediaType: anthropic.Base64ImageSourceMediaType(attachment.ContentType),
},
Expand Down
36 changes: 23 additions & 13 deletions anthropic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/option"
"github.com/anthropics/anthropic-sdk-go/packages/ssestream"
"github.com/kylecarbs/aisdk-go"
"github.com/coder/aisdk-go"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -75,7 +75,7 @@ data: {"type":"message_stop" }`

var acc aisdk.DataStreamAccumulator
stream := aisdk.AnthropicToDataStream(typedStream)
stream = stream.WithToolCalling(func(toolCall aisdk.ToolCall) aisdk.ToolCallResult {
stream = stream.WithToolCalling(func(toolCall aisdk.ToolCall) any {
return map[string]any{"message": "Message printed to the console"}
})
stream = stream.WithAccumulator(&acc)
Expand Down Expand Up @@ -123,12 +123,12 @@ data: {"type":"message_stop" }`
require.Len(t, assistantMsg.Content, 2) // Text block + ToolUse block

// Check Text Content Block
textBlock := assistantMsg.Content[0].OfRequestTextBlock
textBlock := assistantMsg.Content[0].OfText
require.NotNil(t, textBlock)
require.Equal(t, "I'll help you print 'hello world' to the console using the print function.", textBlock.Text)

// Check Tool Use Content Block
toolUseBlock := assistantMsg.Content[1].OfRequestToolUseBlock
toolUseBlock := assistantMsg.Content[1].OfToolUse
require.NotNil(t, toolUseBlock)
require.Equal(t, "toolu_01RA76iwg1LbKuDjJnc6ym45", toolUseBlock.ID)
require.Equal(t, "print", toolUseBlock.Name)
Expand All @@ -139,12 +139,12 @@ data: {"type":"message_stop" }`
require.Equal(t, anthropic.MessageParamRoleUser, userMsg.Role)
require.Len(t, userMsg.Content, 1) // ToolResult block

toolResultBlock := userMsg.Content[0].OfRequestToolResultBlock
toolResultBlock := userMsg.Content[0].OfToolResult
require.NotNil(t, toolResultBlock)
require.Equal(t, "toolu_01RA76iwg1LbKuDjJnc6ym45", toolResultBlock.ToolUseID)
require.Len(t, toolResultBlock.Content, 1)
require.NotNil(t, toolResultBlock.Content[0].OfRequestTextBlock)
require.JSONEq(t, `{"message":"Message printed to the console"}`, toolResultBlock.Content[0].OfRequestTextBlock.Text)
require.NotNil(t, toolResultBlock.Content[0].OfText)
require.JSONEq(t, `{"message":"Message printed to the console"}`, toolResultBlock.Content[0].OfText.Text)

// --- Second conversion check (using expectedMessages) ---
// This part should remain the same, as it also expects 2 messages now.
Expand All @@ -163,12 +163,12 @@ data: {"type":"message_stop" }`
require.Equal(t, anthropic.MessageParamRoleUser, userMsgWithResult.Role)
require.Len(t, userMsgWithResult.Content, 1) // ToolResult block

toolResultBlockWithResult := userMsgWithResult.Content[0].OfRequestToolResultBlock
toolResultBlockWithResult := userMsgWithResult.Content[0].OfToolResult
require.NotNil(t, toolResultBlockWithResult)
require.Equal(t, "toolu_01RA76iwg1LbKuDjJnc6ym45", toolResultBlockWithResult.ToolUseID)
require.Len(t, toolResultBlockWithResult.Content, 1)
require.NotNil(t, toolResultBlockWithResult.Content[0].OfRequestTextBlock)
require.JSONEq(t, `{"message":"Message printed to the console"}`, toolResultBlockWithResult.Content[0].OfRequestTextBlock.Text)
require.NotNil(t, toolResultBlockWithResult.Content[0].OfText)
require.JSONEq(t, `{"message":"Message printed to the console"}`, toolResultBlockWithResult.Content[0].OfText.Text)
}

func TestMessagesToAnthropic_Live(t *testing.T) {
Expand All @@ -181,15 +181,25 @@ func TestMessagesToAnthropic_Live(t *testing.T) {
client := anthropic.NewClient(option.WithAPIKey(apiKey))

// Ensure messages are converted correctly.
prompt := "use the 'print' tool to print 'Hello, world!' and then show the result"
messages, systemPrompts, err := aisdk.MessagesToAnthropic([]aisdk.Message{
{
Role: "system",
Content: "use the 'print' tool to print 'Hello, world!' and then show the result",
Role: "system",
Parts: []aisdk.Part{
{Text: "You are a helpful assistant.", Type: aisdk.PartTypeText},
},
},
{
Role: "user", Content: "Go ahead.",
Role: "user", Parts: []aisdk.Part{
{Text: prompt, Type: aisdk.PartTypeText},
},
},
})
require.Len(t, messages, 1)
require.Len(t, systemPrompts, 1)
require.Len(t, messages[0].Content, 1)
require.NotNil(t, messages[0].Content[0].OfText)
require.Equal(t, messages[0].Content[0].OfText.Text, prompt)
require.NoError(t, err)

stream := client.Messages.NewStreaming(ctx, anthropic.MessageNewParams{
Expand Down
8 changes: 4 additions & 4 deletions demo/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

"github.com/anthropics/anthropic-sdk-go"
anthropicoption "github.com/anthropics/anthropic-sdk-go/option"
"github.com/kylecarbs/aisdk-go"
"github.com/coder/aisdk-go"
"github.com/openai/openai-go"
openaioption "github.com/openai/openai-go/option"
"google.golang.org/genai"
Expand Down Expand Up @@ -63,7 +63,7 @@ func run(ctx context.Context) error {
return
}

handleToolCall := func(toolCall aisdk.ToolCall) aisdk.ToolCallResult {
handleToolCall := func(toolCall aisdk.ToolCall) any {
return map[string]string{
"message": "It worked!",
}
Expand Down Expand Up @@ -115,10 +115,10 @@ func run(ctx context.Context) error {

thinking := anthropic.ThinkingConfigParamUnion{}
if req.Thinking {
thinking = anthropic.ThinkingConfigParamOfThinkingConfigEnabled(2048)
thinking = anthropic.ThinkingConfigParamOfEnabled(2048)
}
stream = aisdk.AnthropicToDataStream(anthropicClient.Messages.NewStreaming(ctx, anthropic.MessageNewParams{
Model: req.Model,
Model: anthropic.Model(req.Model),
Messages: messages,
System: system,
MaxTokens: 4096,
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module github.com/kylecarbs/aisdk-go
module github.com/coder/aisdk-go

go 1.23.7

require (
github.com/anthropics/anthropic-sdk-go v0.2.0-beta.3
github.com/anthropics/anthropic-sdk-go v1.4.0
github.com/google/uuid v1.6.0
github.com/openai/openai-go v0.1.0-beta.6
github.com/openai/openai-go v1.3.0
github.com/stretchr/testify v1.10.0
google.golang.org/genai v0.7.0
google.golang.org/genai v1.10.0
)

require (
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps=
cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8=
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
github.com/anthropics/anthropic-sdk-go v0.2.0-beta.3 h1:b5t1ZJMvV/l99y4jbz7kRFdUp3BSDkI8EhSlHczivtw=
github.com/anthropics/anthropic-sdk-go v0.2.0-beta.3/go.mod h1:AapDW22irxK2PSumZiQXYUFvsdQgkwIWlpESweWZI/c=
github.com/anthropics/anthropic-sdk-go v1.4.0 h1:fU1jKxYbQdQDiEXCxeW5XZRIOwKevn/PMg8Ay1nnUx0=
github.com/anthropics/anthropic-sdk-go v1.4.0/go.mod h1:AapDW22irxK2PSumZiQXYUFvsdQgkwIWlpESweWZI/c=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
Expand Down Expand Up @@ -33,8 +33,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/openai/openai-go v0.1.0-beta.6 h1:JquYDpprfrGnlKvQQg+apy9dQ8R9mIrm+wNvAPp6jCQ=
github.com/openai/openai-go v0.1.0-beta.6/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/openai/openai-go v1.3.0 h1:lBpvgXxGHUufk9DNTguval40y2oK0GHZwgWQyUtjPIQ=
github.com/openai/openai-go v1.3.0/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
Expand Down Expand Up @@ -75,8 +75,8 @@ golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
google.golang.org/genai v0.7.0 h1:TINBYXnP+K+D8b16LfVyb6XR3kdtieXy6nJsGoEXcBc=
google.golang.org/genai v0.7.0/go.mod h1:TyfOKRz/QyCaj6f/ZDt505x+YreXnY40l2I6k8TvgqY=
google.golang.org/genai v1.10.0 h1:ETP0Yksn5KUSEn5+ihMOnP3IqjZ+7Z4i0LjJslEXatI=
google.golang.org/genai v1.10.0/go.mod h1:TyfOKRz/QyCaj6f/ZDt505x+YreXnY40l2I6k8TvgqY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
Expand Down
8 changes: 4 additions & 4 deletions google.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,12 @@ func GoogleToDataStream(stream iter.Seq2[*genai.GenerateContentResponse, error])

// Extract final usage data if available
if lastResp != nil && lastResp.UsageMetadata != nil {
if lastResp.UsageMetadata.PromptTokenCount != nil {
promptTokens := int64(*lastResp.UsageMetadata.PromptTokenCount)
if lastResp.UsageMetadata.PromptTokenCount > 0 {
promptTokens := int64(lastResp.UsageMetadata.PromptTokenCount)
finalUsage.PromptTokens = &promptTokens
}
if lastResp.UsageMetadata.CandidatesTokenCount != nil {
completionTokens := int64(*lastResp.UsageMetadata.CandidatesTokenCount)
if lastResp.UsageMetadata.CandidatesTokenCount > 0 {
completionTokens := int64(lastResp.UsageMetadata.CandidatesTokenCount)
finalUsage.CompletionTokens = &completionTokens
}
}
Expand Down
Loading