gitnexus 1.4.7 → 1.4.9
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 +29 -1
- package/dist/cli/ai-context.d.ts +1 -1
- package/dist/cli/ai-context.js +1 -1
- package/dist/cli/analyze.d.ts +2 -0
- package/dist/cli/analyze.js +54 -21
- package/dist/cli/index-repo.d.ts +15 -0
- package/dist/cli/index-repo.js +115 -0
- package/dist/cli/index.js +13 -3
- package/dist/cli/setup.js +90 -10
- package/dist/cli/wiki.d.ts +4 -0
- package/dist/cli/wiki.js +174 -53
- package/dist/config/supported-languages.d.ts +33 -1
- package/dist/config/supported-languages.js +32 -0
- package/dist/core/embeddings/embedder.d.ts +6 -1
- package/dist/core/embeddings/embedder.js +65 -5
- package/dist/core/embeddings/embedding-pipeline.js +11 -9
- package/dist/core/embeddings/http-client.d.ts +31 -0
- package/dist/core/embeddings/http-client.js +179 -0
- package/dist/core/embeddings/index.d.ts +1 -0
- package/dist/core/embeddings/index.js +1 -0
- package/dist/core/embeddings/types.d.ts +1 -1
- package/dist/core/graph/graph.js +9 -1
- package/dist/core/graph/types.d.ts +11 -2
- package/dist/core/ingestion/call-processor.d.ts +66 -2
- package/dist/core/ingestion/call-processor.js +650 -30
- package/dist/core/ingestion/call-routing.d.ts +9 -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 +52 -28
- 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 +97 -2
- package/dist/core/ingestion/framework-detection.js +114 -14
- package/dist/core/ingestion/heritage-processor.js +62 -66
- package/dist/core/ingestion/import-processor.d.ts +9 -10
- package/dist/core/ingestion/import-processor.js +150 -196
- 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 +10 -1
- package/dist/core/ingestion/import-resolvers/jvm.js +159 -0
- package/dist/core/ingestion/import-resolvers/php.d.ts +25 -0
- package/dist/core/ingestion/import-resolvers/php.js +80 -0
- 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 +2 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +7 -0
- package/dist/core/ingestion/language-config.d.ts +6 -0
- package/dist/core/ingestion/language-config.js +13 -0
- 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/markdown-processor.d.ts +17 -0
- package/dist/core/ingestion/markdown-processor.js +124 -0
- package/dist/core/ingestion/mro-processor.js +22 -18
- package/dist/core/ingestion/named-binding-processor.d.ts +18 -0
- 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 +6 -2
- package/dist/core/ingestion/parsing-processor.js +125 -85
- package/dist/core/ingestion/pipeline.d.ts +10 -0
- package/dist/core/ingestion/pipeline.js +1235 -317
- package/dist/core/ingestion/resolution-context.d.ts +5 -0
- package/dist/core/ingestion/resolution-context.js +8 -5
- 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/symbol-table.d.ts +16 -0
- package/dist/core/ingestion/symbol-table.js +20 -6
- package/dist/core/ingestion/tree-sitter-queries.d.ts +10 -9
- package/dist/core/ingestion/tree-sitter-queries.js +274 -11
- package/dist/core/ingestion/type-env.d.ts +42 -18
- package/dist/core/ingestion/type-env.js +481 -106
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +5 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +119 -0
- package/dist/core/ingestion/type-extractors/csharp.js +149 -16
- 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 +169 -66
- package/dist/core/ingestion/type-extractors/rust.js +35 -1
- package/dist/core/ingestion/type-extractors/shared.d.ts +1 -15
- package/dist/core/ingestion/type-extractors/shared.js +14 -112
- package/dist/core/ingestion/type-extractors/swift.js +338 -7
- package/dist/core/ingestion/type-extractors/types.d.ts +40 -8
- package/dist/core/ingestion/type-extractors/typescript.js +141 -9
- package/dist/core/ingestion/utils/ast-helpers.d.ts +83 -0
- package/dist/core/ingestion/utils/ast-helpers.js +817 -0
- package/dist/core/ingestion/utils/call-analysis.d.ts +73 -0
- package/dist/core/ingestion/utils/call-analysis.js +527 -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 +55 -5
- package/dist/core/ingestion/workers/parse-worker.js +415 -225
- package/dist/core/lbug/csv-generator.js +51 -1
- package/dist/core/lbug/lbug-adapter.d.ts +10 -0
- package/dist/core/lbug/lbug-adapter.js +75 -4
- package/dist/core/lbug/schema.d.ts +8 -4
- package/dist/core/lbug/schema.js +65 -4
- 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/embedder.js +11 -3
- package/dist/mcp/core/lbug-adapter.d.ts +5 -0
- package/dist/mcp/core/lbug-adapter.js +23 -2
- package/dist/mcp/local/local-backend.d.ts +38 -5
- package/dist/mcp/local/local-backend.js +804 -63
- package/dist/mcp/resources.js +2 -0
- package/dist/mcp/tools.js +73 -4
- package/dist/server/api.d.ts +19 -1
- package/dist/server/api.js +66 -6
- package/dist/storage/git.d.ts +12 -0
- package/dist/storage/git.js +21 -0
- package/dist/storage/repo-manager.d.ts +3 -0
- package/package.json +25 -16
- package/dist/core/ingestion/named-binding-extraction.d.ts +0 -61
- package/dist/core/ingestion/named-binding-extraction.js +0 -363
- package/dist/core/ingestion/resolvers/index.d.ts +0 -18
- package/dist/core/ingestion/resolvers/index.js +0 -13
- package/dist/core/ingestion/resolvers/jvm.js +0 -87
- package/dist/core/ingestion/resolvers/php.d.ts +0 -15
- package/dist/core/ingestion/resolvers/php.js +0 -35
- 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 -138
- package/dist/core/ingestion/utils.js +0 -1290
- package/scripts/patch-tree-sitter-swift.cjs +0 -74
package/dist/cli/wiki.js
CHANGED
|
@@ -12,6 +12,7 @@ import { getGitRoot, isGitRepo } from '../storage/git.js';
|
|
|
12
12
|
import { getStoragePaths, loadMeta, loadCLIConfig, saveCLIConfig } from '../storage/repo-manager.js';
|
|
13
13
|
import { WikiGenerator } from '../core/wiki/generator.js';
|
|
14
14
|
import { resolveLLMConfig } from '../core/wiki/llm-client.js';
|
|
15
|
+
import { detectCursorCLI } from '../core/wiki/cursor-client.js';
|
|
15
16
|
/**
|
|
16
17
|
* Prompt the user for input via stdin.
|
|
17
18
|
*/
|
|
@@ -65,6 +66,10 @@ function prompt(question, hide = false) {
|
|
|
65
66
|
});
|
|
66
67
|
}
|
|
67
68
|
export const wikiCommand = async (inputPath, options) => {
|
|
69
|
+
// Set verbose mode globally for cursor-client to pick up
|
|
70
|
+
if (options?.verbose) {
|
|
71
|
+
process.env.GITNEXUS_VERBOSE = '1';
|
|
72
|
+
}
|
|
68
73
|
console.log('\n GitNexus Wiki Generator\n');
|
|
69
74
|
// ── Resolve repo path ───────────────────────────────────────────────
|
|
70
75
|
let repoPath;
|
|
@@ -96,94 +101,130 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
96
101
|
}
|
|
97
102
|
// ── Resolve LLM config (with interactive fallback) ─────────────────
|
|
98
103
|
// Save any CLI overrides immediately
|
|
99
|
-
if (options?.apiKey || options?.model || options?.baseUrl) {
|
|
104
|
+
if (options?.apiKey || options?.model || options?.baseUrl || options?.provider) {
|
|
100
105
|
const existing = await loadCLIConfig();
|
|
101
106
|
const updates = {};
|
|
102
107
|
if (options.apiKey)
|
|
103
108
|
updates.apiKey = options.apiKey;
|
|
104
|
-
if (options.model)
|
|
105
|
-
updates.model = options.model;
|
|
106
109
|
if (options.baseUrl)
|
|
107
110
|
updates.baseUrl = options.baseUrl;
|
|
111
|
+
if (options.provider)
|
|
112
|
+
updates.provider = options.provider;
|
|
113
|
+
// Save model to appropriate field based on provider
|
|
114
|
+
if (options.model) {
|
|
115
|
+
if (options.provider === 'cursor') {
|
|
116
|
+
updates.cursorModel = options.model;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
updates.model = options.model;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
108
122
|
await saveCLIConfig({ ...existing, ...updates });
|
|
109
123
|
console.log(' Config saved to ~/.gitnexus/config.json\n');
|
|
110
124
|
}
|
|
111
125
|
const savedConfig = await loadCLIConfig();
|
|
112
|
-
const hasSavedConfig = !!(savedConfig.apiKey && savedConfig.baseUrl);
|
|
113
|
-
const hasCLIOverrides = !!(options?.apiKey || options?.model || options?.baseUrl);
|
|
126
|
+
const hasSavedConfig = !!(savedConfig.provider === 'cursor' || (savedConfig.apiKey && savedConfig.baseUrl));
|
|
127
|
+
const hasCLIOverrides = !!(options?.apiKey || options?.model || options?.baseUrl || options?.provider);
|
|
114
128
|
let llmConfig = await resolveLLMConfig({
|
|
115
129
|
model: options?.model,
|
|
116
130
|
baseUrl: options?.baseUrl,
|
|
117
131
|
apiKey: options?.apiKey,
|
|
132
|
+
provider: options?.provider,
|
|
118
133
|
});
|
|
119
134
|
// Run interactive setup if no saved config and no CLI flags provided
|
|
120
135
|
// (even if env vars exist — let user explicitly choose their provider)
|
|
121
136
|
if (!hasSavedConfig && !hasCLIOverrides) {
|
|
122
137
|
if (!process.stdin.isTTY) {
|
|
123
|
-
|
|
138
|
+
// Non-interactive mode — need either API key or Cursor CLI
|
|
139
|
+
if (!llmConfig.apiKey && llmConfig.provider !== 'cursor') {
|
|
124
140
|
console.log(' Error: No LLM API key found.');
|
|
125
141
|
console.log(' Set OPENAI_API_KEY or GITNEXUS_API_KEY environment variable,');
|
|
126
|
-
console.log(' or pass --api-key <key
|
|
142
|
+
console.log(' or pass --api-key <key>, or use --provider cursor.\n');
|
|
127
143
|
process.exitCode = 1;
|
|
128
144
|
return;
|
|
129
145
|
}
|
|
130
|
-
// Non-interactive with env var — just use it
|
|
146
|
+
// Non-interactive with env var or cursor — just use it
|
|
131
147
|
}
|
|
132
148
|
else {
|
|
133
149
|
console.log(' No LLM configured. Let\'s set it up.\n');
|
|
134
|
-
console.log(' Supports OpenAI, OpenRouter,
|
|
150
|
+
console.log(' Supports OpenAI, OpenRouter, any OpenAI-compatible API, or Cursor CLI.\n');
|
|
151
|
+
// Check if Cursor CLI is available
|
|
152
|
+
const hasCursor = detectCursorCLI();
|
|
135
153
|
// Provider selection
|
|
136
154
|
console.log(' [1] OpenAI (api.openai.com)');
|
|
137
155
|
console.log(' [2] OpenRouter (openrouter.ai)');
|
|
138
|
-
console.log(' [3] Custom endpoint
|
|
139
|
-
|
|
156
|
+
console.log(' [3] Custom endpoint');
|
|
157
|
+
if (hasCursor) {
|
|
158
|
+
console.log(' [4] Cursor CLI (local, uses your Cursor subscription)');
|
|
159
|
+
}
|
|
160
|
+
console.log('');
|
|
161
|
+
const maxChoice = hasCursor ? '4' : '3';
|
|
162
|
+
const choice = await prompt(` Select provider (1/${maxChoice}): `);
|
|
140
163
|
let baseUrl;
|
|
141
164
|
let defaultModel;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
baseUrl =
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
165
|
+
let provider = 'openai';
|
|
166
|
+
let key = '';
|
|
167
|
+
if (choice === '4' && hasCursor) {
|
|
168
|
+
// Cursor CLI selected - model defaults to 'auto' (Cursor's default)
|
|
169
|
+
provider = 'cursor';
|
|
170
|
+
baseUrl = '';
|
|
171
|
+
const modelInput = await prompt(' Model (leave empty for auto): ');
|
|
172
|
+
const model = modelInput || '';
|
|
173
|
+
// Save config for Cursor
|
|
174
|
+
const cursorConfig = { provider: 'cursor' };
|
|
175
|
+
if (model)
|
|
176
|
+
cursorConfig.cursorModel = model;
|
|
177
|
+
await saveCLIConfig(cursorConfig);
|
|
178
|
+
console.log(' Config saved to ~/.gitnexus/config.json\n');
|
|
179
|
+
llmConfig = { ...llmConfig, provider: 'cursor', model, apiKey: '', baseUrl: '' };
|
|
154
180
|
}
|
|
155
181
|
else {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
182
|
+
// OpenAI-compatible provider
|
|
183
|
+
if (choice === '2') {
|
|
184
|
+
baseUrl = 'https://openrouter.ai/api/v1';
|
|
185
|
+
defaultModel = 'minimax/minimax-m2.5';
|
|
186
|
+
}
|
|
187
|
+
else if (choice === '3') {
|
|
188
|
+
baseUrl = await prompt(' Base URL (e.g. http://localhost:11434/v1): ');
|
|
189
|
+
if (!baseUrl) {
|
|
190
|
+
console.log('\n No URL provided. Aborting.\n');
|
|
191
|
+
process.exitCode = 1;
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
defaultModel = 'gpt-4o-mini';
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
baseUrl = 'https://api.openai.com/v1';
|
|
198
|
+
defaultModel = 'gpt-4o-mini';
|
|
199
|
+
}
|
|
200
|
+
// Model
|
|
201
|
+
const modelInput = await prompt(` Model (default: ${defaultModel}): `);
|
|
202
|
+
const model = modelInput || defaultModel;
|
|
203
|
+
// API key — pre-fill hint if env var exists
|
|
204
|
+
const envKey = process.env.GITNEXUS_API_KEY || process.env.OPENAI_API_KEY || '';
|
|
205
|
+
if (envKey) {
|
|
206
|
+
const masked = envKey.slice(0, 6) + '...' + envKey.slice(-4);
|
|
207
|
+
const useEnv = await prompt(` Use existing env key (${masked})? (Y/n): `);
|
|
208
|
+
if (!useEnv || useEnv.toLowerCase() === 'y' || useEnv.toLowerCase() === 'yes') {
|
|
209
|
+
key = envKey;
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
key = await prompt(' API key: ', true);
|
|
213
|
+
}
|
|
170
214
|
}
|
|
171
215
|
else {
|
|
172
216
|
key = await prompt(' API key: ', true);
|
|
173
217
|
}
|
|
218
|
+
if (!key) {
|
|
219
|
+
console.log('\n No key provided. Aborting.\n');
|
|
220
|
+
process.exitCode = 1;
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
// Save
|
|
224
|
+
await saveCLIConfig({ apiKey: key, baseUrl, model, provider: 'openai' });
|
|
225
|
+
console.log(' Config saved to ~/.gitnexus/config.json\n');
|
|
226
|
+
llmConfig = { ...llmConfig, apiKey: key, baseUrl, model, provider: 'openai' };
|
|
174
227
|
}
|
|
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
228
|
}
|
|
188
229
|
}
|
|
189
230
|
// ── Setup progress bar with elapsed timer ──────────────────────────
|
|
@@ -213,9 +254,8 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
213
254
|
// ── Run generator ───────────────────────────────────────────────────
|
|
214
255
|
const wikiOptions = {
|
|
215
256
|
force: options?.force,
|
|
216
|
-
model: options?.model,
|
|
217
|
-
baseUrl: options?.baseUrl,
|
|
218
257
|
concurrency: options?.concurrency ? parseInt(options.concurrency, 10) : undefined,
|
|
258
|
+
reviewOnly: options?.review,
|
|
219
259
|
};
|
|
220
260
|
const generator = new WikiGenerator(repoPath, storagePath, lbugPath, llmConfig, wikiOptions, (phase, percent, detail) => {
|
|
221
261
|
const label = detail || phase;
|
|
@@ -228,11 +268,92 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
228
268
|
try {
|
|
229
269
|
const result = await generator.run();
|
|
230
270
|
clearInterval(elapsedTimer);
|
|
231
|
-
bar.update(100, { phase: 'Done' });
|
|
232
271
|
bar.stop();
|
|
233
272
|
const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
|
|
234
273
|
const wikiDir = path.join(storagePath, 'wiki');
|
|
235
274
|
const viewerPath = path.join(wikiDir, 'index.html');
|
|
275
|
+
const treeFile = path.join(wikiDir, 'module_tree.json');
|
|
276
|
+
// Review mode: show module tree and ask for confirmation
|
|
277
|
+
if (options?.review && result.moduleTree) {
|
|
278
|
+
console.log(`\n Module structure ready for review (${elapsed}s)\n`);
|
|
279
|
+
console.log(' Modules to generate:\n');
|
|
280
|
+
const printTree = (nodes, indent = 0) => {
|
|
281
|
+
for (const node of nodes) {
|
|
282
|
+
const prefix = ' '.repeat(indent + 2);
|
|
283
|
+
const fileCount = node.files?.length || 0;
|
|
284
|
+
const childCount = node.children?.length || 0;
|
|
285
|
+
const suffix = fileCount > 0 ? ` (${fileCount} files)` : childCount > 0 ? ` (${childCount} children)` : '';
|
|
286
|
+
console.log(`${prefix}- ${node.name}${suffix}`);
|
|
287
|
+
if (node.children && node.children.length > 0) {
|
|
288
|
+
printTree(node.children, indent + 1);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
printTree(result.moduleTree);
|
|
293
|
+
console.log(`\n Tree saved to: ${treeFile}`);
|
|
294
|
+
console.log(' You can edit this file to remove/rename modules.\n');
|
|
295
|
+
// Ask for confirmation (auto-continue in non-interactive environments)
|
|
296
|
+
if (!process.stdin.isTTY) {
|
|
297
|
+
console.log(' Non-interactive mode — auto-continuing with generation.\n');
|
|
298
|
+
}
|
|
299
|
+
const answer = process.stdin.isTTY
|
|
300
|
+
? await prompt(' Continue with generation? (Y/n/edit): ')
|
|
301
|
+
: 'y';
|
|
302
|
+
const choice = answer.trim().toLowerCase();
|
|
303
|
+
if (choice === 'n' || choice === 'no') {
|
|
304
|
+
console.log('\n Generation cancelled. Run `gitnexus wiki` later to generate.\n');
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
if (choice === 'edit' || choice === 'e') {
|
|
308
|
+
// Open editor for the user
|
|
309
|
+
const editor = process.env.EDITOR || process.env.VISUAL || 'vi';
|
|
310
|
+
console.log(`\n Opening ${treeFile} in ${editor}...`);
|
|
311
|
+
console.log(' Save and close the editor when done.\n');
|
|
312
|
+
try {
|
|
313
|
+
execSync(`${editor} "${treeFile}"`, { stdio: 'inherit' });
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
console.log(` Could not open editor. Please edit manually:\n ${treeFile}\n`);
|
|
317
|
+
console.log(' Then run `gitnexus wiki` to continue.\n');
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Continue with generation using the (possibly edited) tree
|
|
322
|
+
console.log('\n Continuing with wiki generation...\n');
|
|
323
|
+
bar.start(100, 30, { phase: 'Generating pages...' });
|
|
324
|
+
// Re-run generator without reviewOnly flag
|
|
325
|
+
const continueOptions = {
|
|
326
|
+
...wikiOptions,
|
|
327
|
+
reviewOnly: false,
|
|
328
|
+
};
|
|
329
|
+
const continueGenerator = new WikiGenerator(repoPath, storagePath, lbugPath, llmConfig, continueOptions, (phase, percent, detail) => {
|
|
330
|
+
const label = detail || phase;
|
|
331
|
+
if (label !== lastPhase) {
|
|
332
|
+
lastPhase = label;
|
|
333
|
+
phaseStart = Date.now();
|
|
334
|
+
}
|
|
335
|
+
bar.update(percent, { phase: label });
|
|
336
|
+
});
|
|
337
|
+
const continueResult = await continueGenerator.run();
|
|
338
|
+
bar.update(100, { phase: 'Done' });
|
|
339
|
+
bar.stop();
|
|
340
|
+
const totalElapsed = ((Date.now() - t0) / 1000).toFixed(1);
|
|
341
|
+
console.log(`\n Wiki generated successfully (${totalElapsed}s)\n`);
|
|
342
|
+
console.log(` Mode: ${continueResult.mode}`);
|
|
343
|
+
console.log(` Pages: ${continueResult.pagesGenerated}`);
|
|
344
|
+
console.log(` Output: ${wikiDir}`);
|
|
345
|
+
console.log(` Viewer: ${viewerPath}`);
|
|
346
|
+
if (continueResult.failedModules && continueResult.failedModules.length > 0) {
|
|
347
|
+
console.log(`\n Failed modules (${continueResult.failedModules.length}):`);
|
|
348
|
+
for (const mod of continueResult.failedModules) {
|
|
349
|
+
console.log(` - ${mod}`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
console.log('');
|
|
353
|
+
await maybePublishGist(viewerPath, options?.gist);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
bar.update(100, { phase: 'Done' });
|
|
236
357
|
if (result.mode === 'up-to-date' && !options?.force) {
|
|
237
358
|
console.log('\n Wiki is already up to date.');
|
|
238
359
|
console.log(` Viewer: ${viewerPath}\n`);
|
|
@@ -280,7 +401,7 @@ export const wikiCommand = async (inputPath, options) => {
|
|
|
280
401
|
}
|
|
281
402
|
else {
|
|
282
403
|
console.log(`\n Error: ${err.message}\n`);
|
|
283
|
-
if (process.env.
|
|
404
|
+
if (process.env.GITNEXUS_VERBOSE) {
|
|
284
405
|
console.error(err);
|
|
285
406
|
}
|
|
286
407
|
}
|
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HOW TO ADD A NEW LANGUAGE:
|
|
3
|
+
*
|
|
4
|
+
* 1. Add the enum member below (e.g., Scala = 'scala')
|
|
5
|
+
* 2. Run `tsc --noEmit` — compiler errors guide you to every dispatch table
|
|
6
|
+
* 3. Use this checklist for each file:
|
|
7
|
+
*
|
|
8
|
+
* FILE | WHAT TO ADD | DEFAULT (simple languages)
|
|
9
|
+
* ----------------------------------|------------------------------------------|---------------------------
|
|
10
|
+
* tree-sitter-queries.ts | Query string + LANGUAGE_QUERIES entry | (required)
|
|
11
|
+
* export-detection.ts | ExportChecker function + table entry | (required)
|
|
12
|
+
* import-resolvers/<lang>.ts | Exported resolve<Lang>Import function | resolveStandard(...)
|
|
13
|
+
* call-routing.ts | CallRouter function (or noRouting) | noRouting
|
|
14
|
+
* entry-point-scoring.ts | ENTRY_POINT_PATTERNS entry | []
|
|
15
|
+
* framework-detection.ts | AST_FRAMEWORK_PATTERNS entry | []
|
|
16
|
+
* type-extractors/<lang>.ts | New file + index.ts import | (required)
|
|
17
|
+
* resolvers/<lang>.ts | Resolver file (if non-standard) | (only if resolveStandard insufficient)
|
|
18
|
+
* named-bindings/<lang>.ts | Extractor (if named imports) | (only if language has named imports)
|
|
19
|
+
*
|
|
20
|
+
* 4. Also check these files for language-specific if-checks (no compile-time guard):
|
|
21
|
+
* - mro-processor.ts (MRO strategy selection)
|
|
22
|
+
* - heritage-processor.ts (extends/implements handling)
|
|
23
|
+
* - parse-worker.ts (AST edge cases)
|
|
24
|
+
* - parsing-processor.ts (node label normalization)
|
|
25
|
+
*
|
|
26
|
+
* 5. Add tree-sitter-<lang> to package.json dependencies
|
|
27
|
+
* 6. Add file extension mapping in utils.ts getLanguageFromFilename()
|
|
28
|
+
* 7. Run full test suite
|
|
29
|
+
*/
|
|
1
30
|
export declare enum SupportedLanguages {
|
|
2
31
|
JavaScript = "javascript",
|
|
3
32
|
TypeScript = "typescript",
|
|
@@ -11,5 +40,8 @@ export declare enum SupportedLanguages {
|
|
|
11
40
|
Rust = "rust",
|
|
12
41
|
PHP = "php",
|
|
13
42
|
Kotlin = "kotlin",
|
|
14
|
-
Swift = "swift"
|
|
43
|
+
Swift = "swift",
|
|
44
|
+
Dart = "dart",
|
|
45
|
+
/** Standalone regex processor — no tree-sitter, no LanguageProvider. */
|
|
46
|
+
Cobol = "cobol"
|
|
15
47
|
}
|
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HOW TO ADD A NEW LANGUAGE:
|
|
3
|
+
*
|
|
4
|
+
* 1. Add the enum member below (e.g., Scala = 'scala')
|
|
5
|
+
* 2. Run `tsc --noEmit` — compiler errors guide you to every dispatch table
|
|
6
|
+
* 3. Use this checklist for each file:
|
|
7
|
+
*
|
|
8
|
+
* FILE | WHAT TO ADD | DEFAULT (simple languages)
|
|
9
|
+
* ----------------------------------|------------------------------------------|---------------------------
|
|
10
|
+
* tree-sitter-queries.ts | Query string + LANGUAGE_QUERIES entry | (required)
|
|
11
|
+
* export-detection.ts | ExportChecker function + table entry | (required)
|
|
12
|
+
* import-resolvers/<lang>.ts | Exported resolve<Lang>Import function | resolveStandard(...)
|
|
13
|
+
* call-routing.ts | CallRouter function (or noRouting) | noRouting
|
|
14
|
+
* entry-point-scoring.ts | ENTRY_POINT_PATTERNS entry | []
|
|
15
|
+
* framework-detection.ts | AST_FRAMEWORK_PATTERNS entry | []
|
|
16
|
+
* type-extractors/<lang>.ts | New file + index.ts import | (required)
|
|
17
|
+
* resolvers/<lang>.ts | Resolver file (if non-standard) | (only if resolveStandard insufficient)
|
|
18
|
+
* named-bindings/<lang>.ts | Extractor (if named imports) | (only if language has named imports)
|
|
19
|
+
*
|
|
20
|
+
* 4. Also check these files for language-specific if-checks (no compile-time guard):
|
|
21
|
+
* - mro-processor.ts (MRO strategy selection)
|
|
22
|
+
* - heritage-processor.ts (extends/implements handling)
|
|
23
|
+
* - parse-worker.ts (AST edge cases)
|
|
24
|
+
* - parsing-processor.ts (node label normalization)
|
|
25
|
+
*
|
|
26
|
+
* 5. Add tree-sitter-<lang> to package.json dependencies
|
|
27
|
+
* 6. Add file extension mapping in utils.ts getLanguageFromFilename()
|
|
28
|
+
* 7. Run full test suite
|
|
29
|
+
*/
|
|
1
30
|
export var SupportedLanguages;
|
|
2
31
|
(function (SupportedLanguages) {
|
|
3
32
|
SupportedLanguages["JavaScript"] = "javascript";
|
|
@@ -13,4 +42,7 @@ export var SupportedLanguages;
|
|
|
13
42
|
SupportedLanguages["PHP"] = "php";
|
|
14
43
|
SupportedLanguages["Kotlin"] = "kotlin";
|
|
15
44
|
SupportedLanguages["Swift"] = "swift";
|
|
45
|
+
SupportedLanguages["Dart"] = "dart";
|
|
46
|
+
/** Standalone regex processor — no tree-sitter, no LanguageProvider. */
|
|
47
|
+
SupportedLanguages["Cobol"] = "cobol";
|
|
16
48
|
})(SupportedLanguages || (SupportedLanguages = {}));
|
|
@@ -30,6 +30,11 @@ export declare const initEmbedder: (onProgress?: ModelProgressCallback, config?:
|
|
|
30
30
|
* Check if the embedder is initialized and ready
|
|
31
31
|
*/
|
|
32
32
|
export declare const isEmbedderReady: () => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Get the effective embedding dimensions.
|
|
35
|
+
* In HTTP mode, uses GITNEXUS_EMBEDDING_DIMS if set, otherwise the default.
|
|
36
|
+
*/
|
|
37
|
+
export declare const getEmbeddingDimensions: () => number;
|
|
33
38
|
/**
|
|
34
39
|
* Get the embedder instance (throws if not initialized)
|
|
35
40
|
*/
|
|
@@ -38,7 +43,7 @@ export declare const getEmbedder: () => FeatureExtractionPipeline;
|
|
|
38
43
|
* Embed a single text string
|
|
39
44
|
*
|
|
40
45
|
* @param text - Text to embed
|
|
41
|
-
* @returns Float32Array of embedding vector
|
|
46
|
+
* @returns Float32Array of embedding vector
|
|
42
47
|
*/
|
|
43
48
|
export declare const embedText: (text: string) => Promise<Float32Array>;
|
|
44
49
|
/**
|
|
@@ -15,17 +15,53 @@ if (!process.env.ORT_LOG_LEVEL) {
|
|
|
15
15
|
import { pipeline, env } from '@huggingface/transformers';
|
|
16
16
|
import { existsSync } from 'fs';
|
|
17
17
|
import { execFileSync } from 'child_process';
|
|
18
|
-
import { join } from 'path';
|
|
18
|
+
import { join, dirname } from 'path';
|
|
19
|
+
import { createRequire } from 'module';
|
|
19
20
|
import { DEFAULT_EMBEDDING_CONFIG } from './types.js';
|
|
21
|
+
import { isHttpMode, getHttpDimensions, httpEmbed } from './http-client.js';
|
|
22
|
+
/**
|
|
23
|
+
* Check whether the onnxruntime-node package that @huggingface/transformers
|
|
24
|
+
* will actually load at runtime ships the CUDA execution provider.
|
|
25
|
+
*
|
|
26
|
+
* Critical: we resolve from transformers' own module scope, NOT from ours.
|
|
27
|
+
* npm may install two copies — a top-level 1.24.x (our dep) and a nested
|
|
28
|
+
* 1.21.0 (transformers' pinned dep). The guard must inspect whichever copy
|
|
29
|
+
* transformers.js will dlopen, otherwise the check is meaningless.
|
|
30
|
+
*/
|
|
31
|
+
function hasOrtCudaProvider() {
|
|
32
|
+
try {
|
|
33
|
+
const require = createRequire(import.meta.url);
|
|
34
|
+
// Resolve from @huggingface/transformers' scope so we find the same
|
|
35
|
+
// onnxruntime-node binary that transformers.js will use at runtime
|
|
36
|
+
const transformersDir = dirname(require.resolve('@huggingface/transformers/package.json'));
|
|
37
|
+
const ortRequire = createRequire(join(transformersDir, 'package.json'));
|
|
38
|
+
const ortPath = dirname(ortRequire.resolve('onnxruntime-node/package.json'));
|
|
39
|
+
// ORT 1.24.x only ships CUDA binaries for linux/x64 (downloaded from NuGet
|
|
40
|
+
// at postinstall). arm64 will correctly return false here until ORT adds support.
|
|
41
|
+
const arch = process.arch;
|
|
42
|
+
return existsSync(join(ortPath, 'bin', 'napi-v6', 'linux', arch, 'libonnxruntime_providers_cuda.so'));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
20
48
|
/**
|
|
21
49
|
* Check whether CUDA libraries are actually available on this system.
|
|
22
50
|
* ONNX Runtime's native layer crashes (uncatchable) if we attempt CUDA
|
|
23
51
|
* without the required shared libraries, so we probe first.
|
|
24
52
|
*
|
|
25
|
-
* Checks
|
|
26
|
-
*
|
|
53
|
+
* Checks both:
|
|
54
|
+
* 1. That system CUDA libraries (libcublasLt) are present
|
|
55
|
+
* 2. That onnxruntime-node ships the CUDA execution provider binary
|
|
56
|
+
*
|
|
57
|
+
* Both conditions must be true — system CUDA libs alone are not enough
|
|
58
|
+
* if onnxruntime-node is a CPU-only build (versions < 1.24.0).
|
|
27
59
|
*/
|
|
28
60
|
function isCudaAvailable() {
|
|
61
|
+
// First, verify onnxruntime-node has the CUDA provider binary.
|
|
62
|
+
// Without this, requesting CUDA causes an uncatchable native crash.
|
|
63
|
+
if (!hasOrtCudaProvider())
|
|
64
|
+
return false;
|
|
29
65
|
// Primary: query the dynamic linker cache — covers all architectures,
|
|
30
66
|
// distro layouts, and custom install paths registered with ldconfig
|
|
31
67
|
try {
|
|
@@ -70,6 +106,10 @@ export const getCurrentDevice = () => currentDevice;
|
|
|
70
106
|
* @returns Promise resolving to the embedder pipeline
|
|
71
107
|
*/
|
|
72
108
|
export const initEmbedder = async (onProgress, config = {}, forceDevice) => {
|
|
109
|
+
if (isHttpMode()) {
|
|
110
|
+
throw new Error('initEmbedder() should not be called in HTTP mode. ' +
|
|
111
|
+
'Use embedText()/embedBatch() which handle HTTP transparently.');
|
|
112
|
+
}
|
|
73
113
|
// Return existing instance if available
|
|
74
114
|
if (embedderInstance) {
|
|
75
115
|
return embedderInstance;
|
|
@@ -169,12 +209,25 @@ export const initEmbedder = async (onProgress, config = {}, forceDevice) => {
|
|
|
169
209
|
* Check if the embedder is initialized and ready
|
|
170
210
|
*/
|
|
171
211
|
export const isEmbedderReady = () => {
|
|
172
|
-
return embedderInstance !== null;
|
|
212
|
+
return isHttpMode() || embedderInstance !== null;
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* Get the effective embedding dimensions.
|
|
216
|
+
* In HTTP mode, uses GITNEXUS_EMBEDDING_DIMS if set, otherwise the default.
|
|
217
|
+
*/
|
|
218
|
+
export const getEmbeddingDimensions = () => {
|
|
219
|
+
if (isHttpMode()) {
|
|
220
|
+
return getHttpDimensions() ?? DEFAULT_EMBEDDING_CONFIG.dimensions;
|
|
221
|
+
}
|
|
222
|
+
return DEFAULT_EMBEDDING_CONFIG.dimensions;
|
|
173
223
|
};
|
|
174
224
|
/**
|
|
175
225
|
* Get the embedder instance (throws if not initialized)
|
|
176
226
|
*/
|
|
177
227
|
export const getEmbedder = () => {
|
|
228
|
+
if (isHttpMode()) {
|
|
229
|
+
throw new Error('getEmbedder() is not available in HTTP embedding mode. Use embedText()/embedBatch() instead.');
|
|
230
|
+
}
|
|
178
231
|
if (!embedderInstance) {
|
|
179
232
|
throw new Error('Embedder not initialized. Call initEmbedder() first.');
|
|
180
233
|
}
|
|
@@ -184,9 +237,13 @@ export const getEmbedder = () => {
|
|
|
184
237
|
* Embed a single text string
|
|
185
238
|
*
|
|
186
239
|
* @param text - Text to embed
|
|
187
|
-
* @returns Float32Array of embedding vector
|
|
240
|
+
* @returns Float32Array of embedding vector
|
|
188
241
|
*/
|
|
189
242
|
export const embedText = async (text) => {
|
|
243
|
+
if (isHttpMode()) {
|
|
244
|
+
const [vec] = await httpEmbed([text]);
|
|
245
|
+
return vec;
|
|
246
|
+
}
|
|
190
247
|
const embedder = getEmbedder();
|
|
191
248
|
const result = await embedder(text, {
|
|
192
249
|
pooling: 'mean',
|
|
@@ -206,6 +263,9 @@ export const embedBatch = async (texts) => {
|
|
|
206
263
|
if (texts.length === 0) {
|
|
207
264
|
return [];
|
|
208
265
|
}
|
|
266
|
+
if (isHttpMode()) {
|
|
267
|
+
return httpEmbed(texts);
|
|
268
|
+
}
|
|
209
269
|
const embedder = getEmbedder();
|
|
210
270
|
// Process batch
|
|
211
271
|
const result = await embedder(texts, {
|
|
@@ -121,14 +121,16 @@ export const runEmbeddingPipeline = async (executeQuery, executeWithReusedStatem
|
|
|
121
121
|
percent: 0,
|
|
122
122
|
modelDownloadPercent: 0,
|
|
123
123
|
});
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
124
|
+
if (!isEmbedderReady()) {
|
|
125
|
+
await initEmbedder((modelProgress) => {
|
|
126
|
+
const downloadPercent = modelProgress.progress ?? 0;
|
|
127
|
+
onProgress({
|
|
128
|
+
phase: 'loading-model',
|
|
129
|
+
percent: Math.round(downloadPercent * 0.2),
|
|
130
|
+
modelDownloadPercent: downloadPercent,
|
|
131
|
+
});
|
|
132
|
+
}, finalConfig);
|
|
133
|
+
}
|
|
132
134
|
onProgress({
|
|
133
135
|
phase: 'loading-model',
|
|
134
136
|
percent: 20,
|
|
@@ -255,7 +257,7 @@ export const semanticSearch = async (executeQuery, query, k = 10, maxDistance =
|
|
|
255
257
|
// Query the vector index on CodeEmbedding to get nodeIds and distances
|
|
256
258
|
const vectorQuery = `
|
|
257
259
|
CALL QUERY_VECTOR_INDEX('CodeEmbedding', 'code_embedding_idx',
|
|
258
|
-
CAST(${queryVecStr} AS FLOAT[
|
|
260
|
+
CAST(${queryVecStr} AS FLOAT[${queryVec.length}]), ${k})
|
|
259
261
|
YIELD node AS emb, distance
|
|
260
262
|
WITH emb, distance
|
|
261
263
|
WHERE distance < ${maxDistance}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP Embedding Client
|
|
3
|
+
*
|
|
4
|
+
* Shared fetch+retry logic for OpenAI-compatible /v1/embeddings endpoints.
|
|
5
|
+
* Imported by both the core embedder (batch) and MCP embedder (query).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check whether HTTP embedding mode is active (env vars are set).
|
|
9
|
+
*/
|
|
10
|
+
export declare const isHttpMode: () => boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Return the configured embedding dimensions for HTTP mode, or undefined
|
|
13
|
+
* if HTTP mode is not active or no explicit dimensions are set.
|
|
14
|
+
*/
|
|
15
|
+
export declare const getHttpDimensions: () => number | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Embed texts via the HTTP backend, splitting into batches.
|
|
18
|
+
* Reads config from env vars on every call.
|
|
19
|
+
*
|
|
20
|
+
* @param texts - Array of texts to embed
|
|
21
|
+
* @returns Array of Float32Array embedding vectors
|
|
22
|
+
*/
|
|
23
|
+
export declare const httpEmbed: (texts: string[]) => Promise<Float32Array[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Embed a single query text via the HTTP backend.
|
|
26
|
+
* Convenience for MCP search where only one vector is needed.
|
|
27
|
+
*
|
|
28
|
+
* @param text - Query text to embed
|
|
29
|
+
* @returns Embedding vector as number array
|
|
30
|
+
*/
|
|
31
|
+
export declare const httpEmbedQuery: (text: string) => Promise<number[]>;
|