claude-code-workflow 6.3.19 → 6.3.20

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 (51) hide show
  1. package/.claude/agents/issue-plan-agent.md +31 -2
  2. package/.claude/commands/issue/new.md +92 -2
  3. package/.claude/commands/issue/plan.md +3 -2
  4. package/.codex/prompts/issue-execute.md +5 -0
  5. package/ccw/dist/core/routes/litellm-api-routes.d.ts.map +1 -1
  6. package/ccw/dist/core/routes/litellm-api-routes.js +8 -0
  7. package/ccw/dist/core/routes/litellm-api-routes.js.map +1 -1
  8. package/ccw/dist/core/server.d.ts.map +1 -1
  9. package/ccw/dist/core/server.js +5 -0
  10. package/ccw/dist/core/server.js.map +1 -1
  11. package/ccw/dist/core/services/api-key-tester.d.ts +11 -0
  12. package/ccw/dist/core/services/api-key-tester.d.ts.map +1 -1
  13. package/ccw/dist/core/services/api-key-tester.js +30 -10
  14. package/ccw/dist/core/services/api-key-tester.js.map +1 -1
  15. package/ccw/dist/core/services/health-check-service.d.ts +6 -0
  16. package/ccw/dist/core/services/health-check-service.d.ts.map +1 -1
  17. package/ccw/dist/core/services/health-check-service.js +22 -0
  18. package/ccw/dist/core/services/health-check-service.js.map +1 -1
  19. package/ccw/src/core/routes/litellm-api-routes.ts +8 -0
  20. package/ccw/src/core/server.ts +6 -0
  21. package/ccw/src/core/services/api-key-tester.ts +33 -10
  22. package/ccw/src/core/services/health-check-service.ts +26 -0
  23. package/ccw/src/templates/dashboard-js/i18n.js +10 -0
  24. package/ccw/src/templates/dashboard-js/views/codexlens-manager.js +10 -0
  25. package/codex-lens/src/codexlens/__pycache__/config.cpython-312.pyc +0 -0
  26. package/codex-lens/src/codexlens/__pycache__/config.cpython-313.pyc +0 -0
  27. package/codex-lens/src/codexlens/__pycache__/env_config.cpython-312.pyc +0 -0
  28. package/codex-lens/src/codexlens/__pycache__/env_config.cpython-313.pyc +0 -0
  29. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-312.pyc +0 -0
  30. package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
  31. package/codex-lens/src/codexlens/cli/embedding_manager.py +13 -4
  32. package/codex-lens/src/codexlens/config.py +35 -0
  33. package/codex-lens/src/codexlens/env_config.py +6 -0
  34. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-312.pyc +0 -0
  35. package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
  36. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-312.pyc +0 -0
  37. package/codex-lens/src/codexlens/search/__pycache__/ranking.cpython-313.pyc +0 -0
  38. package/codex-lens/src/codexlens/search/chain_search.py +10 -0
  39. package/codex-lens/src/codexlens/search/ranking.py +50 -0
  40. package/codex-lens/src/codexlens/semantic/__pycache__/chunker.cpython-313.pyc +0 -0
  41. package/codex-lens/src/codexlens/semantic/chunker.py +328 -23
  42. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/__init__.cpython-312.pyc +0 -0
  43. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/api_reranker.cpython-312.pyc +0 -0
  44. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/base.cpython-312.pyc +0 -0
  45. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/factory.cpython-312.pyc +0 -0
  46. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/fastembed_reranker.cpython-312.pyc +0 -0
  47. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/legacy.cpython-312.pyc +0 -0
  48. package/codex-lens/src/codexlens/semantic/reranker/__pycache__/onnx_reranker.cpython-312.pyc +0 -0
  49. package/codex-lens/src/codexlens/storage/__pycache__/index_tree.cpython-313.pyc +0 -0
  50. package/codex-lens/src/codexlens/storage/index_tree.py +46 -2
  51. package/package.json +1 -1
@@ -3,6 +3,26 @@
3
3
  * Shared module for testing API key connectivity across different provider types.
4
4
  * Used by both manual testing (litellm-api-routes.ts) and health check service.
5
5
  */
6
+ /**
7
+ * Validate API base URL format
8
+ * Note: This is a local development tool, so we allow localhost and internal networks
9
+ * for users who run local API gateways or proxies.
10
+ * @param url - The URL to validate
11
+ * @returns Object with valid flag and optional error message
12
+ */
13
+ export function validateApiBaseUrl(url) {
14
+ try {
15
+ const parsed = new URL(url);
16
+ // Must be HTTP or HTTPS
17
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
18
+ return { valid: false, error: 'URL must use HTTP or HTTPS protocol' };
19
+ }
20
+ return { valid: true };
21
+ }
22
+ catch {
23
+ return { valid: false, error: 'Invalid URL format' };
24
+ }
25
+ }
6
26
  /**
7
27
  * Get default API base URL for a provider type
8
28
  */
@@ -23,24 +43,24 @@ export function getDefaultApiBase(providerType) {
23
43
  * @returns TestResult indicating if the key is valid
24
44
  */
25
45
  export async function testApiKeyConnection(providerType, apiBase, apiKey, timeout = 10000) {
46
+ // Validate URL to prevent SSRF
47
+ const urlValidation = validateApiBaseUrl(apiBase);
48
+ if (!urlValidation.valid) {
49
+ return { valid: false, error: urlValidation.error };
50
+ }
26
51
  const controller = new AbortController();
27
52
  const timeoutId = setTimeout(() => controller.abort(), timeout);
28
53
  const startTime = Date.now();
29
54
  try {
30
55
  if (providerType === 'anthropic') {
31
- // Anthropic format: POST /v1/messages with minimal payload
32
- const response = await fetch(`${apiBase}/messages`, {
33
- method: 'POST',
56
+ // Anthropic format: Use /v1/models endpoint (no cost, no model dependency)
57
+ // This validates the API key without making a billable request
58
+ const response = await fetch(`${apiBase}/models`, {
59
+ method: 'GET',
34
60
  headers: {
35
- 'Content-Type': 'application/json',
36
61
  'x-api-key': apiKey,
37
62
  'anthropic-version': '2023-06-01',
38
63
  },
39
- body: JSON.stringify({
40
- model: 'claude-3-haiku-20240307',
41
- max_tokens: 1,
42
- messages: [{ role: 'user', content: 'Hi' }],
43
- }),
44
64
  signal: controller.signal,
45
65
  });
46
66
  clearTimeout(timeoutId);
@@ -51,7 +71,7 @@ export async function testApiKeyConnection(providerType, apiBase, apiKey, timeou
51
71
  // Parse error response
52
72
  const errorBody = await response.json().catch(() => ({}));
53
73
  const errorMessage = errorBody?.error?.message || response.statusText;
54
- // 401 = invalid API key, other 4xx might be valid key with other issues
74
+ // 401 = invalid API key
55
75
  if (response.status === 401) {
56
76
  return { valid: false, error: 'Invalid API key' };
57
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"api-key-tester.js","sourceRoot":"","sources":["../../../src/core/services/api-key-tester.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api-key-tester.js","sourceRoot":"","sources":["../../../src/core/services/api-key-tester.ts"],"names":[],"mappings":"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"}
@@ -74,6 +74,12 @@ export declare class HealthCheckService {
74
74
  * Get list of provider IDs currently being monitored
75
75
  */
76
76
  getMonitoredProviders(): string[];
77
+ /**
78
+ * Clean up all state for a deleted provider
79
+ * Call this when a provider is deleted to prevent memory leaks
80
+ * @param providerId - The provider ID to clean up
81
+ */
82
+ cleanupProvider(providerId: string): void;
77
83
  }
78
84
  /**
79
85
  * Get the singleton health check service instance
@@ -1 +1 @@
1
- {"version":3,"file":"health-check-service.d.ts","sourceRoot":"","sources":["../../../src/core/services/health-check-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAE5C,8DAA8D;IAC9D,OAAO,CAAC,MAAM,CAA0C;IAExD,kFAAkF;IAClF,OAAO,CAAC,SAAS,CAA0C;IAE3D,2CAA2C;IAC3C,OAAO,CAAC,OAAO,CAAc;IAE7B,yDAAyD;IACzD,OAAO,CAAC,iBAAiB,CAA0B;IAEnD,OAAO;IAEP;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,kBAAkB;IAOxC;;;OAGG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAoC1C;;;OAGG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IASzC;;;OAGG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAoB3C;;OAEG;IACH,mBAAmB,IAAI,IAAI;IAS3B;;;OAGG;IACG,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqDzD;;OAEG;YACW,cAAc;IAyD5B;;OAEG;IACH,OAAO,CAAC,eAAe;IA0BvB;;OAEG;IACH,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;QACjD,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;QAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IAmBF;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE;CAGlC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,kBAAkB,CAE1D"}
1
+ {"version":3,"file":"health-check-service.d.ts","sourceRoot":"","sources":["../../../src/core/services/health-check-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAE5C,8DAA8D;IAC9D,OAAO,CAAC,MAAM,CAA0C;IAExD,kFAAkF;IAClF,OAAO,CAAC,SAAS,CAA0C;IAE3D,2CAA2C;IAC3C,OAAO,CAAC,OAAO,CAAc;IAE7B,yDAAyD;IACzD,OAAO,CAAC,iBAAiB,CAA0B;IAEnD,OAAO;IAEP;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,kBAAkB;IAOxC;;;OAGG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAoC1C;;;OAGG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IASzC;;;OAGG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAoB3C;;OAEG;IACH,mBAAmB,IAAI,IAAI;IAS3B;;;OAGG;IACG,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqDzD;;OAEG;YACW,cAAc;IAyD5B;;OAEG;IACH,OAAO,CAAC,eAAe;IA0BvB;;OAEG;IACH,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;QACjD,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;QAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,mBAAmB,EAAE,MAAM,CAAC;QAC5B,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IAmBF;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,qBAAqB,IAAI,MAAM,EAAE;IAIjC;;;;OAIG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;CAoB1C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,kBAAkB,CAE1D"}
@@ -261,6 +261,28 @@ export class HealthCheckService {
261
261
  getMonitoredProviders() {
262
262
  return Array.from(this.timers.keys());
263
263
  }
264
+ /**
265
+ * Clean up all state for a deleted provider
266
+ * Call this when a provider is deleted to prevent memory leaks
267
+ * @param providerId - The provider ID to clean up
268
+ */
269
+ cleanupProvider(providerId) {
270
+ // Stop health check timer
271
+ this.stopHealthCheck(providerId);
272
+ // Remove all key states for this provider
273
+ const keysToRemove = [];
274
+ for (const key of this.keyStates.keys()) {
275
+ if (key.startsWith(`${providerId}:`)) {
276
+ keysToRemove.push(key);
277
+ }
278
+ }
279
+ for (const key of keysToRemove) {
280
+ this.keyStates.delete(key);
281
+ }
282
+ if (keysToRemove.length > 0) {
283
+ console.log(`[HealthCheck] Cleaned up ${keysToRemove.length} key state(s) for deleted provider ${providerId}`);
284
+ }
285
+ }
264
286
  }
265
287
  /**
266
288
  * Get the singleton health check service instance
@@ -1 +1 @@
1
- {"version":3,"file":"health-check-service.js","sourceRoot":"","sources":["../../../src/core/services/health-check-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"health-check-service.js","sourceRoot":"","sources":["../../../src/core/services/health-check-service.ts"],"names":[],"mappings":"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"}
@@ -292,6 +292,14 @@ export async function handleLiteLLMApiRoutes(ctx: RouteContext): Promise<boolean
292
292
  return true;
293
293
  }
294
294
 
295
+ // Clean up health check service state for deleted provider
296
+ try {
297
+ const { getHealthCheckService } = await import('../services/health-check-service.js');
298
+ getHealthCheckService().cleanupProvider(providerId);
299
+ } catch (cleanupErr) {
300
+ console.warn('[Provider Delete] Failed to cleanup health check state:', cleanupErr);
301
+ }
302
+
295
303
  broadcastToClients({
296
304
  type: 'LITELLM_PROVIDER_DELETED',
297
305
  payload: { providerId, timestamp: new Date().toISOString() }
@@ -640,6 +640,12 @@ export async function startServer(options: ServerOptions = {}): Promise<http.Ser
640
640
  try {
641
641
  const healthCheckService = getHealthCheckService();
642
642
  healthCheckService.startAllHealthChecks(initialPath);
643
+
644
+ // Graceful shutdown: stop health checks when server closes
645
+ server.on('close', () => {
646
+ console.log('[Server] Shutting down health check service...');
647
+ healthCheckService.stopAllHealthChecks();
648
+ });
643
649
  } catch (err) {
644
650
  console.warn('[Server] Failed to start health check service:', err);
645
651
  }
@@ -6,6 +6,28 @@
6
6
 
7
7
  import type { ProviderType } from '../../types/litellm-api-config.js';
8
8
 
9
+ /**
10
+ * Validate API base URL format
11
+ * Note: This is a local development tool, so we allow localhost and internal networks
12
+ * for users who run local API gateways or proxies.
13
+ * @param url - The URL to validate
14
+ * @returns Object with valid flag and optional error message
15
+ */
16
+ export function validateApiBaseUrl(url: string): { valid: boolean; error?: string } {
17
+ try {
18
+ const parsed = new URL(url);
19
+
20
+ // Must be HTTP or HTTPS
21
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
22
+ return { valid: false, error: 'URL must use HTTP or HTTPS protocol' };
23
+ }
24
+
25
+ return { valid: true };
26
+ } catch {
27
+ return { valid: false, error: 'Invalid URL format' };
28
+ }
29
+ }
30
+
9
31
  /**
10
32
  * Result of an API key connection test
11
33
  */
@@ -44,25 +66,26 @@ export async function testApiKeyConnection(
44
66
  apiKey: string,
45
67
  timeout: number = 10000
46
68
  ): Promise<TestResult> {
69
+ // Validate URL to prevent SSRF
70
+ const urlValidation = validateApiBaseUrl(apiBase);
71
+ if (!urlValidation.valid) {
72
+ return { valid: false, error: urlValidation.error };
73
+ }
74
+
47
75
  const controller = new AbortController();
48
76
  const timeoutId = setTimeout(() => controller.abort(), timeout);
49
77
  const startTime = Date.now();
50
78
 
51
79
  try {
52
80
  if (providerType === 'anthropic') {
53
- // Anthropic format: POST /v1/messages with minimal payload
54
- const response = await fetch(`${apiBase}/messages`, {
55
- method: 'POST',
81
+ // Anthropic format: Use /v1/models endpoint (no cost, no model dependency)
82
+ // This validates the API key without making a billable request
83
+ const response = await fetch(`${apiBase}/models`, {
84
+ method: 'GET',
56
85
  headers: {
57
- 'Content-Type': 'application/json',
58
86
  'x-api-key': apiKey,
59
87
  'anthropic-version': '2023-06-01',
60
88
  },
61
- body: JSON.stringify({
62
- model: 'claude-3-haiku-20240307',
63
- max_tokens: 1,
64
- messages: [{ role: 'user', content: 'Hi' }],
65
- }),
66
89
  signal: controller.signal,
67
90
  });
68
91
 
@@ -77,7 +100,7 @@ export async function testApiKeyConnection(
77
100
  const errorBody = await response.json().catch(() => ({}));
78
101
  const errorMessage = (errorBody as any)?.error?.message || response.statusText;
79
102
 
80
- // 401 = invalid API key, other 4xx might be valid key with other issues
103
+ // 401 = invalid API key
81
104
  if (response.status === 401) {
82
105
  return { valid: false, error: 'Invalid API key' };
83
106
  }
@@ -330,6 +330,32 @@ export class HealthCheckService {
330
330
  getMonitoredProviders(): string[] {
331
331
  return Array.from(this.timers.keys());
332
332
  }
333
+
334
+ /**
335
+ * Clean up all state for a deleted provider
336
+ * Call this when a provider is deleted to prevent memory leaks
337
+ * @param providerId - The provider ID to clean up
338
+ */
339
+ cleanupProvider(providerId: string): void {
340
+ // Stop health check timer
341
+ this.stopHealthCheck(providerId);
342
+
343
+ // Remove all key states for this provider
344
+ const keysToRemove: string[] = [];
345
+ for (const key of this.keyStates.keys()) {
346
+ if (key.startsWith(`${providerId}:`)) {
347
+ keysToRemove.push(key);
348
+ }
349
+ }
350
+
351
+ for (const key of keysToRemove) {
352
+ this.keyStates.delete(key);
353
+ }
354
+
355
+ if (keysToRemove.length > 0) {
356
+ console.log(`[HealthCheck] Cleaned up ${keysToRemove.length} key state(s) for deleted provider ${providerId}`);
357
+ }
358
+ }
333
359
  }
334
360
 
335
361
  /**
@@ -294,6 +294,7 @@ const i18n = {
294
294
  'codexlens.envGroup.reranker': 'Reranker Configuration',
295
295
  'codexlens.envGroup.concurrency': 'Concurrency Settings',
296
296
  'codexlens.envGroup.cascade': 'Cascade Search Settings',
297
+ 'codexlens.envGroup.chunking': 'Chunking Options',
297
298
  'codexlens.envGroup.llm': 'LLM Features',
298
299
  // Environment variable field labels
299
300
  'codexlens.envField.backend': 'Backend',
@@ -313,6 +314,10 @@ const i18n = {
313
314
  'codexlens.envField.searchStrategy': 'Search Strategy',
314
315
  'codexlens.envField.coarseK': 'Coarse K (1st stage)',
315
316
  'codexlens.envField.fineK': 'Fine K (final)',
317
+ 'codexlens.envField.stripComments': 'Strip Comments',
318
+ 'codexlens.envField.stripDocstrings': 'Strip Docstrings',
319
+ 'codexlens.envField.testFilePenalty': 'Test File Penalty',
320
+ 'codexlens.envField.docstringWeight': 'Docstring Weight',
316
321
  'codexlens.usingApiReranker': 'Using API Reranker',
317
322
  'codexlens.currentModel': 'Current Model',
318
323
  'codexlens.localModels': 'Local Models',
@@ -2443,6 +2448,7 @@ const i18n = {
2443
2448
  'codexlens.envGroup.reranker': '重排序配置',
2444
2449
  'codexlens.envGroup.concurrency': '并发设置',
2445
2450
  'codexlens.envGroup.cascade': '级联搜索设置',
2451
+ 'codexlens.envGroup.chunking': '分块选项',
2446
2452
  'codexlens.envGroup.llm': 'LLM 功能',
2447
2453
  // 环境变量字段标签
2448
2454
  'codexlens.envField.backend': '后端',
@@ -2462,6 +2468,10 @@ const i18n = {
2462
2468
  'codexlens.envField.searchStrategy': '搜索策略',
2463
2469
  'codexlens.envField.coarseK': '粗筛 K (第一阶段)',
2464
2470
  'codexlens.envField.fineK': '精筛 K (最终)',
2471
+ 'codexlens.envField.stripComments': '去除注释',
2472
+ 'codexlens.envField.stripDocstrings': '去除文档字符串',
2473
+ 'codexlens.envField.testFilePenalty': '测试文件惩罚',
2474
+ 'codexlens.envField.docstringWeight': '文档字符串权重',
2465
2475
  'codexlens.usingApiReranker': '使用 API 重排序',
2466
2476
  'codexlens.currentModel': '当前模型',
2467
2477
  'codexlens.localModels': '本地模型',
@@ -1109,6 +1109,16 @@ var ENV_VAR_GROUPS = {
1109
1109
  'CODEXLENS_CASCADE_COARSE_K': { labelKey: 'codexlens.envField.coarseK', type: 'number', placeholder: '100', default: '100', settingsPath: 'cascade.coarse_k', min: 10, max: 500 },
1110
1110
  'CODEXLENS_CASCADE_FINE_K': { labelKey: 'codexlens.envField.fineK', type: 'number', placeholder: '10', default: '10', settingsPath: 'cascade.fine_k', min: 1, max: 100 }
1111
1111
  }
1112
+ },
1113
+ chunking: {
1114
+ labelKey: 'codexlens.envGroup.chunking',
1115
+ icon: 'scissors',
1116
+ vars: {
1117
+ 'CHUNK_STRIP_COMMENTS': { labelKey: 'codexlens.envField.stripComments', type: 'select', options: ['true', 'false'], default: 'true', settingsPath: 'chunking.strip_comments' },
1118
+ 'CHUNK_STRIP_DOCSTRINGS': { labelKey: 'codexlens.envField.stripDocstrings', type: 'select', options: ['true', 'false'], default: 'true', settingsPath: 'chunking.strip_docstrings' },
1119
+ 'RERANKER_TEST_FILE_PENALTY': { labelKey: 'codexlens.envField.testFilePenalty', type: 'number', placeholder: '0.0', default: '0.0', settingsPath: 'reranker.test_file_penalty', min: 0, max: 1, step: 0.1 },
1120
+ 'RERANKER_DOCSTRING_WEIGHT': { labelKey: 'codexlens.envField.docstringWeight', type: 'number', placeholder: '1.0', default: '1.0', settingsPath: 'reranker.docstring_weight', min: 0, max: 1, step: 0.1 }
1121
+ }
1112
1122
  }
1113
1123
  };
1114
1124
 
@@ -535,10 +535,15 @@ def generate_embeddings(
535
535
 
536
536
  # skip_token_count=True: Use fast estimation (len/4) instead of expensive tiktoken
537
537
  # This significantly reduces CPU usage with minimal impact on metadata accuracy
538
+ # Load chunk stripping config from settings
539
+ from codexlens.config import Config
540
+ chunk_cfg = Config.load()
538
541
  chunker = Chunker(config=ChunkConfig(
539
542
  max_chunk_size=chunk_size,
540
543
  overlap=overlap,
541
- skip_token_count=True
544
+ skip_token_count=True,
545
+ strip_comments=getattr(chunk_cfg, 'chunk_strip_comments', True),
546
+ strip_docstrings=getattr(chunk_cfg, 'chunk_strip_docstrings', True),
542
547
  ))
543
548
 
544
549
  # Log embedder info with endpoint count for multi-endpoint mode
@@ -1307,10 +1312,15 @@ def generate_dense_embeddings_centralized(
1307
1312
  "error": f"Invalid embedding backend: {embedding_backend}",
1308
1313
  }
1309
1314
 
1315
+ # Load chunk stripping config from settings
1316
+ from codexlens.config import Config
1317
+ chunk_cfg = Config.load()
1310
1318
  chunker = Chunker(config=ChunkConfig(
1311
1319
  max_chunk_size=chunk_size,
1312
1320
  overlap=overlap,
1313
- skip_token_count=True
1321
+ skip_token_count=True,
1322
+ strip_comments=getattr(chunk_cfg, 'chunk_strip_comments', True),
1323
+ strip_docstrings=getattr(chunk_cfg, 'chunk_strip_docstrings', True),
1314
1324
  ))
1315
1325
 
1316
1326
  if progress_callback:
@@ -1319,8 +1329,7 @@ def generate_dense_embeddings_centralized(
1319
1329
  progress_callback(f"Using model: {embedder.model_name} ({embedder.embedding_dim} dimensions)")
1320
1330
 
1321
1331
  # Calculate dynamic batch size based on model capacity
1322
- from codexlens.config import Config
1323
- batch_config = Config.load()
1332
+ batch_config = chunk_cfg # Reuse already loaded config
1324
1333
  effective_batch_size = calculate_dynamic_batch_size(batch_config, embedder)
1325
1334
 
1326
1335
  if progress_callback and batch_config.api_batch_size_dynamic:
@@ -141,6 +141,12 @@ class Config:
141
141
  reranker_model: str = "cross-encoder/ms-marco-MiniLM-L-6-v2"
142
142
  reranker_top_k: int = 50
143
143
  reranker_max_input_tokens: int = 8192 # Maximum tokens for reranker API batching
144
+ reranker_chunk_type_weights: Optional[Dict[str, float]] = None # Weights for chunk types: {"code": 1.0, "docstring": 0.7}
145
+ reranker_test_file_penalty: float = 0.0 # Penalty for test files (0.0-1.0, e.g., 0.2 = 20% reduction)
146
+
147
+ # Chunk stripping configuration (for semantic embedding)
148
+ chunk_strip_comments: bool = True # Strip comments from code chunks
149
+ chunk_strip_docstrings: bool = True # Strip docstrings from code chunks
144
150
 
145
151
  # Cascade search configuration (two-stage retrieval)
146
152
  enable_cascade_search: bool = False # Enable cascade search (coarse + fine ranking)
@@ -545,6 +551,35 @@ class Config:
545
551
  except ValueError:
546
552
  log.warning("Invalid RERANKER_MAX_INPUT_TOKENS in .env: %r", reranker_max_tokens)
547
553
 
554
+ # Reranker tuning from environment
555
+ test_penalty = get_env("RERANKER_TEST_FILE_PENALTY")
556
+ if test_penalty:
557
+ try:
558
+ self.reranker_test_file_penalty = float(test_penalty)
559
+ log.debug("Overriding reranker_test_file_penalty from .env: %s", self.reranker_test_file_penalty)
560
+ except ValueError:
561
+ log.warning("Invalid RERANKER_TEST_FILE_PENALTY in .env: %r", test_penalty)
562
+
563
+ docstring_weight = get_env("RERANKER_DOCSTRING_WEIGHT")
564
+ if docstring_weight:
565
+ try:
566
+ weight = float(docstring_weight)
567
+ self.reranker_chunk_type_weights = {"code": 1.0, "docstring": weight}
568
+ log.debug("Overriding reranker docstring weight from .env: %s", weight)
569
+ except ValueError:
570
+ log.warning("Invalid RERANKER_DOCSTRING_WEIGHT in .env: %r", docstring_weight)
571
+
572
+ # Chunk stripping from environment
573
+ strip_comments = get_env("CHUNK_STRIP_COMMENTS")
574
+ if strip_comments:
575
+ self.chunk_strip_comments = strip_comments.lower() in ("true", "1", "yes")
576
+ log.debug("Overriding chunk_strip_comments from .env: %s", self.chunk_strip_comments)
577
+
578
+ strip_docstrings = get_env("CHUNK_STRIP_DOCSTRINGS")
579
+ if strip_docstrings:
580
+ self.chunk_strip_docstrings = strip_docstrings.lower() in ("true", "1", "yes")
581
+ log.debug("Overriding chunk_strip_docstrings from .env: %s", self.chunk_strip_docstrings)
582
+
548
583
  @classmethod
549
584
  def load(cls) -> "Config":
550
585
  """Load config with settings from file."""
@@ -45,6 +45,12 @@ ENV_VARS = {
45
45
  # General configuration
46
46
  "CODEXLENS_DATA_DIR": "Custom data directory path",
47
47
  "CODEXLENS_DEBUG": "Enable debug mode (true/false)",
48
+ # Chunking configuration
49
+ "CHUNK_STRIP_COMMENTS": "Strip comments from code chunks for embedding: true/false (default: true)",
50
+ "CHUNK_STRIP_DOCSTRINGS": "Strip docstrings from code chunks for embedding: true/false (default: true)",
51
+ # Reranker tuning
52
+ "RERANKER_TEST_FILE_PENALTY": "Penalty for test files in reranking: 0.0-1.0 (default: 0.0)",
53
+ "RERANKER_DOCSTRING_WEIGHT": "Weight for docstring chunks in reranking: 0.0-1.0 (default: 1.0)",
48
54
  }
49
55
 
50
56
 
@@ -1816,12 +1816,22 @@ class ChainSearchEngine:
1816
1816
  # Use cross_encoder_rerank from ranking module
1817
1817
  from codexlens.search.ranking import cross_encoder_rerank
1818
1818
 
1819
+ # Get chunk_type weights and test_file_penalty from config
1820
+ chunk_type_weights = None
1821
+ test_file_penalty = 0.0
1822
+
1823
+ if self._config is not None:
1824
+ chunk_type_weights = getattr(self._config, "reranker_chunk_type_weights", None)
1825
+ test_file_penalty = getattr(self._config, "reranker_test_file_penalty", 0.0)
1826
+
1819
1827
  return cross_encoder_rerank(
1820
1828
  query=query,
1821
1829
  results=results,
1822
1830
  reranker=reranker,
1823
1831
  top_k=top_k,
1824
1832
  batch_size=32,
1833
+ chunk_type_weights=chunk_type_weights,
1834
+ test_file_penalty=test_file_penalty,
1825
1835
  )
1826
1836
 
1827
1837
  def search_files_only(self, query: str,
@@ -613,11 +613,24 @@ def cross_encoder_rerank(
613
613
  reranker: Any,
614
614
  top_k: int = 50,
615
615
  batch_size: int = 32,
616
+ chunk_type_weights: Optional[Dict[str, float]] = None,
617
+ test_file_penalty: float = 0.0,
616
618
  ) -> List[SearchResult]:
617
619
  """Second-stage reranking using a cross-encoder model.
618
620
 
619
621
  This function is dependency-agnostic: callers can pass any object that exposes
620
622
  a compatible `score_pairs(pairs, batch_size=...)` method.
623
+
624
+ Args:
625
+ query: Search query string
626
+ results: List of search results to rerank
627
+ reranker: Cross-encoder model with score_pairs or predict method
628
+ top_k: Number of top results to rerank
629
+ batch_size: Batch size for reranking
630
+ chunk_type_weights: Optional weights for different chunk types.
631
+ Example: {"code": 1.0, "docstring": 0.7} - reduce docstring influence
632
+ test_file_penalty: Penalty applied to test files (0.0-1.0).
633
+ Example: 0.2 means test files get 20% score reduction
621
634
  """
622
635
  if not results:
623
636
  return []
@@ -667,13 +680,50 @@ def cross_encoder_rerank(
667
680
 
668
681
  reranked_results: List[SearchResult] = []
669
682
 
683
+ # Helper to detect test files
684
+ def is_test_file(path: str) -> bool:
685
+ if not path:
686
+ return False
687
+ basename = path.split("/")[-1].split("\\")[-1]
688
+ return (
689
+ basename.startswith("test_") or
690
+ basename.endswith("_test.py") or
691
+ basename.endswith(".test.ts") or
692
+ basename.endswith(".test.js") or
693
+ basename.endswith(".spec.ts") or
694
+ basename.endswith(".spec.js") or
695
+ "/tests/" in path or
696
+ "\\tests\\" in path or
697
+ "/test/" in path or
698
+ "\\test\\" in path
699
+ )
700
+
670
701
  for idx, result in enumerate(results):
671
702
  if idx < rerank_count:
672
703
  prev_score = float(result.score)
673
704
  ce_score = scores[idx]
674
705
  ce_prob = probs[idx]
706
+
707
+ # Base combined score
675
708
  combined_score = 0.5 * prev_score + 0.5 * ce_prob
676
709
 
710
+ # Apply chunk_type weight adjustment
711
+ if chunk_type_weights:
712
+ chunk_type = None
713
+ if result.chunk and hasattr(result.chunk, "metadata"):
714
+ chunk_type = result.chunk.metadata.get("chunk_type")
715
+ elif result.metadata:
716
+ chunk_type = result.metadata.get("chunk_type")
717
+
718
+ if chunk_type and chunk_type in chunk_type_weights:
719
+ weight = chunk_type_weights[chunk_type]
720
+ # Apply weight to CE contribution only
721
+ combined_score = 0.5 * prev_score + 0.5 * ce_prob * weight
722
+
723
+ # Apply test file penalty
724
+ if test_file_penalty > 0 and is_test_file(result.path):
725
+ combined_score = combined_score * (1.0 - test_file_penalty)
726
+
677
727
  reranked_results.append(
678
728
  SearchResult(
679
729
  path=result.path,