@prom.codes/memory-mcp 0.10.0 → 0.10.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/bin.js +57 -10
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -194,9 +194,6 @@ function isHomeOrFilesystemRoot(root) {
|
|
|
194
194
|
return false;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
// ../shared/dist/index.js
|
|
198
|
-
var PROMETHEUS_VERSION = "0.1.0";
|
|
199
|
-
|
|
200
197
|
// dist/composition.js
|
|
201
198
|
import { createHash } from "node:crypto";
|
|
202
199
|
import { homedir as homedir3 } from "node:os";
|
|
@@ -876,6 +873,7 @@ var DEFAULT_BASE2 = "https://api.prom.codes";
|
|
|
876
873
|
var DEFAULT_NAME = "prometheus";
|
|
877
874
|
var DEFAULT_MODEL2 = "prometheus";
|
|
878
875
|
var DEFAULT_BATCH4 = 100;
|
|
876
|
+
var DEFAULT_BATCH_CHARS2 = 4e5;
|
|
879
877
|
var DEFAULT_RETRIES4 = 4;
|
|
880
878
|
var DEFAULT_BACKOFF4 = 250;
|
|
881
879
|
function sleep4(ms, signal) {
|
|
@@ -907,6 +905,7 @@ var PrometheusRerankProvider = class {
|
|
|
907
905
|
#apiKey;
|
|
908
906
|
#url;
|
|
909
907
|
#batchSize;
|
|
908
|
+
#maxBatchChars;
|
|
910
909
|
#maxRetries;
|
|
911
910
|
#retryBaseMs;
|
|
912
911
|
#fetch;
|
|
@@ -924,6 +923,7 @@ var PrometheusRerankProvider = class {
|
|
|
924
923
|
this.#apiKey = opts.apiKey;
|
|
925
924
|
this.#url = `${(opts.baseUrl ?? DEFAULT_BASE2).replace(/\/+$/, "")}/rerank`;
|
|
926
925
|
this.#batchSize = opts.batchSize ?? DEFAULT_BATCH4;
|
|
926
|
+
this.#maxBatchChars = opts.maxBatchChars ?? DEFAULT_BATCH_CHARS2;
|
|
927
927
|
this.#maxRetries = opts.maxRetries ?? DEFAULT_RETRIES4;
|
|
928
928
|
this.#retryBaseMs = opts.retryBaseMs ?? DEFAULT_BACKOFF4;
|
|
929
929
|
this.#fetch = opts.fetch ?? fetch;
|
|
@@ -937,21 +937,44 @@ var PrometheusRerankProvider = class {
|
|
|
937
937
|
return [];
|
|
938
938
|
const all = new Array(candidates.length);
|
|
939
939
|
let cursor = 0;
|
|
940
|
-
|
|
941
|
-
|
|
940
|
+
let start = 0;
|
|
941
|
+
while (start < candidates.length) {
|
|
942
|
+
const end = this.#batchEnd(query, candidates, start);
|
|
943
|
+
const slice = candidates.slice(start, end);
|
|
942
944
|
const scored = await this.#rerankBatch(query, slice, opts?.signal);
|
|
943
945
|
for (const hit of scored) {
|
|
944
946
|
const globalIndex = start + hit.localIndex;
|
|
945
947
|
const cand = candidates[globalIndex];
|
|
946
948
|
all[cursor++] = { id: cand.id, index: globalIndex, score: hit.score };
|
|
947
949
|
}
|
|
950
|
+
start = end;
|
|
948
951
|
}
|
|
952
|
+
all.length = cursor;
|
|
949
953
|
all.sort((a, b) => b.score - a.score);
|
|
950
954
|
if (opts?.topK !== void 0 && opts.topK >= 0 && opts.topK < all.length) {
|
|
951
955
|
return all.slice(0, opts.topK);
|
|
952
956
|
}
|
|
953
957
|
return all;
|
|
954
958
|
}
|
|
959
|
+
/**
|
|
960
|
+
* Greedy batch cut honouring both the document-count cap and the
|
|
961
|
+
* char budget (query + documents must stay under the proxy limit).
|
|
962
|
+
* Always advances by at least one candidate, even if a single
|
|
963
|
+
* document alone exceeds the budget (the proxy applies upstream
|
|
964
|
+
* truncation; refusing to send it would strand the rest).
|
|
965
|
+
*/
|
|
966
|
+
#batchEnd(query, candidates, start) {
|
|
967
|
+
let chars = query.length;
|
|
968
|
+
let end = start;
|
|
969
|
+
while (end < candidates.length && end - start < this.#batchSize) {
|
|
970
|
+
const len = candidates[end].text.length;
|
|
971
|
+
if (end > start && chars + len > this.#maxBatchChars)
|
|
972
|
+
break;
|
|
973
|
+
chars += len;
|
|
974
|
+
end += 1;
|
|
975
|
+
}
|
|
976
|
+
return end;
|
|
977
|
+
}
|
|
955
978
|
async #rerankBatch(query, batch, signal) {
|
|
956
979
|
const init = {
|
|
957
980
|
method: "POST",
|
|
@@ -2907,14 +2930,16 @@ var setupInput = {
|
|
|
2907
2930
|
runtimes: z.array(runtimeEnum).min(1).optional()
|
|
2908
2931
|
};
|
|
2909
2932
|
var emptyInput = {};
|
|
2910
|
-
function registerTools(server,
|
|
2911
|
-
const
|
|
2912
|
-
const mirrorToFiles = !deps.rootIsHomeOrFsRoot;
|
|
2933
|
+
function registerTools(server, source) {
|
|
2934
|
+
const ready = typeof source === "function" ? source : () => Promise.resolve(source);
|
|
2913
2935
|
server.registerTool("read", {
|
|
2914
2936
|
title: "Recall agent memory",
|
|
2915
2937
|
description: "Read agent memory for this project along the scope chain (project \u2192 workspace \u2192 tenant \u2192 system; narrowest scope wins). Syncs `.prometheus/memories/*.md` first, then returns the resolved records plus a prompt-ready `woven` markdown block (token-capped). Call this at the START of a session or task to recall what earlier sessions learned.",
|
|
2916
2938
|
inputSchema: readInput
|
|
2917
2939
|
}, async (args) => {
|
|
2940
|
+
const deps = await ready();
|
|
2941
|
+
const { backend, workspaceRoot, projectId, projectName } = deps;
|
|
2942
|
+
const mirrorToFiles = !deps.rootIsHomeOrFsRoot;
|
|
2918
2943
|
const limit = clampLimit(args.limit, DEFAULT_READ_LIMIT);
|
|
2919
2944
|
const synced = mirrorToFiles ? await syncProjectFiles(backend, { projectId, workspaceRoot }) : 0;
|
|
2920
2945
|
const records = await backend.read({
|
|
@@ -2935,6 +2960,9 @@ function registerTools(server, deps) {
|
|
|
2935
2960
|
description: "Upsert one memory record (identity: scope+type+key). Use type `semantic` for durable facts, `procedural` for how-to knowledge, `episodic` for session events, `working` for short-lived notes. Default scope `project` also mirrors the value to `.prometheus/memories/<key>.md` (git-versioned, human-editable). Values matching the secret deny-list are rejected. Call this whenever the user states a durable preference, decision, or correction worth remembering.",
|
|
2936
2961
|
inputSchema: writeInput
|
|
2937
2962
|
}, async (args) => {
|
|
2963
|
+
const deps = await ready();
|
|
2964
|
+
const { backend, workspaceRoot, projectId } = deps;
|
|
2965
|
+
const mirrorToFiles = !deps.rootIsHomeOrFsRoot;
|
|
2938
2966
|
assertValueSize(args.value);
|
|
2939
2967
|
assertNoSecrets(`${args.key}
|
|
2940
2968
|
${args.value}`);
|
|
@@ -2962,6 +2990,7 @@ ${args.value}`);
|
|
|
2962
2990
|
description: "Session-end consolidation: `plan`/`outcome` become one episodic record (key = sessionId), `facts` become semantic upserts, `procedures` become procedural upserts. Secret-bearing payloads are rejected. Call this at the END of a session to persist what was learned.",
|
|
2963
2991
|
inputSchema: captureInput
|
|
2964
2992
|
}, async (args) => {
|
|
2993
|
+
const { backend, projectId, extractor } = await ready();
|
|
2965
2994
|
const texts = [
|
|
2966
2995
|
args.plan ?? "",
|
|
2967
2996
|
args.outcome ?? "",
|
|
@@ -3025,6 +3054,9 @@ ${f.value}`);
|
|
|
3025
3054
|
description: "Full-text search (FTS5) over memory keys and values within this project's scope chain, ranked by relevance. Returns matching records plus a highlighted snippet per hit. Use this when memory_read's recall is not specific enough. Does not bump useCount.",
|
|
3026
3055
|
inputSchema: searchInput
|
|
3027
3056
|
}, async (args) => {
|
|
3057
|
+
const deps = await ready();
|
|
3058
|
+
const { backend, workspaceRoot, projectId } = deps;
|
|
3059
|
+
const mirrorToFiles = !deps.rootIsHomeOrFsRoot;
|
|
3028
3060
|
const limit = clampLimit(args.limit, 20);
|
|
3029
3061
|
if (mirrorToFiles)
|
|
3030
3062
|
await syncProjectFiles(backend, { projectId, workspaceRoot });
|
|
@@ -3048,6 +3080,7 @@ ${f.value}`);
|
|
|
3048
3080
|
description: "Flat listing of this project's memory records without scope resolution \u2014 inspection/debug surface. Optional filters: scope, type, keyContains (case-insensitive substring).",
|
|
3049
3081
|
inputSchema: listInput
|
|
3050
3082
|
}, async (args) => {
|
|
3083
|
+
const { backend, projectId, projectName, dbPath } = await ready();
|
|
3051
3084
|
const limit = clampLimit(args.limit, DEFAULT_READ_LIMIT);
|
|
3052
3085
|
const records = await backend.list({
|
|
3053
3086
|
projectId,
|
|
@@ -3068,6 +3101,9 @@ ${f.value}`);
|
|
|
3068
3101
|
description: "Delete one memory record by identity (scope+type+key). For project-scoped semantic records the mirrored `.prometheus/memories/<key>.md` file is removed as well. Returns whether a record/file was actually removed.",
|
|
3069
3102
|
inputSchema: deleteInput
|
|
3070
3103
|
}, async (args) => {
|
|
3104
|
+
const deps = await ready();
|
|
3105
|
+
const { backend, workspaceRoot, projectId } = deps;
|
|
3106
|
+
const mirrorToFiles = !deps.rootIsHomeOrFsRoot;
|
|
3071
3107
|
const scope = args.scope;
|
|
3072
3108
|
const removed = await backend.delete({
|
|
3073
3109
|
projectId,
|
|
@@ -3087,6 +3123,9 @@ ${f.value}`);
|
|
|
3087
3123
|
description: "Idempotently install the Prometheus memory-protocol rule block into agent runtime configs in this workspace: CLAUDE.md (claude-code), .cursor/rules/prometheus-memory.mdc (cursor), .augment/rules/prometheus-memory.md (augment), AGENTS.md (agents). Without `runtimes` it auto-detects which runtimes are present (fallback: agents). Only the marked block is written \u2014 existing content is never touched. Re-running updates the block in place.",
|
|
3088
3124
|
inputSchema: setupInput
|
|
3089
3125
|
}, async (args) => {
|
|
3126
|
+
const deps = await ready();
|
|
3127
|
+
const { workspaceRoot } = deps;
|
|
3128
|
+
const mirrorToFiles = !deps.rootIsHomeOrFsRoot;
|
|
3090
3129
|
if (!mirrorToFiles) {
|
|
3091
3130
|
return textResult({
|
|
3092
3131
|
workspaceRoot,
|
|
@@ -3106,6 +3145,9 @@ ${f.value}`);
|
|
|
3106
3145
|
description: "Health check for this project's agent memory. Reports the resolved workspace root, project id, DB path, how many records are stored (total + by scope), the embedding provider with a zero-cost key-reachability probe, and which quality levers are active (rerank / rewrite / temporal). CALL THIS to confirm where memory is stored, how much is there, and whether the API key works.",
|
|
3107
3146
|
inputSchema: emptyInput
|
|
3108
3147
|
}, async () => {
|
|
3148
|
+
const deps = await ready();
|
|
3149
|
+
const { backend, workspaceRoot, projectId, projectName, dbPath } = deps;
|
|
3150
|
+
const mirrorToFiles = !deps.rootIsHomeOrFsRoot;
|
|
3109
3151
|
const stats = await backend.stats(projectId);
|
|
3110
3152
|
let embeddingsReachable = null;
|
|
3111
3153
|
let embeddingsError = null;
|
|
@@ -3153,7 +3195,7 @@ ${f.value}`);
|
|
|
3153
3195
|
// dist/server.js
|
|
3154
3196
|
var SERVER_IDENTITY = {
|
|
3155
3197
|
name: "prometheus-memory-mcp",
|
|
3156
|
-
version:
|
|
3198
|
+
version: "0.10.2",
|
|
3157
3199
|
title: "prom.codes Memory"
|
|
3158
3200
|
};
|
|
3159
3201
|
var SERVER_INSTRUCTIONS = "Persistent agent memory for this workspace \u2014 USE IT PROACTIVELY; the user will not tell you to. Protocol:\n1. ONE-TIME: if this workspace has no Prometheus memory rule yet, call memory_setup now (idempotent) so the protocol is installed into the runtime rule files and survives future sessions. (The server also auto-installs it on startup when a project rule file already exists \u2014 memory_setup covers the rest.)\n2. SESSION START: before any non-trivial task, call memory_read to recall facts, decisions and procedures from earlier sessions.\n3. DURING WORK: when the user states a durable preference, decision, correction or project fact, store it with memory_write (semantic for facts, procedural for how-tos) \u2014 without being asked.\n4. LOOK-UP: use memory_search for keyword recall when memory_read is not specific enough.\n5. SESSION END: consolidate what was learned with memory_capture.\nCall memory_status anytime to check what is stored and whether the rule is installed. Never store secrets, API keys or credentials \u2014 such writes are rejected.";
|
|
@@ -3175,6 +3217,11 @@ async function main() {
|
|
|
3175
3217
|
instructions: SERVER_INSTRUCTIONS
|
|
3176
3218
|
});
|
|
3177
3219
|
let composed = null;
|
|
3220
|
+
let composedResolve;
|
|
3221
|
+
const composedReady = new Promise((res) => {
|
|
3222
|
+
composedResolve = res;
|
|
3223
|
+
});
|
|
3224
|
+
registerTools(server, () => composedReady);
|
|
3178
3225
|
const shutdown = async (signal) => {
|
|
3179
3226
|
process.stderr.write(`prometheus-memory-mcp: received ${signal}, shutting down
|
|
3180
3227
|
`);
|
|
@@ -3208,7 +3255,7 @@ async function main() {
|
|
|
3208
3255
|
}).catch(() => {
|
|
3209
3256
|
});
|
|
3210
3257
|
}
|
|
3211
|
-
|
|
3258
|
+
composedResolve(composed);
|
|
3212
3259
|
};
|
|
3213
3260
|
if (eagerVia !== null) {
|
|
3214
3261
|
boot(void 0, eagerVia);
|