Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
181 lines
5.8 KiB
Go
181 lines
5.8 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/Wei-Shaw/sub2api/internal/config"
|
|
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
|
)
|
|
|
|
type BatchImageProvider interface {
|
|
Name() string
|
|
SupportsAccount(account *Account) bool
|
|
Submit(ctx context.Context, job *BatchImageJob, account *Account, input BatchImageInput) (*BatchProviderJob, error)
|
|
Get(ctx context.Context, job *BatchImageJob, account *Account) (*BatchProviderStatus, error)
|
|
Cancel(ctx context.Context, job *BatchImageJob, account *Account) error
|
|
OpenResult(ctx context.Context, job *BatchImageJob, account *Account) (io.ReadCloser, string, error)
|
|
Cleanup(ctx context.Context, job *BatchImageJob, account *Account, target CleanupTarget) error
|
|
}
|
|
|
|
type BatchImageProviderRegistry struct {
|
|
providers map[string]BatchImageProvider
|
|
}
|
|
|
|
func NewBatchImageProviderRegistry(providers ...BatchImageProvider) *BatchImageProviderRegistry {
|
|
r := &BatchImageProviderRegistry{providers: make(map[string]BatchImageProvider, len(providers))}
|
|
for _, provider := range providers {
|
|
if provider == nil || strings.TrimSpace(provider.Name()) == "" {
|
|
continue
|
|
}
|
|
r.providers[provider.Name()] = provider
|
|
}
|
|
return r
|
|
}
|
|
|
|
func NewDefaultBatchImageProviderRegistry() *BatchImageProviderRegistry {
|
|
return NewBatchImageProviderRegistry(
|
|
NewGeminiAPIBatchImageProvider(nil),
|
|
NewVertexBatchImageProvider(VertexBatchImageProviderOptions{}, nil, nil, nil),
|
|
)
|
|
}
|
|
|
|
func NewBatchImageProviderRegistryFromConfig(cfg *config.Config) *BatchImageProviderRegistry {
|
|
return NewBatchImageProviderRegistry(
|
|
NewGeminiAPIBatchImageProvider(nil),
|
|
NewVertexBatchImageProviderFromConfig(cfg, nil, nil, nil),
|
|
)
|
|
}
|
|
|
|
func (r *BatchImageProviderRegistry) Get(provider string) (BatchImageProvider, bool) {
|
|
if r == nil {
|
|
return nil, false
|
|
}
|
|
p, ok := r.providers[provider]
|
|
return p, ok
|
|
}
|
|
|
|
func (r *BatchImageProviderRegistry) MustGet(provider string) (BatchImageProvider, error) {
|
|
p, ok := r.Get(provider)
|
|
if !ok {
|
|
return nil, ErrBatchImageInvalidProvider
|
|
}
|
|
return p, nil
|
|
}
|
|
|
|
type BatchImageInput struct {
|
|
BatchID string
|
|
Model string
|
|
DisplayName string
|
|
Items []BatchImageInputItem
|
|
|
|
ResponseMimeType string
|
|
AspectRatio string
|
|
ImageSize string
|
|
|
|
Metadata map[string]string
|
|
}
|
|
|
|
type BatchImageInputItem struct {
|
|
CustomID string
|
|
Prompt string
|
|
|
|
ReferenceImages []BatchImageReference
|
|
}
|
|
|
|
type BatchImageReference struct {
|
|
ID string
|
|
Type string
|
|
MimeType string
|
|
Data []byte
|
|
FileURI string
|
|
}
|
|
|
|
type BatchProviderJob struct {
|
|
ProviderJobName string
|
|
ProviderInputRef string
|
|
ProviderOutputRef string
|
|
RawState string
|
|
}
|
|
|
|
type BatchProviderInternalState string
|
|
|
|
const (
|
|
BatchProviderStateQueued BatchProviderInternalState = "queued"
|
|
BatchProviderStateRunning BatchProviderInternalState = "running"
|
|
BatchProviderStateSucceeded BatchProviderInternalState = "succeeded"
|
|
BatchProviderStateFailed BatchProviderInternalState = "failed"
|
|
BatchProviderStateCancelled BatchProviderInternalState = "cancelled"
|
|
BatchProviderStateExpired BatchProviderInternalState = "expired"
|
|
)
|
|
|
|
type BatchProviderStatus struct {
|
|
RawState string
|
|
|
|
InternalState BatchProviderInternalState
|
|
Done bool
|
|
|
|
ProviderOutputRef string
|
|
|
|
ErrorCode string
|
|
ErrorMessage string
|
|
|
|
SuggestedRequeueAfter time.Duration
|
|
}
|
|
|
|
type CleanupTarget string
|
|
|
|
const (
|
|
CleanupTargetInput CleanupTarget = "input"
|
|
CleanupTargetOutput CleanupTarget = "output"
|
|
CleanupTargetAll CleanupTarget = "all"
|
|
)
|
|
|
|
var (
|
|
ErrBatchImageProviderUnsupportedAccount = infraerrors.New(http.StatusBadRequest, "BATCH_IMAGE_PROVIDER_UNSUPPORTED_ACCOUNT", "batch image provider does not support this account")
|
|
ErrBatchImageProviderMissingAPIKey = infraerrors.New(http.StatusBadRequest, "BATCH_IMAGE_PROVIDER_MISSING_API_KEY", "batch image provider account is missing api key")
|
|
ErrBatchImageProviderMissingServiceAccount = infraerrors.New(http.StatusBadRequest, "BATCH_IMAGE_PROVIDER_MISSING_SERVICE_ACCOUNT", "batch image provider account is missing service account credentials")
|
|
ErrBatchImageProviderMissingJobName = infraerrors.New(http.StatusBadRequest, "BATCH_IMAGE_PROVIDER_MISSING_JOB_NAME", "batch image provider job name is missing")
|
|
ErrBatchImageProviderMissingResultRef = infraerrors.New(http.StatusBadRequest, "BATCH_IMAGE_PROVIDER_MISSING_RESULT_REF", "batch image provider result reference is missing")
|
|
ErrBatchImageProviderInlineResultUnsupported = infraerrors.New(http.StatusBadRequest, "GEMINI_INLINE_BATCH_RESULT_UNSUPPORTED", "Gemini inline batch result is not supported")
|
|
ErrBatchImageProviderInvalidInput = infraerrors.New(http.StatusBadRequest, "BATCH_IMAGE_PROVIDER_INVALID_INPUT", "invalid batch image provider input")
|
|
ErrBatchImageProviderUnsafeCleanupPath = infraerrors.New(http.StatusBadRequest, "VERTEX_UNSAFE_CLEANUP_PATH", "unsafe batch image cleanup path")
|
|
ErrUnsupportedCleanupTarget = infraerrors.New(http.StatusBadRequest, "BATCH_IMAGE_PROVIDER_UNSUPPORTED_CLEANUP_TARGET", "unsupported batch image cleanup target")
|
|
)
|
|
|
|
func batchImageProviderJobName(job *BatchImageJob) string {
|
|
if job == nil || job.ProviderJobName == nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(*job.ProviderJobName)
|
|
}
|
|
|
|
func batchImageProviderInputRef(job *BatchImageJob) string {
|
|
if job == nil || job.ProviderInputRef == nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(*job.ProviderInputRef)
|
|
}
|
|
|
|
func batchImageProviderOutputRef(job *BatchImageJob) string {
|
|
if job == nil || job.ProviderOutputRef == nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(*job.ProviderOutputRef)
|
|
}
|
|
|
|
func batchImageProviderAPIKey(account *Account) string {
|
|
if account == nil {
|
|
return ""
|
|
}
|
|
return strings.TrimSpace(account.GetCredential("api_key"))
|
|
}
|
|
|
|
func batchImageProviderInputError(format string, args ...any) error {
|
|
return ErrBatchImageProviderInvalidInput.WithCause(fmt.Errorf(format, args...))
|
|
}
|