@vedtechsolutions/engram-mcp 1.0.18 → 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.
- package/dist/{chunk-OY2XHPUF.js → chunk-O3ZP4K3T.js} +7 -4
- package/dist/hook.js +56 -46
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -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 &&
|
|
11188
|
-
|
|
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-
|
|
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-
|
|
177
|
+
} from "./chunk-O3ZP4K3T.js";
|
|
178
178
|
|
|
179
179
|
// src/hook.ts
|
|
180
|
-
import { readFileSync, writeFileSync, existsSync, renameSync, statSync, readdirSync, unlinkSync,
|
|
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) {
|
|
@@ -3244,11 +3268,22 @@ function sanitizeCognitiveState(state) {
|
|
|
3244
3268
|
if (cog.current_approach && cog.current_approach.length < 5) {
|
|
3245
3269
|
cog.current_approach = null;
|
|
3246
3270
|
}
|
|
3247
|
-
|
|
3248
|
-
|
|
3271
|
+
const templatePrefixes = ["Pre-compaction", "chronologically analyze", "This session is being continued"];
|
|
3272
|
+
if (cog.current_approach) {
|
|
3273
|
+
for (const prefix of templatePrefixes) {
|
|
3274
|
+
if (cog.current_approach.startsWith(prefix)) {
|
|
3275
|
+
cog.current_approach = null;
|
|
3276
|
+
break;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3249
3279
|
}
|
|
3250
|
-
if (cog.recent_discovery
|
|
3251
|
-
|
|
3280
|
+
if (cog.recent_discovery) {
|
|
3281
|
+
for (const prefix of templatePrefixes) {
|
|
3282
|
+
if (cog.recent_discovery.startsWith(prefix)) {
|
|
3283
|
+
cog.recent_discovery = null;
|
|
3284
|
+
break;
|
|
3285
|
+
}
|
|
3286
|
+
}
|
|
3252
3287
|
}
|
|
3253
3288
|
if (state.active_task && state.active_task.startsWith("<")) {
|
|
3254
3289
|
state.active_task = null;
|
|
@@ -3335,6 +3370,12 @@ function writeSessionHandoff(state, narrative) {
|
|
|
3335
3370
|
reasoning_trail: reasoningTrail.slice(0, 10)
|
|
3336
3371
|
};
|
|
3337
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
|
+
}
|
|
3338
3379
|
const tmpPath = handoffPath + ".tmp";
|
|
3339
3380
|
writeFileSync(tmpPath, JSON.stringify(handoff, null, 2), "utf-8");
|
|
3340
3381
|
renameSync(tmpPath, handoffPath);
|
|
@@ -3455,16 +3496,16 @@ var [command, ...args] = process.argv.slice(2);
|
|
|
3455
3496
|
async function main() {
|
|
3456
3497
|
const stdinRaw = await readStdin();
|
|
3457
3498
|
const stdinJson = safeParse(stdinRaw);
|
|
3458
|
-
const
|
|
3459
|
-
if (
|
|
3460
|
-
activeSessionId =
|
|
3499
|
+
const validatedSessionId = validateSessionId(stdinJson?.session_id);
|
|
3500
|
+
if (validatedSessionId) {
|
|
3501
|
+
activeSessionId = validatedSessionId;
|
|
3461
3502
|
} else if (process.env.ENGRAM_SESSION_ID) {
|
|
3462
|
-
|
|
3503
|
+
const envSessionId = validateSessionId(process.env.ENGRAM_SESSION_ID);
|
|
3504
|
+
if (envSessionId) activeSessionId = envSessionId;
|
|
3463
3505
|
}
|
|
3464
3506
|
migrateLegacyWatcherState();
|
|
3465
3507
|
try {
|
|
3466
|
-
const
|
|
3467
|
-
const cwdForDb = stdinCwd ?? process.cwd();
|
|
3508
|
+
const cwdForDb = validateCwd(stdinJson?.cwd) ?? process.cwd();
|
|
3468
3509
|
const projectRoot = inferProjectPath(cwdForDb);
|
|
3469
3510
|
const projectDbPath = deriveProjectDbPath(projectRoot);
|
|
3470
3511
|
initProjectDatabase(projectDbPath);
|
|
@@ -3485,29 +3526,12 @@ async function main() {
|
|
|
3485
3526
|
handlePostToolGeneric(stdinJson);
|
|
3486
3527
|
break;
|
|
3487
3528
|
case "notification": {
|
|
3488
|
-
try {
|
|
3489
|
-
appendFileSync(
|
|
3490
|
-
join(homedir(), ".engram", "notification-debug.log"),
|
|
3491
|
-
`[${(/* @__PURE__ */ new Date()).toISOString()}] NOTIFICATION stdin_keys=${Object.keys(stdinJson ?? {}).join(",")}
|
|
3492
|
-
`
|
|
3493
|
-
);
|
|
3494
|
-
} catch {
|
|
3495
|
-
}
|
|
3496
3529
|
const notifType = stdinJson?.notification_type ?? args[0] ?? "general";
|
|
3497
3530
|
const notifMessage = stdinJson?.message ?? args[1] ?? "";
|
|
3498
3531
|
handleNotification(notifType, notifMessage);
|
|
3499
3532
|
break;
|
|
3500
3533
|
}
|
|
3501
3534
|
case "session-start":
|
|
3502
|
-
try {
|
|
3503
|
-
const src = stdinJson?.source ?? "unknown";
|
|
3504
|
-
appendFileSync(
|
|
3505
|
-
join(homedir(), ".engram", "notification-debug.log"),
|
|
3506
|
-
`[${(/* @__PURE__ */ new Date()).toISOString()}] SESSION-START source=${src} stdin_keys=${Object.keys(stdinJson ?? {}).join(",")}
|
|
3507
|
-
`
|
|
3508
|
-
);
|
|
3509
|
-
} catch {
|
|
3510
|
-
}
|
|
3511
3535
|
handleSessionStart(stdinJson, args[0]);
|
|
3512
3536
|
break;
|
|
3513
3537
|
case "session-end":
|
|
@@ -3521,14 +3545,6 @@ async function main() {
|
|
|
3521
3545
|
handleEngramUsed(stdinJson, args[0]);
|
|
3522
3546
|
break;
|
|
3523
3547
|
case "pre-compact":
|
|
3524
|
-
try {
|
|
3525
|
-
appendFileSync(
|
|
3526
|
-
join(homedir(), ".engram", "notification-debug.log"),
|
|
3527
|
-
`[${(/* @__PURE__ */ new Date()).toISOString()}] PRE-COMPACT stdin=${JSON.stringify(stdinJson).slice(0, 2e3)}
|
|
3528
|
-
`
|
|
3529
|
-
);
|
|
3530
|
-
} catch {
|
|
3531
|
-
}
|
|
3532
3548
|
handlePreCompact();
|
|
3533
3549
|
break;
|
|
3534
3550
|
case "prompt-check":
|
|
@@ -4773,12 +4789,6 @@ function extractFilesFromToolCall(tool, input, output) {
|
|
|
4773
4789
|
function handleNotification(type, data) {
|
|
4774
4790
|
try {
|
|
4775
4791
|
log.info("Notification received", { type, data: truncate(data, 300) });
|
|
4776
|
-
try {
|
|
4777
|
-
const debugLine = `[${(/* @__PURE__ */ new Date()).toISOString()}] type=${type} data=${truncate(data, 500)}
|
|
4778
|
-
`;
|
|
4779
|
-
appendFileSync(join(homedir(), ".engram", "notification-debug.log"), debugLine);
|
|
4780
|
-
} catch {
|
|
4781
|
-
}
|
|
4782
4792
|
const isContextWarning = type === "context_window" || type === "context" || /context.*(low|full|limit|running out|compact)/i.test(data) || /remaining.*context/i.test(data);
|
|
4783
4793
|
if (isContextWarning) {
|
|
4784
4794
|
log.info("Context pressure detected \u2014 proactive offload triggered", { type, data });
|
|
@@ -5984,7 +5994,7 @@ function handlePromptCheck(stdinJson, argFallback) {
|
|
|
5984
5994
|
}
|
|
5985
5995
|
try {
|
|
5986
5996
|
if (state.total_turns > 0 && state.total_turns % CONTEXT_PRESSURE.MIN_TURNS_BETWEEN_CHECKS === 0) {
|
|
5987
|
-
const transcriptPath = stdinJson?.transcript_path;
|
|
5997
|
+
const transcriptPath = validateTranscriptPath(stdinJson?.transcript_path);
|
|
5988
5998
|
const remaining = estimateContextRemaining(transcriptPath);
|
|
5989
5999
|
if (remaining !== null) {
|
|
5990
6000
|
state.last_context_remaining = remaining;
|
|
@@ -6167,7 +6177,7 @@ function handlePromptCheck(stdinJson, argFallback) {
|
|
|
6167
6177
|
} catch {
|
|
6168
6178
|
}
|
|
6169
6179
|
try {
|
|
6170
|
-
const transcriptPath2 = stdinJson?.transcript_path;
|
|
6180
|
+
const transcriptPath2 = validateTranscriptPath(stdinJson?.transcript_path);
|
|
6171
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)) {
|
|
6172
6182
|
const reasoningSnippets = extractReasoningFromTranscript(transcriptPath2);
|
|
6173
6183
|
for (const snippet of reasoningSnippets.slice(0, 2)) {
|
|
@@ -7175,7 +7185,7 @@ function handlePostCompact(stdinJson) {
|
|
|
7175
7185
|
}
|
|
7176
7186
|
}
|
|
7177
7187
|
try {
|
|
7178
|
-
const transcriptPath = stdinJson?.transcript_path
|
|
7188
|
+
const transcriptPath = validateTranscriptPath(stdinJson?.transcript_path);
|
|
7179
7189
|
if (transcriptPath) {
|
|
7180
7190
|
const reasoningSnippets = extractReasoningFromTranscript(transcriptPath, TRANSCRIPT_REASONING.POST_COMPACT_MAX_MESSAGES);
|
|
7181
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-
|
|
157
|
+
} from "./chunk-O3ZP4K3T.js";
|
|
158
158
|
|
|
159
159
|
// src/index.ts
|
|
160
160
|
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|