engrm 0.4.32 → 0.4.33
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/README.md +2 -1
- package/dist/hooks/session-start.js +89 -3
- package/dist/hooks/stop.js +1 -1
- package/dist/server.js +42 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -403,9 +403,10 @@ What each tool is good for:
|
|
|
403
403
|
- `capture_status` tells you whether prompt/tool hooks are live on this machine
|
|
404
404
|
- `capture_quality` shows whether chat recall is transcript-backed, history-backed, or still hook-only across the workspace
|
|
405
405
|
- `memory_console` gives the quickest project snapshot, including whether continuity is `fresh`, `thin`, or `cold`
|
|
406
|
-
- `resume_thread` is the fastest “get me back into the live thread” path when you want freshness, source, next actions, tool trail, and
|
|
406
|
+
- `resume_thread` is the fastest “get me back into the live thread” path when you want freshness, source, next actions, tool trail, chat, and one exact `load_recall_item(...)` suggestion in one place
|
|
407
407
|
- `list_recall_items` is the deterministic directory-first path when you want to inspect the best candidate handoffs/threads before opening one exact item
|
|
408
408
|
- `load_recall_item` completes that protocol by letting agents open one exact recall key directly after listing
|
|
409
|
+
- `memory_console`, `project_memory_index`, and `session_context` now also surface one best exact `load_recall_item(...)` jump, so the workbench can hand you the right deterministic next step instead of only showing recall counts
|
|
409
410
|
- `memory_console`, `project_memory_index`, and `session_context` now also show whether project chat recall is transcript-backed, history-backed, or only hook-captured
|
|
410
411
|
- `memory_console`, `project_memory_index`, and `session_context` also expose resume-readiness directly, so you can see whether a repo is `live`, `recent`, or `stale` before drilling deeper
|
|
411
412
|
- when chat continuity is only partial, the workbench and startup hints now prefer `repair_recall`, and still suggest `refresh_chat_recall` when a single session likely just needs transcript hydration
|
|
@@ -3144,7 +3144,7 @@ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync
|
|
|
3144
3144
|
import { join as join3 } from "node:path";
|
|
3145
3145
|
import { homedir } from "node:os";
|
|
3146
3146
|
var STATE_PATH = join3(homedir(), ".engrm", "config-fingerprint.json");
|
|
3147
|
-
var CLIENT_VERSION = "0.4.
|
|
3147
|
+
var CLIENT_VERSION = "0.4.33";
|
|
3148
3148
|
function hashFile(filePath) {
|
|
3149
3149
|
try {
|
|
3150
3150
|
if (!existsSync3(filePath))
|
|
@@ -5617,7 +5617,15 @@ function formatSplashScreen(data) {
|
|
|
5617
5617
|
lines.push(` ${line}`);
|
|
5618
5618
|
}
|
|
5619
5619
|
}
|
|
5620
|
-
const
|
|
5620
|
+
const recallItems = buildStartupRecallItems(data.context);
|
|
5621
|
+
const recallPreview = formatStartupRecallPreview(recallItems);
|
|
5622
|
+
if (recallPreview.length > 0) {
|
|
5623
|
+
lines.push("");
|
|
5624
|
+
for (const line of recallPreview) {
|
|
5625
|
+
lines.push(` ${line}`);
|
|
5626
|
+
}
|
|
5627
|
+
}
|
|
5628
|
+
const inspectHints = formatInspectHints(data.context, contextIndex.observationIds, recallItems);
|
|
5621
5629
|
if (inspectHints.length > 0) {
|
|
5622
5630
|
lines.push("");
|
|
5623
5631
|
for (const line of inspectHints) {
|
|
@@ -5836,7 +5844,7 @@ function formatContextIndex(context, shownItems) {
|
|
|
5836
5844
|
observationIds: selected.map((obs) => obs.id)
|
|
5837
5845
|
};
|
|
5838
5846
|
}
|
|
5839
|
-
function formatInspectHints(context, visibleObservationIds = []) {
|
|
5847
|
+
function formatInspectHints(context, visibleObservationIds = [], recallItems = []) {
|
|
5840
5848
|
const hints = [];
|
|
5841
5849
|
const continuityState = getStartupContinuityState(context);
|
|
5842
5850
|
if ((context.recentSessions?.length ?? 0) > 0) {
|
|
@@ -5875,12 +5883,90 @@ function formatInspectHints(context, visibleObservationIds = []) {
|
|
|
5875
5883
|
if (unique.length === 0)
|
|
5876
5884
|
return [];
|
|
5877
5885
|
const ids = visibleObservationIds.slice(0, 5);
|
|
5886
|
+
const openNowItem = recallItems.find((item) => item.kind !== "memory") ?? null;
|
|
5878
5887
|
const fetchHint = ids.length > 0 ? `get_observations([${ids.join(", ")}])` : null;
|
|
5879
5888
|
return [
|
|
5880
5889
|
`${c2.dim}Next look:${c2.reset} ${unique.join(" \xB7 ")}`,
|
|
5890
|
+
...openNowItem ? [`${c2.dim}Open now:${c2.reset} load_recall_item("${openNowItem.key}")`] : [],
|
|
5881
5891
|
...fetchHint ? [`${c2.dim}Pull detail:${c2.reset} ${fetchHint}`] : []
|
|
5882
5892
|
];
|
|
5883
5893
|
}
|
|
5894
|
+
function formatStartupRecallPreview(recallItems) {
|
|
5895
|
+
const items = recallItems.slice(0, 3);
|
|
5896
|
+
if (items.length === 0)
|
|
5897
|
+
return [];
|
|
5898
|
+
return [
|
|
5899
|
+
`${c2.dim}Recall preview:${c2.reset} exact keys you can open now`,
|
|
5900
|
+
...items.map((item) => `${item.key} [${item.kind} \xB7 ${item.freshness}] ${truncateInline(item.title, 110)}`)
|
|
5901
|
+
];
|
|
5902
|
+
}
|
|
5903
|
+
function buildStartupRecallItems(context) {
|
|
5904
|
+
const items = [];
|
|
5905
|
+
for (const handoff of context.recentHandoffs?.slice(0, 2) ?? []) {
|
|
5906
|
+
const title = handoff.title.replace(/^Handoff(?: Draft)?:\s*/i, "").replace(/\s+\u00B7\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}Z$/, "").trim();
|
|
5907
|
+
if (!title)
|
|
5908
|
+
continue;
|
|
5909
|
+
const freshness = classifyResumeFreshness(handoff.created_at_epoch);
|
|
5910
|
+
items.push({
|
|
5911
|
+
key: `handoff:${handoff.id}`,
|
|
5912
|
+
kind: "handoff",
|
|
5913
|
+
freshness,
|
|
5914
|
+
title,
|
|
5915
|
+
score: freshnessScore(freshness) + 40
|
|
5916
|
+
});
|
|
5917
|
+
}
|
|
5918
|
+
for (const session of context.recentSessions?.slice(0, 2) ?? []) {
|
|
5919
|
+
const title = chooseMeaningfulSessionSummary(session.request, session.completed);
|
|
5920
|
+
if (!title)
|
|
5921
|
+
continue;
|
|
5922
|
+
const sourceEpoch = session.completed_at_epoch ?? session.started_at_epoch ?? null;
|
|
5923
|
+
const freshness = classifyResumeFreshness(sourceEpoch);
|
|
5924
|
+
items.push({
|
|
5925
|
+
key: `session:${session.session_id}`,
|
|
5926
|
+
kind: "thread",
|
|
5927
|
+
freshness,
|
|
5928
|
+
title,
|
|
5929
|
+
score: freshnessScore(freshness) + 30
|
|
5930
|
+
});
|
|
5931
|
+
}
|
|
5932
|
+
for (const message of context.recentChatMessages?.slice(-2) ?? []) {
|
|
5933
|
+
if (!message.content.trim())
|
|
5934
|
+
continue;
|
|
5935
|
+
const freshness = classifyResumeFreshness(message.created_at_epoch);
|
|
5936
|
+
items.push({
|
|
5937
|
+
key: `chat:${message.id}`,
|
|
5938
|
+
kind: "chat",
|
|
5939
|
+
freshness,
|
|
5940
|
+
title: `[${message.role}] ${message.content.replace(/\s+/g, " ").trim()}`,
|
|
5941
|
+
score: freshnessScore(freshness) + 20
|
|
5942
|
+
});
|
|
5943
|
+
}
|
|
5944
|
+
for (const obs of pickContextIndexObservations(context).slice(0, 2)) {
|
|
5945
|
+
const createdAtEpoch = Math.floor(new Date(obs.created_at).getTime() / 1000);
|
|
5946
|
+
const freshness = classifyResumeFreshness(Number.isFinite(createdAtEpoch) ? createdAtEpoch : null);
|
|
5947
|
+
items.push({
|
|
5948
|
+
key: `obs:${obs.id}`,
|
|
5949
|
+
kind: "memory",
|
|
5950
|
+
freshness,
|
|
5951
|
+
title: obs.title,
|
|
5952
|
+
score: freshnessScore(freshness) + 10
|
|
5953
|
+
});
|
|
5954
|
+
}
|
|
5955
|
+
const seen = new Set;
|
|
5956
|
+
return items.sort((a, b) => b.score - a.score || a.key.localeCompare(b.key)).filter((item) => {
|
|
5957
|
+
if (seen.has(item.key))
|
|
5958
|
+
return false;
|
|
5959
|
+
seen.add(item.key);
|
|
5960
|
+
return true;
|
|
5961
|
+
}).map(({ score: _score, ...item }) => item);
|
|
5962
|
+
}
|
|
5963
|
+
function freshnessScore(freshness) {
|
|
5964
|
+
if (freshness === "live")
|
|
5965
|
+
return 3;
|
|
5966
|
+
if (freshness === "recent")
|
|
5967
|
+
return 2;
|
|
5968
|
+
return 1;
|
|
5969
|
+
}
|
|
5884
5970
|
function rememberShownItem(shown, value) {
|
|
5885
5971
|
if (!value)
|
|
5886
5972
|
return;
|
package/dist/hooks/stop.js
CHANGED
|
@@ -3082,7 +3082,7 @@ function buildBeacon(db, config, sessionId, metrics) {
|
|
|
3082
3082
|
sentinel_used: valueSignals.security_findings_count > 0,
|
|
3083
3083
|
risk_score: riskScore,
|
|
3084
3084
|
stacks_detected: stacks,
|
|
3085
|
-
client_version: "0.4.
|
|
3085
|
+
client_version: "0.4.33",
|
|
3086
3086
|
context_observations_injected: metrics?.contextObsInjected ?? 0,
|
|
3087
3087
|
context_total_available: metrics?.contextTotalAvailable ?? 0,
|
|
3088
3088
|
recall_attempts: metrics?.recallAttempts ?? 0,
|
package/dist/server.js
CHANGED
|
@@ -18602,6 +18602,7 @@ function getProjectMemoryIndex(db, input) {
|
|
|
18602
18602
|
`));
|
|
18603
18603
|
const continuityState = classifyContinuityState(recentRequestsCount, recentToolsCount, recentHandoffsCount.length, recentChatCount, recentSessions, recentOutcomes.length);
|
|
18604
18604
|
const sourceTimestamp = pickResumeSourceTimestamp(latestSession, recentChat.messages);
|
|
18605
|
+
const bestRecallItem = pickBestRecallItem(recallIndex.items);
|
|
18605
18606
|
return {
|
|
18606
18607
|
project: project.name,
|
|
18607
18608
|
canonical_id: project.canonical_id,
|
|
@@ -18615,6 +18616,9 @@ function getProjectMemoryIndex(db, input) {
|
|
|
18615
18616
|
freshness: item.freshness,
|
|
18616
18617
|
title: item.title
|
|
18617
18618
|
})),
|
|
18619
|
+
best_recall_key: bestRecallItem?.key ?? null,
|
|
18620
|
+
best_recall_title: bestRecallItem?.title ?? null,
|
|
18621
|
+
best_recall_kind: bestRecallItem?.kind ?? null,
|
|
18618
18622
|
resume_freshness: classifyResumeFreshness(sourceTimestamp),
|
|
18619
18623
|
resume_source_session_id: latestSession?.session_id ?? null,
|
|
18620
18624
|
resume_source_device_id: latestSession?.device_id ?? null,
|
|
@@ -18643,6 +18647,9 @@ function getProjectMemoryIndex(db, input) {
|
|
|
18643
18647
|
suggested_tools: suggestedTools
|
|
18644
18648
|
};
|
|
18645
18649
|
}
|
|
18650
|
+
function pickBestRecallItem(items) {
|
|
18651
|
+
return items.find((item) => item.kind !== "memory") ?? items[0] ?? null;
|
|
18652
|
+
}
|
|
18646
18653
|
function pickResumeSourceTimestamp(latestSession, messages) {
|
|
18647
18654
|
const latestChatEpoch = messages.length > 0 ? messages[messages.length - 1]?.created_at_epoch ?? null : null;
|
|
18648
18655
|
return latestChatEpoch ?? latestSession?.completed_at_epoch ?? latestSession?.started_at_epoch ?? null;
|
|
@@ -18825,6 +18832,9 @@ function getMemoryConsole(db, input) {
|
|
|
18825
18832
|
freshness: item.freshness,
|
|
18826
18833
|
title: item.title
|
|
18827
18834
|
})),
|
|
18835
|
+
best_recall_key: projectIndex?.best_recall_key ?? (recallIndex.items.find((item) => item.kind !== "memory") ?? recallIndex.items[0] ?? null)?.key ?? null,
|
|
18836
|
+
best_recall_title: projectIndex?.best_recall_title ?? (recallIndex.items.find((item) => item.kind !== "memory") ?? recallIndex.items[0] ?? null)?.title ?? null,
|
|
18837
|
+
best_recall_kind: projectIndex?.best_recall_kind ?? (recallIndex.items.find((item) => item.kind !== "memory") ?? recallIndex.items[0] ?? null)?.kind ?? null,
|
|
18828
18838
|
resume_freshness: projectIndex?.resume_freshness ?? "stale",
|
|
18829
18839
|
resume_source_session_id: projectIndex?.resume_source_session_id ?? sessions[0]?.session_id ?? null,
|
|
18830
18840
|
resume_source_device_id: projectIndex?.resume_source_device_id ?? sessions[0]?.device_id ?? null,
|
|
@@ -19721,6 +19731,7 @@ function getSessionContext(db, input) {
|
|
|
19721
19731
|
const continuityState = classifyContinuityState(recentRequests, recentTools, recentHandoffs, recentChatMessages, context.recentSessions ?? [], (context.recentOutcomes ?? []).length);
|
|
19722
19732
|
const latestChatEpoch = recentChat.messages.length > 0 ? recentChat.messages[recentChat.messages.length - 1]?.created_at_epoch ?? null : null;
|
|
19723
19733
|
const resumeTimestamp = latestChatEpoch ?? latestSession?.completed_at_epoch ?? latestSession?.started_at_epoch ?? null;
|
|
19734
|
+
const bestRecallItem = recallIndex.items.find((item) => item.kind !== "memory") ?? recallIndex.items[0] ?? null;
|
|
19724
19735
|
return {
|
|
19725
19736
|
project_name: context.project_name,
|
|
19726
19737
|
canonical_id: context.canonical_id,
|
|
@@ -19734,6 +19745,9 @@ function getSessionContext(db, input) {
|
|
|
19734
19745
|
freshness: item.freshness,
|
|
19735
19746
|
title: item.title
|
|
19736
19747
|
})),
|
|
19748
|
+
best_recall_key: bestRecallItem?.key ?? null,
|
|
19749
|
+
best_recall_title: bestRecallItem?.title ?? null,
|
|
19750
|
+
best_recall_kind: bestRecallItem?.kind ?? null,
|
|
19737
19751
|
resume_freshness: classifyResumeFreshness(resumeTimestamp),
|
|
19738
19752
|
resume_source_session_id: latestSession?.session_id ?? null,
|
|
19739
19753
|
resume_source_device_id: latestSession?.device_id ?? null,
|
|
@@ -20390,6 +20404,7 @@ async function resumeThread(db, config2, input = {}) {
|
|
|
20390
20404
|
}
|
|
20391
20405
|
}
|
|
20392
20406
|
const { context, handoff, recentChat, recentSessions, recall } = snapshot;
|
|
20407
|
+
const bestRecallItem = pickBestRecallItem2(snapshot.recallIndex.items);
|
|
20393
20408
|
const latestSession = recentSessions[0] ?? null;
|
|
20394
20409
|
const latestSummary = latestSession ? db.getSessionSummary(latestSession.session_id) : null;
|
|
20395
20410
|
const inferredRequest = latestSession?.request?.trim() || null;
|
|
@@ -20418,6 +20433,7 @@ async function resumeThread(db, config2, input = {}) {
|
|
|
20418
20433
|
currentThread
|
|
20419
20434
|
});
|
|
20420
20435
|
const suggestedTools = Array.from(new Set([
|
|
20436
|
+
...bestRecallItem ? ["load_recall_item"] : [],
|
|
20421
20437
|
"search_recall",
|
|
20422
20438
|
...recentChat.coverage_state !== "transcript-backed" && recentChat.messages.length > 0 ? ["repair_recall", "refresh_chat_recall"] : [],
|
|
20423
20439
|
...handoff ? ["load_handoff"] : [],
|
|
@@ -20432,6 +20448,9 @@ async function resumeThread(db, config2, input = {}) {
|
|
|
20432
20448
|
resume_source_device_id: handoff?.device_id ?? latestSession?.device_id ?? null,
|
|
20433
20449
|
resume_confidence: resumeConfidence,
|
|
20434
20450
|
resume_basis: resumeBasis,
|
|
20451
|
+
best_recall_key: bestRecallItem?.key ?? null,
|
|
20452
|
+
best_recall_title: bestRecallItem?.title ?? null,
|
|
20453
|
+
best_recall_kind: bestRecallItem?.kind ?? null,
|
|
20435
20454
|
repair_attempted: shouldRepair,
|
|
20436
20455
|
repair_result: repairResult ? {
|
|
20437
20456
|
imported_chat_messages: repairResult.imported_chat_messages,
|
|
@@ -20490,14 +20509,25 @@ async function buildResumeSnapshot(db, cwd, userId, currentDeviceId, limit) {
|
|
|
20490
20509
|
user_id: userId,
|
|
20491
20510
|
limit
|
|
20492
20511
|
});
|
|
20512
|
+
const recallIndex = listRecallItems(db, {
|
|
20513
|
+
cwd,
|
|
20514
|
+
project_scoped: true,
|
|
20515
|
+
user_id: userId,
|
|
20516
|
+
current_device_id: currentDeviceId,
|
|
20517
|
+
limit
|
|
20518
|
+
});
|
|
20493
20519
|
return {
|
|
20494
20520
|
context,
|
|
20495
20521
|
handoff: handoffResult.handoff,
|
|
20496
20522
|
recentChat,
|
|
20497
20523
|
recentSessions,
|
|
20498
|
-
recall
|
|
20524
|
+
recall,
|
|
20525
|
+
recallIndex
|
|
20499
20526
|
};
|
|
20500
20527
|
}
|
|
20528
|
+
function pickBestRecallItem2(items) {
|
|
20529
|
+
return items.find((item) => item.kind !== "memory") ?? items[0] ?? null;
|
|
20530
|
+
}
|
|
20501
20531
|
function extractCurrentThread(handoff) {
|
|
20502
20532
|
const narrative = handoff?.narrative ?? "";
|
|
20503
20533
|
const match = narrative.match(/Current thread:\s*(.+)/i);
|
|
@@ -22429,7 +22459,7 @@ process.on("SIGTERM", () => {
|
|
|
22429
22459
|
});
|
|
22430
22460
|
var server = new McpServer({
|
|
22431
22461
|
name: "engrm",
|
|
22432
|
-
version: "0.4.
|
|
22462
|
+
version: "0.4.33"
|
|
22433
22463
|
});
|
|
22434
22464
|
server.tool("save_observation", "Save an observation to memory", {
|
|
22435
22465
|
type: exports_external.enum([
|
|
@@ -23023,6 +23053,8 @@ server.tool("resume_thread", "USE FIRST when you want one direct 'where were we?
|
|
|
23023
23053
|
const handoffLine = result.handoff ? `Handoff: #${result.handoff.id} ${result.handoff.title}${result.handoff.source ? ` (${result.handoff.source})` : ""}
|
|
23024
23054
|
` : `Handoff: (none)
|
|
23025
23055
|
`;
|
|
23056
|
+
const openExactLine = result.best_recall_key ? `Open exact: load_recall_item("${result.best_recall_key}")${result.best_recall_title ? ` # ${result.best_recall_title}` : ""}
|
|
23057
|
+
` : "";
|
|
23026
23058
|
const basisLines = result.resume_basis.length > 0 ? result.resume_basis.map((item) => `- ${item}`).join(`
|
|
23027
23059
|
`) : "- (none)";
|
|
23028
23060
|
const toolTrailLines = result.tool_trail.length > 0 ? result.tool_trail.map((item) => `- ${item}`).join(`
|
|
@@ -23057,7 +23089,7 @@ server.tool("resume_thread", "USE FIRST when you want one direct 'where were we?
|
|
|
23057
23089
|
` + `Freshness: ${result.resume_freshness}
|
|
23058
23090
|
` + `Source: ${result.resume_source_session_id ?? "(unknown session)"}${result.resume_source_device_id ? ` (${result.resume_source_device_id})` : ""}
|
|
23059
23091
|
` + `Resume confidence: ${result.resume_confidence}
|
|
23060
|
-
` + repairLine + `Current thread: ${result.current_thread ?? "(unknown)"}
|
|
23092
|
+
` + repairLine + openExactLine + `Current thread: ${result.current_thread ?? "(unknown)"}
|
|
23061
23093
|
` + `Latest request: ${result.latest_request ?? "(none)"}
|
|
23062
23094
|
` + `${handoffLine}` + `Chat recall: ${result.chat_coverage_state}
|
|
23063
23095
|
` + `Suggested tools: ${result.suggested_tools.join(", ") || "(none)"}
|
|
@@ -23395,6 +23427,8 @@ server.tool("memory_console", "Show a high-signal local overview of what Engrm c
|
|
|
23395
23427
|
`) : "- (none)";
|
|
23396
23428
|
const recallPreviewLines = result.recall_index_preview.length > 0 ? result.recall_index_preview.map((item) => `- ${item.key} [${item.kind} · ${item.freshness}] ${item.title}`).join(`
|
|
23397
23429
|
`) : "- (none)";
|
|
23430
|
+
const openExactLine = result.best_recall_key ? `Open exact: load_recall_item("${result.best_recall_key}")${result.best_recall_title ? ` # ${result.best_recall_title}` : ""}
|
|
23431
|
+
` : "";
|
|
23398
23432
|
const projectLine = result.project ? `Project: ${result.project}
|
|
23399
23433
|
|
|
23400
23434
|
` : "";
|
|
@@ -23416,7 +23450,7 @@ server.tool("memory_console", "Show a high-signal local overview of what Engrm c
|
|
|
23416
23450
|
` + `${typeof result.estimated_read_tokens === "number" ? `Estimated read cost: ~${result.estimated_read_tokens}t
|
|
23417
23451
|
` : ""}` + `Suggested tools: ${result.suggested_tools.join(", ") || "(none)"}
|
|
23418
23452
|
|
|
23419
|
-
` + `Recall preview:
|
|
23453
|
+
` + openExactLine + `Recall preview:
|
|
23420
23454
|
${recallPreviewLines}
|
|
23421
23455
|
|
|
23422
23456
|
` + `Next actions:
|
|
@@ -23617,6 +23651,7 @@ server.tool("session_context", "Preview the exact project memory context Engrm w
|
|
|
23617
23651
|
` + `Canonical ID: ${result.canonical_id}
|
|
23618
23652
|
` + `Continuity: ${result.continuity_state} — ${result.continuity_summary}
|
|
23619
23653
|
` + `Recall index: ${result.recall_mode} · ${result.recall_items_ready} items ready
|
|
23654
|
+
` + `Open exact: ${result.best_recall_key ? `load_recall_item("${result.best_recall_key}")` : "(none)"}
|
|
23620
23655
|
` + `Resume readiness: ${result.resume_freshness} · ${result.resume_source_session_id ?? "(unknown session)"}${result.resume_source_device_id ? ` (${result.resume_source_device_id})` : ""}
|
|
23621
23656
|
` + `Loaded observations: ${result.session_count}
|
|
23622
23657
|
` + `Searchable total: ${result.total_active}
|
|
@@ -23697,6 +23732,8 @@ server.tool("project_memory_index", "Show a typed local memory index for the cur
|
|
|
23697
23732
|
`) : "- (none)";
|
|
23698
23733
|
const recallPreviewLines = result.recall_index_preview.length > 0 ? result.recall_index_preview.map((item) => `- ${item.key} [${item.kind} · ${item.freshness}] ${item.title}`).join(`
|
|
23699
23734
|
`) : "- (none)";
|
|
23735
|
+
const openExactLine = result.best_recall_key ? `Open exact: load_recall_item("${result.best_recall_key}")${result.best_recall_title ? ` # ${result.best_recall_title}` : ""}
|
|
23736
|
+
` : "";
|
|
23700
23737
|
return {
|
|
23701
23738
|
content: [
|
|
23702
23739
|
{
|
|
@@ -23720,7 +23757,7 @@ server.tool("project_memory_index", "Show a typed local memory index for the cur
|
|
|
23720
23757
|
` + `Estimated read cost: ~${result.estimated_read_tokens}t
|
|
23721
23758
|
` + `Suggested tools: ${result.suggested_tools.join(", ") || "(none)"}
|
|
23722
23759
|
|
|
23723
|
-
` + `Recall preview:
|
|
23760
|
+
` + openExactLine + `Recall preview:
|
|
23724
23761
|
${recallPreviewLines}
|
|
23725
23762
|
|
|
23726
23763
|
` + `Next actions:
|
package/package.json
CHANGED