Skip to content

fix veo3 adapter - #1794

Merged
Calcium-Ion merged 1 commit into
QuantumNous:mainfrom
seefs001:fix/veo3
Sep 13, 2025
Merged

fix veo3 adapter#1794
Calcium-Ion merged 1 commit into
QuantumNous:mainfrom
seefs001:fix/veo3

Conversation

@seefs001

@seefs001 seefs001 commented Sep 13, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added status polling for Vertex tasks, enabling retrieval of long‑running operation progress and results.
    • Introduced asynchronous workflow support for Vertex submissions.
  • Improvements

    • More reliable request/response handling with standardized Vertex-compatible payloads and unified validation.
    • Enhanced region and project resolution for upstream requests, with sensible global defaults.
    • Clearer, consistent task status mapping (success, in progress, failure) in results.
    • Improved authentication flow for Vertex requests.
    • Default values (e.g., sample count) applied when not provided, reducing setup friction.

@coderabbitai

coderabbitai Bot commented Sep 13, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Refactors the Vertex TaskAdaptor to be stateful and RelayInfo-driven, updates all method signatures accordingly, unifies validation, rewrites URL/header/body construction, adjusts request/response handling, adds status polling via FetchTask, and standardizes result mapping to shared model status constants within a single adaptor file.

Changes

Cohort / File(s) Summary
Vertex TaskAdaptor refactor
relay/channel/task/vertex/adaptor.go
Convert TaskAdaptor to stateful (ChannelType, apiKey, baseURL). Replace TaskRelayInfo with RelayInfo across methods. Centralize validation. Rework URL/header/body builders to use adaptor fields and Vertex payloads. Update request/response handling. Add FetchTask for operation polling. Map operation states to model.TaskStatus*. Remove old helpers and add new parsing utilities.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant Adaptor as TaskAdaptor (stateful)
    participant Vertex as Vertex AI API

    Note over Adaptor: Initialized with ChannelType, apiKey, baseURL

    Client->>Adaptor: Init(RelayInfo)
    Client->>Adaptor: ValidateRequestAndSetAction(c, RelayInfo)
    Adaptor->>Adaptor: ValidateBasicTaskRequest(...)
    Client->>Adaptor: BuildRequestURL(RelayInfo)
    Adaptor->>Adaptor: Derive model & region from RelayInfo
    Client->>Adaptor: BuildRequestHeader(c, req, RelayInfo)
    Adaptor->>Adaptor: Decode credentials, acquire access token
    Client->>Adaptor: BuildRequestBody(c, RelayInfo)
    Adaptor->>Adaptor: Compose Vertex requestPayload
    Client->>Adaptor: DoRequest(c, RelayInfo, body)
    Adaptor->>Vertex: POST submit request
    Vertex-->>Adaptor: submitResponse (operation name)
    Adaptor-->>Client: DoResponse(...) → task_id (from operation)
Loading
sequenceDiagram
    autonumber
    participant Client
    participant Adaptor as TaskAdaptor
    participant Vertex as Vertex Operations API

    Client->>Adaptor: FetchTask(baseURL, key, {operationName})
    Adaptor->>Vertex: GET /operations/{name}
    Vertex-->>Adaptor: operationResponse (state, metadata)
    Adaptor->>Adaptor: ParseTaskResult → model.TaskStatus*
    Adaptor-->>Client: status, mapped result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • veo #1792: Also modifies relay/channel/task/vertex/adaptor.go with overlapping submit/fetch flow changes.
  • task_relay_info #1656: Refactors adaptor APIs from TaskRelayInfo to RelayInfo across the codebase, directly touching these signatures.
  • feat: vertex veo (#1450) #1659: Further updates to the Vertex TaskAdaptor, including request/response handling and polling.

Suggested reviewers

  • creamlike1024
  • Calcium-Ion
  • xyfacai

Poem

I thump my paws—new routes I chart,
Stateful burrows, a Relay heart.
I fetch the clouds, await the sign,
Operations bloom—success in line.
With headers snug and payload neat,
I hop through tasks on Vertex Street. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The current title "fix veo3 adapter" is related to the primary change (the Vertex/task adaptor rewrite) and therefore meets the requirement of being relevant to the changeset, but the shorthand "veo3" and the terse, lowercase phrasing make the intent less clear to reviewers.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
relay/channel/task/vertex/adaptor.go (2)

167-185: Handle non-2xx upstream responses and surface error details.
Currently all responses are parsed as success; a 4xx/5xx becomes a 500 "invalid_response". Preserve upstream status and message.

Apply:

 func (a *TaskAdaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) (taskID string, taskData []byte, taskErr *dto.TaskError) {
   responseBody, err := io.ReadAll(resp.Body)
   if err != nil {
     return "", nil, service.TaskErrorWrapper(err, "read_response_body_failed", http.StatusInternalServerError)
   }
   _ = resp.Body.Close()
+
+  if resp.StatusCode < 200 || resp.StatusCode >= 300 {
+    var em struct {
+      Error struct {
+        Message string `json:"message"`
+      } `json:"error"`
+    }
+    _ = json.Unmarshal(responseBody, &em)
+    msg := strings.TrimSpace(em.Error.Message)
+    if msg == "" {
+      msg = string(responseBody)
+    }
+    return "", nil, service.TaskErrorWrapper(fmt.Errorf(msg), "upstream_error", resp.StatusCode)
+  }
 
   var s submitResponse
   if err := json.Unmarshal(responseBody, &s); err != nil {
     return "", nil, service.TaskErrorWrapper(err, "unmarshal_response_failed", http.StatusInternalServerError)
   }

112-129: Pass channel proxy to Vertex token acquisition and cache tokens.

vertexcore.AcquireAccessToken(creds, proxy string) is implemented at relay/channel/vertex/service_account.go:142 — the Task adaptor currently calls AcquireAccessToken(..., "") which ignores proxy. Replace "" with info.ChannelSetting.Proxy at the two call sites: relay/channel/task/vertex/adaptor.go:122 and relay/channel/task/vertex/adaptor.go:224. Also add short-lived token caching (refresh near-expiry) to avoid repeated auth calls.

🧹 Nitpick comments (8)
relay/channel/task/vertex/adaptor.go (8)

24-27: Section banners are fine; keep consistent with repo style.
If there’s a linter/formatter rule for comments, align to it.


63-67: Unused struct field and missed opportunity for credential/token caching.

  • baseURL is set in Init but never used; remove or wire it into URL construction.
  • Repeated JSON unmarshal of apiKey occurs in multiple methods; decode once and cache.

Apply if you decide to remove the unused field:

 type TaskAdaptor struct {
   ChannelType int
-  apiKey      string
-  baseURL     string
+  apiKey      string
 }

And in Init (see next comment) drop the assignment to baseURL.


69-73: Decode service account JSON once during Init and store the typed creds.
This avoids repeated json.Unmarshal and centralizes credential validation.

I can provide a follow-up diff to add creds vertexcore.Credentials to TaskAdaptor and unmarshal here if you want.


81-110: URL building mostly correct; align defaults and avoid per-call JSON decode.

  • Region fallback here is "global" but FetchTask assumes "us-central1" on parse failure; pick one default to avoid split behavior.
  • Consider pre-parsed creds from Init to avoid repeating json.Unmarshal here.

Would you like a patch to centralize region defaulting and creds usage?


190-214: baseUrl parameter is unused; proxy and token concerns repeat here.

  • baseUrl is not referenced; either use it to override domain or remove from signature.
  • AcquireAccessToken again passes ""; use the same proxy strategy as request flow and share token caching.

If keeping baseUrl, consider honoring it when constructing url, or drop the parameter to avoid confusion.


205-206: Operation-name parsing: guard rails look good.
Ensure logs include the offending name when extraction fails to aid debugging.


239-302: Optional: include MIME inference once and reuse.
Current branches repeat encoding→MIME conversion. Factor into a small helper to reduce duplication.

I can draft a tiny helper like inferVideoMIME(enc string) string if helpful.


320-355: Regex extractors look safe for Vertex op names.
Patterns match expected shapes; consider unit tests for edge cases.

I can add tests for encode/decode and extractors; want me to open a small PR with those?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 28ed421 and da6f24a.

📒 Files selected for processing (1)
  • relay/channel/task/vertex/adaptor.go (10 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
relay/channel/task/vertex/adaptor.go (5)
relay/common/relay_info.go (1)
  • RelayInfo (74-120)
relay/common/relay_utils.go (1)
  • ValidateBasicTaskRequest (67-84)
relay/channel/vertex/service_account.go (2)
  • Credentials (22-28)
  • AcquireAccessToken (142-148)
relay/channel/api_request.go (1)
  • DoTaskApiRequest (279-301)
model/task.go (3)
  • TaskStatusFailure (18-18)
  • TaskStatusInProgress (17-17)
  • TaskStatusSuccess (19-19)
🔇 Additional comments (7)
relay/channel/task/vertex/adaptor.go (7)

10-10: Import of model status constants is correct.
Used appropriately in ParseTaskResult.


162-165: Delegation to shared request helper looks good.
Keeps behavior uniform across adaptors.


211-214: Region-aware fetch URLs look correct.
Matches global vs regional endpoints with fetchPredictOperation suffix.


246-256: Using centralized status constants is the right move.
Aligns with model.TaskStatus* across the codebase.


304-307: Helper section separation is clear.
No action needed.


308-318: ID encode/decode helpers look correct.
Base64 Raw URL encoding avoids slashes.


131-160: Harden BuildRequestBody: safe type-assert + coerce sampleCount

  • Use a safe type assertion for c.Get("task_request") to avoid panics. Apply the original diff below in relay/channel/task/vertex/adaptor.go (BuildRequestBody):
- v, ok := c.Get("task_request")
- if !ok {
+ v, ok := c.Get("task_request")
+ if !ok {
   return nil, fmt.Errorf("request not found in context")
- }
- req := v.(relaycommon.TaskSubmitReq)
+ }
+ req, ok := v.(relaycommon.TaskSubmitReq)
+ if !ok {
+   return nil, fmt.Errorf("invalid task_request type")
+ }
  • Coerce metadata["sampleCount"] to an int before adding to body.Parameters to avoid sending floats/strings to Vertex. Example minimal approach (add import strconv):
if v, ok := req.Metadata["sampleCount"]; ok {
  switch t := v.(type) {
  case int:
    body.Parameters["sampleCount"] = t
  case float64:
    body.Parameters["sampleCount"] = int(t)
  case string:
    s := strings.TrimSpace(t)
    if n, err := strconv.Atoi(s); err == nil {
      body.Parameters["sampleCount"] = n
    } else if f, err := strconv.ParseFloat(s, 64); err == nil {
      body.Parameters["sampleCount"] = int(f)
    }
  }
}
  • Confirm upstream parameter names/types: verify that Vertex expects "storageUri" and integer "sampleCount" in Parameters (adjust names/types if upstream differs).

File/loc: relay/channel/task/vertex/adaptor.go — BuildRequestBody (around lines ~131–160).

Comment on lines +75 to 79
// ValidateRequestAndSetAction parses body, validates fields and sets default action.
func (a *TaskAdaptor) ValidateRequestAndSetAction(c *gin.Context, info *relaycommon.RelayInfo) (taskErr *dto.TaskError) {
// Use the standard validation method for TaskSubmitReq
return relaycommon.ValidateBasicTaskRequest(c, info, constant.TaskActionTextGenerate)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Confirm the action type for video generation.
Using constant.TaskActionTextGenerate may be incorrect for Veo video tasks.

Run to verify the right constant (e.g., TaskActionVideoGenerate) exists and is used elsewhere:

If video-specific action exists, update:

- return relaycommon.ValidateBasicTaskRequest(c, info, constant.TaskActionTextGenerate)
+ return relaycommon.ValidateBasicTaskRequest(c, info, constant.TaskActionVideoGenerate)

🏁 Script executed:

#!/bin/bash
rg -n -C2 'TaskAction.*(Video|Text).*Generate' -- types
rg -n -C2 'ValidateBasicTaskRequest\('

Length of output: 1754


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "=== TaskAction symbols (all occurrences) ==="
rg -n -S '\bTaskAction\w*\b' || true

echo
echo "=== Usages of constant.TaskAction.* ==="
rg -n -S 'constant\.TaskAction\w*' || true

echo
echo "=== Files declaring package constant ==="
rg -n -S 'package constant' --files || true

echo
echo "=== Search for specific TaskAction constant names ==="
rg -n -S 'TaskActionTextGenerate|TaskActionVideoGenerate|TaskActionGenerate' || true

echo
echo "=== Show files that likely define constants (const blocks) ==="
rg -n -S '^\s*const\s+\(|^\s*const\s+\w+' || true

Length of output: 265682


Use TaskActionGenerate for video generation (TaskActionVideoGenerate doesn't exist). Change the call in relay/channel/task/vertex/adaptor.go (ValidateRequestAndSetAction — ~line 78) from constant.TaskActionTextGenerate to constant.TaskActionGenerate if this adaptor should accept video-generation requests; if the adaptor is text-only, keep as-is.

🤖 Prompt for AI Agents
In relay/channel/task/vertex/adaptor.go around lines 75-79, the call to
relaycommon.ValidateBasicTaskRequest currently passes
constant.TaskActionTextGenerate but this adaptor should accept video-generation
requests; update the argument to constant.TaskActionGenerate so the validator
allows video generation actions, keeping the rest of the call identical.

@Calcium-Ion
Calcium-Ion merged commit 7d71f46 into QuantumNous:main Sep 13, 2025
1 check passed
@coderabbitai coderabbitai Bot mentioned this pull request Nov 3, 2025
x22x22 pushed a commit to x22x22/new-api that referenced this pull request Apr 24, 2026
@coderabbitai coderabbitai Bot mentioned this pull request May 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants