@memnexus-ai/cli 1.7.218 → 1.7.220
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/commands/memories.d.ts +2 -14
- package/dist/commands/memories.d.ts.map +1 -1
- package/dist/commands/memories.js +132 -106
- package/dist/commands/memories.js.map +1 -1
- package/dist/lib/retry.d.ts +98 -0
- package/dist/lib/retry.d.ts.map +1 -0
- package/dist/lib/retry.js +183 -0
- package/dist/lib/retry.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Extract the HTTP status from the several error shapes the SDK/axios throw. */
|
|
2
|
+
export declare function httpStatus(error: any): number | undefined;
|
|
3
|
+
/** True when an error is an HTTP 429 (rate limited). */
|
|
4
|
+
export declare function isRateLimitError(error: any): boolean;
|
|
5
|
+
/** True when an error is an HTTP 503 (service unavailable — transient). */
|
|
6
|
+
export declare function isServiceUnavailableError(error: any): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* True when an error is a transient/ambiguous status the server MAY or MAY NOT
|
|
9
|
+
* have processed: 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout,
|
|
10
|
+
* 408 Request Timeout. These are retry-safe ONLY for idempotent requests — see
|
|
11
|
+
* the retry matrix in {@link withSingleShotRetry}. 500 is intentionally
|
|
12
|
+
* excluded: it signals a server-side application fault, not a transient
|
|
13
|
+
* infrastructure hiccup, and retrying rarely helps.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isTransientError(error: any): boolean;
|
|
16
|
+
/** True when an error is an HTTP 402 (quota / payment required). Never retried. */
|
|
17
|
+
export declare function isQuotaError(error: any): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Extract the server's Retry-After hint in milliseconds, or null if absent.
|
|
20
|
+
* The API surfaces it as a body field (`retryAfter`, seconds) on 429s
|
|
21
|
+
* (see lib/errors.ts) and may also send a Retry-After header; we honor both.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getRetryAfterMs(error: any): number | null;
|
|
24
|
+
/** Promise-based sleep. Extracted so tests can inject a no-op/spy. */
|
|
25
|
+
export declare function sleep(ms: number): Promise<void>;
|
|
26
|
+
/** Default retry attempts (beyond the first try) when MX_CLI_MAX_RETRIES unset. */
|
|
27
|
+
export declare const SINGLE_SHOT_DEFAULT_MAX_RETRIES = 3;
|
|
28
|
+
/** Clamp band for MX_CLI_MAX_RETRIES. 0 disables retry (fail like today). */
|
|
29
|
+
export declare const SINGLE_SHOT_MAX_RETRIES_MIN = 0;
|
|
30
|
+
export declare const SINGLE_SHOT_MAX_RETRIES_MAX = 5;
|
|
31
|
+
/** Base for the exponential fallback backoff when no Retry-After hint is given. */
|
|
32
|
+
export declare const SINGLE_SHOT_BASE_BACKOFF_MS = 500;
|
|
33
|
+
/**
|
|
34
|
+
* Hard cap on any single wait (30s). A hostile or fat-fingered Retry-After (e.g.
|
|
35
|
+
* 86400) must not hang an unattended CLI — we clamp the per-attempt wait so the
|
|
36
|
+
* worst case is bounded by maxRetries * this cap.
|
|
37
|
+
*/
|
|
38
|
+
export declare const SINGLE_SHOT_MAX_WAIT_MS = 30000;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the retry budget from MX_CLI_MAX_RETRIES, clamped to
|
|
41
|
+
* [MIN, MAX] = [0, 5]. Out-of-band numbers are clamped to the nearest bound;
|
|
42
|
+
* non-numeric falls back to the default. Warns once on stderr — mirrors the
|
|
43
|
+
* RECALL_MAX_MS / MX_CREATE_CONCURRENCY clamp convention. 0 disables retry.
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveMaxRetries(raw: string | undefined, warn?: (msg: string) => void): number;
|
|
46
|
+
/**
|
|
47
|
+
* Process-wide retry budget, resolved once at import so the clamp WARN fires at
|
|
48
|
+
* most once per CLI invocation (matches the RECALL_MAX_MS import-time IIFE).
|
|
49
|
+
*/
|
|
50
|
+
export declare const SINGLE_SHOT_MAX_RETRIES: number;
|
|
51
|
+
export interface SingleShotRetryOptions {
|
|
52
|
+
/**
|
|
53
|
+
* Whether the wrapped request is idempotent (safe to send more than once).
|
|
54
|
+
* GET reads (search/get/list/recall) and CAS/by-name writes are idempotent.
|
|
55
|
+
* A plain POST create or non-CAS update is NOT — see the matrix below.
|
|
56
|
+
*/
|
|
57
|
+
idempotent: boolean;
|
|
58
|
+
/** Sleep function (injectable for tests). Defaults to the real timer. */
|
|
59
|
+
sleep?: (ms: number) => Promise<void>;
|
|
60
|
+
/** Retry budget (attempts beyond the first). Defaults to the resolved env value. */
|
|
61
|
+
maxRetries?: number;
|
|
62
|
+
/** Base backoff for the no-Retry-After fallback. */
|
|
63
|
+
baseBackoffMs?: number;
|
|
64
|
+
/** Cap on any single wait. */
|
|
65
|
+
maxWaitMs?: number;
|
|
66
|
+
/** [0,1) source for jitter — injectable for deterministic tests. */
|
|
67
|
+
random?: () => number;
|
|
68
|
+
/** Called before each sleep so the caller can print a STDERR-only notice. */
|
|
69
|
+
onRetry?: (info: {
|
|
70
|
+
attempt: number;
|
|
71
|
+
maxRetries: number;
|
|
72
|
+
waitMs: number;
|
|
73
|
+
status?: number;
|
|
74
|
+
}) => void;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Run `fn`, retrying transient failures per this matrix (the safety-critical
|
|
78
|
+
* part — idempotency decides 5xx behavior):
|
|
79
|
+
*
|
|
80
|
+
* 429 (rate limited): the server REJECTED the request before processing it, so
|
|
81
|
+
* it never acted on the payload. Safe to retry for ANY method, including a
|
|
82
|
+
* POST create — retrying cannot duplicate a create the server never made.
|
|
83
|
+
*
|
|
84
|
+
* 502/503/504/408 (transient/ambiguous): the request MAY have been processed
|
|
85
|
+
* server-side before the error surfaced. Retry ONLY when `idempotent` is
|
|
86
|
+
* true (GET reads; CAS/by-name writes). For a non-idempotent POST create or
|
|
87
|
+
* non-CAS update we must NOT auto-retry — a retry could produce a DUPLICATE
|
|
88
|
+
* create — so we surface the original error instead.
|
|
89
|
+
*
|
|
90
|
+
* Everything else (402 quota, 401/403 auth, 422 validation, 500, other 4xx):
|
|
91
|
+
* never retried — the original error propagates to handleError for its clear
|
|
92
|
+
* message and exit code (no behavior change vs. today on final failure).
|
|
93
|
+
*
|
|
94
|
+
* Wait per attempt = the server's Retry-After hint when present, else an
|
|
95
|
+
* exponential backoff with jitter; either way capped at `maxWaitMs`.
|
|
96
|
+
*/
|
|
97
|
+
export declare function withSingleShotRetry<T>(fn: () => Promise<T>, opts: SingleShotRetryOptions): Promise<T>;
|
|
98
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/lib/retry.ts"],"names":[],"mappings":"AAiBA,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,SAAS,CAEzD;AAED,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAEpD;AAED,2EAA2E;AAC3E,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAE7D;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAGpD;AAED,mFAAmF;AACnF,wBAAgB,YAAY,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAoBzD;AAED,sEAAsE;AACtE,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAGD,mFAAmF;AACnF,eAAO,MAAM,+BAA+B,IAAI,CAAC;AACjD,6EAA6E;AAC7E,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,mFAAmF;AACnF,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAE9C;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,IAAI,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAA2C,GACjE,MAAM,CAiBR;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAoD,CAAC;AAEzF,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB,yEAAyE;IACzE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,KAAK,IAAI,CAAC;CACZ;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,CAAC,CAAC,CA8BZ"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SINGLE_SHOT_MAX_RETRIES = exports.SINGLE_SHOT_MAX_WAIT_MS = exports.SINGLE_SHOT_BASE_BACKOFF_MS = exports.SINGLE_SHOT_MAX_RETRIES_MAX = exports.SINGLE_SHOT_MAX_RETRIES_MIN = exports.SINGLE_SHOT_DEFAULT_MAX_RETRIES = void 0;
|
|
7
|
+
exports.httpStatus = httpStatus;
|
|
8
|
+
exports.isRateLimitError = isRateLimitError;
|
|
9
|
+
exports.isServiceUnavailableError = isServiceUnavailableError;
|
|
10
|
+
exports.isTransientError = isTransientError;
|
|
11
|
+
exports.isQuotaError = isQuotaError;
|
|
12
|
+
exports.getRetryAfterMs = getRetryAfterMs;
|
|
13
|
+
exports.sleep = sleep;
|
|
14
|
+
exports.resolveMaxRetries = resolveMaxRetries;
|
|
15
|
+
exports.withSingleShotRetry = withSingleShotRetry;
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
// ── Single-shot retry helper (PO CLI-latency directive, item 3) ──────────────
|
|
18
|
+
// Scripted single-request commands (`mx memories search/get/recall/create/list/
|
|
19
|
+
// update`) that hit core-api's rate limiter (429) or a transient 5xx used to
|
|
20
|
+
// fail immediately (errors.ts exits 5, no retry). This module provides a bounded
|
|
21
|
+
// retry that honors the server's Retry-After hint so a single 429 no longer
|
|
22
|
+
// breaks an unattended script.
|
|
23
|
+
//
|
|
24
|
+
// It is deliberately separate from the BATCH retry helpers in
|
|
25
|
+
// commands/memories.ts (bulkDeleteWithRetry / batchCreateWithRetry). Those own
|
|
26
|
+
// their per-item retry loops for `--batch/--stdin/--all` and
|
|
27
|
+
// `create --stdin-jsonl`; this helper is ONLY for the plain single-request
|
|
28
|
+
// commands. The shared HTTP-status/Retry-After primitives live here and are
|
|
29
|
+
// re-exported from commands/memories.ts so the batch helpers and their tests
|
|
30
|
+
// keep using the same implementation (single source of truth).
|
|
31
|
+
/** Extract the HTTP status from the several error shapes the SDK/axios throw. */
|
|
32
|
+
function httpStatus(error) {
|
|
33
|
+
return error?.status ?? error?.statusCode ?? error?.response?.status;
|
|
34
|
+
}
|
|
35
|
+
/** True when an error is an HTTP 429 (rate limited). */
|
|
36
|
+
function isRateLimitError(error) {
|
|
37
|
+
return httpStatus(error) === 429;
|
|
38
|
+
}
|
|
39
|
+
/** True when an error is an HTTP 503 (service unavailable — transient). */
|
|
40
|
+
function isServiceUnavailableError(error) {
|
|
41
|
+
return httpStatus(error) === 503;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* True when an error is a transient/ambiguous status the server MAY or MAY NOT
|
|
45
|
+
* have processed: 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout,
|
|
46
|
+
* 408 Request Timeout. These are retry-safe ONLY for idempotent requests — see
|
|
47
|
+
* the retry matrix in {@link withSingleShotRetry}. 500 is intentionally
|
|
48
|
+
* excluded: it signals a server-side application fault, not a transient
|
|
49
|
+
* infrastructure hiccup, and retrying rarely helps.
|
|
50
|
+
*/
|
|
51
|
+
function isTransientError(error) {
|
|
52
|
+
const status = httpStatus(error);
|
|
53
|
+
return status === 502 || status === 503 || status === 504 || status === 408;
|
|
54
|
+
}
|
|
55
|
+
/** True when an error is an HTTP 402 (quota / payment required). Never retried. */
|
|
56
|
+
function isQuotaError(error) {
|
|
57
|
+
return httpStatus(error) === 402;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Extract the server's Retry-After hint in milliseconds, or null if absent.
|
|
61
|
+
* The API surfaces it as a body field (`retryAfter`, seconds) on 429s
|
|
62
|
+
* (see lib/errors.ts) and may also send a Retry-After header; we honor both.
|
|
63
|
+
*/
|
|
64
|
+
function getRetryAfterMs(error) {
|
|
65
|
+
const data = error?.data ?? error?.response?.data ?? {};
|
|
66
|
+
const secs = data?.retryAfter ?? data?.retry_after;
|
|
67
|
+
if (typeof secs === 'number' && Number.isFinite(secs) && secs >= 0) {
|
|
68
|
+
return Math.round(secs * 1000);
|
|
69
|
+
}
|
|
70
|
+
const headers = error?.headers ?? error?.response?.headers;
|
|
71
|
+
let headerVal;
|
|
72
|
+
if (headers) {
|
|
73
|
+
if (typeof headers.get === 'function') {
|
|
74
|
+
headerVal = headers.get('retry-after') ?? headers.get('Retry-After');
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
headerVal = headers['retry-after'] ?? headers['Retry-After'];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (headerVal !== undefined && headerVal !== null) {
|
|
81
|
+
const n = parseInt(String(headerVal), 10);
|
|
82
|
+
if (Number.isFinite(n) && n >= 0)
|
|
83
|
+
return n * 1000;
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
/** Promise-based sleep. Extracted so tests can inject a no-op/spy. */
|
|
88
|
+
function sleep(ms) {
|
|
89
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
90
|
+
}
|
|
91
|
+
// ── Retry configuration ──────────────────────────────────────────────────────
|
|
92
|
+
/** Default retry attempts (beyond the first try) when MX_CLI_MAX_RETRIES unset. */
|
|
93
|
+
exports.SINGLE_SHOT_DEFAULT_MAX_RETRIES = 3;
|
|
94
|
+
/** Clamp band for MX_CLI_MAX_RETRIES. 0 disables retry (fail like today). */
|
|
95
|
+
exports.SINGLE_SHOT_MAX_RETRIES_MIN = 0;
|
|
96
|
+
exports.SINGLE_SHOT_MAX_RETRIES_MAX = 5;
|
|
97
|
+
/** Base for the exponential fallback backoff when no Retry-After hint is given. */
|
|
98
|
+
exports.SINGLE_SHOT_BASE_BACKOFF_MS = 500;
|
|
99
|
+
/**
|
|
100
|
+
* Hard cap on any single wait (30s). A hostile or fat-fingered Retry-After (e.g.
|
|
101
|
+
* 86400) must not hang an unattended CLI — we clamp the per-attempt wait so the
|
|
102
|
+
* worst case is bounded by maxRetries * this cap.
|
|
103
|
+
*/
|
|
104
|
+
exports.SINGLE_SHOT_MAX_WAIT_MS = 30_000;
|
|
105
|
+
/**
|
|
106
|
+
* Resolve the retry budget from MX_CLI_MAX_RETRIES, clamped to
|
|
107
|
+
* [MIN, MAX] = [0, 5]. Out-of-band numbers are clamped to the nearest bound;
|
|
108
|
+
* non-numeric falls back to the default. Warns once on stderr — mirrors the
|
|
109
|
+
* RECALL_MAX_MS / MX_CREATE_CONCURRENCY clamp convention. 0 disables retry.
|
|
110
|
+
*/
|
|
111
|
+
function resolveMaxRetries(raw, warn = (m) => console.warn(chalk_1.default.yellow(m))) {
|
|
112
|
+
if (raw === undefined || raw === '')
|
|
113
|
+
return exports.SINGLE_SHOT_DEFAULT_MAX_RETRIES;
|
|
114
|
+
const n = parseInt(raw, 10);
|
|
115
|
+
if (!Number.isFinite(n)) {
|
|
116
|
+
warn(`MX_CLI_MAX_RETRIES=${raw} is not a number, using default ${exports.SINGLE_SHOT_DEFAULT_MAX_RETRIES}`);
|
|
117
|
+
return exports.SINGLE_SHOT_DEFAULT_MAX_RETRIES;
|
|
118
|
+
}
|
|
119
|
+
if (n < exports.SINGLE_SHOT_MAX_RETRIES_MIN || n > exports.SINGLE_SHOT_MAX_RETRIES_MAX) {
|
|
120
|
+
const clamped = Math.max(exports.SINGLE_SHOT_MAX_RETRIES_MIN, Math.min(exports.SINGLE_SHOT_MAX_RETRIES_MAX, n));
|
|
121
|
+
warn(`MX_CLI_MAX_RETRIES=${raw} out of range [${exports.SINGLE_SHOT_MAX_RETRIES_MIN},${exports.SINGLE_SHOT_MAX_RETRIES_MAX}], clamped to ${clamped}`);
|
|
122
|
+
return clamped;
|
|
123
|
+
}
|
|
124
|
+
return n;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Process-wide retry budget, resolved once at import so the clamp WARN fires at
|
|
128
|
+
* most once per CLI invocation (matches the RECALL_MAX_MS import-time IIFE).
|
|
129
|
+
*/
|
|
130
|
+
exports.SINGLE_SHOT_MAX_RETRIES = resolveMaxRetries(process.env.MX_CLI_MAX_RETRIES);
|
|
131
|
+
/**
|
|
132
|
+
* Run `fn`, retrying transient failures per this matrix (the safety-critical
|
|
133
|
+
* part — idempotency decides 5xx behavior):
|
|
134
|
+
*
|
|
135
|
+
* 429 (rate limited): the server REJECTED the request before processing it, so
|
|
136
|
+
* it never acted on the payload. Safe to retry for ANY method, including a
|
|
137
|
+
* POST create — retrying cannot duplicate a create the server never made.
|
|
138
|
+
*
|
|
139
|
+
* 502/503/504/408 (transient/ambiguous): the request MAY have been processed
|
|
140
|
+
* server-side before the error surfaced. Retry ONLY when `idempotent` is
|
|
141
|
+
* true (GET reads; CAS/by-name writes). For a non-idempotent POST create or
|
|
142
|
+
* non-CAS update we must NOT auto-retry — a retry could produce a DUPLICATE
|
|
143
|
+
* create — so we surface the original error instead.
|
|
144
|
+
*
|
|
145
|
+
* Everything else (402 quota, 401/403 auth, 422 validation, 500, other 4xx):
|
|
146
|
+
* never retried — the original error propagates to handleError for its clear
|
|
147
|
+
* message and exit code (no behavior change vs. today on final failure).
|
|
148
|
+
*
|
|
149
|
+
* Wait per attempt = the server's Retry-After hint when present, else an
|
|
150
|
+
* exponential backoff with jitter; either way capped at `maxWaitMs`.
|
|
151
|
+
*/
|
|
152
|
+
async function withSingleShotRetry(fn, opts) {
|
|
153
|
+
const maxRetries = opts.maxRetries ?? exports.SINGLE_SHOT_MAX_RETRIES;
|
|
154
|
+
const doSleep = opts.sleep ?? sleep;
|
|
155
|
+
const baseBackoff = opts.baseBackoffMs ?? exports.SINGLE_SHOT_BASE_BACKOFF_MS;
|
|
156
|
+
const maxWait = opts.maxWaitMs ?? exports.SINGLE_SHOT_MAX_WAIT_MS;
|
|
157
|
+
const random = opts.random ?? Math.random;
|
|
158
|
+
let attempt = 0;
|
|
159
|
+
for (;;) {
|
|
160
|
+
try {
|
|
161
|
+
return await fn();
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
const status = httpStatus(error);
|
|
165
|
+
const rateLimited = isRateLimitError(error);
|
|
166
|
+
// 429 → retry any method; transient 5xx → retry only if idempotent.
|
|
167
|
+
const retryable = rateLimited || (opts.idempotent && isTransientError(error));
|
|
168
|
+
if (!retryable || attempt >= maxRetries) {
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
const hinted = getRetryAfterMs(error);
|
|
172
|
+
// Exponential backoff (500ms, 1s, 2s, …) + up to 250ms jitter when the
|
|
173
|
+
// server gives no hint. Jitter avoids a thundering-herd of scripted CLIs
|
|
174
|
+
// retrying in lockstep.
|
|
175
|
+
const backoff = baseBackoff * 2 ** attempt + Math.floor(random() * 250);
|
|
176
|
+
const waitMs = Math.min(hinted ?? backoff, maxWait);
|
|
177
|
+
attempt++;
|
|
178
|
+
opts.onRetry?.({ attempt, maxRetries, waitMs, status });
|
|
179
|
+
await doSleep(waitMs);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/lib/retry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memnexus-ai/cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.220",
|
|
4
4
|
"description": "Command-line interface for MemNexus Core API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"node": ">=18.0.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@memnexus-ai/typescript-sdk": "^1.60.
|
|
37
|
+
"@memnexus-ai/typescript-sdk": "^1.60.28",
|
|
38
38
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
39
39
|
"axios": "^1.13.6",
|
|
40
40
|
"chalk": "^5.3.0",
|