@lotargo/memory_plugin 1.2.1 → 1.2.3
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/mcp-server/cli.js
CHANGED
|
@@ -1109,13 +1109,26 @@ export async function runCli() {
|
|
|
1109
1109
|
break;
|
|
1110
1110
|
}
|
|
1111
1111
|
|
|
1112
|
-
const docItems = docs.map((doc) =>
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1112
|
+
const docItems = docs.map((doc) => {
|
|
1113
|
+
const rawDate = doc.created_at || doc.updated_at || "";
|
|
1114
|
+
let formattedDate = "";
|
|
1115
|
+
if (rawDate) {
|
|
1116
|
+
try {
|
|
1117
|
+
const d = typeof rawDate === "number" ? new Date(rawDate) : new Date(String(rawDate));
|
|
1118
|
+
formattedDate = isNaN(d.getTime()) ? String(rawDate).substring(0, 16) : d.toISOString().replace("T", " ").substring(0, 16);
|
|
1119
|
+
} catch (e) {
|
|
1120
|
+
formattedDate = String(rawDate).substring(0, 16);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
const docIdStr = doc.id != null ? String(doc.id) : "";
|
|
1124
|
+
return {
|
|
1125
|
+
label: doc.title || doc.path || "Untitled Document",
|
|
1126
|
+
badge: formattedDate,
|
|
1127
|
+
hint: docIdStr ? `ID: ${docIdStr.substring(0, 8)}...` : "",
|
|
1128
|
+
info: `Path: ${doc.path || "N/A"}`,
|
|
1129
|
+
value: doc,
|
|
1130
|
+
};
|
|
1131
|
+
});
|
|
1119
1132
|
docItems.push({ label: "< Back to Main Menu", value: "back" });
|
|
1120
1133
|
|
|
1121
1134
|
const docRes = await selectSimpleMenu({
|
|
@@ -148,13 +148,17 @@ export async function getExtractor(modelName = null, progressCallback = null) {
|
|
|
148
148
|
|
|
149
149
|
if (targetModel !== "Xenova/multilingual-e5-small") {
|
|
150
150
|
console.warn(`[Fallback] Reverting to standard default model "Xenova/multilingual-e5-small"...`);
|
|
151
|
+
resetExtractor();
|
|
151
152
|
try {
|
|
152
|
-
|
|
153
|
+
const fallbackOpts = {
|
|
153
154
|
quantized: true,
|
|
154
155
|
dtype: "q8",
|
|
155
156
|
device: "cpu",
|
|
156
157
|
session_options: { graphOptimizationLevel: "all", executionMode: "sequential" },
|
|
157
|
-
}
|
|
158
|
+
};
|
|
159
|
+
if (progressCallback) fallbackOpts.progress_callback = progressCallback;
|
|
160
|
+
|
|
161
|
+
extractorInstance = await pipeline("feature-extraction", "Xenova/multilingual-e5-small", fallbackOpts);
|
|
158
162
|
loadedModelName = "Xenova/multilingual-e5-small";
|
|
159
163
|
loadedDevice = "cpu";
|
|
160
164
|
} catch (err3) {
|
|
@@ -175,6 +179,38 @@ export function resetExtractor() {
|
|
|
175
179
|
loadedDevice = null;
|
|
176
180
|
}
|
|
177
181
|
|
|
182
|
+
export function deleteModelCache(modelName) {
|
|
183
|
+
const info = getModelStorageInfo(modelName);
|
|
184
|
+
if (info.status === "not_downloaded" || !fs.existsSync(info.dir)) {
|
|
185
|
+
return { deleted: false, reason: "Model directory not found" };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
resetExtractor();
|
|
189
|
+
if (global.gc) {
|
|
190
|
+
try { global.gc(); } catch (e) {}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
fs.rmSync(info.dir, { recursive: true, force: true });
|
|
195
|
+
const parentDir = path.dirname(info.dir);
|
|
196
|
+
if (fs.existsSync(parentDir) && fs.readdirSync(parentDir).length === 0) {
|
|
197
|
+
fs.rmdirSync(parentDir);
|
|
198
|
+
}
|
|
199
|
+
return { deleted: true, modelName, freedMB: info.sizeMB };
|
|
200
|
+
} catch (err) {
|
|
201
|
+
try {
|
|
202
|
+
const corruptPath = `${info.dir}.corrupt_${Date.now()}`;
|
|
203
|
+
fs.renameSync(info.dir, corruptPath);
|
|
204
|
+
setTimeout(() => {
|
|
205
|
+
try { fs.rmSync(corruptPath, { recursive: true, force: true }); } catch (e) {}
|
|
206
|
+
}, 1000);
|
|
207
|
+
return { deleted: true, modelName, freedMB: info.sizeMB };
|
|
208
|
+
} catch (renameErr) {
|
|
209
|
+
return { deleted: false, reason: `${err.message} (Rename fallback: ${renameErr.message})` };
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
178
214
|
export function formatInputText(text, isQuery = false, modelName = null, instruction = null) {
|
|
179
215
|
if (!text) return "";
|
|
180
216
|
const targetModel = modelName || getConfig().embeddingModel || "Xenova/multilingual-e5-small";
|
|
@@ -510,25 +546,6 @@ export function getModelStorageInfo(modelName) {
|
|
|
510
546
|
return { status: "partial", sizeMB, bytes: totalBytes, dir: modelDir };
|
|
511
547
|
}
|
|
512
548
|
|
|
513
|
-
export function deleteModelCache(modelName) {
|
|
514
|
-
const info = getModelStorageInfo(modelName);
|
|
515
|
-
if (info.status === "not_downloaded" || !fs.existsSync(info.dir)) {
|
|
516
|
-
return { deleted: false, reason: "Model directory not found" };
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
try {
|
|
520
|
-
fs.rmSync(info.dir, { recursive: true, force: true });
|
|
521
|
-
const parentDir = path.dirname(info.dir);
|
|
522
|
-
if (fs.existsSync(parentDir) && fs.readdirSync(parentDir).length === 0) {
|
|
523
|
-
fs.rmdirSync(parentDir);
|
|
524
|
-
}
|
|
525
|
-
resetExtractor();
|
|
526
|
-
return { deleted: true, modelName, freedMB: info.sizeMB };
|
|
527
|
-
} catch (err) {
|
|
528
|
-
return { deleted: false, reason: err.message };
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
549
|
export function listAllCachedModels() {
|
|
533
550
|
const result = [];
|
|
534
551
|
if (!fs.existsSync(MODELS_DIR)) return result;
|
|
@@ -8,7 +8,9 @@ const END_MARKER = "<!-- END MEMORY AGENT PROMPT -->";
|
|
|
8
8
|
|
|
9
9
|
export const PROMPT_BLOCK = `${START_MARKER}
|
|
10
10
|
[SYSTEM INSTRUCTION: PERSONAL CONTEXT & MEMORY AGENT]
|
|
11
|
-
|
|
11
|
+
1. MANDATORY FIRST STEP (SESSION INITIALIZATION): At the very start of every session or conversation, your VERY FIRST ACTION MUST BE to execute \`recall\` from \`memory-agent\` to load all saved facts, user preferences, personal context, and project guidelines BEFORE performing any other tasks or reading code.
|
|
12
|
+
2. PROACTIVE SAVING DIRECTIVE: You MUST automatically and proactively call \`remember\` from \`memory-agent\` whenever the user shares durable facts, personal preferences, coding guidelines, technology choices, or project architecture decisions. Do NOT wait for explicit user commands like "remember this".
|
|
13
|
+
3. SIGNAL FILTER: Save only high-signal facts (name, language, roles, constraints, tech stack preferences, architecture decisions, conventions). Translate facts into clear, concise English when saving. Do NOT save transient details or one-off conversation turns.
|
|
12
14
|
${END_MARKER}`;
|
|
13
15
|
|
|
14
16
|
export function getGlobalPromptTargets() {
|
package/mcp-server/setup.js
CHANGED
|
@@ -115,9 +115,12 @@ export async function runSetup() {
|
|
|
115
115
|
};
|
|
116
116
|
await writeFile(geminiConfigFile, JSON.stringify(config, null, 2));
|
|
117
117
|
|
|
118
|
-
// Local workspace config (.agents/mcp_config.json) if
|
|
118
|
+
// Local workspace config (.agents/mcp_config.json) only if .agents exists or --local flag is set
|
|
119
119
|
const cwd = process.cwd();
|
|
120
|
-
|
|
120
|
+
const hasAgentsDir = existsSync(join(cwd, ".agents"));
|
|
121
|
+
const isLocalRequested = args.includes("--local");
|
|
122
|
+
|
|
123
|
+
if (hasAgentsDir || isLocalRequested) {
|
|
121
124
|
const localAgentsDir = join(cwd, ".agents");
|
|
122
125
|
await mkdir(localAgentsDir, { recursive: true });
|
|
123
126
|
const localMcpFile = join(localAgentsDir, "mcp_config.json");
|
|
@@ -133,9 +136,10 @@ export async function runSetup() {
|
|
|
133
136
|
args: ["-y", "@lotargo/memory_plugin"],
|
|
134
137
|
};
|
|
135
138
|
await writeFile(localMcpFile, JSON.stringify(localConfig, null, 2));
|
|
139
|
+
console.log(" [OK] Antigravity: configured MCP server in ~/.gemini/config/mcp_config.json and .agents/mcp_config.json");
|
|
140
|
+
} else {
|
|
141
|
+
console.log(" [OK] Antigravity: configured MCP server in ~/.gemini/config/mcp_config.json");
|
|
136
142
|
}
|
|
137
|
-
|
|
138
|
-
console.log(" [OK] Antigravity: configured MCP server in ~/.gemini/config/mcp_config.json and .agents/mcp_config.json");
|
|
139
143
|
configuredCount++;
|
|
140
144
|
} catch (err) {
|
|
141
145
|
console.log(" [SKIP] Antigravity setup skipped:", err.message);
|
package/opencode-plugin/index.js
CHANGED
|
@@ -74,12 +74,15 @@ async function notify(client, message, variant = "success") {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const MEMORY_INSTRUCTION =
|
|
77
|
+
"MANDATORY FIRST STEP (READ MEMORIES FIRST):\n" +
|
|
78
|
+
"At the start of every session, you MUST thoroughly review all saved memories provided below BEFORE performing any user task or editing code.\n" +
|
|
79
|
+
"PROACTIVE MEMORY DIRECTIVE:\n" +
|
|
80
|
+
"You MUST automatically and proactively call `remember` whenever the user shares durable facts, personal preferences, coding guidelines, tech stack choices, architecture decisions, or project conventions.\n" +
|
|
81
|
+
"Do NOT wait for explicit user commands like \"remember this\". Automatically capture high-signal facts in real time.\n" +
|
|
77
82
|
"Use `remember` only for important, durable facts about the user and project.\n" +
|
|
78
|
-
"Save high-signal
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
"or anything unlikely to be useful in future sessions.\n" +
|
|
82
|
-
"When saving, translate the fact into English and keep it concise.\n" +
|
|
83
|
+
"Save high-signal items: user role, goals, constraints, tech stack preferences, architecture decisions, project conventions.\n" +
|
|
84
|
+
"DO NOT save: transient details, one-off statements, full conversation turns, or anything unlikely to be useful in future sessions.\n" +
|
|
85
|
+
"When saving, translate the fact into clear, concise English.\n" +
|
|
83
86
|
"Use `scope: \"global\"` for personal facts, `scope: \"project\"` for project-specific facts.";
|
|
84
87
|
|
|
85
88
|
function buildMemoryContext(globalFacts, projectFacts, projectKey) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lotargo/memory_plugin",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Persistent memory agent for coding AI tools — remembers user preferences and project context across sessions. Works with Antigravity, OpenCode, Claude Code, and Codex.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "opencode-plugin/index.js",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: using-memory
|
|
3
|
-
description: Comprehensive guide for using the Memory & Hybrid RAG Knowledge Engine tools (remember, recall, forget, ingest_document, query_knowledge_base, manage_knowledge_base). Trigger whenever
|
|
3
|
+
description: Comprehensive guide for using the Memory & Hybrid RAG Knowledge Engine tools (remember, recall, forget, link_knowledge, ingest_document, query_knowledge_base, manage_knowledge_base). Trigger proactively whenever user preferences, project conventions, technology stack choices, or architecture decisions are introduced, or when querying ingested documentation, indexing files/repos, or managing persistent knowledge.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Using Memory & Hybrid RAG Knowledge Engine
|
|
@@ -116,7 +116,8 @@ In such cases, use the **Full Raw Document Reading** mechanism:
|
|
|
116
116
|
|
|
117
117
|
## 4. Core Directives for AI Agents
|
|
118
118
|
|
|
119
|
-
1. **
|
|
120
|
-
2. **
|
|
121
|
-
3. **
|
|
122
|
-
4. **
|
|
119
|
+
1. **Read Memories First (MANDATORY)**: At the very start of any session or conversation, your VERY FIRST STEP MUST BE to execute `recall` to load all saved facts, user context, and project guidelines BEFORE performing any other task or code analysis.
|
|
120
|
+
2. **Be Proactive**: When the user mentions a durable preference, personal fact, or constraint, save it immediately using `remember`. Do not wait for explicit user commands.
|
|
121
|
+
3. **Check Knowledge Base First**: If a user asks how a specific module, API, or project architecture works, call `query_knowledge_base` using concept-dense search phrases.
|
|
122
|
+
4. **Inspect Ambiguous Docs Directly**: If querying produces low relevance scores on abstractly-named documents, call `manage_knowledge_base(action: "read_document")` to inspect the full text directly.
|
|
123
|
+
5. **Keep Memory Clean**: If a preference changes, call `forget` on the outdated entry before saving the new one.
|