@memnexus-ai/cli 1.7.220 → 1.7.222
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 -2
- package/dist/commands/memories.d.ts.map +1 -1
- package/dist/commands/memories.js +190 -91
- package/dist/commands/memories.js.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/errors.d.ts +47 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +172 -48
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/retry.d.ts +83 -1
- package/dist/lib/retry.d.ts.map +1 -1
- package/dist/lib/retry.js +143 -3
- package/dist/lib/retry.js.map +1 -1
- package/dist/lib/spinner.d.ts +32 -2
- package/dist/lib/spinner.d.ts.map +1 -1
- package/dist/lib/spinner.js +40 -2
- package/dist/lib/spinner.js.map +1 -1
- package/hooks/capture-hooks.test.sh +465 -0
- package/hooks/capture-precompact.sh +11 -1
- package/hooks/capture-session-end.sh +101 -7
- package/package.json +2 -2
package/dist/lib/retry.js
CHANGED
|
@@ -3,12 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
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;
|
|
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 = exports.NON_NAME_CONFLICT_409_CODES = void 0;
|
|
7
7
|
exports.httpStatus = httpStatus;
|
|
8
8
|
exports.isRateLimitError = isRateLimitError;
|
|
9
9
|
exports.isServiceUnavailableError = isServiceUnavailableError;
|
|
10
10
|
exports.isTransientError = isTransientError;
|
|
11
|
+
exports.errorBody = errorBody;
|
|
12
|
+
exports.errorCode = errorCode;
|
|
11
13
|
exports.isQuotaError = isQuotaError;
|
|
14
|
+
exports.isNameConflictError = isNameConflictError;
|
|
12
15
|
exports.getRetryAfterMs = getRetryAfterMs;
|
|
13
16
|
exports.sleep = sleep;
|
|
14
17
|
exports.resolveMaxRetries = resolveMaxRetries;
|
|
@@ -52,9 +55,146 @@ function isTransientError(error) {
|
|
|
52
55
|
const status = httpStatus(error);
|
|
53
56
|
return status === 502 || status === 503 || status === 504 || status === 408;
|
|
54
57
|
}
|
|
55
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Extract the parsed JSON error body from the shapes the SDK/axios throw.
|
|
60
|
+
* Mirrors {@link httpStatus}: callers should not have to know which client
|
|
61
|
+
* produced the error.
|
|
62
|
+
*/
|
|
63
|
+
function errorBody(error) {
|
|
64
|
+
return error?.data ?? error?.body ?? error?.response?.data;
|
|
65
|
+
}
|
|
66
|
+
/** Codes the message fallback is allowed to recognise. */
|
|
67
|
+
const MESSAGE_FALLBACK_CODES = ['QUOTA_EXCEEDED', 'MEMORY_NAME_CONFLICT'];
|
|
68
|
+
/**
|
|
69
|
+
* Matches a code only where a code can legitimately appear: at the start of the
|
|
70
|
+
* message or after whitespace/punctuation, and NOT followed by a character that
|
|
71
|
+
* would make it part of a longer identifier (`-`, `_`, alphanumerics).
|
|
72
|
+
*
|
|
73
|
+
* `\b` is not enough. `\bQUOTA_EXCEEDED\b` matches inside `QUOTA_EXCEEDED-notes`
|
|
74
|
+
* because `-` is a word boundary, which is exactly how a user-supplied memory
|
|
75
|
+
* name reaches this scan.
|
|
76
|
+
*/
|
|
77
|
+
const ERROR_CODE_PATTERN = new RegExp(`(?:^|[\\s:;,.(\\[])(${MESSAGE_FALLBACK_CODES.join('|')})(?![\\w-])`);
|
|
78
|
+
/**
|
|
79
|
+
* Remove single-, double-, and backtick-quoted spans. Server messages embed
|
|
80
|
+
* user-controlled text in quotes — the name-conflict message is
|
|
81
|
+
* `A memory with name '<name>' already exists` — so anything inside quotes is
|
|
82
|
+
* caller input, not a server code, and must not be scanned.
|
|
83
|
+
*/
|
|
84
|
+
function stripQuotedSpans(message) {
|
|
85
|
+
return message
|
|
86
|
+
.replace(/'[^']*'/g, "''")
|
|
87
|
+
.replace(/"[^"]*"/g, '""')
|
|
88
|
+
.replace(/`[^`]*`/g, '``');
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The machine-readable `code` the API puts on an error body, when present.
|
|
92
|
+
*
|
|
93
|
+
* Falls back to scanning the message ONLY when no structured body arrived at
|
|
94
|
+
* all: some SDK/gateway paths surface a bare stringified error, and a quota
|
|
95
|
+
* rejection that arrives as text is still a quota rejection.
|
|
96
|
+
*
|
|
97
|
+
* The fallback is deliberately narrow, because the message contains
|
|
98
|
+
* user-controlled text. Server error messages embed the memory NAME the caller
|
|
99
|
+
* supplied (`A memory with name '<name>' already exists`), so an unrestricted
|
|
100
|
+
* scan let the caller choose the classification: `mx memories create --name
|
|
101
|
+
* "QUOTA_EXCEEDED-notes"` against a server that predates the `code` field —
|
|
102
|
+
* exactly the rolling-deploy case this fallback exists for — turned a name
|
|
103
|
+
* conflict into a quota rejection. The upsert retry was skipped and the user was
|
|
104
|
+
* told "Memory Limit Reached" on an account with capacity.
|
|
105
|
+
*
|
|
106
|
+
* Two restrictions close that:
|
|
107
|
+
* 1. A body that IS present but carries no `code` yields undefined. An old
|
|
108
|
+
* server's name-conflict 409 has a body, so it never reaches the scan.
|
|
109
|
+
* 2. Quoted spans are stripped and the code must stand alone as its own word,
|
|
110
|
+
* so a code appearing inside caller text cannot be read as the server's
|
|
111
|
+
* own code.
|
|
112
|
+
*/
|
|
113
|
+
function errorCode(error) {
|
|
114
|
+
const body = errorBody(error);
|
|
115
|
+
const code = body?.code;
|
|
116
|
+
if (typeof code === 'string')
|
|
117
|
+
return code;
|
|
118
|
+
// A structured body arrived and did not name a code — that is an answer, not a
|
|
119
|
+
// gap. Do not guess from prose.
|
|
120
|
+
if (body !== undefined && body !== null)
|
|
121
|
+
return undefined;
|
|
122
|
+
const message = typeof error?.message === 'string' ? error.message : '';
|
|
123
|
+
const match = ERROR_CODE_PATTERN.exec(stripQuotedSpans(message));
|
|
124
|
+
return match?.[1];
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* True when an error is a quota rejection. Never retried — capacity does not
|
|
128
|
+
* come back on its own.
|
|
129
|
+
*
|
|
130
|
+
* Status alone is NOT sufficient. `POST /api/memories` rejects an over-cap
|
|
131
|
+
* create with **409 + code QUOTA_EXCEEDED**, not 402; this predicate used to test
|
|
132
|
+
* `status === 402` only, so it never matched a real quota rejection. The visible
|
|
133
|
+
* consequence was `create --stdin-jsonl`: the early-stop that exists so a
|
|
134
|
+
* capped account does not hammer the API once capacity is gone never fired, and
|
|
135
|
+
* every remaining line was sent and rejected, each reported as a generic
|
|
136
|
+
* CREATE_FAILED rather than as quota.
|
|
137
|
+
*
|
|
138
|
+
* 402 is retained because the batch/import paths documented it and a future
|
|
139
|
+
* billing-side rejection may still use it. The 409 arm keys on the CODE, never
|
|
140
|
+
* on the bare status: 409 is overloaded — it is also MEMORY_NAME_CONFLICT, which
|
|
141
|
+
* must keep flowing to the named-upsert retry rather than being reported as
|
|
142
|
+
* quota.
|
|
143
|
+
*/
|
|
56
144
|
function isQuotaError(error) {
|
|
57
|
-
|
|
145
|
+
if (httpStatus(error) === 402)
|
|
146
|
+
return true;
|
|
147
|
+
return httpStatus(error) === 409 && errorCode(error) === 'QUOTA_EXCEEDED';
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* 409 codes that are definitively NOT a name conflict.
|
|
151
|
+
*
|
|
152
|
+
* Enforced structurally — {@link isNameConflictError} accepts only
|
|
153
|
+
* MEMORY_NAME_CONFLICT, so every other code already fails closed. The list is
|
|
154
|
+
* kept explicit so the intent is testable and so adding a new 409 server-side
|
|
155
|
+
* has a visible place to be registered.
|
|
156
|
+
*/
|
|
157
|
+
exports.NON_NAME_CONFLICT_409_CODES = [
|
|
158
|
+
'QUOTA_EXCEEDED',
|
|
159
|
+
'NAMED_MEMORY_APPEND_EXHAUSTED',
|
|
160
|
+
'NAMED_WRITE_CONCURRENCY_LIMIT',
|
|
161
|
+
];
|
|
162
|
+
/**
|
|
163
|
+
* True when a 409 means "a named memory with this name already exists" — the
|
|
164
|
+
* only 409 that may be retried as an upsert against PUT /memories/named/:name.
|
|
165
|
+
*
|
|
166
|
+
* POSITIVE classification, with a bounded compatibility window.
|
|
167
|
+
*
|
|
168
|
+
* This used to be "409 that is not a quota rejection". That was correct for the
|
|
169
|
+
* two codes that existed, but it classified by exclusion: any 409 the CLI did
|
|
170
|
+
* not recognise became a name conflict and was retried as an upsert. The upsert
|
|
171
|
+
* sends no `expectedHeadId`, so it overwrites whatever the head is at that
|
|
172
|
+
* moment — and the 409 most likely to be misclassified is a concurrent-write
|
|
173
|
+
* rejection, precisely the case where the head being overwritten is NOT the one
|
|
174
|
+
* the caller read. A new server-side 409 would have turned a rejected write into
|
|
175
|
+
* a silent clobber of someone else's version.
|
|
176
|
+
*
|
|
177
|
+
* The rule now:
|
|
178
|
+
* - `code === 'MEMORY_NAME_CONFLICT'` → name conflict. Positive, exact.
|
|
179
|
+
* - Any OTHER code → not a name conflict. New codes fail closed; see
|
|
180
|
+
* {@link NON_NAME_CONFLICT_409_CODES}.
|
|
181
|
+
* - NO code on the body at all → fall back to the bare-409 heuristic. The
|
|
182
|
+
* name-conflict body only began carrying `code` in v4.05, and during a
|
|
183
|
+
* rolling deploy the CLI still has to upsert against an older server. This
|
|
184
|
+
* arm is the compatibility window and can be deleted once no pre-v4.05
|
|
185
|
+
* server is in service.
|
|
186
|
+
*/
|
|
187
|
+
function isNameConflictError(error) {
|
|
188
|
+
if (httpStatus(error) !== 409)
|
|
189
|
+
return false;
|
|
190
|
+
const code = errorCode(error);
|
|
191
|
+
if (code === 'MEMORY_NAME_CONFLICT')
|
|
192
|
+
return true;
|
|
193
|
+
if (code !== undefined)
|
|
194
|
+
return false;
|
|
195
|
+
// Legacy path: pre-v4.05 server, no code anywhere. A bare 409 from the create
|
|
196
|
+
// route was a name conflict on those versions.
|
|
197
|
+
return true;
|
|
58
198
|
}
|
|
59
199
|
/**
|
|
60
200
|
* Extract the server's Retry-After hint in milliseconds, or null if absent.
|
package/dist/lib/retry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/lib/retry.ts"],"names":[],"mappings":";;;;;;AAkBA,gCAEC;AAGD,4CAEC;AAGD,8DAEC;AAUD,4CAGC;
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/lib/retry.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/spinner.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { OutputFormat } from '../types';
|
|
2
|
+
export interface SpinnerFailOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Process exit code to set. Defaults to 1. Pass `null` to leave
|
|
5
|
+
* `process.exitCode` untouched (the command is expected to exit 0 anyway).
|
|
6
|
+
*/
|
|
7
|
+
exitCode?: number | null;
|
|
8
|
+
}
|
|
2
9
|
/**
|
|
3
10
|
* Conditional spinner that only shows when output format is not JSON
|
|
4
11
|
* This prevents spinners from interfering with JSON output that may be piped to other tools
|
|
@@ -16,9 +23,32 @@ export declare class ConditionalSpinner {
|
|
|
16
23
|
*/
|
|
17
24
|
succeed(text?: string): this;
|
|
18
25
|
/**
|
|
19
|
-
* Stop the spinner and
|
|
26
|
+
* Stop the spinner and report a failure.
|
|
27
|
+
*
|
|
28
|
+
* The failure text always goes to STDERR — including in `--format json`
|
|
29
|
+
* mode, where the spinner itself is disabled and this used to be a complete
|
|
30
|
+
* no-op (the command then exited 0 with empty stdout, indistinguishable from
|
|
31
|
+
* an empty result). It also always sets `process.exitCode` (default 1), which
|
|
32
|
+
* ora never did, so the failure is visible to callers that only check the
|
|
33
|
+
* exit status.
|
|
34
|
+
*
|
|
35
|
+
* We stop the spinner and write the line ourselves rather than calling ora's
|
|
36
|
+
* fail(): ora writes to stderr too, but only when the spinner is enabled, so
|
|
37
|
+
* routing through it would keep json mode silent. Writing directly makes both
|
|
38
|
+
* modes behave identically.
|
|
39
|
+
*
|
|
40
|
+
* For failures the command deliberately continues past — a genuine not-found
|
|
41
|
+
* banner, a per-item warning in a batch — use `softFail()` instead.
|
|
42
|
+
*/
|
|
43
|
+
fail(text?: string, opts?: SpinnerFailOptions): this;
|
|
44
|
+
/**
|
|
45
|
+
* Stop the spinner and show ora's failure banner without setting an exit
|
|
46
|
+
* code — the legacy `fail()` behaviour, byte for byte. Reserved for outcomes
|
|
47
|
+
* that are NOT errors: a genuine not-found lookup, or a per-item warning in a
|
|
48
|
+
* batch that intentionally continues. Anything that means "the operation did
|
|
49
|
+
* not happen" must use `fail()`.
|
|
20
50
|
*/
|
|
21
|
-
|
|
51
|
+
softFail(text?: string): this;
|
|
22
52
|
/**
|
|
23
53
|
* Stop the spinner and show warning message
|
|
24
54
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/lib/spinner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/lib/spinner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,OAAO,CAAU;gBAEb,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM;IASxD;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAO5B;;;;;;;;;;;;;;;;;OAiBG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,IAAI;IAgBpD;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAO7B;;OAEG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAOzB;;OAEG;IACH,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;IAOzB;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACH,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,EAIrB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;CACF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,GAAG,kBAAkB,CAE9F"}
|
package/dist/lib/spinner.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.ConditionalSpinner = void 0;
|
|
7
7
|
exports.createSpinner = createSpinner;
|
|
8
8
|
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
10
|
/**
|
|
10
11
|
* Conditional spinner that only shows when output format is not JSON
|
|
11
12
|
* This prevents spinners from interfering with JSON output that may be piped to other tools
|
|
@@ -39,9 +40,46 @@ class ConditionalSpinner {
|
|
|
39
40
|
return this;
|
|
40
41
|
}
|
|
41
42
|
/**
|
|
42
|
-
* Stop the spinner and
|
|
43
|
+
* Stop the spinner and report a failure.
|
|
44
|
+
*
|
|
45
|
+
* The failure text always goes to STDERR — including in `--format json`
|
|
46
|
+
* mode, where the spinner itself is disabled and this used to be a complete
|
|
47
|
+
* no-op (the command then exited 0 with empty stdout, indistinguishable from
|
|
48
|
+
* an empty result). It also always sets `process.exitCode` (default 1), which
|
|
49
|
+
* ora never did, so the failure is visible to callers that only check the
|
|
50
|
+
* exit status.
|
|
51
|
+
*
|
|
52
|
+
* We stop the spinner and write the line ourselves rather than calling ora's
|
|
53
|
+
* fail(): ora writes to stderr too, but only when the spinner is enabled, so
|
|
54
|
+
* routing through it would keep json mode silent. Writing directly makes both
|
|
55
|
+
* modes behave identically.
|
|
56
|
+
*
|
|
57
|
+
* For failures the command deliberately continues past — a genuine not-found
|
|
58
|
+
* banner, a per-item warning in a batch — use `softFail()` instead.
|
|
43
59
|
*/
|
|
44
|
-
fail(text) {
|
|
60
|
+
fail(text, opts) {
|
|
61
|
+
// Stop rather than ora.fail() so exactly one failure line is emitted,
|
|
62
|
+
// from here, in json and non-json mode alike.
|
|
63
|
+
if (this.enabled && this.spinner) {
|
|
64
|
+
this.spinner.stop();
|
|
65
|
+
}
|
|
66
|
+
if (text) {
|
|
67
|
+
console.error(chalk_1.default.red(`✖ ${text}`));
|
|
68
|
+
}
|
|
69
|
+
const code = opts && 'exitCode' in opts ? opts.exitCode : 1;
|
|
70
|
+
if (code !== null && code !== undefined) {
|
|
71
|
+
process.exitCode = code;
|
|
72
|
+
}
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Stop the spinner and show ora's failure banner without setting an exit
|
|
77
|
+
* code — the legacy `fail()` behaviour, byte for byte. Reserved for outcomes
|
|
78
|
+
* that are NOT errors: a genuine not-found lookup, or a per-item warning in a
|
|
79
|
+
* batch that intentionally continues. Anything that means "the operation did
|
|
80
|
+
* not happen" must use `fail()`.
|
|
81
|
+
*/
|
|
82
|
+
softFail(text) {
|
|
45
83
|
if (this.enabled && this.spinner) {
|
|
46
84
|
this.spinner.fail(text);
|
|
47
85
|
}
|
package/dist/lib/spinner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/lib/spinner.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/lib/spinner.ts"],"names":[],"mappings":"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"}
|