@yetter/client 0.0.10 → 0.0.12

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 CHANGED
@@ -44,7 +44,7 @@ This function submits an image generation request and long-polls for the result.
44
44
 
45
45
  **Features:**
46
46
  - Submits a generation request.
47
- - Polls for status updates until the job is "COMPLETED" or "FAILED".
47
+ - Polls for status updates until the job is "COMPLETED" or "ERROR".
48
48
  - Timeout after 30 minutes, with an attempt to cancel the job.
49
49
  - Optional `onQueueUpdate` callback for real-time feedback on queue position and status.
50
50
  - Optional `logs` flag to include logs in status updates.
@@ -71,7 +71,7 @@ async function main() {
71
71
  update.logs.map((log) => log.message).forEach(logMessage => console.log(` - ${logMessage}`));
72
72
  } else if (update.status === "COMPLETED") {
73
73
  console.log("Processing completed!");
74
- } else if (update.status === "FAILED") {
74
+ } else if (update.status === "ERROR") {
75
75
  console.error("Processing failed. Logs:", update.logs);
76
76
  }
77
77
  },
@@ -95,18 +95,18 @@ main();
95
95
  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.
96
96
 
97
97
  **Features:**
98
- - Initiates a request and establishes an SSE connection.
99
- - Provides an `AsyncIterator` (`Symbol.asyncIterator`) to loop through status events (`StreamEvent`).
100
- - 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.
101
- - A `cancel()` method: Closes the stream and attempts to cancel the underlying image generation request.
102
- - A `getRequestId()` method: Returns the request ID for the stream.
98
+
99
+ * Initiates a request and establishes an SSE connection.
100
+ * Provides an `AsyncIterator` (`Symbol.asyncIterator`) to loop through status events (`StreamEvent`).
101
+ * A `done()` method: Returns a Promise that resolves with the final `GetResponseResponse` **after the server emits `event: done`** (successful completion), or rejects if the server emits `event: error` or the final response cannot be fetched.
102
+ * A `cancel()` method: Requests cancellation on the backend; the stream naturally ends when the server emits `data` (with `status: "CANCELLED"`) followed by `event: done`.
103
+ * A `getRequestId()` method: Returns the request ID for the stream.
103
104
 
104
105
  **Events (`StreamEvent`):**
105
106
  Each event pushed by the stream is an object typically including:
106
- - `status`: Current status (e.g., "IN_QUEUE", "IN_PROGRESS", "COMPLETED", "FAILED").
107
- - `queue_position`: Current position in the queue.
108
- - `logs`: Array of log messages if any.
109
- - Other model-specific data.
107
+
108
+ * `status`: Current status (e.g., `"IN_QUEUE"`, `"IN_PROGRESS"`, `"COMPLETED"`, `"CANCELLED"`, `"ERROR"`).
109
+ * Other model-specific data.
110
110
 
111
111
  **Example (from `examples/stream.ts`):**
112
112
 
@@ -127,9 +127,11 @@ async function main() {
127
127
  streamRequestId = streamInstance.getRequestId();
128
128
  console.log(`Stream initiated for Request ID: ${streamRequestId}`);
129
129
 
130
- // Iterate over stream events
130
+ // Iterate over stream events (informational; termination is driven by server 'done'/'error' events)
131
131
  for await (const event of streamInstance) {
132
- console.log(`[STREAM EVENT - ${streamRequestId}] Status: ${event.status}, QPos: ${event.queue_position}`);
132
+ console.log(
133
+ `[STREAM EVENT - ${streamRequestId}] Status: ${event.status}, QPos: ${event.queue_position}`
134
+ );
133
135
  if (event.logs && event.logs.length > 0) {
134
136
  console.log(` Logs for ${streamRequestId}:`);
135
137
  event.logs.forEach(log => console.log(` - ${log.message}`));
@@ -137,7 +139,7 @@ async function main() {
137
139
  }
138
140
  console.log(`Stream for ${streamRequestId} finished iterating events.`);
139
141
 
140
- // Wait for the final result from the done() method
142
+ // Final result becomes available after server emits `event: done`
141
143
  const result = await streamInstance.done();
142
144
  console.log("\n--- Stream Test Final Result ---");
143
145
  console.log("Generated Images:", result.images);
@@ -215,7 +217,7 @@ async function main() {
215
217
  console.log("Image Data:", finalResult.data.images);
216
218
  success = true;
217
219
  break;
218
- } else if (currentStatus === "FAILED") {
220
+ } else if (currentStatus === "ERROR") {
219
221
  console.error(`Request ${request_id} FAILED. Logs:`, statusResult.data.logs);
220
222
  break;
221
223
  }
@@ -231,6 +233,59 @@ async function main() {
231
233
  main();
232
234
  ```
233
235
 
236
+ ### 4. Uploading Input Images
237
+
238
+ For models that require an input image (e.g., image-to-image, style transfer), you can upload your image using `yetter.uploadFile()` (Node.js) or `yetter.uploadBlob()` (browser).
239
+
240
+ **Features:**
241
+ - Support for both Node.js filesystem paths and browser File/Blob objects
242
+ - Automatic single-part or multipart upload based on file size
243
+ - Progress tracking with optional callback
244
+ - Returns a public URL to use in generation requests
245
+
246
+ #### Node.js Example
247
+
248
+ ```typescript
249
+ import { yetter } from "@yetter/client";
250
+
251
+ yetter.configure({ apiKey: process.env.YTR_API_KEY });
252
+
253
+ // Upload image
254
+ const uploadResult = await yetter.uploadFile("./input-image.jpg", {
255
+ onProgress: (percent) => console.log(`Upload: ${percent}%`),
256
+ });
257
+
258
+ // Use in generation
259
+ const result = await yetter.subscribe("ytr-ai/model/i2i", {
260
+ input: {
261
+ prompt: "Transform to anime style",
262
+ input_image_url: uploadResult.url,
263
+ },
264
+ });
265
+ ```
266
+
267
+ #### Browser Example
268
+
269
+ ```typescript
270
+ // HTML: <input type="file" id="imageInput" accept="image/*">
271
+
272
+ const fileInput = document.getElementById('imageInput') as HTMLInputElement;
273
+ fileInput.addEventListener('change', async () => {
274
+ const file = fileInput.files![0];
275
+
276
+ const uploadResult = await yetter.uploadBlob(file, {
277
+ onProgress: (pct) => updateProgressBar(pct),
278
+ });
279
+
280
+ console.log("Uploaded:", uploadResult.url);
281
+ });
282
+ ```
283
+
284
+ **Upload Options:**
285
+ - `onProgress?: (progress: number) => void` - Progress callback (0-100)
286
+ - `timeout?: number` - Timeout in milliseconds (default: 5 minutes)
287
+ - `filename?: string` - Custom filename (browser uploads)
288
+
234
289
  ## Error Handling
235
290
 
236
291
  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.
package/bowow2.jpeg ADDED
Binary file
package/dist/api.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ClientOptions, GenerateRequest, GenerateResponse, GetStatusRequest, GetStatusResponse, CancelRequest, CancelResponse, GetResponseRequest, GetResponseResponse } from "./types";
1
+ import { ClientOptions, GenerateRequest, GenerateResponse, GetStatusRequest, GetStatusResponse, CancelRequest, CancelResponse, GetResponseRequest, GetResponseResponse, GetUploadUrlRequest, GetUploadUrlResponse, UploadCompleteRequest, UploadCompleteResponse } from "./types";
2
2
  export declare class YetterImageClient {
3
3
  private apiKey;
4
4
  private endpoint;
@@ -8,4 +8,16 @@ export declare class YetterImageClient {
8
8
  getStatus(body: GetStatusRequest): Promise<GetStatusResponse>;
9
9
  cancel(body: CancelRequest): Promise<CancelResponse>;
10
10
  getResponse(body: GetResponseRequest): Promise<GetResponseResponse>;
11
+ /**
12
+ * Request presigned URL(s) for file upload
13
+ * @param body Upload request parameters
14
+ * @returns Presigned URL response with mode (single/multipart)
15
+ */
16
+ getUploadUrl(body: GetUploadUrlRequest): Promise<GetUploadUrlResponse>;
17
+ /**
18
+ * Notify server that upload is complete
19
+ * @param body Completion request with S3 key
20
+ * @returns Uploaded file metadata with public URL
21
+ */
22
+ uploadComplete(body: UploadCompleteRequest): Promise<UploadCompleteResponse>;
11
23
  }
package/dist/api.js CHANGED
@@ -72,4 +72,44 @@ export class YetterImageClient {
72
72
  }
73
73
  return (await res.json());
74
74
  }
75
+ /**
76
+ * Request presigned URL(s) for file upload
77
+ * @param body Upload request parameters
78
+ * @returns Presigned URL response with mode (single/multipart)
79
+ */
80
+ async getUploadUrl(body) {
81
+ const res = await fetch(`${this.endpoint}/uploads`, {
82
+ method: "POST",
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ Authorization: this.apiKey,
86
+ },
87
+ body: JSON.stringify(body),
88
+ });
89
+ if (!res.ok) {
90
+ const errorText = await res.text();
91
+ throw new Error(`Upload URL request failed (${res.status}): ${errorText}`);
92
+ }
93
+ return (await res.json());
94
+ }
95
+ /**
96
+ * Notify server that upload is complete
97
+ * @param body Completion request with S3 key
98
+ * @returns Uploaded file metadata with public URL
99
+ */
100
+ async uploadComplete(body) {
101
+ const res = await fetch(`${this.endpoint}/uploads/complete`, {
102
+ method: "POST",
103
+ headers: {
104
+ "Content-Type": "application/json",
105
+ Authorization: this.apiKey,
106
+ },
107
+ body: JSON.stringify(body),
108
+ });
109
+ if (!res.ok) {
110
+ const errorText = await res.text();
111
+ throw new Error(`Upload completion failed (${res.status}): ${errorText}`);
112
+ }
113
+ return (await res.json());
114
+ }
75
115
  }
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ClientOptions, GetResponseResponse, SubscribeOptions, GenerateResponse, SubmitQueueOptions, GetResultOptions, GetResultResponse, StatusOptions, StatusResponse, StreamOptions, YetterStream } from "./types.js";
1
+ import { ClientOptions, GetResponseResponse, SubscribeOptions, GenerateResponse, SubmitQueueOptions, GetResultOptions, GetResultResponse, StatusOptions, StatusResponse, StreamOptions, YetterStream, UploadOptions, UploadCompleteResponse } from "./types.js";
2
2
  export declare class yetter {
3
3
  private static apiKey;
4
4
  private static endpoint;
@@ -10,4 +10,56 @@ export declare class yetter {
10
10
  result: (model: string, options: GetResultOptions) => Promise<GetResultResponse>;
11
11
  };
12
12
  static stream(model: string, options: StreamOptions): Promise<YetterStream>;
13
+ /**
14
+ * Upload a file from the filesystem (Node.js) or File/Blob object (browser)
15
+ *
16
+ * @param fileOrPath File path (Node.js) or File/Blob object (browser)
17
+ * @param options Upload configuration options
18
+ * @returns Promise resolving to upload result with public URL
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * // Node.js
23
+ * const result = await yetter.uploadFile("/path/to/image.jpg", {
24
+ * onProgress: (pct) => console.log(`Upload: ${pct}%`)
25
+ * });
26
+ *
27
+ * // Browser
28
+ * const fileInput = document.querySelector('input[type="file"]');
29
+ * const file = fileInput.files[0];
30
+ * const result = await yetter.uploadFile(file, {
31
+ * onProgress: (pct) => updateProgressBar(pct)
32
+ * });
33
+ * ```
34
+ */
35
+ static uploadFile(fileOrPath: string | File | Blob, options?: UploadOptions): Promise<UploadCompleteResponse>;
36
+ /**
37
+ * Upload a file from browser (File or Blob object)
38
+ * This is an alias for uploadFile for better clarity in browser contexts
39
+ */
40
+ static uploadBlob(file: File | Blob, options?: UploadOptions): Promise<UploadCompleteResponse>;
41
+ /**
42
+ * Upload file from filesystem path (Node.js only)
43
+ */
44
+ private static _uploadFromPath;
45
+ /**
46
+ * Upload file from Blob/File object (browser)
47
+ */
48
+ private static _uploadFromBlob;
49
+ /**
50
+ * Upload file using single PUT request (Node.js, private helper)
51
+ */
52
+ private static _uploadFileSingle;
53
+ /**
54
+ * Upload file using multipart upload (Node.js, private helper)
55
+ */
56
+ private static _uploadFileMultipart;
57
+ /**
58
+ * Upload blob using single PUT request (browser, private helper)
59
+ */
60
+ private static _uploadBlobSingle;
61
+ /**
62
+ * Upload blob using multipart upload (browser, private helper)
63
+ */
64
+ private static _uploadBlobMultipart;
13
65
  }