@j0hanz/memory-mcp 1.5.0 → 1.7.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/db/index.js +16 -13
- package/dist/lib/errors.d.ts +4 -0
- package/dist/lib/errors.js +11 -0
- package/dist/lib/graph-traversal.d.ts +12 -0
- package/dist/lib/graph-traversal.js +145 -0
- package/dist/lib/json-schema.d.ts +5 -0
- package/dist/lib/json-schema.js +19 -1
- package/dist/lib/pagination.d.ts +0 -2
- package/dist/lib/pagination.js +0 -43
- package/dist/lib/search.js +44 -23
- package/dist/lib/tool-contracts.js +50 -73
- package/dist/lib/tool-execution.d.ts +13 -0
- package/dist/lib/tool-execution.js +51 -0
- package/dist/prompts/index.js +12 -8
- package/dist/resources/index.js +67 -43
- package/dist/resources/instructions.js +44 -37
- package/dist/resources/server-config.js +33 -22
- package/dist/resources/tool-catalog.js +2 -6
- package/dist/resources/tool-info.js +9 -9
- package/dist/resources/workflows.js +69 -40
- package/dist/schemas/inputs.d.ts +8 -5
- package/dist/schemas/inputs.js +57 -40
- package/dist/schemas/outputs.d.ts +6 -6
- package/dist/schemas/outputs.js +7 -6
- package/dist/server.js +11 -4
- package/dist/tools/create-relationship.js +17 -22
- package/dist/tools/delete-memories.js +30 -39
- package/dist/tools/delete-memory.js +14 -18
- package/dist/tools/delete-relationship.js +9 -24
- package/dist/tools/get-memory.js +12 -17
- package/dist/tools/get-relationships.js +11 -12
- package/dist/tools/memory-stats.js +22 -30
- package/dist/tools/progress.d.ts +6 -0
- package/dist/tools/progress.js +68 -25
- package/dist/tools/recall.js +94 -203
- package/dist/tools/register-contract.d.ts +1 -2
- package/dist/tools/register-contract.js +4 -2
- package/dist/tools/result.d.ts +4 -0
- package/dist/tools/result.js +27 -0
- package/dist/tools/retrieve-context.js +80 -98
- package/dist/tools/search-memories.js +31 -34
- package/dist/tools/store-memories.js +33 -44
- package/dist/tools/store-memory.js +13 -20
- package/dist/tools/update-memory.js +45 -49
- package/package.json +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { CancelledError, E_CANCELLED, E_UNKNOWN, getErrorMessage, rethrowMcpError, } from './errors.js';
|
|
3
|
+
import { createErrorResponse } from './tool-response.js';
|
|
4
|
+
export async function executeToolSafely(work) {
|
|
5
|
+
try {
|
|
6
|
+
return await work();
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
rethrowMcpError(err);
|
|
10
|
+
return createErrorResponse(E_UNKNOWN, getErrorMessage(err));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function summarizeBatch(items, isMatched) {
|
|
14
|
+
let succeeded = 0;
|
|
15
|
+
let matched = 0;
|
|
16
|
+
for (const item of items) {
|
|
17
|
+
if (item.ok) {
|
|
18
|
+
succeeded += 1;
|
|
19
|
+
}
|
|
20
|
+
if (isMatched(item)) {
|
|
21
|
+
matched += 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
succeeded,
|
|
26
|
+
failed: items.length - succeeded,
|
|
27
|
+
matched,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export async function executeLongRunningToolSafely(work, onFinally) {
|
|
31
|
+
let result;
|
|
32
|
+
let thrownError;
|
|
33
|
+
try {
|
|
34
|
+
result = await work();
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err instanceof CancelledError) {
|
|
38
|
+
result = createErrorResponse(E_CANCELLED, 'Request cancelled');
|
|
39
|
+
}
|
|
40
|
+
else if (err instanceof McpError) {
|
|
41
|
+
thrownError = err;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
result = createErrorResponse(E_UNKNOWN, getErrorMessage(err));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (onFinally) {
|
|
48
|
+
await onFinally();
|
|
49
|
+
}
|
|
50
|
+
return result ?? createErrorResponse(E_UNKNOWN, getErrorMessage(thrownError));
|
|
51
|
+
}
|
package/dist/prompts/index.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { loadInstructions } from '../lib/instructions.js';
|
|
2
2
|
const INSTRUCTIONS_CONTENT = loadInstructions();
|
|
3
|
+
const GET_HELP_PROMPT = {
|
|
4
|
+
name: 'get-help',
|
|
5
|
+
title: 'Get Help',
|
|
6
|
+
description: 'Return full usage instructions.',
|
|
7
|
+
};
|
|
3
8
|
function createHelpMessages(instructions) {
|
|
4
9
|
return [
|
|
5
10
|
{
|
|
@@ -19,13 +24,12 @@ function createHelpMessages(instructions) {
|
|
|
19
24
|
];
|
|
20
25
|
}
|
|
21
26
|
const HELP_MESSAGES = createHelpMessages(INSTRUCTIONS_CONTENT);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
description: 'Return full usage instructions.',
|
|
26
|
-
};
|
|
27
|
+
function createGetHelpPromptResult() {
|
|
28
|
+
return { messages: HELP_MESSAGES };
|
|
29
|
+
}
|
|
27
30
|
export function registerAllPrompts(server) {
|
|
28
|
-
server.registerPrompt(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
server.registerPrompt(GET_HELP_PROMPT.name, {
|
|
32
|
+
title: GET_HELP_PROMPT.title,
|
|
33
|
+
description: GET_HELP_PROMPT.description,
|
|
34
|
+
}, createGetHelpPromptResult);
|
|
31
35
|
}
|
package/dist/resources/index.js
CHANGED
|
@@ -44,6 +44,13 @@ function createResourceAnnotations(audience, priority) {
|
|
|
44
44
|
function getSingleVariable(value) {
|
|
45
45
|
return Array.isArray(value) ? value[0] : value;
|
|
46
46
|
}
|
|
47
|
+
function requireValidMemoryHash(variables) {
|
|
48
|
+
const hash = getSingleVariable(variables['hash']);
|
|
49
|
+
if (!hash || !HASH_REGEX.test(hash)) {
|
|
50
|
+
throw new McpError(ErrorCode.InvalidParams, 'Invalid hash: must be a 64-character hex string');
|
|
51
|
+
}
|
|
52
|
+
return hash;
|
|
53
|
+
}
|
|
47
54
|
function requireSingleVariable(variables, key, errorMessage) {
|
|
48
55
|
const value = getSingleVariable(variables[key]);
|
|
49
56
|
if (!value) {
|
|
@@ -51,6 +58,13 @@ function requireSingleVariable(variables, key, errorMessage) {
|
|
|
51
58
|
}
|
|
52
59
|
return value;
|
|
53
60
|
}
|
|
61
|
+
function requireKnownToolInfo(toolName) {
|
|
62
|
+
const info = getToolInfo(toolName);
|
|
63
|
+
if (!info) {
|
|
64
|
+
throw new McpError(ErrorCode.InvalidParams, `Unknown tool: ${toolName}`);
|
|
65
|
+
}
|
|
66
|
+
return info;
|
|
67
|
+
}
|
|
54
68
|
function registerStaticMarkdownResource(server, config) {
|
|
55
69
|
server.registerResource(config.name, config.uri, {
|
|
56
70
|
title: config.title,
|
|
@@ -90,70 +104,75 @@ const INSTRUCTIONS_CONTENT = loadInstructions();
|
|
|
90
104
|
const TOOL_CATALOG_CONTENT = buildToolCatalog();
|
|
91
105
|
const WORKFLOW_GUIDE_CONTENT = buildWorkflowGuide();
|
|
92
106
|
const SERVER_CONFIG_CONTENT = buildServerConfig();
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
107
|
+
const STATIC_CONTENT_BY_KEY = {
|
|
108
|
+
instructions: INSTRUCTIONS_CONTENT,
|
|
109
|
+
toolCatalog: TOOL_CATALOG_CONTENT,
|
|
110
|
+
workflows: WORKFLOW_GUIDE_CONTENT,
|
|
111
|
+
serverConfig: SERVER_CONFIG_CONTENT,
|
|
112
|
+
};
|
|
113
|
+
const STATIC_RESOURCE_SEEDS = [
|
|
114
|
+
{
|
|
97
115
|
name: 'instructions',
|
|
98
116
|
uri: INSTRUCTIONS_URI,
|
|
99
117
|
title: 'Memory Instructions',
|
|
100
118
|
description: 'Complete usage guide: tool inventory, routing decisions, error codes, data model, and workflow patterns. Read this first.',
|
|
101
119
|
audience: ['assistant'],
|
|
102
120
|
priority: 0.9,
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
registerStaticMarkdownResource(server, {
|
|
121
|
+
contentKey: 'instructions',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
107
124
|
name: 'tool-catalog',
|
|
108
125
|
uri: TOOL_CATALOG_URI,
|
|
109
126
|
title: 'Tool Catalog',
|
|
110
127
|
description: 'Tool reference table, optional parameter matrix, and cross-tool data flow.',
|
|
111
128
|
audience: ['assistant'],
|
|
112
129
|
priority: 0.7,
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
server.registerResource('tool-info', new ResourceTemplate(TOOL_INFO_URI_TEMPLATE, {
|
|
117
|
-
list: () => listToolInfoResources(),
|
|
118
|
-
complete: {
|
|
119
|
-
toolName: (value) => TOOL_NAMES.filter((n) => n.startsWith(value)),
|
|
120
|
-
},
|
|
121
|
-
}), {
|
|
122
|
-
title: 'Tool Info',
|
|
123
|
-
description: 'Per-tool detail: parameters, behavior, and output shape. Supports toolName auto-completion.',
|
|
124
|
-
mimeType: 'text/markdown',
|
|
125
|
-
annotations: createResourceAnnotations(['assistant'], 0.6),
|
|
126
|
-
}, (uri, variables) => {
|
|
127
|
-
const toolName = requireSingleVariable(variables, 'toolName', 'Missing toolName parameter');
|
|
128
|
-
const info = getToolInfo(toolName);
|
|
129
|
-
if (!info) {
|
|
130
|
-
throw new McpError(ErrorCode.InvalidParams, `Unknown tool: ${toolName}`);
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
contents: [createMarkdownContent(uri.href, info)],
|
|
134
|
-
};
|
|
135
|
-
});
|
|
136
|
-
// internal://workflows
|
|
137
|
-
registerStaticMarkdownResource(server, {
|
|
130
|
+
contentKey: 'toolCatalog',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
138
133
|
name: 'workflows',
|
|
139
134
|
uri: WORKFLOWS_URI,
|
|
140
135
|
title: 'Workflow Guide',
|
|
141
136
|
description: 'Recommended multi-step workflow sequences with guardrails and tool reference.',
|
|
142
137
|
audience: ['assistant'],
|
|
143
138
|
priority: 0.7,
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
registerStaticMarkdownResource(server, {
|
|
139
|
+
contentKey: 'workflows',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
148
142
|
name: 'server-config',
|
|
149
143
|
uri: SERVER_CONFIG_URI,
|
|
150
144
|
title: 'Server Configuration',
|
|
151
145
|
description: 'Runtime configuration, environment variables, capabilities, and data limits.',
|
|
152
146
|
audience: ['user', 'assistant'],
|
|
153
147
|
priority: 0.5,
|
|
154
|
-
|
|
148
|
+
contentKey: 'serverConfig',
|
|
149
|
+
},
|
|
150
|
+
];
|
|
151
|
+
function getStaticMarkdownResources() {
|
|
152
|
+
return STATIC_RESOURCE_SEEDS.map((seed) => ({
|
|
153
|
+
...seed,
|
|
154
|
+
content: STATIC_CONTENT_BY_KEY[seed.contentKey],
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
function completeToolName(value) {
|
|
158
|
+
return TOOL_NAMES.filter((toolName) => toolName.startsWith(value));
|
|
159
|
+
}
|
|
160
|
+
function registerToolInfoResource(server) {
|
|
161
|
+
server.registerResource('tool-info', new ResourceTemplate(TOOL_INFO_URI_TEMPLATE, {
|
|
162
|
+
list: listToolInfoResources,
|
|
163
|
+
complete: { toolName: completeToolName },
|
|
164
|
+
}), {
|
|
165
|
+
title: 'Tool Info',
|
|
166
|
+
description: 'Per-tool detail: parameters, behavior, and output shape. Supports toolName auto-completion.',
|
|
167
|
+
mimeType: 'text/markdown',
|
|
168
|
+
annotations: createResourceAnnotations(['assistant'], 0.6),
|
|
169
|
+
}, (uri, variables) => {
|
|
170
|
+
const toolName = requireSingleVariable(variables, 'toolName', 'Missing toolName parameter');
|
|
171
|
+
const info = requireKnownToolInfo(toolName);
|
|
172
|
+
return { contents: [createMarkdownContent(uri.href, info)] };
|
|
155
173
|
});
|
|
156
|
-
|
|
174
|
+
}
|
|
175
|
+
function registerMemoryResource(server, db) {
|
|
157
176
|
const hashCompletion = createHashCompletionCallback(db);
|
|
158
177
|
server.registerResource('memory', new ResourceTemplate(MEMORY_RESOURCE_URI_TEMPLATE, {
|
|
159
178
|
list: () => listMemoryResources(db),
|
|
@@ -164,10 +183,7 @@ export function registerAllResources(server, db) {
|
|
|
164
183
|
mimeType: 'application/json',
|
|
165
184
|
annotations: createResourceAnnotations(['assistant'], 0.7),
|
|
166
185
|
}, (uri, variables) => {
|
|
167
|
-
const hash =
|
|
168
|
-
if (!hash || !HASH_REGEX.test(hash)) {
|
|
169
|
-
throw new McpError(ErrorCode.InvalidParams, 'Invalid hash: must be a 64-character hex string');
|
|
170
|
-
}
|
|
186
|
+
const hash = requireValidMemoryHash(variables);
|
|
171
187
|
const row = readMemoryByHash(db, hash);
|
|
172
188
|
if (!row) {
|
|
173
189
|
return createErrorResourceContents(uri.href, 'Not found', hash);
|
|
@@ -177,3 +193,11 @@ export function registerAllResources(server, db) {
|
|
|
177
193
|
};
|
|
178
194
|
});
|
|
179
195
|
}
|
|
196
|
+
// --- Registration ---
|
|
197
|
+
export function registerAllResources(server, db) {
|
|
198
|
+
for (const config of getStaticMarkdownResources()) {
|
|
199
|
+
registerStaticMarkdownResource(server, config);
|
|
200
|
+
}
|
|
201
|
+
registerToolInfoResource(server);
|
|
202
|
+
registerMemoryResource(server, db);
|
|
203
|
+
}
|
|
@@ -63,42 +63,49 @@ function renderSharedConstraints() {
|
|
|
63
63
|
.map((c) => `- ${c}`)
|
|
64
64
|
.join('\n');
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
function renderTaggedSection(section) {
|
|
67
|
+
return [`<${section.tag}>`, section.content, `</${section.tag}>`].join('\n');
|
|
68
|
+
}
|
|
69
|
+
function buildTaggedSections() {
|
|
67
70
|
return [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
71
|
+
{
|
|
72
|
+
tag: 'role',
|
|
73
|
+
content: 'Memory MCP: Persistent memory storage, full-text retrieval, and relationship graph traversal.',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
tag: 'capabilities',
|
|
77
|
+
content: buildToolRouting(),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
tag: 'constraints',
|
|
81
|
+
content: renderSharedConstraints(),
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
tag: 'error_codes',
|
|
85
|
+
content: ERROR_CODES.join('\n'),
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
tag: 'error_result_conventions',
|
|
89
|
+
content: ERROR_RESULT_CONVENTIONS.join('\n'),
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
tag: 'data_model',
|
|
93
|
+
content: DATA_MODEL,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
tag: 'workflows',
|
|
97
|
+
content: WORKFLOWS,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
tag: 'prompts',
|
|
101
|
+
content: PROMPTS_INVENTORY.join('\n'),
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
tag: 'resources',
|
|
105
|
+
content: RESOURCES_INVENTORY.join('\n'),
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
}
|
|
109
|
+
export function buildServerInstructions() {
|
|
110
|
+
return buildTaggedSections().map(renderTaggedSection).join('\n\n');
|
|
104
111
|
}
|
|
@@ -46,32 +46,43 @@ const CAPABILITIES = [
|
|
|
46
46
|
function toEnvVarRow(v) {
|
|
47
47
|
return `| \`${v.name}\` | ${v.default} | ${v.range} | ${v.purpose} |`;
|
|
48
48
|
}
|
|
49
|
-
function
|
|
50
|
-
return `| ${label} | ${
|
|
49
|
+
function toTwoColumnRow(label, value) {
|
|
50
|
+
return `| ${label} | ${value} |`;
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
const envRows = ENV_VARS.map(toEnvVarRow);
|
|
54
|
-
const limitRows = DATA_LIMITS.map((l) => toRangeRow(l.dimension, l.range));
|
|
55
|
-
const capRows = CAPABILITIES.map((c) => toRangeRow(c.capability, c.status));
|
|
52
|
+
function renderTableSection(section) {
|
|
56
53
|
return [
|
|
57
|
-
|
|
58
|
-
'',
|
|
59
|
-
'## Environment Variables',
|
|
60
|
-
'',
|
|
61
|
-
'| Variable | Default | Range | Purpose |',
|
|
62
|
-
'|----------|---------|-------|---------|',
|
|
63
|
-
...envRows,
|
|
64
|
-
'',
|
|
65
|
-
'## Capabilities',
|
|
54
|
+
`## ${section.title}`,
|
|
66
55
|
'',
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
...
|
|
56
|
+
section.header,
|
|
57
|
+
section.separator,
|
|
58
|
+
...section.rows,
|
|
70
59
|
'',
|
|
71
|
-
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
export function buildServerConfig() {
|
|
63
|
+
const sections = [
|
|
64
|
+
{
|
|
65
|
+
title: 'Environment Variables',
|
|
66
|
+
header: '| Variable | Default | Range | Purpose |',
|
|
67
|
+
separator: '|----------|---------|-------|---------|',
|
|
68
|
+
rows: ENV_VARS.map(toEnvVarRow),
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
title: 'Capabilities',
|
|
72
|
+
header: '| Capability | Status |',
|
|
73
|
+
separator: '|------------|--------|',
|
|
74
|
+
rows: CAPABILITIES.map((c) => toTwoColumnRow(c.capability, c.status)),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
title: 'Data Limits',
|
|
78
|
+
header: '| Dimension | Range |',
|
|
79
|
+
separator: '|-----------|-------|',
|
|
80
|
+
rows: DATA_LIMITS.map((l) => toTwoColumnRow(l.dimension, l.range)),
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
return [
|
|
84
|
+
'# Server Configuration',
|
|
72
85
|
'',
|
|
73
|
-
|
|
74
|
-
'|-----------|-------|',
|
|
75
|
-
...limitRows,
|
|
86
|
+
...sections.flatMap(renderTableSection),
|
|
76
87
|
].join('\n');
|
|
77
88
|
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getSchemaMeta } from '../lib/json-schema.js';
|
|
2
2
|
import { getToolContracts } from '../lib/tool-contracts.js';
|
|
3
3
|
import { buildCoreContextPack } from './tool-info.js';
|
|
4
4
|
function extractOptionalParams(toolName, schema) {
|
|
5
|
-
const
|
|
6
|
-
const properties = (jsonSchema['properties'] ?? {});
|
|
7
|
-
const requiredFields = new Set(Array.isArray(jsonSchema['required'])
|
|
8
|
-
? jsonSchema['required']
|
|
9
|
-
: []);
|
|
5
|
+
const { properties, requiredFields } = getSchemaMeta(schema);
|
|
10
6
|
const rows = [];
|
|
11
7
|
for (const [name, prop] of Object.entries(properties).sort(([a], [b]) => a.localeCompare(b))) {
|
|
12
8
|
if (requiredFields.has(name))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { extractJsonSchema, } from '../lib/json-schema.js';
|
|
1
|
+
import { extractJsonSchema, getSchemaMeta, } from '../lib/json-schema.js';
|
|
2
2
|
import { getToolContracts } from '../lib/tool-contracts.js';
|
|
3
3
|
// --- Shared Constraints (Single Source of Truth) ---
|
|
4
4
|
const SHARED_CONSTRAINTS = [
|
|
@@ -61,6 +61,12 @@ function formatParamConstraints(prop) {
|
|
|
61
61
|
parts.push(`enum: ${prop['enum'].join(' | ')}`);
|
|
62
62
|
return parts.length > 0 ? `; ${parts.join(', ')}` : '';
|
|
63
63
|
}
|
|
64
|
+
function getSortedSchemaProperties(properties) {
|
|
65
|
+
return Object.entries(properties).sort(([a], [b]) => a.localeCompare(b));
|
|
66
|
+
}
|
|
67
|
+
function formatParamLines(meta) {
|
|
68
|
+
return getSortedSchemaProperties(meta.properties).map(([pName, pSchema]) => formatParam(pName, pSchema, meta.requiredFields.has(pName)));
|
|
69
|
+
}
|
|
64
70
|
function formatParam(name, prop, required) {
|
|
65
71
|
const type = typeof prop['type'] === 'string' ? prop['type'] : 'unknown';
|
|
66
72
|
const desc = typeof prop['description'] === 'string' ? prop['description'] : '';
|
|
@@ -87,14 +93,8 @@ export function getToolInfo(name) {
|
|
|
87
93
|
const contract = getToolContracts().find((c) => c.name === name);
|
|
88
94
|
if (!contract)
|
|
89
95
|
return undefined;
|
|
90
|
-
const
|
|
91
|
-
const
|
|
92
|
-
const requiredFields = new Set(Array.isArray(inputSchema['required'])
|
|
93
|
-
? inputSchema['required']
|
|
94
|
-
: []);
|
|
95
|
-
const paramLines = Object.entries(properties)
|
|
96
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
97
|
-
.map(([pName, pSchema]) => formatParam(pName, pSchema, requiredFields.has(pName)));
|
|
96
|
+
const inputMeta = getSchemaMeta(contract.inputSchema);
|
|
97
|
+
const paramLines = formatParamLines(inputMeta);
|
|
98
98
|
const behaviorLine = formatBehavior(contract.annotations);
|
|
99
99
|
const outputShape = formatOutputShape(contract.outputSchema);
|
|
100
100
|
return [
|
|
@@ -1,53 +1,82 @@
|
|
|
1
1
|
import { getSharedConstraints } from './tool-info.js';
|
|
2
|
-
const WORKFLOW_TRACKS =
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
2
|
+
const WORKFLOW_TRACKS = [
|
|
3
|
+
{
|
|
4
|
+
title: 'Workflow A: Store and Link',
|
|
5
|
+
steps: [
|
|
6
|
+
'`store_memories({ items: [...] })` → `{ items[].hash, succeeded, failed }`',
|
|
7
|
+
'`create_relationship({ from_hash, to_hash, relation_type })` × N',
|
|
8
|
+
],
|
|
9
|
+
notes: [
|
|
10
|
+
'Constraint: Both endpoint memories must exist before creating a relationship.',
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
title: 'Workflow B: Search and Read',
|
|
15
|
+
steps: [
|
|
16
|
+
'`search_memories({ query, limit })` → `{ memories[], nextCursor }`',
|
|
17
|
+
'`get_memory({ hash })` for full detail on a specific result',
|
|
18
|
+
],
|
|
19
|
+
notes: [
|
|
20
|
+
'Or use `recall({ query, depth: 1 })` → `{ memories[], graph[] }` to follow relationships.',
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
title: 'Workflow C: Fill Context Window',
|
|
25
|
+
steps: [
|
|
26
|
+
"`retrieve_context({ query, token_budget: 4000, strategy: 'relevance' })` → `{ memories[], estimated_tokens, truncated }`",
|
|
27
|
+
],
|
|
28
|
+
notes: [
|
|
29
|
+
'Use `strategy` to control sort: `relevance` (FTS rank), `importance` (highest first), or `recency` (newest first).',
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
title: 'Workflow D: Update a Memory',
|
|
34
|
+
steps: ['`update_memory({ hash, content })` → `{ old_hash, new_hash }`'],
|
|
35
|
+
notes: [
|
|
36
|
+
'Existing relationships auto-update to new_hash via CASCADE.',
|
|
37
|
+
'Returns E_CONFLICT if the new content+tags already maps to an existing hash.',
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
title: 'Workflow E: Batch Delete',
|
|
42
|
+
steps: [
|
|
43
|
+
'`delete_memories({ hashes: [...] })` → `{ items[].{ hash, deleted }, succeeded, failed }`',
|
|
44
|
+
],
|
|
45
|
+
notes: [
|
|
46
|
+
'`deleted: false` means hash not found - not an error, the batch still succeeds.',
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
title: 'Workflow F: Explore Graph',
|
|
51
|
+
steps: [
|
|
52
|
+
'`recall({ query, depth: 2 })` → `{ memories[], graph[], depth_reached, aborted }`',
|
|
53
|
+
"`get_relationships({ hash, direction: 'both' })` for a specific memory's edges",
|
|
54
|
+
],
|
|
55
|
+
notes: [
|
|
56
|
+
'BFS traversal emits progress per hop. Use `depth: 0` to skip traversal.',
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
];
|
|
41
60
|
function renderSharedConstraintsSection() {
|
|
42
61
|
return getSharedConstraints()
|
|
43
62
|
.map((c) => `- ${c}`)
|
|
44
63
|
.join('\n');
|
|
45
64
|
}
|
|
65
|
+
function renderWorkflowTrack(track) {
|
|
66
|
+
const stepLines = track.steps
|
|
67
|
+
.map((step, idx) => `${idx + 1}. ${step}`)
|
|
68
|
+
.join('\n');
|
|
69
|
+
const noteLines = track.notes.map((note) => `> ${note}`).join('\n');
|
|
70
|
+
return [`## ${track.title}`, '', stepLines, '', noteLines].join('\n');
|
|
71
|
+
}
|
|
72
|
+
function renderWorkflowTracks() {
|
|
73
|
+
return WORKFLOW_TRACKS.map(renderWorkflowTrack).join('\n\n');
|
|
74
|
+
}
|
|
46
75
|
export function buildWorkflowGuide() {
|
|
47
76
|
return [
|
|
48
77
|
'# Workflow Reference',
|
|
49
78
|
'',
|
|
50
|
-
|
|
79
|
+
renderWorkflowTracks(),
|
|
51
80
|
'',
|
|
52
81
|
'## Shared Constraints',
|
|
53
82
|
renderSharedConstraintsSection(),
|
package/dist/schemas/inputs.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ export declare const GetMemoryInputSchema: z.ZodObject<{
|
|
|
63
63
|
}, z.core.$strict>;
|
|
64
64
|
export declare const UpdateMemoryInputSchema: z.ZodObject<{
|
|
65
65
|
hash: z.ZodString;
|
|
66
|
-
content: z.ZodString
|
|
66
|
+
content: z.ZodOptional<z.ZodString>;
|
|
67
67
|
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
68
68
|
}, z.core.$strict>;
|
|
69
69
|
export declare const DeleteMemoryInputSchema: z.ZodObject<{
|
|
@@ -77,7 +77,7 @@ export declare const SearchMemoriesInputSchema: z.ZodObject<{
|
|
|
77
77
|
max_importance: z.ZodOptional<z.ZodNumber>;
|
|
78
78
|
memory_type: z.ZodOptional<typeof MEMORY_TYPE_SCHEMA>;
|
|
79
79
|
query: z.ZodString;
|
|
80
|
-
limit: z.ZodPrefault<z.ZodOptional<z.
|
|
80
|
+
limit: z.ZodPrefault<z.ZodOptional<z.ZodNumber>>;
|
|
81
81
|
cursor: z.ZodOptional<z.ZodString>;
|
|
82
82
|
}, z.core.$strict>;
|
|
83
83
|
export declare const RecallInputSchema: z.ZodObject<{
|
|
@@ -85,13 +85,16 @@ export declare const RecallInputSchema: z.ZodObject<{
|
|
|
85
85
|
max_importance: z.ZodOptional<z.ZodNumber>;
|
|
86
86
|
memory_type: z.ZodOptional<typeof MEMORY_TYPE_SCHEMA>;
|
|
87
87
|
query: z.ZodString;
|
|
88
|
-
depth: z.ZodPrefault<z.ZodOptional<z.
|
|
89
|
-
limit: z.ZodPrefault<z.ZodOptional<z.
|
|
88
|
+
depth: z.ZodPrefault<z.ZodOptional<z.ZodNumber>>;
|
|
89
|
+
limit: z.ZodPrefault<z.ZodOptional<z.ZodNumber>>;
|
|
90
90
|
cursor: z.ZodOptional<z.ZodString>;
|
|
91
91
|
}, z.core.$strict>;
|
|
92
92
|
export declare const RetrieveContextInputSchema: z.ZodObject<{
|
|
93
|
+
min_importance: z.ZodOptional<z.ZodNumber>;
|
|
94
|
+
max_importance: z.ZodOptional<z.ZodNumber>;
|
|
95
|
+
memory_type: z.ZodOptional<typeof MEMORY_TYPE_SCHEMA>;
|
|
93
96
|
query: z.ZodString;
|
|
94
|
-
token_budget: z.ZodPrefault<z.ZodOptional<z.
|
|
97
|
+
token_budget: z.ZodPrefault<z.ZodOptional<z.ZodNumber>>;
|
|
95
98
|
strategy: z.ZodPrefault<z.ZodOptional<z.ZodEnum<{
|
|
96
99
|
importance: "importance";
|
|
97
100
|
recency: "recency";
|