gitnexus 1.4.8 → 1.4.10
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/README.md +7 -0
- package/dist/cli/index-repo.d.ts +15 -0
- package/dist/cli/index-repo.js +115 -0
- package/dist/cli/index.js +11 -2
- package/dist/cli/setup.js +12 -9
- package/dist/cli/wiki.d.ts +4 -0
- package/dist/cli/wiki.js +174 -53
- package/dist/config/supported-languages.d.ts +7 -5
- package/dist/config/supported-languages.js +6 -4
- package/dist/core/graph/graph.js +9 -1
- package/dist/core/graph/types.d.ts +10 -2
- package/dist/core/ingestion/call-processor.d.ts +18 -1
- package/dist/core/ingestion/call-processor.js +297 -38
- package/dist/core/ingestion/call-routing.d.ts +3 -18
- package/dist/core/ingestion/call-routing.js +0 -19
- package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
- package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
- package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
- package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
- package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
- package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
- package/dist/core/ingestion/cobol-processor.d.ts +54 -0
- package/dist/core/ingestion/cobol-processor.js +1186 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
- package/dist/core/ingestion/entry-point-scoring.js +18 -4
- package/dist/core/ingestion/export-detection.d.ts +47 -8
- package/dist/core/ingestion/export-detection.js +29 -50
- package/dist/core/ingestion/field-extractor.d.ts +29 -0
- package/dist/core/ingestion/field-extractor.js +25 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
- package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
- package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
- package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
- package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
- package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
- package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
- package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
- package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
- package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
- package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
- package/dist/core/ingestion/field-extractors/generic.js +111 -0
- package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
- package/dist/core/ingestion/field-extractors/typescript.js +291 -0
- package/dist/core/ingestion/field-types.d.ts +59 -0
- package/dist/core/ingestion/field-types.js +2 -0
- package/dist/core/ingestion/framework-detection.d.ts +87 -0
- package/dist/core/ingestion/framework-detection.js +65 -2
- package/dist/core/ingestion/heritage-processor.js +15 -17
- package/dist/core/ingestion/import-processor.d.ts +9 -10
- package/dist/core/ingestion/import-processor.js +59 -14
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
- package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/dart.js +44 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +9 -1
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.js +56 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/php.d.ts +6 -10
- package/dist/core/ingestion/{resolvers → import-resolvers}/php.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
- package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/swift.js +23 -0
- package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
- package/dist/core/ingestion/import-resolvers/types.js +6 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +0 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +0 -9
- package/dist/core/ingestion/language-config.d.ts +4 -1
- package/dist/core/ingestion/language-provider.d.ts +121 -0
- package/dist/core/ingestion/language-provider.js +24 -0
- package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
- package/dist/core/ingestion/languages/c-cpp.js +71 -0
- package/dist/core/ingestion/languages/cobol.d.ts +1 -0
- package/dist/core/ingestion/languages/cobol.js +26 -0
- package/dist/core/ingestion/languages/csharp.d.ts +8 -0
- package/dist/core/ingestion/languages/csharp.js +49 -0
- package/dist/core/ingestion/languages/dart.d.ts +12 -0
- package/dist/core/ingestion/languages/dart.js +58 -0
- package/dist/core/ingestion/languages/go.d.ts +11 -0
- package/dist/core/ingestion/languages/go.js +28 -0
- package/dist/core/ingestion/languages/index.d.ts +38 -0
- package/dist/core/ingestion/languages/index.js +63 -0
- package/dist/core/ingestion/languages/java.d.ts +9 -0
- package/dist/core/ingestion/languages/java.js +29 -0
- package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
- package/dist/core/ingestion/languages/kotlin.js +53 -0
- package/dist/core/ingestion/languages/php.d.ts +8 -0
- package/dist/core/ingestion/languages/php.js +145 -0
- package/dist/core/ingestion/languages/python.d.ts +12 -0
- package/dist/core/ingestion/languages/python.js +39 -0
- package/dist/core/ingestion/languages/ruby.d.ts +9 -0
- package/dist/core/ingestion/languages/ruby.js +44 -0
- package/dist/core/ingestion/languages/rust.d.ts +12 -0
- package/dist/core/ingestion/languages/rust.js +44 -0
- package/dist/core/ingestion/languages/swift.d.ts +12 -0
- package/dist/core/ingestion/languages/swift.js +133 -0
- package/dist/core/ingestion/languages/typescript.d.ts +10 -0
- package/dist/core/ingestion/languages/typescript.js +60 -0
- package/dist/core/ingestion/mro-processor.js +14 -15
- package/dist/core/ingestion/{named-binding-extraction.d.ts → named-binding-processor.d.ts} +0 -9
- package/dist/core/ingestion/named-binding-processor.js +42 -0
- package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/csharp.js +37 -0
- package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/java.js +29 -0
- package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
- package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/php.js +61 -0
- package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/python.js +49 -0
- package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/rust.js +64 -0
- package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
- package/dist/core/ingestion/named-bindings/types.js +6 -0
- package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/typescript.js +58 -0
- package/dist/core/ingestion/parsing-processor.d.ts +5 -1
- package/dist/core/ingestion/parsing-processor.js +115 -16
- package/dist/core/ingestion/pipeline.js +925 -424
- package/dist/core/ingestion/resolution-context.js +1 -1
- package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
- package/dist/core/ingestion/route-extractors/expo.js +36 -0
- package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
- package/dist/core/ingestion/route-extractors/middleware.js +143 -0
- package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
- package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
- package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
- package/dist/core/ingestion/route-extractors/php.js +21 -0
- package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
- package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
- package/dist/core/ingestion/tree-sitter-queries.d.ts +8 -7
- package/dist/core/ingestion/tree-sitter-queries.js +231 -9
- package/dist/core/ingestion/type-env.d.ts +14 -17
- package/dist/core/ingestion/type-env.js +66 -14
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +1 -1
- package/dist/core/ingestion/type-extractors/csharp.js +1 -1
- package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
- package/dist/core/ingestion/type-extractors/dart.js +371 -0
- package/dist/core/ingestion/type-extractors/jvm.js +1 -1
- package/dist/core/ingestion/type-extractors/shared.d.ts +1 -13
- package/dist/core/ingestion/type-extractors/shared.js +9 -102
- package/dist/core/ingestion/type-extractors/swift.js +334 -4
- package/dist/core/ingestion/type-extractors/types.d.ts +3 -1
- package/dist/core/ingestion/{ast-helpers.d.ts → utils/ast-helpers.d.ts} +16 -13
- package/dist/core/ingestion/{ast-helpers.js → utils/ast-helpers.js} +111 -32
- package/dist/core/ingestion/{call-analysis.js → utils/call-analysis.js} +37 -0
- package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
- package/dist/core/ingestion/utils/event-loop.js +5 -0
- package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
- package/dist/core/ingestion/utils/language-detection.js +70 -0
- package/dist/core/ingestion/utils/verbose.d.ts +1 -0
- package/dist/core/ingestion/utils/verbose.js +7 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +43 -2
- package/dist/core/ingestion/workers/parse-worker.js +361 -150
- package/dist/core/lbug/csv-generator.js +34 -1
- package/dist/core/lbug/lbug-adapter.js +6 -0
- package/dist/core/lbug/schema.d.ts +5 -3
- package/dist/core/lbug/schema.js +39 -2
- package/dist/core/tree-sitter/parser-loader.js +7 -1
- package/dist/core/wiki/cursor-client.d.ts +31 -0
- package/dist/core/wiki/cursor-client.js +127 -0
- package/dist/core/wiki/generator.d.ts +28 -9
- package/dist/core/wiki/generator.js +115 -18
- package/dist/core/wiki/graph-queries.d.ts +4 -0
- package/dist/core/wiki/graph-queries.js +7 -1
- package/dist/core/wiki/llm-client.d.ts +2 -0
- package/dist/core/wiki/llm-client.js +8 -4
- package/dist/core/wiki/prompts.d.ts +3 -3
- package/dist/core/wiki/prompts.js +6 -0
- package/dist/mcp/core/lbug-adapter.d.ts +5 -0
- package/dist/mcp/core/lbug-adapter.js +11 -1
- package/dist/mcp/local/local-backend.d.ts +16 -5
- package/dist/mcp/local/local-backend.js +711 -74
- package/dist/mcp/tools.js +71 -2
- package/dist/storage/repo-manager.d.ts +3 -0
- package/package.json +14 -14
- package/dist/core/ingestion/import-resolution.d.ts +0 -101
- package/dist/core/ingestion/import-resolution.js +0 -251
- package/dist/core/ingestion/named-binding-extraction.js +0 -373
- package/dist/core/ingestion/resolvers/index.d.ts +0 -18
- package/dist/core/ingestion/resolvers/index.js +0 -13
- package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
- package/dist/core/ingestion/type-extractors/index.js +0 -31
- package/dist/core/ingestion/utils.d.ts +0 -20
- package/dist/core/ingestion/utils.js +0 -242
- package/scripts/patch-tree-sitter-swift.cjs +0 -74
- /package/dist/core/ingestion/{call-analysis.d.ts → utils/call-analysis.d.ts} +0 -0
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
import fs from 'fs/promises';
|
|
13
13
|
import path from 'path';
|
|
14
14
|
import { execSync, execFileSync } from 'child_process';
|
|
15
|
-
import { initWikiDb, closeWikiDb, getFilesWithExports, getAllFiles, getIntraModuleCallEdges, getInterModuleCallEdges, getProcessesForFiles, getAllProcesses, getInterModuleEdgesForOverview, } from './graph-queries.js';
|
|
15
|
+
import { initWikiDb, closeWikiDb, touchWikiDb, getFilesWithExports, getAllFiles, getIntraModuleCallEdges, getInterModuleCallEdges, getProcessesForFiles, getAllProcesses, getInterModuleEdgesForOverview, } from './graph-queries.js';
|
|
16
16
|
import { generateHTMLViewer } from './html-viewer.js';
|
|
17
17
|
import { callLLM, estimateTokens, } from './llm-client.js';
|
|
18
|
+
import { callCursorLLM, resolveCursorConfig, } from './cursor-client.js';
|
|
18
19
|
import { GROUPING_SYSTEM_PROMPT, GROUPING_USER_PROMPT, MODULE_SYSTEM_PROMPT, MODULE_USER_PROMPT, PARENT_SYSTEM_PROMPT, PARENT_USER_PROMPT, OVERVIEW_SYSTEM_PROMPT, OVERVIEW_USER_PROMPT, fillTemplate, formatFileListForGrouping, formatDirectoryTree, formatCallEdges, formatProcesses, } from './prompts.js';
|
|
19
20
|
import { shouldIgnorePath } from '../../config/ignore-service.js';
|
|
20
21
|
// ─── Constants ────────────────────────────────────────────────────────
|
|
@@ -51,17 +52,55 @@ export class WikiGenerator {
|
|
|
51
52
|
lastPercent = 0;
|
|
52
53
|
/**
|
|
53
54
|
* Create streaming options that report LLM progress to the progress bar.
|
|
54
|
-
*
|
|
55
|
+
*
|
|
56
|
+
* Progress calculation:
|
|
57
|
+
* - If fixedPercent is provided, we show incremental progress within that phase
|
|
58
|
+
* based on token generation (e.g., grouping at 15% → 15-28%)
|
|
59
|
+
* - If fixedPercent is NOT provided, we only update the label with token count
|
|
60
|
+
* but keep the current percentage (avoids fluctuation during module generation)
|
|
61
|
+
*
|
|
62
|
+
* Also touches the DB connection periodically to prevent idle timeout.
|
|
55
63
|
*/
|
|
56
|
-
streamOpts(label, fixedPercent) {
|
|
64
|
+
streamOpts(label, fixedPercent, percentRange = 10) {
|
|
65
|
+
const hasFixedStart = fixedPercent !== undefined;
|
|
66
|
+
const startPercent = fixedPercent ?? this.lastPercent;
|
|
67
|
+
const expectedTokens = 2000;
|
|
68
|
+
let lastTouch = Date.now();
|
|
57
69
|
return {
|
|
58
70
|
onChunk: (chars) => {
|
|
59
71
|
const tokens = Math.round(chars / 4);
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
if (hasFixedStart) {
|
|
73
|
+
// For fixed phases (like grouping), show incremental progress
|
|
74
|
+
const progress = Math.min(1, tokens / expectedTokens);
|
|
75
|
+
const pct = Math.round(startPercent + (progress * percentRange));
|
|
76
|
+
this.onProgress('stream', pct, `${label} (${tokens} tok)`);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
// For module generation, only update the label, keep current percent
|
|
80
|
+
this.onProgress('stream', this.lastPercent, `${label} (${tokens} tok)`);
|
|
81
|
+
}
|
|
82
|
+
// Touch DB every 60s to prevent idle timeout during long LLM calls
|
|
83
|
+
const now = Date.now();
|
|
84
|
+
if (now - lastTouch > 60_000) {
|
|
85
|
+
touchWikiDb();
|
|
86
|
+
lastTouch = now;
|
|
87
|
+
}
|
|
62
88
|
},
|
|
63
89
|
};
|
|
64
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Route LLM call to the appropriate provider (OpenAI-compatible or Cursor CLI).
|
|
93
|
+
*/
|
|
94
|
+
async invokeLLM(prompt, systemPrompt, options) {
|
|
95
|
+
if (this.llmConfig.provider === 'cursor') {
|
|
96
|
+
const cursorConfig = resolveCursorConfig({
|
|
97
|
+
model: this.llmConfig.model,
|
|
98
|
+
workingDirectory: this.repoPath,
|
|
99
|
+
});
|
|
100
|
+
return callCursorLLM(prompt, cursorConfig, systemPrompt, options);
|
|
101
|
+
}
|
|
102
|
+
return callLLM(prompt, this.llmConfig, systemPrompt, options);
|
|
103
|
+
}
|
|
65
104
|
/**
|
|
66
105
|
* Main entry point. Runs the full pipeline or incremental update.
|
|
67
106
|
*/
|
|
@@ -144,6 +183,13 @@ export class WikiGenerator {
|
|
|
144
183
|
// Phase 1: Build module tree
|
|
145
184
|
const moduleTree = await this.buildModuleTree(enrichedFiles);
|
|
146
185
|
pagesGenerated = 0;
|
|
186
|
+
// If reviewOnly mode, save tree and stop for user to review/edit
|
|
187
|
+
if (this.options.reviewOnly) {
|
|
188
|
+
await this.saveModuleTree(moduleTree);
|
|
189
|
+
this.onProgress('review', 30, 'Module tree ready for review');
|
|
190
|
+
const reviewResult = { pagesGenerated: 0, mode: 'full', failedModules: [], moduleTree };
|
|
191
|
+
return reviewResult;
|
|
192
|
+
}
|
|
147
193
|
// Phase 2: Generate module pages (parallel with concurrency limit)
|
|
148
194
|
const totalModules = this.countModules(moduleTree);
|
|
149
195
|
let modulesProcessed = 0;
|
|
@@ -213,6 +259,19 @@ export class WikiGenerator {
|
|
|
213
259
|
}
|
|
214
260
|
// ─── Phase 1: Build Module Tree ────────────────────────────────────
|
|
215
261
|
async buildModuleTree(files) {
|
|
262
|
+
// First, check for user-edited module_tree.json (from --review workflow)
|
|
263
|
+
const editablePath = path.join(this.wikiDir, 'module_tree.json');
|
|
264
|
+
try {
|
|
265
|
+
const edited = await fs.readFile(editablePath, 'utf-8');
|
|
266
|
+
const parsed = JSON.parse(edited);
|
|
267
|
+
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
268
|
+
this.onProgress('grouping', 25, 'Using edited module tree');
|
|
269
|
+
return parsed;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
// No edited tree, check for original snapshot
|
|
274
|
+
}
|
|
216
275
|
// Check for existing immutable snapshot (resumability)
|
|
217
276
|
const snapshotPath = path.join(this.wikiDir, 'first_module_tree.json');
|
|
218
277
|
try {
|
|
@@ -233,7 +292,7 @@ export class WikiGenerator {
|
|
|
233
292
|
FILE_LIST: fileList,
|
|
234
293
|
DIRECTORY_TREE: dirTree,
|
|
235
294
|
});
|
|
236
|
-
const response = await
|
|
295
|
+
const response = await this.invokeLLM(prompt, GROUPING_SYSTEM_PROMPT, this.streamOpts('Grouping files', 15, 13));
|
|
237
296
|
const grouping = this.parseGroupingResponse(response.content, files);
|
|
238
297
|
// Convert to tree nodes
|
|
239
298
|
const tree = [];
|
|
@@ -243,8 +302,14 @@ export class WikiGenerator {
|
|
|
243
302
|
// Token budget check — split if too large
|
|
244
303
|
const totalTokens = await this.estimateModuleTokens(modulePaths);
|
|
245
304
|
if (totalTokens > this.maxTokensPerModule && modulePaths.length > 3) {
|
|
246
|
-
|
|
247
|
-
|
|
305
|
+
const children = this.splitBySubdirectory(moduleName, modulePaths);
|
|
306
|
+
// Only create hierarchy if we actually got multiple children
|
|
307
|
+
// If splitting results in 1 child, keep files flat (avoid redundant nesting)
|
|
308
|
+
if (children.length > 1) {
|
|
309
|
+
node.children = children;
|
|
310
|
+
node.files = []; // Parent doesn't own files directly when split
|
|
311
|
+
}
|
|
312
|
+
// If only 1 child, keep original flat structure (files stay in node.files)
|
|
248
313
|
}
|
|
249
314
|
tree.push(node);
|
|
250
315
|
}
|
|
@@ -322,12 +387,13 @@ export class WikiGenerator {
|
|
|
322
387
|
}
|
|
323
388
|
/**
|
|
324
389
|
* Split a large module into sub-modules by subdirectory.
|
|
390
|
+
* Uses the full subDir path for naming to avoid slug collisions
|
|
391
|
+
* (e.g., "synapse-screen/src" vs "synapse-core/src").
|
|
325
392
|
*/
|
|
326
393
|
splitBySubdirectory(moduleName, files) {
|
|
327
394
|
const subGroups = new Map();
|
|
328
395
|
for (const fp of files) {
|
|
329
396
|
const parts = fp.replace(/\\/g, '/').split('/');
|
|
330
|
-
// Use the deepest common-ish directory
|
|
331
397
|
const subDir = parts.length > 2 ? parts.slice(0, 2).join('/') : parts[0];
|
|
332
398
|
let group = subGroups.get(subDir);
|
|
333
399
|
if (!group) {
|
|
@@ -336,11 +402,17 @@ export class WikiGenerator {
|
|
|
336
402
|
}
|
|
337
403
|
group.push(fp);
|
|
338
404
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
405
|
+
// Check if basenames are unique; if not, use the full subDir path
|
|
406
|
+
const basenames = Array.from(subGroups.keys()).map(s => path.basename(s));
|
|
407
|
+
const hasCollisions = new Set(basenames).size < basenames.length;
|
|
408
|
+
return Array.from(subGroups.entries()).map(([subDir, subFiles]) => {
|
|
409
|
+
const label = hasCollisions ? subDir.replace(/\//g, '-') : path.basename(subDir);
|
|
410
|
+
return {
|
|
411
|
+
name: `${moduleName} — ${label}`,
|
|
412
|
+
slug: this.slugify(`${moduleName}-${label}`),
|
|
413
|
+
files: subFiles,
|
|
414
|
+
};
|
|
415
|
+
});
|
|
344
416
|
}
|
|
345
417
|
// ─── Phase 2: Generate Module Pages ─────────────────────────────────
|
|
346
418
|
/**
|
|
@@ -370,7 +442,7 @@ export class WikiGenerator {
|
|
|
370
442
|
INCOMING_CALLS: formatCallEdges(interCalls.incoming),
|
|
371
443
|
PROCESSES: formatProcesses(processes),
|
|
372
444
|
});
|
|
373
|
-
const response = await
|
|
445
|
+
const response = await this.invokeLLM(prompt, MODULE_SYSTEM_PROMPT, this.streamOpts(node.name));
|
|
374
446
|
// Write page with front matter
|
|
375
447
|
const pageContent = `# ${node.name}\n\n${response.content}`;
|
|
376
448
|
await fs.writeFile(path.join(this.wikiDir, `${node.slug}.md`), pageContent, 'utf-8');
|
|
@@ -406,7 +478,7 @@ export class WikiGenerator {
|
|
|
406
478
|
CROSS_MODULE_CALLS: formatCallEdges(crossCalls),
|
|
407
479
|
CROSS_PROCESSES: formatProcesses(processes),
|
|
408
480
|
});
|
|
409
|
-
const response = await
|
|
481
|
+
const response = await this.invokeLLM(prompt, PARENT_SYSTEM_PROMPT, this.streamOpts(node.name));
|
|
410
482
|
const pageContent = `# ${node.name}\n\n${response.content}`;
|
|
411
483
|
await fs.writeFile(path.join(this.wikiDir, `${node.slug}.md`), pageContent, 'utf-8');
|
|
412
484
|
}
|
|
@@ -442,7 +514,7 @@ export class WikiGenerator {
|
|
|
442
514
|
MODULE_EDGES: edgesText,
|
|
443
515
|
TOP_PROCESSES: formatProcesses(topProcesses),
|
|
444
516
|
});
|
|
445
|
-
const response = await
|
|
517
|
+
const response = await this.invokeLLM(prompt, OVERVIEW_SYSTEM_PROMPT, this.streamOpts('Generating overview', 88));
|
|
446
518
|
const pageContent = `# ${path.basename(this.repoPath)} — Wiki\n\n${response.content}`;
|
|
447
519
|
await fs.writeFile(path.join(this.wikiDir, 'overview.md'), pageContent, 'utf-8');
|
|
448
520
|
}
|
|
@@ -451,6 +523,13 @@ export class WikiGenerator {
|
|
|
451
523
|
this.onProgress('incremental', 5, 'Detecting changes...');
|
|
452
524
|
// Get changed files since last generation
|
|
453
525
|
const changedFiles = this.getChangedFiles(existingMeta.fromCommit, currentCommit);
|
|
526
|
+
// If null, commits are on divergent branches (e.g., wiki generated on feature branch,
|
|
527
|
+
// now running on main). Fall back to full generation.
|
|
528
|
+
if (changedFiles === null) {
|
|
529
|
+
this.onProgress('incremental', 10, 'Branch diverged, running full generation...');
|
|
530
|
+
const fullResult = await this.fullGeneration(currentCommit);
|
|
531
|
+
return { ...fullResult, mode: 'incremental' };
|
|
532
|
+
}
|
|
454
533
|
if (changedFiles.length === 0) {
|
|
455
534
|
// No file changes but commit differs (e.g. merge commit)
|
|
456
535
|
await this.saveWikiMeta({
|
|
@@ -559,13 +638,31 @@ export class WikiGenerator {
|
|
|
559
638
|
return '';
|
|
560
639
|
}
|
|
561
640
|
}
|
|
641
|
+
/**
|
|
642
|
+
* Check if fromCommit is an ancestor of toCommit (reachable in git history).
|
|
643
|
+
* Returns false if commits are on divergent branches or fromCommit doesn't exist.
|
|
644
|
+
*/
|
|
645
|
+
isCommitReachable(fromCommit, toCommit) {
|
|
646
|
+
try {
|
|
647
|
+
execFileSync('git', ['merge-base', '--is-ancestor', fromCommit, toCommit], { cwd: this.repoPath, stdio: 'ignore' });
|
|
648
|
+
return true;
|
|
649
|
+
}
|
|
650
|
+
catch {
|
|
651
|
+
return false;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
562
654
|
getChangedFiles(fromCommit, toCommit) {
|
|
655
|
+
// First check if fromCommit is reachable from toCommit
|
|
656
|
+
// This handles the case where wiki was generated on a different branch
|
|
657
|
+
if (!this.isCommitReachable(fromCommit, toCommit)) {
|
|
658
|
+
return null; // Signal that we can't compute diff (divergent branches)
|
|
659
|
+
}
|
|
563
660
|
try {
|
|
564
661
|
const output = execFileSync('git', ['diff', `${fromCommit}..${toCommit}`, '--name-only'], { cwd: this.repoPath }).toString().trim();
|
|
565
662
|
return output ? output.split('\n').filter(Boolean) : [];
|
|
566
663
|
}
|
|
567
664
|
catch {
|
|
568
|
-
return
|
|
665
|
+
return null; // Treat git errors as needing full regen
|
|
569
666
|
}
|
|
570
667
|
}
|
|
571
668
|
async readSourceFiles(filePaths) {
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
* Encapsulated Cypher queries against the GitNexus knowledge graph.
|
|
5
5
|
* Uses the MCP-style pooled lbug-adapter for connection management.
|
|
6
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* Touch the wiki DB connection to prevent idle timeout during long LLM calls.
|
|
9
|
+
*/
|
|
10
|
+
export declare function touchWikiDb(): void;
|
|
7
11
|
export interface FileWithExports {
|
|
8
12
|
filePath: string;
|
|
9
13
|
symbols: Array<{
|
|
@@ -4,8 +4,14 @@
|
|
|
4
4
|
* Encapsulated Cypher queries against the GitNexus knowledge graph.
|
|
5
5
|
* Uses the MCP-style pooled lbug-adapter for connection management.
|
|
6
6
|
*/
|
|
7
|
-
import { initLbug, executeQuery, closeLbug } from '../../mcp/core/lbug-adapter.js';
|
|
7
|
+
import { initLbug, executeQuery, closeLbug, touchRepo } from '../../mcp/core/lbug-adapter.js';
|
|
8
8
|
const REPO_ID = '__wiki__';
|
|
9
|
+
/**
|
|
10
|
+
* Touch the wiki DB connection to prevent idle timeout during long LLM calls.
|
|
11
|
+
*/
|
|
12
|
+
export function touchWikiDb() {
|
|
13
|
+
touchRepo(REPO_ID);
|
|
14
|
+
}
|
|
9
15
|
/**
|
|
10
16
|
* Initialize the LadybugDB connection for wiki generation.
|
|
11
17
|
*/
|
|
@@ -6,12 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Config priority: CLI flags > env vars > defaults
|
|
8
8
|
*/
|
|
9
|
+
export type LLMProvider = 'openai' | 'cursor';
|
|
9
10
|
export interface LLMConfig {
|
|
10
11
|
apiKey: string;
|
|
11
12
|
baseUrl: string;
|
|
12
13
|
model: string;
|
|
13
14
|
maxTokens: number;
|
|
14
15
|
temperature: number;
|
|
16
|
+
provider?: LLMProvider;
|
|
15
17
|
}
|
|
16
18
|
export interface LLMResponse {
|
|
17
19
|
content: string;
|
|
@@ -15,23 +15,27 @@
|
|
|
15
15
|
export async function resolveLLMConfig(overrides) {
|
|
16
16
|
const { loadCLIConfig } = await import('../../storage/repo-manager.js');
|
|
17
17
|
const savedConfig = await loadCLIConfig();
|
|
18
|
+
const provider = overrides?.provider || savedConfig.provider || 'openai';
|
|
18
19
|
const apiKey = overrides?.apiKey
|
|
19
20
|
|| process.env.GITNEXUS_API_KEY
|
|
20
21
|
|| process.env.OPENAI_API_KEY
|
|
21
22
|
|| savedConfig.apiKey
|
|
22
23
|
|| '';
|
|
24
|
+
// For cursor provider, only use model if explicitly provided (default is 'auto' handled by CLI)
|
|
25
|
+
// For openai provider, use model with fallback to default
|
|
26
|
+
const model = provider === 'cursor'
|
|
27
|
+
? (overrides?.model || savedConfig.cursorModel || '')
|
|
28
|
+
: (overrides?.model || process.env.GITNEXUS_MODEL || savedConfig.model || 'minimax/minimax-m2.5');
|
|
23
29
|
return {
|
|
24
30
|
apiKey,
|
|
25
31
|
baseUrl: overrides?.baseUrl
|
|
26
32
|
|| process.env.GITNEXUS_LLM_BASE_URL
|
|
27
33
|
|| savedConfig.baseUrl
|
|
28
34
|
|| 'https://openrouter.ai/api/v1',
|
|
29
|
-
model
|
|
30
|
-
|| process.env.GITNEXUS_MODEL
|
|
31
|
-
|| savedConfig.model
|
|
32
|
-
|| 'minimax/minimax-m2.5',
|
|
35
|
+
model,
|
|
33
36
|
maxTokens: overrides?.maxTokens ?? 16_384,
|
|
34
37
|
temperature: overrides?.temperature ?? 0,
|
|
38
|
+
provider,
|
|
35
39
|
};
|
|
36
40
|
}
|
|
37
41
|
/**
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export declare const GROUPING_SYSTEM_PROMPT = "You are a documentation architect. Given a list of source files with their exported symbols, group them into logical documentation modules.\n\nRules:\n- Each module should represent a cohesive feature, layer, or domain\n- Every file must appear in exactly one module\n- Module names should be human-readable (e.g. \"Authentication\", \"Database Layer\", \"API Routes\")\n- Aim for 5-15 modules for a typical project. Fewer for small projects, more for large ones\n- Group by functionality, not by file type or directory structure alone\n- Do NOT create modules for tests, configs, or non-source files";
|
|
8
8
|
export declare const GROUPING_USER_PROMPT = "Group these source files into documentation modules.\n\n**Files and their exports:**\n{{FILE_LIST}}\n\n**Directory structure:**\n{{DIRECTORY_TREE}}\n\nRespond with ONLY a JSON object mapping module names to file path arrays. No markdown, no explanation.\nExample format:\n{\n \"Authentication\": [\"src/auth/login.ts\", \"src/auth/session.ts\"],\n \"Database\": [\"src/db/connection.ts\", \"src/db/models.ts\"]\n}";
|
|
9
|
-
export declare const MODULE_SYSTEM_PROMPT = "You are a technical documentation writer. Write clear, developer-focused documentation for a code module.\n\nRules:\n- Reference actual function names, class names, and code patterns \u2014 do NOT invent APIs\n- Use the call graph and execution flow data for accuracy, but do NOT mechanically list every edge\n- Include Mermaid diagrams only when they genuinely help understanding. Keep them small (5-10 nodes max)\n- Structure the document however makes sense for this module \u2014 there is no mandatory format\n- Write for a developer who needs to understand and contribute to this code";
|
|
9
|
+
export declare const MODULE_SYSTEM_PROMPT = "You are a technical documentation writer. Write clear, developer-focused documentation for a code module.\n\nRules:\n- Output ONLY the documentation content \u2014 no meta-commentary like \"I've written...\", \"Here's the documentation...\", \"The documentation covers...\", or similar\n- Start directly with the module heading and content\n- Reference actual function names, class names, and code patterns \u2014 do NOT invent APIs\n- Use the call graph and execution flow data for accuracy, but do NOT mechanically list every edge\n- Include Mermaid diagrams only when they genuinely help understanding. Keep them small (5-10 nodes max)\n- Structure the document however makes sense for this module \u2014 there is no mandatory format\n- Write for a developer who needs to understand and contribute to this code";
|
|
10
10
|
export declare const MODULE_USER_PROMPT = "Write documentation for the **{{MODULE_NAME}}** module.\n\n## Source Code\n\n{{SOURCE_CODE}}\n\n## Call Graph & Execution Flows (reference for accuracy)\n\nInternal calls: {{INTRA_CALLS}}\nOutgoing calls: {{OUTGOING_CALLS}}\nIncoming calls: {{INCOMING_CALLS}}\nExecution flows: {{PROCESSES}}\n\n---\n\nWrite comprehensive documentation for this module. Cover its purpose, how it works, its key components, and how it connects to the rest of the codebase. Use whatever structure best fits this module \u2014 you decide the sections and headings. Include a Mermaid diagram only if it genuinely clarifies the architecture.";
|
|
11
|
-
export declare const PARENT_SYSTEM_PROMPT = "You are a technical documentation writer. Write a summary page for a module that contains sub-modules. Synthesize the children's documentation \u2014 do not re-read source code.\n\nRules:\n- Reference actual components from the child modules\n- Focus on how the sub-modules work together, not repeating their individual docs\n- Keep it concise \u2014 the reader can click through to child pages for detail\n- Include a Mermaid diagram only if it genuinely clarifies how the sub-modules relate";
|
|
11
|
+
export declare const PARENT_SYSTEM_PROMPT = "You are a technical documentation writer. Write a summary page for a module that contains sub-modules. Synthesize the children's documentation \u2014 do not re-read source code.\n\nRules:\n- Output ONLY the documentation content \u2014 no meta-commentary like \"I've written...\", \"Here's the documentation...\", \"The documentation covers...\", or similar\n- Start directly with the module heading and content\n- Reference actual components from the child modules\n- Focus on how the sub-modules work together, not repeating their individual docs\n- Keep it concise \u2014 the reader can click through to child pages for detail\n- Include a Mermaid diagram only if it genuinely clarifies how the sub-modules relate";
|
|
12
12
|
export declare const PARENT_USER_PROMPT = "Write documentation for the **{{MODULE_NAME}}** module, which contains these sub-modules:\n\n{{CHILDREN_DOCS}}\n\nCross-module calls: {{CROSS_MODULE_CALLS}}\nShared execution flows: {{CROSS_PROCESSES}}\n\n---\n\nWrite a concise overview of this module group. Explain its purpose, how the sub-modules fit together, and the key workflows that span them. Link to sub-module pages (e.g. `[Sub-module Name](sub-module-slug.md)`) rather than repeating their content. Use whatever structure fits best.";
|
|
13
|
-
export declare const OVERVIEW_SYSTEM_PROMPT = "You are a technical documentation writer. Write the top-level overview page for a repository wiki. This is the first page a new developer sees.\n\nRules:\n- Be clear and welcoming \u2014 this is the entry point to the entire codebase\n- Reference actual module names so readers can navigate to their docs\n- Include a high-level Mermaid architecture diagram showing only the most important modules and their relationships (max 10 nodes). A new dev should grasp it in 10 seconds\n- Do NOT create module index tables or list every module with descriptions \u2014 just link to module pages naturally within the text\n- Use the inter-module edges and execution flow data for accuracy, but do NOT dump them raw";
|
|
13
|
+
export declare const OVERVIEW_SYSTEM_PROMPT = "You are a technical documentation writer. Write the top-level overview page for a repository wiki. This is the first page a new developer sees.\n\nRules:\n- Output ONLY the documentation content \u2014 no meta-commentary like \"I've written...\", \"Here's the documentation...\", \"The page has been rewritten...\", or similar\n- Start directly with the project heading and content\n- Be clear and welcoming \u2014 this is the entry point to the entire codebase\n- Reference actual module names so readers can navigate to their docs\n- Include a high-level Mermaid architecture diagram showing only the most important modules and their relationships (max 10 nodes). A new dev should grasp it in 10 seconds\n- Do NOT create module index tables or list every module with descriptions \u2014 just link to module pages naturally within the text\n- Use the inter-module edges and execution flow data for accuracy, but do NOT dump them raw";
|
|
14
14
|
export declare const OVERVIEW_USER_PROMPT = "Write the overview page for this repository's wiki.\n\n## Project Info\n\n{{PROJECT_INFO}}\n\n## Module Summaries\n\n{{MODULE_SUMMARIES}}\n\n## Reference Data (for accuracy \u2014 do not reproduce verbatim)\n\nInter-module call edges: {{MODULE_EDGES}}\nKey system flows: {{TOP_PROCESSES}}\n\n---\n\nWrite a clear overview of this project: what it does, how it's architected, and the key end-to-end flows. Include a simple Mermaid architecture diagram (max 10 nodes, big-picture only). Link to module pages (e.g. `[Module Name](module-slug.md)`) naturally in the text rather than listing them in a table. If project config was provided, include brief setup instructions. Structure the page however reads best.";
|
|
15
15
|
/**
|
|
16
16
|
* Replace {{PLACEHOLDER}} tokens in a template string.
|
|
@@ -32,6 +32,8 @@ Example format:
|
|
|
32
32
|
export const MODULE_SYSTEM_PROMPT = `You are a technical documentation writer. Write clear, developer-focused documentation for a code module.
|
|
33
33
|
|
|
34
34
|
Rules:
|
|
35
|
+
- Output ONLY the documentation content — no meta-commentary like "I've written...", "Here's the documentation...", "The documentation covers...", or similar
|
|
36
|
+
- Start directly with the module heading and content
|
|
35
37
|
- Reference actual function names, class names, and code patterns — do NOT invent APIs
|
|
36
38
|
- Use the call graph and execution flow data for accuracy, but do NOT mechanically list every edge
|
|
37
39
|
- Include Mermaid diagrams only when they genuinely help understanding. Keep them small (5-10 nodes max)
|
|
@@ -57,6 +59,8 @@ Write comprehensive documentation for this module. Cover its purpose, how it wor
|
|
|
57
59
|
export const PARENT_SYSTEM_PROMPT = `You are a technical documentation writer. Write a summary page for a module that contains sub-modules. Synthesize the children's documentation — do not re-read source code.
|
|
58
60
|
|
|
59
61
|
Rules:
|
|
62
|
+
- Output ONLY the documentation content — no meta-commentary like "I've written...", "Here's the documentation...", "The documentation covers...", or similar
|
|
63
|
+
- Start directly with the module heading and content
|
|
60
64
|
- Reference actual components from the child modules
|
|
61
65
|
- Focus on how the sub-modules work together, not repeating their individual docs
|
|
62
66
|
- Keep it concise — the reader can click through to child pages for detail
|
|
@@ -75,6 +79,8 @@ Write a concise overview of this module group. Explain its purpose, how the sub-
|
|
|
75
79
|
export const OVERVIEW_SYSTEM_PROMPT = `You are a technical documentation writer. Write the top-level overview page for a repository wiki. This is the first page a new developer sees.
|
|
76
80
|
|
|
77
81
|
Rules:
|
|
82
|
+
- Output ONLY the documentation content — no meta-commentary like "I've written...", "Here's the documentation...", "The page has been rewritten...", or similar
|
|
83
|
+
- Start directly with the project heading and content
|
|
78
84
|
- Be clear and welcoming — this is the entry point to the entire codebase
|
|
79
85
|
- Reference actual module names so readers can navigate to their docs
|
|
80
86
|
- Include a high-level Mermaid architecture diagram showing only the most important modules and their relationships (max 10 nodes). A new dev should grasp it in 10 seconds
|
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
import lbug from '@ladybugdb/core';
|
|
16
16
|
/** Saved real stdout.write — used to silence LadybugDB native output without race conditions */
|
|
17
17
|
export declare const realStdoutWrite: any;
|
|
18
|
+
/**
|
|
19
|
+
* Touch a repo to reset its idle timeout.
|
|
20
|
+
* Call this during long-running operations to prevent the connection from being closed.
|
|
21
|
+
*/
|
|
22
|
+
export declare const touchRepo: (repoId: string) => void;
|
|
18
23
|
/**
|
|
19
24
|
* Initialize (or reuse) a Database + connection pool for a specific repo.
|
|
20
25
|
* Retries on lock errors (e.g., when `gitnexus analyze` is running).
|
|
@@ -46,6 +46,16 @@ function ensureIdleTimer() {
|
|
|
46
46
|
idleTimer.unref();
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Touch a repo to reset its idle timeout.
|
|
51
|
+
* Call this during long-running operations to prevent the connection from being closed.
|
|
52
|
+
*/
|
|
53
|
+
export const touchRepo = (repoId) => {
|
|
54
|
+
const entry = pool.get(repoId);
|
|
55
|
+
if (entry) {
|
|
56
|
+
entry.lastUsed = Date.now();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
49
59
|
/**
|
|
50
60
|
* Evict the least-recently-used repo if pool is at capacity
|
|
51
61
|
*/
|
|
@@ -459,7 +469,7 @@ export const closeLbug = async (repoId) => {
|
|
|
459
469
|
*/
|
|
460
470
|
export const isLbugReady = (repoId) => pool.has(repoId);
|
|
461
471
|
/** Regex to detect write operations in user-supplied Cypher queries */
|
|
462
|
-
export const CYPHER_WRITE_RE =
|
|
472
|
+
export const CYPHER_WRITE_RE = /(?<!:)\b(CREATE|DELETE|SET|MERGE|REMOVE|DROP|ALTER|COPY|DETACH|FOREACH)\b/i;
|
|
463
473
|
/** Check if a Cypher query contains write operations */
|
|
464
474
|
export function isWriteQuery(query) {
|
|
465
475
|
return CYPHER_WRITE_RE.test(query);
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* Supports multiple indexed repositories via a global registry.
|
|
6
6
|
* LadybugDB connections are opened lazily per repo on first query.
|
|
7
7
|
*/
|
|
8
|
+
import { isWriteQuery } from '../core/lbug-adapter.js';
|
|
9
|
+
export { isWriteQuery };
|
|
8
10
|
import { type RegistryEntry } from '../../storage/repo-manager.js';
|
|
9
11
|
/**
|
|
10
12
|
* Quick test-file detection for filtering impact results.
|
|
@@ -35,10 +37,6 @@ export declare const VALID_RELATION_TYPES: Set<string>;
|
|
|
35
37
|
* (unknown type) – conservative fallback → 0.5
|
|
36
38
|
*/
|
|
37
39
|
export declare const IMPACT_RELATION_CONFIDENCE: Readonly<Record<string, number>>;
|
|
38
|
-
/** Regex to detect write operations in user-supplied Cypher queries */
|
|
39
|
-
export declare const CYPHER_WRITE_RE: RegExp;
|
|
40
|
-
/** Check if a Cypher query contains write operations */
|
|
41
|
-
export declare function isWriteQuery(query: string): boolean;
|
|
42
40
|
export interface CodebaseContext {
|
|
43
41
|
projectName: string;
|
|
44
42
|
stats: {
|
|
@@ -167,6 +165,20 @@ export declare class LocalBackend {
|
|
|
167
165
|
private rename;
|
|
168
166
|
private impact;
|
|
169
167
|
private _impactImpl;
|
|
168
|
+
/**
|
|
169
|
+
* Fetch Route nodes with their consumers in a single query.
|
|
170
|
+
* Shared by routeMap and shapeCheck to avoid N+1 query patterns.
|
|
171
|
+
*/
|
|
172
|
+
private fetchRoutesWithConsumers;
|
|
173
|
+
/**
|
|
174
|
+
* Batch-fetch execution flows linked to a set of Route or Tool nodes.
|
|
175
|
+
* Single query instead of N+1.
|
|
176
|
+
*/
|
|
177
|
+
private fetchLinkedFlowsBatch;
|
|
178
|
+
private routeMap;
|
|
179
|
+
private shapeCheck;
|
|
180
|
+
private toolMap;
|
|
181
|
+
private apiImpact;
|
|
170
182
|
/**
|
|
171
183
|
* Query clusters (communities) directly from graph.
|
|
172
184
|
* Used by getClustersResource — avoids legacy overview() dispatch.
|
|
@@ -193,4 +205,3 @@ export declare class LocalBackend {
|
|
|
193
205
|
queryProcessDetail(name: string, repoName?: string): Promise<any>;
|
|
194
206
|
disconnect(): Promise<void>;
|
|
195
207
|
}
|
|
196
|
-
export {};
|