cicada-mcp 0.1.5__tar.gz → 0.1.7__tar.gz
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.
Potentially problematic release.
This version of cicada-mcp might be problematic. Click here for more details.
- {cicada_mcp-0.1.5/cicada_mcp.egg-info → cicada_mcp-0.1.7}/PKG-INFO +1 -1
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/indexer.py +60 -42
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/mcp_server.py +7 -23
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/setup.py +14 -7
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7/cicada_mcp.egg-info}/PKG-INFO +1 -1
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/pyproject.toml +1 -1
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_indexer_comprehensive.py +5 -5
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/LICENSE +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/README.md +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/__init__.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/clean.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/command_logger.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/dead_code_analyzer.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/extractors/__init__.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/extractors/base.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/extractors/call.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/extractors/dependency.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/extractors/doc.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/extractors/function.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/extractors/module.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/extractors/spec.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/find_dead_code.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/formatter.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/git_helper.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/install.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/keyword_search.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/lightweight_keyword_extractor.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/mcp_tools.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/parser.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/pr_finder.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/pr_indexer/__init__.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/pr_indexer/cli.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/pr_indexer/github_api_client.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/pr_indexer/indexer.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/pr_indexer/line_mapper.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/pr_indexer/pr_index_builder.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/__init__.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/call_site_formatter.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/function_grouper.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/hash_utils.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/index_utils.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/path_utils.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/signature_builder.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/storage.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/subprocess_runner.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/utils/text_utils.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada/version_check.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada_mcp.egg-info/SOURCES.txt +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada_mcp.egg-info/dependency_links.txt +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada_mcp.egg-info/entry_points.txt +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada_mcp.egg-info/requires.txt +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/cicada_mcp.egg-info/top_level.txt +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/setup.cfg +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_acceptance.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_call_sites.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_claude_md_update.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_clean.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_command_logger.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_dead_code_analyzer.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_e2e.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_find_dead_code.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_formatter.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_git_extended_history.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_git_helper.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_github_api_client.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_gitignore_integration.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_hash_utils.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_index_utils.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_install_comprehensive.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_install_detection.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_install_summary.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_intelligent_mcp_config.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_keyword_search.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_line_mapper.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_mcp_e2e.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_mcp_git_integration.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_mcp_logging_integration.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_mcp_pr_tools.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_mcp_server_core.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_mcp_server_formatting.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_mcp_server_pr_history.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_module_usage_categories.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_multi_editor_setup.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_parser.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_parser_comprehensive.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_path_utils.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_pr_finder.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_pr_index_builder.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_pr_indexer_integration.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_pr_indexer_unit.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_search_function.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_server_cli.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_setup.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_signal_handling.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_stdout_redirect.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_storage.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_subprocess_runner.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_test_files_filter.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_version_check.py +0 -0
- {cicada_mcp-0.1.5 → cicada_mcp-0.1.7}/tests/test_with_aliases.py +0 -0
|
@@ -102,7 +102,8 @@ class ElixirIndexer:
|
|
|
102
102
|
if not repo_path_obj.exists():
|
|
103
103
|
raise ValueError(f"Repository path does not exist: {repo_path_obj}")
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
if self.verbose:
|
|
106
|
+
print(f"Indexing repository: {repo_path_obj}")
|
|
106
107
|
|
|
107
108
|
# Set up signal handlers for graceful interruption
|
|
108
109
|
signal.signal(signal.SIGINT, self._handle_interrupt)
|
|
@@ -118,20 +119,22 @@ class ElixirIndexer:
|
|
|
118
119
|
)
|
|
119
120
|
|
|
120
121
|
keyword_extractor = LightweightKeywordExtractor(
|
|
121
|
-
verbose=
|
|
122
|
+
verbose=self.verbose, model_size=spacy_model
|
|
122
123
|
)
|
|
123
124
|
except Exception as e:
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
if self.verbose:
|
|
126
|
+
print(f"Warning: Could not initialize keyword extractor: {e}")
|
|
127
|
+
print("Continuing without keyword extraction...")
|
|
126
128
|
extract_keywords = False
|
|
127
129
|
|
|
128
130
|
# Find all Elixir files
|
|
129
131
|
elixir_files = self._find_elixir_files(repo_path_obj)
|
|
130
132
|
total_files = len(elixir_files)
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
if self.verbose:
|
|
135
|
+
print(f"Found {total_files} Elixir files")
|
|
136
|
+
if extract_keywords:
|
|
137
|
+
print("Keyword extraction enabled")
|
|
135
138
|
|
|
136
139
|
# Parse all files
|
|
137
140
|
all_modules = {}
|
|
@@ -222,7 +225,10 @@ class ElixirIndexer:
|
|
|
222
225
|
files_processed += 1
|
|
223
226
|
|
|
224
227
|
# Progress reporting
|
|
225
|
-
if
|
|
228
|
+
if (
|
|
229
|
+
self.verbose
|
|
230
|
+
and files_processed % self.PROGRESS_REPORT_INTERVAL == 0
|
|
231
|
+
):
|
|
226
232
|
print(f" Processed {files_processed}/{total_files} files...")
|
|
227
233
|
|
|
228
234
|
# Check for interruption after each file
|
|
@@ -230,7 +236,8 @@ class ElixirIndexer:
|
|
|
230
236
|
break
|
|
231
237
|
|
|
232
238
|
except Exception as e:
|
|
233
|
-
|
|
239
|
+
if self.verbose:
|
|
240
|
+
print(f" Skipping {file_path}: {e}")
|
|
234
241
|
# Check for interruption even after error
|
|
235
242
|
if self._check_and_report_interruption(files_processed, total_files):
|
|
236
243
|
break
|
|
@@ -258,12 +265,14 @@ class ElixirIndexer:
|
|
|
258
265
|
from cicada.utils.path_utils import ensure_gitignore_has_cicada
|
|
259
266
|
|
|
260
267
|
if ensure_gitignore_has_cicada(repo_path_obj):
|
|
261
|
-
|
|
268
|
+
if self.verbose:
|
|
269
|
+
print("✓ Added .cicada/ to .gitignore")
|
|
262
270
|
|
|
263
271
|
save_index(index, output_path_obj, create_dirs=True)
|
|
264
272
|
|
|
265
273
|
# Compute and save hashes for all PROCESSED files for future incremental updates
|
|
266
|
-
|
|
274
|
+
if self.verbose:
|
|
275
|
+
print("Computing file hashes for incremental updates...")
|
|
267
276
|
# Only hash files that were actually processed
|
|
268
277
|
processed_files = [
|
|
269
278
|
str(f.relative_to(repo_path_obj)) for f in elixir_files[:files_processed]
|
|
@@ -272,30 +281,31 @@ class ElixirIndexer:
|
|
|
272
281
|
save_file_hashes(str(output_path_obj.parent), file_hashes)
|
|
273
282
|
|
|
274
283
|
# Report completion status
|
|
275
|
-
if self.
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
284
|
+
if self.verbose:
|
|
285
|
+
if self._interrupted:
|
|
286
|
+
print(f"\n✓ Partial index saved!")
|
|
287
|
+
print(
|
|
288
|
+
f" Processed: {files_processed}/{total_files} files ({files_processed/total_files*100:.1f}%)"
|
|
289
|
+
)
|
|
290
|
+
print(f" Modules: {len(all_modules)}")
|
|
291
|
+
print(f" Functions: {total_functions}")
|
|
292
|
+
print(
|
|
293
|
+
f"\n💡 Run the command again to continue indexing remaining {total_files - files_processed} file(s)"
|
|
294
|
+
)
|
|
295
|
+
else:
|
|
296
|
+
print(f"\nIndexing complete!")
|
|
297
|
+
print(f" Modules: {len(all_modules)}")
|
|
298
|
+
print(f" Functions: {total_functions}")
|
|
289
299
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
300
|
+
# Report keyword extraction failures if any
|
|
301
|
+
if extract_keywords and keyword_extraction_failures > 0:
|
|
302
|
+
print(
|
|
303
|
+
f"\n⚠️ Warning: Keyword extraction failed for {keyword_extraction_failures} module(s) or function(s)"
|
|
304
|
+
)
|
|
305
|
+
print(" Some documentation may not be indexed for keyword search.")
|
|
296
306
|
|
|
297
|
-
|
|
298
|
-
|
|
307
|
+
print(f"\nIndex saved to: {output_path_obj}")
|
|
308
|
+
print(f"Hashes saved to: {output_path_obj.parent}/hashes.json")
|
|
299
309
|
|
|
300
310
|
return index
|
|
301
311
|
|
|
@@ -351,7 +361,8 @@ class ElixirIndexer:
|
|
|
351
361
|
str(repo_path_obj), str(output_path_obj), extract_keywords, spacy_model
|
|
352
362
|
)
|
|
353
363
|
|
|
354
|
-
|
|
364
|
+
if self.verbose:
|
|
365
|
+
print(f"Performing incremental index of: {repo_path_obj}")
|
|
355
366
|
|
|
356
367
|
# Set up signal handlers for graceful interruption
|
|
357
368
|
signal.signal(signal.SIGINT, self._handle_interrupt)
|
|
@@ -364,7 +375,8 @@ class ElixirIndexer:
|
|
|
364
375
|
relative_files = [str(f.relative_to(repo_path_obj)) for f in elixir_files]
|
|
365
376
|
|
|
366
377
|
# Detect file changes
|
|
367
|
-
|
|
378
|
+
if self.verbose:
|
|
379
|
+
print("Detecting file changes...")
|
|
368
380
|
new_files, modified_files, deleted_files = detect_file_changes(
|
|
369
381
|
relative_files, existing_hashes, str(repo_path_obj)
|
|
370
382
|
)
|
|
@@ -377,10 +389,14 @@ class ElixirIndexer:
|
|
|
377
389
|
print("No changes detected. Index is up to date.")
|
|
378
390
|
return existing_index
|
|
379
391
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
392
|
+
if self.verbose:
|
|
393
|
+
print(f"Changes detected:")
|
|
394
|
+
if self.verbose:
|
|
395
|
+
print(f" New files: {len(new_files)}")
|
|
396
|
+
if self.verbose:
|
|
397
|
+
print(f" Modified files: {len(modified_files)}")
|
|
398
|
+
if self.verbose:
|
|
399
|
+
print(f" Deleted files: {len(deleted_files)}")
|
|
384
400
|
|
|
385
401
|
if files_to_process:
|
|
386
402
|
print(f"\nProcessing {len(files_to_process)} changed file(s)...")
|
|
@@ -394,7 +410,7 @@ class ElixirIndexer:
|
|
|
394
410
|
)
|
|
395
411
|
|
|
396
412
|
keyword_extractor = LightweightKeywordExtractor(
|
|
397
|
-
verbose=
|
|
413
|
+
verbose=self.verbose, model_size=spacy_model
|
|
398
414
|
)
|
|
399
415
|
except Exception as e:
|
|
400
416
|
print(f"Warning: Could not initialize keyword extractor: {e}")
|
|
@@ -502,13 +518,15 @@ class ElixirIndexer:
|
|
|
502
518
|
}
|
|
503
519
|
|
|
504
520
|
# Merge with existing index
|
|
505
|
-
|
|
521
|
+
if self.verbose:
|
|
522
|
+
print("\nMerging with existing index...")
|
|
506
523
|
merged_index = merge_indexes_incremental(
|
|
507
524
|
existing_index, new_index, deleted_files
|
|
508
525
|
)
|
|
509
526
|
|
|
510
527
|
# Update hashes for all current files
|
|
511
|
-
|
|
528
|
+
if self.verbose:
|
|
529
|
+
print("Updating file hashes...")
|
|
512
530
|
updated_hashes = dict(existing_hashes)
|
|
513
531
|
|
|
514
532
|
# Compute hashes only for files that were actually processed
|
|
@@ -1496,43 +1496,27 @@ def _auto_setup_if_needed():
|
|
|
1496
1496
|
# Already set up, nothing to do
|
|
1497
1497
|
return
|
|
1498
1498
|
|
|
1499
|
-
# Setup needed - create storage and index
|
|
1500
|
-
print("=" * 60, file=sys.stderr)
|
|
1501
|
-
print("Cicada: First-time setup detected", file=sys.stderr)
|
|
1502
|
-
print("=" * 60, file=sys.stderr)
|
|
1503
|
-
print(file=sys.stderr)
|
|
1504
|
-
|
|
1499
|
+
# Setup needed - create storage and index (silent mode)
|
|
1505
1500
|
# Validate it's an Elixir project
|
|
1506
1501
|
if not (repo_path / "mix.exs").exists():
|
|
1507
1502
|
print(
|
|
1508
|
-
f"Error: {repo_path} does not appear to be an Elixir project",
|
|
1503
|
+
f"Error: {repo_path} does not appear to be an Elixir project (mix.exs not found)",
|
|
1509
1504
|
file=sys.stderr,
|
|
1510
1505
|
)
|
|
1511
|
-
print("(mix.exs not found)", file=sys.stderr)
|
|
1512
1506
|
sys.exit(1)
|
|
1513
1507
|
|
|
1514
1508
|
try:
|
|
1515
1509
|
# Create storage directory
|
|
1516
1510
|
storage_dir = create_storage_dir(repo_path)
|
|
1517
|
-
print(f"Repository: {repo_path}", file=sys.stderr)
|
|
1518
|
-
print(f"Storage: {storage_dir}", file=sys.stderr)
|
|
1519
|
-
print(file=sys.stderr)
|
|
1520
|
-
|
|
1521
|
-
# Index repository
|
|
1522
|
-
index_repository(repo_path)
|
|
1523
|
-
print(file=sys.stderr)
|
|
1524
1511
|
|
|
1525
|
-
#
|
|
1526
|
-
|
|
1527
|
-
print(file=sys.stderr)
|
|
1512
|
+
# Index repository (silent mode)
|
|
1513
|
+
index_repository(repo_path, verbose=False)
|
|
1528
1514
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
print("=" * 60, file=sys.stderr)
|
|
1532
|
-
print(file=sys.stderr)
|
|
1515
|
+
# Create config.yaml (silent mode)
|
|
1516
|
+
create_config_yaml(repo_path, storage_dir, verbose=False)
|
|
1533
1517
|
|
|
1534
1518
|
except Exception as e:
|
|
1535
|
-
print(f"
|
|
1519
|
+
print(f"Cicada auto-setup error: {e}", file=sys.stderr)
|
|
1536
1520
|
sys.exit(1)
|
|
1537
1521
|
|
|
1538
1522
|
|
|
@@ -163,13 +163,16 @@ def get_mcp_config_for_editor(
|
|
|
163
163
|
return config_path, config
|
|
164
164
|
|
|
165
165
|
|
|
166
|
-
def create_config_yaml(
|
|
166
|
+
def create_config_yaml(
|
|
167
|
+
repo_path: Path, storage_dir: Path, verbose: bool = True
|
|
168
|
+
) -> None:
|
|
167
169
|
"""
|
|
168
170
|
Create config.yaml in storage directory.
|
|
169
171
|
|
|
170
172
|
Args:
|
|
171
173
|
repo_path: Path to the repository
|
|
172
174
|
storage_dir: Path to the storage directory
|
|
175
|
+
verbose: Whether to print progress messages (default: True)
|
|
173
176
|
"""
|
|
174
177
|
config_path = get_config_path(repo_path)
|
|
175
178
|
index_path = get_index_path(repo_path)
|
|
@@ -184,22 +187,24 @@ storage:
|
|
|
184
187
|
with open(config_path, "w") as f:
|
|
185
188
|
f.write(config_content)
|
|
186
189
|
|
|
187
|
-
|
|
190
|
+
if verbose:
|
|
191
|
+
print(f"✓ Config file created at {config_path}")
|
|
188
192
|
|
|
189
193
|
|
|
190
|
-
def index_repository(repo_path: Path) -> None:
|
|
194
|
+
def index_repository(repo_path: Path, verbose: bool = True) -> None:
|
|
191
195
|
"""
|
|
192
196
|
Index the repository with keyword extraction enabled.
|
|
193
197
|
|
|
194
198
|
Args:
|
|
195
199
|
repo_path: Path to the repository
|
|
200
|
+
verbose: Whether to print progress messages (default: True)
|
|
196
201
|
|
|
197
202
|
Raises:
|
|
198
203
|
Exception: If indexing fails
|
|
199
204
|
"""
|
|
200
205
|
try:
|
|
201
206
|
index_path = get_index_path(repo_path)
|
|
202
|
-
indexer = ElixirIndexer(verbose=
|
|
207
|
+
indexer = ElixirIndexer(verbose=verbose)
|
|
203
208
|
|
|
204
209
|
# Index with keyword extraction enabled by default
|
|
205
210
|
# Note: Using 'small' model for compatibility with uvx
|
|
@@ -211,10 +216,12 @@ def index_repository(repo_path: Path) -> None:
|
|
|
211
216
|
spacy_model="small",
|
|
212
217
|
)
|
|
213
218
|
|
|
214
|
-
|
|
219
|
+
if verbose:
|
|
220
|
+
print(f"✓ Repository indexed at {index_path}")
|
|
215
221
|
except Exception as e:
|
|
216
|
-
|
|
217
|
-
|
|
222
|
+
if verbose:
|
|
223
|
+
print(f"Error: Failed to index repository: {e}")
|
|
224
|
+
print("Please check that the repository contains valid Elixir files.")
|
|
218
225
|
raise
|
|
219
226
|
|
|
220
227
|
|
|
@@ -421,7 +421,7 @@ class TestElixirIndexerKeywordExtraction:
|
|
|
421
421
|
MockKeywordExtractor,
|
|
422
422
|
)
|
|
423
423
|
|
|
424
|
-
indexer = ElixirIndexer()
|
|
424
|
+
indexer = ElixirIndexer(verbose=True)
|
|
425
425
|
|
|
426
426
|
# Create a test file with documentation
|
|
427
427
|
test_file = tmp_path / "test.ex"
|
|
@@ -572,7 +572,7 @@ class TestElixirIndexerProgressReporting:
|
|
|
572
572
|
|
|
573
573
|
def test_progress_reporting_multiple_files(self, tmp_path, capsys):
|
|
574
574
|
"""Test that progress is reported every 10 files"""
|
|
575
|
-
indexer = ElixirIndexer()
|
|
575
|
+
indexer = ElixirIndexer(verbose=True)
|
|
576
576
|
|
|
577
577
|
# Create 15 test files
|
|
578
578
|
for i in range(15):
|
|
@@ -688,7 +688,7 @@ class TestElixirIndexerGitignoreIntegration:
|
|
|
688
688
|
|
|
689
689
|
def test_first_run_creates_gitignore_entry(self, tmp_path, capsys):
|
|
690
690
|
"""Test that first run adds .cicada/ to .gitignore"""
|
|
691
|
-
indexer = ElixirIndexer()
|
|
691
|
+
indexer = ElixirIndexer(verbose=True)
|
|
692
692
|
|
|
693
693
|
# Create a .gitignore file
|
|
694
694
|
gitignore = tmp_path / ".gitignore"
|
|
@@ -743,7 +743,7 @@ class TestElixirIndexerSignalHandling:
|
|
|
743
743
|
self, tmp_path, monkeypatch, capsys
|
|
744
744
|
):
|
|
745
745
|
"""Test that interrupted indexing saves partial progress"""
|
|
746
|
-
indexer = ElixirIndexer()
|
|
746
|
+
indexer = ElixirIndexer(verbose=True)
|
|
747
747
|
|
|
748
748
|
# Create multiple test files
|
|
749
749
|
for i in range(5):
|
|
@@ -973,7 +973,7 @@ class TestElixirIndexerAdditionalEdgeCases:
|
|
|
973
973
|
BrokenKeywordExtractor,
|
|
974
974
|
)
|
|
975
975
|
|
|
976
|
-
indexer = ElixirIndexer()
|
|
976
|
+
indexer = ElixirIndexer(verbose=True)
|
|
977
977
|
|
|
978
978
|
test_file = tmp_path / "test.ex"
|
|
979
979
|
test_file.write_text(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|