picoclaw/pkg/providers/types.go
dj-oyu a888e9c9cc fix: resolve post-merge test failures and lint issues
- Fix test assertions to match upstream's changed error messages and
  command output formats across tools, agent, and channels packages
- Fix mockEditorWithSendID/mockDraftSender to properly shadow embedded
  EditMessage method in channels manager tests
- Remove unused functions (selectCandidates, findNearestUserMessage,
  retryLLMCall, inboundMetadata, absolutePathPattern, processRunning)
- Fix dogsled violations with newTestAgentLoopSimple helper
- Deduplicate test setup code (plan nudge, plan model tests)
- Add nolint directives for intentional CJK test fixtures and
  structurally similar but distinct test table patterns
- Auto-fix formatting (gci, gofumpt, golines, whitespace)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:48:58 +09:00

114 lines
3.2 KiB
Go

package providers
import (
"context"
"encoding/json"
"fmt"
"github.com/sipeed/picoclaw/pkg/providers/protocoltypes"
)
type (
ToolCall = protocoltypes.ToolCall
FunctionCall = protocoltypes.FunctionCall
LLMResponse = protocoltypes.LLMResponse
UsageInfo = protocoltypes.UsageInfo
Message = protocoltypes.Message
ToolDefinition = protocoltypes.ToolDefinition
ToolFunctionDefinition = protocoltypes.ToolFunctionDefinition
ExtraContent = protocoltypes.ExtraContent
GoogleExtra = protocoltypes.GoogleExtra
ContentBlock = protocoltypes.ContentBlock
CacheControl = protocoltypes.CacheControl
)
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()
}
// 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
}
// FailoverReason classifies why an LLM request failed for fallback decisions.
type FailoverReason string
const (
FailoverAuth FailoverReason = "auth"
FailoverRateLimit FailoverReason = "rate_limit"
FailoverBilling FailoverReason = "billing"
FailoverTimeout FailoverReason = "timeout"
FailoverFormat FailoverReason = "format"
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
}
// ModelConfig holds primary model and fallback list.
type ModelConfig struct {
Primary string
Fallbacks []string
}
// StreamingProvider extends LLMProvider with SSE channel-based streaming.
// Use a type assertion to check if a provider supports streaming:
//
// if sp, ok := provider.(StreamingProvider); ok && sp.CanStream() { ... }
type StreamingProvider interface {
LLMProvider
CanStream() bool
ChatStream(
ctx context.Context,
messages []Message,
tools []ToolDefinition,
model string,
options map[string]any,
) (<-chan protocoltypes.StreamEvent, error)
}
// UnmarshalArguments is a helper to parse FunctionCall.Arguments from json.RawMessage.
func UnmarshalArguments(raw json.RawMessage) (map[string]any, error) {
var m map[string]any
if err := json.Unmarshal(raw, &m); err != nil {
return nil, err
}
return m, nil
}