@veewo/gitnexus 1.3.4

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.
Files changed (231) hide show
  1. package/README.md +234 -0
  2. package/dist/benchmark/agent-context/evaluators.d.ts +9 -0
  3. package/dist/benchmark/agent-context/evaluators.js +196 -0
  4. package/dist/benchmark/agent-context/evaluators.test.d.ts +1 -0
  5. package/dist/benchmark/agent-context/evaluators.test.js +39 -0
  6. package/dist/benchmark/agent-context/io.d.ts +2 -0
  7. package/dist/benchmark/agent-context/io.js +23 -0
  8. package/dist/benchmark/agent-context/io.test.d.ts +1 -0
  9. package/dist/benchmark/agent-context/io.test.js +19 -0
  10. package/dist/benchmark/agent-context/report.d.ts +2 -0
  11. package/dist/benchmark/agent-context/report.js +59 -0
  12. package/dist/benchmark/agent-context/report.test.d.ts +1 -0
  13. package/dist/benchmark/agent-context/report.test.js +85 -0
  14. package/dist/benchmark/agent-context/runner.d.ts +46 -0
  15. package/dist/benchmark/agent-context/runner.js +111 -0
  16. package/dist/benchmark/agent-context/runner.test.d.ts +1 -0
  17. package/dist/benchmark/agent-context/runner.test.js +79 -0
  18. package/dist/benchmark/agent-context/tool-runner.d.ts +7 -0
  19. package/dist/benchmark/agent-context/tool-runner.js +18 -0
  20. package/dist/benchmark/agent-context/tool-runner.test.d.ts +1 -0
  21. package/dist/benchmark/agent-context/tool-runner.test.js +11 -0
  22. package/dist/benchmark/agent-context/types.d.ts +40 -0
  23. package/dist/benchmark/agent-context/types.js +1 -0
  24. package/dist/benchmark/analyze-runner.d.ts +16 -0
  25. package/dist/benchmark/analyze-runner.js +51 -0
  26. package/dist/benchmark/analyze-runner.test.d.ts +1 -0
  27. package/dist/benchmark/analyze-runner.test.js +37 -0
  28. package/dist/benchmark/evaluators.d.ts +6 -0
  29. package/dist/benchmark/evaluators.js +10 -0
  30. package/dist/benchmark/evaluators.test.d.ts +1 -0
  31. package/dist/benchmark/evaluators.test.js +12 -0
  32. package/dist/benchmark/io.d.ts +7 -0
  33. package/dist/benchmark/io.js +25 -0
  34. package/dist/benchmark/io.test.d.ts +1 -0
  35. package/dist/benchmark/io.test.js +35 -0
  36. package/dist/benchmark/neonspark-candidates.d.ts +19 -0
  37. package/dist/benchmark/neonspark-candidates.js +94 -0
  38. package/dist/benchmark/neonspark-candidates.test.d.ts +1 -0
  39. package/dist/benchmark/neonspark-candidates.test.js +43 -0
  40. package/dist/benchmark/neonspark-materialize.d.ts +19 -0
  41. package/dist/benchmark/neonspark-materialize.js +111 -0
  42. package/dist/benchmark/neonspark-materialize.test.d.ts +1 -0
  43. package/dist/benchmark/neonspark-materialize.test.js +124 -0
  44. package/dist/benchmark/neonspark-sync.d.ts +3 -0
  45. package/dist/benchmark/neonspark-sync.js +53 -0
  46. package/dist/benchmark/neonspark-sync.test.d.ts +1 -0
  47. package/dist/benchmark/neonspark-sync.test.js +20 -0
  48. package/dist/benchmark/report.d.ts +1 -0
  49. package/dist/benchmark/report.js +7 -0
  50. package/dist/benchmark/runner.d.ts +48 -0
  51. package/dist/benchmark/runner.js +302 -0
  52. package/dist/benchmark/runner.test.d.ts +1 -0
  53. package/dist/benchmark/runner.test.js +50 -0
  54. package/dist/benchmark/scoring.d.ts +16 -0
  55. package/dist/benchmark/scoring.js +27 -0
  56. package/dist/benchmark/scoring.test.d.ts +1 -0
  57. package/dist/benchmark/scoring.test.js +24 -0
  58. package/dist/benchmark/tool-runner.d.ts +6 -0
  59. package/dist/benchmark/tool-runner.js +17 -0
  60. package/dist/benchmark/types.d.ts +36 -0
  61. package/dist/benchmark/types.js +1 -0
  62. package/dist/cli/ai-context.d.ts +22 -0
  63. package/dist/cli/ai-context.js +184 -0
  64. package/dist/cli/ai-context.test.d.ts +1 -0
  65. package/dist/cli/ai-context.test.js +30 -0
  66. package/dist/cli/analyze-multi-scope-regression.test.d.ts +1 -0
  67. package/dist/cli/analyze-multi-scope-regression.test.js +22 -0
  68. package/dist/cli/analyze-options.d.ts +7 -0
  69. package/dist/cli/analyze-options.js +56 -0
  70. package/dist/cli/analyze-options.test.d.ts +1 -0
  71. package/dist/cli/analyze-options.test.js +36 -0
  72. package/dist/cli/analyze.d.ts +14 -0
  73. package/dist/cli/analyze.js +384 -0
  74. package/dist/cli/augment.d.ts +13 -0
  75. package/dist/cli/augment.js +33 -0
  76. package/dist/cli/benchmark-agent-context.d.ts +29 -0
  77. package/dist/cli/benchmark-agent-context.js +61 -0
  78. package/dist/cli/benchmark-agent-context.test.d.ts +1 -0
  79. package/dist/cli/benchmark-agent-context.test.js +80 -0
  80. package/dist/cli/benchmark-unity.d.ts +15 -0
  81. package/dist/cli/benchmark-unity.js +31 -0
  82. package/dist/cli/benchmark-unity.test.d.ts +1 -0
  83. package/dist/cli/benchmark-unity.test.js +18 -0
  84. package/dist/cli/claude-hooks.d.ts +22 -0
  85. package/dist/cli/claude-hooks.js +97 -0
  86. package/dist/cli/clean.d.ts +10 -0
  87. package/dist/cli/clean.js +60 -0
  88. package/dist/cli/eval-server.d.ts +30 -0
  89. package/dist/cli/eval-server.js +372 -0
  90. package/dist/cli/index.d.ts +2 -0
  91. package/dist/cli/index.js +182 -0
  92. package/dist/cli/list.d.ts +6 -0
  93. package/dist/cli/list.js +33 -0
  94. package/dist/cli/mcp.d.ts +8 -0
  95. package/dist/cli/mcp.js +34 -0
  96. package/dist/cli/repo-manager-alias.test.d.ts +1 -0
  97. package/dist/cli/repo-manager-alias.test.js +40 -0
  98. package/dist/cli/scope-filter.test.d.ts +1 -0
  99. package/dist/cli/scope-filter.test.js +49 -0
  100. package/dist/cli/serve.d.ts +4 -0
  101. package/dist/cli/serve.js +6 -0
  102. package/dist/cli/setup.d.ts +8 -0
  103. package/dist/cli/setup.js +311 -0
  104. package/dist/cli/setup.test.d.ts +1 -0
  105. package/dist/cli/setup.test.js +31 -0
  106. package/dist/cli/status.d.ts +6 -0
  107. package/dist/cli/status.js +27 -0
  108. package/dist/cli/tool.d.ts +40 -0
  109. package/dist/cli/tool.js +94 -0
  110. package/dist/cli/version.test.d.ts +1 -0
  111. package/dist/cli/version.test.js +19 -0
  112. package/dist/cli/wiki.d.ts +15 -0
  113. package/dist/cli/wiki.js +361 -0
  114. package/dist/config/ignore-service.d.ts +1 -0
  115. package/dist/config/ignore-service.js +210 -0
  116. package/dist/config/supported-languages.d.ts +12 -0
  117. package/dist/config/supported-languages.js +15 -0
  118. package/dist/core/augmentation/engine.d.ts +26 -0
  119. package/dist/core/augmentation/engine.js +213 -0
  120. package/dist/core/embeddings/embedder.d.ts +60 -0
  121. package/dist/core/embeddings/embedder.js +251 -0
  122. package/dist/core/embeddings/embedding-pipeline.d.ts +51 -0
  123. package/dist/core/embeddings/embedding-pipeline.js +329 -0
  124. package/dist/core/embeddings/index.d.ts +9 -0
  125. package/dist/core/embeddings/index.js +9 -0
  126. package/dist/core/embeddings/text-generator.d.ts +24 -0
  127. package/dist/core/embeddings/text-generator.js +182 -0
  128. package/dist/core/embeddings/types.d.ts +87 -0
  129. package/dist/core/embeddings/types.js +32 -0
  130. package/dist/core/graph/graph.d.ts +2 -0
  131. package/dist/core/graph/graph.js +66 -0
  132. package/dist/core/graph/types.d.ts +61 -0
  133. package/dist/core/graph/types.js +1 -0
  134. package/dist/core/ingestion/ast-cache.d.ts +11 -0
  135. package/dist/core/ingestion/ast-cache.js +34 -0
  136. package/dist/core/ingestion/call-processor.d.ts +15 -0
  137. package/dist/core/ingestion/call-processor.js +327 -0
  138. package/dist/core/ingestion/cluster-enricher.d.ts +38 -0
  139. package/dist/core/ingestion/cluster-enricher.js +170 -0
  140. package/dist/core/ingestion/community-processor.d.ts +39 -0
  141. package/dist/core/ingestion/community-processor.js +312 -0
  142. package/dist/core/ingestion/entry-point-scoring.d.ts +39 -0
  143. package/dist/core/ingestion/entry-point-scoring.js +260 -0
  144. package/dist/core/ingestion/filesystem-walker.d.ts +28 -0
  145. package/dist/core/ingestion/filesystem-walker.js +80 -0
  146. package/dist/core/ingestion/framework-detection.d.ts +39 -0
  147. package/dist/core/ingestion/framework-detection.js +235 -0
  148. package/dist/core/ingestion/heritage-processor.d.ts +20 -0
  149. package/dist/core/ingestion/heritage-processor.js +197 -0
  150. package/dist/core/ingestion/import-processor.d.ts +38 -0
  151. package/dist/core/ingestion/import-processor.js +778 -0
  152. package/dist/core/ingestion/parsing-processor.d.ts +15 -0
  153. package/dist/core/ingestion/parsing-processor.js +291 -0
  154. package/dist/core/ingestion/pipeline.d.ts +5 -0
  155. package/dist/core/ingestion/pipeline.js +323 -0
  156. package/dist/core/ingestion/process-processor.d.ts +51 -0
  157. package/dist/core/ingestion/process-processor.js +309 -0
  158. package/dist/core/ingestion/scope-filter.d.ts +25 -0
  159. package/dist/core/ingestion/scope-filter.js +100 -0
  160. package/dist/core/ingestion/structure-processor.d.ts +2 -0
  161. package/dist/core/ingestion/structure-processor.js +36 -0
  162. package/dist/core/ingestion/symbol-table.d.ts +33 -0
  163. package/dist/core/ingestion/symbol-table.js +38 -0
  164. package/dist/core/ingestion/tree-sitter-queries.d.ts +12 -0
  165. package/dist/core/ingestion/tree-sitter-queries.js +398 -0
  166. package/dist/core/ingestion/utils.d.ts +10 -0
  167. package/dist/core/ingestion/utils.js +50 -0
  168. package/dist/core/ingestion/workers/parse-worker.d.ts +59 -0
  169. package/dist/core/ingestion/workers/parse-worker.js +672 -0
  170. package/dist/core/ingestion/workers/worker-pool.d.ts +16 -0
  171. package/dist/core/ingestion/workers/worker-pool.js +120 -0
  172. package/dist/core/kuzu/csv-generator.d.ts +29 -0
  173. package/dist/core/kuzu/csv-generator.js +336 -0
  174. package/dist/core/kuzu/kuzu-adapter.d.ts +101 -0
  175. package/dist/core/kuzu/kuzu-adapter.js +753 -0
  176. package/dist/core/kuzu/schema.d.ts +53 -0
  177. package/dist/core/kuzu/schema.js +407 -0
  178. package/dist/core/search/bm25-index.d.ts +23 -0
  179. package/dist/core/search/bm25-index.js +95 -0
  180. package/dist/core/search/hybrid-search.d.ts +49 -0
  181. package/dist/core/search/hybrid-search.js +118 -0
  182. package/dist/core/tree-sitter/parser-loader.d.ts +4 -0
  183. package/dist/core/tree-sitter/parser-loader.js +44 -0
  184. package/dist/core/wiki/generator.d.ts +110 -0
  185. package/dist/core/wiki/generator.js +786 -0
  186. package/dist/core/wiki/graph-queries.d.ts +80 -0
  187. package/dist/core/wiki/graph-queries.js +238 -0
  188. package/dist/core/wiki/html-viewer.d.ts +10 -0
  189. package/dist/core/wiki/html-viewer.js +297 -0
  190. package/dist/core/wiki/llm-client.d.ts +40 -0
  191. package/dist/core/wiki/llm-client.js +162 -0
  192. package/dist/core/wiki/prompts.d.ts +53 -0
  193. package/dist/core/wiki/prompts.js +174 -0
  194. package/dist/lib/utils.d.ts +1 -0
  195. package/dist/lib/utils.js +3 -0
  196. package/dist/mcp/core/embedder.d.ts +27 -0
  197. package/dist/mcp/core/embedder.js +108 -0
  198. package/dist/mcp/core/kuzu-adapter.d.ts +34 -0
  199. package/dist/mcp/core/kuzu-adapter.js +231 -0
  200. package/dist/mcp/local/local-backend.d.ts +160 -0
  201. package/dist/mcp/local/local-backend.js +1646 -0
  202. package/dist/mcp/resources.d.ts +31 -0
  203. package/dist/mcp/resources.js +407 -0
  204. package/dist/mcp/server.d.ts +23 -0
  205. package/dist/mcp/server.js +251 -0
  206. package/dist/mcp/staleness.d.ts +15 -0
  207. package/dist/mcp/staleness.js +29 -0
  208. package/dist/mcp/tools.d.ts +24 -0
  209. package/dist/mcp/tools.js +195 -0
  210. package/dist/server/api.d.ts +10 -0
  211. package/dist/server/api.js +344 -0
  212. package/dist/server/mcp-http.d.ts +13 -0
  213. package/dist/server/mcp-http.js +100 -0
  214. package/dist/storage/git.d.ts +6 -0
  215. package/dist/storage/git.js +32 -0
  216. package/dist/storage/repo-manager.d.ts +125 -0
  217. package/dist/storage/repo-manager.js +257 -0
  218. package/dist/types/pipeline.d.ts +34 -0
  219. package/dist/types/pipeline.js +18 -0
  220. package/hooks/claude/gitnexus-hook.cjs +135 -0
  221. package/hooks/claude/pre-tool-use.sh +78 -0
  222. package/hooks/claude/session-start.sh +42 -0
  223. package/package.json +92 -0
  224. package/skills/gitnexus-cli.md +82 -0
  225. package/skills/gitnexus-debugging.md +89 -0
  226. package/skills/gitnexus-exploring.md +78 -0
  227. package/skills/gitnexus-guide.md +64 -0
  228. package/skills/gitnexus-impact-analysis.md +97 -0
  229. package/skills/gitnexus-refactoring.md +121 -0
  230. package/vendor/leiden/index.cjs +355 -0
  231. package/vendor/leiden/utils.cjs +392 -0
@@ -0,0 +1,361 @@
1
+ /**
2
+ * Wiki Command
3
+ *
4
+ * Generates repository documentation from the knowledge graph.
5
+ * Usage: gitnexus wiki [path] [options]
6
+ */
7
+ import path from 'path';
8
+ import readline from 'readline';
9
+ import { execSync } from 'child_process';
10
+ import cliProgress from 'cli-progress';
11
+ import { getGitRoot, isGitRepo } from '../storage/git.js';
12
+ import { getStoragePaths, loadMeta, loadCLIConfig, saveCLIConfig } from '../storage/repo-manager.js';
13
+ import { WikiGenerator } from '../core/wiki/generator.js';
14
+ import { resolveLLMConfig } from '../core/wiki/llm-client.js';
15
+ /**
16
+ * Prompt the user for input via stdin.
17
+ */
18
+ function prompt(question, hide = false) {
19
+ return new Promise((resolve) => {
20
+ const rl = readline.createInterface({
21
+ input: process.stdin,
22
+ output: process.stdout,
23
+ });
24
+ if (hide && process.stdin.isTTY) {
25
+ // Mask input for API keys
26
+ process.stdout.write(question);
27
+ let input = '';
28
+ process.stdin.setRawMode(true);
29
+ process.stdin.resume();
30
+ process.stdin.setEncoding('utf-8');
31
+ const onData = (char) => {
32
+ if (char === '\n' || char === '\r' || char === '\u0004') {
33
+ process.stdin.setRawMode(false);
34
+ process.stdin.removeListener('data', onData);
35
+ process.stdout.write('\n');
36
+ rl.close();
37
+ resolve(input);
38
+ }
39
+ else if (char === '\u0003') {
40
+ // Ctrl+C
41
+ process.stdin.setRawMode(false);
42
+ rl.close();
43
+ process.exit(1);
44
+ }
45
+ else if (char === '\u007F' || char === '\b') {
46
+ // Backspace
47
+ if (input.length > 0) {
48
+ input = input.slice(0, -1);
49
+ process.stdout.write('\b \b');
50
+ }
51
+ }
52
+ else {
53
+ input += char;
54
+ process.stdout.write('*');
55
+ }
56
+ };
57
+ process.stdin.on('data', onData);
58
+ }
59
+ else {
60
+ rl.question(question, (answer) => {
61
+ rl.close();
62
+ resolve(answer.trim());
63
+ });
64
+ }
65
+ });
66
+ }
67
+ export const wikiCommand = async (inputPath, options) => {
68
+ console.log('\n GitNexus Wiki Generator\n');
69
+ // ── Resolve repo path ───────────────────────────────────────────────
70
+ let repoPath;
71
+ if (inputPath) {
72
+ repoPath = path.resolve(inputPath);
73
+ }
74
+ else {
75
+ const gitRoot = getGitRoot(process.cwd());
76
+ if (!gitRoot) {
77
+ console.log(' Error: Not inside a git repository\n');
78
+ process.exitCode = 1;
79
+ return;
80
+ }
81
+ repoPath = gitRoot;
82
+ }
83
+ if (!isGitRepo(repoPath)) {
84
+ console.log(' Error: Not a git repository\n');
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+ // ── Check for existing index ────────────────────────────────────────
89
+ const { storagePath, kuzuPath } = getStoragePaths(repoPath);
90
+ const meta = await loadMeta(storagePath);
91
+ if (!meta) {
92
+ console.log(' Error: No GitNexus index found.');
93
+ console.log(' Run `gitnexus analyze` first to index this repository.\n');
94
+ process.exitCode = 1;
95
+ return;
96
+ }
97
+ // ── Resolve LLM config (with interactive fallback) ─────────────────
98
+ // Save any CLI overrides immediately
99
+ if (options?.apiKey || options?.model || options?.baseUrl) {
100
+ const existing = await loadCLIConfig();
101
+ const updates = {};
102
+ if (options.apiKey)
103
+ updates.apiKey = options.apiKey;
104
+ if (options.model)
105
+ updates.model = options.model;
106
+ if (options.baseUrl)
107
+ updates.baseUrl = options.baseUrl;
108
+ await saveCLIConfig({ ...existing, ...updates });
109
+ console.log(' Config saved to ~/.gitnexus/config.json\n');
110
+ }
111
+ const savedConfig = await loadCLIConfig();
112
+ const hasSavedConfig = !!(savedConfig.apiKey && savedConfig.baseUrl);
113
+ const hasCLIOverrides = !!(options?.apiKey || options?.model || options?.baseUrl);
114
+ let llmConfig = await resolveLLMConfig({
115
+ model: options?.model,
116
+ baseUrl: options?.baseUrl,
117
+ apiKey: options?.apiKey,
118
+ });
119
+ // Run interactive setup if no saved config and no CLI flags provided
120
+ // (even if env vars exist — let user explicitly choose their provider)
121
+ if (!hasSavedConfig && !hasCLIOverrides) {
122
+ if (!process.stdin.isTTY) {
123
+ if (!llmConfig.apiKey) {
124
+ console.log(' Error: No LLM API key found.');
125
+ console.log(' Set OPENAI_API_KEY or GITNEXUS_API_KEY environment variable,');
126
+ console.log(' or pass --api-key <key>.\n');
127
+ process.exitCode = 1;
128
+ return;
129
+ }
130
+ // Non-interactive with env var — just use it
131
+ }
132
+ else {
133
+ console.log(' No LLM configured. Let\'s set it up.\n');
134
+ console.log(' Supports OpenAI, OpenRouter, or any OpenAI-compatible API.\n');
135
+ // Provider selection
136
+ console.log(' [1] OpenAI (api.openai.com)');
137
+ console.log(' [2] OpenRouter (openrouter.ai)');
138
+ console.log(' [3] Custom endpoint\n');
139
+ const choice = await prompt(' Select provider (1/2/3): ');
140
+ let baseUrl;
141
+ let defaultModel;
142
+ if (choice === '2') {
143
+ baseUrl = 'https://openrouter.ai/api/v1';
144
+ defaultModel = 'minimax/minimax-m2.5';
145
+ }
146
+ else if (choice === '3') {
147
+ baseUrl = await prompt(' Base URL (e.g. http://localhost:11434/v1): ');
148
+ if (!baseUrl) {
149
+ console.log('\n No URL provided. Aborting.\n');
150
+ process.exitCode = 1;
151
+ return;
152
+ }
153
+ defaultModel = 'gpt-4o-mini';
154
+ }
155
+ else {
156
+ baseUrl = 'https://api.openai.com/v1';
157
+ defaultModel = 'gpt-4o-mini';
158
+ }
159
+ // Model
160
+ const modelInput = await prompt(` Model (default: ${defaultModel}): `);
161
+ const model = modelInput || defaultModel;
162
+ // API key — pre-fill hint if env var exists
163
+ const envKey = process.env.GITNEXUS_API_KEY || process.env.OPENAI_API_KEY || '';
164
+ let key;
165
+ if (envKey) {
166
+ const masked = envKey.slice(0, 6) + '...' + envKey.slice(-4);
167
+ const useEnv = await prompt(` Use existing env key (${masked})? (Y/n): `);
168
+ if (!useEnv || useEnv.toLowerCase() === 'y' || useEnv.toLowerCase() === 'yes') {
169
+ key = envKey;
170
+ }
171
+ else {
172
+ key = await prompt(' API key: ', true);
173
+ }
174
+ }
175
+ else {
176
+ key = await prompt(' API key: ', true);
177
+ }
178
+ if (!key) {
179
+ console.log('\n No key provided. Aborting.\n');
180
+ process.exitCode = 1;
181
+ return;
182
+ }
183
+ // Save
184
+ await saveCLIConfig({ apiKey: key, baseUrl, model });
185
+ console.log(' Config saved to ~/.gitnexus/config.json\n');
186
+ llmConfig = { ...llmConfig, apiKey: key, baseUrl, model };
187
+ }
188
+ }
189
+ // ── Setup progress bar with elapsed timer ──────────────────────────
190
+ const bar = new cliProgress.SingleBar({
191
+ format: ' {bar} {percentage}% | {phase}',
192
+ barCompleteChar: '\u2588',
193
+ barIncompleteChar: '\u2591',
194
+ hideCursor: true,
195
+ barGlue: '',
196
+ autopadding: true,
197
+ clearOnComplete: false,
198
+ stopOnComplete: false,
199
+ }, cliProgress.Presets.shades_grey);
200
+ bar.start(100, 0, { phase: 'Initializing...' });
201
+ const t0 = Date.now();
202
+ let lastPhase = '';
203
+ let phaseStart = t0;
204
+ // Tick elapsed time every second while stuck on the same phase
205
+ const elapsedTimer = setInterval(() => {
206
+ if (lastPhase) {
207
+ const elapsed = Math.round((Date.now() - phaseStart) / 1000);
208
+ if (elapsed >= 3) {
209
+ bar.update({ phase: `${lastPhase} (${elapsed}s)` });
210
+ }
211
+ }
212
+ }, 1000);
213
+ // ── Run generator ───────────────────────────────────────────────────
214
+ const wikiOptions = {
215
+ force: options?.force,
216
+ model: options?.model,
217
+ baseUrl: options?.baseUrl,
218
+ concurrency: options?.concurrency ? parseInt(options.concurrency, 10) : undefined,
219
+ };
220
+ const generator = new WikiGenerator(repoPath, storagePath, kuzuPath, llmConfig, wikiOptions, (phase, percent, detail) => {
221
+ const label = detail || phase;
222
+ if (label !== lastPhase) {
223
+ lastPhase = label;
224
+ phaseStart = Date.now();
225
+ }
226
+ bar.update(percent, { phase: label });
227
+ });
228
+ try {
229
+ const result = await generator.run();
230
+ clearInterval(elapsedTimer);
231
+ bar.update(100, { phase: 'Done' });
232
+ bar.stop();
233
+ const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
234
+ const wikiDir = path.join(storagePath, 'wiki');
235
+ const viewerPath = path.join(wikiDir, 'index.html');
236
+ if (result.mode === 'up-to-date' && !options?.force) {
237
+ console.log('\n Wiki is already up to date.');
238
+ console.log(` Viewer: ${viewerPath}\n`);
239
+ await maybePublishGist(viewerPath, options?.gist);
240
+ return;
241
+ }
242
+ console.log(`\n Wiki generated successfully (${elapsed}s)\n`);
243
+ console.log(` Mode: ${result.mode}`);
244
+ console.log(` Pages: ${result.pagesGenerated}`);
245
+ console.log(` Output: ${wikiDir}`);
246
+ console.log(` Viewer: ${viewerPath}`);
247
+ if (result.failedModules && result.failedModules.length > 0) {
248
+ console.log(`\n Failed modules (${result.failedModules.length}):`);
249
+ for (const mod of result.failedModules) {
250
+ console.log(` - ${mod}`);
251
+ }
252
+ console.log(' Re-run to retry failed modules (pages will be regenerated).');
253
+ }
254
+ console.log('');
255
+ await maybePublishGist(viewerPath, options?.gist);
256
+ }
257
+ catch (err) {
258
+ clearInterval(elapsedTimer);
259
+ bar.stop();
260
+ if (err.message?.includes('No source files')) {
261
+ console.log(`\n ${err.message}\n`);
262
+ }
263
+ else if (err.message?.includes('API key') || err.message?.includes('API error')) {
264
+ console.log(`\n LLM Error: ${err.message}\n`);
265
+ // Offer to reconfigure on auth-related failures
266
+ const isAuthError = err.message?.includes('401') || err.message?.includes('403')
267
+ || err.message?.includes('502') || err.message?.includes('authenticate')
268
+ || err.message?.includes('Unauthorized');
269
+ if (isAuthError && process.stdin.isTTY) {
270
+ const answer = await new Promise((resolve) => {
271
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
272
+ rl.question(' Reconfigure LLM settings? (Y/n): ', (ans) => { rl.close(); resolve(ans.trim().toLowerCase()); });
273
+ });
274
+ if (!answer || answer === 'y' || answer === 'yes') {
275
+ // Clear saved config so next run triggers interactive setup
276
+ await saveCLIConfig({});
277
+ console.log(' Config cleared. Run `gitnexus wiki` again to reconfigure.\n');
278
+ }
279
+ }
280
+ }
281
+ else {
282
+ console.log(`\n Error: ${err.message}\n`);
283
+ if (process.env.DEBUG) {
284
+ console.error(err);
285
+ }
286
+ }
287
+ process.exitCode = 1;
288
+ }
289
+ };
290
+ // ─── Gist Publishing ───────────────────────────────────────────────────
291
+ function hasGhCLI() {
292
+ try {
293
+ execSync('gh --version', { stdio: 'ignore' });
294
+ return true;
295
+ }
296
+ catch {
297
+ return false;
298
+ }
299
+ }
300
+ function publishGist(htmlPath) {
301
+ try {
302
+ const output = execSync(`gh gist create "${htmlPath}" --desc "Repository Wiki — generated by GitNexus" --public`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
303
+ // gh gist create prints the gist URL as the last line
304
+ const lines = output.split('\n');
305
+ const gistUrl = lines.find(l => l.includes('gist.github.com')) || lines[lines.length - 1];
306
+ if (!gistUrl || !gistUrl.includes('gist.github.com'))
307
+ return null;
308
+ // Build a raw viewer URL via gist.githack.com
309
+ // gist URL format: https://gist.github.com/{user}/{id}
310
+ const match = gistUrl.match(/gist\.github\.com\/([^/]+)\/([a-f0-9]+)/);
311
+ let rawUrl = gistUrl;
312
+ if (match) {
313
+ rawUrl = `https://gistcdn.githack.com/${match[1]}/${match[2]}/raw/index.html`;
314
+ }
315
+ return { url: gistUrl.trim(), rawUrl };
316
+ }
317
+ catch {
318
+ return null;
319
+ }
320
+ }
321
+ async function maybePublishGist(htmlPath, gistFlag) {
322
+ if (gistFlag === false)
323
+ return;
324
+ // Check that the HTML file exists
325
+ try {
326
+ const fs = await import('fs/promises');
327
+ await fs.access(htmlPath);
328
+ }
329
+ catch {
330
+ return;
331
+ }
332
+ if (!hasGhCLI()) {
333
+ if (gistFlag) {
334
+ console.log(' GitHub CLI (gh) is not installed. Cannot publish gist.');
335
+ console.log(' Install it: https://cli.github.com\n');
336
+ }
337
+ return;
338
+ }
339
+ let shouldPublish = !!gistFlag;
340
+ if (!shouldPublish && process.stdin.isTTY) {
341
+ const answer = await new Promise((resolve) => {
342
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
343
+ rl.question(' Publish wiki as a GitHub Gist for easy viewing? (Y/n): ', (ans) => {
344
+ rl.close();
345
+ resolve(ans.trim().toLowerCase());
346
+ });
347
+ });
348
+ shouldPublish = !answer || answer === 'y' || answer === 'yes';
349
+ }
350
+ if (!shouldPublish)
351
+ return;
352
+ console.log('\n Publishing to GitHub Gist...');
353
+ const result = publishGist(htmlPath);
354
+ if (result) {
355
+ console.log(` Gist: ${result.url}`);
356
+ console.log(` Viewer: ${result.rawUrl}\n`);
357
+ }
358
+ else {
359
+ console.log(' Failed to publish gist. Make sure `gh auth login` is configured.\n');
360
+ }
361
+ }
@@ -0,0 +1 @@
1
+ export declare const shouldIgnorePath: (filePath: string) => boolean;
@@ -0,0 +1,210 @@
1
+ const DEFAULT_IGNORE_LIST = new Set([
2
+ // Version Control
3
+ '.git',
4
+ '.svn',
5
+ '.hg',
6
+ '.bzr',
7
+ // IDEs & Editors
8
+ '.idea',
9
+ '.vscode',
10
+ '.vs',
11
+ '.eclipse',
12
+ '.settings',
13
+ '.DS_Store',
14
+ 'Thumbs.db',
15
+ // Dependencies
16
+ 'node_modules',
17
+ 'bower_components',
18
+ 'jspm_packages',
19
+ 'vendor', // PHP/Go
20
+ // 'packages' removed - commonly used for monorepo source code (lerna, pnpm, yarn workspaces)
21
+ 'venv',
22
+ '.venv',
23
+ 'env',
24
+ '.env',
25
+ '__pycache__',
26
+ '.pytest_cache',
27
+ '.mypy_cache',
28
+ 'site-packages',
29
+ '.tox',
30
+ 'eggs',
31
+ '.eggs',
32
+ 'lib64',
33
+ 'parts',
34
+ 'sdist',
35
+ 'wheels',
36
+ // Build Outputs
37
+ 'dist',
38
+ 'build',
39
+ 'out',
40
+ 'output',
41
+ 'bin',
42
+ 'obj',
43
+ 'target', // Java/Rust
44
+ '.next',
45
+ '.nuxt',
46
+ '.output',
47
+ '.vercel',
48
+ '.netlify',
49
+ '.serverless',
50
+ '_build',
51
+ 'public/build',
52
+ '.parcel-cache',
53
+ '.turbo',
54
+ '.svelte-kit',
55
+ // Test & Coverage
56
+ 'coverage',
57
+ '.nyc_output',
58
+ 'htmlcov',
59
+ '.coverage',
60
+ '__tests__', // Often just test files
61
+ '__mocks__',
62
+ '.jest',
63
+ // Logs & Temp
64
+ 'logs',
65
+ 'log',
66
+ 'tmp',
67
+ 'temp',
68
+ 'cache',
69
+ '.cache',
70
+ '.tmp',
71
+ '.temp',
72
+ // Generated/Compiled
73
+ '.generated',
74
+ 'generated',
75
+ 'auto-generated',
76
+ '.terraform',
77
+ '.serverless',
78
+ // Documentation (optional - might want to keep)
79
+ // 'docs',
80
+ // 'documentation',
81
+ // Misc
82
+ '.husky',
83
+ '.github', // GitHub config, not code
84
+ '.circleci',
85
+ '.gitlab',
86
+ 'fixtures', // Test fixtures
87
+ 'snapshots', // Jest snapshots
88
+ '__snapshots__',
89
+ ]);
90
+ const IGNORED_EXTENSIONS = new Set([
91
+ // Images
92
+ '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.webp', '.bmp', '.tiff', '.tif',
93
+ '.psd', '.ai', '.sketch', '.fig', '.xd',
94
+ // Archives
95
+ '.zip', '.tar', '.gz', '.rar', '.7z', '.bz2', '.xz', '.tgz',
96
+ // Binary/Compiled
97
+ '.exe', '.dll', '.so', '.dylib', '.a', '.lib', '.o', '.obj',
98
+ '.class', '.jar', '.war', '.ear',
99
+ '.pyc', '.pyo', '.pyd',
100
+ '.beam', // Erlang
101
+ '.wasm', // WebAssembly - important!
102
+ '.node', // Native Node addons
103
+ // Documents
104
+ '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx',
105
+ '.odt', '.ods', '.odp',
106
+ // Media
107
+ '.mp4', '.mp3', '.wav', '.mov', '.avi', '.mkv', '.flv', '.wmv',
108
+ '.ogg', '.webm', '.flac', '.aac', '.m4a',
109
+ // Fonts
110
+ '.woff', '.woff2', '.ttf', '.eot', '.otf',
111
+ // Databases
112
+ '.db', '.sqlite', '.sqlite3', '.mdb', '.accdb',
113
+ // Minified/Bundled files
114
+ '.min.js', '.min.css', '.bundle.js', '.chunk.js',
115
+ // Source maps (debug files, not source)
116
+ '.map',
117
+ // Lock files (handled separately, but also here)
118
+ '.lock',
119
+ // Certificates & Keys (security - don't index!)
120
+ '.pem', '.key', '.crt', '.cer', '.p12', '.pfx',
121
+ // Data files (often large/binary)
122
+ '.csv', '.tsv', '.parquet', '.avro', '.feather',
123
+ '.npy', '.npz', '.pkl', '.pickle', '.h5', '.hdf5',
124
+ // Misc binary
125
+ '.bin', '.dat', '.data', '.raw',
126
+ '.iso', '.img', '.dmg',
127
+ // Unity metadata assets
128
+ '.meta',
129
+ ]);
130
+ // Files to ignore by exact name
131
+ const IGNORED_FILES = new Set([
132
+ 'package-lock.json',
133
+ 'yarn.lock',
134
+ 'pnpm-lock.yaml',
135
+ 'composer.lock',
136
+ 'Gemfile.lock',
137
+ 'poetry.lock',
138
+ 'Cargo.lock',
139
+ 'go.sum',
140
+ '.gitignore',
141
+ '.gitattributes',
142
+ '.npmrc',
143
+ '.yarnrc',
144
+ '.editorconfig',
145
+ '.prettierrc',
146
+ '.prettierignore',
147
+ '.eslintignore',
148
+ '.dockerignore',
149
+ 'Thumbs.db',
150
+ '.DS_Store',
151
+ 'LICENSE',
152
+ 'LICENSE.md',
153
+ 'LICENSE.txt',
154
+ 'CHANGELOG.md',
155
+ 'CHANGELOG',
156
+ 'CONTRIBUTING.md',
157
+ 'CODE_OF_CONDUCT.md',
158
+ 'SECURITY.md',
159
+ '.env',
160
+ '.env.local',
161
+ '.env.development',
162
+ '.env.production',
163
+ '.env.test',
164
+ '.env.example',
165
+ ]);
166
+ export const shouldIgnorePath = (filePath) => {
167
+ const normalizedPath = filePath.replace(/\\/g, '/');
168
+ const parts = normalizedPath.split('/');
169
+ const fileName = parts[parts.length - 1];
170
+ const fileNameLower = fileName.toLowerCase();
171
+ // Check if any path segment is in ignore list
172
+ for (const part of parts) {
173
+ if (DEFAULT_IGNORE_LIST.has(part)) {
174
+ return true;
175
+ }
176
+ }
177
+ // Check exact filename matches
178
+ if (IGNORED_FILES.has(fileName) || IGNORED_FILES.has(fileNameLower)) {
179
+ return true;
180
+ }
181
+ // Check extension
182
+ const lastDotIndex = fileNameLower.lastIndexOf('.');
183
+ if (lastDotIndex !== -1) {
184
+ const ext = fileNameLower.substring(lastDotIndex);
185
+ if (IGNORED_EXTENSIONS.has(ext))
186
+ return true;
187
+ // Handle compound extensions like .min.js, .bundle.js
188
+ const secondLastDot = fileNameLower.lastIndexOf('.', lastDotIndex - 1);
189
+ if (secondLastDot !== -1) {
190
+ const compoundExt = fileNameLower.substring(secondLastDot);
191
+ if (IGNORED_EXTENSIONS.has(compoundExt))
192
+ return true;
193
+ }
194
+ }
195
+ // Ignore hidden files (starting with .)
196
+ if (fileName.startsWith('.') && fileName !== '.') {
197
+ // But allow some important config files
198
+ const allowedDotFiles = ['.env', '.gitignore']; // Already in IGNORED_FILES, so this is redundant
199
+ // Actually, let's NOT ignore all dot files - many are important configs
200
+ // Just rely on the explicit lists above
201
+ }
202
+ // Ignore files that look like generated/bundled code
203
+ if (fileNameLower.includes('.bundle.') ||
204
+ fileNameLower.includes('.chunk.') ||
205
+ fileNameLower.includes('.generated.') ||
206
+ fileNameLower.endsWith('.d.ts')) { // TypeScript declaration files
207
+ return true;
208
+ }
209
+ return false;
210
+ };
@@ -0,0 +1,12 @@
1
+ export declare enum SupportedLanguages {
2
+ JavaScript = "javascript",
3
+ TypeScript = "typescript",
4
+ Python = "python",
5
+ Java = "java",
6
+ C = "c",
7
+ CPlusPlus = "cpp",
8
+ CSharp = "csharp",
9
+ Go = "go",
10
+ Rust = "rust",
11
+ PHP = "php"
12
+ }
@@ -0,0 +1,15 @@
1
+ export var SupportedLanguages;
2
+ (function (SupportedLanguages) {
3
+ SupportedLanguages["JavaScript"] = "javascript";
4
+ SupportedLanguages["TypeScript"] = "typescript";
5
+ SupportedLanguages["Python"] = "python";
6
+ SupportedLanguages["Java"] = "java";
7
+ SupportedLanguages["C"] = "c";
8
+ SupportedLanguages["CPlusPlus"] = "cpp";
9
+ SupportedLanguages["CSharp"] = "csharp";
10
+ SupportedLanguages["Go"] = "go";
11
+ SupportedLanguages["Rust"] = "rust";
12
+ SupportedLanguages["PHP"] = "php";
13
+ // Ruby = 'ruby',
14
+ // Swift = 'swift',
15
+ })(SupportedLanguages || (SupportedLanguages = {}));
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Augmentation Engine
3
+ *
4
+ * Lightweight, fast-path enrichment of search patterns with knowledge graph context.
5
+ * Designed to be called from platform hooks (Claude Code PreToolUse, Cursor beforeShellExecution)
6
+ * when an agent runs grep/glob/search.
7
+ *
8
+ * Performance target: <500ms cold start, <200ms warm.
9
+ *
10
+ * Design decisions:
11
+ * - Uses only BM25 search (no semantic/embedding) for speed
12
+ * - Clusters used internally for ranking, NEVER in output
13
+ * - Output is pure relationships: callers, callees, process participation
14
+ * - Graceful failure: any error → return empty string
15
+ */
16
+ /**
17
+ * Augment a search pattern with knowledge graph context.
18
+ *
19
+ * 1. BM25 search for the pattern
20
+ * 2. For top matches, fetch callers/callees/processes
21
+ * 3. Rank by internal cluster cohesion (not exposed)
22
+ * 4. Format as structured text block
23
+ *
24
+ * Returns empty string on any error (graceful failure).
25
+ */
26
+ export declare function augment(pattern: string, cwd?: string): Promise<string>;