How to Detect Terminal Task Statuses in GPT-Image2

GPT-Image2 considers a generation task terminal when the provider reports either completed or failed, enabling clients to determine completion by polling the /api/generation/status endpoint and inspecting the status field in the JSON response.

The freestylefly/awesome-gpt-image-2 repository implements a robust task lifecycle for image generation workflows. Detecting terminal task statuses is essential for managing UI states, releasing resources, and displaying final results or errors to users. This article examines the detection logic implemented in the API layer and provides practical code for checking task completion.

What Constitutes a Terminal Status

In GPT-Image2, a task reaches a terminal state when no further processing will occur. The system recognizes two terminal values:

  • completed – The image generation succeeded and a result URL is available.
  • failed – The generation encountered an error and the task cannot proceed.

These values are normalized from the provider’s native terminology and exposed through the public API, ensuring consistent client behavior regardless of upstream changes.

Server-Side Detection in api/generation/status.js

The primary detection logic resides in api/generation/status.js, which handles GET requests to /api/generation/status. The endpoint accepts a taskId query parameter and determines whether the task has finished by examining the status property.

The Terminal State Check

After retrieving the task—either from a stored reservation or by calling the APIMart API via getApimartTask—the handler evaluates the status field:

if (['completed', 'failed'].includes(task.status)) {
  await settlePlatformGeneration(auth.client, reservation, task);
}

This check appears at lines 63–66 in api/generation/status.js. When the condition evaluates to true, the system finalizes the task by invoking settlePlatformGeneration, which persists the result or error and updates the reservation record.

Handling Completed vs. Failed States

  • Completed tasks: The settlePlatformGeneration function stores the result image URL and marks the reservation as finalized.
  • Failed tasks: The system releases the reservation and records an error code, preventing resource leaks while maintaining audit trails.

Normalizing Provider Status Values

The backend must reconcile differences between the provider’s status vocabulary and the public API contract. The provider uses succeeded to indicate a finished generation, while the API exposes completed.

The formatStoredGeneration utility in api/_lib/generation.js handles this translation:

  • Maps succeeded → completed
  • Sets progress to 100% for terminal successes
  • Ensures the response shape matches expectations defined in api/_lib/generation.test.js

This normalization guarantees that clients only need to check for the standardized completed value, not provider-specific variants.

Client-Side Implementation

To detect terminal statuses from the browser or another HTTP client, poll the status endpoint and examine the status property. A value of completed or failed indicates the task is finished.

// Query the status of a generation task
async function getTaskStatus(taskId) {
  const resp = await fetch(`/api/generation/status?taskId=${taskId}`);
  const data = await resp.json();

  if (!data.ok) {
    throw new Error(`Error ${data.error}`);
  }

  // Terminal when status is "completed" or "failed"
  const isTerminal = ['completed', 'failed'].includes(data.status);
  console.log('Task status:', data.status, 'Terminal?', isTerminal);
  return { ...data, isTerminal };
}

// Usage
getTaskStatus('task_abcdefgh')
  .then(info => {
    if (info.isTerminal) {
      console.log('Result image:', info.image);
    } else {
      console.log('Task still in progress…');
    }
  })
  .catch(err => console.error(err));

When the task is terminal, the response includes the image URL, cost, and expiresAt timestamp. For non-terminal tasks, these fields are omitted to reduce payload size.

Key Components in the Detection Flow

Understanding the full architecture requires familiarity with these modules:

  • api/generation/status.js – The public endpoint handler that detects terminal states and triggers settlement logic.
  • api/_lib/generation.js – Core utilities including formatStoredGeneration for status normalization and settlePlatformGeneration for finalizing reservations.
  • api/_lib/generation.test.js – Validates that stored terminal rows are correctly transformed into the unified browser-facing shape.
  • shared/apimart.test.js – Confirms that HTTP errors and terminal task failures map to distinct, user-facing error codes.

Summary

  • Terminal values: GPT-Image2 treats completed and failed as the only terminal statuses.
  • Detection mechanism: Check task.status in the response from /api/generation/status.
  • Normalization: The backend converts the provider’s succeeded status to completed via formatStoredGeneration.
  • Settlement: Terminal tasks trigger settlePlatformGeneration to persist results and release reservations.
  • Polling strategy: Clients should poll the endpoint (which sets Cache-Control: no-store) until isTerminal is true.

Frequently Asked Questions

What HTTP endpoint should I use to check if a GPT-Image2 task is finished?

Send a GET request to /api/generation/status?taskId={taskId}. The endpoint returns a JSON object where the status field indicates the current state. When this value is either completed or failed, the task has reached a terminal state and will no longer change.

Why does the API return "completed" when the provider reports "succeeded"?

The backend normalizes provider-specific terminology through formatStoredGeneration in api/_lib/generation.js. The upstream provider uses succeeded for successful generations, but the public API unifies this to completed for consistency across client implementations, also setting progress to 100% in the response.

How does the system handle failed terminal tasks?

When the status is failed, the settlePlatformGeneration function in api/_lib/generation.js releases the reservation to free up resources and records the specific error code. This ensures that failed tasks do not consume capacity indefinitely while preserving diagnostic information for debugging.

Can I cache the status endpoint response to reduce API calls?

No. The endpoint explicitly sets Cache-Control: no-store headers via the internal json helper function to prevent caching of intermediate states. This guarantees that polling clients always receive the current task status rather than a stale, non-terminal response.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →