e071084ebe
govulncheck / govulncheck (push) Waiting to run
Harness (E2E) / Harnesses (mock LLM) (push) Waiting to run
Harness (E2E) / Provider harnesses (live LLM conformance) (push) Waiting to run
Lint / golangci-lint (push) Waiting to run
Run Tests / Unit Tests (push) Waiting to run
Run Tests / Etcd Integration Tests (push) Waiting to run
160 lines
4.9 KiB
Go
160 lines
4.9 KiB
Go
package ai
|
|
|
|
import "sort"
|
|
|
|
// CapabilityRow is one deterministic row in a provider capability matrix.
|
|
type CapabilityRow struct {
|
|
// Provider is the registered provider name.
|
|
Provider string `json:"provider"`
|
|
Capabilities
|
|
}
|
|
|
|
// Capabilities describes the AI interfaces a provider has registered.
|
|
// It is intentionally based on package registration rather than external
|
|
// provider marketing claims, so it reflects what this build can actually use.
|
|
type Capabilities struct {
|
|
// Model reports whether ai.New can construct a chat/text model provider.
|
|
Model bool `json:"model"`
|
|
// Image reports whether ai.NewImage can construct an image model provider.
|
|
Image bool `json:"image"`
|
|
// Video reports whether ai.NewVideo can construct a video model provider.
|
|
Video bool `json:"video"`
|
|
// Stream reports whether the provider has registered end-to-end token streaming.
|
|
// Providers that only satisfy the Model interface with ErrStreamingUnsupported
|
|
// leave this false until their Stream implementation is usable.
|
|
Stream bool `json:"stream"`
|
|
// ToolStream reports whether the provider supports agent Stream requests that
|
|
// include tool schemas. Providers may support plain token streaming while
|
|
// leaving this false when their streaming API cannot accept tools.
|
|
ToolStream bool `json:"tool_stream"`
|
|
}
|
|
|
|
// ProviderCapabilities reports the capabilities registered for provider.
|
|
func ProviderCapabilities(provider string) Capabilities {
|
|
_, hasModel := providers[provider]
|
|
_, hasImage := imageProviders[provider]
|
|
_, hasVideo := videoProviders[provider]
|
|
_, hasStream := streamProviders[provider]
|
|
_, hasToolStream := toolStreamProviders[provider]
|
|
|
|
return Capabilities{
|
|
Model: hasModel,
|
|
Image: hasImage,
|
|
Video: hasVideo,
|
|
Stream: hasStream,
|
|
ToolStream: hasToolStream,
|
|
}
|
|
}
|
|
|
|
// CapabilityMatrix returns a snapshot of all registered AI providers and the
|
|
// interfaces they support. The returned map is a copy and can be modified by
|
|
// callers without mutating the registry. Use CapabilityRows when rendering a
|
|
// deterministic table or report.
|
|
func CapabilityMatrix() map[string]Capabilities {
|
|
names := map[string]struct{}{}
|
|
for name := range providers {
|
|
names[name] = struct{}{}
|
|
}
|
|
for name := range imageProviders {
|
|
names[name] = struct{}{}
|
|
}
|
|
for name := range videoProviders {
|
|
names[name] = struct{}{}
|
|
}
|
|
for name := range streamProviders {
|
|
names[name] = struct{}{}
|
|
}
|
|
for name := range toolStreamProviders {
|
|
names[name] = struct{}{}
|
|
}
|
|
|
|
matrix := make(map[string]Capabilities, len(names))
|
|
for name := range names {
|
|
matrix[name] = ProviderCapabilities(name)
|
|
}
|
|
return matrix
|
|
}
|
|
|
|
// CapabilityRows returns a deterministic capability support matrix for every
|
|
// registered AI provider. It is the ordered form of CapabilityMatrix, intended
|
|
// for CLIs, docs generators, and conformance reports that need stable output.
|
|
func CapabilityRows() []CapabilityRow {
|
|
names := RegisteredProviders("")
|
|
rows := make([]CapabilityRow, 0, len(names))
|
|
for _, name := range names {
|
|
rows = append(rows, CapabilityRow{
|
|
Provider: name,
|
|
Capabilities: ProviderCapabilities(name),
|
|
})
|
|
}
|
|
return rows
|
|
}
|
|
|
|
// RegisterStream records that provider has a usable Stream implementation.
|
|
// Providers should call this from init alongside Register once Stream returns
|
|
// chunks instead of ErrStreamingUnsupported.
|
|
func RegisterStream(provider string) {
|
|
streamProviders[provider] = struct{}{}
|
|
}
|
|
|
|
// RegisterToolStream records that provider can accept tool schemas in Stream
|
|
// requests. This is intentionally separate from RegisterStream because some
|
|
// providers can stream tokens but cannot expose tools while streaming.
|
|
func RegisterToolStream(provider string) {
|
|
toolStreamProviders[provider] = struct{}{}
|
|
}
|
|
|
|
var streamProviders = make(map[string]struct{})
|
|
var toolStreamProviders = make(map[string]struct{})
|
|
|
|
// RegisteredProviders returns the registered provider names in sorted order.
|
|
// kind may be "model", "image", "video", "stream", "tool_stream", or empty for the union of all
|
|
// provider registries.
|
|
func RegisteredProviders(kind string) []string {
|
|
names := map[string]struct{}{}
|
|
add := func(registry any) {
|
|
switch r := registry.(type) {
|
|
case map[string]NewFunc:
|
|
for name := range r {
|
|
names[name] = struct{}{}
|
|
}
|
|
case map[string]NewImageFunc:
|
|
for name := range r {
|
|
names[name] = struct{}{}
|
|
}
|
|
case map[string]NewVideoFunc:
|
|
for name := range r {
|
|
names[name] = struct{}{}
|
|
}
|
|
case map[string]struct{}:
|
|
for name := range r {
|
|
names[name] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch kind {
|
|
case "model":
|
|
add(providers)
|
|
case "stream":
|
|
add(streamProviders)
|
|
case "tool_stream":
|
|
add(toolStreamProviders)
|
|
case "image":
|
|
add(imageProviders)
|
|
case "video":
|
|
add(videoProviders)
|
|
default:
|
|
add(providers)
|
|
add(imageProviders)
|
|
add(videoProviders)
|
|
}
|
|
|
|
out := make([]string, 0, len(names))
|
|
for name := range names {
|
|
out = append(out, name)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|