@yetter/client 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Yetter JS Client
|
|
2
|
+
|
|
3
|
+
The Yetter JS Client provides a convenient way to interact with the Yetter API for image generation. It supports different modes of operation: subscribing to real-time updates, submitting jobs to a queue, and streaming events.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @yetter/client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Authentication
|
|
12
|
+
|
|
13
|
+
The client requires a Yetter API key for authentication. Ensure you have the `YTR_API_KEY` environment variable set:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export YTR_API_KEY="your_api_key_here"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Core Functionalities
|
|
20
|
+
|
|
21
|
+
The client is available via the `yetter` object imported from `yetter-js` (or the relevant path to `client.js`/`client.ts` if used directly).
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { yetter } from "@yetter/client";
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 1. `yetter.subscribe()`
|
|
28
|
+
|
|
29
|
+
This function submits an image generation request and long-polls for the result. It provides updates on the queue status and logs if requested.
|
|
30
|
+
|
|
31
|
+
**Features:**
|
|
32
|
+
- Submits a generation request.
|
|
33
|
+
- Polls for status updates until the job is "COMPLETED" or "FAILED".
|
|
34
|
+
- Timeout after 30 minutes, with an attempt to cancel the job.
|
|
35
|
+
- Optional `onQueueUpdate` callback for real-time feedback on queue position and status.
|
|
36
|
+
- Optional `logs` flag to include logs in status updates.
|
|
37
|
+
|
|
38
|
+
**Example (from `examples/subscribe.ts`):**
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { yetter } from "@yetter/client";
|
|
42
|
+
|
|
43
|
+
async function main() {
|
|
44
|
+
const model = "ytr-ai/flux/dev"; // Replace with your desired model
|
|
45
|
+
try {
|
|
46
|
+
console.log("\n--- Starting Subscribe Test ---");
|
|
47
|
+
const result = await yetter.subscribe(model, {
|
|
48
|
+
input: {
|
|
49
|
+
prompt: "a vibrant coral reef, underwater photography",
|
|
50
|
+
},
|
|
51
|
+
logs: true,
|
|
52
|
+
onQueueUpdate: (update) => {
|
|
53
|
+
console.log(`[Queue Update] Status: ${update.status}, Position: ${update.queue_position}`);
|
|
54
|
+
if (update.status === "IN_PROGRESS" && update.logs) {
|
|
55
|
+
console.log("Logs:");
|
|
56
|
+
update.logs.map((log) => log.message).forEach(logMessage => console.log(` - ${logMessage}`));
|
|
57
|
+
} else if (update.status === "COMPLETED") {
|
|
58
|
+
console.log("Processing completed!");
|
|
59
|
+
} else if (update.status === "FAILED") {
|
|
60
|
+
console.error("Processing failed. Logs:", update.logs);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
console.log("\n--- Subscribe Test Result ---");
|
|
66
|
+
console.log("Results:", result); // Contains image data, prompt, etc.
|
|
67
|
+
|
|
68
|
+
} catch (err: any) {
|
|
69
|
+
console.error("\n--- Subscribe Test Failed ---");
|
|
70
|
+
console.error("Error during subscribe:", err.message || err);
|
|
71
|
+
// ... error handling ...
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
main();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. `yetter.stream()`
|
|
79
|
+
|
|
80
|
+
This function submits an image generation request and returns an async iterable stream of events using Server-Sent Events (SSE). This allows for real-time updates on the job's progress, status, and logs.
|
|
81
|
+
|
|
82
|
+
**Features:**
|
|
83
|
+
- Initiates a request and establishes an SSE connection.
|
|
84
|
+
- Provides an `AsyncIterator` (`Symbol.asyncIterator`) to loop through status events (`StreamEvent`).
|
|
85
|
+
- A `done()` method: Returns a Promise that resolves with the final `GetResponseResponse` when the job is "COMPLETED", or rejects if it "FAILED" or the stream is prematurely closed.
|
|
86
|
+
- A `cancel()` method: Closes the stream and attempts to cancel the underlying image generation request.
|
|
87
|
+
- A `getRequestId()` method: Returns the request ID for the stream.
|
|
88
|
+
|
|
89
|
+
**Events (`StreamEvent`):**
|
|
90
|
+
Each event pushed by the stream is an object typically including:
|
|
91
|
+
- `status`: Current status (e.g., "IN_QUEUE", "IN_PROGRESS", "COMPLETED", "FAILED").
|
|
92
|
+
- `queue_position`: Current position in the queue.
|
|
93
|
+
- `logs`: Array of log messages if any.
|
|
94
|
+
- Other model-specific data.
|
|
95
|
+
|
|
96
|
+
**Example (from `examples/stream.ts`):**
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { yetter } from "@yetter/client"; // Adjust path as needed
|
|
100
|
+
|
|
101
|
+
async function main() {
|
|
102
|
+
const model = "ytr-ai/flux/dev";
|
|
103
|
+
let streamRequestId = "";
|
|
104
|
+
try {
|
|
105
|
+
console.log("\n--- Starting Stream Test ---");
|
|
106
|
+
const streamInstance = await yetter.stream(model, {
|
|
107
|
+
input: {
|
|
108
|
+
prompt: "a bioluminescent forest at night, fantasy art",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
streamRequestId = streamInstance.getRequestId();
|
|
112
|
+
console.log(`Stream initiated for Request ID: ${streamRequestId}`);
|
|
113
|
+
|
|
114
|
+
// Iterate over stream events
|
|
115
|
+
for await (const event of streamInstance) {
|
|
116
|
+
console.log(`[STREAM EVENT - ${streamRequestId}] Status: ${event.status}, QPos: ${event.queue_position}`);
|
|
117
|
+
if (event.logs && event.logs.length > 0) {
|
|
118
|
+
console.log(` Logs for ${streamRequestId}:`);
|
|
119
|
+
event.logs.forEach(log => console.log(` - ${log.message}`));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
console.log(`Stream for ${streamRequestId} finished iterating events.`);
|
|
123
|
+
|
|
124
|
+
// Wait for the final result from the done() method
|
|
125
|
+
const result = await streamInstance.done();
|
|
126
|
+
console.log("\n--- Stream Test Final Result ---");
|
|
127
|
+
console.log("Generated Images:", result.images);
|
|
128
|
+
|
|
129
|
+
} catch (err: any) {
|
|
130
|
+
console.error(`\n--- Stream Test Failed (Request ID: ${streamRequestId || 'UNKNOWN'}) ---`);
|
|
131
|
+
console.error("Error during stream test:", err.message || err);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
main();
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 3. `yetter.queue`
|
|
139
|
+
|
|
140
|
+
This namespace provides methods for managing jobs in a queue-based workflow. This is useful if you want to submit a job and check its status or retrieve its result later, without maintaining a persistent connection.
|
|
141
|
+
|
|
142
|
+
#### `yetter.queue.submit(model, options)`
|
|
143
|
+
Submits a job to the queue.
|
|
144
|
+
|
|
145
|
+
- **`model`**: The model ID (e.g., `"ytr-ai/flux/dev"`).
|
|
146
|
+
- **`options.input`**: An object containing the input parameters for the model (e.g., `{ prompt: "your prompt" }`).
|
|
147
|
+
|
|
148
|
+
Returns a promise that resolves to an object containing `request_id`, `status`, and `queue_position`.
|
|
149
|
+
|
|
150
|
+
#### `yetter.queue.status(model, options)`
|
|
151
|
+
Checks the status of a previously submitted job.
|
|
152
|
+
|
|
153
|
+
- **`model`**: The model ID.
|
|
154
|
+
- **`options.requestId`**: The `request_id` obtained from `queue.submit()`.
|
|
155
|
+
|
|
156
|
+
Returns a promise that resolves to an object containing the status data and `requestId`.
|
|
157
|
+
|
|
158
|
+
#### `yetter.queue.result(model, options)`
|
|
159
|
+
Retrieves the result of a completed job.
|
|
160
|
+
|
|
161
|
+
- **`model`**: The model ID.
|
|
162
|
+
- **`options.requestId`**: The `request_id` of the completed job.
|
|
163
|
+
|
|
164
|
+
Returns a promise that resolves to an object containing the result data (e.g., images, prompt) and `requestId`.
|
|
165
|
+
|
|
166
|
+
**Example (from `examples/submit.ts`):**
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
import { yetter } from "@yetter/client";
|
|
170
|
+
|
|
171
|
+
async function main() {
|
|
172
|
+
const model = "ytr-ai/flux/dev";
|
|
173
|
+
try {
|
|
174
|
+
console.log("\n--- Starting Queue Submit Test ---");
|
|
175
|
+
const { request_id } = await yetter.queue.submit(model, {
|
|
176
|
+
input: {
|
|
177
|
+
prompt: "a fluffy white kitten playing with a yarn ball",
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
console.log("Request ID:", request_id);
|
|
181
|
+
|
|
182
|
+
if (request_id) {
|
|
183
|
+
console.log(`\n--- Polling for status of Request ID: ${request_id} ---`);
|
|
184
|
+
// Polling logic:
|
|
185
|
+
let success = false;
|
|
186
|
+
const startTime = Date.now();
|
|
187
|
+
const timeoutMilliseconds = 3 * 60 * 1000; // 3 minutes
|
|
188
|
+
const pollIntervalMilliseconds = 10 * 1000; // Poll every 10 seconds
|
|
189
|
+
|
|
190
|
+
while (Date.now() - startTime < timeoutMilliseconds) {
|
|
191
|
+
const statusResult = await yetter.queue.status(model, { requestId: request_id });
|
|
192
|
+
const currentStatus = statusResult.data.status;
|
|
193
|
+
console.log(`[${new Date().toLocaleTimeString()}] Status: ${currentStatus}, QPos: ${statusResult.data.queue_position}`);
|
|
194
|
+
|
|
195
|
+
if (currentStatus === "COMPLETED") {
|
|
196
|
+
const finalResult = await yetter.queue.result(model, { requestId: request_id });
|
|
197
|
+
console.log("\n--- Get Result Test Succeeded ---");
|
|
198
|
+
console.log("Image Data:", finalResult.data.images);
|
|
199
|
+
success = true;
|
|
200
|
+
break;
|
|
201
|
+
} else if (currentStatus === "FAILED") {
|
|
202
|
+
console.error(`Request ${request_id} FAILED. Logs:`, statusResult.data.logs);
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
await new Promise(resolve => setTimeout(resolve, pollIntervalMilliseconds));
|
|
206
|
+
}
|
|
207
|
+
if (!success) console.error(`Polling Timed Out or Failed for ${request_id}`);
|
|
208
|
+
}
|
|
209
|
+
} catch (err: any) {
|
|
210
|
+
console.error("\n--- Queue Submit Test Failed ---", err.message);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
main();
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Error Handling
|
|
218
|
+
|
|
219
|
+
The client functions generally throw errors for API issues, network problems, or failed generation requests. Ensure you wrap API calls in `try...catch` blocks to handle potential errors gracefully. Specific error messages or details (like logs for failed jobs) are often included in the thrown error object or the final status response.
|
|
220
|
+
The `stream()` function's `done()` promise will reject on failure or premature closure, and iterating the stream might also throw if connection errors occur.
|