@zabaca/lattice 1.0.22 → 1.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/main.js +398 -103
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -406,95 +406,172 @@ function ensureLatticeHome() {
|
|
|
406
406
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
407
407
|
var __dirname2 = path.dirname(__filename2);
|
|
408
408
|
var COMMANDS = ["research.md", "graph-sync.md", "entity-extract.md"];
|
|
409
|
+
var SITE_TEMPLATE_FILES = [
|
|
410
|
+
"astro.config.ts",
|
|
411
|
+
"package.json",
|
|
412
|
+
"tsconfig.json",
|
|
413
|
+
"src/content.config.ts",
|
|
414
|
+
"src/collections/authors.ts",
|
|
415
|
+
"src/collections/documents.ts",
|
|
416
|
+
"src/collections/tags.ts"
|
|
417
|
+
];
|
|
409
418
|
|
|
410
419
|
class InitCommand extends CommandRunner2 {
|
|
411
420
|
async run(_inputs, _options) {
|
|
412
421
|
try {
|
|
413
422
|
ensureLatticeHome();
|
|
423
|
+
const latticeHome = getLatticeHome();
|
|
414
424
|
const envPath = getEnvPath();
|
|
415
425
|
if (!existsSync3(envPath)) {
|
|
416
426
|
writeFileSync(envPath, `# Lattice Configuration
|
|
417
427
|
# Get your API key from: https://www.voyageai.com/
|
|
418
|
-
|
|
419
428
|
VOYAGE_API_KEY=
|
|
429
|
+
|
|
430
|
+
# Site Configuration (for lattice site command)
|
|
431
|
+
SPACESHIP_AUTHOR="Lattice"
|
|
432
|
+
SPACESHIP_BASE="/"
|
|
433
|
+
SPACESHIP_SITE="https://example.com"
|
|
434
|
+
SPACESHIP_TITLE="Lattice"
|
|
435
|
+
SPACESHIP_DESCRIPTION="Research Knowledge Base"
|
|
436
|
+
OBSIDIAN_VAULT_DIR=docs
|
|
420
437
|
`);
|
|
438
|
+
} else {
|
|
439
|
+
const envContent = await fs.readFile(envPath, "utf-8");
|
|
440
|
+
if (!envContent.includes("SPACESHIP_")) {
|
|
441
|
+
await fs.appendFile(envPath, `
|
|
442
|
+
# Site Configuration (for lattice site command)
|
|
443
|
+
SPACESHIP_AUTHOR="Lattice"
|
|
444
|
+
SPACESHIP_BASE="/"
|
|
445
|
+
SPACESHIP_SITE="https://example.com"
|
|
446
|
+
SPACESHIP_TITLE="Lattice"
|
|
447
|
+
SPACESHIP_DESCRIPTION="Research Knowledge Base"
|
|
448
|
+
OBSIDIAN_VAULT_DIR=docs
|
|
449
|
+
`);
|
|
450
|
+
console.log("\u2705 Added site configuration to .env");
|
|
451
|
+
}
|
|
421
452
|
}
|
|
422
|
-
console.log(`\u2705 Lattice home directory: ${
|
|
453
|
+
console.log(`\u2705 Lattice home directory: ${latticeHome}`);
|
|
423
454
|
console.log(` Documents: ${getDocsPath()}`);
|
|
424
455
|
console.log(` Config: ${envPath}`);
|
|
425
456
|
console.log();
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
try {
|
|
429
|
-
await fs.access(commandsSourceDir);
|
|
430
|
-
} catch {
|
|
431
|
-
commandsSourceDir = path.resolve(__dirname2, "..", "..", "commands");
|
|
432
|
-
}
|
|
433
|
-
try {
|
|
434
|
-
await fs.access(commandsSourceDir);
|
|
435
|
-
} catch {
|
|
436
|
-
console.error("Error: Commands source directory not found at", commandsSourceDir);
|
|
437
|
-
console.error("This may indicate a corrupted installation. Try reinstalling @zabaca/lattice.");
|
|
438
|
-
process.exit(1);
|
|
439
|
-
}
|
|
440
|
-
await fs.mkdir(targetDir, { recursive: true });
|
|
441
|
-
let copied = 0;
|
|
442
|
-
let skipped = 0;
|
|
443
|
-
const installed = [];
|
|
444
|
-
for (const file of COMMANDS) {
|
|
445
|
-
const sourcePath = path.join(commandsSourceDir, file);
|
|
446
|
-
const targetPath = path.join(targetDir, file);
|
|
447
|
-
try {
|
|
448
|
-
await fs.access(sourcePath);
|
|
449
|
-
try {
|
|
450
|
-
await fs.access(targetPath);
|
|
451
|
-
const sourceContent = await fs.readFile(sourcePath, "utf-8");
|
|
452
|
-
const targetContent = await fs.readFile(targetPath, "utf-8");
|
|
453
|
-
if (sourceContent === targetContent) {
|
|
454
|
-
skipped++;
|
|
455
|
-
continue;
|
|
456
|
-
}
|
|
457
|
-
} catch {}
|
|
458
|
-
await fs.copyFile(sourcePath, targetPath);
|
|
459
|
-
installed.push(file);
|
|
460
|
-
copied++;
|
|
461
|
-
} catch (err) {
|
|
462
|
-
console.error(`Warning: Could not copy ${file}:`, err instanceof Error ? err.message : String(err));
|
|
463
|
-
}
|
|
464
|
-
}
|
|
457
|
+
await this.setupSiteTemplate(latticeHome);
|
|
458
|
+
await this.installClaudeCommands();
|
|
465
459
|
console.log();
|
|
466
|
-
console.log(
|
|
460
|
+
console.log("Available commands:");
|
|
461
|
+
console.log(" lattice site - Build and run the documentation site");
|
|
462
|
+
console.log(" lattice sync - Sync documents to knowledge graph");
|
|
463
|
+
console.log(" lattice status - Show documents needing sync");
|
|
464
|
+
console.log(" lattice search - Semantic search across documents");
|
|
467
465
|
console.log();
|
|
468
|
-
|
|
469
|
-
console.log(`Installed ${copied} command(s):`);
|
|
470
|
-
installed.forEach((f) => {
|
|
471
|
-
const name = f.replace(".md", "");
|
|
472
|
-
console.log(` - /${name}`);
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
if (skipped > 0) {
|
|
476
|
-
console.log(`Skipped ${skipped} unchanged command(s)`);
|
|
477
|
-
}
|
|
478
|
-
console.log();
|
|
479
|
-
console.log("Available commands in Claude Code:");
|
|
466
|
+
console.log("Claude Code slash commands:");
|
|
480
467
|
console.log(" /research <topic> - AI-assisted research workflow");
|
|
481
468
|
console.log(" /graph-sync - Extract entities and sync to graph");
|
|
482
|
-
console.log(" /entity-extract - Extract entities from a
|
|
483
|
-
console.log();
|
|
484
|
-
console.log(`\u26A0\uFE0F Add your Voyage API key to: ${getEnvPath()}`);
|
|
469
|
+
console.log(" /entity-extract - Extract entities from a document");
|
|
485
470
|
console.log();
|
|
471
|
+
if (!(await fs.readFile(envPath, "utf-8")).includes("pa-")) {
|
|
472
|
+
console.log(`\u26A0\uFE0F Add your Voyage API key to: ${envPath}`);
|
|
473
|
+
console.log();
|
|
474
|
+
}
|
|
486
475
|
process.exit(0);
|
|
487
476
|
} catch (error) {
|
|
488
477
|
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
489
478
|
process.exit(1);
|
|
490
479
|
}
|
|
491
480
|
}
|
|
481
|
+
async setupSiteTemplate(latticeHome) {
|
|
482
|
+
let templateDir = path.resolve(__dirname2, "..", "site-template");
|
|
483
|
+
try {
|
|
484
|
+
await fs.access(templateDir);
|
|
485
|
+
} catch {
|
|
486
|
+
templateDir = path.resolve(__dirname2, "..", "..", "site-template");
|
|
487
|
+
}
|
|
488
|
+
try {
|
|
489
|
+
await fs.access(templateDir);
|
|
490
|
+
} catch {
|
|
491
|
+
console.log("\u26A0\uFE0F Site template not found - skipping site setup");
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
await fs.mkdir(path.join(latticeHome, "src", "collections"), {
|
|
495
|
+
recursive: true
|
|
496
|
+
});
|
|
497
|
+
let copied = 0;
|
|
498
|
+
let skipped = 0;
|
|
499
|
+
for (const file of SITE_TEMPLATE_FILES) {
|
|
500
|
+
const sourcePath = path.join(templateDir, file);
|
|
501
|
+
const targetPath = path.join(latticeHome, file);
|
|
502
|
+
try {
|
|
503
|
+
await fs.access(sourcePath);
|
|
504
|
+
try {
|
|
505
|
+
await fs.access(targetPath);
|
|
506
|
+
const sourceContent = await fs.readFile(sourcePath, "utf-8");
|
|
507
|
+
const targetContent = await fs.readFile(targetPath, "utf-8");
|
|
508
|
+
if (sourceContent === targetContent) {
|
|
509
|
+
skipped++;
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
} catch {}
|
|
513
|
+
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
514
|
+
await fs.copyFile(sourcePath, targetPath);
|
|
515
|
+
copied++;
|
|
516
|
+
} catch (err) {}
|
|
517
|
+
}
|
|
518
|
+
if (copied > 0) {
|
|
519
|
+
console.log(`\u2705 Site template: ${copied} file(s) installed`);
|
|
520
|
+
}
|
|
521
|
+
if (skipped > 0) {
|
|
522
|
+
console.log(` Site template: ${skipped} file(s) unchanged`);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
async installClaudeCommands() {
|
|
526
|
+
const targetDir = path.join(homedir2(), ".claude", "commands");
|
|
527
|
+
let commandsSourceDir = path.resolve(__dirname2, "..", "commands");
|
|
528
|
+
try {
|
|
529
|
+
await fs.access(commandsSourceDir);
|
|
530
|
+
} catch {
|
|
531
|
+
commandsSourceDir = path.resolve(__dirname2, "..", "..", "commands");
|
|
532
|
+
}
|
|
533
|
+
try {
|
|
534
|
+
await fs.access(commandsSourceDir);
|
|
535
|
+
} catch {
|
|
536
|
+
console.log("\u26A0\uFE0F Claude commands not found - skipping");
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
540
|
+
let copied = 0;
|
|
541
|
+
let skipped = 0;
|
|
542
|
+
const installed = [];
|
|
543
|
+
for (const file of COMMANDS) {
|
|
544
|
+
const sourcePath = path.join(commandsSourceDir, file);
|
|
545
|
+
const targetPath = path.join(targetDir, file);
|
|
546
|
+
try {
|
|
547
|
+
await fs.access(sourcePath);
|
|
548
|
+
try {
|
|
549
|
+
await fs.access(targetPath);
|
|
550
|
+
const sourceContent = await fs.readFile(sourcePath, "utf-8");
|
|
551
|
+
const targetContent = await fs.readFile(targetPath, "utf-8");
|
|
552
|
+
if (sourceContent === targetContent) {
|
|
553
|
+
skipped++;
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
} catch {}
|
|
557
|
+
await fs.copyFile(sourcePath, targetPath);
|
|
558
|
+
installed.push(file);
|
|
559
|
+
copied++;
|
|
560
|
+
} catch (err) {}
|
|
561
|
+
}
|
|
562
|
+
if (copied > 0) {
|
|
563
|
+
console.log(`\u2705 Claude commands: ${copied} installed to ${targetDir}`);
|
|
564
|
+
}
|
|
565
|
+
if (skipped > 0) {
|
|
566
|
+
console.log(` Claude commands: ${skipped} unchanged`);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
492
569
|
}
|
|
493
570
|
InitCommand = __legacyDecorateClassTS([
|
|
494
571
|
Injectable3(),
|
|
495
572
|
Command2({
|
|
496
573
|
name: "init",
|
|
497
|
-
description: "
|
|
574
|
+
description: "Initialize Lattice with Claude Code commands and site generator"
|
|
498
575
|
})
|
|
499
576
|
], InitCommand);
|
|
500
577
|
// src/commands/migrate.command.ts
|
|
@@ -873,8 +950,7 @@ class GraphService {
|
|
|
873
950
|
const allResults = [];
|
|
874
951
|
const conn = await this.ensureConnected();
|
|
875
952
|
const vectorStr = `[${queryVector.join(", ")}]`;
|
|
876
|
-
|
|
877
|
-
const reader = await conn.runAndReadAll(`
|
|
953
|
+
const sql = `
|
|
878
954
|
SELECT
|
|
879
955
|
name,
|
|
880
956
|
label,
|
|
@@ -883,10 +959,11 @@ class GraphService {
|
|
|
883
959
|
array_cosine_similarity(embedding, ${vectorStr}::FLOAT[${this.embeddingDimensions}]) as similarity
|
|
884
960
|
FROM nodes
|
|
885
961
|
WHERE embedding IS NOT NULL
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
962
|
+
`;
|
|
963
|
+
try {
|
|
964
|
+
const reader = await conn.runAndReadAll(sql);
|
|
965
|
+
const rows = reader.getRows();
|
|
966
|
+
for (const row of rows) {
|
|
890
967
|
const [name, label, title, description, similarity] = row;
|
|
891
968
|
allResults.push({
|
|
892
969
|
name,
|
|
@@ -3120,10 +3197,214 @@ SqlCommand = __legacyDecorateClassTS([
|
|
|
3120
3197
|
typeof GraphService === "undefined" ? Object : GraphService
|
|
3121
3198
|
])
|
|
3122
3199
|
], SqlCommand);
|
|
3123
|
-
// src/commands/
|
|
3200
|
+
// src/commands/site.command.ts
|
|
3201
|
+
import { spawn } from "child_process";
|
|
3202
|
+
import { existsSync as existsSync6, readFileSync as readFileSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
3203
|
+
import * as path2 from "path";
|
|
3124
3204
|
import { Injectable as Injectable16 } from "@nestjs/common";
|
|
3125
3205
|
import { Command as Command6, CommandRunner as CommandRunner6, Option as Option4 } from "nest-commander";
|
|
3126
|
-
class
|
|
3206
|
+
class SiteCommand extends CommandRunner6 {
|
|
3207
|
+
getPidFile() {
|
|
3208
|
+
return path2.join(getLatticeHome(), "site.pid");
|
|
3209
|
+
}
|
|
3210
|
+
async run(_inputs, options) {
|
|
3211
|
+
if (options.kill) {
|
|
3212
|
+
this.killSiteProcess();
|
|
3213
|
+
process.exit(0);
|
|
3214
|
+
}
|
|
3215
|
+
const latticeHome = getLatticeHome();
|
|
3216
|
+
const packageJsonPath = path2.join(latticeHome, "package.json");
|
|
3217
|
+
const nodeModulesPath = path2.join(latticeHome, "node_modules");
|
|
3218
|
+
if (!existsSync6(packageJsonPath)) {
|
|
3219
|
+
console.error("Error: Site not initialized. Run 'lattice init' first.");
|
|
3220
|
+
process.exit(1);
|
|
3221
|
+
}
|
|
3222
|
+
if (this.isRunning()) {
|
|
3223
|
+
console.error("Error: A Lattice site is already running.");
|
|
3224
|
+
console.error("Use 'lattice site --kill' to stop it first.");
|
|
3225
|
+
process.exit(1);
|
|
3226
|
+
}
|
|
3227
|
+
if (!existsSync6(nodeModulesPath)) {
|
|
3228
|
+
console.log("\uD83D\uDCE6 Installing dependencies...");
|
|
3229
|
+
await this.runCommand("bun", ["install"], latticeHome);
|
|
3230
|
+
console.log();
|
|
3231
|
+
}
|
|
3232
|
+
if (options.build) {
|
|
3233
|
+
console.log("\uD83D\uDD28 Building site...");
|
|
3234
|
+
await this.runCommand("bun", ["run", "build"], latticeHome);
|
|
3235
|
+
console.log(`
|
|
3236
|
+
\u2705 Build complete! Output in: ~/.lattice/dist/`);
|
|
3237
|
+
process.exit(0);
|
|
3238
|
+
}
|
|
3239
|
+
if (options.dev) {
|
|
3240
|
+
console.log("\uD83D\uDE80 Starting dev server...");
|
|
3241
|
+
const port2 = options.port || "4321";
|
|
3242
|
+
await this.runServerCommand("bun", ["run", "dev", "--", "--port", port2], latticeHome);
|
|
3243
|
+
process.exit(0);
|
|
3244
|
+
}
|
|
3245
|
+
console.log("\uD83D\uDD28 Building site with search index...");
|
|
3246
|
+
await this.runCommand("bun", ["run", "build"], latticeHome);
|
|
3247
|
+
console.log(`
|
|
3248
|
+
\uD83D\uDE80 Starting preview server...`);
|
|
3249
|
+
const port = options.port || "4321";
|
|
3250
|
+
await this.runServerCommand("bun", ["run", "preview", "--", "--port", port], latticeHome);
|
|
3251
|
+
}
|
|
3252
|
+
runCommand(cmd, args, cwd) {
|
|
3253
|
+
return new Promise((resolve4, reject) => {
|
|
3254
|
+
const child = spawn(cmd, args, {
|
|
3255
|
+
cwd,
|
|
3256
|
+
stdio: "pipe",
|
|
3257
|
+
env: { ...process.env, FORCE_COLOR: "1" }
|
|
3258
|
+
});
|
|
3259
|
+
child.stdout?.on("data", (data) => {
|
|
3260
|
+
process.stdout.write(data);
|
|
3261
|
+
});
|
|
3262
|
+
child.stderr?.on("data", (data) => {
|
|
3263
|
+
process.stderr.write(data);
|
|
3264
|
+
});
|
|
3265
|
+
child.on("close", (code) => {
|
|
3266
|
+
if (code === 0) {
|
|
3267
|
+
resolve4();
|
|
3268
|
+
} else {
|
|
3269
|
+
reject(new Error(`Command failed with code ${code}`));
|
|
3270
|
+
}
|
|
3271
|
+
});
|
|
3272
|
+
child.on("error", (err) => {
|
|
3273
|
+
reject(err);
|
|
3274
|
+
});
|
|
3275
|
+
});
|
|
3276
|
+
}
|
|
3277
|
+
runServerCommand(cmd, args, cwd) {
|
|
3278
|
+
return new Promise((resolve4, reject) => {
|
|
3279
|
+
const child = spawn(cmd, args, {
|
|
3280
|
+
cwd,
|
|
3281
|
+
stdio: "inherit",
|
|
3282
|
+
env: { ...process.env, FORCE_COLOR: "1" }
|
|
3283
|
+
});
|
|
3284
|
+
if (child.pid) {
|
|
3285
|
+
writeFileSync2(this.getPidFile(), String(child.pid));
|
|
3286
|
+
}
|
|
3287
|
+
const cleanup = () => {
|
|
3288
|
+
try {
|
|
3289
|
+
unlinkSync(this.getPidFile());
|
|
3290
|
+
} catch {}
|
|
3291
|
+
};
|
|
3292
|
+
child.on("close", (code) => {
|
|
3293
|
+
cleanup();
|
|
3294
|
+
if (code === 0) {
|
|
3295
|
+
resolve4();
|
|
3296
|
+
} else {
|
|
3297
|
+
reject(new Error(`Command failed with code ${code}`));
|
|
3298
|
+
}
|
|
3299
|
+
});
|
|
3300
|
+
child.on("error", (err) => {
|
|
3301
|
+
cleanup();
|
|
3302
|
+
reject(err);
|
|
3303
|
+
});
|
|
3304
|
+
process.on("SIGINT", cleanup);
|
|
3305
|
+
process.on("SIGTERM", cleanup);
|
|
3306
|
+
});
|
|
3307
|
+
}
|
|
3308
|
+
isRunning() {
|
|
3309
|
+
const pidFile = this.getPidFile();
|
|
3310
|
+
if (!existsSync6(pidFile)) {
|
|
3311
|
+
return false;
|
|
3312
|
+
}
|
|
3313
|
+
try {
|
|
3314
|
+
const pid = parseInt(readFileSync2(pidFile, "utf-8").trim(), 10);
|
|
3315
|
+
process.kill(pid, 0);
|
|
3316
|
+
return true;
|
|
3317
|
+
} catch {
|
|
3318
|
+
try {
|
|
3319
|
+
unlinkSync(pidFile);
|
|
3320
|
+
} catch {}
|
|
3321
|
+
return false;
|
|
3322
|
+
}
|
|
3323
|
+
}
|
|
3324
|
+
killSiteProcess() {
|
|
3325
|
+
const pidFile = this.getPidFile();
|
|
3326
|
+
if (!existsSync6(pidFile)) {
|
|
3327
|
+
console.log("No Lattice site process running");
|
|
3328
|
+
return;
|
|
3329
|
+
}
|
|
3330
|
+
try {
|
|
3331
|
+
const pid = parseInt(readFileSync2(pidFile, "utf-8").trim(), 10);
|
|
3332
|
+
try {
|
|
3333
|
+
process.kill(-pid, "SIGTERM");
|
|
3334
|
+
} catch {
|
|
3335
|
+
process.kill(pid, "SIGTERM");
|
|
3336
|
+
}
|
|
3337
|
+
unlinkSync(pidFile);
|
|
3338
|
+
console.log(`\u2705 Killed Lattice site process (PID: ${pid})`);
|
|
3339
|
+
} catch (err) {
|
|
3340
|
+
try {
|
|
3341
|
+
unlinkSync(pidFile);
|
|
3342
|
+
} catch {}
|
|
3343
|
+
console.log("No Lattice site process running");
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
parseBuild() {
|
|
3347
|
+
return true;
|
|
3348
|
+
}
|
|
3349
|
+
parseDev() {
|
|
3350
|
+
return true;
|
|
3351
|
+
}
|
|
3352
|
+
parsePort(val) {
|
|
3353
|
+
return val;
|
|
3354
|
+
}
|
|
3355
|
+
parseKill() {
|
|
3356
|
+
return true;
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
__legacyDecorateClassTS([
|
|
3360
|
+
Option4({
|
|
3361
|
+
flags: "-b, --build",
|
|
3362
|
+
description: "Build the site without starting the server"
|
|
3363
|
+
}),
|
|
3364
|
+
__legacyMetadataTS("design:type", Function),
|
|
3365
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
3366
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
3367
|
+
], SiteCommand.prototype, "parseBuild", null);
|
|
3368
|
+
__legacyDecorateClassTS([
|
|
3369
|
+
Option4({
|
|
3370
|
+
flags: "-d, --dev",
|
|
3371
|
+
description: "Run in development mode (hot reload, no search)"
|
|
3372
|
+
}),
|
|
3373
|
+
__legacyMetadataTS("design:type", Function),
|
|
3374
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
3375
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
3376
|
+
], SiteCommand.prototype, "parseDev", null);
|
|
3377
|
+
__legacyDecorateClassTS([
|
|
3378
|
+
Option4({
|
|
3379
|
+
flags: "-p, --port <port>",
|
|
3380
|
+
description: "Port to run the server on (default: 4321)"
|
|
3381
|
+
}),
|
|
3382
|
+
__legacyMetadataTS("design:type", Function),
|
|
3383
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
3384
|
+
String
|
|
3385
|
+
]),
|
|
3386
|
+
__legacyMetadataTS("design:returntype", String)
|
|
3387
|
+
], SiteCommand.prototype, "parsePort", null);
|
|
3388
|
+
__legacyDecorateClassTS([
|
|
3389
|
+
Option4({
|
|
3390
|
+
flags: "-k, --kill",
|
|
3391
|
+
description: "Kill the running Lattice site process"
|
|
3392
|
+
}),
|
|
3393
|
+
__legacyMetadataTS("design:type", Function),
|
|
3394
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
3395
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
3396
|
+
], SiteCommand.prototype, "parseKill", null);
|
|
3397
|
+
SiteCommand = __legacyDecorateClassTS([
|
|
3398
|
+
Injectable16(),
|
|
3399
|
+
Command6({
|
|
3400
|
+
name: "site",
|
|
3401
|
+
description: "Build and run the Lattice documentation site"
|
|
3402
|
+
})
|
|
3403
|
+
], SiteCommand);
|
|
3404
|
+
// src/commands/status.command.ts
|
|
3405
|
+
import { Injectable as Injectable17 } from "@nestjs/common";
|
|
3406
|
+
import { Command as Command7, CommandRunner as CommandRunner7, Option as Option5 } from "nest-commander";
|
|
3407
|
+
class StatusCommand extends CommandRunner7 {
|
|
3127
3408
|
syncService;
|
|
3128
3409
|
dbChangeDetector;
|
|
3129
3410
|
constructor(syncService, dbChangeDetector) {
|
|
@@ -3189,7 +3470,7 @@ class StatusCommand extends CommandRunner6 {
|
|
|
3189
3470
|
}
|
|
3190
3471
|
}
|
|
3191
3472
|
__legacyDecorateClassTS([
|
|
3192
|
-
|
|
3473
|
+
Option5({
|
|
3193
3474
|
flags: "-v, --verbose",
|
|
3194
3475
|
description: "Show all documents including unchanged"
|
|
3195
3476
|
}),
|
|
@@ -3198,8 +3479,8 @@ __legacyDecorateClassTS([
|
|
|
3198
3479
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3199
3480
|
], StatusCommand.prototype, "parseVerbose", null);
|
|
3200
3481
|
StatusCommand = __legacyDecorateClassTS([
|
|
3201
|
-
|
|
3202
|
-
|
|
3482
|
+
Injectable17(),
|
|
3483
|
+
Command7({
|
|
3203
3484
|
name: "status",
|
|
3204
3485
|
description: "Show documents that need syncing (new or updated)"
|
|
3205
3486
|
}),
|
|
@@ -3210,12 +3491,12 @@ StatusCommand = __legacyDecorateClassTS([
|
|
|
3210
3491
|
], StatusCommand);
|
|
3211
3492
|
// src/commands/sync.command.ts
|
|
3212
3493
|
import { watch } from "fs";
|
|
3213
|
-
import { join as
|
|
3214
|
-
import { Injectable as
|
|
3215
|
-
import { Command as
|
|
3494
|
+
import { join as join4 } from "path";
|
|
3495
|
+
import { Injectable as Injectable19 } from "@nestjs/common";
|
|
3496
|
+
import { Command as Command8, CommandRunner as CommandRunner8, Option as Option6 } from "nest-commander";
|
|
3216
3497
|
|
|
3217
3498
|
// src/sync/graph-validator.service.ts
|
|
3218
|
-
import { Injectable as
|
|
3499
|
+
import { Injectable as Injectable18, Logger as Logger9 } from "@nestjs/common";
|
|
3219
3500
|
class GraphValidatorService {
|
|
3220
3501
|
graph;
|
|
3221
3502
|
logger = new Logger9(GraphValidatorService.name);
|
|
@@ -3334,15 +3615,15 @@ class GraphValidatorService {
|
|
|
3334
3615
|
});
|
|
3335
3616
|
}
|
|
3336
3617
|
}
|
|
3337
|
-
async validateDocument(
|
|
3618
|
+
async validateDocument(path3) {
|
|
3338
3619
|
const issues = [];
|
|
3339
3620
|
try {
|
|
3340
|
-
const result = await this.graph.query(`SELECT label, name, properties FROM nodes WHERE label = 'Document' AND name = '${this.escape(
|
|
3621
|
+
const result = await this.graph.query(`SELECT label, name, properties FROM nodes WHERE label = 'Document' AND name = '${this.escape(path3)}'`);
|
|
3341
3622
|
if (result.resultSet.length === 0) {
|
|
3342
3623
|
issues.push({
|
|
3343
3624
|
type: "error",
|
|
3344
3625
|
nodeLabel: "Document",
|
|
3345
|
-
nodeName:
|
|
3626
|
+
nodeName: path3,
|
|
3346
3627
|
field: "node",
|
|
3347
3628
|
message: "Document not found in graph",
|
|
3348
3629
|
suggestion: "Run 'lattice sync' to add this document"
|
|
@@ -3352,9 +3633,9 @@ class GraphValidatorService {
|
|
|
3352
3633
|
const row = result.resultSet[0];
|
|
3353
3634
|
const propertiesJson = row[2];
|
|
3354
3635
|
const properties = typeof propertiesJson === "string" ? JSON.parse(propertiesJson) : propertiesJson;
|
|
3355
|
-
this.validateDocumentNode(
|
|
3636
|
+
this.validateDocumentNode(path3, properties, issues);
|
|
3356
3637
|
} catch (error) {
|
|
3357
|
-
this.logger.error(`Failed to validate document ${
|
|
3638
|
+
this.logger.error(`Failed to validate document ${path3}: ${error instanceof Error ? error.message : String(error)}`);
|
|
3358
3639
|
throw error;
|
|
3359
3640
|
}
|
|
3360
3641
|
return issues;
|
|
@@ -3364,35 +3645,45 @@ class GraphValidatorService {
|
|
|
3364
3645
|
}
|
|
3365
3646
|
}
|
|
3366
3647
|
GraphValidatorService = __legacyDecorateClassTS([
|
|
3367
|
-
|
|
3648
|
+
Injectable18(),
|
|
3368
3649
|
__legacyMetadataTS("design:paramtypes", [
|
|
3369
3650
|
typeof GraphService === "undefined" ? Object : GraphService
|
|
3370
3651
|
])
|
|
3371
3652
|
], GraphValidatorService);
|
|
3372
3653
|
|
|
3373
3654
|
// src/commands/sync.command.ts
|
|
3374
|
-
class SyncCommand extends
|
|
3655
|
+
class SyncCommand extends CommandRunner8 {
|
|
3375
3656
|
syncService;
|
|
3657
|
+
graphService;
|
|
3376
3658
|
_graphValidator;
|
|
3377
3659
|
watcher = null;
|
|
3378
3660
|
isShuttingDown = false;
|
|
3379
|
-
constructor(syncService, _graphValidator) {
|
|
3661
|
+
constructor(syncService, graphService, _graphValidator) {
|
|
3380
3662
|
super();
|
|
3381
3663
|
this.syncService = syncService;
|
|
3664
|
+
this.graphService = graphService;
|
|
3382
3665
|
this._graphValidator = _graphValidator;
|
|
3383
3666
|
}
|
|
3667
|
+
async safeExit(code) {
|
|
3668
|
+
try {
|
|
3669
|
+
await this.graphService.checkpoint();
|
|
3670
|
+
} catch (error) {
|
|
3671
|
+
console.error("Warning: checkpoint failed during exit");
|
|
3672
|
+
}
|
|
3673
|
+
process.exit(code);
|
|
3674
|
+
}
|
|
3384
3675
|
async run(paths, options) {
|
|
3385
3676
|
if (options.watch && options.dryRun) {
|
|
3386
3677
|
console.log(`
|
|
3387
3678
|
\u26A0\uFE0F Watch mode is not compatible with --dry-run mode
|
|
3388
3679
|
`);
|
|
3389
|
-
|
|
3680
|
+
await this.safeExit(1);
|
|
3390
3681
|
}
|
|
3391
3682
|
if (options.watch && options.force) {
|
|
3392
3683
|
console.log(`
|
|
3393
3684
|
\u26A0\uFE0F Watch mode is not compatible with --force mode (for safety)
|
|
3394
3685
|
`);
|
|
3395
|
-
|
|
3686
|
+
await this.safeExit(1);
|
|
3396
3687
|
}
|
|
3397
3688
|
if (options.force && paths.length === 0) {
|
|
3398
3689
|
console.log(`
|
|
@@ -3400,7 +3691,7 @@ class SyncCommand extends CommandRunner7 {
|
|
|
3400
3691
|
`);
|
|
3401
3692
|
console.log(` Usage: lattice sync --force <path1> [path2] ...
|
|
3402
3693
|
`);
|
|
3403
|
-
|
|
3694
|
+
await this.safeExit(1);
|
|
3404
3695
|
}
|
|
3405
3696
|
const syncOptions = {
|
|
3406
3697
|
force: options.force,
|
|
@@ -3447,12 +3738,12 @@ class SyncCommand extends CommandRunner7 {
|
|
|
3447
3738
|
if (options.watch) {
|
|
3448
3739
|
await this.enterWatchMode(syncOptions);
|
|
3449
3740
|
} else {
|
|
3450
|
-
|
|
3741
|
+
await this.safeExit(initialResult.errors.length > 0 ? 1 : 0);
|
|
3451
3742
|
}
|
|
3452
3743
|
} catch (error) {
|
|
3453
3744
|
console.error(`
|
|
3454
3745
|
\u274C Sync failed:`, error instanceof Error ? error.message : String(error));
|
|
3455
|
-
|
|
3746
|
+
await this.safeExit(1);
|
|
3456
3747
|
}
|
|
3457
3748
|
}
|
|
3458
3749
|
async enterWatchMode(syncOptions) {
|
|
@@ -3504,15 +3795,17 @@ class SyncCommand extends CommandRunner7 {
|
|
|
3504
3795
|
`);
|
|
3505
3796
|
this.watcher = watch(docsPath, { recursive: true }, (event, filename) => {
|
|
3506
3797
|
if (filename?.endsWith(".md")) {
|
|
3507
|
-
const fullPath =
|
|
3798
|
+
const fullPath = join4(docsPath, filename);
|
|
3508
3799
|
trackedFiles.add(fullPath);
|
|
3509
3800
|
debouncedSync();
|
|
3510
3801
|
}
|
|
3511
3802
|
});
|
|
3512
|
-
process.on("SIGINT", () =>
|
|
3803
|
+
process.on("SIGINT", () => {
|
|
3804
|
+
this.shutdown().catch(console.error);
|
|
3805
|
+
});
|
|
3513
3806
|
await new Promise(() => {});
|
|
3514
3807
|
}
|
|
3515
|
-
shutdown() {
|
|
3808
|
+
async shutdown() {
|
|
3516
3809
|
if (this.isShuttingDown)
|
|
3517
3810
|
return;
|
|
3518
3811
|
this.isShuttingDown = true;
|
|
@@ -3522,7 +3815,7 @@ class SyncCommand extends CommandRunner7 {
|
|
|
3522
3815
|
if (this.watcher) {
|
|
3523
3816
|
this.watcher.close();
|
|
3524
3817
|
}
|
|
3525
|
-
|
|
3818
|
+
await this.safeExit(0);
|
|
3526
3819
|
}
|
|
3527
3820
|
printSyncResults(result, isWatchMode = false) {
|
|
3528
3821
|
console.log(`
|
|
@@ -3632,7 +3925,7 @@ class SyncCommand extends CommandRunner7 {
|
|
|
3632
3925
|
}
|
|
3633
3926
|
}
|
|
3634
3927
|
__legacyDecorateClassTS([
|
|
3635
|
-
|
|
3928
|
+
Option6({
|
|
3636
3929
|
flags: "-f, --force",
|
|
3637
3930
|
description: "Force re-sync specified documents (requires paths to be specified)"
|
|
3638
3931
|
}),
|
|
@@ -3641,7 +3934,7 @@ __legacyDecorateClassTS([
|
|
|
3641
3934
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3642
3935
|
], SyncCommand.prototype, "parseForce", null);
|
|
3643
3936
|
__legacyDecorateClassTS([
|
|
3644
|
-
|
|
3937
|
+
Option6({
|
|
3645
3938
|
flags: "-d, --dry-run",
|
|
3646
3939
|
description: "Show what would change without applying"
|
|
3647
3940
|
}),
|
|
@@ -3650,7 +3943,7 @@ __legacyDecorateClassTS([
|
|
|
3650
3943
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3651
3944
|
], SyncCommand.prototype, "parseDryRun", null);
|
|
3652
3945
|
__legacyDecorateClassTS([
|
|
3653
|
-
|
|
3946
|
+
Option6({
|
|
3654
3947
|
flags: "-v, --verbose",
|
|
3655
3948
|
description: "Show detailed output"
|
|
3656
3949
|
}),
|
|
@@ -3659,7 +3952,7 @@ __legacyDecorateClassTS([
|
|
|
3659
3952
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3660
3953
|
], SyncCommand.prototype, "parseVerbose", null);
|
|
3661
3954
|
__legacyDecorateClassTS([
|
|
3662
|
-
|
|
3955
|
+
Option6({
|
|
3663
3956
|
flags: "-w, --watch",
|
|
3664
3957
|
description: "Watch for file changes and sync automatically"
|
|
3665
3958
|
}),
|
|
@@ -3668,7 +3961,7 @@ __legacyDecorateClassTS([
|
|
|
3668
3961
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3669
3962
|
], SyncCommand.prototype, "parseWatch", null);
|
|
3670
3963
|
__legacyDecorateClassTS([
|
|
3671
|
-
|
|
3964
|
+
Option6({
|
|
3672
3965
|
flags: "--diff",
|
|
3673
3966
|
description: "Show only changed documents (alias for --dry-run)"
|
|
3674
3967
|
}),
|
|
@@ -3677,7 +3970,7 @@ __legacyDecorateClassTS([
|
|
|
3677
3970
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3678
3971
|
], SyncCommand.prototype, "parseDiff", null);
|
|
3679
3972
|
__legacyDecorateClassTS([
|
|
3680
|
-
|
|
3973
|
+
Option6({
|
|
3681
3974
|
flags: "--skip-cascade",
|
|
3682
3975
|
description: "Skip cascade analysis (faster for large repos)"
|
|
3683
3976
|
}),
|
|
@@ -3686,7 +3979,7 @@ __legacyDecorateClassTS([
|
|
|
3686
3979
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3687
3980
|
], SyncCommand.prototype, "parseSkipCascade", null);
|
|
3688
3981
|
__legacyDecorateClassTS([
|
|
3689
|
-
|
|
3982
|
+
Option6({
|
|
3690
3983
|
flags: "--no-embeddings",
|
|
3691
3984
|
description: "Disable embedding generation during sync"
|
|
3692
3985
|
}),
|
|
@@ -3695,7 +3988,7 @@ __legacyDecorateClassTS([
|
|
|
3695
3988
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3696
3989
|
], SyncCommand.prototype, "parseNoEmbeddings", null);
|
|
3697
3990
|
__legacyDecorateClassTS([
|
|
3698
|
-
|
|
3991
|
+
Option6({
|
|
3699
3992
|
flags: "--skip-extraction",
|
|
3700
3993
|
description: "Skip AI entity extraction (sync without re-extracting entities)"
|
|
3701
3994
|
}),
|
|
@@ -3704,14 +3997,15 @@ __legacyDecorateClassTS([
|
|
|
3704
3997
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3705
3998
|
], SyncCommand.prototype, "parseSkipExtraction", null);
|
|
3706
3999
|
SyncCommand = __legacyDecorateClassTS([
|
|
3707
|
-
|
|
3708
|
-
|
|
4000
|
+
Injectable19(),
|
|
4001
|
+
Command8({
|
|
3709
4002
|
name: "sync",
|
|
3710
4003
|
arguments: "[paths...]",
|
|
3711
4004
|
description: "Synchronize documents to the knowledge graph"
|
|
3712
4005
|
}),
|
|
3713
4006
|
__legacyMetadataTS("design:paramtypes", [
|
|
3714
4007
|
typeof SyncService === "undefined" ? Object : SyncService,
|
|
4008
|
+
typeof GraphService === "undefined" ? Object : GraphService,
|
|
3715
4009
|
typeof GraphValidatorService === "undefined" ? Object : GraphValidatorService
|
|
3716
4010
|
])
|
|
3717
4011
|
], SyncCommand);
|
|
@@ -3743,7 +4037,7 @@ GraphModule = __legacyDecorateClassTS([
|
|
|
3743
4037
|
import { Module as Module3 } from "@nestjs/common";
|
|
3744
4038
|
|
|
3745
4039
|
// src/query/query.service.ts
|
|
3746
|
-
import { Injectable as
|
|
4040
|
+
import { Injectable as Injectable20, Logger as Logger10 } from "@nestjs/common";
|
|
3747
4041
|
class QueryService {
|
|
3748
4042
|
graphService;
|
|
3749
4043
|
logger = new Logger10(QueryService.name);
|
|
@@ -3756,7 +4050,7 @@ class QueryService {
|
|
|
3756
4050
|
}
|
|
3757
4051
|
}
|
|
3758
4052
|
QueryService = __legacyDecorateClassTS([
|
|
3759
|
-
|
|
4053
|
+
Injectable20(),
|
|
3760
4054
|
__legacyMetadataTS("design:paramtypes", [
|
|
3761
4055
|
typeof GraphService === "undefined" ? Object : GraphService
|
|
3762
4056
|
])
|
|
@@ -3829,7 +4123,8 @@ AppModule = __legacyDecorateClassTS([
|
|
|
3829
4123
|
SqlCommand,
|
|
3830
4124
|
OntologyCommand,
|
|
3831
4125
|
InitCommand,
|
|
3832
|
-
MigrateCommand
|
|
4126
|
+
MigrateCommand,
|
|
4127
|
+
SiteCommand
|
|
3833
4128
|
]
|
|
3834
4129
|
})
|
|
3835
4130
|
], AppModule);
|