@zabaca/lattice 0.3.1 → 0.3.2
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 +621 -350
- package/dist/main.js +3035 -0
- package/package.json +3 -4
package/dist/cli.js
CHANGED
|
@@ -16,12 +16,8 @@ var __legacyMetadataTS = (k, v) => {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
// src/main.ts
|
|
19
|
-
import
|
|
20
|
-
|
|
21
|
-
// src/commands/sync.command.ts
|
|
22
|
-
import { NestFactory } from "@nestjs/core";
|
|
23
|
-
import { watch } from "fs";
|
|
24
|
-
import { join } from "path";
|
|
19
|
+
import"reflect-metadata";
|
|
20
|
+
import { CommandFactory } from "nest-commander";
|
|
25
21
|
|
|
26
22
|
// src/app.module.ts
|
|
27
23
|
import { Module as Module5 } from "@nestjs/common";
|
|
@@ -2036,264 +2032,343 @@ QueryModule = __legacyDecorateClassTS([
|
|
|
2036
2032
|
})
|
|
2037
2033
|
], QueryModule);
|
|
2038
2034
|
|
|
2039
|
-
// src/app.module.ts
|
|
2040
|
-
class AppModule {
|
|
2041
|
-
}
|
|
2042
|
-
AppModule = __legacyDecorateClassTS([
|
|
2043
|
-
Module5({
|
|
2044
|
-
imports: [
|
|
2045
|
-
ConfigModule2.forRoot({
|
|
2046
|
-
isGlobal: true
|
|
2047
|
-
}),
|
|
2048
|
-
GraphModule,
|
|
2049
|
-
SyncModule,
|
|
2050
|
-
EmbeddingModule,
|
|
2051
|
-
QueryModule
|
|
2052
|
-
]
|
|
2053
|
-
})
|
|
2054
|
-
], AppModule);
|
|
2055
|
-
|
|
2056
2035
|
// src/commands/sync.command.ts
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2036
|
+
import { Injectable as Injectable10 } from "@nestjs/common";
|
|
2037
|
+
import { Command, CommandRunner, Option } from "nest-commander";
|
|
2038
|
+
import { watch } from "fs";
|
|
2039
|
+
import { join } from "path";
|
|
2040
|
+
class SyncCommand extends CommandRunner {
|
|
2041
|
+
syncService;
|
|
2042
|
+
watcher = null;
|
|
2043
|
+
isShuttingDown = false;
|
|
2044
|
+
constructor(syncService) {
|
|
2045
|
+
super();
|
|
2046
|
+
this.syncService = syncService;
|
|
2047
|
+
}
|
|
2048
|
+
async run(paths, options) {
|
|
2049
|
+
if (options.watch && options.dryRun) {
|
|
2063
2050
|
console.log(`
|
|
2064
|
-
\
|
|
2051
|
+
\u26A0\uFE0F Watch mode is not compatible with --dry-run mode
|
|
2065
2052
|
`);
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
console.log(`
|
|
2070
|
-
|
|
2071
|
-
console.log(` \uD83E\uDDE0 Embeddings: ${result.embeddingsGenerated}`);
|
|
2072
|
-
}
|
|
2073
|
-
console.log(` \u23F1\uFE0F Duration: ${result.duration}ms`);
|
|
2074
|
-
if (result.errors.length > 0) {
|
|
2075
|
-
console.log(`
|
|
2076
|
-
\u274C Errors (${result.errors.length}):
|
|
2053
|
+
process.exit(1);
|
|
2054
|
+
}
|
|
2055
|
+
if (options.watch && options.force) {
|
|
2056
|
+
console.log(`
|
|
2057
|
+
\u26A0\uFE0F Watch mode is not compatible with --force mode (for safety)
|
|
2077
2058
|
`);
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2059
|
+
process.exit(1);
|
|
2060
|
+
}
|
|
2061
|
+
const syncOptions = {
|
|
2062
|
+
force: options.force,
|
|
2063
|
+
dryRun: options.dryRun || options.diff,
|
|
2064
|
+
verbose: options.verbose,
|
|
2065
|
+
paths: paths.length > 0 ? paths : undefined,
|
|
2066
|
+
skipCascade: options.skipCascade,
|
|
2067
|
+
embeddings: options.embeddings !== false
|
|
2068
|
+
};
|
|
2069
|
+
console.log(`
|
|
2070
|
+
\uD83D\uDD04 Graph Sync
|
|
2071
|
+
`);
|
|
2072
|
+
if (syncOptions.force) {
|
|
2073
|
+
if (syncOptions.paths && syncOptions.paths.length > 0) {
|
|
2074
|
+
console.log(`\u26A0\uFE0F Force mode: ${syncOptions.paths.length} document(s) will be cleared and re-synced
|
|
2075
|
+
`);
|
|
2076
|
+
} else {
|
|
2077
|
+
console.log(`\u26A0\uFE0F Force mode: Entire graph will be cleared and rebuilt
|
|
2085
2078
|
`);
|
|
2086
|
-
result.changes.forEach((c) => {
|
|
2087
|
-
const icon = {
|
|
2088
|
-
new: "\u2795",
|
|
2089
|
-
updated: "\uD83D\uDD04",
|
|
2090
|
-
deleted: "\uD83D\uDDD1\uFE0F",
|
|
2091
|
-
unchanged: "\u23ED\uFE0F"
|
|
2092
|
-
}[c.changeType];
|
|
2093
|
-
console.log(` ${icon} ${c.changeType}: ${c.path}`);
|
|
2094
|
-
if (c.reason) {
|
|
2095
|
-
console.log(` ${c.reason}`);
|
|
2096
|
-
}
|
|
2097
|
-
});
|
|
2098
2079
|
}
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
\
|
|
2080
|
+
}
|
|
2081
|
+
if (syncOptions.dryRun) {
|
|
2082
|
+
console.log(`\uD83D\uDCCB Dry run mode: No changes will be applied
|
|
2102
2083
|
`);
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
existing.push(warning);
|
|
2107
|
-
warningsByTrigger.set(warning.trigger, existing);
|
|
2108
|
-
}
|
|
2109
|
-
for (const [trigger, warnings] of warningsByTrigger) {
|
|
2110
|
-
const triggerLabel = trigger.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
2111
|
-
console.log(` \uD83D\uDCCC ${triggerLabel}
|
|
2084
|
+
}
|
|
2085
|
+
if (syncOptions.skipCascade) {
|
|
2086
|
+
console.log(`\u26A1 Cascade analysis skipped
|
|
2112
2087
|
`);
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2088
|
+
}
|
|
2089
|
+
if (!syncOptions.embeddings) {
|
|
2090
|
+
console.log(`\uD83D\uDEAB Embedding generation disabled
|
|
2116
2091
|
`);
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2092
|
+
}
|
|
2093
|
+
if (syncOptions.paths) {
|
|
2094
|
+
console.log(`\uD83D\uDCC1 Syncing specific paths: ${syncOptions.paths.join(", ")}
|
|
2095
|
+
`);
|
|
2096
|
+
}
|
|
2097
|
+
try {
|
|
2098
|
+
const initialResult = await this.syncService.sync(syncOptions);
|
|
2099
|
+
this.printSyncResults(initialResult, options.watch);
|
|
2100
|
+
if (options.dryRun) {
|
|
2101
|
+
console.log("\uD83D\uDCA1 Run without --dry-run to apply changes");
|
|
2102
|
+
}
|
|
2103
|
+
if (options.watch) {
|
|
2104
|
+
await this.enterWatchMode(syncOptions);
|
|
2105
|
+
} else {
|
|
2106
|
+
process.exit(initialResult.errors.length > 0 ? 1 : 0);
|
|
2107
|
+
}
|
|
2108
|
+
} catch (error) {
|
|
2109
|
+
console.error(`
|
|
2110
|
+
\u274C Sync failed:`, error instanceof Error ? error.message : String(error));
|
|
2111
|
+
process.exit(1);
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
async enterWatchMode(syncOptions) {
|
|
2115
|
+
const docsPath = process.env.DOCS_PATH || "docs";
|
|
2116
|
+
let debounceTimeout = null;
|
|
2117
|
+
const trackedFiles = new Set;
|
|
2118
|
+
const debouncedSync = () => {
|
|
2119
|
+
if (debounceTimeout) {
|
|
2120
|
+
clearTimeout(debounceTimeout);
|
|
2121
|
+
}
|
|
2122
|
+
debounceTimeout = setTimeout(async () => {
|
|
2123
|
+
if (this.isShuttingDown)
|
|
2124
|
+
return;
|
|
2125
|
+
if (trackedFiles.size === 0)
|
|
2126
|
+
return;
|
|
2127
|
+
try {
|
|
2128
|
+
const changedPaths = Array.from(trackedFiles);
|
|
2129
|
+
trackedFiles.clear();
|
|
2130
|
+
console.log(`
|
|
2131
|
+
\uD83D\uDCDD Changes detected (${changedPaths.length} file${changedPaths.length !== 1 ? "s" : ""})`);
|
|
2132
|
+
const watchResult = await this.syncService.sync({
|
|
2133
|
+
...syncOptions,
|
|
2134
|
+
paths: changedPaths,
|
|
2135
|
+
dryRun: false
|
|
2136
|
+
});
|
|
2137
|
+
const hasChanges = watchResult.added > 0 || watchResult.updated > 0 || watchResult.deleted > 0;
|
|
2138
|
+
if (hasChanges) {
|
|
2139
|
+
console.log(` \u2705 Synced: +${watchResult.added} ~${watchResult.updated} -${watchResult.deleted}`);
|
|
2140
|
+
if (watchResult.errors.length > 0) {
|
|
2141
|
+
console.log(` \u274C Errors: ${watchResult.errors.map((e) => e.path).join(", ")}`);
|
|
2142
|
+
}
|
|
2143
|
+
if (watchResult.cascadeWarnings && watchResult.cascadeWarnings.length > 0) {
|
|
2144
|
+
console.log(` \u26A0\uFE0F Cascade impacts detected: ${watchResult.cascadeWarnings.length} warning(s)`);
|
|
2127
2145
|
}
|
|
2128
|
-
|
|
2146
|
+
} else {
|
|
2147
|
+
console.log(" \u23ED\uFE0F No changes detected");
|
|
2129
2148
|
}
|
|
2130
|
-
|
|
2131
|
-
console.log(` \uD83D\uDCA1 Run /update-related to apply suggested changes
|
|
2149
|
+
console.log(`\u23F3 Watching for changes...
|
|
2132
2150
|
`);
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
\u23F3 Watching for changes... (Ctrl+C to stop)
|
|
2151
|
+
} catch (error) {
|
|
2152
|
+
console.error(` \u274C Sync failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2153
|
+
console.log(`\u23F3 Watching for changes...
|
|
2137
2154
|
`);
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
const shutdown = async () => {
|
|
2141
|
-
if (isShuttingDown)
|
|
2142
|
-
return;
|
|
2143
|
-
isShuttingDown = true;
|
|
2144
|
-
console.log(`
|
|
2145
|
-
|
|
2146
|
-
\uD83D\uDC4B Stopping watch mode...`);
|
|
2147
|
-
if (watcher) {
|
|
2148
|
-
watcher.close();
|
|
2149
|
-
}
|
|
2150
|
-
if (app) {
|
|
2151
|
-
await app.close();
|
|
2152
|
-
}
|
|
2153
|
-
process.exit(0);
|
|
2155
|
+
}
|
|
2156
|
+
}, 500);
|
|
2154
2157
|
};
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
logger: options.verbose ? ["log", "error", "warn"] : ["error"]
|
|
2158
|
-
});
|
|
2159
|
-
const sync = app.get(SyncService);
|
|
2160
|
-
if (options.watch && options.dryRun) {
|
|
2161
|
-
console.log(`
|
|
2162
|
-
\u26A0\uFE0F Watch mode is not compatible with --dry-run mode
|
|
2158
|
+
console.log(`
|
|
2159
|
+
\uD83D\uDC41\uFE0F Watch mode enabled
|
|
2163
2160
|
`);
|
|
2164
|
-
|
|
2165
|
-
|
|
2161
|
+
this.watcher = watch(docsPath, { recursive: true }, (event, filename) => {
|
|
2162
|
+
if (filename && filename.endsWith(".md")) {
|
|
2163
|
+
const fullPath = join(docsPath, filename);
|
|
2164
|
+
trackedFiles.add(fullPath);
|
|
2165
|
+
debouncedSync();
|
|
2166
2166
|
}
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2167
|
+
});
|
|
2168
|
+
process.on("SIGINT", () => this.shutdown());
|
|
2169
|
+
await new Promise(() => {});
|
|
2170
|
+
}
|
|
2171
|
+
shutdown() {
|
|
2172
|
+
if (this.isShuttingDown)
|
|
2173
|
+
return;
|
|
2174
|
+
this.isShuttingDown = true;
|
|
2175
|
+
console.log(`
|
|
2176
|
+
|
|
2177
|
+
\uD83D\uDC4B Stopping watch mode...`);
|
|
2178
|
+
if (this.watcher) {
|
|
2179
|
+
this.watcher.close();
|
|
2180
|
+
}
|
|
2181
|
+
process.exit(0);
|
|
2182
|
+
}
|
|
2183
|
+
printSyncResults(result, isWatchMode = false) {
|
|
2184
|
+
console.log(`
|
|
2185
|
+
\uD83D\uDCCA Sync Results:
|
|
2170
2186
|
`);
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
embeddings: options.embeddings !== false
|
|
2181
|
-
};
|
|
2187
|
+
console.log(` \u2705 Added: ${result.added}`);
|
|
2188
|
+
console.log(` \uD83D\uDD04 Updated: ${result.updated}`);
|
|
2189
|
+
console.log(` \uD83D\uDDD1\uFE0F Deleted: ${result.deleted}`);
|
|
2190
|
+
console.log(` \u23ED\uFE0F Unchanged: ${result.unchanged}`);
|
|
2191
|
+
if (result.embeddingsGenerated > 0) {
|
|
2192
|
+
console.log(` \uD83E\uDDE0 Embeddings: ${result.embeddingsGenerated}`);
|
|
2193
|
+
}
|
|
2194
|
+
console.log(` \u23F1\uFE0F Duration: ${result.duration}ms`);
|
|
2195
|
+
if (result.errors.length > 0) {
|
|
2182
2196
|
console.log(`
|
|
2183
|
-
\
|
|
2184
|
-
`);
|
|
2185
|
-
if (syncOptions.force) {
|
|
2186
|
-
if (syncOptions.paths && syncOptions.paths.length > 0) {
|
|
2187
|
-
console.log(`\u26A0\uFE0F Force mode: ${syncOptions.paths.length} document(s) will be cleared and re-synced
|
|
2197
|
+
\u274C Errors (${result.errors.length}):
|
|
2188
2198
|
`);
|
|
2189
|
-
|
|
2190
|
-
|
|
2199
|
+
result.errors.forEach((e) => {
|
|
2200
|
+
console.log(` ${e.path}: ${e.error}`);
|
|
2201
|
+
});
|
|
2202
|
+
}
|
|
2203
|
+
if (result.changes && result.changes.length > 0) {
|
|
2204
|
+
console.log(`
|
|
2205
|
+
\uD83D\uDCDD Changes:
|
|
2191
2206
|
`);
|
|
2207
|
+
result.changes.forEach((c) => {
|
|
2208
|
+
const icon = {
|
|
2209
|
+
new: "\u2795",
|
|
2210
|
+
updated: "\uD83D\uDD04",
|
|
2211
|
+
deleted: "\uD83D\uDDD1\uFE0F",
|
|
2212
|
+
unchanged: "\u23ED\uFE0F"
|
|
2213
|
+
}[c.changeType];
|
|
2214
|
+
console.log(` ${icon} ${c.changeType}: ${c.path}`);
|
|
2215
|
+
if (c.reason) {
|
|
2216
|
+
console.log(` ${c.reason}`);
|
|
2192
2217
|
}
|
|
2193
|
-
}
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
`
|
|
2197
|
-
|
|
2198
|
-
if (syncOptions.skipCascade) {
|
|
2199
|
-
console.log(`\u26A1 Cascade analysis skipped
|
|
2218
|
+
});
|
|
2219
|
+
}
|
|
2220
|
+
if (result.cascadeWarnings && result.cascadeWarnings.length > 0) {
|
|
2221
|
+
console.log(`
|
|
2222
|
+
\u26A0\uFE0F Cascade Impacts Detected:
|
|
2200
2223
|
`);
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2224
|
+
const warningsByTrigger = new Map;
|
|
2225
|
+
for (const warning of result.cascadeWarnings) {
|
|
2226
|
+
const existing = warningsByTrigger.get(warning.trigger) || [];
|
|
2227
|
+
existing.push(warning);
|
|
2228
|
+
warningsByTrigger.set(warning.trigger, existing);
|
|
2229
|
+
}
|
|
2230
|
+
for (const [trigger, warnings] of warningsByTrigger) {
|
|
2231
|
+
const triggerLabel = trigger.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
2232
|
+
console.log(` \uD83D\uDCCC ${triggerLabel}
|
|
2204
2233
|
`);
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
`);
|
|
2209
|
-
}
|
|
2210
|
-
const initialResult = await sync.sync(syncOptions);
|
|
2211
|
-
printSyncResults(initialResult, options.watch);
|
|
2212
|
-
if (options.dryRun) {
|
|
2213
|
-
console.log("\uD83D\uDCA1 Run without --dry-run to apply changes");
|
|
2214
|
-
}
|
|
2215
|
-
if (options.watch) {
|
|
2216
|
-
const docsPath = process.env.DOCS_PATH || "docs";
|
|
2217
|
-
let debounceTimeout = null;
|
|
2218
|
-
const trackedFiles = new Set;
|
|
2219
|
-
const debouncedSync = () => {
|
|
2220
|
-
if (debounceTimeout) {
|
|
2221
|
-
clearTimeout(debounceTimeout);
|
|
2222
|
-
}
|
|
2223
|
-
debounceTimeout = setTimeout(async () => {
|
|
2224
|
-
if (isShuttingDown)
|
|
2225
|
-
return;
|
|
2226
|
-
if (trackedFiles.size === 0)
|
|
2227
|
-
return;
|
|
2228
|
-
try {
|
|
2229
|
-
const changedPaths = Array.from(trackedFiles);
|
|
2230
|
-
trackedFiles.clear();
|
|
2231
|
-
console.log(`
|
|
2232
|
-
\uD83D\uDCDD Changes detected (${changedPaths.length} file${changedPaths.length !== 1 ? "s" : ""})`);
|
|
2233
|
-
const watchResult = await sync.sync({
|
|
2234
|
-
...syncOptions,
|
|
2235
|
-
paths: changedPaths,
|
|
2236
|
-
dryRun: false
|
|
2237
|
-
});
|
|
2238
|
-
const hasChanges = watchResult.added > 0 || watchResult.updated > 0 || watchResult.deleted > 0;
|
|
2239
|
-
if (hasChanges) {
|
|
2240
|
-
console.log(` \u2705 Synced: +${watchResult.added} ~${watchResult.updated} -${watchResult.deleted}`);
|
|
2241
|
-
if (watchResult.errors.length > 0) {
|
|
2242
|
-
console.log(` \u274C Errors: ${watchResult.errors.map((e) => e.path).join(", ")}`);
|
|
2243
|
-
}
|
|
2244
|
-
if (watchResult.cascadeWarnings && watchResult.cascadeWarnings.length > 0) {
|
|
2245
|
-
console.log(` \u26A0\uFE0F Cascade impacts detected: ${watchResult.cascadeWarnings.length} warning(s)`);
|
|
2246
|
-
}
|
|
2247
|
-
} else {
|
|
2248
|
-
console.log(" \u23ED\uFE0F No changes detected");
|
|
2249
|
-
}
|
|
2250
|
-
console.log(`\u23F3 Watching for changes...
|
|
2251
|
-
`);
|
|
2252
|
-
} catch (error) {
|
|
2253
|
-
console.error(` \u274C Sync failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2254
|
-
console.log(`\u23F3 Watching for changes...
|
|
2234
|
+
for (const analysis of warnings) {
|
|
2235
|
+
console.log(` ${analysis.summary}`);
|
|
2236
|
+
console.log(` Source: ${analysis.sourceDocument}
|
|
2255
2237
|
`);
|
|
2238
|
+
if (analysis.affectedDocuments.length > 0) {
|
|
2239
|
+
for (const affected of analysis.affectedDocuments) {
|
|
2240
|
+
const icon = affected.confidence === "high" ? "\uD83D\uDD34" : affected.confidence === "medium" ? "\uD83D\uDFE1" : "\uD83D\uDFE2";
|
|
2241
|
+
console.log(` ${icon} [${affected.confidence.toUpperCase()}] ${affected.path}`);
|
|
2242
|
+
console.log(` ${affected.reason}`);
|
|
2243
|
+
const suggestedAction = affected.suggestedAction.split("_").join(" ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
2244
|
+
console.log(` \u2192 ${suggestedAction}`);
|
|
2256
2245
|
}
|
|
2257
|
-
}
|
|
2258
|
-
|
|
2259
|
-
console.log(`
|
|
2260
|
-
\uD83D\uDC41\uFE0F Watch mode enabled
|
|
2261
|
-
`);
|
|
2262
|
-
watcher = watch(docsPath, { recursive: true }, (event, filename) => {
|
|
2263
|
-
if (filename && filename.endsWith(".md")) {
|
|
2264
|
-
const fullPath = join(docsPath, filename);
|
|
2265
|
-
trackedFiles.add(fullPath);
|
|
2266
|
-
debouncedSync();
|
|
2246
|
+
} else {
|
|
2247
|
+
console.log(` \u2139\uFE0F No directly affected documents detected`);
|
|
2267
2248
|
}
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
await new Promise(() => {});
|
|
2271
|
-
} else {
|
|
2272
|
-
await app.close();
|
|
2273
|
-
process.exit(initialResult.errors.length > 0 ? 1 : 0);
|
|
2249
|
+
console.log();
|
|
2250
|
+
}
|
|
2274
2251
|
}
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2252
|
+
console.log(` \uD83D\uDCA1 Run /update-related to apply suggested changes
|
|
2253
|
+
`);
|
|
2254
|
+
}
|
|
2255
|
+
if (isWatchMode) {
|
|
2256
|
+
console.log(`
|
|
2257
|
+
\u23F3 Watching for changes... (Ctrl+C to stop)
|
|
2258
|
+
`);
|
|
2281
2259
|
}
|
|
2282
|
-
}
|
|
2260
|
+
}
|
|
2261
|
+
parseForce() {
|
|
2262
|
+
return true;
|
|
2263
|
+
}
|
|
2264
|
+
parseDryRun() {
|
|
2265
|
+
return true;
|
|
2266
|
+
}
|
|
2267
|
+
parseVerbose() {
|
|
2268
|
+
return true;
|
|
2269
|
+
}
|
|
2270
|
+
parseWatch() {
|
|
2271
|
+
return true;
|
|
2272
|
+
}
|
|
2273
|
+
parseDiff() {
|
|
2274
|
+
return true;
|
|
2275
|
+
}
|
|
2276
|
+
parseSkipCascade() {
|
|
2277
|
+
return true;
|
|
2278
|
+
}
|
|
2279
|
+
parseNoEmbeddings() {
|
|
2280
|
+
return false;
|
|
2281
|
+
}
|
|
2283
2282
|
}
|
|
2283
|
+
__legacyDecorateClassTS([
|
|
2284
|
+
Option({
|
|
2285
|
+
flags: "-f, --force",
|
|
2286
|
+
description: "Force re-sync: with paths, clears only those docs; without paths, rebuilds entire graph"
|
|
2287
|
+
}),
|
|
2288
|
+
__legacyMetadataTS("design:type", Function),
|
|
2289
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2290
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2291
|
+
], SyncCommand.prototype, "parseForce", null);
|
|
2292
|
+
__legacyDecorateClassTS([
|
|
2293
|
+
Option({
|
|
2294
|
+
flags: "-d, --dry-run",
|
|
2295
|
+
description: "Show what would change without applying"
|
|
2296
|
+
}),
|
|
2297
|
+
__legacyMetadataTS("design:type", Function),
|
|
2298
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2299
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2300
|
+
], SyncCommand.prototype, "parseDryRun", null);
|
|
2301
|
+
__legacyDecorateClassTS([
|
|
2302
|
+
Option({
|
|
2303
|
+
flags: "-v, --verbose",
|
|
2304
|
+
description: "Show detailed output"
|
|
2305
|
+
}),
|
|
2306
|
+
__legacyMetadataTS("design:type", Function),
|
|
2307
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2308
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2309
|
+
], SyncCommand.prototype, "parseVerbose", null);
|
|
2310
|
+
__legacyDecorateClassTS([
|
|
2311
|
+
Option({
|
|
2312
|
+
flags: "-w, --watch",
|
|
2313
|
+
description: "Watch for file changes and sync automatically"
|
|
2314
|
+
}),
|
|
2315
|
+
__legacyMetadataTS("design:type", Function),
|
|
2316
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2317
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2318
|
+
], SyncCommand.prototype, "parseWatch", null);
|
|
2319
|
+
__legacyDecorateClassTS([
|
|
2320
|
+
Option({
|
|
2321
|
+
flags: "--diff",
|
|
2322
|
+
description: "Show only changed documents (alias for --dry-run)"
|
|
2323
|
+
}),
|
|
2324
|
+
__legacyMetadataTS("design:type", Function),
|
|
2325
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2326
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2327
|
+
], SyncCommand.prototype, "parseDiff", null);
|
|
2328
|
+
__legacyDecorateClassTS([
|
|
2329
|
+
Option({
|
|
2330
|
+
flags: "--skip-cascade",
|
|
2331
|
+
description: "Skip cascade analysis (faster for large repos)"
|
|
2332
|
+
}),
|
|
2333
|
+
__legacyMetadataTS("design:type", Function),
|
|
2334
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2335
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2336
|
+
], SyncCommand.prototype, "parseSkipCascade", null);
|
|
2337
|
+
__legacyDecorateClassTS([
|
|
2338
|
+
Option({
|
|
2339
|
+
flags: "--no-embeddings",
|
|
2340
|
+
description: "Disable embedding generation during sync"
|
|
2341
|
+
}),
|
|
2342
|
+
__legacyMetadataTS("design:type", Function),
|
|
2343
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2344
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2345
|
+
], SyncCommand.prototype, "parseNoEmbeddings", null);
|
|
2346
|
+
SyncCommand = __legacyDecorateClassTS([
|
|
2347
|
+
Injectable10(),
|
|
2348
|
+
Command({
|
|
2349
|
+
name: "sync",
|
|
2350
|
+
arguments: "[paths...]",
|
|
2351
|
+
description: "Synchronize documents to the knowledge graph"
|
|
2352
|
+
}),
|
|
2353
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2354
|
+
typeof SyncService === "undefined" ? Object : SyncService
|
|
2355
|
+
])
|
|
2356
|
+
], SyncCommand);
|
|
2284
2357
|
// src/commands/status.command.ts
|
|
2285
|
-
import {
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2358
|
+
import { Injectable as Injectable11 } from "@nestjs/common";
|
|
2359
|
+
import { Command as Command2, CommandRunner as CommandRunner2, Option as Option2 } from "nest-commander";
|
|
2360
|
+
class StatusCommand extends CommandRunner2 {
|
|
2361
|
+
syncService;
|
|
2362
|
+
manifestService;
|
|
2363
|
+
constructor(syncService, manifestService) {
|
|
2364
|
+
super();
|
|
2365
|
+
this.syncService = syncService;
|
|
2366
|
+
this.manifestService = manifestService;
|
|
2367
|
+
}
|
|
2368
|
+
async run(_inputs, options) {
|
|
2289
2369
|
try {
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
});
|
|
2293
|
-
const sync = app.get(SyncService);
|
|
2294
|
-
const manifest = app.get(ManifestService);
|
|
2295
|
-
await manifest.load();
|
|
2296
|
-
const changes = await sync.detectChanges();
|
|
2370
|
+
await this.manifestService.load();
|
|
2371
|
+
const changes = await this.syncService.detectChanges();
|
|
2297
2372
|
const newDocs = changes.filter((c) => c.changeType === "new");
|
|
2298
2373
|
const updatedDocs = changes.filter((c) => c.changeType === "updated");
|
|
2299
2374
|
const deletedDocs = changes.filter((c) => c.changeType === "deleted");
|
|
@@ -2337,27 +2412,48 @@ function registerStatusCommand(program) {
|
|
|
2337
2412
|
console.log(`Total: ${pendingCount} document(s) need syncing`);
|
|
2338
2413
|
console.log("\uD83D\uDCA1 Run `lattice sync` to apply changes\n");
|
|
2339
2414
|
}
|
|
2340
|
-
await app.close();
|
|
2341
2415
|
process.exit(0);
|
|
2342
2416
|
} catch (error) {
|
|
2343
2417
|
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
2344
|
-
if (app)
|
|
2345
|
-
await app.close();
|
|
2346
2418
|
process.exit(1);
|
|
2347
2419
|
}
|
|
2348
|
-
}
|
|
2420
|
+
}
|
|
2421
|
+
parseVerbose() {
|
|
2422
|
+
return true;
|
|
2423
|
+
}
|
|
2349
2424
|
}
|
|
2425
|
+
__legacyDecorateClassTS([
|
|
2426
|
+
Option2({
|
|
2427
|
+
flags: "-v, --verbose",
|
|
2428
|
+
description: "Show all documents including unchanged"
|
|
2429
|
+
}),
|
|
2430
|
+
__legacyMetadataTS("design:type", Function),
|
|
2431
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2432
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2433
|
+
], StatusCommand.prototype, "parseVerbose", null);
|
|
2434
|
+
StatusCommand = __legacyDecorateClassTS([
|
|
2435
|
+
Injectable11(),
|
|
2436
|
+
Command2({
|
|
2437
|
+
name: "status",
|
|
2438
|
+
description: "Show documents that need syncing (new or updated)"
|
|
2439
|
+
}),
|
|
2440
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2441
|
+
typeof SyncService === "undefined" ? Object : SyncService,
|
|
2442
|
+
typeof ManifestService === "undefined" ? Object : ManifestService
|
|
2443
|
+
])
|
|
2444
|
+
], StatusCommand);
|
|
2350
2445
|
// src/commands/query.command.ts
|
|
2351
|
-
import {
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2446
|
+
import { Injectable as Injectable12 } from "@nestjs/common";
|
|
2447
|
+
import { Command as Command3, CommandRunner as CommandRunner3, Option as Option3 } from "nest-commander";
|
|
2448
|
+
class StatsCommand extends CommandRunner3 {
|
|
2449
|
+
graphService;
|
|
2450
|
+
constructor(graphService) {
|
|
2451
|
+
super();
|
|
2452
|
+
this.graphService = graphService;
|
|
2453
|
+
}
|
|
2454
|
+
async run() {
|
|
2355
2455
|
try {
|
|
2356
|
-
|
|
2357
|
-
logger: ["error"]
|
|
2358
|
-
});
|
|
2359
|
-
const graph = app.get(GraphService);
|
|
2360
|
-
const stats = await graph.getStats();
|
|
2456
|
+
const stats = await this.graphService.getStats();
|
|
2361
2457
|
console.log(`
|
|
2362
2458
|
=== Graph Statistics ===
|
|
2363
2459
|
`);
|
|
@@ -2376,28 +2472,40 @@ Relationship Types (${stats.relationshipTypes.length}):`);
|
|
|
2376
2472
|
console.log(` - ${relType}: ${count}`);
|
|
2377
2473
|
});
|
|
2378
2474
|
console.log();
|
|
2379
|
-
await app.close();
|
|
2380
2475
|
process.exit(0);
|
|
2381
2476
|
} catch (error) {
|
|
2382
2477
|
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
2383
|
-
if (app)
|
|
2384
|
-
await app.close();
|
|
2385
2478
|
process.exit(1);
|
|
2386
2479
|
}
|
|
2387
|
-
}
|
|
2388
|
-
|
|
2389
|
-
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
StatsCommand = __legacyDecorateClassTS([
|
|
2483
|
+
Injectable12(),
|
|
2484
|
+
Command3({
|
|
2485
|
+
name: "stats",
|
|
2486
|
+
description: "Show graph statistics"
|
|
2487
|
+
}),
|
|
2488
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2489
|
+
typeof GraphService === "undefined" ? Object : GraphService
|
|
2490
|
+
])
|
|
2491
|
+
], StatsCommand);
|
|
2492
|
+
|
|
2493
|
+
class SearchCommand extends CommandRunner3 {
|
|
2494
|
+
graphService;
|
|
2495
|
+
embeddingService;
|
|
2496
|
+
constructor(graphService, embeddingService) {
|
|
2497
|
+
super();
|
|
2498
|
+
this.graphService = graphService;
|
|
2499
|
+
this.embeddingService = embeddingService;
|
|
2500
|
+
}
|
|
2501
|
+
async run(inputs, options) {
|
|
2502
|
+
const query = inputs[0];
|
|
2503
|
+
const limit = Math.min(parseInt(options.limit || "20", 10), 100);
|
|
2390
2504
|
try {
|
|
2391
|
-
|
|
2392
|
-
logger: ["error"]
|
|
2393
|
-
});
|
|
2394
|
-
const graph = app.get(GraphService);
|
|
2395
|
-
const embedding = app.get(EmbeddingService);
|
|
2396
|
-
const limit = Math.min(parseInt(options.limit, 10), 100);
|
|
2397
|
-
const queryEmbedding = await embedding.generateEmbedding(query);
|
|
2505
|
+
const queryEmbedding = await this.embeddingService.generateEmbedding(query);
|
|
2398
2506
|
let results;
|
|
2399
2507
|
if (options.label) {
|
|
2400
|
-
const labelResults = await
|
|
2508
|
+
const labelResults = await this.graphService.vectorSearch(options.label, queryEmbedding, limit);
|
|
2401
2509
|
results = labelResults.map((r) => ({
|
|
2402
2510
|
name: r.name,
|
|
2403
2511
|
label: options.label,
|
|
@@ -2405,7 +2513,7 @@ Relationship Types (${stats.relationshipTypes.length}):`);
|
|
|
2405
2513
|
score: r.score
|
|
2406
2514
|
}));
|
|
2407
2515
|
} else {
|
|
2408
|
-
results = await
|
|
2516
|
+
results = await this.graphService.vectorSearchAll(queryEmbedding, limit);
|
|
2409
2517
|
}
|
|
2410
2518
|
const labelSuffix = options.label ? ` (${options.label})` : "";
|
|
2411
2519
|
console.log(`
|
|
@@ -2418,7 +2526,6 @@ Relationship Types (${stats.relationshipTypes.length}):`);
|
|
|
2418
2526
|
console.log(`Tip: Try without --label to search all entity types.
|
|
2419
2527
|
`);
|
|
2420
2528
|
}
|
|
2421
|
-
await app.close();
|
|
2422
2529
|
process.exit(0);
|
|
2423
2530
|
}
|
|
2424
2531
|
results.forEach((result, idx) => {
|
|
@@ -2433,7 +2540,6 @@ Relationship Types (${stats.relationshipTypes.length}):`);
|
|
|
2433
2540
|
console.log(` Similarity: ${(result.score * 100).toFixed(2)}%`);
|
|
2434
2541
|
});
|
|
2435
2542
|
console.log();
|
|
2436
|
-
await app.close();
|
|
2437
2543
|
process.exit(0);
|
|
2438
2544
|
} catch (error) {
|
|
2439
2545
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
@@ -2444,21 +2550,64 @@ Note: Semantic search requires embeddings to be generated first.`);
|
|
|
2444
2550
|
console.log(`Run 'lattice sync' to generate embeddings for documents.
|
|
2445
2551
|
`);
|
|
2446
2552
|
}
|
|
2447
|
-
if (app)
|
|
2448
|
-
await app.close();
|
|
2449
2553
|
process.exit(1);
|
|
2450
2554
|
}
|
|
2451
|
-
}
|
|
2452
|
-
|
|
2453
|
-
|
|
2555
|
+
}
|
|
2556
|
+
parseLabel(value) {
|
|
2557
|
+
return value;
|
|
2558
|
+
}
|
|
2559
|
+
parseLimit(value) {
|
|
2560
|
+
return value;
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
__legacyDecorateClassTS([
|
|
2564
|
+
Option3({
|
|
2565
|
+
flags: "-l, --label <label>",
|
|
2566
|
+
description: "Filter by entity label (e.g., Technology, Concept, Document)"
|
|
2567
|
+
}),
|
|
2568
|
+
__legacyMetadataTS("design:type", Function),
|
|
2569
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2570
|
+
String
|
|
2571
|
+
]),
|
|
2572
|
+
__legacyMetadataTS("design:returntype", String)
|
|
2573
|
+
], SearchCommand.prototype, "parseLabel", null);
|
|
2574
|
+
__legacyDecorateClassTS([
|
|
2575
|
+
Option3({
|
|
2576
|
+
flags: "--limit <n>",
|
|
2577
|
+
description: "Limit results",
|
|
2578
|
+
defaultValue: "20"
|
|
2579
|
+
}),
|
|
2580
|
+
__legacyMetadataTS("design:type", Function),
|
|
2581
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2582
|
+
String
|
|
2583
|
+
]),
|
|
2584
|
+
__legacyMetadataTS("design:returntype", String)
|
|
2585
|
+
], SearchCommand.prototype, "parseLimit", null);
|
|
2586
|
+
SearchCommand = __legacyDecorateClassTS([
|
|
2587
|
+
Injectable12(),
|
|
2588
|
+
Command3({
|
|
2589
|
+
name: "search",
|
|
2590
|
+
arguments: "<query>",
|
|
2591
|
+
description: "Semantic search across the knowledge graph"
|
|
2592
|
+
}),
|
|
2593
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2594
|
+
typeof GraphService === "undefined" ? Object : GraphService,
|
|
2595
|
+
typeof EmbeddingService === "undefined" ? Object : EmbeddingService
|
|
2596
|
+
])
|
|
2597
|
+
], SearchCommand);
|
|
2598
|
+
|
|
2599
|
+
class RelsCommand extends CommandRunner3 {
|
|
2600
|
+
graphService;
|
|
2601
|
+
constructor(graphService) {
|
|
2602
|
+
super();
|
|
2603
|
+
this.graphService = graphService;
|
|
2604
|
+
}
|
|
2605
|
+
async run(inputs) {
|
|
2606
|
+
const name = inputs[0];
|
|
2454
2607
|
try {
|
|
2455
|
-
app = await NestFactory3.createApplicationContext(AppModule, {
|
|
2456
|
-
logger: ["error"]
|
|
2457
|
-
});
|
|
2458
|
-
const graph = app.get(GraphService);
|
|
2459
2608
|
const escapedName = name.replace(/'/g, "\\'");
|
|
2460
2609
|
const cypher = `MATCH (a { name: '${escapedName}' })-[r]-(b) RETURN a, r, b`;
|
|
2461
|
-
const result = await
|
|
2610
|
+
const result = await this.graphService.query(cypher);
|
|
2462
2611
|
const results = result.resultSet || [];
|
|
2463
2612
|
console.log(`
|
|
2464
2613
|
=== Relationships for "${name}" ===
|
|
@@ -2466,7 +2615,6 @@ Note: Semantic search requires embeddings to be generated first.`);
|
|
|
2466
2615
|
if (results.length === 0) {
|
|
2467
2616
|
console.log(`No relationships found.
|
|
2468
2617
|
`);
|
|
2469
|
-
await app.close();
|
|
2470
2618
|
process.exit(0);
|
|
2471
2619
|
}
|
|
2472
2620
|
const incoming = [];
|
|
@@ -2498,59 +2646,84 @@ Note: Semantic search requires embeddings to be generated first.`);
|
|
|
2498
2646
|
incoming.forEach((r) => console.log(r));
|
|
2499
2647
|
}
|
|
2500
2648
|
console.log();
|
|
2501
|
-
await app.close();
|
|
2502
2649
|
process.exit(0);
|
|
2503
2650
|
} catch (error) {
|
|
2504
2651
|
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
2505
|
-
if (app)
|
|
2506
|
-
await app.close();
|
|
2507
2652
|
process.exit(1);
|
|
2508
2653
|
}
|
|
2509
|
-
}
|
|
2510
|
-
|
|
2511
|
-
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
RelsCommand = __legacyDecorateClassTS([
|
|
2657
|
+
Injectable12(),
|
|
2658
|
+
Command3({
|
|
2659
|
+
name: "rels",
|
|
2660
|
+
arguments: "<name>",
|
|
2661
|
+
description: "Show relationships for a node"
|
|
2662
|
+
}),
|
|
2663
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2664
|
+
typeof GraphService === "undefined" ? Object : GraphService
|
|
2665
|
+
])
|
|
2666
|
+
], RelsCommand);
|
|
2667
|
+
|
|
2668
|
+
class CypherCommand extends CommandRunner3 {
|
|
2669
|
+
graphService;
|
|
2670
|
+
constructor(graphService) {
|
|
2671
|
+
super();
|
|
2672
|
+
this.graphService = graphService;
|
|
2673
|
+
}
|
|
2674
|
+
async run(inputs) {
|
|
2675
|
+
const query = inputs[0];
|
|
2512
2676
|
try {
|
|
2513
|
-
|
|
2514
|
-
logger: ["error"]
|
|
2515
|
-
});
|
|
2516
|
-
const graph = app.get(GraphService);
|
|
2517
|
-
const result = await graph.query(query);
|
|
2677
|
+
const result = await this.graphService.query(query);
|
|
2518
2678
|
console.log(`
|
|
2519
2679
|
=== Cypher Query Results ===
|
|
2520
2680
|
`);
|
|
2521
2681
|
console.log(JSON.stringify(result, null, 2));
|
|
2522
2682
|
console.log();
|
|
2523
|
-
await app.close();
|
|
2524
2683
|
process.exit(0);
|
|
2525
2684
|
} catch (error) {
|
|
2526
2685
|
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
2527
|
-
if (app)
|
|
2528
|
-
await app.close();
|
|
2529
2686
|
process.exit(1);
|
|
2530
2687
|
}
|
|
2531
|
-
}
|
|
2532
|
-
|
|
2533
|
-
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
CypherCommand = __legacyDecorateClassTS([
|
|
2691
|
+
Injectable12(),
|
|
2692
|
+
Command3({
|
|
2693
|
+
name: "cypher",
|
|
2694
|
+
arguments: "<query>",
|
|
2695
|
+
description: "Execute raw Cypher query"
|
|
2696
|
+
}),
|
|
2697
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2698
|
+
typeof GraphService === "undefined" ? Object : GraphService
|
|
2699
|
+
])
|
|
2700
|
+
], CypherCommand);
|
|
2701
|
+
|
|
2702
|
+
class RelatedCommand extends CommandRunner3 {
|
|
2703
|
+
graphService;
|
|
2704
|
+
pathResolverService;
|
|
2705
|
+
constructor(graphService, pathResolverService) {
|
|
2706
|
+
super();
|
|
2707
|
+
this.graphService = graphService;
|
|
2708
|
+
this.pathResolverService = pathResolverService;
|
|
2709
|
+
}
|
|
2710
|
+
async run(inputs, options) {
|
|
2711
|
+
const path = inputs[0];
|
|
2712
|
+
const limit = Math.min(parseInt(options.limit || "10", 10), 50);
|
|
2534
2713
|
try {
|
|
2535
|
-
|
|
2536
|
-
logger: ["error"]
|
|
2537
|
-
});
|
|
2538
|
-
const graph = app.get(GraphService);
|
|
2539
|
-
const pathResolver = app.get(PathResolverService);
|
|
2540
|
-
const absolutePath = pathResolver.resolveDocPath(path, {
|
|
2714
|
+
const absolutePath = this.pathResolverService.resolveDocPath(path, {
|
|
2541
2715
|
requireExists: true,
|
|
2542
2716
|
requireInDocs: true
|
|
2543
2717
|
});
|
|
2544
|
-
const limit = Math.min(parseInt(options.limit, 10), 50);
|
|
2545
2718
|
const escapedPath = absolutePath.replace(/'/g, "\\'");
|
|
2546
2719
|
const cypher = `
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
const result = await
|
|
2720
|
+
MATCH (d:Document { name: '${escapedPath}' })<-[:APPEARS_IN]-(e)-[:APPEARS_IN]->(other:Document)
|
|
2721
|
+
WHERE other.name <> '${escapedPath}'
|
|
2722
|
+
RETURN DISTINCT other.name as path, other.title as title, count(e) as shared
|
|
2723
|
+
ORDER BY shared DESC
|
|
2724
|
+
LIMIT ${limit}
|
|
2725
|
+
`;
|
|
2726
|
+
const result = await this.graphService.query(cypher);
|
|
2554
2727
|
const results = result.resultSet || [];
|
|
2555
2728
|
console.log(`
|
|
2556
2729
|
=== Documents Related to "${path}" ===
|
|
@@ -2558,7 +2731,6 @@ Note: Semantic search requires embeddings to be generated first.`);
|
|
|
2558
2731
|
if (results.length === 0) {
|
|
2559
2732
|
console.log(`No related documents found.
|
|
2560
2733
|
`);
|
|
2561
|
-
await app.close();
|
|
2562
2734
|
process.exit(0);
|
|
2563
2735
|
}
|
|
2564
2736
|
results.forEach((row) => {
|
|
@@ -2571,29 +2743,54 @@ Note: Semantic search requires embeddings to be generated first.`);
|
|
|
2571
2743
|
}
|
|
2572
2744
|
});
|
|
2573
2745
|
console.log();
|
|
2574
|
-
await app.close();
|
|
2575
2746
|
process.exit(0);
|
|
2576
2747
|
} catch (error) {
|
|
2577
2748
|
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
2578
|
-
if (app)
|
|
2579
|
-
await app.close();
|
|
2580
2749
|
process.exit(1);
|
|
2581
2750
|
}
|
|
2582
|
-
}
|
|
2751
|
+
}
|
|
2752
|
+
parseLimit(value) {
|
|
2753
|
+
return value;
|
|
2754
|
+
}
|
|
2583
2755
|
}
|
|
2756
|
+
__legacyDecorateClassTS([
|
|
2757
|
+
Option3({
|
|
2758
|
+
flags: "--limit <n>",
|
|
2759
|
+
description: "Limit results",
|
|
2760
|
+
defaultValue: "10"
|
|
2761
|
+
}),
|
|
2762
|
+
__legacyMetadataTS("design:type", Function),
|
|
2763
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2764
|
+
String
|
|
2765
|
+
]),
|
|
2766
|
+
__legacyMetadataTS("design:returntype", String)
|
|
2767
|
+
], RelatedCommand.prototype, "parseLimit", null);
|
|
2768
|
+
RelatedCommand = __legacyDecorateClassTS([
|
|
2769
|
+
Injectable12(),
|
|
2770
|
+
Command3({
|
|
2771
|
+
name: "related",
|
|
2772
|
+
arguments: "<path>",
|
|
2773
|
+
description: "Find documents related to the given document"
|
|
2774
|
+
}),
|
|
2775
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2776
|
+
typeof GraphService === "undefined" ? Object : GraphService,
|
|
2777
|
+
typeof PathResolverService === "undefined" ? Object : PathResolverService
|
|
2778
|
+
])
|
|
2779
|
+
], RelatedCommand);
|
|
2584
2780
|
// src/commands/validate.command.ts
|
|
2585
|
-
import {
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2781
|
+
import { Injectable as Injectable13 } from "@nestjs/common";
|
|
2782
|
+
import { Command as Command4, CommandRunner as CommandRunner4, Option as Option4 } from "nest-commander";
|
|
2783
|
+
class ValidateCommand extends CommandRunner4 {
|
|
2784
|
+
parserService;
|
|
2785
|
+
constructor(parserService) {
|
|
2786
|
+
super();
|
|
2787
|
+
this.parserService = parserService;
|
|
2788
|
+
}
|
|
2789
|
+
async run(_inputs, options) {
|
|
2589
2790
|
try {
|
|
2590
|
-
app = await NestFactory4.createApplicationContext(AppModule, {
|
|
2591
|
-
logger: ["error"]
|
|
2592
|
-
});
|
|
2593
|
-
const parser = app.get(DocumentParserService);
|
|
2594
2791
|
console.log(`Validating entities and relationships...
|
|
2595
2792
|
`);
|
|
2596
|
-
const { docs, errors: schemaErrors } = await
|
|
2793
|
+
const { docs, errors: schemaErrors } = await this.parserService.parseAllDocumentsWithErrors();
|
|
2597
2794
|
const issues = [];
|
|
2598
2795
|
for (const schemaError of schemaErrors) {
|
|
2599
2796
|
issues.push({
|
|
@@ -2638,40 +2835,69 @@ function registerValidateCommand(program) {
|
|
|
2638
2835
|
if (issues.length === 0) {
|
|
2639
2836
|
console.log("All validations passed!");
|
|
2640
2837
|
}
|
|
2641
|
-
await app.close();
|
|
2642
2838
|
process.exit(issues.length > 0 ? 1 : 0);
|
|
2643
2839
|
} catch (error) {
|
|
2644
2840
|
console.error("Validation failed:", error instanceof Error ? error.message : String(error));
|
|
2645
|
-
if (app)
|
|
2646
|
-
await app.close();
|
|
2647
2841
|
process.exit(1);
|
|
2648
2842
|
}
|
|
2649
|
-
}
|
|
2843
|
+
}
|
|
2844
|
+
parseFix() {
|
|
2845
|
+
return true;
|
|
2846
|
+
}
|
|
2650
2847
|
}
|
|
2848
|
+
__legacyDecorateClassTS([
|
|
2849
|
+
Option4({
|
|
2850
|
+
flags: "--fix",
|
|
2851
|
+
description: "Show suggestions for common issues"
|
|
2852
|
+
}),
|
|
2853
|
+
__legacyMetadataTS("design:type", Function),
|
|
2854
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2855
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2856
|
+
], ValidateCommand.prototype, "parseFix", null);
|
|
2857
|
+
ValidateCommand = __legacyDecorateClassTS([
|
|
2858
|
+
Injectable13(),
|
|
2859
|
+
Command4({
|
|
2860
|
+
name: "validate",
|
|
2861
|
+
description: "Validate entity references and relationships across documents"
|
|
2862
|
+
}),
|
|
2863
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2864
|
+
typeof DocumentParserService === "undefined" ? Object : DocumentParserService
|
|
2865
|
+
])
|
|
2866
|
+
], ValidateCommand);
|
|
2651
2867
|
// src/commands/ontology.command.ts
|
|
2652
|
-
import {
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2868
|
+
import { Injectable as Injectable14 } from "@nestjs/common";
|
|
2869
|
+
import { Command as Command5, CommandRunner as CommandRunner5 } from "nest-commander";
|
|
2870
|
+
class OntologyCommand extends CommandRunner5 {
|
|
2871
|
+
ontologyService;
|
|
2872
|
+
constructor(ontologyService) {
|
|
2873
|
+
super();
|
|
2874
|
+
this.ontologyService = ontologyService;
|
|
2875
|
+
}
|
|
2876
|
+
async run() {
|
|
2656
2877
|
try {
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
});
|
|
2660
|
-
const ontologyService = app.get(OntologyService);
|
|
2661
|
-
const ontology = await ontologyService.deriveOntology();
|
|
2662
|
-
ontologyService.printSummary(ontology);
|
|
2663
|
-
await app.close();
|
|
2878
|
+
const ontology = await this.ontologyService.deriveOntology();
|
|
2879
|
+
this.ontologyService.printSummary(ontology);
|
|
2664
2880
|
process.exit(0);
|
|
2665
2881
|
} catch (error) {
|
|
2666
2882
|
console.error(`
|
|
2667
2883
|
\u274C Ontology derivation failed:`, error instanceof Error ? error.message : String(error));
|
|
2668
|
-
if (app)
|
|
2669
|
-
await app.close();
|
|
2670
2884
|
process.exit(1);
|
|
2671
2885
|
}
|
|
2672
|
-
}
|
|
2886
|
+
}
|
|
2673
2887
|
}
|
|
2888
|
+
OntologyCommand = __legacyDecorateClassTS([
|
|
2889
|
+
Injectable14(),
|
|
2890
|
+
Command5({
|
|
2891
|
+
name: "ontology",
|
|
2892
|
+
description: "Derive and display ontology from all documents"
|
|
2893
|
+
}),
|
|
2894
|
+
__legacyMetadataTS("design:paramtypes", [
|
|
2895
|
+
typeof OntologyService === "undefined" ? Object : OntologyService
|
|
2896
|
+
])
|
|
2897
|
+
], OntologyCommand);
|
|
2674
2898
|
// src/commands/init.command.ts
|
|
2899
|
+
import { Injectable as Injectable15 } from "@nestjs/common";
|
|
2900
|
+
import { Command as Command6, CommandRunner as CommandRunner6, Option as Option5 } from "nest-commander";
|
|
2675
2901
|
import * as fs from "fs/promises";
|
|
2676
2902
|
import * as path from "path";
|
|
2677
2903
|
import { fileURLToPath } from "url";
|
|
@@ -2679,8 +2905,9 @@ import { homedir } from "os";
|
|
|
2679
2905
|
var __filename2 = fileURLToPath(import.meta.url);
|
|
2680
2906
|
var __dirname2 = path.dirname(__filename2);
|
|
2681
2907
|
var COMMANDS = ["research.md", "graph-sync.md", "entity-extract.md"];
|
|
2682
|
-
|
|
2683
|
-
|
|
2908
|
+
|
|
2909
|
+
class InitCommand extends CommandRunner6 {
|
|
2910
|
+
async run(_inputs, options) {
|
|
2684
2911
|
try {
|
|
2685
2912
|
const targetDir = options.global ? path.join(homedir(), ".claude", "commands") : path.join(process.cwd(), ".claude", "commands");
|
|
2686
2913
|
let commandsSourceDir = path.resolve(__dirname2, "..", "commands");
|
|
@@ -2748,17 +2975,61 @@ function registerInitCommand(program) {
|
|
|
2748
2975
|
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
2749
2976
|
process.exit(1);
|
|
2750
2977
|
}
|
|
2751
|
-
}
|
|
2978
|
+
}
|
|
2979
|
+
parseGlobal() {
|
|
2980
|
+
return true;
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
__legacyDecorateClassTS([
|
|
2984
|
+
Option5({
|
|
2985
|
+
flags: "-g, --global",
|
|
2986
|
+
description: "Install to ~/.claude/commands/ (available in all projects)"
|
|
2987
|
+
}),
|
|
2988
|
+
__legacyMetadataTS("design:type", Function),
|
|
2989
|
+
__legacyMetadataTS("design:paramtypes", []),
|
|
2990
|
+
__legacyMetadataTS("design:returntype", Boolean)
|
|
2991
|
+
], InitCommand.prototype, "parseGlobal", null);
|
|
2992
|
+
InitCommand = __legacyDecorateClassTS([
|
|
2993
|
+
Injectable15(),
|
|
2994
|
+
Command6({
|
|
2995
|
+
name: "init",
|
|
2996
|
+
description: "Install Claude Code slash commands for Lattice"
|
|
2997
|
+
})
|
|
2998
|
+
], InitCommand);
|
|
2999
|
+
// src/app.module.ts
|
|
3000
|
+
class AppModule {
|
|
2752
3001
|
}
|
|
3002
|
+
AppModule = __legacyDecorateClassTS([
|
|
3003
|
+
Module5({
|
|
3004
|
+
imports: [
|
|
3005
|
+
ConfigModule2.forRoot({
|
|
3006
|
+
isGlobal: true
|
|
3007
|
+
}),
|
|
3008
|
+
GraphModule,
|
|
3009
|
+
SyncModule,
|
|
3010
|
+
EmbeddingModule,
|
|
3011
|
+
QueryModule
|
|
3012
|
+
],
|
|
3013
|
+
providers: [
|
|
3014
|
+
SyncCommand,
|
|
3015
|
+
StatusCommand,
|
|
3016
|
+
StatsCommand,
|
|
3017
|
+
SearchCommand,
|
|
3018
|
+
RelsCommand,
|
|
3019
|
+
CypherCommand,
|
|
3020
|
+
RelatedCommand,
|
|
3021
|
+
ValidateCommand,
|
|
3022
|
+
OntologyCommand,
|
|
3023
|
+
InitCommand
|
|
3024
|
+
]
|
|
3025
|
+
})
|
|
3026
|
+
], AppModule);
|
|
3027
|
+
|
|
2753
3028
|
// src/main.ts
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
registerSyncCommand(program);
|
|
2757
|
-
registerStatusCommand(program);
|
|
2758
|
-
registerQueryCommands(program);
|
|
2759
|
-
registerValidateCommand(program);
|
|
2760
|
-
registerOntologyCommand(program);
|
|
2761
|
-
program.parse(process.argv);
|
|
2762
|
-
if (!process.argv.slice(2).length) {
|
|
2763
|
-
program.outputHelp();
|
|
3029
|
+
async function bootstrap() {
|
|
3030
|
+
await CommandFactory.run(AppModule, ["error"]);
|
|
2764
3031
|
}
|
|
3032
|
+
bootstrap().catch((err) => {
|
|
3033
|
+
console.error("\u274C CLI failed:", err);
|
|
3034
|
+
process.exit(1);
|
|
3035
|
+
});
|