@vedtechsolutions/engram-mcp 1.0.20 → 1.0.21
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/hook.js +74 -10
- package/package.json +1 -1
package/dist/hook.js
CHANGED
|
@@ -3250,13 +3250,29 @@ function sanitizeCognitiveState(state) {
|
|
|
3250
3250
|
const cog = state.cognitive_state;
|
|
3251
3251
|
if (!cog) return;
|
|
3252
3252
|
const placeholders = ["X", "X.", "Y", "Y.", "Z", "Z."];
|
|
3253
|
-
|
|
3253
|
+
const templatePatterns = [
|
|
3254
|
+
/^X[\.\s]/,
|
|
3255
|
+
// Starts with X. or X<space>
|
|
3256
|
+
/^Approach:\s*X/i,
|
|
3257
|
+
// "Approach: X..."
|
|
3258
|
+
/Hypothesis:\s*[XYZ][\.\s]/,
|
|
3259
|
+
// Contains "Hypothesis: X."
|
|
3260
|
+
/Discovery:\s*[XYZ][\.\s]/,
|
|
3261
|
+
// Contains "Discovery: Z."
|
|
3262
|
+
/^[XYZ]\.\s+(?:Hypothesis|Discovery|Approach):/i
|
|
3263
|
+
// "X. Hypothesis: Y..."
|
|
3264
|
+
];
|
|
3265
|
+
const isPlaceholderValue = (val) => {
|
|
3266
|
+
if (placeholders.includes(val)) return true;
|
|
3267
|
+
return templatePatterns.some((p) => p.test(val));
|
|
3268
|
+
};
|
|
3269
|
+
if (cog.current_approach && isPlaceholderValue(cog.current_approach)) {
|
|
3254
3270
|
cog.current_approach = null;
|
|
3255
3271
|
}
|
|
3256
|
-
if (cog.active_hypothesis &&
|
|
3272
|
+
if (cog.active_hypothesis && isPlaceholderValue(cog.active_hypothesis)) {
|
|
3257
3273
|
cog.active_hypothesis = null;
|
|
3258
3274
|
}
|
|
3259
|
-
if (cog.recent_discovery &&
|
|
3275
|
+
if (cog.recent_discovery && isPlaceholderValue(cog.recent_discovery)) {
|
|
3260
3276
|
cog.recent_discovery = null;
|
|
3261
3277
|
}
|
|
3262
3278
|
if (cog.active_hypothesis && cog.active_hypothesis.startsWith("/")) {
|
|
@@ -3285,11 +3301,35 @@ function sanitizeCognitiveState(state) {
|
|
|
3285
3301
|
}
|
|
3286
3302
|
}
|
|
3287
3303
|
}
|
|
3304
|
+
if (cog.recent_discovery && cog.recent_discovery.length < 15 && !cog.recent_discovery.includes(" ")) {
|
|
3305
|
+
cog.recent_discovery = null;
|
|
3306
|
+
}
|
|
3307
|
+
if (cog.recent_discovery && /^that\s/i.test(cog.recent_discovery) && cog.recent_discovery.length < 40) {
|
|
3308
|
+
cog.recent_discovery = null;
|
|
3309
|
+
}
|
|
3288
3310
|
if (state.active_task && state.active_task.startsWith("<")) {
|
|
3289
3311
|
state.active_task = null;
|
|
3290
3312
|
}
|
|
3313
|
+
if (state.active_task) {
|
|
3314
|
+
const conversationalPatterns = [
|
|
3315
|
+
/^i have another/i,
|
|
3316
|
+
/^just letting you/i,
|
|
3317
|
+
/^just a quick/i,
|
|
3318
|
+
/^now tell me/i,
|
|
3319
|
+
/^do another final/i,
|
|
3320
|
+
/^reviewing$/i
|
|
3321
|
+
// Generic tool-inferred task, not specific
|
|
3322
|
+
];
|
|
3323
|
+
if (conversationalPatterns.some((p) => p.test(state.active_task))) {
|
|
3324
|
+
state.active_task = null;
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3291
3327
|
if (!state.active_task || state.active_task === "unknown task") {
|
|
3292
|
-
const editedFiles = state.recent_actions.filter((a) => a.tool === "Edit" || a.tool === "Write").map((a) =>
|
|
3328
|
+
const editedFiles = state.recent_actions.filter((a) => a.tool === "Edit" || a.tool === "Write").map((a) => {
|
|
3329
|
+
const arrowIdx = a.target.indexOf(" \u2192");
|
|
3330
|
+
const path = arrowIdx > 0 ? a.target.slice(0, arrowIdx) : a.target;
|
|
3331
|
+
return path.split(/[/\\]/).pop() ?? path;
|
|
3332
|
+
});
|
|
3293
3333
|
const uniqueFiles = [...new Set(editedFiles)].slice(-5);
|
|
3294
3334
|
if (uniqueFiles.length > 0) {
|
|
3295
3335
|
if (cog.current_approach && cog.current_approach.length >= 10) {
|
|
@@ -3299,6 +3339,16 @@ function sanitizeCognitiveState(state) {
|
|
|
3299
3339
|
}
|
|
3300
3340
|
}
|
|
3301
3341
|
}
|
|
3342
|
+
if (state.session_files.length > 0) {
|
|
3343
|
+
state.session_files = state.session_files.filter((f) => {
|
|
3344
|
+
if (f.length < 3 || f.length > 500) return false;
|
|
3345
|
+
if (!f.includes("/") && !f.includes("\\")) return false;
|
|
3346
|
+
if (f.includes("/../") || f.startsWith("../")) return false;
|
|
3347
|
+
if (/^\/?\d+\.\d+/.test(f)) return false;
|
|
3348
|
+
if (f === "/root/.ssh" || f.includes("/etc/cron")) return false;
|
|
3349
|
+
return true;
|
|
3350
|
+
});
|
|
3351
|
+
}
|
|
3302
3352
|
}
|
|
3303
3353
|
function deleteSessionState() {
|
|
3304
3354
|
const watcherPath = getWatcherPath(activeSessionId);
|
|
@@ -5449,6 +5499,9 @@ function handleSubagentStop(stdinJson) {
|
|
|
5449
5499
|
const fileMatches = lastMessage.match(/(?:\/[\w./+-]+\.\w+|[\w./+-]+\.(?:ts|js|py|xml|json|css|scss|md))/g);
|
|
5450
5500
|
if (fileMatches) {
|
|
5451
5501
|
for (const f of fileMatches) {
|
|
5502
|
+
if (!f.includes("/")) continue;
|
|
5503
|
+
if (f.includes("/../") || f.startsWith("../") || /^\/?\d+\.\d+/.test(f)) continue;
|
|
5504
|
+
if (f === "/root/.ssh" || f.includes("/etc/cron")) continue;
|
|
5452
5505
|
if (!state.session_files.includes(f)) {
|
|
5453
5506
|
state.session_files.push(f);
|
|
5454
5507
|
}
|
|
@@ -5457,7 +5510,7 @@ function handleSubagentStop(stdinJson) {
|
|
|
5457
5510
|
state.session_files = state.session_files.slice(-50);
|
|
5458
5511
|
}
|
|
5459
5512
|
}
|
|
5460
|
-
const isMetaAnalysis = lastMessage.startsWith("<analysis>") || lastMessage.startsWith("<summary>") || /^#+\s/.test(lastMessage) || lastMessage.startsWith("Based on ");
|
|
5513
|
+
const isMetaAnalysis = lastMessage.startsWith("<analysis>") || lastMessage.startsWith("<summary>") || /^#+\s/.test(lastMessage) || lastMessage.startsWith("Based on ") || /^(I now have|Perfect!|I have (sufficient|enough|comprehensive))/i.test(lastMessage) || /^(Here('s| is) (the|my|a) (comprehensive|complete|detailed|full))/i.test(lastMessage) || lastMessage.includes("## ") && lastMessage.length > 500;
|
|
5461
5514
|
const hasError = !isMetaAnalysis && containsError(lastMessage);
|
|
5462
5515
|
if (hasError) {
|
|
5463
5516
|
state.recent_errors.push(truncate(lastMessage, 200));
|
|
@@ -5696,13 +5749,20 @@ function buildContinuationBrief(state) {
|
|
|
5696
5749
|
for (const id of state.decision_memory_ids.slice(-5)) {
|
|
5697
5750
|
try {
|
|
5698
5751
|
const mem = getMemory(id);
|
|
5699
|
-
if (mem)
|
|
5752
|
+
if (mem) {
|
|
5753
|
+
const content = mem.content;
|
|
5754
|
+
if (/^Delegated:|^Decision:\s*Delegated/i.test(content)) continue;
|
|
5755
|
+
decisions.push(truncate(content, 150));
|
|
5756
|
+
}
|
|
5700
5757
|
} catch {
|
|
5701
5758
|
}
|
|
5702
5759
|
}
|
|
5703
5760
|
const triedFailed = (state.session_outcomes ?? []).filter((o) => o.includes("\u2192 fail") || o.includes("\u2192 dead end") || o.includes("\u2192 blocked")).slice(-5).map((o) => truncate(o, 120));
|
|
5704
5761
|
const editActions = state.recent_actions.filter((a) => a.tool === "Edit" || a.tool === "Write");
|
|
5705
|
-
const keyFiles = [...new Set(editActions.map((a) =>
|
|
5762
|
+
const keyFiles = [...new Set(editActions.map((a) => {
|
|
5763
|
+
const arrowIdx = a.target.indexOf(" \u2192");
|
|
5764
|
+
return arrowIdx > 0 ? a.target.slice(0, arrowIdx) : a.target;
|
|
5765
|
+
}))].slice(-10);
|
|
5706
5766
|
const recentBash = state.recent_commands?.slice(-5) ?? [];
|
|
5707
5767
|
if (recentBash.length > 0) {
|
|
5708
5768
|
const bashSummary = recentBash.map((c) => truncate(c.cmd, 80));
|
|
@@ -7131,10 +7191,14 @@ function handlePostCompact(stdinJson) {
|
|
|
7131
7191
|
if (!recovery) return;
|
|
7132
7192
|
const budget = new OutputBudget(OUTPUT_BUDGET.POST_COMPACT_MAX_BYTES);
|
|
7133
7193
|
const lines = [];
|
|
7134
|
-
|
|
7135
|
-
|
|
7194
|
+
sanitizeCognitiveState(state);
|
|
7195
|
+
const brief = buildContinuationBrief(state);
|
|
7196
|
+
const briefUsable = brief.task !== "unknown task" || brief.last_actions.length > 0;
|
|
7197
|
+
if (briefUsable) {
|
|
7136
7198
|
const mindLines = ["[Engram] Continue from where you left off:"];
|
|
7137
|
-
|
|
7199
|
+
if (brief.task !== "unknown task") {
|
|
7200
|
+
mindLines.push(` Task: ${brief.task}`);
|
|
7201
|
+
}
|
|
7138
7202
|
mindLines.push(` Phase: ${brief.phase}`);
|
|
7139
7203
|
if (brief.last_actions.length > 0) {
|
|
7140
7204
|
mindLines.push(` Last actions:`);
|