dreamlayer 0.4.0-beta.2 → 0.4.0-beta.3
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 +4 -0
- package/dist/cli.js +19 -16
- package/dist/client.js +10 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -167,3 +167,7 @@ retry the indicated recovery action, never blindly repeat a paid command.
|
|
|
167
167
|
use `authentication_failed` (exit 2). A cancelled run uses `execution_cancelled`, exit 4,
|
|
168
168
|
and a JSON error on stderr. Unknown client failures use `client_error`; they do not
|
|
169
169
|
prove that the server-side generation failed.
|
|
170
|
+
|
|
171
|
+
## Error handling updates in beta.3
|
|
172
|
+
|
|
173
|
+
Transport failures include a safe connection category without exposing URLs or credentials. Cancelled executions recommend a status check; download authentication failures retain exit code 2. Help flags are parsed as options so a literal `-h` option value is preserved.
|
package/dist/cli.js
CHANGED
|
@@ -102,7 +102,9 @@ async function downloadOutput(api, url) {
|
|
|
102
102
|
try {
|
|
103
103
|
return await api.download(url);
|
|
104
104
|
}
|
|
105
|
-
catch {
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (error instanceof ApiError && [401, 403].includes(error.status))
|
|
107
|
+
throw error;
|
|
106
108
|
throw new CommandError("download_failed", "The completed output could not be downloaded.", 5, true, "Retry dreamlayer download with the saved execution_id. Do not generate again.");
|
|
107
109
|
}
|
|
108
110
|
}
|
|
@@ -116,11 +118,14 @@ function parseOptions(argv) {
|
|
|
116
118
|
aspect: "1:1",
|
|
117
119
|
json: false,
|
|
118
120
|
quiet: false,
|
|
121
|
+
help: false,
|
|
119
122
|
idempotencyKey: null,
|
|
120
123
|
};
|
|
121
124
|
for (let i = 0; i < argv.length; i += 1) {
|
|
122
125
|
const token = argv[i];
|
|
123
|
-
if (token === "--
|
|
126
|
+
if (token === "--help" || token === "-h")
|
|
127
|
+
options.help = true;
|
|
128
|
+
else if (token === "--json")
|
|
124
129
|
options.json = true;
|
|
125
130
|
else if (token === "--quiet")
|
|
126
131
|
options.quiet = true;
|
|
@@ -317,15 +322,15 @@ async function main(argv) {
|
|
|
317
322
|
process.stdout.write(USAGE);
|
|
318
323
|
return command ? 0 : 1;
|
|
319
324
|
}
|
|
320
|
-
if (rest.includes("--help") || rest.includes("-h")) {
|
|
321
|
-
process.stdout.write(USAGE);
|
|
322
|
-
return 0;
|
|
323
|
-
}
|
|
324
325
|
if (command === "--version" || command === "-v") {
|
|
325
326
|
process.stdout.write(`${PACKAGE_VERSION}\n`);
|
|
326
327
|
return 0;
|
|
327
328
|
}
|
|
328
329
|
const { positional, options } = parseOptions(rest);
|
|
330
|
+
if (options.help) {
|
|
331
|
+
process.stdout.write(USAGE);
|
|
332
|
+
return 0;
|
|
333
|
+
}
|
|
329
334
|
if (["generate", "edit", "cutout", "upscale", "sprite", "answer"].includes(command)) {
|
|
330
335
|
options.out ??= command === "sprite" ? `dreamlayer-${Date.now()}.zip` : defaultOut();
|
|
331
336
|
await preflightOutput(options.out);
|
|
@@ -441,7 +446,7 @@ main(process.argv.slice(2))
|
|
|
441
446
|
const known = error instanceof CommandError ? error : error instanceof InputValidationError
|
|
442
447
|
? new CommandError("invalid_request", error.message, 1)
|
|
443
448
|
: error instanceof RecoveryRequiredError
|
|
444
|
-
? new CommandError("temporarily_unavailable",
|
|
449
|
+
? new CommandError("temporarily_unavailable", error.message, 5, true, "Use status and download for the saved execution. If no ID was received, replay identical inputs with the original idempotency key.") : null;
|
|
445
450
|
if (known) {
|
|
446
451
|
const partial = error.partialOutcome;
|
|
447
452
|
const identity = { ...recovery, ...(partial?.execution_id ? { execution_id: partial.execution_id } : {}) };
|
|
@@ -449,9 +454,12 @@ main(process.argv.slice(2))
|
|
|
449
454
|
if (process.argv.slice(2).includes("--json"))
|
|
450
455
|
process.stderr.write(`${JSON.stringify(envelope)}\n`);
|
|
451
456
|
else {
|
|
452
|
-
process.stderr.write(`${known.message}\n${known.guidance
|
|
453
|
-
if (identity.execution_id)
|
|
454
|
-
process.stderr.write(`Execution: ${identity.execution_id}\n dreamlayer status ${identity.execution_id}\n
|
|
457
|
+
process.stderr.write(`${known.message}\n${known.guidance ? known.guidance + "\n" : ""}`);
|
|
458
|
+
if (identity.execution_id) {
|
|
459
|
+
process.stderr.write(`Execution: ${identity.execution_id}\n dreamlayer status ${identity.execution_id}\n`);
|
|
460
|
+
if (["local_output_failed", "download_failed"].includes(known.reason))
|
|
461
|
+
process.stderr.write(` dreamlayer download ${identity.execution_id} --out <new-file>\n`);
|
|
462
|
+
}
|
|
455
463
|
if (identity.idempotency_key)
|
|
456
464
|
process.stderr.write(`Idempotency key: ${identity.idempotency_key}\n`);
|
|
457
465
|
}
|
|
@@ -482,12 +490,7 @@ main(process.argv.slice(2))
|
|
|
482
490
|
: error.retryable
|
|
483
491
|
? "Temporary. Retry with --idempotency-key to avoid paying twice."
|
|
484
492
|
: "";
|
|
485
|
-
|
|
486
|
-
process.stderr.write(`${JSON.stringify(error.toPublicEnvelope())}\n`);
|
|
487
|
-
}
|
|
488
|
-
else {
|
|
489
|
-
process.stderr.write(`${error.message}\nReason: ${error.reason}${hint ? `\n${hint}` : ""}\n`);
|
|
490
|
-
}
|
|
493
|
+
process.stderr.write(`${error.message}\nReason: ${error.reason}${hint ? `\n${hint}` : ""}\n`);
|
|
491
494
|
process.exitCode = exitCodeFor(error);
|
|
492
495
|
return;
|
|
493
496
|
}
|
package/dist/client.js
CHANGED
|
@@ -491,8 +491,16 @@ export class ManagedClient {
|
|
|
491
491
|
throw error;
|
|
492
492
|
if (!executionId && error instanceof ApiError)
|
|
493
493
|
throw error;
|
|
494
|
-
if (!executionId || ++failures > 5)
|
|
495
|
-
|
|
494
|
+
if (!executionId || ++failures > 5) {
|
|
495
|
+
const code = error?.cause?.code ?? error?.code;
|
|
496
|
+
const causes = {
|
|
497
|
+
ECONNREFUSED: "Connection refused", ENOTFOUND: "Host lookup failed", EAI_AGAIN: "Host lookup temporarily failed",
|
|
498
|
+
ECONNRESET: "Connection reset", ETIMEDOUT: "Connection timed out", UND_ERR_CONNECT_TIMEOUT: "Connection timed out",
|
|
499
|
+
UND_ERR_SOCKET: "Connection closed", CERT_HAS_EXPIRED: "TLS certificate expired", DEPTH_ZERO_SELF_SIGNED_CERT: "TLS certificate is untrusted",
|
|
500
|
+
};
|
|
501
|
+
const cause = code && causes[code] ? `${causes[code]} (${code}). ` : "Transport connection failed. ";
|
|
502
|
+
throw new RecoveryRequiredError(cause + "Execution state is uncertain. Read saved state before retrying.");
|
|
503
|
+
}
|
|
496
504
|
}
|
|
497
505
|
if (!executionId)
|
|
498
506
|
throw new RecoveryRequiredError("Execution stream ended before an identifier was received; reuse your idempotency key.");
|