@memnexus-ai/cli 1.7.219 → 1.7.221
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.map +1 -1
- package/dist/commands/memories.js +185 -90
- 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 +137 -48
- package/dist/lib/errors.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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memories.d.ts","sourceRoot":"","sources":["../../src/commands/memories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"memories.d.ts","sourceRoot":"","sources":["../../src/commands/memories.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,OAAO,EACL,gBAAgB,EAChB,yBAAyB,EACzB,YAAY,EACZ,eAAe,EACf,KAAK,EAGN,MAAM,cAAc,CAAC;AAqBtB,qEAAqE;AACrE,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAC7C,mDAAmD;AACnD,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAElD,mDAAmD;AACnD,wBAAgB,sBAAsB,IAAI,MAAM,CAE/C;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAYlF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CASnE;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CA0B5E;AA0CD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzE;AA8RD,sFAAsF;AACtF,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,2EAA2E;AAC3E,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,oDAAoD;AACpD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,iDAAiD;AACjD,eAAO,MAAM,0BAA0B,MAAM,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACzC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,EAAE,CAUpE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAIrD;AAED,4DAA4D;AAC5D,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,MAA4B,GAAG,MAAM,EAAE,EAAE,CAMtF;AAMD,OAAO,EAAE,gBAAgB,EAAE,yBAAyB,EAAE,YAAY,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;AAyD7F,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACvD,6CAA6C;IAC7C,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EAAE,EACb,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAkB3B;AAED,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,gBAAgB,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;CACtB;AAaD;;;;;;;;;;GAUG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EAAE,EACb,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,GAAG;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACpF,GACA,OAAO,CAAC,qBAAqB,CAAC,CA8ChC;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,EACrC,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EAC1C,QAAQ,GAAE,MAAmC,GAC5C,OAAO,CAAC,MAAM,EAAE,CAAC,CAcnB;AAwKD,oEAAoE;AACpE,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,yFAAyF;AACzF,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,+EAA+E;AAC/E,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,QAAoB,CAAC;AAC9D;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,QAAc,CAAC;AAEvD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,aAapC,CAAC;AAEH,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAE1D;AAED,MAAM,WAAW,eAAe;IAC9B,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAC7B,aAAa,GACb,eAAe,GACf,eAAe,GACf,eAAe,GACf,eAAe,CAAC;AAEpB,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,IAAI,CAAC,EAAE,qBAAqB,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,YAAY,EAAE,OAAO,CAAC;IACtB,+DAA+D;IAC/D,gBAAgB,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAuFA;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,IAAI,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAA2C,GACjE,MAAM,CAoBR;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAmB1B;AAED,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAChD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,eAAe,EAAE,EACxB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,kBAAkB,CAAC,CA0G7B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,EAAE,CAUpE;AAED,0EAA0E;AAC1E,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,KAAK,EAAE,MAAM;aACb,KAAK,EAAE,MAAM;IAH/B,QAAQ,CAAC,IAAI,qBAAqB;gBAEhB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM;CAKhC;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,QAAQ,GAAE,MAAqC,GAC9C,OAAO,CAAC,MAAM,CAAC,CA+BjB;AAaD;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,GAAE,MAAqC,GACnD,OAAO,CAAC,IAAI,CAAC,CAqFf;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAunD/D;AA0YD;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAkN1E;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA0ErE;AAED;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAsE1E;AA0DD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAkI7D;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA8F7D;AAkLD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA0H5D;AAkOD;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CA8NnE"}
|
|
@@ -1342,8 +1342,7 @@ function registerMemoriesCommands(program) {
|
|
|
1342
1342
|
if (options.last) {
|
|
1343
1343
|
limit = parseInt(options.last, 10);
|
|
1344
1344
|
if (isNaN(limit) || limit < 1) {
|
|
1345
|
-
|
|
1346
|
-
return;
|
|
1345
|
+
throw (0, errors_1.validationError)('--last must be a positive number');
|
|
1347
1346
|
}
|
|
1348
1347
|
sortField = 'createdAt';
|
|
1349
1348
|
sortOrder = 'desc';
|
|
@@ -1354,17 +1353,14 @@ function registerMemoriesCommands(program) {
|
|
|
1354
1353
|
const validFields = ['createdAt', 'eventTime'];
|
|
1355
1354
|
const validOrders = ['asc', 'desc'];
|
|
1356
1355
|
if (sortParts.length !== 2) {
|
|
1357
|
-
|
|
1358
|
-
return;
|
|
1356
|
+
throw (0, errors_1.validationError)('--sort must be in format field:order (e.g., createdAt:desc)');
|
|
1359
1357
|
}
|
|
1360
1358
|
const [field, order] = sortParts;
|
|
1361
1359
|
if (!validFields.includes(field)) {
|
|
1362
|
-
|
|
1363
|
-
return;
|
|
1360
|
+
throw (0, errors_1.validationError)(`Sort field must be one of: ${validFields.join(', ')}`);
|
|
1364
1361
|
}
|
|
1365
1362
|
if (!validOrders.includes(order)) {
|
|
1366
|
-
|
|
1367
|
-
return;
|
|
1363
|
+
throw (0, errors_1.validationError)(`Sort order must be one of: ${validOrders.join(', ')}`);
|
|
1368
1364
|
}
|
|
1369
1365
|
sortField = field;
|
|
1370
1366
|
sortOrder = order;
|
|
@@ -1387,9 +1383,7 @@ function registerMemoriesCommands(program) {
|
|
|
1387
1383
|
if (recentDuration) {
|
|
1388
1384
|
const recentTs = (0, date_utils_1.getRecentTimestamp)(recentDuration);
|
|
1389
1385
|
if (!recentTs) {
|
|
1390
|
-
|
|
1391
|
-
console.log(chalk_1.default.yellow('Supported formats: 30m, 1h, 7d, 2w'));
|
|
1392
|
-
return;
|
|
1386
|
+
throw (0, errors_1.validationError)(`Invalid duration format: ${recentDuration}. Supported formats: 30m, 1h, 7d, 2w`);
|
|
1393
1387
|
}
|
|
1394
1388
|
listParams.from = recentTs;
|
|
1395
1389
|
}
|
|
@@ -1479,7 +1473,7 @@ function registerMemoriesCommands(program) {
|
|
|
1479
1473
|
}));
|
|
1480
1474
|
const memory = response.data?.data;
|
|
1481
1475
|
if (!memory) {
|
|
1482
|
-
spinner.
|
|
1476
|
+
spinner.softFail(`No memory found with name '${options.name}'`);
|
|
1483
1477
|
return;
|
|
1484
1478
|
}
|
|
1485
1479
|
spinner.succeed(`Found named memory '${options.name}' (v${memory.version || 1})`);
|
|
@@ -1498,14 +1492,12 @@ function registerMemoriesCommands(program) {
|
|
|
1498
1492
|
// Remove duplicates while preserving order
|
|
1499
1493
|
allIds = [...new Set(allIds)].filter((id) => id.trim().length > 0);
|
|
1500
1494
|
if (allIds.length === 0) {
|
|
1501
|
-
|
|
1502
|
-
return;
|
|
1495
|
+
throw (0, errors_1.validationError)('No memory IDs provided');
|
|
1503
1496
|
}
|
|
1504
1497
|
// Discovery options only work with single ID
|
|
1505
1498
|
const hasDiscoveryOptions = options.similar || options.conversation || options.related;
|
|
1506
1499
|
if (hasDiscoveryOptions && allIds.length > 1) {
|
|
1507
|
-
|
|
1508
|
-
return;
|
|
1500
|
+
throw (0, errors_1.validationError)('--similar, --conversation, and --related options only work with a single memory ID');
|
|
1509
1501
|
}
|
|
1510
1502
|
// Single ID mode - use existing logic with short ID support
|
|
1511
1503
|
if (allIds.length === 1) {
|
|
@@ -1521,7 +1513,7 @@ function registerMemoriesCommands(program) {
|
|
|
1521
1513
|
}));
|
|
1522
1514
|
const memory = response.data?.data;
|
|
1523
1515
|
if (!memory) {
|
|
1524
|
-
spinner.
|
|
1516
|
+
spinner.softFail(`No memory found with name '${singleId}'`);
|
|
1525
1517
|
return;
|
|
1526
1518
|
}
|
|
1527
1519
|
spinner.succeed(`Found named memory '${singleId}' (v${memory.version || 1})`);
|
|
@@ -1531,7 +1523,16 @@ function registerMemoriesCommands(program) {
|
|
|
1531
1523
|
return;
|
|
1532
1524
|
}
|
|
1533
1525
|
catch (e) {
|
|
1534
|
-
|
|
1526
|
+
// Only a genuine 404 is "no such name" (exit 0 + banner — a fleet
|
|
1527
|
+
// hook substring-matches this line). Every other failure (5xx,
|
|
1528
|
+
// network, auth) previously rendered as the same banner and exited
|
|
1529
|
+
// 0, which reported an outage as an empty store. Rethrow those to
|
|
1530
|
+
// handleError. Mirrors the explicit --name path above, which has
|
|
1531
|
+
// no catch and always propagates.
|
|
1532
|
+
if (!(0, errors_1.isNotFoundError)(e)) {
|
|
1533
|
+
throw e;
|
|
1534
|
+
}
|
|
1535
|
+
spinner.softFail(`No memory found with name '${singleId}'`);
|
|
1535
1536
|
console.log(chalk_1.default.gray(` Tip: use --name explicitly or pass a UUID/prefix`));
|
|
1536
1537
|
return;
|
|
1537
1538
|
}
|
|
@@ -1539,9 +1540,8 @@ function registerMemoriesCommands(program) {
|
|
|
1539
1540
|
const isShortId = singleId.length < 36;
|
|
1540
1541
|
const MIN_PREFIX_LENGTH = 6;
|
|
1541
1542
|
if (isShortId && singleId.length < MIN_PREFIX_LENGTH) {
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
return;
|
|
1543
|
+
throw (0, errors_1.validationError)(`ID prefix must be at least ${MIN_PREFIX_LENGTH} characters. ` +
|
|
1544
|
+
'Example: mx memories get 2d09116a');
|
|
1545
1545
|
}
|
|
1546
1546
|
let memoryId = singleId;
|
|
1547
1547
|
let resolvedMemory = null;
|
|
@@ -1554,7 +1554,7 @@ function registerMemoriesCommands(program) {
|
|
|
1554
1554
|
}));
|
|
1555
1555
|
const matches = listResponse.data?.data || [];
|
|
1556
1556
|
if (matches.length === 0) {
|
|
1557
|
-
spinner.
|
|
1557
|
+
spinner.softFail(`No memory found with ID prefix: ${singleId}`);
|
|
1558
1558
|
return;
|
|
1559
1559
|
}
|
|
1560
1560
|
if (matches.length > 1) {
|
|
@@ -1750,14 +1750,13 @@ function registerMemoriesCommands(program) {
|
|
|
1750
1750
|
else {
|
|
1751
1751
|
// Direct mode - validate conversationId is provided
|
|
1752
1752
|
if (!options.conversationId) {
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
return;
|
|
1753
|
+
throw (0, errors_1.validationError)('--conversation-id is required.\n' +
|
|
1754
|
+
'\nTo create a new conversation, use:\n' +
|
|
1755
|
+
' mx memories create --conversation-id NEW --content "Your message"\n' +
|
|
1756
|
+
'\nTo add to an existing conversation, use:\n' +
|
|
1757
|
+
' mx memories create --conversation-id conv_abc123 --content "Your message"\n' +
|
|
1758
|
+
'\nOr use interactive mode:\n' +
|
|
1759
|
+
' mx memories create --interactive');
|
|
1761
1760
|
}
|
|
1762
1761
|
// Auto-detect Claude Code session ID for conversation grouping
|
|
1763
1762
|
const claudeSession = config_1.config.isAIAgentContext() ? (0, session_reader_1.readSessionContext)() : undefined;
|
|
@@ -1843,11 +1842,22 @@ function registerMemoriesCommands(program) {
|
|
|
1843
1842
|
// Response is properly typed as CreateMemoryResponse with data and meta fields
|
|
1844
1843
|
const memory = response.data?.data;
|
|
1845
1844
|
const meta = response.data?.meta;
|
|
1845
|
+
// A 2xx without an id means nothing was persisted that we can address.
|
|
1846
|
+
// The success lines below used to render "ID: undefined", and the
|
|
1847
|
+
// --supersedes step below is gated on `memory?.id` so it silently did
|
|
1848
|
+
// nothing — the caller saw a success glyph for a write that produced no
|
|
1849
|
+
// usable memory (v4.04).
|
|
1850
|
+
if (!memory?.id) {
|
|
1851
|
+
spinner.stop();
|
|
1852
|
+
throw (0, errors_1.unusableResponseError)(upserted ? 'Named memory update' : 'Memory creation', responseShape(response.data));
|
|
1853
|
+
}
|
|
1846
1854
|
if (upserted) {
|
|
1847
1855
|
const version = meta?.version || 'new';
|
|
1848
1856
|
spinner.succeed(`Named memory '${memoryData.name}' updated (v${version}) via auto-upsert. ID: ${memory?.id}`);
|
|
1849
1857
|
if (meta?.previousVersionId) {
|
|
1850
|
-
|
|
1858
|
+
if (options.format !== 'json' && options.format !== 'yaml') {
|
|
1859
|
+
console.log(chalk_1.default.gray(`Previous version: ${meta.previousVersionId}`));
|
|
1860
|
+
}
|
|
1851
1861
|
}
|
|
1852
1862
|
}
|
|
1853
1863
|
else {
|
|
@@ -1856,7 +1866,9 @@ function registerMemoriesCommands(program) {
|
|
|
1856
1866
|
: 'Memory created with';
|
|
1857
1867
|
if (isNewConversation && meta?.conversationCreated) {
|
|
1858
1868
|
spinner.succeed(`New conversation created: ${meta.conversationId}\n${nameLabel} ID: ${memory?.id}`);
|
|
1859
|
-
|
|
1869
|
+
if (options.format !== 'json' && options.format !== 'yaml') {
|
|
1870
|
+
console.log(chalk_1.default.gray(`\nSession ID: ${meta.sessionId}`));
|
|
1871
|
+
}
|
|
1860
1872
|
}
|
|
1861
1873
|
else {
|
|
1862
1874
|
spinner.succeed(`${nameLabel} ID: ${memory?.id}`);
|
|
@@ -1876,8 +1888,14 @@ function registerMemoriesCommands(program) {
|
|
|
1876
1888
|
}
|
|
1877
1889
|
catch (relError) {
|
|
1878
1890
|
relSpinner.fail(`Failed to create relationship: ${relError.message || 'Unknown error'}`);
|
|
1879
|
-
|
|
1880
|
-
|
|
1891
|
+
// Partial failure: the memory exists but the SUPERSEDES edge does
|
|
1892
|
+
// not. relSpinner.fail() has already set a non-zero exit code so the
|
|
1893
|
+
// caller cannot mistake this for a clean create. Recovery guidance
|
|
1894
|
+
// goes to stderr — stdout still carries the created-memory body.
|
|
1895
|
+
if (options.format !== 'json' && options.format !== 'yaml') {
|
|
1896
|
+
console.error(chalk_1.default.yellow('Memory was created successfully. You can manually create the relationship with:'));
|
|
1897
|
+
console.error(chalk_1.default.cyan(` mx memories relationships create ${memory.id} --target ${options.supersedes} --type SUPERSEDES`));
|
|
1898
|
+
}
|
|
1881
1899
|
}
|
|
1882
1900
|
}
|
|
1883
1901
|
(0, formatters_1.printOutput)(memory, options.format);
|
|
@@ -1906,13 +1924,11 @@ function registerMemoriesCommands(program) {
|
|
|
1906
1924
|
.action(async (id, options) => {
|
|
1907
1925
|
try {
|
|
1908
1926
|
if (!id && !options.name) {
|
|
1909
|
-
|
|
1910
|
-
return;
|
|
1927
|
+
throw (0, errors_1.validationError)('Provide a memory ID or use --name <name>');
|
|
1911
1928
|
}
|
|
1912
1929
|
// --assign-name and --rename are mutually exclusive
|
|
1913
1930
|
if (options.assignName && options.rename) {
|
|
1914
|
-
|
|
1915
|
-
return;
|
|
1931
|
+
throw (0, errors_1.validationError)('Cannot use --assign-name and --rename together');
|
|
1916
1932
|
}
|
|
1917
1933
|
const updates = {};
|
|
1918
1934
|
if (options.content)
|
|
@@ -1931,8 +1947,7 @@ function registerMemoriesCommands(program) {
|
|
|
1931
1947
|
// --assign-name: assign a name to an existing memory by ID
|
|
1932
1948
|
if (options.assignName) {
|
|
1933
1949
|
if (!id) {
|
|
1934
|
-
|
|
1935
|
-
return;
|
|
1950
|
+
throw (0, errors_1.validationError)('--assign-name requires a memory ID');
|
|
1936
1951
|
}
|
|
1937
1952
|
updates.name = options.assignName;
|
|
1938
1953
|
const spinner = (0, spinner_1.createSpinner)('Assigning name...', options.format).start();
|
|
@@ -1970,8 +1985,7 @@ function registerMemoriesCommands(program) {
|
|
|
1970
1985
|
(0, formatters_1.printOutput)(memory, options.format);
|
|
1971
1986
|
return;
|
|
1972
1987
|
}
|
|
1973
|
-
|
|
1974
|
-
return;
|
|
1988
|
+
throw (0, errors_1.validationError)('--rename requires a memory ID or --name <current-name>');
|
|
1975
1989
|
}
|
|
1976
1990
|
if (Object.keys(updates).length === 0) {
|
|
1977
1991
|
console.log(chalk_1.default.yellow('No updates provided. Use --help to see available options.'));
|
|
@@ -1991,7 +2005,9 @@ function registerMemoriesCommands(program) {
|
|
|
1991
2005
|
const meta = response.data?.meta;
|
|
1992
2006
|
spinner.succeed(`Named memory '${options.name}' updated to v${meta?.version}`);
|
|
1993
2007
|
if (meta?.previousVersionId) {
|
|
1994
|
-
|
|
2008
|
+
if (options.format !== 'json' && options.format !== 'yaml') {
|
|
2009
|
+
console.log(chalk_1.default.gray(`Previous version: ${meta.previousVersionId}`));
|
|
2010
|
+
}
|
|
1995
2011
|
}
|
|
1996
2012
|
(0, formatters_1.printOutput)(memory, options.format);
|
|
1997
2013
|
return;
|
|
@@ -2021,7 +2037,7 @@ function registerMemoriesCommands(program) {
|
|
|
2021
2037
|
const response = await retryRead(() => (0, api_client_1.getSdk)().memories.getNamedMemoryHistory(name));
|
|
2022
2038
|
const data = response.data;
|
|
2023
2039
|
if (!data?.versions?.length) {
|
|
2024
|
-
spinner.
|
|
2040
|
+
spinner.softFail(`No memory found with name '${name}'`);
|
|
2025
2041
|
return;
|
|
2026
2042
|
}
|
|
2027
2043
|
const limit = parseInt(options.limit, 10) || 20;
|
|
@@ -2280,41 +2296,34 @@ function registerMemoriesCommands(program) {
|
|
|
2280
2296
|
.action(async (options, command) => {
|
|
2281
2297
|
try {
|
|
2282
2298
|
if (!options.query) {
|
|
2283
|
-
|
|
2284
|
-
return;
|
|
2299
|
+
throw (0, errors_1.validationError)('--query is required');
|
|
2285
2300
|
}
|
|
2286
2301
|
// Validate search method
|
|
2287
2302
|
const validMethods = ['keyword', 'semantic', 'hybrid'];
|
|
2288
2303
|
if (options.method && !validMethods.includes(options.method)) {
|
|
2289
|
-
|
|
2290
|
-
return;
|
|
2304
|
+
throw (0, errors_1.validationError)(`--method must be one of: ${validMethods.join(', ')}`);
|
|
2291
2305
|
}
|
|
2292
2306
|
// Validate search mode
|
|
2293
2307
|
const validModes = ['unified', 'content', 'facts'];
|
|
2294
2308
|
if (options.mode && !validModes.includes(options.mode)) {
|
|
2295
|
-
|
|
2296
|
-
return;
|
|
2309
|
+
throw (0, errors_1.validationError)(`--mode must be one of: ${validModes.join(', ')}`);
|
|
2297
2310
|
}
|
|
2298
2311
|
// Validate memory type (before spinner starts)
|
|
2299
2312
|
const validTypes = ['episodic', 'semantic', 'procedural'];
|
|
2300
2313
|
if (options.type && !validTypes.includes(options.type)) {
|
|
2301
|
-
|
|
2302
|
-
return;
|
|
2314
|
+
throw (0, errors_1.validationError)(`--type must be one of: ${validTypes.join(', ')}`);
|
|
2303
2315
|
}
|
|
2304
2316
|
// Validate --group-by field
|
|
2305
2317
|
const validGroupByFields = ['conversation'];
|
|
2306
2318
|
if (options.groupBy && !validGroupByFields.includes(options.groupBy)) {
|
|
2307
|
-
|
|
2308
|
-
return;
|
|
2319
|
+
throw (0, errors_1.validationError)(`--group-by must be one of: ${validGroupByFields.join(', ')}`);
|
|
2309
2320
|
}
|
|
2310
2321
|
// Handle --recent duration shortcut
|
|
2311
2322
|
let recentTimestamp = null;
|
|
2312
2323
|
if (options.recent) {
|
|
2313
2324
|
recentTimestamp = (0, date_utils_1.getRecentTimestamp)(options.recent);
|
|
2314
2325
|
if (!recentTimestamp) {
|
|
2315
|
-
|
|
2316
|
-
console.log(chalk_1.default.yellow('Supported formats: 30m, 1h, 7d, 2w'));
|
|
2317
|
-
return;
|
|
2326
|
+
throw (0, errors_1.validationError)(`Invalid duration format: ${options.recent}. Supported formats: 30m, 1h, 7d, 2w`);
|
|
2318
2327
|
}
|
|
2319
2328
|
}
|
|
2320
2329
|
// Handle --brief preset: apply quick lookup defaults
|
|
@@ -2426,8 +2435,7 @@ function registerMemoriesCommands(program) {
|
|
|
2426
2435
|
if (options.sort) {
|
|
2427
2436
|
const validSortFields = ['score', 'createdAt', 'updatedAt', 'eventTime'];
|
|
2428
2437
|
if (!validSortFields.includes(options.sort)) {
|
|
2429
|
-
|
|
2430
|
-
return;
|
|
2438
|
+
throw (0, errors_1.validationError)(`--sort must be one of: ${validSortFields.join(', ')}`);
|
|
2431
2439
|
}
|
|
2432
2440
|
if (options.sort !== 'score') {
|
|
2433
2441
|
searchRequest.sortBy = options.sort;
|
|
@@ -2436,14 +2444,21 @@ function registerMemoriesCommands(program) {
|
|
|
2436
2444
|
if (options.order) {
|
|
2437
2445
|
const validOrders = ['asc', 'desc'];
|
|
2438
2446
|
if (!validOrders.includes(options.order)) {
|
|
2439
|
-
|
|
2440
|
-
return;
|
|
2447
|
+
throw (0, errors_1.validationError)(`--order must be one of: ${validOrders.join(', ')}`);
|
|
2441
2448
|
}
|
|
2442
2449
|
searchRequest.order = options.order;
|
|
2443
2450
|
}
|
|
2444
2451
|
// Use GET endpoint for better performance (Issue #79)
|
|
2445
2452
|
const response = await retryRead(() => (0, api_client_1.getSdk)().memories.searchMemoriesGet(searchRequest));
|
|
2446
2453
|
const searchData = response.data;
|
|
2454
|
+
// A 2xx with no results array is NOT an empty result set: the search did
|
|
2455
|
+
// not return data. Rendering it as "Found 0 results" (exit 0) made a
|
|
2456
|
+
// backend outage look like an empty store (v4.04). A genuine zero-hit
|
|
2457
|
+
// search returns `data: []` and still reports "Found 0 results".
|
|
2458
|
+
if (!searchData || !Array.isArray(searchData.data)) {
|
|
2459
|
+
spinner?.stop();
|
|
2460
|
+
throw (0, errors_1.unusableResponseError)('Memory search', responseShape(searchData));
|
|
2461
|
+
}
|
|
2447
2462
|
// Normalize: API may return flat objects or {memory, score} wrappers.
|
|
2448
2463
|
// Ensure consistent {memory, score, matchedVia} shape for display code.
|
|
2449
2464
|
if (searchData?.data) {
|
|
@@ -2969,8 +2984,7 @@ function registerMemoryRelationshipCommands(memories) {
|
|
|
2969
2984
|
try {
|
|
2970
2985
|
const validDirections = ['outgoing', 'incoming', 'both'];
|
|
2971
2986
|
if (!validDirections.includes(options.direction)) {
|
|
2972
|
-
|
|
2973
|
-
return;
|
|
2987
|
+
throw (0, errors_1.validationError)(`--direction must be one of: ${validDirections.join(', ')}`);
|
|
2974
2988
|
}
|
|
2975
2989
|
const spinner = (0, spinner_1.createSpinner)('Fetching relationships...', options.format).start();
|
|
2976
2990
|
const response = await retryRead(() => (0, api_client_1.getSdk)().memories.getMemoryRelationships(id, {
|
|
@@ -3070,8 +3084,7 @@ function registerMemoryRelationshipCommands(memories) {
|
|
|
3070
3084
|
}
|
|
3071
3085
|
else {
|
|
3072
3086
|
if (!validTypes.includes(options.type.toUpperCase())) {
|
|
3073
|
-
|
|
3074
|
-
return;
|
|
3087
|
+
throw (0, errors_1.validationError)(`--type must be one of: ${validTypes.join(', ')}`);
|
|
3075
3088
|
}
|
|
3076
3089
|
relationshipData = {
|
|
3077
3090
|
targetMemoryId: options.target,
|
|
@@ -3329,12 +3342,10 @@ function registerDigestCommand(memories) {
|
|
|
3329
3342
|
.action(async (options) => {
|
|
3330
3343
|
try {
|
|
3331
3344
|
if (!options.query) {
|
|
3332
|
-
|
|
3333
|
-
return;
|
|
3345
|
+
throw (0, errors_1.validationError)('--query is required');
|
|
3334
3346
|
}
|
|
3335
3347
|
if (!validDigestFormats.includes(options.digestFormat)) {
|
|
3336
|
-
|
|
3337
|
-
return;
|
|
3348
|
+
throw (0, errors_1.validationError)(`--digest-format must be one of: ${validDigestFormats.join(', ')}`);
|
|
3338
3349
|
}
|
|
3339
3350
|
const spinner = (0, spinner_1.createSpinner)('Generating digest...', options.format).start();
|
|
3340
3351
|
const body = {
|
|
@@ -3369,12 +3380,24 @@ function registerDigestCommand(memories) {
|
|
|
3369
3380
|
sdk.config.timeoutMs = prevTimeout;
|
|
3370
3381
|
}
|
|
3371
3382
|
const data = response.data;
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3383
|
+
// A 2xx with no body means the digest was never produced. Reporting it
|
|
3384
|
+
// as a soft failure and exiting 0 made an outage look like "nothing to
|
|
3385
|
+
// say" (v4.04).
|
|
3386
|
+
if (!data || !data.metadata) {
|
|
3387
|
+
spinner.stop();
|
|
3388
|
+
throw (0, errors_1.unusableResponseError)('Digest generation', responseShape(data));
|
|
3375
3389
|
}
|
|
3376
3390
|
const { digest, metadata, sources, keyFacts, entities, effectiveStateBreakdown } = data;
|
|
3377
|
-
|
|
3391
|
+
if (metadata.sourcesUsed === 0) {
|
|
3392
|
+
// Zero sources is a genuine empty result (exit 0), but it is not a
|
|
3393
|
+
// success: the old "Digest generated from 0 memories" success glyph
|
|
3394
|
+
// read as "here is your answer" when nothing was retrieved.
|
|
3395
|
+
spinner.info('No sources met the relevance threshold for this query');
|
|
3396
|
+
}
|
|
3397
|
+
else {
|
|
3398
|
+
spinner.succeed(`Digest generated from ${metadata.sourcesUsed} memories across ${metadata.conversationsSpanned} conversations`);
|
|
3399
|
+
}
|
|
3400
|
+
printRetrievalCaveats(metadata, data.meta);
|
|
3378
3401
|
// JSON/YAML output
|
|
3379
3402
|
if (options.format === 'json' || options.format === 'yaml') {
|
|
3380
3403
|
(0, formatters_1.printOutput)(data, options.format);
|
|
@@ -3421,13 +3444,11 @@ function registerStatusCommand(memories) {
|
|
|
3421
3444
|
.action(async (options) => {
|
|
3422
3445
|
try {
|
|
3423
3446
|
if (!options.query) {
|
|
3424
|
-
|
|
3425
|
-
return;
|
|
3447
|
+
throw (0, errors_1.validationError)('--query is required');
|
|
3426
3448
|
}
|
|
3427
3449
|
const maxSources = parseInt(options.maxSources, 10);
|
|
3428
3450
|
if (isNaN(maxSources) || maxSources < 1) {
|
|
3429
|
-
|
|
3430
|
-
return;
|
|
3451
|
+
throw (0, errors_1.validationError)('--max-sources must be a positive integer');
|
|
3431
3452
|
}
|
|
3432
3453
|
const spinner = (0, spinner_1.createSpinner)('Generating status report...', options.format).start();
|
|
3433
3454
|
const body = {
|
|
@@ -3458,12 +3479,21 @@ function registerStatusCommand(memories) {
|
|
|
3458
3479
|
sdk.config.timeoutMs = prevTimeout;
|
|
3459
3480
|
}
|
|
3460
3481
|
const data = response.data;
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3482
|
+
// A 2xx with no body means the digest was never produced. Reporting it
|
|
3483
|
+
// as a soft failure and exiting 0 made an outage look like "nothing to
|
|
3484
|
+
// say" (v4.04).
|
|
3485
|
+
if (!data || !data.metadata) {
|
|
3486
|
+
spinner.stop();
|
|
3487
|
+
throw (0, errors_1.unusableResponseError)('Status report generation', responseShape(data));
|
|
3464
3488
|
}
|
|
3465
3489
|
const { digest, metadata, sources, keyFacts, entities, effectiveStateBreakdown } = data;
|
|
3466
|
-
|
|
3490
|
+
if (metadata.sourcesUsed === 0) {
|
|
3491
|
+
spinner.info('No sources met the relevance threshold for this query');
|
|
3492
|
+
}
|
|
3493
|
+
else {
|
|
3494
|
+
spinner.succeed(`Status report from ${metadata.sourcesUsed} memories across ${metadata.conversationsSpanned} conversations`);
|
|
3495
|
+
}
|
|
3496
|
+
printRetrievalCaveats(metadata, data.meta);
|
|
3467
3497
|
if (options.format === 'json' || options.format === 'yaml') {
|
|
3468
3498
|
(0, formatters_1.printOutput)(data, options.format);
|
|
3469
3499
|
return;
|
|
@@ -3479,6 +3509,68 @@ function registerStatusCommand(memories) {
|
|
|
3479
3509
|
}
|
|
3480
3510
|
});
|
|
3481
3511
|
}
|
|
3512
|
+
/**
|
|
3513
|
+
* Describe an unusable response body for the DEBUG-only details payload.
|
|
3514
|
+
*
|
|
3515
|
+
* Never pass the body itself: it can hold memory content and transcript text,
|
|
3516
|
+
* and DEBUG=1 stderr is collected by CI and agent harnesses. A shape summary
|
|
3517
|
+
* is what actually helps diagnosis — which keys came back, and what the data
|
|
3518
|
+
* field was.
|
|
3519
|
+
*/
|
|
3520
|
+
function responseShape(body) {
|
|
3521
|
+
const keys = body && typeof body === 'object' && !Array.isArray(body) ? Object.keys(body) : [];
|
|
3522
|
+
const data = body?.data;
|
|
3523
|
+
const dataType = Array.isArray(data) ? 'array' : data === null ? 'null' : typeof data;
|
|
3524
|
+
return { responseKeys: keys, dataType };
|
|
3525
|
+
}
|
|
3526
|
+
/**
|
|
3527
|
+
* Surface retrieval-quality caveats that travel with a digest/status response.
|
|
3528
|
+
*
|
|
3529
|
+
* The server sets these when it fell back to weak or heterogeneous matches
|
|
3530
|
+
* (core-api/src/schemas/digest.schema.ts — "Consumers should surface a warning
|
|
3531
|
+
* to the calling agent"). Without them a loosely-related digest reads exactly
|
|
3532
|
+
* like a well-matched one.
|
|
3533
|
+
*
|
|
3534
|
+
* Caveats go to STDERR so they reach the caller in every output format,
|
|
3535
|
+
* including `--format json`, where the digest body must remain the only
|
|
3536
|
+
* top-level JSON on stdout.
|
|
3537
|
+
*
|
|
3538
|
+
* @param metadata - DigestMetadata from the response
|
|
3539
|
+
* @param meta - Optional response-level meta (forward-compat, see below)
|
|
3540
|
+
*/
|
|
3541
|
+
function printRetrievalCaveats(metadata, meta) {
|
|
3542
|
+
const avg = typeof metadata?.averageRelevance === 'number' ? metadata.averageRelevance : null;
|
|
3543
|
+
const avgLabel = avg === null ? 'unknown' : avg.toFixed(3);
|
|
3544
|
+
if (metadata?.narrowWindowFallback) {
|
|
3545
|
+
console.error(chalk_1.default.yellow(`⚠ Low-relevance results: average relevance ${avgLabel} is below the confidence ` +
|
|
3546
|
+
'threshold — this digest was synthesised from weak matches and may be only ' +
|
|
3547
|
+
'loosely related to your query.'));
|
|
3548
|
+
}
|
|
3549
|
+
if (metadata?.crossProjectFallback) {
|
|
3550
|
+
console.error(chalk_1.default.yellow(`⚠ Cross-project results: average relevance ${avgLabel} is below the confidence ` +
|
|
3551
|
+
'threshold and the sources span more than one project — this content may come ' +
|
|
3552
|
+
'from a different project than the one you are working in.'));
|
|
3553
|
+
}
|
|
3554
|
+
// Forward-compat with the retrieval team's degraded-retrieval contract
|
|
3555
|
+
// (meta.degraded / meta.branchFailures). Both fields are absent on today's
|
|
3556
|
+
// responses, so every access is guarded.
|
|
3557
|
+
if (meta?.degraded) {
|
|
3558
|
+
const failures = Array.isArray(meta.branchFailures) ? meta.branchFailures : [];
|
|
3559
|
+
// Branch names are server-supplied and land on stderr, which agents read.
|
|
3560
|
+
// Constrain them to an identifier shape and cap the count rather than
|
|
3561
|
+
// echoing arbitrary text: an unbounded string here is an injection channel
|
|
3562
|
+
// into agent context (and can carry ANSI escapes from a hostile apiUrl).
|
|
3563
|
+
const names = failures
|
|
3564
|
+
.map((b) => (typeof b === 'string' ? b : b?.branch || b?.name))
|
|
3565
|
+
.filter((n) => typeof n === 'string' && /^[A-Za-z0-9_-]{1,32}$/.test(n))
|
|
3566
|
+
.slice(0, 8);
|
|
3567
|
+
const detail = names.length
|
|
3568
|
+
? `failed branches: ${names.join(', ')}`
|
|
3569
|
+
: 'one or more retrieval branches failed';
|
|
3570
|
+
console.error(chalk_1.default.yellow(`⚠ Degraded retrieval — ${detail}. These results are incomplete; re-run before ` +
|
|
3571
|
+
'treating them as a full answer.'));
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3482
3574
|
/**
|
|
3483
3575
|
* Display a formatted digest with header box and metadata footer
|
|
3484
3576
|
*/
|
|
@@ -3570,9 +3662,8 @@ function registerRecapCommand(memories) {
|
|
|
3570
3662
|
// Calculate time filter
|
|
3571
3663
|
const recentTimestamp = (0, date_utils_1.getRecentTimestamp)(options.recent);
|
|
3572
3664
|
if (!recentTimestamp) {
|
|
3573
|
-
spinner.
|
|
3574
|
-
|
|
3575
|
-
return;
|
|
3665
|
+
spinner.stop();
|
|
3666
|
+
throw (0, errors_1.validationError)(`Invalid duration format: ${options.recent}. Supported formats: 30m, 1h, 7d, 2w`);
|
|
3576
3667
|
}
|
|
3577
3668
|
const fetchLimit = parseInt(options.limit, 10);
|
|
3578
3669
|
// Build exclude-topics value (used by both paths)
|
|
@@ -3852,10 +3943,15 @@ function registerBuildContextCommand(memories) {
|
|
|
3852
3943
|
}
|
|
3853
3944
|
const sdk = (0, api_client_1.getSdk)();
|
|
3854
3945
|
const response = await retryRead(() => sdk.memories.buildContext(body));
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3946
|
+
// `|| response` used to make the guard below unreachable: on a 2xx with
|
|
3947
|
+
// an empty body it fell back to the truthy response envelope, so the
|
|
3948
|
+
// command printed "Context briefing ready" and an empty briefing (exit
|
|
3949
|
+
// 0). Unwrap first, then test what we actually got (v4.04).
|
|
3950
|
+
const envelope = response;
|
|
3951
|
+
const data = envelope && typeof envelope === 'object' && 'data' in envelope ? envelope.data : envelope;
|
|
3952
|
+
if (!data || typeof data !== 'object') {
|
|
3953
|
+
spinner.stop();
|
|
3954
|
+
throw (0, errors_1.unusableResponseError)('Context briefing', responseShape(data));
|
|
3859
3955
|
}
|
|
3860
3956
|
spinner.succeed('Context briefing ready');
|
|
3861
3957
|
// JSON output
|
|
@@ -3937,8 +4033,7 @@ function registerBuildContextCommand(memories) {
|
|
|
3937
4033
|
try {
|
|
3938
4034
|
const validDimensions = ['day', 'week', 'month', 'topic'];
|
|
3939
4035
|
if (!options.groupBy || !validDimensions.includes(options.groupBy)) {
|
|
3940
|
-
|
|
3941
|
-
return;
|
|
4036
|
+
throw (0, errors_1.validationError)('--group-by is required and must be one of: day, week, month, topic');
|
|
3942
4037
|
}
|
|
3943
4038
|
const spinner = (0, spinner_1.createSpinner)('Fetching memory stats...', options.format).start();
|
|
3944
4039
|
const apiUrl = config_1.config.getApiUrl();
|