local-agent-memory 0.0.0-stage → 1.0.0

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.
Files changed (43) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +108 -2
  3. package/dist/cli/commands/hook.d.ts +1 -0
  4. package/dist/cli/commands/hook.js +66 -0
  5. package/dist/cli/commands/init.d.ts +5 -0
  6. package/dist/cli/commands/init.js +158 -0
  7. package/dist/cli/commands/record.d.ts +3 -0
  8. package/dist/cli/commands/record.js +58 -0
  9. package/dist/cli/commands/reindex.d.ts +1 -0
  10. package/dist/cli/commands/reindex.js +41 -0
  11. package/dist/cli/commands/status.d.ts +1 -0
  12. package/dist/cli/commands/status.js +88 -0
  13. package/dist/cli/commands/sync.d.ts +8 -0
  14. package/dist/cli/commands/sync.js +134 -0
  15. package/dist/cli/commands/template.d.ts +1 -0
  16. package/dist/cli/commands/template.js +116 -0
  17. package/dist/cli/index.d.ts +2 -0
  18. package/dist/cli/index.js +140 -0
  19. package/dist/cli/mcp.d.ts +2 -0
  20. package/dist/cli/mcp.js +13 -0
  21. package/dist/core/embeddings.d.ts +14 -0
  22. package/dist/core/embeddings.js +127 -0
  23. package/dist/core/parser.d.ts +25 -0
  24. package/dist/core/parser.js +151 -0
  25. package/dist/core/search.d.ts +19 -0
  26. package/dist/core/search.js +100 -0
  27. package/dist/core/sync.d.ts +22 -0
  28. package/dist/core/sync.js +159 -0
  29. package/dist/db/project.d.ts +12 -0
  30. package/dist/db/project.js +113 -0
  31. package/dist/db/registry.d.ts +9 -0
  32. package/dist/db/registry.js +92 -0
  33. package/dist/mcp/middleware.d.ts +1 -0
  34. package/dist/mcp/middleware.js +46 -0
  35. package/dist/mcp/server.d.ts +2 -0
  36. package/dist/mcp/server.js +102 -0
  37. package/dist/mcp/tools.d.ts +2 -0
  38. package/dist/mcp/tools.js +244 -0
  39. package/dist/mcp/utils.d.ts +5 -0
  40. package/dist/mcp/utils.js +82 -0
  41. package/dist/setup/initGlobal.d.ts +5 -0
  42. package/dist/setup/initGlobal.js +167 -0
  43. package/package.json +72 -6
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,109 @@
1
- # Temporary Holding Version
1
+ # local-agent-memory
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **local-agent-memory** es una herramienta de indexación de memoria para agentes de IA que opera localmente en tus repositorios. Permite sincronizar documentos Markdown, llevar un registro de sesiones de codificación y exponer toda esta información a asistentes virtuales e IDEs a través del protocolo **Model Context Protocol (MCP)**. Además, aprovecha bases de datos SQLite con FTS5 (búsqueda de texto completo) y modelos vectoriales ONNX para potentes búsquedas semánticas.
4
+
5
+ ---
6
+
7
+ ## Instalación
8
+
9
+ Puedes instalar este paquete de forma global usando npm, lo cual te dará acceso a los binarios `memory` y `memory-mcp`.
10
+
11
+ ```bash
12
+ npm install -g local-agent-memory
13
+ ```
14
+
15
+ ---
16
+
17
+ ## Funcionalidades y Comandos Principales (`memory`)
18
+
19
+ Una vez instalado, tienes a tu disposición el CLI `memory` con los siguientes comandos para gestionar la memoria de tus proyectos:
20
+
21
+ ### 1. `init`
22
+ Inicializa el entorno de memoria en el repositorio actual. Esto crea las bases de datos SQLite locales y configura las estructuras necesarias en una carpeta oculta (`.memory`).
23
+
24
+ **Opciones:**
25
+ - `-f, --force`: Fuerza la inicialización incluso si el proyecto ya fue inicializado.
26
+ - `-r, --rules <rules>`: Inyecta reglas específicas para tu IDE (opciones: `cursor`, `claude`, `copilot`, `antigravity-ide`, `antigravity-cli`, `all`).
27
+ - `-d, --docs <path>`: Ruta opcional a un directorio de documentación existente para mapearlo/indexarlo automáticamente.
28
+
29
+ ```bash
30
+ memory init --rules all --docs ./docs
31
+ ```
32
+
33
+ ### 2. `sync`
34
+ Sincroniza los archivos Markdown del proyecto en el índice de memoria local. Escanea los documentos y actualiza la base de datos para que los agentes cuenten con el contexto más reciente.
35
+
36
+ ```bash
37
+ memory sync
38
+ ```
39
+
40
+ ### 3. `status`
41
+ Comprueba el estado de sincronización del proyecto de memoria actual, mostrando detalles sobre archivos indexados y pendienetes.
42
+
43
+ ```bash
44
+ memory status
45
+ ```
46
+
47
+ ### 4. `reindex` (o `prune`)
48
+ Reconstruye los índices FTS (texto completo) y vectoriales desde cero. Útil si sospechas que hay corrupción o desincronización en la base de datos local.
49
+
50
+ ```bash
51
+ memory reindex
52
+ # o
53
+ memory prune
54
+ ```
55
+
56
+ ### 5. `record-session`
57
+ Registra un resumen de tu sesión de trabajo actual en el "ledger" (libro mayor) de memoria, documentando las tareas completadas y el contexto para retomarlo más adelante.
58
+
59
+ **Opciones:**
60
+ - `-s, --summary <summary>`: Define el texto del resumen del trabajo realizado.
61
+
62
+ ```bash
63
+ memory record-session -s "Implementación del comando sync y corrección de bugs en SQLite"
64
+ ```
65
+
66
+ ### 6. `install-hook`
67
+ Instala ganchos de Git (Git hooks) en tu repositorio local para recordar automáticamente a los desarrolladores registrar sesiones al hacer commits, o para automatizar el registro.
68
+
69
+ ```bash
70
+ memory install-hook
71
+ ```
72
+
73
+ ### 7. `template <action>`
74
+ Gestiona las plantillas de memoria (permite listar, crear o exportar plantillas desde el proyecto).
75
+
76
+ **Opciones:**
77
+ - `-n, --name <name>`: El nombre de la plantilla a gestionar.
78
+
79
+ ```bash
80
+ memory template create --name mi-plantilla
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Integración de Agentes y Model Context Protocol (MCP)
86
+
87
+ Para que tus agentes de IA (como Claude Desktop, Cursor o Antigravity) puedan acceder a esta memoria enriquecida, el paquete provee un servidor MCP incorporado.
88
+
89
+ ### Configuración Automática (`memory mcp-setup`)
90
+ Esta utilidad configura tu entorno global instalando los modelos ONNX y binarios SQLite necesarios y, de manera interactiva, modifica el archivo de configuración del cliente MCP seleccionado (Claude, Cursor, Antigravity) para apuntar automáticamente a `memory-mcp`.
91
+
92
+ ```bash
93
+ memory mcp-setup
94
+ ```
95
+
96
+ ### Ejecución Manual del Servidor (`memory-mcp`)
97
+ Levanta el servidor compatible con el Model Context Protocol a través de stdio. Normalmente no necesitas ejecutar este comando directamente; los clientes como Claude Desktop o Cursor lo lanzan de forma transparente utilizando su archivo de configuración interno.
98
+
99
+ ```bash
100
+ memory-mcp
101
+ ```
102
+
103
+ *(Si configuras MCP manualmente, deberás establecer que tu cliente ejecute `memory-mcp` sin argumentos extra)*
104
+
105
+ ---
106
+
107
+ ## Licencia
108
+
109
+ Este proyecto está bajo la licencia **ISC**.
@@ -0,0 +1 @@
1
+ export declare function installGitHook(): Promise<void>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.installGitHook = installGitHook;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ async function installGitHook() {
11
+ const cwd = process.cwd();
12
+ const gitDir = node_path_1.default.join(cwd, ".git");
13
+ const hooksDir = node_path_1.default.join(gitDir, "hooks");
14
+ const spinner = (0, ora_1.default)("Installing Git hook...").start();
15
+ try {
16
+ if (!node_fs_1.default.existsSync(gitDir)) {
17
+ spinner.fail("No .git directory found. Initialize a git repository first.");
18
+ process.exit(1);
19
+ }
20
+ if (!node_fs_1.default.existsSync(hooksDir)) {
21
+ await node_fs_1.default.promises.mkdir(hooksDir, { recursive: true });
22
+ }
23
+ // A prepare-commit-msg hook that reminds the developer
24
+ const hookName = "prepare-commit-msg";
25
+ const hookPath = node_path_1.default.join(hooksDir, hookName);
26
+ const hookContent = `#!/bin/sh
27
+ # local-agent-memory prepare-commit-msg hook
28
+
29
+ # Add a reminder to the commit message template
30
+ echo "" >> "$1"
31
+ echo "# 🧠 Remember to update the local-agent-memory ledger if you made architectural changes." >> "$1"
32
+ echo "# You can run: memory record-session --summary \\"..."\\"" >> "$1"
33
+ `;
34
+ // Write file
35
+ await node_fs_1.default.promises.writeFile(hookPath, hookContent, { mode: 0o755 });
36
+ node_fs_1.default.chmodSync(hookPath, 0o755);
37
+ // Also a post-commit hook that optionally captures the commit msg as a session if wanted.
38
+ // For now, the prompt requested a prepare-commit-msg or pre-commit hook that reminds or updates the ledger.
39
+ // Given git hooks are usually headless, appending a reminder to prepare-commit-msg is the standard approach,
40
+ // or using a post-commit hook to execute the memory update automatically.
41
+ // Let's create a post-commit hook too, as a fallback passive memory strategy
42
+ const postHookName = "post-commit";
43
+ const postHookPath = node_path_1.default.join(hooksDir, postHookName);
44
+ const postHookContent = `#!/bin/sh
45
+ # local-agent-memory post-commit hook
46
+ # Automatically records a memory session for this commit.
47
+
48
+ COMMIT_MSG=$(git log -1 --pretty=%B)
49
+
50
+ # If memory CLI exists, run it
51
+ if command -v memory >/dev/null 2>&1; then
52
+ memory record-session --summary "Commit: $COMMIT_MSG" > /dev/null 2>&1 &
53
+ elif npx --no-install memory --version >/dev/null 2>&1; then
54
+ npx --no-install memory record-session --summary "Commit: $COMMIT_MSG" > /dev/null 2>&1 &
55
+ fi
56
+ `;
57
+ await node_fs_1.default.promises.writeFile(postHookPath, postHookContent, { mode: 0o755 });
58
+ node_fs_1.default.chmodSync(postHookPath, 0o755);
59
+ spinner.succeed(`Successfully installed git hooks (prepare-commit-msg, post-commit) to ensure memory consistency.`);
60
+ }
61
+ catch (err) {
62
+ spinner.fail("Failed to install Git hook.");
63
+ console.error(err.message);
64
+ process.exit(1);
65
+ }
66
+ }
@@ -0,0 +1,5 @@
1
+ export declare function initProject(options?: {
2
+ force?: boolean;
3
+ rules?: string;
4
+ docs?: string;
5
+ }): Promise<void>;
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initProject = initProject;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const inquirer_1 = __importDefault(require("inquirer"));
11
+ const ora_1 = __importDefault(require("ora"));
12
+ const project_1 = require("../../db/project");
13
+ const registry_1 = require("../../db/registry");
14
+ async function initProject(options = {}) {
15
+ const cwd = process.cwd();
16
+ const memoryDir = node_path_1.default.join(cwd, ".memory");
17
+ const gitDir = node_path_1.default.join(cwd, ".git");
18
+ if (!node_fs_1.default.existsSync(gitDir)) {
19
+ console.warn("⚠️ No .git directory found. Automatic Git hooks cannot be installed yet.");
20
+ console.warn(" Run `git init` and then `memory install-hook` later.\n");
21
+ }
22
+ const spinner = (0, ora_1.default)("Initializing project...").start();
23
+ try {
24
+ if (node_fs_1.default.existsSync(memoryDir)) {
25
+ if (!options.force) {
26
+ spinner.fail("Project already initialized. Use --force to overwrite.");
27
+ process.exit(1);
28
+ }
29
+ else {
30
+ // If force, we just continue (or we might want to clear it, but prompt says "a menos que se use --force", meaning we can overwrite or just proceed)
31
+ }
32
+ }
33
+ else {
34
+ await node_fs_1.default.promises.mkdir(memoryDir, { recursive: true });
35
+ }
36
+ // Subdirectories
37
+ await node_fs_1.default.promises.mkdir(node_path_1.default.join(memoryDir, "decisions"), {
38
+ recursive: true,
39
+ });
40
+ await node_fs_1.default.promises.mkdir(node_path_1.default.join(memoryDir, "context"), {
41
+ recursive: true,
42
+ });
43
+ // UUID
44
+ const projectId = node_crypto_1.default.randomUUID();
45
+ // Config file
46
+ const configData = {
47
+ project_id: projectId,
48
+ created_at: new Date().toISOString(),
49
+ include_paths: [".memory"],
50
+ };
51
+ if (options.docs) {
52
+ configData.include_paths.push(options.docs);
53
+ }
54
+ await node_fs_1.default.promises.writeFile(node_path_1.default.join(memoryDir, "config.json"), JSON.stringify(configData, null, 2));
55
+ // Core markdown
56
+ const coreMd = `# Core Rules\n\nThis file contains the core behavior and rules for this project.\n`;
57
+ await node_fs_1.default.promises.writeFile(node_path_1.default.join(memoryDir, "core.md"), coreMd);
58
+ // Initialize local DB
59
+ const localDbPath = (0, project_1.getLocalDbPath)(cwd);
60
+ const localDb = (0, project_1.initLocalDb)(localDbPath);
61
+ await new Promise((resolve, reject) => {
62
+ localDb.close((err) => {
63
+ if (err)
64
+ reject(err);
65
+ else
66
+ resolve();
67
+ });
68
+ });
69
+ // Global Registry
70
+ // Make sure global registry db is initialized
71
+ const registryDb = (0, registry_1.initRegistryDb)();
72
+ await new Promise((resolve, reject) => {
73
+ registryDb.close((err) => {
74
+ if (err)
75
+ reject(err);
76
+ else
77
+ resolve();
78
+ });
79
+ });
80
+ await (0, registry_1.registerProject)(projectId, cwd);
81
+ // Inject agent instructions
82
+ const memoryInstructions = `
83
+ <!-- local-agent-memory rules -->
84
+ - Consulta la herramienta MCP \`search_memory\` antes de proponer cambios de arquitectura, interfaces o decisiones de diseño.
85
+ - Utiliza \`log_decision\` cada vez que se adopte una convención de código, biblioteca o patrón técnico nuevo.
86
+ - Utiliza la herramienta de sesión para resumir acuerdos antes de dar por terminada una tarea.
87
+ `;
88
+ spinner.stop();
89
+ let tools = [];
90
+ const availableRules = {
91
+ cursor: ".cursorrules",
92
+ windsurf: ".windsurfrules",
93
+ copilot: ".github/copilot-instructions.md",
94
+ claude: "CLAUDE.md",
95
+ "antigravity-ide": ".agents/rules/memory.md",
96
+ "antigravity-cli": ".agents/rules/memory.md",
97
+ };
98
+ if (options.rules) {
99
+ if (options.rules.toLowerCase() === "all") {
100
+ tools = Array.from(new Set(Object.values(availableRules)));
101
+ }
102
+ else {
103
+ const rulesList = options.rules
104
+ .split(",")
105
+ .map((r) => r.trim().toLowerCase());
106
+ tools = Array.from(new Set(rulesList
107
+ .map((r) => availableRules[r])
108
+ .filter((r) => Boolean(r))));
109
+ }
110
+ }
111
+ else {
112
+ const answers = await inquirer_1.default.prompt([
113
+ {
114
+ type: "checkbox",
115
+ name: "tools",
116
+ message: "Select the IDEs/CLIs to generate or inject memory rules into:",
117
+ choices: [
118
+ { name: "Cursor (.cursorrules)", value: ".cursorrules" },
119
+ { name: "Windsurf (.windsurfrules)", value: ".windsurfrules" },
120
+ {
121
+ name: "GitHub Copilot (.github/copilot-instructions.md)",
122
+ value: ".github/copilot-instructions.md",
123
+ },
124
+ { name: "Claude Code (CLAUDE.md)", value: "CLAUDE.md" },
125
+ {
126
+ name: "Antigravity IDE / CLI (.agents/rules/memory.md)",
127
+ value: ".agents/rules/memory.md",
128
+ },
129
+ ],
130
+ },
131
+ ]);
132
+ tools = answers.tools;
133
+ }
134
+ spinner.start("Finishing initialization...");
135
+ for (const file of tools) {
136
+ const filePath = node_path_1.default.join(cwd, file);
137
+ const dir = node_path_1.default.dirname(filePath);
138
+ if (!node_fs_1.default.existsSync(dir)) {
139
+ await node_fs_1.default.promises.mkdir(dir, { recursive: true });
140
+ }
141
+ if (node_fs_1.default.existsSync(filePath)) {
142
+ const content = await node_fs_1.default.promises.readFile(filePath, "utf8");
143
+ if (!content.includes("<!-- local-agent-memory rules -->")) {
144
+ await node_fs_1.default.promises.appendFile(filePath, `\n${memoryInstructions}`);
145
+ }
146
+ }
147
+ else {
148
+ await node_fs_1.default.promises.writeFile(filePath, `${memoryInstructions.trim()}\n`);
149
+ }
150
+ }
151
+ spinner.succeed(`Project initialized successfully with ID: ${projectId}`);
152
+ }
153
+ catch (err) {
154
+ spinner.fail("Failed to initialize project.");
155
+ console.error(err.message);
156
+ process.exit(1);
157
+ }
158
+ }
@@ -0,0 +1,3 @@
1
+ export declare function recordSession(options?: {
2
+ summary?: string;
3
+ }): Promise<void>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.recordSession = recordSession;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const inquirer_1 = __importDefault(require("inquirer"));
10
+ const ora_1 = __importDefault(require("ora"));
11
+ const middleware_1 = require("../../mcp/middleware");
12
+ async function recordSession(options = {}) {
13
+ const cwd = process.cwd();
14
+ const memoryDir = node_path_1.default.join(cwd, ".memory");
15
+ const ledgerDir = node_path_1.default.join(memoryDir, "ledger");
16
+ const dateObj = new Date();
17
+ const year = dateObj.getFullYear();
18
+ const month = String(dateObj.getMonth() + 1).padStart(2, "0");
19
+ const day = String(dateObj.getDate()).padStart(2, "0");
20
+ const hours = String(dateObj.getHours()).padStart(2, "0");
21
+ const minutes = String(dateObj.getMinutes()).padStart(2, "0");
22
+ const seconds = String(dateObj.getSeconds()).padStart(2, "0");
23
+ const filename = `${year}-${month}-${day}-${hours}-${minutes}-${seconds}-session.md`;
24
+ const summariesPath = node_path_1.default.join(ledgerDir, filename);
25
+ if (!node_fs_1.default.existsSync(memoryDir)) {
26
+ console.error("No .memory directory found. Run `memory init` first.");
27
+ process.exit(1);
28
+ }
29
+ let summary = options.summary;
30
+ if (!summary) {
31
+ const answers = await inquirer_1.default.prompt([
32
+ {
33
+ type: "input",
34
+ name: "summary",
35
+ message: "Enter a summary of the work done in this session:",
36
+ validate: (input) => input.trim().length > 0 || "Summary cannot be empty",
37
+ },
38
+ ]);
39
+ summary = answers.summary;
40
+ }
41
+ const spinner = (0, ora_1.default)("Recording session summary...").start();
42
+ try {
43
+ if (!node_fs_1.default.existsSync(ledgerDir)) {
44
+ await node_fs_1.default.promises.mkdir(ledgerDir, { recursive: true });
45
+ }
46
+ const date = dateObj.toISOString();
47
+ const content = `\n## Session ended at ${date}\n\n${summary}\n\n---\n`;
48
+ await node_fs_1.default.promises.writeFile(summariesPath, content);
49
+ // Trigger sync
50
+ await (0, middleware_1.syncMiddleware)();
51
+ spinner.succeed(`Session summary recorded successfully in .memory/ledger/${filename}`);
52
+ }
53
+ catch (err) {
54
+ spinner.fail("Failed to record session summary.");
55
+ console.error(err.message);
56
+ process.exit(1);
57
+ }
58
+ }
@@ -0,0 +1 @@
1
+ export declare function reindexProject(): Promise<void>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.reindexProject = reindexProject;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const project_1 = require("../../db/project");
11
+ const sync_1 = require("./sync");
12
+ async function reindexProject() {
13
+ const cwd = process.cwd();
14
+ const memoryDir = node_path_1.default.join(cwd, ".memory");
15
+ if (!node_fs_1.default.existsSync(memoryDir)) {
16
+ console.error("Project not initialized. Run memory init first.");
17
+ process.exit(1);
18
+ }
19
+ const spinner = (0, ora_1.default)("Reindexing project memory (this may take a while)...").start();
20
+ try {
21
+ const localDbPath = (0, project_1.getLocalDbPath)(cwd);
22
+ // Check if db exists, then delete to force complete reindex
23
+ if (node_fs_1.default.existsSync(localDbPath)) {
24
+ spinner.text = "Deleting corrupted or existing local index...";
25
+ node_fs_1.default.unlinkSync(localDbPath);
26
+ // Also delete the WAL and SHM files if they exist
27
+ if (node_fs_1.default.existsSync(`${localDbPath}-wal`))
28
+ node_fs_1.default.unlinkSync(`${localDbPath}-wal`);
29
+ if (node_fs_1.default.existsSync(`${localDbPath}-shm`))
30
+ node_fs_1.default.unlinkSync(`${localDbPath}-shm`);
31
+ }
32
+ spinner.text = "Rebuilding index from scratch...";
33
+ const { newCount } = await (0, sync_1.doSyncProject)(cwd);
34
+ spinner.succeed(`Reindex complete: ${newCount} files processed.`);
35
+ }
36
+ catch (err) {
37
+ spinner.fail("Reindex failed.");
38
+ console.error(err.message);
39
+ process.exit(1);
40
+ }
41
+ }
@@ -0,0 +1 @@
1
+ export declare function projectStatus(): Promise<void>;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.projectStatus = projectStatus;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const project_1 = require("../../db/project");
11
+ const registry_1 = require("../../db/registry");
12
+ const sync_1 = require("./sync");
13
+ async function projectStatus() {
14
+ const cwd = process.cwd();
15
+ const memoryDir = node_path_1.default.join(cwd, ".memory");
16
+ if (!node_fs_1.default.existsSync(memoryDir)) {
17
+ console.error("Project not initialized. Run memory init first.");
18
+ process.exit(1);
19
+ }
20
+ const spinner = (0, ora_1.default)("Checking project status...").start();
21
+ try {
22
+ const localDbPath = (0, project_1.getLocalDbPath)(cwd);
23
+ // Check global registry
24
+ const projectId = await (0, registry_1.getProjectByPath)(cwd);
25
+ // Check db manifests
26
+ let manifests = [];
27
+ if (node_fs_1.default.existsSync(localDbPath)) {
28
+ manifests = await (0, project_1.getAllManifests)(localDbPath);
29
+ }
30
+ const manifestMap = new Map(manifests.map((m) => [m.file_path, m]));
31
+ const currentFiles = await getAllMarkdownFiles(memoryDir);
32
+ let newCount = 0;
33
+ let modCount = 0;
34
+ let delCount = 0;
35
+ let syncedCount = 0;
36
+ for (const file of currentFiles) {
37
+ const stats = await node_fs_1.default.promises.stat(file);
38
+ const mtime = stats.mtimeMs;
39
+ const relativePath = node_path_1.default.relative(cwd, file);
40
+ const existing = manifestMap.get(relativePath);
41
+ if (!existing) {
42
+ newCount++;
43
+ }
44
+ else if (existing.mtime !== mtime) {
45
+ // Hash check for modified
46
+ const sha256 = await (0, sync_1.computeSha256)(file);
47
+ if (sha256 !== existing.sha256) {
48
+ modCount++;
49
+ }
50
+ else {
51
+ syncedCount++;
52
+ }
53
+ }
54
+ else {
55
+ syncedCount++;
56
+ }
57
+ manifestMap.delete(relativePath);
58
+ }
59
+ delCount = manifestMap.size;
60
+ spinner.stop();
61
+ console.log(`\nProject ID: ${projectId || "Unknown (Not in global registry)"}`);
62
+ console.log(`Total MD files tracking: ${currentFiles.length}`);
63
+ console.log(`---------------------------------`);
64
+ console.log(`In sync: ${syncedCount}`);
65
+ console.log(`New (untracked): ${newCount}`);
66
+ console.log(`Modified (unsynced): ${modCount}`);
67
+ console.log(`Deleted (orphaned in db): ${delCount}`);
68
+ console.log(`\nRun \`memory sync\` to update index.`);
69
+ }
70
+ catch (err) {
71
+ spinner.fail("Status check failed.");
72
+ console.error(err.message);
73
+ process.exit(1);
74
+ }
75
+ }
76
+ // Utility identical to sync, duplication for simplicity of module boundaries, or could be extracted
77
+ async function getAllMarkdownFiles(dirPath, arrayOfFiles = []) {
78
+ const files = await node_fs_1.default.promises.readdir(dirPath, { withFileTypes: true });
79
+ for (const file of files) {
80
+ if (file.isDirectory()) {
81
+ arrayOfFiles = await getAllMarkdownFiles(node_path_1.default.join(dirPath, file.name), arrayOfFiles);
82
+ }
83
+ else if (file.name.endsWith(".md")) {
84
+ arrayOfFiles.push(node_path_1.default.join(dirPath, file.name));
85
+ }
86
+ }
87
+ return arrayOfFiles;
88
+ }
@@ -0,0 +1,8 @@
1
+ export interface SyncResult {
2
+ newCount: number;
3
+ modCount: number;
4
+ delCount: number;
5
+ }
6
+ export declare function doSyncProject(cwd: string): Promise<SyncResult>;
7
+ export declare function syncProject(): Promise<void>;
8
+ export declare function computeSha256(filePath: string): Promise<string>;