@@ -9,6 +9,7 @@ import (
10 "charm.land/fantasy"
10 "charm.land/fantasy"
11 "charm.land/fantasy/providers/anthropic"
11 "charm.land/fantasy/providers/anthropic"
12+ "charm.land/fantasy/providers/google"
12 "charm.land/fantasy/providers/openai"
13 "charm.land/fantasy/providers/openai"
13 "github.com/charmbracelet/catwalk/pkg/catwalk"
14 "github.com/charmbracelet/catwalk/pkg/catwalk"
@@ -41,11 +42,12 @@ type ContentPart interface {
43type ReasoningContent struct {
44type ReasoningContent struct {
44− Thinking string `json:"thinking"`
45+ Thinking string `json:"thinking"`
45− Signature string `json:"signature"`
46+ Signature string `json:"signature"`
47+ ThoughtSignature string `json:"thought_signature"` // Used for google
46− ResponsesData *openai.ResponsesReasoningMetadata `json:"responses_data"`
48+ ResponsesData *openai.ResponsesReasoningMetadata `json:"responses_data"`
47− StartedAt int64 `json:"started_at,omitempty"`
49+ StartedAt int64 `json:"started_at,omitempty"`
48− FinishedAt int64 `json:"finished_at,omitempty"`
50+ FinishedAt int64 `json:"finished_at,omitempty"`
51func (tc ReasoningContent) String() string {
53func (tc ReasoningContent) String() string {
@@ -259,6 +261,22 @@ func (m *Message) AppendReasoningContent(delta string) {
264+func (m *Message) AppendThoughtSignature(signature string) {
265+ for i, part := range m.Parts {
266+ if c, ok := part.(ReasoningContent); ok {
267+ m.Parts[i] = ReasoningContent{
268+ Thinking: c.Thinking,
269+ ThoughtSignature: c.ThoughtSignature + signature,
270+ Signature: c.Signature,
271+ StartedAt: c.StartedAt,
272+ FinishedAt: c.FinishedAt,
277+ m.Parts = append(m.Parts, ReasoningContent{ThoughtSignature: signature})
262func (m *Message) AppendReasoningSignature(signature string) {
280func (m *Message) AppendReasoningSignature(signature string) {
263 for i, part := range m.Parts {
281 for i, part := range m.Parts {
264 if c, ok := part.(ReasoningContent); ok {
282 if c, ok := part.(ReasoningContent); ok {
@@ -443,6 +461,11 @@ func (m *Message) ToAIMessage() []fantasy.Message {
443 if reasoning.ResponsesData != nil {
461 if reasoning.ResponsesData != nil {
444 reasoningPart.ProviderOptions[openai.Name] = reasoning.ResponsesData
462 reasoningPart.ProviderOptions[openai.Name] = reasoning.ResponsesData
464+ if reasoning.ThoughtSignature != "" {
465+ reasoningPart.ProviderOptions[google.Name] = &google.ReasoningMetadata{
466+ Signature: reasoning.ThoughtSignature,
446 parts = append(parts, reasoningPart)
469 parts = append(parts, reasoningPart)
448 for _, call := range m.ToolCalls() {
471 for _, call := range m.ToolCalls() {