File size: 5,578 Bytes
4f59ab4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package model

import "encoding/json"

// AnthropicRequest represents a request to the Anthropic Messages API
type AnthropicRequest struct {
	Model     string               `json:"model"`
	MaxTokens int                  `json:"max_tokens"`
	System    interface{}          `json:"system,omitempty"`    // string or []AnthropicContentBlock
	Messages  []AnthropicMessage   `json:"messages"`
	Tools     []AnthropicTool      `json:"tools,omitempty"`
	ToolChoice interface{}         `json:"tool_choice,omitempty"`
	Stream    bool                 `json:"stream"`
	Thinking  *AnthropicThinking   `json:"thinking,omitempty"`
}

// AnthropicThinking controls thinking/reasoning behavior
type AnthropicThinking struct {
	Type         string `json:"type"`                    // "enabled" or "disabled"
	BudgetTokens int    `json:"budget_tokens,omitempty"`
}

// AnthropicMessage represents a message in Anthropic format
type AnthropicMessage struct {
	Role    string      `json:"role"`
	Content interface{} `json:"content"` // string or []AnthropicContentBlock
}

// ParseContent extracts text content from an Anthropic message.
// Content can be a plain string or an array of content blocks.
func (m *AnthropicMessage) ParseContent() (text string, blocks []AnthropicContentBlock) {
	switch c := m.Content.(type) {
	case string:
		return c, nil
	case []interface{}:
		for _, item := range c {
			raw, err := json.Marshal(item)
			if err != nil {
				continue
			}
			var block AnthropicContentBlock
			if err := json.Unmarshal(raw, &block); err != nil {
				continue
			}
			blocks = append(blocks, block)
			if block.Type == "text" {
				text += block.Text
			}
		}
	}
	return text, blocks
}

// AnthropicContentBlock represents a content block in Anthropic messages
type AnthropicContentBlock struct {
	Type string `json:"type"`

	// text block
	Text string `json:"text,omitempty"`

	// thinking block
	Thinking string `json:"thinking,omitempty"`

	// tool_use block
	ID    string          `json:"id,omitempty"`
	Name  string          `json:"name,omitempty"`
	Input json.RawMessage `json:"input,omitempty"`

	// tool_result block
	ToolUseID string      `json:"tool_use_id,omitempty"`
	Content   interface{} `json:"content,omitempty"` // string or []AnthropicContentBlock
	IsError   bool        `json:"is_error,omitempty"`

	// image block
	Source *AnthropicImageSource `json:"source,omitempty"`
}

// AnthropicImageSource for base64 image content
type AnthropicImageSource struct {
	Type      string `json:"type"`       // "base64"
	MediaType string `json:"media_type"` // "image/png" etc
	Data      string `json:"data"`
}

// AnthropicTool represents a tool definition in Anthropic format
type AnthropicTool struct {
	Name        string      `json:"name"`
	Description string      `json:"description,omitempty"`
	InputSchema interface{} `json:"input_schema"`
}

// AnthropicResponse represents a non-streaming response
type AnthropicResponse struct {
	ID           string                  `json:"id"`
	Type         string                  `json:"type"` // "message"
	Role         string                  `json:"role"` // "assistant"
	Content      []AnthropicContentBlock `json:"content"`
	Model        string                  `json:"model"`
	StopReason   string                  `json:"stop_reason"` // "end_turn", "tool_use", "max_tokens"
	StopSequence *string                 `json:"stop_sequence"`
	Usage        AnthropicUsage          `json:"usage"`
}

// AnthropicUsage tracks token usage
type AnthropicUsage struct {
	InputTokens  int `json:"input_tokens"`
	OutputTokens int `json:"output_tokens"`
}

// Streaming event types

// AnthropicStreamEvent wraps all SSE event data
type AnthropicStreamEvent struct {
	Type string `json:"type"`
}

// AnthropicMessageStart is the message_start event
type AnthropicMessageStart struct {
	Type    string            `json:"type"` // "message_start"
	Message AnthropicResponse `json:"message"`
}

// AnthropicContentBlockStart is the content_block_start event
type AnthropicContentBlockStart struct {
	Type         string                `json:"type"` // "content_block_start"
	Index        int                   `json:"index"`
	ContentBlock AnthropicContentBlock `json:"content_block"`
}

// AnthropicContentBlockDelta is the content_block_delta event
type AnthropicContentBlockDelta struct {
	Type  string                     `json:"type"` // "content_block_delta"
	Index int                        `json:"index"`
	Delta AnthropicContentBlockDelta2 `json:"delta"`
}

// AnthropicContentBlockDelta2 is the delta payload within content_block_delta
type AnthropicContentBlockDelta2 struct {
	Type         string `json:"type"`                    // "text_delta", "thinking_delta", "input_json_delta"
	Text         string `json:"text,omitempty"`          // for text_delta
	Thinking     string `json:"thinking,omitempty"`      // for thinking_delta
	PartialJSON  string `json:"partial_json,omitempty"`  // for input_json_delta
}

// AnthropicContentBlockStop is the content_block_stop event
type AnthropicContentBlockStop struct {
	Type  string `json:"type"` // "content_block_stop"
	Index int    `json:"index"`
}

// AnthropicMessageDelta is the message_delta event
type AnthropicMessageDelta struct {
	Type  string `json:"type"` // "message_delta"
	Delta struct {
		StopReason   string  `json:"stop_reason"`
		StopSequence *string `json:"stop_sequence"`
	} `json:"delta"`
	Usage AnthropicUsage `json:"usage"`
}

// AnthropicMessageStop is the message_stop event
type AnthropicMessageStop struct {
	Type string `json:"type"` // "message_stop"
}