first commit
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
// This file defines the unified Provider interface and its dual failure model
|
||||
// (US-007). A Provider turns a CompletionRequest into a stream of
|
||||
// AssistantMessageEvents. Failures follow the same contract as StreamFn (FR-13):
|
||||
//
|
||||
// - "cannot even build the stream" (bad config, missing model) → returned error.
|
||||
// - any runtime failure once streaming has begun → a terminal StreamErrorEvent
|
||||
// carrying an assistant message with stopReason=error/aborted, after which
|
||||
// the stream is closed. It is never a returned error.
|
||||
//
|
||||
// Model carries provider-agnostic capability metadata so the loop and UI can
|
||||
// reason about a model without knowing the concrete provider.
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/smallnest/pigo/internal/agentcore"
|
||||
)
|
||||
|
||||
// Model is provider-agnostic metadata describing a single model's identity and
|
||||
// capabilities. Providers construct these; the loop/UI consume them.
|
||||
type Model struct {
|
||||
// Provider is the provider name (e.g. "anthropic", "openai").
|
||||
Provider string `json:"provider"`
|
||||
// ID is the provider-specific model id (e.g. "claude-opus-4-8").
|
||||
ID string `json:"id"`
|
||||
// DisplayName is a human-friendly label; falls back to ID when empty.
|
||||
DisplayName string `json:"displayName,omitempty"`
|
||||
// ContextWindow is the maximum input+output token window, 0 if unknown.
|
||||
ContextWindow int `json:"contextWindow,omitempty"`
|
||||
// MaxOutputTokens is the max tokens the model may emit per response, 0 if
|
||||
// unknown.
|
||||
MaxOutputTokens int `json:"maxOutputTokens,omitempty"`
|
||||
// SupportsThinking reports whether the model exposes a reasoning/thinking
|
||||
// channel.
|
||||
SupportsThinking bool `json:"supportsThinking,omitempty"`
|
||||
// SupportsTools reports whether the model can call tools.
|
||||
SupportsTools bool `json:"supportsTools,omitempty"`
|
||||
// SupportsImages reports whether the model accepts image (multimodal) input.
|
||||
// When false, an image block in the request is reported as a hard error
|
||||
// rather than silently dropped, so the user learns the model cannot see it.
|
||||
SupportsImages bool `json:"supportsImages,omitempty"`
|
||||
// ThinkingLevels maps unified thinking levels to this model's wire values.
|
||||
// nil when the model does not support thinking (decision #10).
|
||||
ThinkingLevels agentcore.ThinkingLevelMap `json:"-"`
|
||||
}
|
||||
|
||||
// CompletionRequest is the provider-agnostic input to StreamCompletion: the
|
||||
// model id, the shaped LLM context, and per-request options.
|
||||
type CompletionRequest struct {
|
||||
// Model is the provider-specific model id to complete against.
|
||||
Model string
|
||||
// Context is the shaped request (system prompt, LLM-bound messages, tools).
|
||||
Context LlmContext
|
||||
// Config carries per-request options (API key, thinking level, extras).
|
||||
Config StreamConfig
|
||||
}
|
||||
|
||||
// Provider is the unified streaming interface implemented by every backend. It
|
||||
// hides per-vendor differences behind a single AssistantMessageEvent stream.
|
||||
type Provider interface {
|
||||
// Name returns the provider's identifier (matches Model.Provider).
|
||||
Name() string
|
||||
// Models lists the models this provider can serve.
|
||||
Models() []Model
|
||||
// StreamCompletion streams a completion for req. Per the dual failure model
|
||||
// it returns an error only for the earliest "cannot build the stream" case;
|
||||
// all runtime failures ride the returned stream as a terminal error event.
|
||||
StreamCompletion(ctx context.Context, req CompletionRequest) (*AssistantMessageEventStream, error)
|
||||
}
|
||||
|
||||
// StreamFnFromProvider adapts a Provider to the loop's StreamFn contract so a
|
||||
// Provider can drive streamAssistantResponse directly. The two failure models
|
||||
// are identical, so the adaptation is a straight delegation.
|
||||
func StreamFnFromProvider(p Provider) StreamFn {
|
||||
return func(ctx context.Context, model string, llm LlmContext, cfg StreamConfig) (*AssistantMessageEventStream, error) {
|
||||
return p.StreamCompletion(ctx, CompletionRequest{Model: model, Context: llm, Config: cfg})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user