Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
248 changes: 248 additions & 0 deletions docs/community-adapters/decart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
---
title: Decart
id: decart-adapter
order: 2
---

The Decart adapter provides access to Decart's image and video generation models.

## Installation

```bash
npm install @decartai/tanstack-ai-adapter
```

## Basic Usage

```typescript
import { generateImage } from "@tanstack/ai";
import { decartImage } from "@decartai/tanstack-ai-adapter";

const result = await generateImage({
adapter: decartImage("lucy-pro-t2i"),
prompt: "A serene mountain landscape at sunset",
});
```

## Basic Usage - Custom API Key

```typescript
import { generateImage } from "@tanstack/ai";
import { createDecartImage } from "@decartai/tanstack-ai-adapter";

const adapter = createDecartImage("lucy-pro-t2i", process.env.DECART_API_KEY!);

const result = await generateImage({
adapter,
prompt: "A serene mountain landscape at sunset",
});
```

## Configuration

```typescript
import { createDecartImage, type DecartImageConfig } from "@decartai/tanstack-ai-adapter";

const config: Omit<DecartImageConfig, "apiKey"> = {
baseUrl: "https://api.decart.ai", // Optional, for custom endpoints
};

const adapter = createDecartImage("lucy-pro-t2i", process.env.DECART_API_KEY!, config);
```

## Image Generation

Generate images with `lucy-pro-t2i`:

```typescript
import { generateImage } from "@tanstack/ai";
import { decartImage } from "@decartai/tanstack-ai-adapter";

const result = await generateImage({
adapter: decartImage("lucy-pro-t2i"),
prompt: "A futuristic cityscape at night",
});

console.log(result.images[0].b64Json);
```

### Image Model Options

```typescript
const result = await generateImage({
adapter: decartImage("lucy-pro-t2i"),
prompt: "A portrait of a robot artist",
modelOptions: {
resolution: "720p",
orientation: "portrait",
seed: 42,
},
});
```

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `resolution` | `"720p"` | `"720p"` | Output resolution |
| `orientation` | `"portrait" \| "landscape"` | `"landscape"` | Image orientation |
| `seed` | `number` | - | Seed for reproducible generation |

## Video Generation

Video generation uses an async job/polling architecture.

### Creating a Video Job

```typescript
import { generateVideo } from "@tanstack/ai";
import { decartVideo } from "@decartai/tanstack-ai-adapter";

const { jobId } = await generateVideo({
adapter: decartVideo("lucy-pro-t2v"),
prompt: "A cat playing with a ball of yarn",
});

console.log("Job started:", jobId);
```

### Polling for Status

```typescript
import { getVideoJobStatus } from "@tanstack/ai";
import { decartVideo } from "@decartai/tanstack-ai-adapter";

const status = await getVideoJobStatus({
adapter: decartVideo("lucy-pro-t2v"),
jobId,
});

console.log("Status:", status.status); // "pending" | "processing" | "completed" | "failed"

if (status.status === "completed" && status.url) {
console.log("Video URL:", status.url);
}
```

### Complete Example with Polling

```typescript
import { generateVideo, getVideoJobStatus } from "@tanstack/ai";
import { decartVideo } from "@decartai/tanstack-ai-adapter";

async function createVideo(prompt: string) {
const adapter = decartVideo("lucy-pro-t2v");

// Create the job
const { jobId } = await generateVideo({ adapter, prompt });
console.log("Job created:", jobId);

// Poll for completion
let status = "pending";
while (status !== "completed" && status !== "failed") {
await new Promise((resolve) => setTimeout(resolve, 5000));

const result = await getVideoJobStatus({ adapter, jobId });
status = result.status;
console.log(`Status: ${status}`);

if (result.status === "failed") {
throw new Error("Video generation failed");
}

if (result.status === "completed" && result.url) {
return result.url;
}
}
}

const videoUrl = await createVideo("A drone shot over a tropical beach");
```
Comment on lines +125 to +158
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 28, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Handle the edge case where video completes without a URL.

The polling loop has a logic gap: if result.status === "completed" but result.url is falsy (line 151), the function won't return. On the next iteration, the while condition (line 140) will be false since status === "completed", causing the loop to exit without a return statement. The function will then return undefined.

🔎 Proposed fix to handle missing URL
     if (result.status === "failed") {
       throw new Error("Video generation failed");
     }

     if (result.status === "completed" && result.url) {
       return result.url;
     }
+
+    if (result.status === "completed") {
+      throw new Error("Video generation completed without a URL");
+    }
   }
 }
🤖 Prompt for AI Agents
In docs/community-adapters/decart.md around lines 125 to 158, the createVideo
polling loop can exit when status === "completed" but result.url is falsy,
leading to an implicit undefined return; fix by ensuring the function either
waits until a completed result includes a URL or throws a clear error: either
(A) change the loop condition to continue until status === "failed" or (status
=== "completed" && result.url) so it only exits when a URL is present or failure
occurs, or (B) leave the loop as-is but add an explicit check after the loop
that if status === "completed" and no url was returned, throw a descriptive
Error (e.g., "Video completed but no URL returned") to avoid returning
undefined.

Copy link
Author

Choose a reason for hiding this comment

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

Not sure it's needed? I'd prefer to keep the example focused, but happy to add it if you think it's useful.

Copy link
Contributor

Choose a reason for hiding this comment

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

@AdirAmsalem You're right—for documentation, keeping the example focused on the happy path is more valuable. The edge case handling would add noise to what's meant to be a clear, educational example. I'm good with leaving it as-is. 👍


### Video Model Options

```typescript
const { jobId } = await generateVideo({
adapter: decartVideo("lucy-pro-t2v"),
prompt: "A timelapse of a blooming flower",
modelOptions: {
resolution: "720p",
orientation: "landscape",
seed: 42,
},
});
```

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `resolution` | `"720p" \| "480p"` | `"720p"` | Output resolution |
| `orientation` | `"portrait" \| "landscape"` | `"landscape"` | Video orientation |
| `seed` | `number` | - | Seed for reproducible generation |

## Environment Variables

Set your API key in environment variables:

```bash
DECART_API_KEY=your-api-key-here
```

## Getting an API Key

1. Go to [Decart Platform](https://platform.decart.ai)
2. Create an account and generate an API key
3. Add it to your environment variables

## API Reference

### `decartImage(model, config?)`

Creates a Decart image adapter using environment variables.

**Parameters:**

- `model` - Model name (`"lucy-pro-t2i"`)
- `config.baseUrl?` - Custom base URL (optional)

**Returns:** A Decart image adapter instance.

### `createDecartImage(model, apiKey, config?)`

Creates a Decart image adapter with an explicit API key.

**Parameters:**

- `model` - Model name (`"lucy-pro-t2i"`)
- `apiKey` - Your Decart API key
- `config.baseUrl?` - Custom base URL (optional)

**Returns:** A Decart image adapter instance.

### `decartVideo(model, config?)`

Creates a Decart video adapter using environment variables.

**Parameters:**

- `model` - Model name (`"lucy-pro-t2v"`)
- `config.baseUrl?` - Custom base URL (optional)

**Returns:** A Decart video adapter instance.

### `createDecartVideo(model, apiKey, config?)`

Creates a Decart video adapter with an explicit API key.

**Parameters:**

- `model` - Model name (`"lucy-pro-t2v"`)
- `apiKey` - Your Decart API key
- `config.baseUrl?` - Custom base URL (optional)

**Returns:** A Decart video adapter instance.

## Next Steps

- [Decart Platform](https://platform.decart.ai) - Visit Decart's platform to generate API keys
- [API Documentation](https://docs.platform.decart.ai) - View complete API reference
- [GitHub Repository](https://github.com/decartai/tanstack-ai) - Explore the adapter source code
- [Image Generation Guide](../guides/image-generation) - Learn about image generation
- [Video Generation Guide](../guides/video-generation) - Learn about video generation
4 changes: 4 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@
{
"label": "Community Adapters Guide",
"to": "community-adapters/guide"
},
{
"label": "Decart",
"to": "community-adapters/decart"
}
]
},
Expand Down