// tool.go tool çağırma (function calling) sözleşmesidir.
//
// Provider ARAYÜZÜ DEĞİŞMEZ: tool desteği isteğe bağlı bir alt arayüzdür (Embedder gibi).
// Böylece tool çağırmayan sağlayıcı olmayan sistemler (test sahteleri, basit sağlayıcılar)
// derlenmeye devam eder; ajan ToolProvider yoksa tool'suz çalışır (bugünkü davranış).
package llm

import "context"

// ToolSpec modele tanıtılacak tool'un tanımıdır (JSON Schema biçiminde).
// Skill ve tool alan modelinin LLM'e giden görünümüdür; sunucuda dönüştürülür.
type ToolSpec struct {
	Name        string         `json:"name"`
	Description string         `json:"description"`
	InputSchema map[string]any `json:"inputSchema,omitempty"`
}

// ToolCall modelin istediği bir tool çağrısıdır.
type ToolCall struct {
	Name string
	// Arguments çağrının girdisi. Sağlayıcı metin (JSON) dönerse parse edilir;
	// ayrıştırılamazsa ArgsError nedeniyle döner (sessizce boş girdiye DÖNÜLMEZ).
	Arguments map[string]any
}

// ArgsError, sağlayıcının tool argümanlarını JSON olarak veremediği durumdur.
type ArgsError struct {
	Raw string
	Err error
}

func (e *ArgsError) Error() string { return "llm: tool argümanları okunamadı: " + e.Err.Error() }
func (e *ArgsError) Unwrap() error { return e.Err }

// ToolProvider tool çağırmayı destekleyen sağlayıcılardır.
// GenerateStream ile AYNI akış sözleşmesini paylaşır: metin delta'ları onDelta'ya akar,
// ancak sonuç ToolCalls içerebilir.
type ToolProvider interface {
	GenerateStreamWithTools(ctx context.Context, req Request, tools []ToolSpec, onDelta DeltaFunc) (Result, error)
}

// SupportsToolCalling sağlayıcının tool çağırmayı destekleyip desteklemediğini bildirir.
func SupportsToolCalling(p Provider) bool {
	_, ok := p.(ToolProvider)
	return ok
}
