mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-05-25 16:00:35 +00:00
639b32703a
* Support streaming * fix: stream pico reasoning updates Route Pico reasoning through the active streamer and hide empty thought placeholders. * fix: harden configured streaming delivery * fix ci * fix split issue
127 lines
3.9 KiB
Go
127 lines
3.9 KiB
Go
package providers
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/sipeed/picoclaw/pkg/providers/protocoltypes"
|
|
)
|
|
|
|
type (
|
|
ToolCall = protocoltypes.ToolCall
|
|
FunctionCall = protocoltypes.FunctionCall
|
|
LLMResponse = protocoltypes.LLMResponse
|
|
StreamChunk = protocoltypes.StreamChunk
|
|
UsageInfo = protocoltypes.UsageInfo
|
|
Message = protocoltypes.Message
|
|
ToolDefinition = protocoltypes.ToolDefinition
|
|
ToolFunctionDefinition = protocoltypes.ToolFunctionDefinition
|
|
ExtraContent = protocoltypes.ExtraContent
|
|
GoogleExtra = protocoltypes.GoogleExtra
|
|
ContentBlock = protocoltypes.ContentBlock
|
|
CacheControl = protocoltypes.CacheControl
|
|
Attachment = protocoltypes.Attachment
|
|
)
|
|
|
|
type LLMProvider interface {
|
|
Chat(
|
|
ctx context.Context,
|
|
messages []Message,
|
|
tools []ToolDefinition,
|
|
model string,
|
|
options map[string]any,
|
|
) (*LLMResponse, error)
|
|
GetDefaultModel() string
|
|
}
|
|
|
|
type StatefulProvider interface {
|
|
LLMProvider
|
|
Close()
|
|
}
|
|
|
|
// StreamingProvider is an optional interface for providers that support token streaming.
|
|
// onChunk receives the accumulated text so far (not individual deltas).
|
|
// The returned LLMResponse is the same complete response for compatibility with tool-call handling.
|
|
type StreamingProvider interface {
|
|
ChatStream(
|
|
ctx context.Context,
|
|
messages []Message,
|
|
tools []ToolDefinition,
|
|
model string,
|
|
options map[string]any,
|
|
onChunk func(accumulated string),
|
|
) (*LLMResponse, error)
|
|
}
|
|
|
|
type StreamingEventProvider interface {
|
|
ChatStreamEvents(
|
|
ctx context.Context,
|
|
messages []Message,
|
|
tools []ToolDefinition,
|
|
model string,
|
|
options map[string]any,
|
|
onChunk func(StreamChunk),
|
|
) (*LLMResponse, error)
|
|
}
|
|
|
|
// ThinkingCapable is an optional interface for providers that support
|
|
// extended thinking (e.g. Anthropic). Used by the agent loop to warn
|
|
// when thinking_level is configured but the active provider cannot use it.
|
|
type ThinkingCapable interface {
|
|
SupportsThinking() bool
|
|
}
|
|
|
|
// NativeSearchCapable is an optional interface for providers that support
|
|
// built-in web search during LLM inference (e.g. OpenAI web_search_preview,
|
|
// xAI Grok search). When the active provider implements this interface and
|
|
// returns true, the agent loop can hide the client-side web_search tool to
|
|
// avoid duplicate search surfaces and use the provider's native search instead.
|
|
type NativeSearchCapable interface {
|
|
SupportsNativeSearch() bool
|
|
}
|
|
|
|
// FailoverReason classifies why an LLM request failed for fallback decisions.
|
|
type FailoverReason string
|
|
|
|
const (
|
|
FailoverAuth FailoverReason = "auth"
|
|
FailoverRateLimit FailoverReason = "rate_limit"
|
|
FailoverBilling FailoverReason = "billing"
|
|
FailoverNetwork FailoverReason = "network"
|
|
FailoverTimeout FailoverReason = "timeout"
|
|
FailoverFormat FailoverReason = "format"
|
|
FailoverContextOverflow FailoverReason = "context_overflow"
|
|
FailoverOverloaded FailoverReason = "overloaded"
|
|
FailoverUnknown FailoverReason = "unknown"
|
|
)
|
|
|
|
// FailoverError wraps an LLM provider error with classification metadata.
|
|
type FailoverError struct {
|
|
Reason FailoverReason
|
|
Provider string
|
|
Model string
|
|
Status int
|
|
Wrapped error
|
|
}
|
|
|
|
func (e *FailoverError) Error() string {
|
|
return fmt.Sprintf("failover(%s): provider=%s model=%s status=%d: %v",
|
|
e.Reason, e.Provider, e.Model, e.Status, e.Wrapped)
|
|
}
|
|
|
|
func (e *FailoverError) Unwrap() error {
|
|
return e.Wrapped
|
|
}
|
|
|
|
// IsRetriable returns true if this error should trigger fallback to next candidate.
|
|
// Non-retriable: Format errors (bad request structure, image dimension/size).
|
|
func (e *FailoverError) IsRetriable() bool {
|
|
return e.Reason != FailoverFormat && e.Reason != FailoverContextOverflow
|
|
}
|
|
|
|
// ModelConfig holds primary model and fallback list.
|
|
type ModelConfig struct {
|
|
Primary string
|
|
Fallbacks []string
|
|
}
|