cf-memory-mcp 3.44.0 → 3.45.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/bin/cf-memory-mcp.js +108 -4
- package/package.json +1 -1
package/bin/cf-memory-mcp.js
CHANGED
|
@@ -3969,6 +3969,10 @@ function parseCliArgs(rest) {
|
|
|
3969
3969
|
flags.card = true;
|
|
3970
3970
|
} else if (a === '--short') {
|
|
3971
3971
|
flags.short = true;
|
|
3972
|
+
} else if (a === '--age') {
|
|
3973
|
+
flags.age = true;
|
|
3974
|
+
} else if (a === '--quality') {
|
|
3975
|
+
flags.quality = true;
|
|
3972
3976
|
} else if (a === '--older-than') {
|
|
3973
3977
|
// Accept "7d" / "30d" / "12h" / raw number (days).
|
|
3974
3978
|
const raw = rest[++i] || '';
|
|
@@ -4131,6 +4135,22 @@ async function runResumeCli() {
|
|
|
4131
4135
|
process.exit(0);
|
|
4132
4136
|
}
|
|
4133
4137
|
|
|
4138
|
+
// --age: print just handoff_age_minutes (single integer).
|
|
4139
|
+
if (flags.age) {
|
|
4140
|
+
const ageMin = payload.resume_handoff?.handoff_age_minutes;
|
|
4141
|
+
if (typeof ageMin !== 'number') process.exit(3);
|
|
4142
|
+
process.stdout.write(String(ageMin) + '\n');
|
|
4143
|
+
process.exit(0);
|
|
4144
|
+
}
|
|
4145
|
+
|
|
4146
|
+
// --quality: print just quality_score (single float).
|
|
4147
|
+
if (flags.quality) {
|
|
4148
|
+
const q = payload.resume_handoff?.quality_score;
|
|
4149
|
+
if (typeof q !== 'number') process.exit(3);
|
|
4150
|
+
process.stdout.write(String(q) + '\n');
|
|
4151
|
+
process.exit(0);
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4134
4154
|
// --short: single line for tmux/status bars. "goal · status"
|
|
4135
4155
|
// truncated to terminal-friendly length.
|
|
4136
4156
|
if (flags.short) {
|
|
@@ -4923,6 +4943,8 @@ const PER_COMMAND_HELP = {
|
|
|
4923
4943
|
--chain Walk parent_session_id back; show the thread history.
|
|
4924
4944
|
--validate Check that files_touched + code_anchors still exist locally.
|
|
4925
4945
|
--raw Print just the raw handoff JSON (no envelope metadata).
|
|
4946
|
+
--age Print handoff_age_minutes (single integer).
|
|
4947
|
+
--quality Print quality_score (single float, 0-1).
|
|
4926
4948
|
--json, -j Full bootstrap payload as JSON.
|
|
4927
4949
|
Exit codes: 0 = found, 3 = no handoff / no data, 4 = --validate found missing files.`,
|
|
4928
4950
|
list: `cf-memory-mcp list [--status S] [--since ISO] [--repo PATH] [--limit N] [--json]
|
|
@@ -4950,10 +4972,13 @@ const PER_COMMAND_HELP = {
|
|
|
4950
4972
|
--all Delete ALL cf-memory disk caches.
|
|
4951
4973
|
--json, -j Emit a JSON list of removed paths.`,
|
|
4952
4974
|
export: `cf-memory-mcp export <session-id-or-prefix> [--md path]
|
|
4975
|
+
cf-memory-mcp export --all
|
|
4953
4976
|
Print a handoff as a JSON bundle to stdout (or write to file). For
|
|
4954
|
-
backup or cross-machine sync.
|
|
4977
|
+
backup or cross-machine sync. With --all, streams ALL handoffs as
|
|
4978
|
+
NDJSON (one bundle per line) suitable for piping to a file.
|
|
4955
4979
|
<session-id> Full UUID or short prefix (>=8 chars).
|
|
4956
|
-
--md <path> Write the JSON to a file
|
|
4980
|
+
--md <path> Write the JSON to a file (single-handoff mode).
|
|
4981
|
+
--all Stream all handoffs as NDJSON.`,
|
|
4957
4982
|
import: `cf-memory-mcp import [<file>|-] [--json]
|
|
4958
4983
|
Restore a handoff bundle into a NEW session (keep_open). Cross-machine
|
|
4959
4984
|
sync. Use "-" to read from stdin.
|
|
@@ -5131,12 +5156,91 @@ async function runExportCli() {
|
|
|
5131
5156
|
}
|
|
5132
5157
|
const { positional, flags } = parseCliArgs(process.argv.slice(3));
|
|
5133
5158
|
const sessionArg = positional[0];
|
|
5134
|
-
|
|
5135
|
-
|
|
5159
|
+
const exportAll = process.argv.includes('--all');
|
|
5160
|
+
if (!sessionArg && !exportAll) {
|
|
5161
|
+
console.error('Usage:');
|
|
5162
|
+
console.error(' cf-memory-mcp export <session-id-or-prefix> # single handoff bundle');
|
|
5163
|
+
console.error(' cf-memory-mcp export --all # all handoffs as NDJSON');
|
|
5136
5164
|
process.exit(1);
|
|
5137
5165
|
}
|
|
5138
5166
|
const server = new CFMemoryMCP();
|
|
5139
5167
|
server.logDebug = () => {};
|
|
5168
|
+
|
|
5169
|
+
// --all: stream every handoff as NDJSON (one bundle per line).
|
|
5170
|
+
if (exportAll) {
|
|
5171
|
+
// EPIPE handler: when piping to `head` etc., downstream closes
|
|
5172
|
+
// stdout while we're still writing. Exit cleanly instead of
|
|
5173
|
+
// dumping a Node stack trace.
|
|
5174
|
+
process.stdout.on('error', (err) => {
|
|
5175
|
+
if (err.code === 'EPIPE') process.exit(0);
|
|
5176
|
+
throw err;
|
|
5177
|
+
});
|
|
5178
|
+
try {
|
|
5179
|
+
// Page through all the user's handoffs via get_context_bootstrap
|
|
5180
|
+
// with recent_handoff_limit=50, sorted by recency. Use `since`
|
|
5181
|
+
// to walk back in time without dupes — query for entries before
|
|
5182
|
+
// the oldest one in the previous batch.
|
|
5183
|
+
const seen = new Set();
|
|
5184
|
+
let cursor = null; // ISO timestamp; entries with ended_at|started_at >= cursor are returned
|
|
5185
|
+
let totalEmitted = 0;
|
|
5186
|
+
for (let page = 0; page < 100; page++) {
|
|
5187
|
+
const args = { resume: true, recent_handoff_limit: 50 };
|
|
5188
|
+
const meta = server.getRepoMetadata();
|
|
5189
|
+
if (meta.repo_path) args.repo_path = meta.repo_path;
|
|
5190
|
+
if (cursor) args.since = cursor;
|
|
5191
|
+
const res = await server.makeRequest({
|
|
5192
|
+
jsonrpc: '2.0', id: `cli-export-all-${page}-${Date.now()}`,
|
|
5193
|
+
method: 'tools/call',
|
|
5194
|
+
params: { name: 'get_context_bootstrap', arguments: args },
|
|
5195
|
+
});
|
|
5196
|
+
const text = res?.result?.content?.[0]?.text;
|
|
5197
|
+
const payload = JSON.parse(text || '{}');
|
|
5198
|
+
const handoffs = payload.recent_handoffs || [];
|
|
5199
|
+
if (handoffs.length === 0) break;
|
|
5200
|
+
let newCount = 0;
|
|
5201
|
+
let oldestSeen = null;
|
|
5202
|
+
for (const h of handoffs) {
|
|
5203
|
+
if (seen.has(h.session_id)) continue;
|
|
5204
|
+
seen.add(h.session_id);
|
|
5205
|
+
// Fetch the full handoff (not just the summary).
|
|
5206
|
+
const fullRes = await server.makeRequest({
|
|
5207
|
+
jsonrpc: '2.0', id: `cli-export-all-detail-${Date.now()}`,
|
|
5208
|
+
method: 'tools/call',
|
|
5209
|
+
params: { name: 'get_context_bootstrap', arguments: { resume: true, session_id_hint: h.session_id } },
|
|
5210
|
+
});
|
|
5211
|
+
const fullText = fullRes?.result?.content?.[0]?.text;
|
|
5212
|
+
const fullPayload = JSON.parse(fullText || '{}');
|
|
5213
|
+
const envelope = fullPayload.resume_handoff;
|
|
5214
|
+
if (!envelope) continue;
|
|
5215
|
+
const bundle = {
|
|
5216
|
+
kind: 'cf-memory-handoff',
|
|
5217
|
+
version: 1,
|
|
5218
|
+
exported_at: new Date().toISOString(),
|
|
5219
|
+
session_id: envelope.session_id,
|
|
5220
|
+
started_at: envelope.started_at,
|
|
5221
|
+
ended_at: envelope.ended_at,
|
|
5222
|
+
handoff: envelope.handoff,
|
|
5223
|
+
};
|
|
5224
|
+
process.stdout.write(JSON.stringify(bundle) + '\n');
|
|
5225
|
+
totalEmitted++;
|
|
5226
|
+
newCount++;
|
|
5227
|
+
const t = envelope.ended_at || envelope.started_at;
|
|
5228
|
+
if (!oldestSeen || t > oldestSeen) oldestSeen = t;
|
|
5229
|
+
}
|
|
5230
|
+
// No new entries → we've exhausted the timeline.
|
|
5231
|
+
if (newCount === 0) break;
|
|
5232
|
+
// Step the cursor forward (next page returns entries from
|
|
5233
|
+
// after the oldest we saw).
|
|
5234
|
+
cursor = oldestSeen;
|
|
5235
|
+
}
|
|
5236
|
+
process.stderr.write(`Exported ${totalEmitted} handoffs.\n`);
|
|
5237
|
+
process.exit(totalEmitted === 0 ? 3 : 0);
|
|
5238
|
+
} catch (err) {
|
|
5239
|
+
console.error('export --all failed:', err.message);
|
|
5240
|
+
process.exit(1);
|
|
5241
|
+
}
|
|
5242
|
+
return;
|
|
5243
|
+
}
|
|
5140
5244
|
try {
|
|
5141
5245
|
const args = { resume: true, session_id_hint: sessionArg };
|
|
5142
5246
|
const response = await server.makeRequest({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cf-memory-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.45.0",
|
|
4
4
|
"description": "Cloudflare-hosted MCP server for code indexing, retrieval, and assistant memory with a direct remote MCP endpoint and local stdio bridge.",
|
|
5
5
|
"main": "bin/cf-memory-mcp.js",
|
|
6
6
|
"bin": {
|