feat(kling): 接入O1与3.0 Omni兼容接口
ci / verify (pull_request) Successful in 15m32s
ci / verify (pull_request) Successful in 15m32s
新增中国区可灵 V1 AK/SK Omni 协议与 API 2.0 兼容路径,补齐任务隔离、外部任务幂等、参数校验和 OpenAPI 文档。\n\n验证:O1 与 3.0 Omni 真实 V1 任务成功;Go、前端、依赖审计、迁移及 CI 脚本门禁通过。
This commit is contained in:
@@ -29,6 +29,16 @@ type TaskListResult struct {
|
||||
PageSize int
|
||||
}
|
||||
|
||||
type CompatTaskListFilter struct {
|
||||
Provider string
|
||||
Version string
|
||||
Statuses []string
|
||||
CreatedFrom *time.Time
|
||||
CreatedTo *time.Time
|
||||
Page int
|
||||
PageSize int
|
||||
}
|
||||
|
||||
func (s *Store) ListTasks(ctx context.Context, user *auth.User, filter TaskListFilter) (TaskListResult, error) {
|
||||
page := filter.Page
|
||||
if page <= 0 {
|
||||
@@ -146,6 +156,122 @@ LIMIT $8 OFFSET $9`, queryArgs...)
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetCompatTask(ctx context.Context, user *auth.User, provider string, version string, identifier string) (GatewayTask, error) {
|
||||
gatewayUserID := localGatewayUserID(user)
|
||||
apiKeyID := ""
|
||||
userID := ""
|
||||
if user != nil {
|
||||
apiKeyID = strings.TrimSpace(user.APIKeyID)
|
||||
userID = strings.TrimSpace(user.ID)
|
||||
}
|
||||
if gatewayUserID == "" && userID == "" {
|
||||
return GatewayTask{}, ErrLocalUserRequired
|
||||
}
|
||||
task, err := scanGatewayTask(s.pool.QueryRow(ctx, `
|
||||
SELECT `+gatewayTaskColumns+`
|
||||
FROM gateway_tasks
|
||||
WHERE (
|
||||
(NULLIF($1, '')::uuid IS NOT NULL AND gateway_user_id = NULLIF($1, '')::uuid)
|
||||
OR (NULLIF($1, '')::uuid IS NULL AND NULLIF($2, '') IS NOT NULL AND user_id = $2)
|
||||
)
|
||||
AND (NULLIF($3, '') IS NULL OR api_key_id = $3)
|
||||
AND request->>'_compat_provider' = $4
|
||||
AND request->>'_kling_compat_version' = $5
|
||||
AND (id::text = $6 OR external_task_id = $6)
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1`, gatewayUserID, userID, apiKeyID, strings.TrimSpace(provider), strings.TrimSpace(version), strings.TrimSpace(identifier)))
|
||||
if err != nil {
|
||||
return GatewayTask{}, err
|
||||
}
|
||||
attempts, err := s.ListTaskAttempts(ctx, task.ID)
|
||||
if err != nil {
|
||||
return GatewayTask{}, err
|
||||
}
|
||||
task.Attempts = attempts
|
||||
return task, nil
|
||||
}
|
||||
|
||||
func (s *Store) ListCompatTasks(ctx context.Context, user *auth.User, filter CompatTaskListFilter) (TaskListResult, error) {
|
||||
page := filter.Page
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
pageSize := filter.PageSize
|
||||
if pageSize <= 0 {
|
||||
pageSize = 30
|
||||
}
|
||||
if pageSize > 500 {
|
||||
pageSize = 500
|
||||
}
|
||||
offset := (page - 1) * pageSize
|
||||
gatewayUserID := localGatewayUserID(user)
|
||||
apiKeyID := ""
|
||||
userID := ""
|
||||
if user != nil {
|
||||
apiKeyID = strings.TrimSpace(user.APIKeyID)
|
||||
userID = strings.TrimSpace(user.ID)
|
||||
}
|
||||
if gatewayUserID == "" && userID == "" {
|
||||
return TaskListResult{}, ErrLocalUserRequired
|
||||
}
|
||||
statuses := filter.Statuses
|
||||
if len(statuses) == 0 {
|
||||
statuses = nil
|
||||
}
|
||||
args := []any{
|
||||
gatewayUserID,
|
||||
userID,
|
||||
apiKeyID,
|
||||
strings.TrimSpace(filter.Provider),
|
||||
strings.TrimSpace(filter.Version),
|
||||
nullableTaskListTime(filter.CreatedFrom),
|
||||
nullableTaskListTime(filter.CreatedTo),
|
||||
statuses,
|
||||
}
|
||||
whereSQL := `
|
||||
WHERE (
|
||||
(NULLIF($1, '')::uuid IS NOT NULL AND gateway_user_id = NULLIF($1, '')::uuid)
|
||||
OR (NULLIF($1, '')::uuid IS NULL AND NULLIF($2, '') IS NOT NULL AND user_id = $2)
|
||||
)
|
||||
AND (NULLIF($3, '') IS NULL OR api_key_id = $3)
|
||||
AND request->>'_compat_provider' = $4
|
||||
AND request->>'_kling_compat_version' = $5
|
||||
AND ($6::timestamptz IS NULL OR created_at >= $6::timestamptz)
|
||||
AND ($7::timestamptz IS NULL OR created_at <= $7::timestamptz)
|
||||
AND ($8::text[] IS NULL OR status = ANY($8::text[]))`
|
||||
var total int
|
||||
if err := s.pool.QueryRow(ctx, `SELECT count(*) FROM gateway_tasks `+whereSQL, args...).Scan(&total); err != nil {
|
||||
return TaskListResult{}, err
|
||||
}
|
||||
queryArgs := append(args, pageSize, offset)
|
||||
rows, err := s.pool.Query(ctx, `
|
||||
SELECT `+gatewayTaskColumns+`
|
||||
FROM gateway_tasks
|
||||
`+whereSQL+`
|
||||
ORDER BY created_at DESC
|
||||
LIMIT $9 OFFSET $10`, queryArgs...)
|
||||
if err != nil {
|
||||
return TaskListResult{}, err
|
||||
}
|
||||
defer rows.Close()
|
||||
items := make([]GatewayTask, 0)
|
||||
for rows.Next() {
|
||||
task, err := scanGatewayTask(rows)
|
||||
if err != nil {
|
||||
return TaskListResult{}, err
|
||||
}
|
||||
items = append(items, task)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return TaskListResult{}, err
|
||||
}
|
||||
items, err = s.attachTaskAttempts(ctx, items)
|
||||
if err != nil {
|
||||
return TaskListResult{}, err
|
||||
}
|
||||
return TaskListResult{Items: items, Total: total, Page: page, PageSize: pageSize}, nil
|
||||
}
|
||||
|
||||
func nullableTaskListTime(value *time.Time) any {
|
||||
if value == nil {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user