@vedtechsolutions/engram-mcp 1.0.19 → 1.0.20

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.
@@ -11178,14 +11178,17 @@ function inferRole(nodeType, filePath, analysis) {
11178
11178
 
11179
11179
  // src/engines/curator.ts
11180
11180
  import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync, realpathSync as realpathSync2, lstatSync as lstatSync2, renameSync } from "fs";
11181
- import { join as join5, dirname as dirname3 } from "path";
11181
+ import { join as join5, dirname as dirname3, resolve as resolve3 } from "path";
11182
11182
  import { homedir as homedir3 } from "os";
11183
11183
  var logger14 = createLogger("curator");
11184
11184
  var lastBridgeWriteTime = 0;
11185
11185
  function discoverMemoryDir(cwd) {
11186
11186
  const envDir = process.env.CLAUDE_MEMORY_DIR;
11187
- if (envDir && existsSync5(envDir)) {
11188
- return envDir;
11187
+ if (envDir && envDir.startsWith("/") && !envDir.includes("\0") && envDir.length < 1e3) {
11188
+ const resolvedEnv = resolve3(envDir);
11189
+ if (resolvedEnv === resolve3(resolvedEnv) && existsSync5(resolvedEnv)) {
11190
+ return resolvedEnv;
11191
+ }
11189
11192
  }
11190
11193
  const home = homedir3();
11191
11194
  const projectsBase = join5(home, ".claude", "projects");
@@ -12672,4 +12675,4 @@ export {
12672
12675
  composeProjectUnderstanding,
12673
12676
  formatMentalModelInjection
12674
12677
  };
12675
- //# sourceMappingURL=chunk-OY2XHPUF.js.map
12678
+ //# sourceMappingURL=chunk-O3ZP4K3T.js.map
package/dist/hook.js CHANGED
@@ -174,10 +174,10 @@ import {
174
174
  updateReasoningChain,
175
175
  updateSelfModelFromSession,
176
176
  updateTask
177
- } from "./chunk-OY2XHPUF.js";
177
+ } from "./chunk-O3ZP4K3T.js";
178
178
 
179
179
  // src/hook.ts
180
- import { readFileSync, writeFileSync, existsSync, renameSync, statSync, readdirSync, unlinkSync, appendFileSync, openSync, readSync, closeSync } from "fs";
180
+ import { readFileSync, writeFileSync, existsSync, renameSync, statSync, readdirSync, unlinkSync, openSync, readSync, closeSync } from "fs";
181
181
  import { join, basename, resolve } from "path";
182
182
  import { homedir } from "os";
183
183
 
@@ -2886,15 +2886,39 @@ function readStdin() {
2886
2886
  return;
2887
2887
  }
2888
2888
  let data = "";
2889
+ const MAX_STDIN_BYTES = 10 * 1024 * 1024;
2889
2890
  process.stdin.setEncoding("utf-8");
2890
2891
  process.stdin.on("data", (chunk) => {
2891
2892
  data += chunk;
2893
+ if (data.length > MAX_STDIN_BYTES) {
2894
+ data = data.slice(0, MAX_STDIN_BYTES);
2895
+ process.stdin.destroy();
2896
+ resolve2(data);
2897
+ }
2892
2898
  });
2893
2899
  process.stdin.on("end", () => resolve2(data));
2894
2900
  process.stdin.on("error", () => resolve2(""));
2895
2901
  setTimeout(() => resolve2(data), 2e3);
2896
2902
  });
2897
2903
  }
2904
+ function validateTranscriptPath(p) {
2905
+ if (!p || typeof p !== "string") return null;
2906
+ const resolved = resolve(p);
2907
+ const allowed = join(homedir(), ".claude", "projects");
2908
+ if (!resolved.startsWith(allowed + "/") || !resolved.endsWith(".jsonl")) return null;
2909
+ return resolved;
2910
+ }
2911
+ function validateSessionId(sid) {
2912
+ if (!sid || typeof sid !== "string") return null;
2913
+ if (!/^[a-zA-Z0-9_-]{1,100}$/.test(sid)) return null;
2914
+ return sid;
2915
+ }
2916
+ function validateCwd(cwd) {
2917
+ if (!cwd || typeof cwd !== "string") return null;
2918
+ if (!cwd.startsWith("/")) return null;
2919
+ if (cwd.includes("\0") || cwd.length > 1e3) return null;
2920
+ return cwd;
2921
+ }
2898
2922
  function distillLesson(context) {
2899
2923
  const parts = [];
2900
2924
  if (context.errors && context.errors.length > 0 && context.fix) {
@@ -3346,6 +3370,12 @@ function writeSessionHandoff(state, narrative) {
3346
3370
  reasoning_trail: reasoningTrail.slice(0, 10)
3347
3371
  };
3348
3372
  try {
3373
+ const serialized = JSON.stringify(handoff, null, 2);
3374
+ if (serialized.length > 65536) {
3375
+ log.warn("Session handoff too large, truncating", { size: serialized.length });
3376
+ handoff.reasoning_trail = handoff.reasoning_trail.slice(0, 3);
3377
+ handoff.lessons = handoff.lessons.slice(0, 3);
3378
+ }
3349
3379
  const tmpPath = handoffPath + ".tmp";
3350
3380
  writeFileSync(tmpPath, JSON.stringify(handoff, null, 2), "utf-8");
3351
3381
  renameSync(tmpPath, handoffPath);
@@ -3466,16 +3496,16 @@ var [command, ...args] = process.argv.slice(2);
3466
3496
  async function main() {
3467
3497
  const stdinRaw = await readStdin();
3468
3498
  const stdinJson = safeParse(stdinRaw);
3469
- const stdinSessionId = stdinJson?.session_id;
3470
- if (stdinSessionId && typeof stdinSessionId === "string" && stdinSessionId.length > 0 && stdinSessionId.length <= 200) {
3471
- activeSessionId = stdinSessionId;
3499
+ const validatedSessionId = validateSessionId(stdinJson?.session_id);
3500
+ if (validatedSessionId) {
3501
+ activeSessionId = validatedSessionId;
3472
3502
  } else if (process.env.ENGRAM_SESSION_ID) {
3473
- activeSessionId = process.env.ENGRAM_SESSION_ID;
3503
+ const envSessionId = validateSessionId(process.env.ENGRAM_SESSION_ID);
3504
+ if (envSessionId) activeSessionId = envSessionId;
3474
3505
  }
3475
3506
  migrateLegacyWatcherState();
3476
3507
  try {
3477
- const stdinCwd = stdinJson?.cwd;
3478
- const cwdForDb = stdinCwd ?? process.cwd();
3508
+ const cwdForDb = validateCwd(stdinJson?.cwd) ?? process.cwd();
3479
3509
  const projectRoot = inferProjectPath(cwdForDb);
3480
3510
  const projectDbPath = deriveProjectDbPath(projectRoot);
3481
3511
  initProjectDatabase(projectDbPath);
@@ -3496,29 +3526,12 @@ async function main() {
3496
3526
  handlePostToolGeneric(stdinJson);
3497
3527
  break;
3498
3528
  case "notification": {
3499
- try {
3500
- appendFileSync(
3501
- join(homedir(), ".engram", "notification-debug.log"),
3502
- `[${(/* @__PURE__ */ new Date()).toISOString()}] NOTIFICATION stdin_keys=${Object.keys(stdinJson ?? {}).join(",")}
3503
- `
3504
- );
3505
- } catch {
3506
- }
3507
3529
  const notifType = stdinJson?.notification_type ?? args[0] ?? "general";
3508
3530
  const notifMessage = stdinJson?.message ?? args[1] ?? "";
3509
3531
  handleNotification(notifType, notifMessage);
3510
3532
  break;
3511
3533
  }
3512
3534
  case "session-start":
3513
- try {
3514
- const src = stdinJson?.source ?? "unknown";
3515
- appendFileSync(
3516
- join(homedir(), ".engram", "notification-debug.log"),
3517
- `[${(/* @__PURE__ */ new Date()).toISOString()}] SESSION-START source=${src} stdin_keys=${Object.keys(stdinJson ?? {}).join(",")}
3518
- `
3519
- );
3520
- } catch {
3521
- }
3522
3535
  handleSessionStart(stdinJson, args[0]);
3523
3536
  break;
3524
3537
  case "session-end":
@@ -3532,14 +3545,6 @@ async function main() {
3532
3545
  handleEngramUsed(stdinJson, args[0]);
3533
3546
  break;
3534
3547
  case "pre-compact":
3535
- try {
3536
- appendFileSync(
3537
- join(homedir(), ".engram", "notification-debug.log"),
3538
- `[${(/* @__PURE__ */ new Date()).toISOString()}] PRE-COMPACT stdin=${JSON.stringify(stdinJson).slice(0, 2e3)}
3539
- `
3540
- );
3541
- } catch {
3542
- }
3543
3548
  handlePreCompact();
3544
3549
  break;
3545
3550
  case "prompt-check":
@@ -4784,12 +4789,6 @@ function extractFilesFromToolCall(tool, input, output) {
4784
4789
  function handleNotification(type, data) {
4785
4790
  try {
4786
4791
  log.info("Notification received", { type, data: truncate(data, 300) });
4787
- try {
4788
- const debugLine = `[${(/* @__PURE__ */ new Date()).toISOString()}] type=${type} data=${truncate(data, 500)}
4789
- `;
4790
- appendFileSync(join(homedir(), ".engram", "notification-debug.log"), debugLine);
4791
- } catch {
4792
- }
4793
4792
  const isContextWarning = type === "context_window" || type === "context" || /context.*(low|full|limit|running out|compact)/i.test(data) || /remaining.*context/i.test(data);
4794
4793
  if (isContextWarning) {
4795
4794
  log.info("Context pressure detected \u2014 proactive offload triggered", { type, data });
@@ -5995,7 +5994,7 @@ function handlePromptCheck(stdinJson, argFallback) {
5995
5994
  }
5996
5995
  try {
5997
5996
  if (state.total_turns > 0 && state.total_turns % CONTEXT_PRESSURE.MIN_TURNS_BETWEEN_CHECKS === 0) {
5998
- const transcriptPath = stdinJson?.transcript_path;
5997
+ const transcriptPath = validateTranscriptPath(stdinJson?.transcript_path);
5999
5998
  const remaining = estimateContextRemaining(transcriptPath);
6000
5999
  if (remaining !== null) {
6001
6000
  state.last_context_remaining = remaining;
@@ -6178,7 +6177,7 @@ function handlePromptCheck(stdinJson, argFallback) {
6178
6177
  } catch {
6179
6178
  }
6180
6179
  try {
6181
- const transcriptPath2 = stdinJson?.transcript_path;
6180
+ const transcriptPath2 = validateTranscriptPath(stdinJson?.transcript_path);
6182
6181
  if (transcriptPath2 && state.total_turns > 0 && state.total_turns - state.last_reasoning_extraction_turn >= TRANSCRIPT_REASONING.EXTRACTION_INTERVAL_TURNS && state.reasoning_extraction_count < TRANSCRIPT_REASONING.MAX_PER_SESSION && canEncodeReasoning(state)) {
6183
6182
  const reasoningSnippets = extractReasoningFromTranscript(transcriptPath2);
6184
6183
  for (const snippet of reasoningSnippets.slice(0, 2)) {
@@ -7186,7 +7185,7 @@ function handlePostCompact(stdinJson) {
7186
7185
  }
7187
7186
  }
7188
7187
  try {
7189
- const transcriptPath = stdinJson?.transcript_path ?? null;
7188
+ const transcriptPath = validateTranscriptPath(stdinJson?.transcript_path);
7190
7189
  if (transcriptPath) {
7191
7190
  const reasoningSnippets = extractReasoningFromTranscript(transcriptPath, TRANSCRIPT_REASONING.POST_COMPACT_MAX_MESSAGES);
7192
7191
  if (reasoningSnippets.length > 0) {
package/dist/index.js CHANGED
@@ -154,7 +154,7 @@ import {
154
154
  vaccinate,
155
155
  vacuumDatabase,
156
156
  validateMultiPerspective
157
- } from "./chunk-OY2XHPUF.js";
157
+ } from "./chunk-O3ZP4K3T.js";
158
158
 
159
159
  // src/index.ts
160
160
  import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vedtechsolutions/engram-mcp",
3
- "version": "1.0.19",
3
+ "version": "1.0.20",
4
4
  "description": "Cognitive memory system for AI — persistent, cross-session learning via MCP",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",