mcp-agents-memory 0.9.30 → 0.9.31

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/.env.example CHANGED
@@ -112,6 +112,11 @@ FORGETTING_INTERVAL_MIN=1440
112
112
  FORGET_THRESHOLD=0.5
113
113
 
114
114
  # Project Alias Promoter (Stage 2) — cold path alias suggestions; default OFF, auto-apply requires explicit opt-in.
115
+ # 콜드패스(태거·임베더·사서·프로모터)는 **메모리 DB 와 로컬 GPU(llama-server)가 같이 있는 기기에서만**
116
+ # 돈다. 그 외 기기는 순수 단말이어야 한다 — 같은 DB 의 advisory lock 을 공유하므로, GPU 없는 기기가
117
+ # 락을 잡으면 태깅이 실패하고 정작 돌아야 할 기기가 락을 못 잡는다.
118
+ # 전용 데몬(`mcp-agents-memory coldpath`, systemd)은 이 값과 무관하게 내부에서 켜고 돈다.
119
+ COLD_PATH_ENABLED=false
115
120
  PROJECT_ALIAS_PROMOTER_ENABLED=false
116
121
  PROJECT_ALIAS_PROMOTER_INTERVAL_HOURS=24
117
122
  PROJECT_ALIAS_AUTO_APPLY=false
package/build/index.js CHANGED
@@ -32765,6 +32765,21 @@ function locateBuzzContext(text) {
32765
32765
  }
32766
32766
  return CONTEXT_OPEN.test(rest.slice(pos, pos + 12)) ? { rest, pos } : null;
32767
32767
  }
32768
+ function historyBoundary(tail) {
32769
+ const history = HISTORY_OPEN.exec(tail);
32770
+ if (!history) return { kind: "none" };
32771
+ const closeTag = `</${history[1]}>`;
32772
+ const bodyStart = history[0].length;
32773
+ for (let close = tail.indexOf(closeTag, bodyStart), movedPast = false; close >= 0; close = tail.indexOf(closeTag, close + 1), movedPast = true) {
32774
+ const turnStart = close + closeTag.length;
32775
+ if (!TURN_OPEN.test(tail.slice(turnStart))) continue;
32776
+ if (movedPast && historyHidesTurn(tail.slice(0, close), tail.slice(bodyStart, close))) {
32777
+ return { kind: "unknown" };
32778
+ }
32779
+ return { kind: "span", bodyStart, bodyEnd: close, turnStart };
32780
+ }
32781
+ return { kind: "unknown" };
32782
+ }
32768
32783
  function cleanBuzzEnvelope(message, opts = {}) {
32769
32784
  try {
32770
32785
  const text = message.trimStart();
@@ -32779,14 +32794,12 @@ function cleanBuzzEnvelope(message, opts = {}) {
32779
32794
  const contextBody = rest.slice(bodyStart, contextClose).replace(/\r+$/, "");
32780
32795
  if (!hasBase && !(BUZZ_SCOPE.test(contextBody) && BUZZ_CHANNEL.test(contextBody))) return null;
32781
32796
  const tail = rest.slice(contextClose + CONTEXT_CLOSE.length);
32797
+ const hist = historyBoundary(tail);
32798
+ if (hist.kind === "unknown") return null;
32782
32799
  let turnStart = 0;
32783
- const history = HISTORY_OPEN.exec(tail);
32784
- if (history) {
32785
- const closeTag = `</${history[1]}>`;
32786
- const close = tail.indexOf(closeTag, history[0].length);
32787
- if (close < 0) return null;
32788
- if (historyHidesTurn(tail.slice(0, close), tail.slice(history[0].length, close))) return null;
32789
- turnStart = close + closeTag.length;
32800
+ if (hist.kind === "span") {
32801
+ if (historyHidesTurn(tail.slice(0, hist.bodyEnd), tail.slice(hist.bodyStart, hist.bodyEnd))) return null;
32802
+ turnStart = hist.turnStart;
32790
32803
  }
32791
32804
  if (TURN_IN_DROPPED.test(rest.slice(0, pos))) return null;
32792
32805
  const turn = tail.slice(turnStart);
@@ -32812,12 +32825,10 @@ function buzzQuotedMessages(message) {
32812
32825
  const contextClose = rest.indexOf(CONTEXT_CLOSE, pos);
32813
32826
  if (contextClose < 0) return null;
32814
32827
  const tail = rest.slice(contextClose + CONTEXT_CLOSE.length);
32815
- const history = HISTORY_OPEN.exec(tail);
32816
- if (!history) return [];
32817
- const closeTag = `</${history[1]}>`;
32818
- const close = tail.indexOf(closeTag, history[0].length);
32819
- if (close < 0) return null;
32820
- return parseQuoteBody(tail.slice(history[0].length, close));
32828
+ const hist = historyBoundary(tail);
32829
+ if (hist.kind === "none") return [];
32830
+ if (hist.kind === "unknown") return null;
32831
+ return parseQuoteBody(tail.slice(hist.bodyStart, hist.bodyEnd));
32821
32832
  } catch {
32822
32833
  return null;
32823
32834
  }
@@ -32844,12 +32855,9 @@ function historyHidesTurn(dropped, body) {
32844
32855
  }
32845
32856
  function turnAfterContext(tail) {
32846
32857
  if (TURN_OPEN.test(tail)) return tail;
32847
- const history = HISTORY_OPEN.exec(tail);
32848
- if (!history) return null;
32849
- const closeTag = `</${history[1]}>`;
32850
- const close = tail.indexOf(closeTag, history[0].length);
32851
- if (close < 0) return null;
32852
- const rest = tail.slice(close + closeTag.length);
32858
+ const hist = historyBoundary(tail);
32859
+ if (hist.kind !== "span") return null;
32860
+ const rest = tail.slice(hist.turnStart);
32853
32861
  return TURN_OPEN.test(rest) ? rest : null;
32854
32862
  }
32855
32863
  function envelopeTail(message) {
@@ -43353,6 +43361,7 @@ __export(buzz_ingest_exports, {
43353
43361
  newChatEvents: () => newChatEvents,
43354
43362
  ownerPubkeys: () => ownerPubkeys,
43355
43363
  parseIngestArgs: () => parseIngestArgs,
43364
+ recleanEnvelopes: () => recleanEnvelopes,
43356
43365
  runBuzzIngest: () => runBuzzIngest
43357
43366
  });
43358
43367
  import { execFile } from "node:child_process";
@@ -43635,6 +43644,13 @@ async function recleanEnvelopes(userId, budget, dryRun) {
43635
43644
  )).rows;
43636
43645
  const cands = [];
43637
43646
  const by = { shape: 0, noRow: 0, textDiffers: 0 };
43647
+ const stuckRows = [];
43648
+ const stuckOmitted = { shape: 0, noRow: 0, textDiffers: 0 };
43649
+ const PER_REASON_CAP = 8;
43650
+ const noteStuck = (id, why) => {
43651
+ if (stuckRows.filter((r) => r.why === why).length < PER_REASON_CAP) stuckRows.push({ id, why });
43652
+ else stuckOmitted[why]++;
43653
+ };
43638
43654
  for (const r of rows) {
43639
43655
  const cleaned = cleanBuzzEnvelope(r.message, { baseless: true });
43640
43656
  const quotes = buzzQuotedMessages(r.message);
@@ -43643,7 +43659,10 @@ async function recleanEnvelopes(userId, budget, dryRun) {
43643
43659
  const venue = [r.venue, venueFromBuzzMessage(r.message)].find((v) => typeof v === "string" && v.startsWith("buzz")) ?? null;
43644
43660
  const q = (quotes ?? []).map((x) => ({ ms: Date.parse(x.time), text: norm(x.content) }));
43645
43661
  if (cleaned === null || quotes === null || !venue || q.some((x) => !Number.isFinite(x.ms))) {
43646
- if (venue || looksLikeBuzzTurn(r.message)) by.shape++;
43662
+ if (venue || looksLikeBuzzTurn(r.message)) {
43663
+ by.shape++;
43664
+ noteStuck(Number(r.id), "shape");
43665
+ }
43647
43666
  continue;
43648
43667
  }
43649
43668
  const misread = quotes.some((x, i) => x.content.split("\n").some((line) => line.startsWith(`[${i + 2}] `)));
@@ -43668,15 +43687,29 @@ async function recleanEnvelopes(userId, budget, dryRun) {
43668
43687
  const ready = [];
43669
43688
  for (const c of cands) {
43670
43689
  if (c.quotes.every((x) => have.has(`${c.venue}\0${x.ms}\0${x.text}`))) ready.push(c);
43671
- else if (c.quotes.some((x) => !slots.has(`${c.venue}\0${x.ms}`))) by.noRow++;
43672
- else if (c.misread) by.shape++;
43673
- else by.textDiffers++;
43690
+ else if (c.quotes.some((x) => !slots.has(`${c.venue}\0${x.ms}`))) {
43691
+ by.noRow++;
43692
+ noteStuck(c.id, "noRow");
43693
+ } else if (c.misread) {
43694
+ by.shape++;
43695
+ noteStuck(c.id, "shape");
43696
+ } else {
43697
+ by.textDiffers++;
43698
+ noteStuck(c.id, "textDiffers");
43699
+ }
43674
43700
  }
43675
43701
  let n = 0;
43676
43702
  for (const c of ready.slice(0, Math.max(0, budget))) {
43677
43703
  if (dryRun || await replaceWithCleaned(c.id, c.cleaned, c.message, c.venue, c.priorRaw)) n++;
43678
43704
  }
43679
- return { recleaned: n, ready: ready.length - n, stuck: by.shape + by.noRow + by.textDiffers, by };
43705
+ return {
43706
+ recleaned: n,
43707
+ ready: ready.length - n,
43708
+ stuck: by.shape + by.noRow + by.textDiffers,
43709
+ by,
43710
+ stuckRows,
43711
+ stuckOmitted
43712
+ };
43680
43713
  }
43681
43714
  async function runBuzzIngest(opts = {}) {
43682
43715
  const dryRun = opts.dryRun ?? false;
@@ -43720,6 +43753,8 @@ async function runBuzzIngest(opts = {}) {
43720
43753
  envelopesReady: 0,
43721
43754
  envelopesStuck: 0,
43722
43755
  envelopesStuckBy: { shape: 0, noRow: 0, textDiffers: 0 },
43756
+ envelopesStuckRows: [],
43757
+ envelopesStuckOmitted: { shape: 0, noRow: 0, textDiffers: 0 },
43723
43758
  byVenue: {},
43724
43759
  ...dryRun ? { unsupported } : {}
43725
43760
  };
@@ -43762,6 +43797,8 @@ async function runBuzzIngest(opts = {}) {
43762
43797
  report.envelopesReady = env.ready;
43763
43798
  report.envelopesStuck = env.stuck;
43764
43799
  report.envelopesStuckBy = env.by;
43800
+ report.envelopesStuckRows = env.stuckRows;
43801
+ report.envelopesStuckOmitted = env.stuckOmitted;
43765
43802
  }
43766
43803
  return report;
43767
43804
  }
@@ -63729,9 +63766,14 @@ async function releaseColdPathLock() {
63729
63766
  } catch {
63730
63767
  }
63731
63768
  }
63769
+ function coldPathEnabled(value) {
63770
+ return (value ?? "").trim().toLowerCase() === "true";
63771
+ }
63732
63772
  async function startColdPathWorker() {
63733
- if (process.env.COLD_PATH_ENABLED === "false") {
63734
- console.error("\u{1F535} [ColdPath] disabled (COLD_PATH_ENABLED=false)");
63773
+ if (!coldPathEnabled(process.env.COLD_PATH_ENABLED)) {
63774
+ console.error(
63775
+ `\u{1F535} [ColdPath] disabled \u2014 COLD_PATH_ENABLED=${process.env.COLD_PATH_ENABLED ?? "(unset)"}. \uBA54\uBAA8\uB9AC DB\xB7GPU \uAC00 \uC788\uB294 \uAE30\uAE30\uC5D0\uC11C\uB9CC "true" \uB85C \uCF20\uB2E4 (\uC804\uC6A9 \uB370\uBAAC\uC740 \uB0B4\uBD80\uC5D0\uC11C \uCF20\uB2E4).`
63776
+ );
63735
63777
  return;
63736
63778
  }
63737
63779
  let got = false;
@@ -64164,12 +64206,14 @@ init_venue();
64164
64206
  import * as fs10 from "node:fs";
64165
64207
  import * as path10 from "node:path";
64166
64208
  import * as os13 from "node:os";
64167
- import { spawnSync } from "node:child_process";
64209
+ import { createRequire } from "node:module";
64168
64210
  import { createHash as createHash2 } from "node:crypto";
64169
64211
  var DEVICE_NAME10 = os13.hostname();
64170
64212
  var CODEX_HOME = process.env.CODEX_HOME ?? path10.join(os13.homedir(), ".codex");
64171
64213
  var SESSIONS_ROOT2 = path10.join(CODEX_HOME, "sessions");
64172
- var STATE_DB2 = path10.join(CODEX_HOME, "state_5.sqlite");
64214
+ function stateDbPath() {
64215
+ return path10.join(process.env.CODEX_HOME ?? path10.join(os13.homedir(), ".codex"), "state_5.sqlite");
64216
+ }
64173
64217
  var FLUSH_DEBOUNCE_MS5 = 200;
64174
64218
  var POLL_INTERVAL_MS6 = 3e3;
64175
64219
  function sourceToPlatform(source) {
@@ -64186,16 +64230,51 @@ function sourceToPlatform(source) {
64186
64230
  return "codex-mcp-client";
64187
64231
  }
64188
64232
  }
64233
+ function originatorToPlatform(originator) {
64234
+ const o = originator.trim().toLowerCase();
64235
+ if (!o) return null;
64236
+ if (o === "codex-tui") return "codex-cli";
64237
+ if (o === "codex_exec") return "codex-exec";
64238
+ if (o === "codex desktop") return "codex-desktop";
64239
+ if (o === "buzz-acp" || o.includes("codex-acp")) return "codex-acp";
64240
+ return null;
64241
+ }
64242
+ var _DatabaseSync3;
64243
+ function sqliteSync() {
64244
+ if (_DatabaseSync3 !== void 0) return _DatabaseSync3;
64245
+ try {
64246
+ _DatabaseSync3 = createRequire(import.meta.url)("node:sqlite")?.DatabaseSync ?? null;
64247
+ } catch {
64248
+ _DatabaseSync3 = null;
64249
+ }
64250
+ return _DatabaseSync3;
64251
+ }
64189
64252
  function lookupPlatform(sessionId) {
64253
+ const DatabaseSync = sqliteSync();
64254
+ if (!DatabaseSync) return "codex-mcp-client";
64255
+ let db2 = null;
64190
64256
  try {
64191
- const res = spawnSync(
64192
- "sqlite3",
64193
- [STATE_DB2, `SELECT source FROM threads WHERE id='${sessionId}' LIMIT 1;`],
64194
- { encoding: "utf-8", timeout: 500 }
64257
+ db2 = new DatabaseSync(stateDbPath(), { readOnly: true });
64258
+ const cols = new Set(
64259
+ db2.prepare("PRAGMA table_info(threads)").all().map((c) => String(c.name))
64195
64260
  );
64196
- const source = (res.stdout ?? "").trim();
64261
+ const hasOriginator = cols.has("originator");
64262
+ const row = db2.prepare(
64263
+ hasOriginator ? "SELECT source, originator FROM threads WHERE id = ? LIMIT 1" : "SELECT source FROM threads WHERE id = ? LIMIT 1"
64264
+ ).get(sessionId);
64265
+ if (!row) return "codex-mcp-client";
64266
+ if (hasOriginator && typeof row.originator === "string") {
64267
+ const byOriginator = originatorToPlatform(row.originator);
64268
+ if (byOriginator) return byOriginator;
64269
+ }
64270
+ const source = typeof row.source === "string" ? row.source.trim() : "";
64197
64271
  if (source) return sourceToPlatform(source);
64198
64272
  } catch {
64273
+ } finally {
64274
+ try {
64275
+ db2?.close();
64276
+ } catch {
64277
+ }
64199
64278
  }
64200
64279
  return "codex-mcp-client";
64201
64280
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-agents-memory",
3
- "version": "0.9.30",
3
+ "version": "0.9.31",
4
4
  "description": "Long-term memory for AI agents with provenance tracking",
5
5
  "main": "build/index.js",
6
6
  "type": "module",
@@ -22,13 +22,16 @@
22
22
  "setup": "npm run build && node build/index.js setup",
23
23
  "migrate": "npm run build && node build/index.js migrate",
24
24
  "bench:tagger": "npx tsx scripts/ab_tagger.ts",
25
+ "check:stuck-ids": "esbuild scripts/check_ingest_stuck_ids.ts --bundle --platform=node --format=esm --packages=external --outfile=node_modules/.cache/mcp-agents-memory/check_ingest_stuck_ids.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_ingest_stuck_ids.mjs",
26
+ "check:platform": "esbuild scripts/check_codex_platform.ts --bundle --platform=node --format=esm --packages=external --outfile=node_modules/.cache/mcp-agents-memory/check_codex_platform.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_codex_platform.mjs",
25
27
  "check:codex": "esbuild scripts/check_codex_capture.ts --bundle --platform=node --format=esm --packages=external --outfile=node_modules/.cache/mcp-agents-memory/check_codex_capture.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_codex_capture.mjs",
26
28
  "check:envelope": "esbuild scripts/check_buzz_envelope.ts --bundle --platform=node --format=esm --outfile=node_modules/.cache/mcp-agents-memory/check_buzz_envelope.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_buzz_envelope.mjs",
27
29
  "check:alias": "esbuild scripts/check_alias_reject.ts --bundle --platform=node --format=esm --outfile=node_modules/.cache/mcp-agents-memory/check_alias_reject.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_alias_reject.mjs",
28
30
  "check:dtag": "esbuild scripts/check_dtag_suggest.ts --bundle --platform=node --format=esm --outfile=node_modules/.cache/mcp-agents-memory/check_dtag_suggest.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_dtag_suggest.mjs",
29
31
  "check:registry": "esbuild scripts/check_project_registry.ts --bundle --platform=node --format=esm --outfile=node_modules/.cache/mcp-agents-memory/check_project_registry.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_project_registry.mjs",
30
32
  "check:alias-evidence": "esbuild scripts/check_alias_evidence.ts --bundle --platform=node --format=esm --outfile=node_modules/.cache/mcp-agents-memory/check_alias_evidence.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_alias_evidence.mjs",
31
- "check:retag": "esbuild scripts/check_ptag_retag.ts --bundle --platform=node --format=esm --outfile=node_modules/.cache/mcp-agents-memory/check_ptag_retag.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_ptag_retag.mjs"
33
+ "check:retag": "esbuild scripts/check_ptag_retag.ts --bundle --platform=node --format=esm --outfile=node_modules/.cache/mcp-agents-memory/check_ptag_retag.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_ptag_retag.mjs",
34
+ "check:coldpath-gate": "esbuild scripts/check_coldpath_gate.ts --bundle --platform=node --format=esm --packages=external --outfile=node_modules/.cache/mcp-agents-memory/check_coldpath_gate.mjs --log-level=warning && node node_modules/.cache/mcp-agents-memory/check_coldpath_gate.mjs"
32
35
  },
33
36
  "keywords": [
34
37
  "mcp",