Files
gnoma/internal/message/content.go
vikingowl 85c643fdca feat: add foundation types, streaming, and provider interface
internal/message/ — Content discriminated union, Message, Usage,
StopReason, Response. 22 tests.

internal/stream/ — Stream pull-based iterator interface, Event types,
Accumulator (assembles Response from events). 8 tests.

internal/provider/ — Provider interface, Request, ToolDefinition,
Registry with factory pattern, ProviderError with HTTP status
classification. errors.AsType[E] for Go 1.26. 13 tests.

43 tests total, all passing.
2026-04-03 10:57:54 +02:00

79 lines
1.9 KiB
Go

package message
import (
"encoding/json"
"fmt"
)
// ContentType discriminates the content block union.
type ContentType int
const (
ContentText ContentType = iota + 1
ContentToolCall
ContentToolResult
ContentThinking
)
func (ct ContentType) String() string {
switch ct {
case ContentText:
return "text"
case ContentToolCall:
return "tool_call"
case ContentToolResult:
return "tool_result"
case ContentThinking:
return "thinking"
default:
return fmt.Sprintf("unknown(%d)", ct)
}
}
// Content is a discriminated union. Exactly one payload field is set per Type.
type Content struct {
Type ContentType
Text string // ContentText
ToolCall *ToolCall // ContentToolCall
ToolResult *ToolResult // ContentToolResult
Thinking *Thinking // ContentThinking
}
// ToolCall represents the model's request to invoke a tool.
type ToolCall struct {
ID string `json:"id"`
Name string `json:"name"`
Arguments json.RawMessage `json:"arguments"`
}
// ToolResult is the output of executing a tool, correlated by ToolCallID.
type ToolResult struct {
ToolCallID string `json:"tool_call_id"`
Content string `json:"content"`
IsError bool `json:"is_error"`
}
// Thinking represents a reasoning/thinking trace.
// Signature must round-trip unchanged (Anthropic requirement).
type Thinking struct {
Text string `json:"text,omitempty"`
Signature string `json:"signature,omitempty"`
Redacted bool `json:"redacted,omitempty"`
}
func NewTextContent(text string) Content {
return Content{Type: ContentText, Text: text}
}
func NewToolCallContent(tc ToolCall) Content {
return Content{Type: ContentToolCall, ToolCall: &tc}
}
func NewToolResultContent(tr ToolResult) Content {
return Content{Type: ContentToolResult, ToolResult: &tr}
}
func NewThinkingContent(th Thinking) Content {
return Content{Type: ContentThinking, Thinking: &th}
}