thumbnailgpt 1.0.6 → 1.0.7
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/dist/client.js +1 -1
- package/dist/index.js +71 -25
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -17,7 +17,7 @@ export class ThumbnailGPTClient {
|
|
|
17
17
|
"Content-Type": "application/json",
|
|
18
18
|
Authorization: `Bearer ${this.apiKey}`,
|
|
19
19
|
Origin: this.apiUrl,
|
|
20
|
-
"User-Agent": "thumbnailgpt-cli/1.0.
|
|
20
|
+
"User-Agent": "thumbnailgpt-cli/1.0.7",
|
|
21
21
|
...options.headers,
|
|
22
22
|
};
|
|
23
23
|
const res = await fetch(url, { ...options, headers });
|
package/dist/index.js
CHANGED
|
@@ -4,11 +4,58 @@ import ora from "ora";
|
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
import { setApiKey, clearApiKey, setApiUrl } from "./config.js";
|
|
6
6
|
import { ThumbnailGPTClient } from "./client.js";
|
|
7
|
+
/**
|
|
8
|
+
* Safely handle errors in CLI commands without crashing libuv timers or exposing internal server details
|
|
9
|
+
*/
|
|
10
|
+
function handleError(err, spinner) {
|
|
11
|
+
if (spinner) {
|
|
12
|
+
try {
|
|
13
|
+
spinner.stop();
|
|
14
|
+
}
|
|
15
|
+
catch { }
|
|
16
|
+
}
|
|
17
|
+
const rawMsg = String(err?.message || err || "").trim();
|
|
18
|
+
const status = Number(err?.status || 0);
|
|
19
|
+
let friendlyMessage = rawMsg;
|
|
20
|
+
// Mask database, internal, or raw HTML errors
|
|
21
|
+
if (status === 401 ||
|
|
22
|
+
rawMsg.toLowerCase().includes("api key") ||
|
|
23
|
+
rawMsg.toLowerCase().includes("unauthorized") ||
|
|
24
|
+
rawMsg.toLowerCase().includes("revoked")) {
|
|
25
|
+
friendlyMessage = "Authentication failed: Invalid, expired, or revoked API key. Please run 'thumbnailgpt login' to update your key.";
|
|
26
|
+
}
|
|
27
|
+
else if (status === 403 || rawMsg.toLowerCase().includes("forbidden")) {
|
|
28
|
+
friendlyMessage = "Access restricted: You do not have permission to access this resource.";
|
|
29
|
+
}
|
|
30
|
+
else if (status === 429 ||
|
|
31
|
+
rawMsg.toLowerCase().includes("rate limit") ||
|
|
32
|
+
rawMsg.toLowerCase().includes("too many requests")) {
|
|
33
|
+
friendlyMessage = "Request rate limit reached. Please wait a moment before trying again.";
|
|
34
|
+
}
|
|
35
|
+
else if (status >= 500 ||
|
|
36
|
+
rawMsg.toLowerCase().includes("internal server error") ||
|
|
37
|
+
rawMsg.toLowerCase().includes("service unavailable")) {
|
|
38
|
+
friendlyMessage = "ThumbnailGPT services are temporarily busy. Please try again in a few moments.";
|
|
39
|
+
}
|
|
40
|
+
else if (rawMsg.includes("ECONNREFUSED") ||
|
|
41
|
+
rawMsg.includes("ENOTFOUND") ||
|
|
42
|
+
rawMsg.includes("fetch failed")) {
|
|
43
|
+
friendlyMessage = "Unable to connect to ThumbnailGPT. Please check your internet connection.";
|
|
44
|
+
}
|
|
45
|
+
else if (rawMsg.includes("<!DOCTYPE") ||
|
|
46
|
+
rawMsg.includes("<html") ||
|
|
47
|
+
rawMsg.includes("SQL") ||
|
|
48
|
+
rawMsg.includes("Postgres")) {
|
|
49
|
+
friendlyMessage = "An unexpected error occurred. Please try again or visit https://thumbnailgpt.com for status updates.";
|
|
50
|
+
}
|
|
51
|
+
console.error(pc.red(`\nError: ${friendlyMessage}\n`));
|
|
52
|
+
process.exitCode = 1;
|
|
53
|
+
}
|
|
7
54
|
const program = new Command();
|
|
8
55
|
program
|
|
9
56
|
.name("thumbnailgpt")
|
|
10
57
|
.description("Official CLI for ThumbnailGPT — Generate, iterate, and manage thumbnails from your terminal")
|
|
11
|
-
.version("1.0.
|
|
58
|
+
.version("1.0.7");
|
|
12
59
|
// 1. Auth Login
|
|
13
60
|
program
|
|
14
61
|
.command("login")
|
|
@@ -54,9 +101,10 @@ program
|
|
|
54
101
|
.command("whoami")
|
|
55
102
|
.description("Display your account and available credit balance")
|
|
56
103
|
.action(async () => {
|
|
104
|
+
let spinner = null;
|
|
57
105
|
try {
|
|
58
106
|
const client = new ThumbnailGPTClient();
|
|
59
|
-
|
|
107
|
+
spinner = ora("Fetching account details...").start();
|
|
60
108
|
const credits = await client.getCredits();
|
|
61
109
|
spinner.stop();
|
|
62
110
|
console.log(pc.bold("\nThumbnailGPT Account"));
|
|
@@ -65,8 +113,7 @@ program
|
|
|
65
113
|
console.log(`${pc.gray("Cost Tiers:")} 1K = 10 cr | 2K = 20 cr | 4K = 30 cr\n`);
|
|
66
114
|
}
|
|
67
115
|
catch (err) {
|
|
68
|
-
|
|
69
|
-
process.exit(1);
|
|
116
|
+
handleError(err, spinner);
|
|
70
117
|
}
|
|
71
118
|
});
|
|
72
119
|
// 4. One-shot Generate
|
|
@@ -83,6 +130,7 @@ program
|
|
|
83
130
|
.option("--json", "Output response as raw JSON")
|
|
84
131
|
.option("--async", "Dispatch job and return immediately without waiting")
|
|
85
132
|
.action(async (prompt, options) => {
|
|
133
|
+
let spinner = null;
|
|
86
134
|
try {
|
|
87
135
|
if (options.ref && options.ref.length > 5) {
|
|
88
136
|
console.error(pc.red("\nError: A maximum of 5 reference images is allowed."));
|
|
@@ -100,7 +148,7 @@ program
|
|
|
100
148
|
}
|
|
101
149
|
const client = new ThumbnailGPTClient();
|
|
102
150
|
if (options.async) {
|
|
103
|
-
|
|
151
|
+
spinner = !options.json && !options.urlOnly ? ora("Dispatching to ThumbnailGPT...").start() : null;
|
|
104
152
|
const dispatch = await client.dispatchStudio({
|
|
105
153
|
prompt,
|
|
106
154
|
chatId: options.chat,
|
|
@@ -121,7 +169,7 @@ program
|
|
|
121
169
|
console.log(`Check status with: ${pc.cyan(`thumbnailgpt chats show ${dispatch.chatId}`)}\n`);
|
|
122
170
|
return;
|
|
123
171
|
}
|
|
124
|
-
|
|
172
|
+
spinner = !options.json && !options.urlOnly ? ora("Validating credits & dispatching...").start() : null;
|
|
125
173
|
const result = await client.generateAndWait({
|
|
126
174
|
prompt,
|
|
127
175
|
chatId: options.chat,
|
|
@@ -167,8 +215,7 @@ program
|
|
|
167
215
|
console.log(`${pc.bold("Web App:")} https://thumbnailgpt.com/studio/${result.chatId}\n`);
|
|
168
216
|
}
|
|
169
217
|
catch (err) {
|
|
170
|
-
|
|
171
|
-
process.exit(1);
|
|
218
|
+
handleError(err, spinner);
|
|
172
219
|
}
|
|
173
220
|
});
|
|
174
221
|
// 5. Interactive Chat REPL
|
|
@@ -230,8 +277,7 @@ program
|
|
|
230
277
|
askPrompt();
|
|
231
278
|
}
|
|
232
279
|
catch (err) {
|
|
233
|
-
|
|
234
|
-
process.exit(1);
|
|
280
|
+
handleError(err);
|
|
235
281
|
}
|
|
236
282
|
});
|
|
237
283
|
// 6. Chats Subcommand
|
|
@@ -240,9 +286,10 @@ chats
|
|
|
240
286
|
.command("list")
|
|
241
287
|
.description("List recent chat conversations")
|
|
242
288
|
.action(async () => {
|
|
289
|
+
let spinner = null;
|
|
243
290
|
try {
|
|
244
291
|
const client = new ThumbnailGPTClient();
|
|
245
|
-
|
|
292
|
+
spinner = ora("Fetching conversations...").start();
|
|
246
293
|
const res = await client.listChats();
|
|
247
294
|
spinner.stop();
|
|
248
295
|
const chatList = res.chats || [];
|
|
@@ -258,17 +305,17 @@ chats
|
|
|
258
305
|
console.log();
|
|
259
306
|
}
|
|
260
307
|
catch (err) {
|
|
261
|
-
|
|
262
|
-
process.exit(1);
|
|
308
|
+
handleError(err, spinner);
|
|
263
309
|
}
|
|
264
310
|
});
|
|
265
311
|
chats
|
|
266
312
|
.command("show <chatId>")
|
|
267
313
|
.description("View conversation history and thumbnails")
|
|
268
314
|
.action(async (chatId) => {
|
|
315
|
+
let spinner = null;
|
|
269
316
|
try {
|
|
270
317
|
const client = new ThumbnailGPTClient();
|
|
271
|
-
|
|
318
|
+
spinner = ora("Fetching thread...").start();
|
|
272
319
|
const res = await client.getChat(chatId);
|
|
273
320
|
spinner.stop();
|
|
274
321
|
console.log(pc.bold(`\nThread: ${res.chat?.title || chatId}\n`));
|
|
@@ -285,8 +332,7 @@ chats
|
|
|
285
332
|
console.log();
|
|
286
333
|
}
|
|
287
334
|
catch (err) {
|
|
288
|
-
|
|
289
|
-
process.exit(1);
|
|
335
|
+
handleError(err, spinner);
|
|
290
336
|
}
|
|
291
337
|
});
|
|
292
338
|
chats
|
|
@@ -304,9 +350,10 @@ thumbnailsCmd
|
|
|
304
350
|
.command("get <thumbnailId>")
|
|
305
351
|
.description("Get detailed information about a thumbnail by ID")
|
|
306
352
|
.action(async (thumbnailId) => {
|
|
353
|
+
let spinner = null;
|
|
307
354
|
try {
|
|
308
355
|
const client = new ThumbnailGPTClient();
|
|
309
|
-
|
|
356
|
+
spinner = ora("Fetching thumbnail details...").start();
|
|
310
357
|
const thumb = await client.getThumbnail(thumbnailId);
|
|
311
358
|
spinner.stop();
|
|
312
359
|
console.log(pc.bold("\nThumbnail Details:"));
|
|
@@ -329,8 +376,7 @@ thumbnailsCmd
|
|
|
329
376
|
console.log(pc.dim("--------------------------------------------------------------------------------\n"));
|
|
330
377
|
}
|
|
331
378
|
catch (err) {
|
|
332
|
-
|
|
333
|
-
process.exit(1);
|
|
379
|
+
handleError(err, spinner);
|
|
334
380
|
}
|
|
335
381
|
});
|
|
336
382
|
thumbnailsCmd
|
|
@@ -342,13 +388,13 @@ thumbnailsCmd
|
|
|
342
388
|
const thumb = await client.getThumbnail(thumbnailId);
|
|
343
389
|
if (!thumb.thumbnail_url) {
|
|
344
390
|
console.error(pc.yellow(`Thumbnail is not ready yet (status: ${thumb.status || "processing"})`));
|
|
345
|
-
process.
|
|
391
|
+
process.exitCode = 1;
|
|
392
|
+
return;
|
|
346
393
|
}
|
|
347
394
|
console.log(thumb.thumbnail_url);
|
|
348
395
|
}
|
|
349
396
|
catch (err) {
|
|
350
|
-
|
|
351
|
-
process.exit(1);
|
|
397
|
+
handleError(err);
|
|
352
398
|
}
|
|
353
399
|
});
|
|
354
400
|
thumbnailsCmd
|
|
@@ -366,9 +412,10 @@ personasCmd
|
|
|
366
412
|
.command("list")
|
|
367
413
|
.description("List your active creator personas (only ready personas are shown)")
|
|
368
414
|
.action(async () => {
|
|
415
|
+
let spinner = null;
|
|
369
416
|
try {
|
|
370
417
|
const client = new ThumbnailGPTClient();
|
|
371
|
-
|
|
418
|
+
spinner = ora("Fetching active personas...").start();
|
|
372
419
|
const personas = await client.getPersonas();
|
|
373
420
|
spinner.stop();
|
|
374
421
|
if (personas.length === 0) {
|
|
@@ -386,8 +433,7 @@ personasCmd
|
|
|
386
433
|
console.log(`Use in generation: ${pc.green('npx thumbnailgpt generate "..." --persona <id>')}\n`);
|
|
387
434
|
}
|
|
388
435
|
catch (err) {
|
|
389
|
-
|
|
390
|
-
process.exit(1);
|
|
436
|
+
handleError(err, spinner);
|
|
391
437
|
}
|
|
392
438
|
});
|
|
393
439
|
personasCmd
|
package/package.json
CHANGED