@prom.codes/memory-mcp 0.11.1 → 0.11.3

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.
Files changed (2) hide show
  1. package/dist/bin.js +68 -16
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -676,6 +676,7 @@ var DEFAULT_BATCH2 = 128;
676
676
  var DEFAULT_BATCH_CHARS = 4e5;
677
677
  var DEFAULT_RETRIES2 = 4;
678
678
  var DEFAULT_BACKOFF2 = 250;
679
+ var DEFAULT_TIMEOUT_MS2 = 15e3;
679
680
  function sleep2(ms, signal) {
680
681
  return new Promise((resolve3, reject) => {
681
682
  if (signal?.aborted === true) {
@@ -707,6 +708,7 @@ var PrometheusEmbeddingProvider = class {
707
708
  #maxBatchChars;
708
709
  #maxRetries;
709
710
  #retryBaseMs;
711
+ #timeoutMs;
710
712
  #fetch;
711
713
  #identity = null;
712
714
  #identityPromise = null;
@@ -721,8 +723,12 @@ var PrometheusEmbeddingProvider = class {
721
723
  this.#url = `${(opts.baseUrl ?? DEFAULT_BASE).replace(/\/+$/, "")}/embed`;
722
724
  this.#batchSize = opts.batchSize ?? DEFAULT_BATCH2;
723
725
  this.#maxBatchChars = opts.maxBatchChars ?? DEFAULT_BATCH_CHARS;
726
+ if (opts.timeoutMs !== void 0 && (!Number.isInteger(opts.timeoutMs) || opts.timeoutMs < 0)) {
727
+ throw new Error(`PrometheusEmbeddingProvider: timeoutMs must be a non-negative integer (0 disables), got ${opts.timeoutMs}`);
728
+ }
724
729
  this.#maxRetries = opts.maxRetries ?? DEFAULT_RETRIES2;
725
730
  this.#retryBaseMs = opts.retryBaseMs ?? DEFAULT_BACKOFF2;
731
+ this.#timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
726
732
  this.#fetch = opts.fetch ?? fetch;
727
733
  }
728
734
  /**
@@ -792,8 +798,6 @@ var PrometheusEmbeddingProvider = class {
792
798
  method: "GET",
793
799
  headers: { authorization: `Bearer ${this.#apiKey}` }
794
800
  };
795
- if (signal !== void 0)
796
- init.signal = signal;
797
801
  const payload = await this.#requestJson(init, signal);
798
802
  if (payload?.ok !== true || typeof payload.fingerprint !== "string" || payload.fingerprint === "" || !Number.isInteger(payload.dimension) || payload.dimension <= 0) {
799
803
  throw nonRetryable2("prometheus-embed: malformed identity response");
@@ -827,8 +831,6 @@ var PrometheusEmbeddingProvider = class {
827
831
  },
828
832
  body: JSON.stringify({ input: batch, inputType })
829
833
  };
830
- if (signal !== void 0)
831
- init.signal = signal;
832
834
  const payload = await this.#requestJson(init, signal);
833
835
  if (payload?.ok !== true || !Array.isArray(payload.embeddings)) {
834
836
  throw nonRetryable2("prometheus-embed: malformed embed response");
@@ -864,8 +866,25 @@ var PrometheusEmbeddingProvider = class {
864
866
  let attempt = 0;
865
867
  let lastError = null;
866
868
  while (attempt <= this.#maxRetries) {
869
+ const controller = new AbortController();
870
+ let timedOut = false;
871
+ let timer;
872
+ if (this.#timeoutMs > 0) {
873
+ timer = setTimeout(() => {
874
+ timedOut = true;
875
+ controller.abort();
876
+ }, this.#timeoutMs);
877
+ timer.unref?.();
878
+ }
879
+ const onParentAbort = () => controller.abort();
880
+ if (signal !== void 0) {
881
+ if (signal.aborted)
882
+ controller.abort();
883
+ else
884
+ signal.addEventListener("abort", onParentAbort, { once: true });
885
+ }
867
886
  try {
868
- const res = await this.#fetch(this.#url, init);
887
+ const res = await this.#fetch(this.#url, { ...init, signal: controller.signal });
869
888
  if (res.status >= 500 && res.status < 600) {
870
889
  lastError = new Error(`prometheus-embed: HTTP ${res.status}`);
871
890
  attempt += 1;
@@ -881,15 +900,21 @@ var PrometheusEmbeddingProvider = class {
881
900
  }
882
901
  return await res.json();
883
902
  } catch (err) {
884
- if (err?.name === "AbortError")
903
+ if (err?.name === "AbortError" && !timedOut)
885
904
  throw err;
886
905
  if (err?.nonRetryable === true)
887
906
  throw err;
907
+ const retryErr = timedOut ? new Error(`prometheus-embed: request timed out after ${this.#timeoutMs}ms`) : err;
888
908
  if (attempt >= this.#maxRetries)
889
- throw err;
890
- lastError = err;
909
+ throw retryErr;
910
+ lastError = retryErr;
891
911
  attempt += 1;
892
912
  await sleep2(this.#retryBaseMs * 2 ** (attempt - 1), signal);
913
+ } finally {
914
+ if (timer !== void 0)
915
+ clearTimeout(timer);
916
+ if (signal !== void 0)
917
+ signal.removeEventListener("abort", onParentAbort);
893
918
  }
894
919
  }
895
920
  throw lastError instanceof Error ? lastError : new Error(`prometheus-embed: exhausted ${this.#maxRetries} retries`);
@@ -1076,6 +1101,7 @@ var DEFAULT_BATCH4 = 100;
1076
1101
  var DEFAULT_BATCH_CHARS2 = 4e5;
1077
1102
  var DEFAULT_RETRIES4 = 4;
1078
1103
  var DEFAULT_BACKOFF4 = 250;
1104
+ var DEFAULT_TIMEOUT_MS3 = 15e3;
1079
1105
  function sleep4(ms, signal) {
1080
1106
  return new Promise((resolve3, reject) => {
1081
1107
  if (signal?.aborted === true) {
@@ -1108,6 +1134,7 @@ var PrometheusRerankProvider = class {
1108
1134
  #maxBatchChars;
1109
1135
  #maxRetries;
1110
1136
  #retryBaseMs;
1137
+ #timeoutMs;
1111
1138
  #fetch;
1112
1139
  #creditsUsed = 0;
1113
1140
  constructor(opts) {
@@ -1124,8 +1151,12 @@ var PrometheusRerankProvider = class {
1124
1151
  this.#url = `${(opts.baseUrl ?? DEFAULT_BASE2).replace(/\/+$/, "")}/rerank`;
1125
1152
  this.#batchSize = opts.batchSize ?? DEFAULT_BATCH4;
1126
1153
  this.#maxBatchChars = opts.maxBatchChars ?? DEFAULT_BATCH_CHARS2;
1154
+ if (opts.timeoutMs !== void 0 && (!Number.isInteger(opts.timeoutMs) || opts.timeoutMs < 0)) {
1155
+ throw new Error(`PrometheusRerankProvider: timeoutMs must be a non-negative integer (0 disables), got ${opts.timeoutMs}`);
1156
+ }
1127
1157
  this.#maxRetries = opts.maxRetries ?? DEFAULT_RETRIES4;
1128
1158
  this.#retryBaseMs = opts.retryBaseMs ?? DEFAULT_BACKOFF4;
1159
+ this.#timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
1129
1160
  this.#fetch = opts.fetch ?? fetch;
1130
1161
  }
1131
1162
  /** Cumulative credits charged across all rerank calls of this instance. */
@@ -1184,8 +1215,6 @@ var PrometheusRerankProvider = class {
1184
1215
  },
1185
1216
  body: JSON.stringify({ query, documents: batch.map((c) => c.text) })
1186
1217
  };
1187
- if (signal !== void 0)
1188
- init.signal = signal;
1189
1218
  const payload = await this.#requestJson(init, signal);
1190
1219
  if (payload?.ok !== true || !Array.isArray(payload.results)) {
1191
1220
  throw nonRetryable4("prometheus-rerank: malformed rerank response");
@@ -1217,8 +1246,25 @@ var PrometheusRerankProvider = class {
1217
1246
  let attempt = 0;
1218
1247
  let lastError = null;
1219
1248
  while (attempt <= this.#maxRetries) {
1249
+ const controller = new AbortController();
1250
+ let timedOut = false;
1251
+ let timer;
1252
+ if (this.#timeoutMs > 0) {
1253
+ timer = setTimeout(() => {
1254
+ timedOut = true;
1255
+ controller.abort();
1256
+ }, this.#timeoutMs);
1257
+ timer.unref?.();
1258
+ }
1259
+ const onParentAbort = () => controller.abort();
1260
+ if (signal !== void 0) {
1261
+ if (signal.aborted)
1262
+ controller.abort();
1263
+ else
1264
+ signal.addEventListener("abort", onParentAbort, { once: true });
1265
+ }
1220
1266
  try {
1221
- const res = await this.#fetch(this.#url, init);
1267
+ const res = await this.#fetch(this.#url, { ...init, signal: controller.signal });
1222
1268
  if (res.status >= 500 && res.status < 600) {
1223
1269
  lastError = new Error(`prometheus-rerank: HTTP ${res.status}`);
1224
1270
  attempt += 1;
@@ -1234,15 +1280,21 @@ var PrometheusRerankProvider = class {
1234
1280
  }
1235
1281
  return await res.json();
1236
1282
  } catch (err) {
1237
- if (err?.name === "AbortError")
1283
+ if (err?.name === "AbortError" && !timedOut)
1238
1284
  throw err;
1239
1285
  if (err?.nonRetryable === true)
1240
1286
  throw err;
1287
+ const retryErr = timedOut ? new Error(`prometheus-rerank: request timed out after ${this.#timeoutMs}ms`) : err;
1241
1288
  if (attempt >= this.#maxRetries)
1242
- throw err;
1243
- lastError = err;
1289
+ throw retryErr;
1290
+ lastError = retryErr;
1244
1291
  attempt += 1;
1245
1292
  await sleep4(this.#retryBaseMs * 2 ** (attempt - 1), signal);
1293
+ } finally {
1294
+ if (timer !== void 0)
1295
+ clearTimeout(timer);
1296
+ if (signal !== void 0)
1297
+ signal.removeEventListener("abort", onParentAbort);
1246
1298
  }
1247
1299
  }
1248
1300
  throw lastError instanceof Error ? lastError : new Error(`prometheus-rerank: exhausted ${this.#maxRetries} retries`);
@@ -3371,7 +3423,7 @@ ${f.value}`);
3371
3423
  embeddingsError = err instanceof Error ? err.message : String(err);
3372
3424
  }
3373
3425
  }
3374
- const update = await buildUpdateStatus("@prom.codes/memory-mcp", "0.11.1", { isDevBuild: false });
3426
+ const update = await buildUpdateStatus("@prom.codes/memory-mcp", "0.11.3", { isDevBuild: false });
3375
3427
  const summary = deps.rootIsHomeOrFsRoot ? `Memory at ${dbPath}: ${stats.total} records, but the workspace resolved to ${workspaceRoot} (home/root) \u2014 open a project folder so memories scope and mirror correctly.` : `Memory at ${dbPath}: ${stats.total} records for project "${projectName}".${update.updateAvailable === true ? ` Update available: ${update.current} \u2192 ${update.latest} (ask me to run update via the context server's update_servers tool).` : ""}`;
3376
3428
  return textResult({
3377
3429
  installed: true,
@@ -3407,7 +3459,7 @@ ${f.value}`);
3407
3459
  // dist/server.js
3408
3460
  var SERVER_IDENTITY = {
3409
3461
  name: "prometheus-memory-mcp",
3410
- version: "0.11.1",
3462
+ version: "0.11.3",
3411
3463
  title: "prom.codes Memory"
3412
3464
  };
3413
3465
  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.";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prom.codes/memory-mcp",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "description": "prom.codes Memory — persistent, local-first agent memory as an MCP server.",
5
5
  "type": "module",
6
6
  "bin": {