gitnexus 1.6.10-rc.32 → 1.6.10-rc.34

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 CHANGED
@@ -249,6 +249,8 @@ gitnexus clean # Delete index for current repo
249
249
  gitnexus clean --all --force # Delete all indexes
250
250
  gitnexus wiki [path] # Generate LLM-powered docs from knowledge graph
251
251
  gitnexus wiki --model <model> # Wiki with custom LLM model (default: minimax/minimax-m2.5)
252
+ gitnexus wiki --base-url http://llama-box.local:8080/v1 --allow-insecure-connection llama-box.local
253
+ # Allow an exact LAN/self-hosted HTTP LLM host; env: GITNEXUS_ALLOW_INSECURE_CONNECTION
252
254
  gitnexus doctor # Show runtime platform capabilities and embedding configuration
253
255
 
254
256
  # Direct graph queries — the same tools the MCP server exposes, no MCP daemon needed
@@ -461,14 +463,14 @@ GitNexus uses optional DuckDB extensions for BM25 and vector search. The `gitnex
461
463
 
462
464
  Configure the behavior with these environment variables:
463
465
 
464
- | Variable | Values | Default | Effect |
465
- | -------------------------------------------- | ---------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
466
- | `GITNEXUS_LBUG_EXTENSION_INSTALL` | `auto`, `load-only`, `never` | `auto` | `auto` runs one bounded install if LOAD fails — a plain `INSTALL`, escalating to `FORCE INSTALL` only when the LOAD error shows the present extension file is broken. `load-only` only uses already-installed extensions (recommended for offline / firewalled environments). `never` skips optional extensions entirely. |
467
- | `GITNEXUS_LBUG_EXTENSION_INSTALL_TIMEOUT_MS` | positive integer | `15000` | Wall-clock budget for the out-of-process extension-install child before it is killed. |
468
- | `GITNEXUS_FTS_STEMMER` | supported LadybugDB stemmer | `porter` | Stemmer used when rebuilding BM25/FTS indexes. Use `none` for CJK-heavy repositories, or a language stemmer such as `german`, `french`, or `spanish` when that better matches repository comments and identifiers. Re-run `gitnexus analyze --repair-fts` after changing it. |
469
- | `GITNEXUS_FTS_CJK_SEGMENTATION` | `none`, `bigram` | `none` | `bigram` inserts overlapping character-bigram boundaries into Chinese/Japanese Han-ideograph spans in `content`/`description` before FTS indexing, so LadybugDB's space-only tokenizer can see sub-phrase word boundaries. Scoped to CJK Unified Ideographs only — Japanese Hiragana/Katakana and Korean Hangul are not currently segmented. Unlike `GITNEXUS_FTS_STEMMER`, this rewrites stored text — enabling it on an already-indexed repo requires a full `gitnexus analyze --force`; neither `--repair-fts` nor a plain incremental `analyze` applies it to previously-indexed files. Set the same value wherever `analyze` and search-serving processes (CLI query, MCP server, web server) run. |
470
- | `GITNEXUS_COMMUNITY_ENGINE` | `graphology`, `icebug`, `auto` | `graphology` | Community-detection engine used during analyze. `graphology` uses the bundled default path. `icebug` and `auto` currently behave identically: both try the experimental Icebug CSR path and fall back to Graphology if the optional native module is unavailable or incompatible. |
471
- | `GITNEXUS_WAL_CHECKPOINT_THRESHOLD` | integer `>= -1` | `67108864` (64 MiB) | LadybugDB WAL auto-checkpoint threshold during analyze (bytes). Auto-checkpoint remains enabled; `-1` keeps Ladybug's stock ~16 MiB. Larger thresholds reduce checkpoint frequency but increase the WAL size at rotation time — choose a smaller value on disk-constrained environments. |
466
+ | Variable | Values | Default | Effect |
467
+ | -------------------------------------------- | ------------------------------ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
468
+ | `GITNEXUS_LBUG_EXTENSION_INSTALL` | `auto`, `load-only`, `never` | `auto` | `auto` runs one bounded install if LOAD fails — a plain `INSTALL`, escalating to `FORCE INSTALL` only when the LOAD error shows the present extension file is broken. `load-only` only uses already-installed extensions (recommended for offline / firewalled environments). `never` skips optional extensions entirely. |
469
+ | `GITNEXUS_LBUG_EXTENSION_INSTALL_TIMEOUT_MS` | positive integer | `15000` | Wall-clock budget for the out-of-process extension-install child before it is killed. |
470
+ | `GITNEXUS_FTS_STEMMER` | supported LadybugDB stemmer | `porter` | Stemmer used when rebuilding BM25/FTS indexes. Use `none` for CJK-heavy repositories, or a language stemmer such as `german`, `french`, or `spanish` when that better matches repository comments and identifiers. Re-run `gitnexus analyze --repair-fts` after changing it. |
471
+ | `GITNEXUS_FTS_CJK_SEGMENTATION` | `none`, `bigram` | `none` | `bigram` inserts overlapping character-bigram boundaries into Chinese/Japanese Han-ideograph spans in `content`/`description` before FTS indexing, so LadybugDB's space-only tokenizer can see sub-phrase word boundaries. Scoped to CJK Unified Ideographs only — Japanese Hiragana/Katakana and Korean Hangul are not currently segmented. Unlike `GITNEXUS_FTS_STEMMER`, this rewrites stored text — enabling it on an already-indexed repo requires a full `gitnexus analyze --force`; neither `--repair-fts` nor a plain incremental `analyze` applies it to previously-indexed files. Set the same value wherever `analyze` and search-serving processes (CLI query, MCP server, web server) run. |
472
+ | `GITNEXUS_COMMUNITY_ENGINE` | `graphology`, `icebug`, `auto` | `graphology` | Community-detection engine used during analyze. `graphology` uses the bundled default path. `icebug` and `auto` currently behave identically: both try the experimental Icebug CSR path and fall back to Graphology if the optional native module is unavailable or incompatible. |
473
+ | `GITNEXUS_WAL_CHECKPOINT_THRESHOLD` | integer `>= -1` | `67108864` (64 MiB) | LadybugDB WAL auto-checkpoint threshold during analyze (bytes). Auto-checkpoint remains enabled; `-1` keeps Ladybug's stock ~16 MiB. Larger thresholds reduce checkpoint frequency but increase the WAL size at rotation time — choose a smaller value on disk-constrained environments. |
472
474
 
473
475
  ```bash
474
476
  # Offline/airgapped: never reach the network for extensions
@@ -533,13 +535,13 @@ For repositories with very large source files, `GITNEXUS_WORKER_SUB_BATCH_MAX_BY
533
535
 
534
536
  Three env vars expose the pool's resilience layers (respawn budget, cumulative-timeout cap, circuit breaker). Defaults are tuned for typical repos; bump them when an analyze legitimately needs more retries, or lower them to fail-fast on a known-bad shape.
535
537
 
536
- | Variable | Default | Effect |
537
- | ----------------------------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------- |
538
- | `GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT` | `3` | Max replacement spawns per slot before the slot is dropped from the active rotation. |
539
- | `GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS` | `5 × subBatchTimeoutMs` | Total retry wall-time budget per job before quarantining. Bounds exponentially-growing retry waits. |
540
- | `GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD` | `max(3, poolSize)` | Per-slot consecutive deaths before the pool's circuit breaker trips. After tripping, dispatches require a fresh pool. |
538
+ | Variable | Default | Effect |
539
+ | ----------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
540
+ | `GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT` | `3` | Max replacement spawns per slot before the slot is dropped from the active rotation. |
541
+ | `GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS` | `5 × subBatchTimeoutMs` | Total retry wall-time budget per job before quarantining. Bounds exponentially-growing retry waits. |
542
+ | `GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD` | `max(3, poolSize)` | Per-slot consecutive deaths before the pool's circuit breaker trips. After tripping, dispatches require a fresh pool. |
541
543
  | `GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS` | `30000` | Max wait at pool shutdown for a retired worker still inside native code — terminated at its next JS-safe point instead of mid-native-call, which would abort the process (`Napi::Error`, #2432). |
542
- | `GITNEXUS_CPP_CAPTURE_BUDGET_MS` | `20000` | Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning (#2432). `0` expires immediately. |
544
+ | `GITNEXUS_CPP_CAPTURE_BUDGET_MS` | `20000` | Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning (#2432). `0` expires immediately. |
543
545
 
544
546
  ### Graph cleanup tuning
545
547
 
@@ -92,6 +92,7 @@ const OPTION_DESCRIPTION_KEYS = {
92
92
  'wiki|--concurrency <n>': 'help.option.wiki.concurrency',
93
93
  'wiki|--timeout <seconds>': 'help.option.wiki.timeout',
94
94
  'wiki|--retries <n>': 'help.option.wiki.retries',
95
+ 'wiki|--allow-insecure-connection <host>': 'help.option.wiki.allowInsecureConnection',
95
96
  'wiki|--gist': 'help.option.wiki.gist',
96
97
  'wiki|-v, --verbose': 'help.option.verbose',
97
98
  'wiki|--review': 'help.option.wiki.review',
@@ -188,6 +188,7 @@ export declare const en: {
188
188
  readonly 'help.option.wiki.concurrency': "Parallel LLM calls (default: 3)";
189
189
  readonly 'help.option.wiki.timeout': "LLM request timeout in seconds (default: disabled)";
190
190
  readonly 'help.option.wiki.retries': "Max LLM retry attempts per request (default: 3)";
191
+ readonly 'help.option.wiki.allowInsecureConnection': "Allow exact host(s) for http:// LLM base URLs (comma-separated; HTTPS is preferred)";
191
192
  readonly 'help.option.wiki.gist': "Publish wiki as a public GitHub Gist after generation";
192
193
  readonly 'help.option.wiki.review': "Stop after grouping to review module structure before generating pages";
193
194
  readonly 'help.option.wiki.lang': "Output language for generated documentation (e.g. english, chinese, spanish, japanese)";
@@ -188,6 +188,7 @@ export const en = {
188
188
  'help.option.wiki.concurrency': 'Parallel LLM calls (default: 3)',
189
189
  'help.option.wiki.timeout': 'LLM request timeout in seconds (default: disabled)',
190
190
  'help.option.wiki.retries': 'Max LLM retry attempts per request (default: 3)',
191
+ 'help.option.wiki.allowInsecureConnection': 'Allow exact host(s) for http:// LLM base URLs (comma-separated; HTTPS is preferred)',
191
192
  'help.option.wiki.gist': 'Publish wiki as a public GitHub Gist after generation',
192
193
  'help.option.wiki.review': 'Stop after grouping to review module structure before generating pages',
193
194
  'help.option.wiki.lang': 'Output language for generated documentation (e.g. english, chinese, spanish, japanese)',
@@ -189,6 +189,7 @@ export declare const cliResources: {
189
189
  readonly 'help.option.wiki.concurrency': "Parallel LLM calls (default: 3)";
190
190
  readonly 'help.option.wiki.timeout': "LLM request timeout in seconds (default: disabled)";
191
191
  readonly 'help.option.wiki.retries': "Max LLM retry attempts per request (default: 3)";
192
+ readonly 'help.option.wiki.allowInsecureConnection': "Allow exact host(s) for http:// LLM base URLs (comma-separated; HTTPS is preferred)";
192
193
  readonly 'help.option.wiki.gist': "Publish wiki as a public GitHub Gist after generation";
193
194
  readonly 'help.option.wiki.review': "Stop after grouping to review module structure before generating pages";
194
195
  readonly 'help.option.wiki.lang': "Output language for generated documentation (e.g. english, chinese, spanish, japanese)";
@@ -436,6 +437,7 @@ export declare const cliResources: {
436
437
  'help.option.wiki.concurrency': string;
437
438
  'help.option.wiki.timeout': string;
438
439
  'help.option.wiki.retries': string;
440
+ 'help.option.wiki.allowInsecureConnection': string;
439
441
  'help.option.wiki.gist': string;
440
442
  'help.option.wiki.review': string;
441
443
  'help.option.wiki.lang': string;
@@ -188,6 +188,7 @@ export declare const zhCN: {
188
188
  'help.option.wiki.concurrency': string;
189
189
  'help.option.wiki.timeout': string;
190
190
  'help.option.wiki.retries': string;
191
+ 'help.option.wiki.allowInsecureConnection': string;
191
192
  'help.option.wiki.gist': string;
192
193
  'help.option.wiki.review': string;
193
194
  'help.option.wiki.lang': string;
@@ -188,6 +188,7 @@ export const zhCN = {
188
188
  'help.option.wiki.concurrency': '并行 LLM 调用数(默认:3)',
189
189
  'help.option.wiki.timeout': 'LLM 请求超时时间(秒,默认:禁用)',
190
190
  'help.option.wiki.retries': '每个请求的最大 LLM 重试次数(默认:3)',
191
+ 'help.option.wiki.allowInsecureConnection': '允许 http:// LLM base URL 使用的精确主机(逗号分隔;推荐使用 HTTPS)',
191
192
  'help.option.wiki.gist': '生成后发布 Wiki 为公开 GitHub Gist',
192
193
  'help.option.wiki.review': '分组后停止,以便在生成页面前审查模块结构',
193
194
  'help.option.wiki.lang': '生成文档的输出语言(如 english、chinese、spanish、japanese)',
package/dist/cli/index.js CHANGED
@@ -192,6 +192,7 @@ program
192
192
  .option('--concurrency <n>', 'Parallel LLM calls (default: 3)', '3')
193
193
  .option('--timeout <seconds>', 'LLM request timeout in seconds (default: disabled)')
194
194
  .option('--retries <n>', 'Max LLM retry attempts per request (default: 3)')
195
+ .option('--allow-insecure-connection <host>', 'Allow exact host(s) for http:// LLM base URLs (comma-separated; HTTPS is preferred)')
195
196
  .option('--gist', 'Publish wiki as a public GitHub Gist after generation')
196
197
  .option('-v, --verbose', 'Enable verbose output (show LLM commands and responses)')
197
198
  .option('--review', 'Stop after grouping to review module structure before generating pages')
@@ -20,5 +20,6 @@ export interface WikiCommandOptions {
20
20
  timeout?: string;
21
21
  retries?: string;
22
22
  lang?: string;
23
+ allowInsecureConnection?: string;
23
24
  }
24
25
  export declare const wikiCommand: (inputPath?: string, options?: WikiCommandOptions) => Promise<void>;
package/dist/cli/wiki.js CHANGED
@@ -11,7 +11,7 @@ import cliProgress from 'cli-progress';
11
11
  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
- import { resolveLLMConfig } from '../core/wiki/llm-client.js';
14
+ import { parseLLMAllowedInsecureHttpHosts, resolveLLMConfig, } from '../core/wiki/llm-client.js';
15
15
  import { detectCursorCLI } from '../core/wiki/cursor-client.js';
16
16
  import { detectLocalCLI } from '../core/wiki/local-cli-client.js';
17
17
  import { logger } from '../core/logger.js';
@@ -152,9 +152,14 @@ const wikiCommandImpl = async (inputPath, options) => {
152
152
  }
153
153
  let timeoutSeconds;
154
154
  let retries;
155
+ let allowedInsecureHttpHosts;
155
156
  try {
156
157
  timeoutSeconds = parsePositiveIntegerOption(options?.timeout, '--timeout', 1000);
157
158
  retries = parsePositiveIntegerOption(options?.retries, '--retries');
159
+ allowedInsecureHttpHosts =
160
+ options?.allowInsecureConnection === undefined
161
+ ? undefined
162
+ : parseLLMAllowedInsecureHttpHosts(options.allowInsecureConnection);
158
163
  }
159
164
  catch (error) {
160
165
  console.log(` Error: ${error.message}\n`);
@@ -210,6 +215,7 @@ const wikiCommandImpl = async (inputPath, options) => {
210
215
  provider: options?.provider,
211
216
  apiVersion: options?.apiVersion,
212
217
  isReasoningModel: options?.reasoningModel,
218
+ allowedInsecureHttpHosts,
213
219
  });
214
220
  // Run interactive setup if no saved config and no CLI flags provided
215
221
  // (even if env vars exist — let user explicitly choose their provider)
@@ -23,6 +23,8 @@ export interface LLMConfig {
23
23
  requestTimeoutMs?: number;
24
24
  /** Max fetch attempts before giving up (default: 3). */
25
25
  maxAttempts?: number;
26
+ /** Exact hostnames allowed for explicit http:// LLM endpoints. */
27
+ allowedInsecureHttpHosts?: readonly string[];
26
28
  }
27
29
  export interface LLMResponse {
28
30
  content: string;
@@ -40,6 +42,8 @@ export declare function resolveLLMConfig(overrides?: Partial<LLMConfig>): Promis
40
42
  * Estimate token count from text (rough heuristic: ~4 chars per token).
41
43
  */
42
44
  export declare function estimateTokens(text: string): number;
45
+ export declare const LLM_ALLOW_INSECURE_CONNECTION_ENV = "GITNEXUS_ALLOW_INSECURE_CONNECTION";
46
+ export declare function parseLLMAllowedInsecureHttpHosts(value: string | undefined): string[];
43
47
  /**
44
48
  * Validate that a base URL supplied for LLM API calls is a safe HTTP/HTTPS
45
49
  * endpoint (CWE-918 / CodeQL js/http-to-file-access).
@@ -47,15 +51,17 @@ export declare function estimateTokens(text: string): number;
47
51
  * Allowed:
48
52
  * - https:// with any hostname (public LLM APIs, Azure, OpenRouter, …)
49
53
  * - http:// restricted to localhost / 127.0.0.1 (local servers: Ollama, LiteLLM, …)
54
+ * - http:// to exact hosts explicitly allowlisted for LAN/self-hosted LLMs
50
55
  *
51
56
  * Rejected:
52
57
  * - file://, data:, javascript:, and any other non-HTTP scheme
53
- * - http:// aimed at non-loopback hosts (avoids SSRF against internal networks)
58
+ * - http:// aimed at non-loopback hosts unless explicitly allowlisted
59
+ * (avoids SSRF against internal networks by default)
54
60
  *
55
61
  * Throws with a descriptive message on validation failure so callers surface a
56
62
  * clear error rather than an opaque network error.
57
63
  */
58
- export declare function validateLLMBaseUrl(baseUrl: string): void;
64
+ export declare function validateLLMBaseUrl(baseUrl: string, allowedInsecureHttpHosts?: readonly string[]): void;
59
65
  /**
60
66
  * Returns true if the given base URL is an Azure OpenAI endpoint.
61
67
  * Uses proper hostname matching to avoid spoofed URLs like
@@ -43,6 +43,8 @@ export async function resolveLLMConfig(overrides) {
43
43
  provider: savedProvider ?? 'openai',
44
44
  apiVersion: overrides?.apiVersion || process.env.GITNEXUS_AZURE_API_VERSION || savedConfig.apiVersion,
45
45
  isReasoningModel: overrides?.isReasoningModel ?? savedConfig.isReasoningModel,
46
+ allowedInsecureHttpHosts: overrides?.allowedInsecureHttpHosts ??
47
+ parseLLMAllowedInsecureHttpHosts(process.env[LLM_ALLOW_INSECURE_CONNECTION_ENV]),
46
48
  };
47
49
  }
48
50
  /**
@@ -64,6 +66,36 @@ function isTimeoutLikeError(err) {
64
66
  return true;
65
67
  return /time(d)?\s*out|timeout/i.test(err.message);
66
68
  }
69
+ export const LLM_ALLOW_INSECURE_CONNECTION_ENV = 'GITNEXUS_ALLOW_INSECURE_CONNECTION';
70
+ function normalizeAllowedInsecureHttpHost(host) {
71
+ const trimmed = host.trim().toLowerCase();
72
+ const fail = () => {
73
+ throw new Error(`--allow-insecure-connection / ${LLM_ALLOW_INSECURE_CONNECTION_ENV} entries must be exact hostnames or IP addresses`);
74
+ };
75
+ if (!trimmed || /[/@?#]/.test(trimmed))
76
+ fail();
77
+ if (trimmed.startsWith('[')) {
78
+ if (!trimmed.endsWith(']'))
79
+ fail();
80
+ const normalized = trimmed.slice(1, -1);
81
+ if (!normalized || /[\[\]]/.test(normalized))
82
+ fail();
83
+ return normalized;
84
+ }
85
+ if (/[\[\]]/.test(trimmed))
86
+ fail();
87
+ if ((trimmed.match(/:/g)?.length ?? 0) === 1) {
88
+ // URL.hostname never includes the port, so accepting "host:port" would
89
+ // create a confusing no-op allowlist entry.
90
+ fail();
91
+ }
92
+ return trimmed;
93
+ }
94
+ export function parseLLMAllowedInsecureHttpHosts(value) {
95
+ if (value === undefined || value.trim() === '')
96
+ return [];
97
+ return [...new Set(value.split(',').map(normalizeAllowedInsecureHttpHost))];
98
+ }
67
99
  /**
68
100
  * Validate that a base URL supplied for LLM API calls is a safe HTTP/HTTPS
69
101
  * endpoint (CWE-918 / CodeQL js/http-to-file-access).
@@ -71,15 +103,17 @@ function isTimeoutLikeError(err) {
71
103
  * Allowed:
72
104
  * - https:// with any hostname (public LLM APIs, Azure, OpenRouter, …)
73
105
  * - http:// restricted to localhost / 127.0.0.1 (local servers: Ollama, LiteLLM, …)
106
+ * - http:// to exact hosts explicitly allowlisted for LAN/self-hosted LLMs
74
107
  *
75
108
  * Rejected:
76
109
  * - file://, data:, javascript:, and any other non-HTTP scheme
77
- * - http:// aimed at non-loopback hosts (avoids SSRF against internal networks)
110
+ * - http:// aimed at non-loopback hosts unless explicitly allowlisted
111
+ * (avoids SSRF against internal networks by default)
78
112
  *
79
113
  * Throws with a descriptive message on validation failure so callers surface a
80
114
  * clear error rather than an opaque network error.
81
115
  */
82
- export function validateLLMBaseUrl(baseUrl) {
116
+ export function validateLLMBaseUrl(baseUrl, allowedInsecureHttpHosts = parseLLMAllowedInsecureHttpHosts(process.env[LLM_ALLOW_INSECURE_CONNECTION_ENV])) {
83
117
  let parsed;
84
118
  try {
85
119
  parsed = new URL(baseUrl);
@@ -96,9 +130,11 @@ export function validateLLMBaseUrl(baseUrl) {
96
130
  // Node's URL parser preserves IPv6 brackets in hostname (e.g. "[::1]"),
97
131
  // so strip them before comparing to bare address literals.
98
132
  const host = parsed.hostname.toLowerCase().replace(/^\[|\]$/g, '');
99
- if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1') {
133
+ const allowedHosts = new Set(allowedInsecureHttpHosts.map(normalizeAllowedInsecureHttpHost));
134
+ if (host !== 'localhost' && host !== '127.0.0.1' && host !== '::1' && !allowedHosts.has(host)) {
100
135
  // Use parsed.origin (scheme+host+port, no credentials) instead of the full URL.
101
- throw new Error(`Insecure http:// LLM base URLs are only allowed for localhost/127.0.0.1. ` +
136
+ throw new Error(`Insecure http:// LLM base URLs are only allowed for localhost/127.0.0.1 ` +
137
+ `or hosts listed by --allow-insecure-connection / ${LLM_ALLOW_INSECURE_CONNECTION_ENV}. ` +
102
138
  `Use https:// for remote endpoints (got ${parsed.origin})`);
103
139
  }
104
140
  }
@@ -145,7 +181,7 @@ export function buildRequestUrl(baseUrl, apiVersion) {
145
181
  */
146
182
  export async function callLLM(prompt, config, systemPrompt, options) {
147
183
  // Validate base URL before any fetch (CodeQL js/http-to-file-access)
148
- validateLLMBaseUrl(config.baseUrl);
184
+ validateLLMBaseUrl(config.baseUrl, config.allowedInsecureHttpHosts);
149
185
  const messages = [];
150
186
  if (systemPrompt) {
151
187
  messages.push({ role: 'system', content: systemPrompt });
@@ -24,14 +24,6 @@ export interface ToolDefinition {
24
24
  minLength?: number;
25
25
  }>;
26
26
  required: string[];
27
- /**
28
- * JSON-Schema `anyOf` for cross-property constraints `required` cannot express
29
- * — e.g. "at least one of route/file". Forwarded verbatim to clients by the
30
- * server's ListTools handler, so MCP clients see the constraint.
31
- */
32
- anyOf?: Array<{
33
- required: string[];
34
- }>;
35
27
  };
36
28
  }
37
29
  /**
package/dist/mcp/tools.js CHANGED
@@ -726,9 +726,6 @@ Response shape is keyed on how many routes match, not on the data: exactly one m
726
726
  repo: { type: 'string', description: 'Repository name or path.' },
727
727
  },
728
728
  required: [],
729
- // Exactly one lookup key is needed, but either works (route wins if both
730
- // are passed) — so the structural constraint is "at least one of route/file".
731
- anyOf: [{ required: ['route'] }, { required: ['file'] }],
732
729
  },
733
730
  },
734
731
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitnexus",
3
- "version": "1.6.10-rc.32",
3
+ "version": "1.6.10-rc.34",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",