engrm 0.4.13 → 0.4.15
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/hooks/session-start.js +103 -12
- package/dist/hooks/stop.js +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
|
@@ -1154,7 +1154,7 @@ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync
|
|
|
1154
1154
|
import { join as join3 } from "node:path";
|
|
1155
1155
|
import { homedir } from "node:os";
|
|
1156
1156
|
var STATE_PATH = join3(homedir(), ".engrm", "config-fingerprint.json");
|
|
1157
|
-
var CLIENT_VERSION = "0.4.
|
|
1157
|
+
var CLIENT_VERSION = "0.4.15";
|
|
1158
1158
|
function hashFile(filePath) {
|
|
1159
1159
|
try {
|
|
1160
1160
|
if (!existsSync3(filePath))
|
|
@@ -3135,7 +3135,7 @@ function formatSplashScreen(data) {
|
|
|
3135
3135
|
const brief = formatVisibleStartupBrief(data.context);
|
|
3136
3136
|
if (brief.length > 0) {
|
|
3137
3137
|
lines.push("");
|
|
3138
|
-
lines.push(` ${c2.bold}
|
|
3138
|
+
lines.push(` ${c2.bold}Handoff${c2.reset}`);
|
|
3139
3139
|
for (const line of brief) {
|
|
3140
3140
|
lines.push(` ${line}`);
|
|
3141
3141
|
}
|
|
@@ -3147,6 +3147,20 @@ function formatSplashScreen(data) {
|
|
|
3147
3147
|
lines.push(` ${line}`);
|
|
3148
3148
|
}
|
|
3149
3149
|
}
|
|
3150
|
+
const legend = formatLegend();
|
|
3151
|
+
if (legend.length > 0) {
|
|
3152
|
+
lines.push("");
|
|
3153
|
+
for (const line of legend) {
|
|
3154
|
+
lines.push(` ${line}`);
|
|
3155
|
+
}
|
|
3156
|
+
}
|
|
3157
|
+
const contextIndex = formatContextIndex(data.context);
|
|
3158
|
+
if (contextIndex.length > 0) {
|
|
3159
|
+
lines.push("");
|
|
3160
|
+
for (const line of contextIndex) {
|
|
3161
|
+
lines.push(` ${line}`);
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3150
3164
|
const inspectHints = formatInspectHints(data.context);
|
|
3151
3165
|
if (inspectHints.length > 0) {
|
|
3152
3166
|
lines.push("");
|
|
@@ -3172,7 +3186,7 @@ function formatVisibleStartupBrief(context) {
|
|
|
3172
3186
|
const projectSignals = buildProjectSignalLine(context);
|
|
3173
3187
|
const shownItems = new Set;
|
|
3174
3188
|
if (promptLines.length > 0) {
|
|
3175
|
-
lines.push(`${c2.cyan}
|
|
3189
|
+
lines.push(`${c2.cyan}Asked recently:${c2.reset}`);
|
|
3176
3190
|
for (const item of promptLines) {
|
|
3177
3191
|
lines.push(` - ${truncateInline(item, 160)}`);
|
|
3178
3192
|
rememberShownItem(shownItems, item);
|
|
@@ -3204,13 +3218,13 @@ function formatVisibleStartupBrief(context) {
|
|
|
3204
3218
|
}
|
|
3205
3219
|
}
|
|
3206
3220
|
} else if (currentRequest && !duplicatesPromptLine(currentRequest, latestPromptLine)) {
|
|
3207
|
-
lines.push(`${c2.cyan}
|
|
3221
|
+
lines.push(`${c2.cyan}What you're on:${c2.reset}`);
|
|
3208
3222
|
lines.push(` - ${truncateInline(currentRequest, 160)}`);
|
|
3209
3223
|
rememberShownItem(shownItems, currentRequest);
|
|
3210
3224
|
if (toolFallbacks.length > 0) {
|
|
3211
3225
|
const additiveTools = filterAdditiveToolFallbacks(toolFallbacks, shownItems);
|
|
3212
3226
|
if (additiveTools.length > 0) {
|
|
3213
|
-
lines.push(`${c2.cyan}
|
|
3227
|
+
lines.push(`${c2.cyan}Tool trail:${c2.reset}`);
|
|
3214
3228
|
for (const item of additiveTools) {
|
|
3215
3229
|
lines.push(` - ${truncateInline(item, 160)}`);
|
|
3216
3230
|
rememberShownItem(shownItems, item);
|
|
@@ -3219,12 +3233,12 @@ function formatVisibleStartupBrief(context) {
|
|
|
3219
3233
|
}
|
|
3220
3234
|
}
|
|
3221
3235
|
if (latest && currentRequest && !hasRequestSection(lines) && !duplicatesPromptLine(currentRequest, latestPromptLine)) {
|
|
3222
|
-
lines.push(`${c2.cyan}
|
|
3236
|
+
lines.push(`${c2.cyan}What you're on:${c2.reset}`);
|
|
3223
3237
|
lines.push(` - ${truncateInline(currentRequest, 160)}`);
|
|
3224
3238
|
rememberShownItem(shownItems, currentRequest);
|
|
3225
3239
|
}
|
|
3226
3240
|
if (recentOutcomeLines.length > 0) {
|
|
3227
|
-
lines.push(`${c2.cyan}
|
|
3241
|
+
lines.push(`${c2.cyan}What's moved:${c2.reset}`);
|
|
3228
3242
|
for (const item of recentOutcomeLines) {
|
|
3229
3243
|
lines.push(` - ${truncateInline(item, 160)}`);
|
|
3230
3244
|
rememberShownItem(shownItems, item);
|
|
@@ -3233,7 +3247,7 @@ function formatVisibleStartupBrief(context) {
|
|
|
3233
3247
|
if (toolFallbacks.length > 0 && latest) {
|
|
3234
3248
|
const additiveTools = filterAdditiveToolFallbacks(toolFallbacks, shownItems);
|
|
3235
3249
|
if (additiveTools.length > 0) {
|
|
3236
|
-
lines.push(`${c2.cyan}
|
|
3250
|
+
lines.push(`${c2.cyan}Tool trail:${c2.reset}`);
|
|
3237
3251
|
for (const item of additiveTools) {
|
|
3238
3252
|
lines.push(` - ${truncateInline(item, 160)}`);
|
|
3239
3253
|
rememberShownItem(shownItems, item);
|
|
@@ -3241,13 +3255,13 @@ function formatVisibleStartupBrief(context) {
|
|
|
3241
3255
|
}
|
|
3242
3256
|
}
|
|
3243
3257
|
if (sessionFallbacks.length > 0) {
|
|
3244
|
-
lines.push(`${c2.cyan}Recent
|
|
3258
|
+
lines.push(`${c2.cyan}Recent threads:${c2.reset}`);
|
|
3245
3259
|
for (const item of sessionFallbacks) {
|
|
3246
3260
|
lines.push(` - ${truncateInline(item, 160)}`);
|
|
3247
3261
|
}
|
|
3248
3262
|
}
|
|
3249
3263
|
if (projectSignals) {
|
|
3250
|
-
lines.push(`${c2.cyan}
|
|
3264
|
+
lines.push(`${c2.cyan}Signal mix:${c2.reset}`);
|
|
3251
3265
|
lines.push(` - ${truncateInline(projectSignals, 160)}`);
|
|
3252
3266
|
}
|
|
3253
3267
|
const stale = pickRelevantStaleDecision(context, latest);
|
|
@@ -3271,10 +3285,31 @@ function formatContextEconomics(data) {
|
|
|
3271
3285
|
if (data.estimatedReadTokens > 0) {
|
|
3272
3286
|
parts.push(`read now ~${data.estimatedReadTokens.toLocaleString()}t`);
|
|
3273
3287
|
}
|
|
3288
|
+
if (data.context.observations.length > 0) {
|
|
3289
|
+
parts.push(`${data.context.observations.length} observations loaded`);
|
|
3290
|
+
}
|
|
3274
3291
|
if (parts.length === 0)
|
|
3275
3292
|
return [];
|
|
3276
3293
|
return [`${c2.dim}Context economics:${c2.reset} ${parts.join(" \xB7 ")}`];
|
|
3277
3294
|
}
|
|
3295
|
+
function formatLegend() {
|
|
3296
|
+
return [
|
|
3297
|
+
`${c2.dim}Legend:${c2.reset} #id | \u25A0 bugfix | \u25B2 feature | \u2248 refactor | \u25CF change | \u25A1 discovery | \u25C7 decision`
|
|
3298
|
+
];
|
|
3299
|
+
}
|
|
3300
|
+
function formatContextIndex(context) {
|
|
3301
|
+
const rows = context.observations.filter((obs) => obs.type !== "digest").slice(0, 6).map((obs) => {
|
|
3302
|
+
const icon = observationIcon(obs.type);
|
|
3303
|
+
const fileHint = extractPrimaryFileHint(obs);
|
|
3304
|
+
return `${icon} #${obs.id} ${truncateInline(obs.title, 110)}${fileHint ? ` ${c2.dim}(${fileHint})${c2.reset}` : ""}`;
|
|
3305
|
+
});
|
|
3306
|
+
if (rows.length === 0)
|
|
3307
|
+
return [];
|
|
3308
|
+
return [
|
|
3309
|
+
`${c2.dim}Handoff index:${c2.reset} use IDs when you want the deeper thread`,
|
|
3310
|
+
...rows
|
|
3311
|
+
];
|
|
3312
|
+
}
|
|
3278
3313
|
function formatInspectHints(context) {
|
|
3279
3314
|
const hints = [];
|
|
3280
3315
|
if ((context.recentSessions?.length ?? 0) > 0) {
|
|
@@ -3290,7 +3325,12 @@ function formatInspectHints(context) {
|
|
|
3290
3325
|
const unique = Array.from(new Set(hints)).slice(0, 4);
|
|
3291
3326
|
if (unique.length === 0)
|
|
3292
3327
|
return [];
|
|
3293
|
-
|
|
3328
|
+
const ids = context.observations.slice(0, 5).map((obs) => obs.id);
|
|
3329
|
+
const fetchHint = ids.length > 0 ? `get_observations([${ids.join(", ")}])` : null;
|
|
3330
|
+
return [
|
|
3331
|
+
`${c2.dim}Next look:${c2.reset} ${unique.join(" \xB7 ")}`,
|
|
3332
|
+
...fetchHint ? [`${c2.dim}Pull detail:${c2.reset} ${fetchHint}`] : []
|
|
3333
|
+
];
|
|
3294
3334
|
}
|
|
3295
3335
|
function rememberShownItem(shown, value) {
|
|
3296
3336
|
if (!value)
|
|
@@ -3412,9 +3452,60 @@ function chooseMeaningfulSessionSummary(request, completed) {
|
|
|
3412
3452
|
function buildProjectSignalLine(context) {
|
|
3413
3453
|
if (!context.projectTypeCounts)
|
|
3414
3454
|
return null;
|
|
3415
|
-
const top = Object.entries(context.projectTypeCounts).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, 4).map(([type, count]) => `${type} ${count}`).join("; ");
|
|
3455
|
+
const top = Object.entries(context.projectTypeCounts).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, 4).map(([type, count]) => `${signalGlyph(type)} ${type} ${count}`).join("; ");
|
|
3416
3456
|
return top || null;
|
|
3417
3457
|
}
|
|
3458
|
+
function signalGlyph(type) {
|
|
3459
|
+
switch (type) {
|
|
3460
|
+
case "bugfix":
|
|
3461
|
+
return "\u25A0";
|
|
3462
|
+
case "feature":
|
|
3463
|
+
return "\u25B2";
|
|
3464
|
+
case "refactor":
|
|
3465
|
+
return "\u2248";
|
|
3466
|
+
case "change":
|
|
3467
|
+
return "\u25CF";
|
|
3468
|
+
case "discovery":
|
|
3469
|
+
return "\u25A1";
|
|
3470
|
+
case "decision":
|
|
3471
|
+
return "\u25C7";
|
|
3472
|
+
default:
|
|
3473
|
+
return "\xB7";
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
function observationIcon(type) {
|
|
3477
|
+
switch (type) {
|
|
3478
|
+
case "bugfix":
|
|
3479
|
+
return "\u25A0";
|
|
3480
|
+
case "feature":
|
|
3481
|
+
return "\u25B2";
|
|
3482
|
+
case "refactor":
|
|
3483
|
+
return "\u2248";
|
|
3484
|
+
case "change":
|
|
3485
|
+
return "\u25CF";
|
|
3486
|
+
case "discovery":
|
|
3487
|
+
return "\u25A1";
|
|
3488
|
+
case "decision":
|
|
3489
|
+
return "\u25C7";
|
|
3490
|
+
default:
|
|
3491
|
+
return "\u2022";
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3494
|
+
function extractPrimaryFileHint(obs) {
|
|
3495
|
+
const firstRead = parseJsonArraySafe(obs.files_read)[0];
|
|
3496
|
+
const firstModified = parseJsonArraySafe(obs.files_modified)[0];
|
|
3497
|
+
return firstModified ?? firstRead ?? null;
|
|
3498
|
+
}
|
|
3499
|
+
function parseJsonArraySafe(value) {
|
|
3500
|
+
if (!value)
|
|
3501
|
+
return [];
|
|
3502
|
+
try {
|
|
3503
|
+
const parsed = JSON.parse(value);
|
|
3504
|
+
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string" && item.trim().length > 0) : [];
|
|
3505
|
+
} catch {
|
|
3506
|
+
return [];
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3418
3509
|
function toSplashLines(value, maxItems) {
|
|
3419
3510
|
if (!value)
|
|
3420
3511
|
return [];
|
package/dist/hooks/stop.js
CHANGED
|
@@ -2535,7 +2535,7 @@ function buildBeacon(db, config, sessionId, metrics) {
|
|
|
2535
2535
|
sentinel_used: valueSignals.security_findings_count > 0,
|
|
2536
2536
|
risk_score: riskScore,
|
|
2537
2537
|
stacks_detected: stacks,
|
|
2538
|
-
client_version: "0.4.
|
|
2538
|
+
client_version: "0.4.15",
|
|
2539
2539
|
context_observations_injected: metrics?.contextObsInjected ?? 0,
|
|
2540
2540
|
context_total_available: metrics?.contextTotalAvailable ?? 0,
|
|
2541
2541
|
recall_attempts: metrics?.recallAttempts ?? 0,
|
package/dist/server.js
CHANGED
|
@@ -19764,7 +19764,7 @@ process.on("SIGTERM", () => {
|
|
|
19764
19764
|
});
|
|
19765
19765
|
var server = new McpServer({
|
|
19766
19766
|
name: "engrm",
|
|
19767
|
-
version: "0.4.
|
|
19767
|
+
version: "0.4.15"
|
|
19768
19768
|
});
|
|
19769
19769
|
server.tool("save_observation", "Save an observation to memory", {
|
|
19770
19770
|
type: exports_external.enum([
|