agentdb 3.2.0 → 3.3.0
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/src/controllers/ReasoningBank.d.ts +36 -0
- package/dist/src/controllers/ReasoningBank.d.ts.map +1 -1
- package/dist/src/controllers/ReasoningBank.js +123 -1
- package/dist/src/controllers/ReasoningBank.js.map +1 -1
- package/dist/src/controllers/ReflexionMemory.d.ts +55 -0
- package/dist/src/controllers/ReflexionMemory.d.ts.map +1 -1
- package/dist/src/controllers/ReflexionMemory.js +209 -5
- package/dist/src/controllers/ReflexionMemory.js.map +1 -1
- package/dist/src/controllers/SkillLibrary.d.ts +50 -0
- package/dist/src/controllers/SkillLibrary.d.ts.map +1 -1
- package/dist/src/controllers/SkillLibrary.js +220 -9
- package/dist/src/controllers/SkillLibrary.js.map +1 -1
- package/dist/src/controllers/crud-helpers.d.ts +45 -0
- package/dist/src/controllers/crud-helpers.d.ts.map +1 -0
- package/dist/src/controllers/crud-helpers.js +130 -0
- package/dist/src/controllers/crud-helpers.js.map +1 -0
- package/dist/src/controllers/episode-hybrid.d.ts +19 -0
- package/dist/src/controllers/episode-hybrid.d.ts.map +1 -1
- package/dist/src/controllers/episode-hybrid.js +23 -0
- package/dist/src/controllers/episode-hybrid.js.map +1 -1
- package/dist/src/mcp/agentdb-mcp-server.js +367 -45
- package/dist/src/mcp/agentdb-mcp-server.js.map +1 -1
- package/dist/src/search/conversation-retrieval.d.ts +5 -0
- package/dist/src/search/conversation-retrieval.d.ts.map +1 -1
- package/dist/src/search/conversation-retrieval.js +29 -0
- package/dist/src/search/conversation-retrieval.js.map +1 -1
- package/dist/src/security/mcp-policy.d.ts.map +1 -1
- package/dist/src/security/mcp-policy.js +13 -0
- package/dist/src/security/mcp-policy.js.map +1 -1
- package/package.json +5 -3
|
@@ -60,6 +60,29 @@ export class EpisodeLexicalIndex {
|
|
|
60
60
|
this.count = count;
|
|
61
61
|
this.maxId = maxId;
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Apply an in-place edit of one episode without a rebuild. `before` must be the row as it was indexed.
|
|
65
|
+
* A no-op when the index is not built yet (the next search builds it from current rows) or the episode
|
|
66
|
+
* is outside the indexed window.
|
|
67
|
+
*/
|
|
68
|
+
update(before, after) {
|
|
69
|
+
if (!this.index)
|
|
70
|
+
return;
|
|
71
|
+
const doc = this.ids.indexOf(before.id);
|
|
72
|
+
if (doc < 0)
|
|
73
|
+
return;
|
|
74
|
+
this.index.replace(doc, EpisodeLexicalIndex.textOf(before), EpisodeLexicalIndex.textOf(after));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Force a full rebuild on the next search. Needed after an in-place edit: an UPDATE changes
|
|
78
|
+
* neither COUNT(*) nor MAX(id), so refresh() alone would keep serving the old text.
|
|
79
|
+
*/
|
|
80
|
+
invalidate() {
|
|
81
|
+
this.index = null;
|
|
82
|
+
this.ids = [];
|
|
83
|
+
this.count = -1;
|
|
84
|
+
this.maxId = 0;
|
|
85
|
+
}
|
|
63
86
|
/** Episode ids with a BM25 match, best first, at most `limit`. */
|
|
64
87
|
search(query, limit) {
|
|
65
88
|
this.refresh();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"episode-hybrid.js","sourceRoot":"","sources":["../../../src/controllers/episode-hybrid.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;AAE1G,SAAS,QAAQ,CAAC,GAAuB,EAAE,QAAgB,EAAE,GAAW,EAAE,GAAW;IACnF,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtE,CAAC;AACD,8DAA8D;AAC9D,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,CAAC;AACnC,6GAA6G;AAC7G,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AACvC,MAAM,KAAK,GAAG,EAAE,CAAC;AAUjB;;;GAGG;AACH,MAAM,OAAO,mBAAmB;IAOX;IACA;IAPX,KAAK,GAAG,CAAC,CAAC,CAAC;IACX,KAAK,GAAG,CAAC,CAAC;IACV,GAAG,GAAa,EAAE,CAAC;IACnB,KAAK,GAAqB,IAAI,CAAC;IAEvC,YACmB,EAAuB,EACvB,UAAU,kBAAkB;QAD5B,OAAE,GAAF,EAAE,CAAqB;QACvB,YAAO,GAAP,OAAO,CAAqB;IAC5C,CAAC;IAEI,MAAM,CAAC,MAAM,CAAC,CAAiB;QACrC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACtF,CAAC;IAEO,OAAO;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAkC,kDAAkD,CAAC,CAAC,GAAG,EAAE,CAAC;QACvH,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK;YAAE,OAAO;QACvE,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;YACpG,MAAM,KAAK,GAAG,IAAI,CAAC,EAAE;iBAClB,OAAO,CAAiB,qFAAqF,CAAC;iBAC9G,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,IAAI,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBACxC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;oBACtB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC9C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACtB,CAAC;gBACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;gBACnB,OAAO;YACT,CAAC;QACH,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE;aACjB,OAAO,CAAiB,iFAAiF,CAAC;aAC1G,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,kEAAkE;IAClE,MAAM,CAAC,KAAa,EAAE,KAAa;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QACtD,MAAM,IAAI,GAAoC,EAAE,CAAC;QACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,IAAI,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5G,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAA2B,EAAE,OAAkC,EAAE,aAAa,GAAG,qBAAqB;IACtI,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IACtC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;QACtD,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,GAAG,aAAa,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,KAAkC,EAAE,WAA8B,EAAE;IAC/F,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;SACxB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3G,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;AACvB,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,mBAAmB,CAAC,QAA2B,EAAE,OAAkC,EAAE,aAAa,GAAG,qBAAqB;IACxI,OAAO,YAAY,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,QAAQ,CAAC,CAAC;AACrF,CAAC;AAED,6HAA6H;AAC7H,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC;AAC/B,uFAAuF;AACvF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAE/B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,KAA0B,EAC1B,UAA6B,EAC7B,MAA0C,EAC1C,KAAc;IAEd,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,MAAM,EAAE,GAAG,MAAM,kBAAkB,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACzE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,GAAG,aAAa,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAClG,CAAC"}
|
|
1
|
+
{"version":3,"file":"episode-hybrid.js","sourceRoot":"","sources":["../../../src/controllers/episode-hybrid.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,8 @@ import { EmbeddingService } from '../controllers/EmbeddingService.js';
|
|
|
22
22
|
import { BatchOperations } from '../optimizations/BatchOperations.js';
|
|
23
23
|
import { ReasoningBank } from '../controllers/ReasoningBank.js';
|
|
24
24
|
import { MCPToolCaches } from '../optimizations/ToolCache.js';
|
|
25
|
-
import { validateId, validateTimestamp, validateSessionId, validateTaskString, validateNumericRange, validateArrayLength, validateBoolean, validateEnum, ValidationError, handleSecurityError, } from '../security/input-validation.js';
|
|
25
|
+
import { validateId, validateTimestamp, validateSessionId, validateTaskString, validateNumericRange, validateArrayLength, validateBoolean, validateEnum, ValidationError, handleSecurityError, sanitizeText, } from '../security/input-validation.js';
|
|
26
|
+
import { assertMetadata, assertTags, inTransaction, toRecordId, CrudValidationError } from '../controllers/crud-helpers.js';
|
|
26
27
|
import * as path from 'path';
|
|
27
28
|
import * as fs from 'fs';
|
|
28
29
|
import { fileURLToPath } from 'url';
|
|
@@ -408,6 +409,141 @@ const tools = [
|
|
|
408
409
|
// ==========================================================================
|
|
409
410
|
// FRONTIER MEMORY FEATURES (EXISTING)
|
|
410
411
|
// ==========================================================================
|
|
412
|
+
{
|
|
413
|
+
name: 'agentdb_get',
|
|
414
|
+
description: 'Get one stored vector record (episode) by id. Returns null when it does not exist. The embedding is omitted unless include_embedding is true.',
|
|
415
|
+
inputSchema: {
|
|
416
|
+
type: 'object',
|
|
417
|
+
properties: {
|
|
418
|
+
id: { type: 'number', description: 'Record id returned by agentdb_insert' },
|
|
419
|
+
include_embedding: { type: 'boolean', description: 'Also return the stored embedding vector', default: false },
|
|
420
|
+
},
|
|
421
|
+
required: ['id'],
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: 'agentdb_list',
|
|
426
|
+
description: 'Page through stored vector records (episodes), newest first. Returns items plus the total count.',
|
|
427
|
+
inputSchema: {
|
|
428
|
+
type: 'object',
|
|
429
|
+
properties: {
|
|
430
|
+
session_id: { type: 'string', description: 'Only records from this session' },
|
|
431
|
+
limit: { type: 'number', description: 'Page size (1-500)', default: 50 },
|
|
432
|
+
offset: { type: 'number', description: 'Records to skip', default: 0 },
|
|
433
|
+
order: { type: 'string', enum: ['newest', 'oldest'], default: 'newest' },
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
name: 'agentdb_update',
|
|
439
|
+
description: 'Update a stored vector record in place, keeping its id. Changing text re-embeds it and refreshes the keyword index; tag or metadata changes do not re-embed. Metadata is merged (null removes a key) unless replace_metadata is true.',
|
|
440
|
+
inputSchema: {
|
|
441
|
+
type: 'object',
|
|
442
|
+
properties: {
|
|
443
|
+
id: { type: 'number', description: 'Record id' },
|
|
444
|
+
text: { type: 'string', description: 'New text content (re-embedded)' },
|
|
445
|
+
tags: { type: 'array', items: { type: 'string' }, description: 'Replacement tag list' },
|
|
446
|
+
metadata: { type: 'object', description: 'Metadata patch (merged by default)' },
|
|
447
|
+
replace_metadata: { type: 'boolean', description: 'Replace metadata instead of merging', default: false },
|
|
448
|
+
reward: { type: 'number', description: 'New reward value' },
|
|
449
|
+
success: { type: 'boolean', description: 'New success flag' },
|
|
450
|
+
},
|
|
451
|
+
required: ['id'],
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
name: 'agentdb_pattern_get',
|
|
456
|
+
description: 'Get one reasoning pattern by id.',
|
|
457
|
+
inputSchema: {
|
|
458
|
+
type: 'object',
|
|
459
|
+
properties: { pattern_id: { type: 'number', description: 'Pattern id' } },
|
|
460
|
+
required: ['pattern_id'],
|
|
461
|
+
},
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
name: 'agentdb_pattern_list',
|
|
465
|
+
description: 'Page through reasoning patterns, newest first, optionally filtered by task type.',
|
|
466
|
+
inputSchema: {
|
|
467
|
+
type: 'object',
|
|
468
|
+
properties: {
|
|
469
|
+
task_type: { type: 'string', description: 'Only patterns of this task type' },
|
|
470
|
+
limit: { type: 'number', default: 50 },
|
|
471
|
+
offset: { type: 'number', default: 0 },
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
name: 'agentdb_pattern_update',
|
|
477
|
+
description: 'Update a reasoning pattern in place. Changing taskType or approach re-embeds it. Usage statistics are not writable here (use agentdb_pattern_feedback).',
|
|
478
|
+
inputSchema: {
|
|
479
|
+
type: 'object',
|
|
480
|
+
properties: {
|
|
481
|
+
pattern_id: { type: 'number', description: 'Pattern id' },
|
|
482
|
+
taskType: { type: 'string' },
|
|
483
|
+
approach: { type: 'string' },
|
|
484
|
+
tags: { type: 'array', items: { type: 'string' } },
|
|
485
|
+
metadata: { type: 'object', description: 'Metadata patch (merged by default)' },
|
|
486
|
+
replace_metadata: { type: 'boolean', default: false },
|
|
487
|
+
},
|
|
488
|
+
required: ['pattern_id'],
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
name: 'agentdb_pattern_delete',
|
|
493
|
+
description: 'Delete a reasoning pattern, its embedding and its vector-index entry.',
|
|
494
|
+
inputSchema: {
|
|
495
|
+
type: 'object',
|
|
496
|
+
properties: { pattern_id: { type: 'number', description: 'Pattern id' } },
|
|
497
|
+
required: ['pattern_id'],
|
|
498
|
+
},
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
name: 'skill_get',
|
|
502
|
+
description: 'Get one skill by id.',
|
|
503
|
+
inputSchema: {
|
|
504
|
+
type: 'object',
|
|
505
|
+
properties: { skill_id: { type: 'number', description: 'Skill id' } },
|
|
506
|
+
required: ['skill_id'],
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
name: 'skill_list',
|
|
511
|
+
description: 'Page through skills, newest first.',
|
|
512
|
+
inputSchema: {
|
|
513
|
+
type: 'object',
|
|
514
|
+
properties: {
|
|
515
|
+
min_success_rate: { type: 'number', description: 'Only skills at or above this success rate' },
|
|
516
|
+
limit: { type: 'number', default: 50 },
|
|
517
|
+
offset: { type: 'number', default: 0 },
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
name: 'skill_update',
|
|
523
|
+
description: 'Update a skill in place. Changing name, description or signature re-embeds it; renaming onto an existing name is rejected. Usage statistics are not writable here (use agentdb_skill_feedback).',
|
|
524
|
+
inputSchema: {
|
|
525
|
+
type: 'object',
|
|
526
|
+
properties: {
|
|
527
|
+
skill_id: { type: 'number', description: 'Skill id' },
|
|
528
|
+
name: { type: 'string' },
|
|
529
|
+
description: { type: 'string' },
|
|
530
|
+
code: { type: 'string' },
|
|
531
|
+
signature: { type: 'object', description: '{ inputs: {...}, outputs: {...} }' },
|
|
532
|
+
metadata: { type: 'object', description: 'Metadata patch (merged by default)' },
|
|
533
|
+
replace_metadata: { type: 'boolean', default: false },
|
|
534
|
+
},
|
|
535
|
+
required: ['skill_id'],
|
|
536
|
+
},
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
name: 'skill_delete',
|
|
540
|
+
description: 'Delete a skill with its embedding, links and vector-index entry.',
|
|
541
|
+
inputSchema: {
|
|
542
|
+
type: 'object',
|
|
543
|
+
properties: { skill_id: { type: 'number', description: 'Skill id' } },
|
|
544
|
+
required: ['skill_id'],
|
|
545
|
+
},
|
|
546
|
+
},
|
|
411
547
|
{
|
|
412
548
|
name: 'reflexion_store',
|
|
413
549
|
description: 'Store an episode with self-critique for reflexion-based learning',
|
|
@@ -974,6 +1110,157 @@ const tools = [
|
|
|
974
1110
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
975
1111
|
return { tools: filterMcpTools(tools, toolPolicy) };
|
|
976
1112
|
});
|
|
1113
|
+
/** Bulk-delete episodes together with their embeddings (FK cascades are off by default). */
|
|
1114
|
+
function deleteEpisodesWhere(condition, value) {
|
|
1115
|
+
const changes = inTransaction(db, () => {
|
|
1116
|
+
db.prepare(`DELETE FROM episode_embeddings WHERE episode_id IN (SELECT id FROM episodes WHERE ${condition})`).run(value);
|
|
1117
|
+
return db.prepare(`DELETE FROM episodes WHERE ${condition}`).run(value).changes;
|
|
1118
|
+
});
|
|
1119
|
+
if (changes > 0) {
|
|
1120
|
+
reflexion.clearCache();
|
|
1121
|
+
caches.stats.clear();
|
|
1122
|
+
}
|
|
1123
|
+
return changes;
|
|
1124
|
+
}
|
|
1125
|
+
/** Reject arguments a tool does not define, so a typo can never silently become a no-op update. */
|
|
1126
|
+
function rejectUnknownArgs(args, allowed, tool) {
|
|
1127
|
+
for (const key of Object.keys(args)) {
|
|
1128
|
+
if (!allowed.includes(key))
|
|
1129
|
+
throw new CrudValidationError(`${tool} does not accept "${key}"`, key);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
function optionalString(value, field, maxLength = 100_000) {
|
|
1133
|
+
if (value === undefined)
|
|
1134
|
+
return undefined;
|
|
1135
|
+
if (typeof value !== 'string')
|
|
1136
|
+
throw new CrudValidationError(`${field} must be a string`, field);
|
|
1137
|
+
if (value.length > maxLength)
|
|
1138
|
+
throw new CrudValidationError(`${field} exceeds ${maxLength} characters`, field);
|
|
1139
|
+
return value;
|
|
1140
|
+
}
|
|
1141
|
+
/** Dispatch for the ADR-017 CRUD tools. Returns a JSON-serialisable result. */
|
|
1142
|
+
async function handleCrudTool(name, args) {
|
|
1143
|
+
switch (name) {
|
|
1144
|
+
case 'agentdb_get': {
|
|
1145
|
+
rejectUnknownArgs(args, ['id', 'include_embedding'], name);
|
|
1146
|
+
const episode = reflexion.getEpisode(toRecordId(args.id), { includeEmbedding: args.include_embedding === true });
|
|
1147
|
+
if (!episode)
|
|
1148
|
+
return null;
|
|
1149
|
+
const { embedding, ...rest } = episode;
|
|
1150
|
+
return embedding ? { ...rest, embedding: Array.from(embedding) } : rest;
|
|
1151
|
+
}
|
|
1152
|
+
case 'agentdb_list': {
|
|
1153
|
+
rejectUnknownArgs(args, ['session_id', 'limit', 'offset', 'order'], name);
|
|
1154
|
+
const order = args.order === undefined ? 'newest' : validateEnum(args.order, 'order', ['newest', 'oldest']);
|
|
1155
|
+
return reflexion.listEpisodes({
|
|
1156
|
+
sessionId: args.session_id === undefined ? undefined : validateSessionId(args.session_id),
|
|
1157
|
+
limit: args.limit,
|
|
1158
|
+
offset: args.offset,
|
|
1159
|
+
order,
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
case 'agentdb_update': {
|
|
1163
|
+
rejectUnknownArgs(args, ['id', 'text', 'tags', 'metadata', 'replace_metadata', 'reward', 'success'], name);
|
|
1164
|
+
// agentdb_insert stores the text as both task and input, so an update keeps them in step.
|
|
1165
|
+
const text = args.text === undefined ? undefined : requireText(args.text, 'text');
|
|
1166
|
+
const result = await reflexion.updateEpisode(toRecordId(args.id), {
|
|
1167
|
+
task: text,
|
|
1168
|
+
input: text,
|
|
1169
|
+
tags: args.tags === undefined ? undefined : assertTags(args.tags),
|
|
1170
|
+
metadata: args.metadata === undefined ? undefined : assertMetadata(args.metadata),
|
|
1171
|
+
reward: args.reward === undefined ? undefined : validateNumericRange(args.reward, 'reward', -1e6, 1e6),
|
|
1172
|
+
success: args.success === undefined ? undefined : validateBoolean(args.success, 'success'),
|
|
1173
|
+
}, { replaceMetadata: args.replace_metadata === true });
|
|
1174
|
+
if (result)
|
|
1175
|
+
caches.stats.clear();
|
|
1176
|
+
return result ? { updated: true, ...result } : { updated: false, reason: 'not found' };
|
|
1177
|
+
}
|
|
1178
|
+
case 'agentdb_pattern_get': {
|
|
1179
|
+
rejectUnknownArgs(args, ['pattern_id'], name);
|
|
1180
|
+
const pattern = reasoningBank.getPattern(toRecordId(args.pattern_id, 'pattern_id'));
|
|
1181
|
+
if (!pattern)
|
|
1182
|
+
return null;
|
|
1183
|
+
const { embedding: _omit, ...rest } = pattern;
|
|
1184
|
+
return rest;
|
|
1185
|
+
}
|
|
1186
|
+
case 'agentdb_pattern_list': {
|
|
1187
|
+
rejectUnknownArgs(args, ['task_type', 'limit', 'offset'], name);
|
|
1188
|
+
return reasoningBank.listPatterns({
|
|
1189
|
+
taskType: optionalString(args.task_type, 'task_type', 1000),
|
|
1190
|
+
limit: args.limit,
|
|
1191
|
+
offset: args.offset,
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
case 'agentdb_pattern_update': {
|
|
1195
|
+
rejectUnknownArgs(args, ['pattern_id', 'taskType', 'approach', 'tags', 'metadata', 'replace_metadata'], name);
|
|
1196
|
+
const result = await reasoningBank.updatePattern(toRecordId(args.pattern_id, 'pattern_id'), {
|
|
1197
|
+
taskType: args.taskType === undefined ? undefined : requireText(args.taskType, 'taskType'),
|
|
1198
|
+
approach: args.approach === undefined ? undefined : requireText(args.approach, 'approach'),
|
|
1199
|
+
tags: args.tags === undefined ? undefined : assertTags(args.tags),
|
|
1200
|
+
metadata: args.metadata === undefined ? undefined : assertMetadata(args.metadata),
|
|
1201
|
+
}, { replaceMetadata: args.replace_metadata === true });
|
|
1202
|
+
if (result) {
|
|
1203
|
+
caches.patterns.clear();
|
|
1204
|
+
caches.stats.clear();
|
|
1205
|
+
}
|
|
1206
|
+
if (!result)
|
|
1207
|
+
return { updated: false, reason: 'not found' };
|
|
1208
|
+
const { embedding: _omit, ...pattern } = result.pattern;
|
|
1209
|
+
return { updated: true, ...result, pattern };
|
|
1210
|
+
}
|
|
1211
|
+
case 'agentdb_pattern_delete': {
|
|
1212
|
+
rejectUnknownArgs(args, ['pattern_id'], name);
|
|
1213
|
+
const deleted = reasoningBank.deletePattern(toRecordId(args.pattern_id, 'pattern_id'));
|
|
1214
|
+
if (deleted) {
|
|
1215
|
+
caches.patterns.clear();
|
|
1216
|
+
caches.stats.clear();
|
|
1217
|
+
}
|
|
1218
|
+
return { deleted };
|
|
1219
|
+
}
|
|
1220
|
+
case 'skill_get': {
|
|
1221
|
+
rejectUnknownArgs(args, ['skill_id'], name);
|
|
1222
|
+
return skills.getSkill(toRecordId(args.skill_id, 'skill_id'));
|
|
1223
|
+
}
|
|
1224
|
+
case 'skill_list': {
|
|
1225
|
+
rejectUnknownArgs(args, ['min_success_rate', 'limit', 'offset'], name);
|
|
1226
|
+
return skills.listSkills({
|
|
1227
|
+
minSuccessRate: args.min_success_rate === undefined ? undefined : validateNumericRange(args.min_success_rate, 'min_success_rate', 0, 1),
|
|
1228
|
+
limit: args.limit,
|
|
1229
|
+
offset: args.offset,
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
case 'skill_update': {
|
|
1233
|
+
rejectUnknownArgs(args, ['skill_id', 'name', 'description', 'code', 'signature', 'metadata', 'replace_metadata'], name);
|
|
1234
|
+
const result = await skills.updateSkill(toRecordId(args.skill_id, 'skill_id'), {
|
|
1235
|
+
name: args.name === undefined ? undefined : requireText(args.name, 'name'),
|
|
1236
|
+
description: args.description === undefined ? undefined : requireText(args.description, 'description'),
|
|
1237
|
+
code: optionalString(args.code, 'code'),
|
|
1238
|
+
signature: args.signature === undefined ? undefined
|
|
1239
|
+
: assertMetadata(args.signature, 'signature'),
|
|
1240
|
+
metadata: args.metadata === undefined ? undefined : assertMetadata(args.metadata),
|
|
1241
|
+
}, { replaceMetadata: args.replace_metadata === true });
|
|
1242
|
+
if (result)
|
|
1243
|
+
caches.stats.clear();
|
|
1244
|
+
return result ? { updated: true, ...result } : { updated: false, reason: 'not found' };
|
|
1245
|
+
}
|
|
1246
|
+
case 'skill_delete': {
|
|
1247
|
+
rejectUnknownArgs(args, ['skill_id'], name);
|
|
1248
|
+
const deleted = skills.deleteSkill(toRecordId(args.skill_id, 'skill_id'));
|
|
1249
|
+
if (deleted)
|
|
1250
|
+
caches.stats.clear();
|
|
1251
|
+
return { deleted };
|
|
1252
|
+
}
|
|
1253
|
+
default:
|
|
1254
|
+
throw new CrudValidationError(`unknown CRUD tool ${name}`, 'name');
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
/** Non-empty text up to `maxLength`, null bytes stripped. Deliberately no content heuristics: stored text may be code. */
|
|
1258
|
+
function requireText(value, field, maxLength = 100_000) {
|
|
1259
|
+
const text = sanitizeText(value, maxLength, field);
|
|
1260
|
+
if (!text.trim())
|
|
1261
|
+
throw new CrudValidationError(`${field} cannot be empty`, field);
|
|
1262
|
+
return text;
|
|
1263
|
+
}
|
|
977
1264
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
978
1265
|
const { name, arguments: args } = request.params;
|
|
979
1266
|
try {
|
|
@@ -991,7 +1278,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
991
1278
|
}
|
|
992
1279
|
// Initialize schema
|
|
993
1280
|
initializeSchema(db);
|
|
994
|
-
const stats = db.prepare(
|
|
1281
|
+
const stats = db.prepare("SELECT COUNT(*) as count FROM sqlite_master WHERE type = 'table'").get();
|
|
995
1282
|
return {
|
|
996
1283
|
content: [
|
|
997
1284
|
{
|
|
@@ -1006,10 +1293,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1006
1293
|
};
|
|
1007
1294
|
}
|
|
1008
1295
|
case 'agentdb_insert': {
|
|
1009
|
-
const text = args?.text;
|
|
1010
|
-
const sessionId = args?.session_id
|
|
1011
|
-
const tags = args?.tags
|
|
1012
|
-
const metadata = args?.metadata
|
|
1296
|
+
const text = requireText(args?.text, 'text');
|
|
1297
|
+
const sessionId = args?.session_id === undefined ? 'default' : validateSessionId(args.session_id);
|
|
1298
|
+
const tags = args?.tags === undefined ? [] : assertTags(args.tags);
|
|
1299
|
+
const metadata = args?.metadata === undefined ? {} : assertMetadata(args.metadata);
|
|
1013
1300
|
const episodeId = await reflexion.storeEpisode({
|
|
1014
1301
|
sessionId,
|
|
1015
1302
|
task: text,
|
|
@@ -1039,19 +1326,24 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1039
1326
|
case 'agentdb_insert_batch': {
|
|
1040
1327
|
const items = validateArrayLength(args?.items ?? [], 'items', 0, MAX_INSERT_BATCH_ITEMS);
|
|
1041
1328
|
const batchSize = args?.batch_size || 100;
|
|
1042
|
-
const episodes = items.map((item) =>
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1329
|
+
const episodes = items.map((item, i) => {
|
|
1330
|
+
if (!item || typeof item !== 'object')
|
|
1331
|
+
throw new ValidationError(`items[${i}] must be an object`, 'INVALID_TYPE', 'items');
|
|
1332
|
+
const text = requireText(item.text, `items[${i}].text`);
|
|
1333
|
+
return {
|
|
1334
|
+
sessionId: item.session_id === undefined ? 'default' : validateSessionId(item.session_id),
|
|
1335
|
+
task: text,
|
|
1336
|
+
reward: 1.0,
|
|
1337
|
+
success: true,
|
|
1338
|
+
input: text,
|
|
1339
|
+
output: '',
|
|
1340
|
+
critique: '',
|
|
1341
|
+
latencyMs: 0,
|
|
1342
|
+
tokensUsed: 0,
|
|
1343
|
+
tags: item.tags === undefined ? [] : assertTags(item.tags, `items[${i}].tags`),
|
|
1344
|
+
metadata: item.metadata === undefined ? {} : assertMetadata(item.metadata, `items[${i}].metadata`),
|
|
1345
|
+
};
|
|
1346
|
+
});
|
|
1055
1347
|
const batchOpsConfig = new BatchOperations(db, embeddingService, {
|
|
1056
1348
|
batchSize,
|
|
1057
1349
|
parallelism: 4,
|
|
@@ -1117,10 +1409,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1117
1409
|
if (id !== undefined) {
|
|
1118
1410
|
// Validate ID
|
|
1119
1411
|
const validatedId = validateId(id, 'id');
|
|
1120
|
-
//
|
|
1121
|
-
|
|
1122
|
-
const result = stmt.run(validatedId);
|
|
1123
|
-
deleted = result.changes;
|
|
1412
|
+
// Through the controller so the embedding, vector index and caches go with the row
|
|
1413
|
+
deleted = (await reflexion.deleteEpisode(validatedId)) ? 1 : 0;
|
|
1124
1414
|
}
|
|
1125
1415
|
else if (filters) {
|
|
1126
1416
|
// Bulk delete with validated filters
|
|
@@ -1128,17 +1418,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1128
1418
|
// Validate session_id
|
|
1129
1419
|
const validatedSessionId = validateSessionId(filters.session_id);
|
|
1130
1420
|
// Use parameterized query
|
|
1131
|
-
|
|
1132
|
-
const result = stmt.run(validatedSessionId);
|
|
1133
|
-
deleted = result.changes;
|
|
1421
|
+
deleted = deleteEpisodesWhere('session_id = ?', validatedSessionId);
|
|
1134
1422
|
}
|
|
1135
1423
|
else if (filters.before_timestamp) {
|
|
1136
1424
|
// Validate timestamp
|
|
1137
1425
|
const validatedTimestamp = validateTimestamp(filters.before_timestamp, 'before_timestamp');
|
|
1138
1426
|
// Use parameterized query
|
|
1139
|
-
|
|
1140
|
-
const result = stmt.run(validatedTimestamp);
|
|
1141
|
-
deleted = result.changes;
|
|
1427
|
+
deleted = deleteEpisodesWhere('ts < ?', validatedTimestamp);
|
|
1142
1428
|
}
|
|
1143
1429
|
else {
|
|
1144
1430
|
throw new ValidationError('Invalid or missing filter criteria', 'INVALID_FILTER');
|
|
@@ -1172,6 +1458,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1172
1458
|
}
|
|
1173
1459
|
}
|
|
1174
1460
|
// ======================================================================
|
|
1461
|
+
// CRUD: get / list / update / delete (ADR-017)
|
|
1462
|
+
// ======================================================================
|
|
1463
|
+
case 'agentdb_get':
|
|
1464
|
+
case 'agentdb_list':
|
|
1465
|
+
case 'agentdb_update':
|
|
1466
|
+
case 'agentdb_pattern_get':
|
|
1467
|
+
case 'agentdb_pattern_list':
|
|
1468
|
+
case 'agentdb_pattern_update':
|
|
1469
|
+
case 'agentdb_pattern_delete':
|
|
1470
|
+
case 'skill_get':
|
|
1471
|
+
case 'skill_list':
|
|
1472
|
+
case 'skill_update':
|
|
1473
|
+
case 'skill_delete': {
|
|
1474
|
+
try {
|
|
1475
|
+
const result = await handleCrudTool(name, (args ?? {}));
|
|
1476
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
1477
|
+
}
|
|
1478
|
+
catch (error) {
|
|
1479
|
+
const message = error instanceof CrudValidationError ? error.message : handleSecurityError(error);
|
|
1480
|
+
return { content: [{ type: 'text', text: `❌ ${name} failed: ${message}` }], isError: true };
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
// ======================================================================
|
|
1175
1484
|
// FRONTIER MEMORY FEATURES (EXISTING)
|
|
1176
1485
|
// ======================================================================
|
|
1177
1486
|
case 'reflexion_store': {
|
|
@@ -2277,30 +2586,40 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2277
2586
|
};
|
|
2278
2587
|
}
|
|
2279
2588
|
case 'agentdb_delete_batch': {
|
|
2280
|
-
const ids = args?.ids
|
|
2589
|
+
const ids = validateArrayLength(args?.ids ?? [], 'ids', 0, MAX_INSERT_BATCH_ITEMS);
|
|
2281
2590
|
const requestedTable = args?.table || 'episodes';
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2591
|
+
// Each table with the embedding table that must be cleaned alongside it (FK cascades are off by default)
|
|
2592
|
+
const embeddingTables = {
|
|
2593
|
+
episodes: ['episode_embeddings', 'episode_id'],
|
|
2594
|
+
reasoning_patterns: ['pattern_embeddings', 'pattern_id'],
|
|
2595
|
+
};
|
|
2596
|
+
if (!Object.prototype.hasOwnProperty.call(embeddingTables, requestedTable)) {
|
|
2597
|
+
throw new ValidationError(`Invalid table: ${requestedTable}`, 'INVALID_TABLE', 'table');
|
|
2285
2598
|
}
|
|
2286
2599
|
if (ids.length === 0) {
|
|
2287
2600
|
return { content: [{ type: 'text', text: '⚠️ No IDs supplied — nothing to delete.' }] };
|
|
2288
2601
|
}
|
|
2289
|
-
|
|
2290
|
-
const safeIds = ids.map((raw) => {
|
|
2291
|
-
const n = Number(raw);
|
|
2292
|
-
if (!Number.isInteger(n) || n <= 0)
|
|
2293
|
-
throw new Error(`Invalid id: ${raw}`);
|
|
2294
|
-
return n;
|
|
2295
|
-
});
|
|
2602
|
+
const safeIds = ids.map((raw, i) => toRecordId(raw, `ids[${i}]`));
|
|
2296
2603
|
const placeholders = safeIds.map(() => '?').join(',');
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
const
|
|
2604
|
+
const [embTable, embColumn] = embeddingTables[requestedTable];
|
|
2605
|
+
// Table names come from the fixed map above; values are bound parameters.
|
|
2606
|
+
const changes = inTransaction(db, () => {
|
|
2607
|
+
db.prepare(`DELETE FROM ${embTable} WHERE ${embColumn} IN (${placeholders})`).run(...safeIds);
|
|
2608
|
+
return db.prepare(`DELETE FROM ${requestedTable} WHERE id IN (${placeholders})`).run(...safeIds).changes;
|
|
2609
|
+
});
|
|
2610
|
+
if (changes > 0) {
|
|
2611
|
+
if (requestedTable === 'episodes')
|
|
2612
|
+
reflexion.clearCache();
|
|
2613
|
+
else {
|
|
2614
|
+
reasoningBank.clearCache();
|
|
2615
|
+
caches.patterns.clear();
|
|
2616
|
+
}
|
|
2617
|
+
caches.stats.clear();
|
|
2618
|
+
}
|
|
2300
2619
|
return {
|
|
2301
2620
|
content: [{
|
|
2302
2621
|
type: 'text',
|
|
2303
|
-
text: `🗑️ Batch delete from \`${requestedTable}\`: ${
|
|
2622
|
+
text: `🗑️ Batch delete from \`${requestedTable}\`: ${changes}/${safeIds.length} rows removed (atomic).`,
|
|
2304
2623
|
}],
|
|
2305
2624
|
};
|
|
2306
2625
|
}
|
|
@@ -2325,11 +2644,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
2325
2644
|
}
|
|
2326
2645
|
}
|
|
2327
2646
|
catch (error) {
|
|
2647
|
+
if (!(error instanceof ValidationError))
|
|
2648
|
+
console.error(`[agentdb-mcp] ${name} failed:`, error);
|
|
2328
2649
|
return {
|
|
2329
2650
|
content: [
|
|
2330
2651
|
{
|
|
2331
2652
|
type: 'text',
|
|
2332
|
-
|
|
2653
|
+
// The stack trace stays in the server log; clients only see the message.
|
|
2654
|
+
text: `❌ Error: ${error?.message ?? String(error)}`,
|
|
2333
2655
|
},
|
|
2334
2656
|
],
|
|
2335
2657
|
isError: true,
|