@learningnodes/elen-mcp 0.1.2
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/index.d.ts +7 -0
- package/dist/index.js +92 -0
- package/dist/server.d.ts +14 -0
- package/dist/server.js +88 -0
- package/dist/tools/commit.d.ts +46 -0
- package/dist/tools/commit.js +40 -0
- package/dist/tools/competency.d.ts +18 -0
- package/dist/tools/competency.js +35 -0
- package/dist/tools/expand.d.ts +20 -0
- package/dist/tools/expand.js +24 -0
- package/dist/tools/get-context.d.ts +34 -0
- package/dist/tools/get-context.js +84 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.js +39 -0
- package/dist/tools/legacy.d.ts +72 -0
- package/dist/tools/legacy.js +80 -0
- package/dist/tools/log-decision.d.ts +81 -0
- package/dist/tools/log-decision.js +121 -0
- package/dist/tools/search.d.ts +28 -0
- package/dist/tools/search.js +49 -0
- package/dist/tools/suggest.d.ts +30 -0
- package/dist/tools/suggest.js +32 -0
- package/dist/tools/supersede.d.ts +50 -0
- package/dist/tools/supersede.js +43 -0
- package/final_test.txt +68 -0
- package/mcp_test2.txt +60 -0
- package/mcp_test_output.txt +107 -0
- package/package.json +24 -0
- package/src/index.ts +107 -0
- package/src/server.ts +116 -0
- package/src/shims.d.ts +41 -0
- package/src/tools/commit.ts +40 -0
- package/src/tools/competency.ts +40 -0
- package/src/tools/expand.ts +24 -0
- package/src/tools/index.ts +23 -0
- package/src/tools/legacy.ts +88 -0
- package/src/tools/suggest.ts +32 -0
- package/src/tools/supersede.ts +43 -0
- package/tests/server.test.ts +43 -0
- package/tests/tools.test.ts +82 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.elenSearchPrecedentsTool = exports.elenLogDecisionTool = void 0;
|
|
4
|
+
exports.validateLogDecisionInput = validateLogDecisionInput;
|
|
5
|
+
exports.validateSearchInput = validateSearchInput;
|
|
6
|
+
exports.handleLogDecision = handleLogDecision;
|
|
7
|
+
exports.handleSearchPrecedents = handleSearchPrecedents;
|
|
8
|
+
exports.elenLogDecisionTool = {
|
|
9
|
+
name: 'elen_log_decision',
|
|
10
|
+
description: 'Create a validated Decision Record from constraints/evidence/answer.',
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
question: { type: 'string' },
|
|
15
|
+
domain: { type: 'string' },
|
|
16
|
+
constraints: { type: 'array', items: { type: 'string' } },
|
|
17
|
+
evidence: { type: 'array', items: { type: 'string' } },
|
|
18
|
+
answer: { type: 'string' },
|
|
19
|
+
parentPrompt: { type: 'string' }
|
|
20
|
+
},
|
|
21
|
+
required: ['question', 'constraints', 'evidence', 'answer']
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports.elenSearchPrecedentsTool = {
|
|
25
|
+
name: 'elen_search_precedents',
|
|
26
|
+
description: 'Search validated decisions for precedents.',
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
query: { type: 'string' },
|
|
31
|
+
domain: { type: 'string' },
|
|
32
|
+
minConfidence: { type: 'number' },
|
|
33
|
+
limit: { type: 'number' }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
function validateLogDecisionInput(input) {
|
|
38
|
+
if (!input || typeof input !== 'object')
|
|
39
|
+
throw new Error('missing required field: question');
|
|
40
|
+
const candidate = input;
|
|
41
|
+
for (const field of ['question', 'constraints', 'evidence', 'answer']) {
|
|
42
|
+
if (!(field in candidate))
|
|
43
|
+
throw new Error(`missing required field: ${field}`);
|
|
44
|
+
}
|
|
45
|
+
return candidate;
|
|
46
|
+
}
|
|
47
|
+
function validateSearchInput(input) {
|
|
48
|
+
if (!input)
|
|
49
|
+
return {};
|
|
50
|
+
if (typeof input !== 'object')
|
|
51
|
+
throw new Error('invalid search input');
|
|
52
|
+
const c = input;
|
|
53
|
+
if (c.limit !== undefined && typeof c.limit !== 'number')
|
|
54
|
+
throw new Error('limit must be a number');
|
|
55
|
+
if (c.minConfidence !== undefined && typeof c.minConfidence !== 'number') {
|
|
56
|
+
throw new Error('minConfidence must be a number');
|
|
57
|
+
}
|
|
58
|
+
return c;
|
|
59
|
+
}
|
|
60
|
+
async function handleLogDecision(elen, args) {
|
|
61
|
+
const parsed = validateLogDecisionInput(args);
|
|
62
|
+
const result = await elen.logDecision({
|
|
63
|
+
question: parsed.question,
|
|
64
|
+
domain: parsed.domain ?? 'general',
|
|
65
|
+
constraints: parsed.constraints,
|
|
66
|
+
evidence: parsed.evidence,
|
|
67
|
+
answer: parsed.answer,
|
|
68
|
+
parentPrompt: parsed.parentPrompt
|
|
69
|
+
});
|
|
70
|
+
return { ...result, next_suggested_action: 'Use elen_search_precedents to discover related decisions.' };
|
|
71
|
+
}
|
|
72
|
+
async function handleSearchPrecedents(elen, args) {
|
|
73
|
+
const parsed = validateSearchInput(args);
|
|
74
|
+
return elen.searchRecords({
|
|
75
|
+
query: parsed.query,
|
|
76
|
+
domain: parsed.domain,
|
|
77
|
+
minConfidence: parsed.minConfidence,
|
|
78
|
+
limit: parsed.limit
|
|
79
|
+
});
|
|
80
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { Elen, LogDecisionInput } from '@learningnodes/elen';
|
|
2
|
+
export declare const elenLogDecisionTool: {
|
|
3
|
+
readonly name: "elen_log_decision";
|
|
4
|
+
readonly description: "When you make a decision involving trade-offs or multiple viable options, log it here with your reasoning, constraints, and evidence. This creates a validated Decision Record — frozen, queryable, and citable by other agents. If you recently searched precedents with elen_search_precedents, cite the found record_ids in linkedPrecedents to build the decision network.";
|
|
5
|
+
readonly inputSchema: {
|
|
6
|
+
readonly type: "object";
|
|
7
|
+
readonly required: readonly ["question", "constraints", "evidence", "answer"];
|
|
8
|
+
readonly properties: {
|
|
9
|
+
readonly question: {
|
|
10
|
+
readonly type: "string";
|
|
11
|
+
readonly description: "The decision question";
|
|
12
|
+
};
|
|
13
|
+
readonly domain: {
|
|
14
|
+
readonly type: "string";
|
|
15
|
+
readonly description: "Domain of the decision (e.g. infrastructure, security, architecture)";
|
|
16
|
+
};
|
|
17
|
+
readonly constraints: {
|
|
18
|
+
readonly type: "array";
|
|
19
|
+
readonly items: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
};
|
|
22
|
+
readonly description: "Constraints bounding this decision";
|
|
23
|
+
};
|
|
24
|
+
readonly evidence: {
|
|
25
|
+
readonly type: "array";
|
|
26
|
+
readonly items: {
|
|
27
|
+
readonly type: "string";
|
|
28
|
+
};
|
|
29
|
+
readonly description: "Evidence supporting your choice";
|
|
30
|
+
};
|
|
31
|
+
readonly answer: {
|
|
32
|
+
readonly type: "string";
|
|
33
|
+
readonly description: "Your decision/answer";
|
|
34
|
+
};
|
|
35
|
+
readonly tags: {
|
|
36
|
+
readonly type: "array";
|
|
37
|
+
readonly items: {
|
|
38
|
+
readonly type: "string";
|
|
39
|
+
};
|
|
40
|
+
readonly description: "Optional tags";
|
|
41
|
+
};
|
|
42
|
+
readonly linkedPrecedents: {
|
|
43
|
+
readonly type: "array";
|
|
44
|
+
readonly items: {
|
|
45
|
+
readonly type: "string";
|
|
46
|
+
};
|
|
47
|
+
readonly description: "Record IDs of cited precedents. If your most recent elen_search_precedents returned results, pass their record_ids here to link this decision to prior knowledge.";
|
|
48
|
+
};
|
|
49
|
+
readonly threadId: {
|
|
50
|
+
readonly type: "string";
|
|
51
|
+
readonly description: "Thread ID to group related decisions (auto-derived from domain if omitted)";
|
|
52
|
+
};
|
|
53
|
+
readonly threadName: {
|
|
54
|
+
readonly type: "string";
|
|
55
|
+
readonly description: "Human-readable thread name (auto-derived from domain if omitted)";
|
|
56
|
+
};
|
|
57
|
+
readonly turnType: {
|
|
58
|
+
readonly type: "string";
|
|
59
|
+
readonly enum: readonly ["ASK", "VALIDATE", "DECISION"];
|
|
60
|
+
readonly description: "Turn type: ASK (question), VALIDATE (human/peer validation), DECISION (final resolved). Auto-derived if omitted.";
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export declare function validateLogDecisionInput(input: unknown): LogDecisionInput;
|
|
66
|
+
export declare function handleLogDecision(elen: Elen, input: unknown, autoLinkedPrecedents?: string[]): Promise<{
|
|
67
|
+
next_suggested_action: string;
|
|
68
|
+
record_id: string;
|
|
69
|
+
decision_id: string;
|
|
70
|
+
agent_id: string;
|
|
71
|
+
question: string;
|
|
72
|
+
answer: string;
|
|
73
|
+
confidence: number;
|
|
74
|
+
domain: string;
|
|
75
|
+
tags: string[];
|
|
76
|
+
published_at: string;
|
|
77
|
+
thread_id?: string;
|
|
78
|
+
thread_name?: string;
|
|
79
|
+
turn_type?: "ASK" | "VALIDATE" | "DECISION";
|
|
80
|
+
linked_records?: string[];
|
|
81
|
+
}>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.elenLogDecisionTool = void 0;
|
|
4
|
+
exports.validateLogDecisionInput = validateLogDecisionInput;
|
|
5
|
+
exports.handleLogDecision = handleLogDecision;
|
|
6
|
+
exports.elenLogDecisionTool = {
|
|
7
|
+
name: 'elen_log_decision',
|
|
8
|
+
description: 'When you make a decision involving trade-offs or multiple viable options, log it here with your reasoning, constraints, and evidence. This creates a validated Decision Record — frozen, queryable, and citable by other agents. If you recently searched precedents with elen_search_precedents, cite the found record_ids in linkedPrecedents to build the decision network.',
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
required: ['question', 'constraints', 'evidence', 'answer'],
|
|
12
|
+
properties: {
|
|
13
|
+
question: { type: 'string', description: 'The decision question' },
|
|
14
|
+
domain: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Domain of the decision (e.g. infrastructure, security, architecture)'
|
|
17
|
+
},
|
|
18
|
+
constraints: {
|
|
19
|
+
type: 'array',
|
|
20
|
+
items: { type: 'string' },
|
|
21
|
+
description: 'Constraints bounding this decision'
|
|
22
|
+
},
|
|
23
|
+
evidence: {
|
|
24
|
+
type: 'array',
|
|
25
|
+
items: { type: 'string' },
|
|
26
|
+
description: 'Evidence supporting your choice'
|
|
27
|
+
},
|
|
28
|
+
answer: { type: 'string', description: 'Your decision/answer' },
|
|
29
|
+
tags: { type: 'array', items: { type: 'string' }, description: 'Optional tags' },
|
|
30
|
+
linkedPrecedents: {
|
|
31
|
+
type: 'array',
|
|
32
|
+
items: { type: 'string' },
|
|
33
|
+
description: 'Record IDs of cited precedents. If your most recent elen_search_precedents returned results, pass their record_ids here to link this decision to prior knowledge.'
|
|
34
|
+
},
|
|
35
|
+
threadId: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
description: 'Thread ID to group related decisions (auto-derived from domain if omitted)'
|
|
38
|
+
},
|
|
39
|
+
threadName: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'Human-readable thread name (auto-derived from domain if omitted)'
|
|
42
|
+
},
|
|
43
|
+
turnType: {
|
|
44
|
+
type: 'string',
|
|
45
|
+
enum: ['ASK', 'VALIDATE', 'DECISION'],
|
|
46
|
+
description: 'Turn type: ASK (question), VALIDATE (human/peer validation), DECISION (final resolved). Auto-derived if omitted.'
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
function validateLogDecisionInput(input) {
|
|
52
|
+
if (!input || typeof input !== 'object') {
|
|
53
|
+
throw new Error('Invalid input: expected object');
|
|
54
|
+
}
|
|
55
|
+
const candidate = input;
|
|
56
|
+
const requiredFields = ['question', 'constraints', 'evidence', 'answer'];
|
|
57
|
+
for (const field of requiredFields) {
|
|
58
|
+
if (!(field in candidate)) {
|
|
59
|
+
throw new Error(`Invalid input: missing required field \"${field}\"`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (typeof candidate.question !== 'string') {
|
|
63
|
+
throw new Error('Invalid input: question must be a string');
|
|
64
|
+
}
|
|
65
|
+
if (!Array.isArray(candidate.constraints) || candidate.constraints.some((v) => typeof v !== 'string')) {
|
|
66
|
+
throw new Error('Invalid input: constraints must be an array of strings');
|
|
67
|
+
}
|
|
68
|
+
if (!Array.isArray(candidate.evidence) || candidate.evidence.some((v) => typeof v !== 'string')) {
|
|
69
|
+
throw new Error('Invalid input: evidence must be an array of strings');
|
|
70
|
+
}
|
|
71
|
+
if (typeof candidate.answer !== 'string') {
|
|
72
|
+
throw new Error('Invalid input: answer must be a string');
|
|
73
|
+
}
|
|
74
|
+
if (candidate.domain !== undefined && typeof candidate.domain !== 'string') {
|
|
75
|
+
throw new Error('Invalid input: domain must be a string');
|
|
76
|
+
}
|
|
77
|
+
if (candidate.tags !== undefined && (!Array.isArray(candidate.tags) || candidate.tags.some((v) => typeof v !== 'string'))) {
|
|
78
|
+
throw new Error('Invalid input: tags must be an array of strings');
|
|
79
|
+
}
|
|
80
|
+
if (candidate.linkedPrecedents !== undefined &&
|
|
81
|
+
(!Array.isArray(candidate.linkedPrecedents) || candidate.linkedPrecedents.some((v) => typeof v !== 'string'))) {
|
|
82
|
+
throw new Error('Invalid input: linkedPrecedents must be an array of strings');
|
|
83
|
+
}
|
|
84
|
+
if (candidate.threadId !== undefined && typeof candidate.threadId !== 'string') {
|
|
85
|
+
throw new Error('Invalid input: threadId must be a string');
|
|
86
|
+
}
|
|
87
|
+
if (candidate.threadName !== undefined && typeof candidate.threadName !== 'string') {
|
|
88
|
+
throw new Error('Invalid input: threadName must be a string');
|
|
89
|
+
}
|
|
90
|
+
if (candidate.turnType !== undefined && !['ASK', 'VALIDATE', 'DECISION'].includes(candidate.turnType)) {
|
|
91
|
+
throw new Error('Invalid input: turnType must be ASK, VALIDATE, or DECISION');
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
question: candidate.question,
|
|
95
|
+
domain: candidate.domain ?? 'general',
|
|
96
|
+
constraints: candidate.constraints,
|
|
97
|
+
evidence: candidate.evidence,
|
|
98
|
+
answer: candidate.answer,
|
|
99
|
+
tags: candidate.tags,
|
|
100
|
+
linkedPrecedents: candidate.linkedPrecedents,
|
|
101
|
+
threadId: candidate.threadId,
|
|
102
|
+
threadName: candidate.threadName,
|
|
103
|
+
turnType: candidate.turnType,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
async function handleLogDecision(elen, input, autoLinkedPrecedents = []) {
|
|
107
|
+
const parsed = validateLogDecisionInput(input);
|
|
108
|
+
// Auto-link: merge any stashed search results if user didn't provide their own
|
|
109
|
+
if ((!parsed.linkedPrecedents || parsed.linkedPrecedents.length === 0) && autoLinkedPrecedents.length > 0) {
|
|
110
|
+
parsed.linkedPrecedents = [...autoLinkedPrecedents];
|
|
111
|
+
autoLinkedPrecedents.length = 0; // Clear after use
|
|
112
|
+
}
|
|
113
|
+
const record = await elen.logDecision(parsed);
|
|
114
|
+
// Enrich response with contextual nudge — this keeps agents in-context
|
|
115
|
+
return {
|
|
116
|
+
...record,
|
|
117
|
+
next_suggested_action: record.linked_records && record.linked_records.length > 0
|
|
118
|
+
? `Decision recorded with ${record.linked_records.length} cited precedent(s). Cross-thread bridges updated.`
|
|
119
|
+
: 'Decision recorded. Consider using elen_search_precedents to find related prior decisions before your next choice.',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Elen, SearchOptions } from '@learningnodes/elen';
|
|
2
|
+
export declare const elenSearchPrecedentsTool: {
|
|
3
|
+
readonly name: "elen_search_precedents";
|
|
4
|
+
readonly description: "Before making a significant technical decision, search for existing validated decisions in this domain. Returns past Decision Records with evidence and confidence scores.";
|
|
5
|
+
readonly inputSchema: {
|
|
6
|
+
readonly type: "object";
|
|
7
|
+
readonly properties: {
|
|
8
|
+
readonly query: {
|
|
9
|
+
readonly type: "string";
|
|
10
|
+
readonly description: "Natural language search query";
|
|
11
|
+
};
|
|
12
|
+
readonly domain: {
|
|
13
|
+
readonly type: "string";
|
|
14
|
+
readonly description: "Filter by domain";
|
|
15
|
+
};
|
|
16
|
+
readonly minConfidence: {
|
|
17
|
+
readonly type: "number";
|
|
18
|
+
readonly description: "Minimum confidence threshold (0-1)";
|
|
19
|
+
};
|
|
20
|
+
readonly limit: {
|
|
21
|
+
readonly type: "number";
|
|
22
|
+
readonly description: "Max results (default 5)";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare function validateSearchInput(input: unknown): SearchOptions;
|
|
28
|
+
export declare function handleSearchPrecedents(elen: Elen, input: unknown): Promise<import("@learningnodes/elen").DecisionRecord[]>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.elenSearchPrecedentsTool = void 0;
|
|
4
|
+
exports.validateSearchInput = validateSearchInput;
|
|
5
|
+
exports.handleSearchPrecedents = handleSearchPrecedents;
|
|
6
|
+
exports.elenSearchPrecedentsTool = {
|
|
7
|
+
name: 'elen_search_precedents',
|
|
8
|
+
description: 'Before making a significant technical decision, search for existing validated decisions in this domain. Returns past Decision Records with evidence and confidence scores.',
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
query: { type: 'string', description: 'Natural language search query' },
|
|
13
|
+
domain: { type: 'string', description: 'Filter by domain' },
|
|
14
|
+
minConfidence: { type: 'number', description: 'Minimum confidence threshold (0-1)' },
|
|
15
|
+
limit: { type: 'number', description: 'Max results (default 5)' }
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
function validateSearchInput(input) {
|
|
20
|
+
if (input === undefined) {
|
|
21
|
+
return { limit: 5 };
|
|
22
|
+
}
|
|
23
|
+
if (!input || typeof input !== 'object') {
|
|
24
|
+
throw new Error('Invalid input: expected object');
|
|
25
|
+
}
|
|
26
|
+
const candidate = input;
|
|
27
|
+
if (candidate.query !== undefined && typeof candidate.query !== 'string') {
|
|
28
|
+
throw new Error('Invalid input: query must be a string');
|
|
29
|
+
}
|
|
30
|
+
if (candidate.domain !== undefined && typeof candidate.domain !== 'string') {
|
|
31
|
+
throw new Error('Invalid input: domain must be a string');
|
|
32
|
+
}
|
|
33
|
+
if (candidate.minConfidence !== undefined && typeof candidate.minConfidence !== 'number') {
|
|
34
|
+
throw new Error('Invalid input: minConfidence must be a number');
|
|
35
|
+
}
|
|
36
|
+
if (candidate.limit !== undefined && typeof candidate.limit !== 'number') {
|
|
37
|
+
throw new Error('Invalid input: limit must be a number');
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
query: candidate.query,
|
|
41
|
+
domain: candidate.domain,
|
|
42
|
+
minConfidence: candidate.minConfidence,
|
|
43
|
+
limit: candidate.limit ?? 5
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function handleSearchPrecedents(elen, input) {
|
|
47
|
+
const parsed = validateSearchInput(input);
|
|
48
|
+
return elen.searchRecords(parsed);
|
|
49
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Elen } from '@learningnodes/elen';
|
|
3
|
+
export declare const elenSuggestTool: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: string;
|
|
8
|
+
properties: {
|
|
9
|
+
query: {
|
|
10
|
+
type: string;
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
domain: {
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
limit: {
|
|
18
|
+
type: string;
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
required: string[];
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
export declare const suggestInputSchema: z.ZodObject<{
|
|
26
|
+
query: z.ZodString;
|
|
27
|
+
domain: z.ZodOptional<z.ZodString>;
|
|
28
|
+
limit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
export declare function handleSuggest(elen: Elen, args: unknown): Promise<unknown>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.suggestInputSchema = exports.elenSuggestTool = void 0;
|
|
4
|
+
exports.handleSuggest = handleSuggest;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
exports.elenSuggestTool = {
|
|
7
|
+
name: 'elen_suggest',
|
|
8
|
+
description: 'Before making a decision or taking action, retrieve pointer-first minimal candidates of prior decisions.',
|
|
9
|
+
inputSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
query: { type: 'string', description: 'Search term or question' },
|
|
13
|
+
domain: { type: 'string', description: 'Filter by domain' },
|
|
14
|
+
limit: { type: 'number', description: 'Max suggestions to return (Top-K)' }
|
|
15
|
+
},
|
|
16
|
+
required: ['query']
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
exports.suggestInputSchema = zod_1.z.object({
|
|
20
|
+
query: zod_1.z.string().min(1),
|
|
21
|
+
domain: zod_1.z.string().optional(),
|
|
22
|
+
limit: zod_1.z.number().int().min(1).max(50).optional().default(5)
|
|
23
|
+
});
|
|
24
|
+
async function handleSuggest(elen, args) {
|
|
25
|
+
const parsed = exports.suggestInputSchema.parse(args);
|
|
26
|
+
const results = await elen.suggest({
|
|
27
|
+
query: parsed.query,
|
|
28
|
+
domain: parsed.domain,
|
|
29
|
+
limit: parsed.limit
|
|
30
|
+
});
|
|
31
|
+
return results;
|
|
32
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { Elen } from '@learningnodes/elen';
|
|
3
|
+
export declare const elenSupersedeTool: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: string;
|
|
8
|
+
properties: {
|
|
9
|
+
oldDecisionId: {
|
|
10
|
+
type: string;
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
question: {
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
domain: {
|
|
18
|
+
type: string;
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
decisionText: {
|
|
22
|
+
type: string;
|
|
23
|
+
description: string;
|
|
24
|
+
};
|
|
25
|
+
constraints: {
|
|
26
|
+
type: string;
|
|
27
|
+
items: {
|
|
28
|
+
type: string;
|
|
29
|
+
};
|
|
30
|
+
description: string;
|
|
31
|
+
};
|
|
32
|
+
refs: {
|
|
33
|
+
type: string;
|
|
34
|
+
items: {
|
|
35
|
+
type: string;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
required: string[];
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export declare const supersedeInputSchema: z.ZodObject<{
|
|
43
|
+
question: z.ZodString;
|
|
44
|
+
domain: z.ZodString;
|
|
45
|
+
decisionText: z.ZodString;
|
|
46
|
+
constraints: z.ZodArray<z.ZodString>;
|
|
47
|
+
refs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
48
|
+
oldDecisionId: z.ZodString;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
export declare function handleSupersede(elen: Elen, args: unknown): Promise<unknown>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.supersedeInputSchema = exports.elenSupersedeTool = void 0;
|
|
4
|
+
exports.handleSupersede = handleSupersede;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const commit_1 = require("./commit");
|
|
7
|
+
exports.elenSupersedeTool = {
|
|
8
|
+
name: 'elen_supersede',
|
|
9
|
+
description: 'Explicitly revise and supersede an older decision with a new one.',
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
oldDecisionId: { type: 'string', description: 'The old decision_id to supersede' },
|
|
14
|
+
question: { type: 'string', description: 'The question or problem statement' },
|
|
15
|
+
domain: { type: 'string', description: 'Domain of decision' },
|
|
16
|
+
decisionText: { type: 'string', description: 'The new revised answer/decision' },
|
|
17
|
+
constraints: {
|
|
18
|
+
type: 'array',
|
|
19
|
+
items: { type: 'string' },
|
|
20
|
+
description: 'Plain-text constraint rules'
|
|
21
|
+
},
|
|
22
|
+
refs: {
|
|
23
|
+
type: 'array',
|
|
24
|
+
items: { type: 'string' }
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
required: ['oldDecisionId', 'question', 'domain', 'decisionText', 'constraints']
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
exports.supersedeInputSchema = commit_1.commitInputSchema.extend({
|
|
31
|
+
oldDecisionId: zod_1.z.string().min(1)
|
|
32
|
+
});
|
|
33
|
+
async function handleSupersede(elen, args) {
|
|
34
|
+
const parsed = exports.supersedeInputSchema.parse(args);
|
|
35
|
+
const result = await elen.supersedeDecision(parsed.oldDecisionId, {
|
|
36
|
+
question: parsed.question,
|
|
37
|
+
domain: parsed.domain,
|
|
38
|
+
decisionText: parsed.decisionText,
|
|
39
|
+
constraints: parsed.constraints,
|
|
40
|
+
refs: parsed.refs
|
|
41
|
+
});
|
|
42
|
+
return result;
|
|
43
|
+
}
|
package/final_test.txt
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
[1m[7m[36m RUN [39m[27m[22m [36mv2.1.9 [39m[90mC:/Users/ln_ni/OneDrive/Desktop/Desktop/ventures/learningnodes/git/marketplace-repos/Elen/packages/mcp-server[39m
|
|
3
|
+
|
|
4
|
+
[32mΓ£ô[39m tests/tools.test.ts[2m > [22mMCP tool schemas[2m > [22mtool descriptions match expected format
|
|
5
|
+
[32mΓ£ô[39m tests/tools.test.ts[2m > [22mMCP tool schemas[2m > [22melen_log_decision schema has required fields
|
|
6
|
+
[32mΓ£ô[39m tests/tools.test.ts[2m > [22mMCP tool schemas[2m > [22melen_search_precedents schema includes optional filters
|
|
7
|
+
[32mΓ£ô[39m tests/tools.test.ts[2m > [22mMCP tool schemas[2m > [22melen_get_competency schema supports optional agentId
|
|
8
|
+
[32mΓ£ô[39m tests/tools.test.ts[2m > [22mMCP tool handlers[2m > [22melen_log_decision creates a record via SDK
|
|
9
|
+
[32mΓ£ô[39m tests/tools.test.ts[2m > [22mMCP tool handlers[2m > [22melen_search_precedents returns matching records
|
|
10
|
+
[32mΓ£ô[39m tests/tools.test.ts[2m > [22mMCP tool handlers[2m > [22melen_get_competency returns profile
|
|
11
|
+
[32mΓ£ô[39m tests/tools.test.ts[2m > [22mMCP tool handlers[2m > [22mthrows on invalid tool inputs
|
|
12
|
+
[32mΓ£ô[39m tests/server.test.ts[2m > [22mMCP server CLI[2m > [22mparses --agent-id and --storage args
|
|
13
|
+
[31m×[39m tests/server.test.ts[2m > [22mMCP server CLI[2m > [22muses defaults when args are omitted
|
|
14
|
+
[31m → expected 'C:\Users\ln_ni\.elen\decisions.db' to contain '.elen/decisions.db'[39m
|
|
15
|
+
[32mΓ£ô[39m tests/server.test.ts[2m > [22mrouteToolCall[2m > [22mroutes known tools and throws for unknown tool
|
|
16
|
+
|
|
17
|
+
node.exe : [31m⎯⎯⎯⎯⎯⎯⎯[1m[7m
|
|
18
|
+
Failed Tests 1
|
|
19
|
+
[27m[22m⎯⎯⎯⎯⎯⎯⎯[39m
|
|
20
|
+
At C:\Users\ln_ni\AppData\Roaming\npm\npx.ps1:24
|
|
21
|
+
char:5
|
|
22
|
+
+ & "node$exe"
|
|
23
|
+
"$basedir/node_modules/npm/bin/npx-cli.js" $args
|
|
24
|
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
25
|
+
~~~~~~~~~~~~~~~~~~~
|
|
26
|
+
+ CategoryInfo : NotSpecified: ([3
|
|
27
|
+
1mΓÄ»ΓÄ»ΓÄ»Γ...»ΓÄ»ΓÄ»ΓÄ»[39m:String) [], R
|
|
28
|
+
emoteException
|
|
29
|
+
+ FullyQualifiedErrorId : NativeCommandError
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
[31m[1m[7m FAIL [27m[22m[39m
|
|
33
|
+
tests/server.test.ts[2m > [22mMCP server
|
|
34
|
+
CLI[2m > [22muses defaults when args are
|
|
35
|
+
omitted
|
|
36
|
+
[31m[1mAssertionError[22m: expected
|
|
37
|
+
'C:\Users\ln_ni\.elen\decisions.db' to contain
|
|
38
|
+
'.elen/decisions.db'[39m
|
|
39
|
+
|
|
40
|
+
Expected: [32m".elen[7m/[27mdecisions.db"[39m
|
|
41
|
+
Received: [31m"[7mC:\Users\ln_ni\[27m.elen[7m
|
|
42
|
+
\[27mdecisions.db"[39m
|
|
43
|
+
|
|
44
|
+
[36m [2mΓ¥»[22m
|
|
45
|
+
tests/server.test.ts:[2m17:34[22m[39m
|
|
46
|
+
[90m 15| [39m
|
|
47
|
+
[90m 16| [39m [34mexpect[39m(parsed[3
|
|
48
|
+
3m.[39magentId)[33m.[39m[34mtoBe[39m([32m'd
|
|
49
|
+
efault-agent'[39m)[33m;[39m
|
|
50
|
+
[90m 17| [39m [34mexpect[39m([34mdefa
|
|
51
|
+
ultStoragePath[39m())[33m.[39m[34mtoContain[
|
|
52
|
+
39m([32m'.elen/decisions.db'[39m)[33m;[39m
|
|
53
|
+
[90m | [39m
|
|
54
|
+
[31m^[39m
|
|
55
|
+
[90m 18| [39m [34mexpect[39m(parsed[3
|
|
56
|
+
3m.[39mstoragePath)[33m.[39m[34mtoBeUndefined
|
|
57
|
+
[39m()[33m;[39m
|
|
58
|
+
[90m 19| [39m })[33m;[39m
|
|
59
|
+
|
|
60
|
+
[31m[2mΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»Γ
|
|
61
|
+
Ä»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»[1/1]ΓÄ»[22m[39
|
|
62
|
+
m
|
|
63
|
+
|
|
64
|
+
[2m Test Files [22m [1m[31m1 failed[39m[22m[2m | [22m[1m[32m1 passed[39m[22m[90m (2)[39m
|
|
65
|
+
[2m Tests [22m [1m[31m1 failed[39m[22m[2m | [22m[1m[32m10 passed[39m[22m[90m (11)[39m
|
|
66
|
+
[2m Start at [22m 12:30:07
|
|
67
|
+
[2m Duration [22m 2.52s[2m (transform 537ms, setup 0ms, collect 1.54s, tests 85ms, environment 2ms, prepare 1.04s)[22m
|
|
68
|
+
|
package/mcp_test2.txt
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
|
|
2
|
+
[1m[7m[36m RUN [39m[27m[22m [36mv2.1.9 [39m[90mC:/Users/ln_ni/OneDrive/Desktop/Desktop/ventures/learningnodes/git/marketplace-repos/Elen/packages/mcp-server[39m
|
|
3
|
+
|
|
4
|
+
[32mΓ£ô[39m tests/server.test.ts[2m > [22mMCP server CLI[2m > [22mparses --agent-id and --storage args
|
|
5
|
+
[31m×[39m tests/server.test.ts[2m > [22mMCP server CLI[2m > [22muses defaults when args are omitted
|
|
6
|
+
[31m → expected 'C:\Users\ln_ni\.elen\decisions.db' to contain '.elen/decisions.db'[39m
|
|
7
|
+
[32mΓ£ô[39m tests/server.test.ts[2m > [22mrouteToolCall[2m > [22mroutes known tools and throws for unknown tool
|
|
8
|
+
|
|
9
|
+
node.exe : [31m⎯⎯⎯⎯⎯⎯⎯[1m[7m
|
|
10
|
+
Failed Tests 1
|
|
11
|
+
[27m[22m⎯⎯⎯⎯⎯⎯⎯[39m
|
|
12
|
+
At C:\Users\ln_ni\AppData\Roaming\npm\npx.ps1:24
|
|
13
|
+
char:5
|
|
14
|
+
+ & "node$exe"
|
|
15
|
+
"$basedir/node_modules/npm/bin/npx-cli.js" $args
|
|
16
|
+
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
17
|
+
~~~~~~~~~~~~~~~~~~~
|
|
18
|
+
+ CategoryInfo : NotSpecified: ([3
|
|
19
|
+
1mΓÄ»ΓÄ»ΓÄ»Γ...»ΓÄ»ΓÄ»ΓÄ»[39m:String) [], R
|
|
20
|
+
emoteException
|
|
21
|
+
+ FullyQualifiedErrorId : NativeCommandError
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
[31m[1m[7m FAIL [27m[22m[39m
|
|
25
|
+
tests/server.test.ts[2m > [22mMCP server
|
|
26
|
+
CLI[2m > [22muses defaults when args are
|
|
27
|
+
omitted
|
|
28
|
+
[31m[1mAssertionError[22m: expected
|
|
29
|
+
'C:\Users\ln_ni\.elen\decisions.db' to contain
|
|
30
|
+
'.elen/decisions.db'[39m
|
|
31
|
+
|
|
32
|
+
Expected: [32m".elen[7m/[27mdecisions.db"[39m
|
|
33
|
+
Received: [31m"[7mC:\Users\ln_ni\[27m.elen[7m
|
|
34
|
+
\[27mdecisions.db"[39m
|
|
35
|
+
|
|
36
|
+
[36m [2mΓ¥»[22m
|
|
37
|
+
tests/server.test.ts:[2m17:34[22m[39m
|
|
38
|
+
[90m 15| [39m
|
|
39
|
+
[90m 16| [39m [34mexpect[39m(parsed[3
|
|
40
|
+
3m.[39magentId)[33m.[39m[34mtoBe[39m([32m'd
|
|
41
|
+
efault-agent'[39m)[33m;[39m
|
|
42
|
+
[90m 17| [39m [34mexpect[39m([34mdefa
|
|
43
|
+
ultStoragePath[39m())[33m.[39m[34mtoContain[
|
|
44
|
+
39m([32m'.elen/decisions.db'[39m)[33m;[39m
|
|
45
|
+
[90m | [39m
|
|
46
|
+
[31m^[39m
|
|
47
|
+
[90m 18| [39m [34mexpect[39m(parsed[3
|
|
48
|
+
3m.[39mstoragePath)[33m.[39m[34mtoBeUndefined
|
|
49
|
+
[39m()[33m;[39m
|
|
50
|
+
[90m 19| [39m })[33m;[39m
|
|
51
|
+
|
|
52
|
+
[31m[2mΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»Γ
|
|
53
|
+
Ä»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»ΓÄ»[1/1]ΓÄ»[22m[39
|
|
54
|
+
m
|
|
55
|
+
|
|
56
|
+
[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
|
|
57
|
+
[2m Tests [22m [1m[31m1 failed[39m[22m[2m | [22m[1m[32m2 passed[39m[22m[90m (3)[39m
|
|
58
|
+
[2m Start at [22m 12:22:13
|
|
59
|
+
[2m Duration [22m 7.20s[2m (transform 1.16s, setup 0ms, collect 3.05s, tests 132ms, environment 3ms, prepare 2.39s)[22m
|
|
60
|
+
|