@skrr-ai/cli 0.1.29 → 0.1.31
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.
|
@@ -63,3 +63,5 @@ export declare abstract class DedicatedLeaseCommand extends BaseCommand {
|
|
|
63
63
|
workspace?: string;
|
|
64
64
|
}, goal: DedicatedWaitGoal | null, verb: string): Promise<void>;
|
|
65
65
|
}
|
|
66
|
+
/** The same transient verdict BaseCommand gives an ordinary API call. */
|
|
67
|
+
export declare function dedicatedRuntimeApiErrorRetryable(err: unknown): boolean;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DedicatedLeaseCommand = exports.DEDICATED_LEASE_ARG_DESCRIPTION = exports.DEDICATED_SELF_LEASE = exports.dedicatedWaitFlags = void 0;
|
|
4
|
+
exports.dedicatedRuntimeApiErrorRetryable = dedicatedRuntimeApiErrorRetryable;
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const base_command_1 = require("../base-command");
|
|
7
|
+
const api_fetch_1 = require("./api-fetch");
|
|
6
8
|
const dedicated_machines_1 = require("./dedicated-machines");
|
|
7
9
|
const dedicated_terminal_1 = require("./dedicated-terminal");
|
|
8
10
|
const daemonBroker_1 = require("./daemonBroker");
|
|
@@ -176,8 +178,23 @@ class DedicatedLeaseCommand extends base_command_1.BaseCommand {
|
|
|
176
178
|
this.error(err.message, { exit: 1 });
|
|
177
179
|
}
|
|
178
180
|
const message = (0, dedicated_machines_1.formatDedicatedRuntimeApiError)(err);
|
|
179
|
-
if (message)
|
|
180
|
-
|
|
181
|
+
if (message) {
|
|
182
|
+
const retryable = dedicatedRuntimeApiErrorRetryable(err);
|
|
183
|
+
this.failWithCliError({
|
|
184
|
+
message: retryable
|
|
185
|
+
? `Stopped waiting for ${id}; nothing was cancelled and the operation continues server-side. Check it with \`${this.config.bin} machines dedicated show ${id}\`. The status poll failed: ${message}`
|
|
186
|
+
: message,
|
|
187
|
+
code: (0, dedicated_machines_1.dedicatedRuntimeApiErrorCode)(err) ?? 'CLI_ERROR',
|
|
188
|
+
status: err instanceof api_fetch_1.ApiFetchError ? err.status : undefined,
|
|
189
|
+
exit: 1,
|
|
190
|
+
retryable,
|
|
191
|
+
details: {
|
|
192
|
+
...(0, dedicated_machines_1.dedicatedRuntimeApiErrorDetails)(err),
|
|
193
|
+
leaseId: id,
|
|
194
|
+
operationContinues: true,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
}
|
|
181
198
|
this.handleApiError(err);
|
|
182
199
|
}
|
|
183
200
|
}
|
|
@@ -192,3 +209,19 @@ class DedicatedLeaseCommand extends base_command_1.BaseCommand {
|
|
|
192
209
|
}
|
|
193
210
|
}
|
|
194
211
|
exports.DedicatedLeaseCommand = DedicatedLeaseCommand;
|
|
212
|
+
/** The same transient verdict BaseCommand gives an ordinary API call. */
|
|
213
|
+
function dedicatedRuntimeApiErrorRetryable(err) {
|
|
214
|
+
if (!(err instanceof api_fetch_1.ApiFetchError))
|
|
215
|
+
return false;
|
|
216
|
+
let body = null;
|
|
217
|
+
try {
|
|
218
|
+
const parsed = JSON.parse(err.body || '');
|
|
219
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
220
|
+
body = parsed;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch {
|
|
224
|
+
// The HTTP status remains authoritative for an unparseable edge response.
|
|
225
|
+
}
|
|
226
|
+
return (0, base_command_1.isRetryableFailure)(err.status, body);
|
|
227
|
+
}
|
|
@@ -71,6 +71,7 @@ export declare const DEDICATED_WAIT_TIMEOUT_EXIT = 124;
|
|
|
71
71
|
export declare const DEDICATED_WAIT_DEFAULT_TIMEOUT_MS: number;
|
|
72
72
|
export declare const DEDICATED_WAIT_DEFAULT_INTERVAL_MS: number;
|
|
73
73
|
export declare const DEDICATED_WAIT_MAX_READ_FAILURES = 3;
|
|
74
|
+
export declare const DEDICATED_WAIT_MAX_RATE_LIMIT_FAILURES = 6;
|
|
74
75
|
export declare function waitForDedicatedLease(leaseId: string, goal: DedicatedWaitGoal, options?: DedicatedRuntimeScope & {
|
|
75
76
|
initial?: DedicatedLease;
|
|
76
77
|
intervalMs?: number;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEDICATED_WAIT_MAX_READ_FAILURES = exports.DEDICATED_WAIT_DEFAULT_INTERVAL_MS = exports.DEDICATED_WAIT_DEFAULT_TIMEOUT_MS = exports.DEDICATED_WAIT_TIMEOUT_EXIT = exports.DedicatedWaitFailedError = exports.DedicatedWaitTimeoutError = void 0;
|
|
3
|
+
exports.DEDICATED_WAIT_MAX_RATE_LIMIT_FAILURES = exports.DEDICATED_WAIT_MAX_READ_FAILURES = exports.DEDICATED_WAIT_DEFAULT_INTERVAL_MS = exports.DEDICATED_WAIT_DEFAULT_TIMEOUT_MS = exports.DEDICATED_WAIT_TIMEOUT_EXIT = exports.DedicatedWaitFailedError = exports.DedicatedWaitTimeoutError = void 0;
|
|
4
4
|
exports.evaluateDedicatedWait = evaluateDedicatedWait;
|
|
5
5
|
exports.waitForDedicatedLease = waitForDedicatedLease;
|
|
6
6
|
const dedicated_machines_1 = require("./dedicated-machines");
|
|
7
|
+
const api_fetch_1 = require("./api-fetch");
|
|
7
8
|
const RUNNING_STATES = new Set(['ready', 'active', 'idle']);
|
|
8
9
|
/** Terminal for the lease itself, so no goal but `destroyed` can still be reached. */
|
|
9
10
|
const DEAD_STATES = new Set(['failed', 'lost', 'terminated']);
|
|
@@ -194,6 +195,15 @@ exports.DEDICATED_WAIT_TIMEOUT_EXIT = 124;
|
|
|
194
195
|
exports.DEDICATED_WAIT_DEFAULT_TIMEOUT_MS = 15 * 60 * 1000;
|
|
195
196
|
exports.DEDICATED_WAIT_DEFAULT_INTERVAL_MS = 5 * 1000;
|
|
196
197
|
exports.DEDICATED_WAIT_MAX_READ_FAILURES = 3;
|
|
198
|
+
exports.DEDICATED_WAIT_MAX_RATE_LIMIT_FAILURES = 6;
|
|
199
|
+
function readRetryDelayMs(err, consecutiveFailures, intervalMs) {
|
|
200
|
+
if (!(err instanceof api_fetch_1.ApiFetchError) || err.status !== 429)
|
|
201
|
+
return intervalMs;
|
|
202
|
+
// A normal five-second poll repeated three times stays inside the same
|
|
203
|
+
// minute bucket and turns a healthy server-side operation into a CLI error.
|
|
204
|
+
// Back off across the bucket boundary while keeping the overall wait bounded.
|
|
205
|
+
return Math.min(intervalMs * 2 ** consecutiveFailures, 60_000);
|
|
206
|
+
}
|
|
197
207
|
async function waitForDedicatedLease(leaseId, goal, options = {}) {
|
|
198
208
|
const intervalMs = options.intervalMs ?? exports.DEDICATED_WAIT_DEFAULT_INTERVAL_MS;
|
|
199
209
|
const timeoutMs = options.timeoutMs ?? exports.DEDICATED_WAIT_DEFAULT_TIMEOUT_MS;
|
|
@@ -217,9 +227,12 @@ async function waitForDedicatedLease(leaseId, goal, options = {}) {
|
|
|
217
227
|
}
|
|
218
228
|
catch (err) {
|
|
219
229
|
consecutiveReadFailures += 1;
|
|
220
|
-
|
|
230
|
+
const maxFailures = err instanceof api_fetch_1.ApiFetchError && err.status === 429
|
|
231
|
+
? exports.DEDICATED_WAIT_MAX_RATE_LIMIT_FAILURES
|
|
232
|
+
: exports.DEDICATED_WAIT_MAX_READ_FAILURES;
|
|
233
|
+
if (consecutiveReadFailures >= maxFailures)
|
|
221
234
|
throw err;
|
|
222
|
-
await sleep(intervalMs);
|
|
235
|
+
await sleep(readRetryDelayMs(err, consecutiveReadFailures, intervalMs));
|
|
223
236
|
}
|
|
224
237
|
}
|
|
225
238
|
};
|