@zabaca/lattice 1.0.23 → 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 +370 -88
- package/package.json +2 -2
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
|
|
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
|
|
420
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
|
-
}
|
|
465
|
-
console.log();
|
|
466
|
-
console.log(`\u2705 Lattice commands installed to ${targetDir}`);
|
|
457
|
+
await this.setupSiteTemplate(latticeHome);
|
|
458
|
+
await this.installClaudeCommands();
|
|
467
459
|
console.log();
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
if (skipped > 0) {
|
|
476
|
-
console.log(`Skipped ${skipped} unchanged command(s)`);
|
|
477
|
-
}
|
|
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");
|
|
478
465
|
console.log();
|
|
479
|
-
console.log("
|
|
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
|
|
@@ -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,14 +3645,14 @@ 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;
|
|
3376
3657
|
graphService;
|
|
3377
3658
|
_graphValidator;
|
|
@@ -3514,7 +3795,7 @@ class SyncCommand extends CommandRunner7 {
|
|
|
3514
3795
|
`);
|
|
3515
3796
|
this.watcher = watch(docsPath, { recursive: true }, (event, filename) => {
|
|
3516
3797
|
if (filename?.endsWith(".md")) {
|
|
3517
|
-
const fullPath =
|
|
3798
|
+
const fullPath = join4(docsPath, filename);
|
|
3518
3799
|
trackedFiles.add(fullPath);
|
|
3519
3800
|
debouncedSync();
|
|
3520
3801
|
}
|
|
@@ -3644,7 +3925,7 @@ class SyncCommand extends CommandRunner7 {
|
|
|
3644
3925
|
}
|
|
3645
3926
|
}
|
|
3646
3927
|
__legacyDecorateClassTS([
|
|
3647
|
-
|
|
3928
|
+
Option6({
|
|
3648
3929
|
flags: "-f, --force",
|
|
3649
3930
|
description: "Force re-sync specified documents (requires paths to be specified)"
|
|
3650
3931
|
}),
|
|
@@ -3653,7 +3934,7 @@ __legacyDecorateClassTS([
|
|
|
3653
3934
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3654
3935
|
], SyncCommand.prototype, "parseForce", null);
|
|
3655
3936
|
__legacyDecorateClassTS([
|
|
3656
|
-
|
|
3937
|
+
Option6({
|
|
3657
3938
|
flags: "-d, --dry-run",
|
|
3658
3939
|
description: "Show what would change without applying"
|
|
3659
3940
|
}),
|
|
@@ -3662,7 +3943,7 @@ __legacyDecorateClassTS([
|
|
|
3662
3943
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3663
3944
|
], SyncCommand.prototype, "parseDryRun", null);
|
|
3664
3945
|
__legacyDecorateClassTS([
|
|
3665
|
-
|
|
3946
|
+
Option6({
|
|
3666
3947
|
flags: "-v, --verbose",
|
|
3667
3948
|
description: "Show detailed output"
|
|
3668
3949
|
}),
|
|
@@ -3671,7 +3952,7 @@ __legacyDecorateClassTS([
|
|
|
3671
3952
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3672
3953
|
], SyncCommand.prototype, "parseVerbose", null);
|
|
3673
3954
|
__legacyDecorateClassTS([
|
|
3674
|
-
|
|
3955
|
+
Option6({
|
|
3675
3956
|
flags: "-w, --watch",
|
|
3676
3957
|
description: "Watch for file changes and sync automatically"
|
|
3677
3958
|
}),
|
|
@@ -3680,7 +3961,7 @@ __legacyDecorateClassTS([
|
|
|
3680
3961
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3681
3962
|
], SyncCommand.prototype, "parseWatch", null);
|
|
3682
3963
|
__legacyDecorateClassTS([
|
|
3683
|
-
|
|
3964
|
+
Option6({
|
|
3684
3965
|
flags: "--diff",
|
|
3685
3966
|
description: "Show only changed documents (alias for --dry-run)"
|
|
3686
3967
|
}),
|
|
@@ -3689,7 +3970,7 @@ __legacyDecorateClassTS([
|
|
|
3689
3970
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3690
3971
|
], SyncCommand.prototype, "parseDiff", null);
|
|
3691
3972
|
__legacyDecorateClassTS([
|
|
3692
|
-
|
|
3973
|
+
Option6({
|
|
3693
3974
|
flags: "--skip-cascade",
|
|
3694
3975
|
description: "Skip cascade analysis (faster for large repos)"
|
|
3695
3976
|
}),
|
|
@@ -3698,7 +3979,7 @@ __legacyDecorateClassTS([
|
|
|
3698
3979
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3699
3980
|
], SyncCommand.prototype, "parseSkipCascade", null);
|
|
3700
3981
|
__legacyDecorateClassTS([
|
|
3701
|
-
|
|
3982
|
+
Option6({
|
|
3702
3983
|
flags: "--no-embeddings",
|
|
3703
3984
|
description: "Disable embedding generation during sync"
|
|
3704
3985
|
}),
|
|
@@ -3707,7 +3988,7 @@ __legacyDecorateClassTS([
|
|
|
3707
3988
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3708
3989
|
], SyncCommand.prototype, "parseNoEmbeddings", null);
|
|
3709
3990
|
__legacyDecorateClassTS([
|
|
3710
|
-
|
|
3991
|
+
Option6({
|
|
3711
3992
|
flags: "--skip-extraction",
|
|
3712
3993
|
description: "Skip AI entity extraction (sync without re-extracting entities)"
|
|
3713
3994
|
}),
|
|
@@ -3716,8 +3997,8 @@ __legacyDecorateClassTS([
|
|
|
3716
3997
|
__legacyMetadataTS("design:returntype", Boolean)
|
|
3717
3998
|
], SyncCommand.prototype, "parseSkipExtraction", null);
|
|
3718
3999
|
SyncCommand = __legacyDecorateClassTS([
|
|
3719
|
-
|
|
3720
|
-
|
|
4000
|
+
Injectable19(),
|
|
4001
|
+
Command8({
|
|
3721
4002
|
name: "sync",
|
|
3722
4003
|
arguments: "[paths...]",
|
|
3723
4004
|
description: "Synchronize documents to the knowledge graph"
|
|
@@ -3756,7 +4037,7 @@ GraphModule = __legacyDecorateClassTS([
|
|
|
3756
4037
|
import { Module as Module3 } from "@nestjs/common";
|
|
3757
4038
|
|
|
3758
4039
|
// src/query/query.service.ts
|
|
3759
|
-
import { Injectable as
|
|
4040
|
+
import { Injectable as Injectable20, Logger as Logger10 } from "@nestjs/common";
|
|
3760
4041
|
class QueryService {
|
|
3761
4042
|
graphService;
|
|
3762
4043
|
logger = new Logger10(QueryService.name);
|
|
@@ -3769,7 +4050,7 @@ class QueryService {
|
|
|
3769
4050
|
}
|
|
3770
4051
|
}
|
|
3771
4052
|
QueryService = __legacyDecorateClassTS([
|
|
3772
|
-
|
|
4053
|
+
Injectable20(),
|
|
3773
4054
|
__legacyMetadataTS("design:paramtypes", [
|
|
3774
4055
|
typeof GraphService === "undefined" ? Object : GraphService
|
|
3775
4056
|
])
|
|
@@ -3842,7 +4123,8 @@ AppModule = __legacyDecorateClassTS([
|
|
|
3842
4123
|
SqlCommand,
|
|
3843
4124
|
OntologyCommand,
|
|
3844
4125
|
InitCommand,
|
|
3845
|
-
MigrateCommand
|
|
4126
|
+
MigrateCommand,
|
|
4127
|
+
SiteCommand
|
|
3846
4128
|
]
|
|
3847
4129
|
})
|
|
3848
4130
|
], AppModule);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zabaca/lattice",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Human-initiated, AI-powered knowledge graph for markdown documentation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@anthropic-ai/claude-agent-sdk": "^0.1.67",
|
|
47
|
-
"@duckdb/node-api": "1.
|
|
47
|
+
"@duckdb/node-api": "1.3.1-alpha.23",
|
|
48
48
|
"@nestjs/common": "^10.0.0",
|
|
49
49
|
"@nestjs/config": "^3.0.0",
|
|
50
50
|
"@nestjs/core": "^10.0.0",
|