gnosys-mcp 2.0.1 → 2.1.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.
- package/dist/cli.js +250 -72
- package/dist/cli.js.map +1 -1
- package/dist/index.js +81 -61
- package/dist/index.js.map +1 -1
- package/dist/lib/db.d.ts +61 -4
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +181 -15
- package/dist/lib/db.js.map +1 -1
- package/dist/lib/dbWrite.d.ts +3 -1
- package/dist/lib/dbWrite.d.ts.map +1 -1
- package/dist/lib/dbWrite.js +5 -1
- package/dist/lib/dbWrite.js.map +1 -1
- package/dist/lib/migrate.d.ts.map +1 -1
- package/dist/lib/migrate.js +4 -0
- package/dist/lib/migrate.js.map +1 -1
- package/dist/lib/projectIdentity.d.ts +66 -0
- package/dist/lib/projectIdentity.d.ts.map +1 -0
- package/dist/lib/projectIdentity.js +148 -0
- package/dist/lib/projectIdentity.js.map +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25,6 +25,7 @@ import { GnosysAsk } from "./lib/ask.js";
|
|
|
25
25
|
import { getLLMProvider, isProviderAvailable } from "./lib/llm.js";
|
|
26
26
|
import { GnosysDB } from "./lib/db.js";
|
|
27
27
|
import { migrate, formatMigrationReport } from "./lib/migrate.js";
|
|
28
|
+
import { createProjectIdentity } from "./lib/projectIdentity.js";
|
|
28
29
|
// Load API keys from ~/.config/gnosys/.env (same as MCP server)
|
|
29
30
|
const home = process.env.HOME || process.env.USERPROFILE || "/tmp";
|
|
30
31
|
dotenv.config({ path: path.join(home, ".config", "gnosys", ".env") });
|
|
@@ -212,67 +213,95 @@ program
|
|
|
212
213
|
// ─── gnosys init ─────────────────────────────────────────────────────────
|
|
213
214
|
program
|
|
214
215
|
.command("init")
|
|
215
|
-
.description("Initialize
|
|
216
|
+
.description("Initialize Gnosys in the current directory. Creates project identity, registers in central DB, and sets up store.")
|
|
216
217
|
.option("-d, --directory <dir>", "Target directory (default: cwd)")
|
|
218
|
+
.option("-n, --name <name>", "Project name (default: directory basename)")
|
|
217
219
|
.action(async (opts) => {
|
|
218
220
|
const targetDir = opts.directory
|
|
219
221
|
? path.resolve(opts.directory)
|
|
220
222
|
: process.cwd();
|
|
221
223
|
const storePath = path.join(targetDir, ".gnosys");
|
|
224
|
+
// Check if already exists — re-sync identity instead of failing
|
|
225
|
+
let isResync = false;
|
|
222
226
|
try {
|
|
223
227
|
await fs.stat(storePath);
|
|
224
|
-
|
|
225
|
-
process.exit(1);
|
|
228
|
+
isResync = true;
|
|
226
229
|
}
|
|
227
230
|
catch {
|
|
228
|
-
// Good
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const { execSync } = await import("child_process");
|
|
251
|
-
execSync("git init", { cwd: storePath, stdio: "pipe" });
|
|
252
|
-
// Ensure git has a user identity for the initial commit
|
|
231
|
+
// Good — fresh init
|
|
232
|
+
}
|
|
233
|
+
if (!isResync) {
|
|
234
|
+
await fs.mkdir(storePath, { recursive: true });
|
|
235
|
+
await fs.mkdir(path.join(storePath, ".config"), { recursive: true });
|
|
236
|
+
const defaultRegistry = {
|
|
237
|
+
domain: [
|
|
238
|
+
"architecture", "api", "auth", "database", "devops",
|
|
239
|
+
"frontend", "backend", "testing", "security", "performance",
|
|
240
|
+
],
|
|
241
|
+
type: [
|
|
242
|
+
"decision", "concept", "convention", "requirement",
|
|
243
|
+
"observation", "fact", "question",
|
|
244
|
+
],
|
|
245
|
+
concern: ["dx", "scalability", "maintainability", "reliability"],
|
|
246
|
+
status_tag: ["draft", "stable", "deprecated", "experimental"],
|
|
247
|
+
};
|
|
248
|
+
await fs.writeFile(path.join(storePath, ".config", "tags.json"), JSON.stringify(defaultRegistry, null, 2), "utf-8");
|
|
249
|
+
// Write default gnosys.json config (LLM settings)
|
|
250
|
+
await fs.writeFile(path.join(storePath, ".config", "gnosys-config.json"), generateConfigTemplate() + "\n", "utf-8");
|
|
251
|
+
const changelog = `# Gnosys Changelog\n\n## ${new Date().toISOString().split("T")[0]}\n\n- Store initialized\n`;
|
|
252
|
+
await fs.writeFile(path.join(storePath, "CHANGELOG.md"), changelog, "utf-8");
|
|
253
253
|
try {
|
|
254
|
-
|
|
254
|
+
const { execSync } = await import("child_process");
|
|
255
|
+
execSync("git init", { cwd: storePath, stdio: "pipe" });
|
|
256
|
+
try {
|
|
257
|
+
execSync("git config user.name", { cwd: storePath, stdio: "pipe" });
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
execSync('git config user.name "Gnosys"', { cwd: storePath, stdio: "pipe" });
|
|
261
|
+
execSync('git config user.email "gnosys@local"', { cwd: storePath, stdio: "pipe" });
|
|
262
|
+
}
|
|
263
|
+
execSync("git add -A && git add -f .config/", { cwd: storePath, stdio: "pipe" });
|
|
264
|
+
execSync('git commit -m "Initialize Gnosys store"', {
|
|
265
|
+
cwd: storePath,
|
|
266
|
+
stdio: "pipe",
|
|
267
|
+
});
|
|
255
268
|
}
|
|
256
269
|
catch {
|
|
257
|
-
|
|
258
|
-
execSync('git config user.email "gnosys@local"', { cwd: storePath, stdio: "pipe" });
|
|
270
|
+
// Git not available
|
|
259
271
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
272
|
+
}
|
|
273
|
+
// v3.0: Create/update project identity and register in central DB
|
|
274
|
+
let centralDb = null;
|
|
275
|
+
try {
|
|
276
|
+
centralDb = GnosysDB.openCentral();
|
|
277
|
+
if (!centralDb.isAvailable())
|
|
278
|
+
centralDb = null;
|
|
265
279
|
}
|
|
266
280
|
catch {
|
|
267
|
-
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
281
|
+
centralDb = null;
|
|
282
|
+
}
|
|
283
|
+
const identity = await createProjectIdentity(targetDir, {
|
|
284
|
+
projectName: opts.name,
|
|
285
|
+
centralDb: centralDb || undefined,
|
|
286
|
+
});
|
|
287
|
+
if (centralDb)
|
|
288
|
+
centralDb.close();
|
|
289
|
+
const action = isResync ? "re-synced" : "initialized";
|
|
290
|
+
console.log(`Gnosys store ${action} at ${storePath}`);
|
|
291
|
+
console.log(`\nProject Identity:`);
|
|
292
|
+
console.log(` ID: ${identity.projectId}`);
|
|
293
|
+
console.log(` Name: ${identity.projectName}`);
|
|
294
|
+
console.log(` Directory: ${identity.workingDirectory}`);
|
|
295
|
+
console.log(` Agent: ${identity.agentRulesTarget || "none detected"}`);
|
|
296
|
+
console.log(` Central DB: ${centralDb ? "registered ✓" : "not available"}`);
|
|
297
|
+
if (!isResync) {
|
|
298
|
+
console.log(`\nCreated:`);
|
|
299
|
+
console.log(` gnosys.json (project identity)`);
|
|
300
|
+
console.log(` .config/ (internal config)`);
|
|
301
|
+
console.log(` tags.json (tag registry)`);
|
|
302
|
+
console.log(` CHANGELOG.md`);
|
|
303
|
+
console.log(` git repo`);
|
|
304
|
+
}
|
|
276
305
|
console.log(`\nStart adding memories with: gnosys add "your knowledge here"`);
|
|
277
306
|
});
|
|
278
307
|
// ─── gnosys stale ───────────────────────────────────────────────────────
|
|
@@ -1556,33 +1585,7 @@ program
|
|
|
1556
1585
|
console.log(` → ${rp}`);
|
|
1557
1586
|
}
|
|
1558
1587
|
});
|
|
1559
|
-
//
|
|
1560
|
-
program
|
|
1561
|
-
.command("migrate")
|
|
1562
|
-
.description("Migrate v1.x data (Markdown + archive.db) into unified gnosys.db (v2.0)")
|
|
1563
|
-
.option("--verbose", "Show detailed progress")
|
|
1564
|
-
.action(async (opts) => {
|
|
1565
|
-
const resolver = await getResolver();
|
|
1566
|
-
const stores = resolver.getStores();
|
|
1567
|
-
if (stores.length === 0) {
|
|
1568
|
-
console.error("No stores found. Run gnosys init first.");
|
|
1569
|
-
process.exit(1);
|
|
1570
|
-
}
|
|
1571
|
-
const storePath = stores[0].path;
|
|
1572
|
-
// Check if already migrated
|
|
1573
|
-
const db = new GnosysDB(storePath);
|
|
1574
|
-
if (db.isMigrated()) {
|
|
1575
|
-
const counts = db.getMemoryCount();
|
|
1576
|
-
console.log(`Already migrated. gnosys.db has ${counts.active} active + ${counts.archived} archived memories.`);
|
|
1577
|
-
console.log("To re-migrate, delete gnosys.db and run this command again.");
|
|
1578
|
-
db.close();
|
|
1579
|
-
return;
|
|
1580
|
-
}
|
|
1581
|
-
db.close();
|
|
1582
|
-
console.log("Migrating v1.x data → gnosys.db...\n");
|
|
1583
|
-
const stats = await migrate(storePath, { verbose: opts.verbose });
|
|
1584
|
-
console.log(formatMigrationReport(stats));
|
|
1585
|
-
});
|
|
1588
|
+
// NOTE: gnosys migrate is defined below (near the end) with --to-central support
|
|
1586
1589
|
// ─── gnosys doctor ──────────────────────────────────────────────────────
|
|
1587
1590
|
program
|
|
1588
1591
|
.command("doctor")
|
|
@@ -1981,5 +1984,180 @@ program
|
|
|
1981
1984
|
console.log(formatAuditTimeline(entries));
|
|
1982
1985
|
}
|
|
1983
1986
|
});
|
|
1987
|
+
// ─── gnosys backup ──────────────────────────────────────────────────────
|
|
1988
|
+
program
|
|
1989
|
+
.command("backup")
|
|
1990
|
+
.description("Create a backup of the central Gnosys database")
|
|
1991
|
+
.option("-o, --output <dir>", "Backup output directory (default: ~/.gnosys/)")
|
|
1992
|
+
.action(async (opts) => {
|
|
1993
|
+
let centralDb = null;
|
|
1994
|
+
try {
|
|
1995
|
+
centralDb = GnosysDB.openCentral();
|
|
1996
|
+
if (!centralDb.isAvailable()) {
|
|
1997
|
+
console.error("Central DB not available (better-sqlite3 missing).");
|
|
1998
|
+
process.exit(1);
|
|
1999
|
+
}
|
|
2000
|
+
const backupPath = centralDb.backup(opts.output);
|
|
2001
|
+
console.log(`Backup created: ${backupPath}`);
|
|
2002
|
+
const counts = centralDb.getMemoryCount();
|
|
2003
|
+
console.log(` Memories: ${counts.total} (${counts.active} active, ${counts.archived} archived)`);
|
|
2004
|
+
console.log(` Projects: ${centralDb.getAllProjects().length}`);
|
|
2005
|
+
}
|
|
2006
|
+
catch (err) {
|
|
2007
|
+
console.error(`Backup failed: ${err instanceof Error ? err.message : err}`);
|
|
2008
|
+
process.exit(1);
|
|
2009
|
+
}
|
|
2010
|
+
finally {
|
|
2011
|
+
centralDb?.close();
|
|
2012
|
+
}
|
|
2013
|
+
});
|
|
2014
|
+
// ─── gnosys restore ─────────────────────────────────────────────────────
|
|
2015
|
+
program
|
|
2016
|
+
.command("restore <backupFile>")
|
|
2017
|
+
.description("Restore the central Gnosys database from a backup")
|
|
2018
|
+
.action(async (backupFile) => {
|
|
2019
|
+
const resolved = path.resolve(backupFile);
|
|
2020
|
+
try {
|
|
2021
|
+
const db = GnosysDB.restore(resolved);
|
|
2022
|
+
const counts = db.getMemoryCount();
|
|
2023
|
+
console.log(`Database restored from ${resolved}`);
|
|
2024
|
+
console.log(` Memories: ${counts.total} (${counts.active} active, ${counts.archived} archived)`);
|
|
2025
|
+
console.log(` Projects: ${db.getAllProjects().length}`);
|
|
2026
|
+
db.close();
|
|
2027
|
+
}
|
|
2028
|
+
catch (err) {
|
|
2029
|
+
console.error(`Restore failed: ${err instanceof Error ? err.message : err}`);
|
|
2030
|
+
process.exit(1);
|
|
2031
|
+
}
|
|
2032
|
+
});
|
|
2033
|
+
// ─── gnosys migrate --to-central ────────────────────────────────────────
|
|
2034
|
+
program
|
|
2035
|
+
.command("migrate")
|
|
2036
|
+
.description("Migrate data. Use --to-central to move per-project stores into the central DB.")
|
|
2037
|
+
.option("--to-central", "Migrate all discovered per-project stores into ~/.gnosys/gnosys.db")
|
|
2038
|
+
.option("-v, --verbose", "Verbose output")
|
|
2039
|
+
.action(async (opts) => {
|
|
2040
|
+
if (!opts.toCentral) {
|
|
2041
|
+
// Legacy v1→v2 migration (existing behavior)
|
|
2042
|
+
const resolver = await getResolver();
|
|
2043
|
+
const writeTarget = resolver.getWriteTarget();
|
|
2044
|
+
if (!writeTarget) {
|
|
2045
|
+
console.error("No writable store found. Run 'gnosys init' first.");
|
|
2046
|
+
process.exit(1);
|
|
2047
|
+
}
|
|
2048
|
+
const stats = await migrate(writeTarget.store.getStorePath(), { verbose: opts.verbose });
|
|
2049
|
+
console.log(formatMigrationReport(stats));
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
// v3.0: Migrate per-project stores into central DB
|
|
2053
|
+
console.log("Migrating per-project stores to central DB (~/.gnosys/gnosys.db)...\n");
|
|
2054
|
+
let centralDb = null;
|
|
2055
|
+
try {
|
|
2056
|
+
centralDb = GnosysDB.openCentral();
|
|
2057
|
+
if (!centralDb.isAvailable()) {
|
|
2058
|
+
console.error("Central DB not available (better-sqlite3 missing).");
|
|
2059
|
+
process.exit(1);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
catch (err) {
|
|
2063
|
+
console.error(`Cannot open central DB: ${err instanceof Error ? err.message : err}`);
|
|
2064
|
+
process.exit(1);
|
|
2065
|
+
}
|
|
2066
|
+
// Discover all registered project stores
|
|
2067
|
+
const resolver = await getResolver();
|
|
2068
|
+
const detectedStores = await resolver.detectAllStores();
|
|
2069
|
+
const projectDirs = detectedStores
|
|
2070
|
+
.filter(s => s.hasGnosys)
|
|
2071
|
+
.map(s => s.path);
|
|
2072
|
+
if (projectDirs.length === 0) {
|
|
2073
|
+
console.log("No per-project stores found to migrate.");
|
|
2074
|
+
centralDb.close();
|
|
2075
|
+
return;
|
|
2076
|
+
}
|
|
2077
|
+
console.log(`Found ${projectDirs.length} project store(s) to migrate:\n`);
|
|
2078
|
+
let totalMemories = 0;
|
|
2079
|
+
let totalProjects = 0;
|
|
2080
|
+
for (const projectDir of projectDirs) {
|
|
2081
|
+
const storePath = path.join(projectDir, ".gnosys");
|
|
2082
|
+
const log = opts.verbose ? console.log : () => { };
|
|
2083
|
+
try {
|
|
2084
|
+
// Create project identity if it doesn't exist
|
|
2085
|
+
const identity = await createProjectIdentity(projectDir, {
|
|
2086
|
+
centralDb: centralDb,
|
|
2087
|
+
});
|
|
2088
|
+
log(` [${identity.projectName}] ID: ${identity.projectId}`);
|
|
2089
|
+
// Open per-project DB and import memories
|
|
2090
|
+
const projectDb = new GnosysDB(storePath);
|
|
2091
|
+
if (!projectDb.isAvailable() || !projectDb.isMigrated()) {
|
|
2092
|
+
log(` [${identity.projectName}] No migrated gnosys.db — skipping`);
|
|
2093
|
+
continue;
|
|
2094
|
+
}
|
|
2095
|
+
const memories = projectDb.getAllMemories();
|
|
2096
|
+
let count = 0;
|
|
2097
|
+
centralDb.transaction(() => {
|
|
2098
|
+
for (const mem of memories) {
|
|
2099
|
+
centralDb.insertMemory({
|
|
2100
|
+
...mem,
|
|
2101
|
+
project_id: identity.projectId,
|
|
2102
|
+
scope: "project",
|
|
2103
|
+
});
|
|
2104
|
+
count++;
|
|
2105
|
+
}
|
|
2106
|
+
});
|
|
2107
|
+
projectDb.close();
|
|
2108
|
+
totalMemories += count;
|
|
2109
|
+
totalProjects++;
|
|
2110
|
+
console.log(` ✓ ${identity.projectName}: ${count} memories migrated`);
|
|
2111
|
+
}
|
|
2112
|
+
catch (err) {
|
|
2113
|
+
console.error(` ✗ ${projectDir}: ${err instanceof Error ? err.message : err}`);
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
centralDb.close();
|
|
2117
|
+
console.log(`\n╔════════════════════════════════════════╗`);
|
|
2118
|
+
console.log(`║ Central Migration Complete ║`);
|
|
2119
|
+
console.log(`╚════════════════════════════════════════╝`);
|
|
2120
|
+
console.log(` Projects migrated: ${totalProjects}`);
|
|
2121
|
+
console.log(` Memories imported: ${totalMemories}`);
|
|
2122
|
+
console.log(`\n Per-project gnosys.db files are untouched.`);
|
|
2123
|
+
console.log(` Central DB: ${GnosysDB.getCentralDbPath()}`);
|
|
2124
|
+
});
|
|
2125
|
+
// ─── gnosys projects ────────────────────────────────────────────────────
|
|
2126
|
+
program
|
|
2127
|
+
.command("projects")
|
|
2128
|
+
.description("List all registered projects in the central DB")
|
|
2129
|
+
.action(async () => {
|
|
2130
|
+
let centralDb = null;
|
|
2131
|
+
try {
|
|
2132
|
+
centralDb = GnosysDB.openCentral();
|
|
2133
|
+
if (!centralDb.isAvailable()) {
|
|
2134
|
+
console.error("Central DB not available (better-sqlite3 missing).");
|
|
2135
|
+
process.exit(1);
|
|
2136
|
+
}
|
|
2137
|
+
const projects = centralDb.getAllProjects();
|
|
2138
|
+
if (projects.length === 0) {
|
|
2139
|
+
console.log("No projects registered. Run 'gnosys init' in a project directory.");
|
|
2140
|
+
centralDb.close();
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
console.log(`${projects.length} registered project(s):\n`);
|
|
2144
|
+
for (const p of projects) {
|
|
2145
|
+
const memCount = centralDb.getMemoriesByProject(p.id).length;
|
|
2146
|
+
console.log(` ${p.name}`);
|
|
2147
|
+
console.log(` ID: ${p.id}`);
|
|
2148
|
+
console.log(` Directory: ${p.working_directory}`);
|
|
2149
|
+
console.log(` Memories: ${memCount}`);
|
|
2150
|
+
console.log(` Created: ${p.created}`);
|
|
2151
|
+
console.log();
|
|
2152
|
+
}
|
|
2153
|
+
}
|
|
2154
|
+
catch (err) {
|
|
2155
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
2156
|
+
process.exit(1);
|
|
2157
|
+
}
|
|
2158
|
+
finally {
|
|
2159
|
+
centralDb?.close();
|
|
2160
|
+
}
|
|
2161
|
+
});
|
|
1984
2162
|
program.parse();
|
|
1985
2163
|
//# sourceMappingURL=cli.js.map
|