claude-code-workflow 6.2.6 → 6.2.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/ccw/dist/cli.d.ts.map +1 -1
- package/ccw/dist/cli.js +18 -7
- package/ccw/dist/cli.js.map +1 -1
- package/ccw/dist/core/routes/system-routes.js +1 -1
- package/ccw/dist/core/routes/system-routes.js.map +1 -1
- package/ccw/src/cli.ts +256 -244
- package/ccw/src/core/routes/system-routes.ts +1 -1
- package/ccw/src/templates/dashboard-js/components/cli-status.js +35 -2
- package/ccw/src/templates/dashboard-js/views/cli-manager.js +45 -6
- package/codex-lens/src/codexlens/cli/__pycache__/commands.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/embedding_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/__pycache__/model_manager.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/cli/commands.py +41 -15
- package/codex-lens/src/codexlens/cli/embedding_manager.py +15 -0
- package/codex-lens/src/codexlens/cli/model_manager.py +337 -311
- package/codex-lens/src/codexlens/search/__pycache__/chain_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/__pycache__/hybrid_search.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/search/chain_search.py +14 -1
- package/codex-lens/src/codexlens/search/hybrid_search.py +25 -12
- package/codex-lens/src/codexlens/semantic/__pycache__/vector_store.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/semantic/vector_store.py +97 -0
- package/codex-lens/src/codexlens/storage/__pycache__/path_mapper.cpython-313.pyc +0 -0
- package/codex-lens/src/codexlens/storage/path_mapper.py +27 -1
- package/package.json +13 -5
- package/ccw/package.json +0 -65
|
@@ -349,6 +349,50 @@ function getSelectedModel() {
|
|
|
349
349
|
return select ? select.value : 'code';
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Build model select options HTML, showing only installed models
|
|
354
|
+
* @returns {string} HTML string for select options
|
|
355
|
+
*/
|
|
356
|
+
function buildModelSelectOptions() {
|
|
357
|
+
var installedModels = window.cliToolsStatus?.codexlens?.installedModels || [];
|
|
358
|
+
var allModels = window.cliToolsStatus?.codexlens?.allModels || [];
|
|
359
|
+
|
|
360
|
+
// Model display configuration
|
|
361
|
+
var modelConfig = {
|
|
362
|
+
'code': { label: t('index.modelCode') || 'Code (768d)', star: true },
|
|
363
|
+
'base': { label: t('index.modelBase') || 'Base (768d)', star: false },
|
|
364
|
+
'fast': { label: t('index.modelFast') || 'Fast (384d)', star: false },
|
|
365
|
+
'minilm': { label: t('index.modelMinilm') || 'MiniLM (384d)', star: false },
|
|
366
|
+
'multilingual': { label: t('index.modelMultilingual') || 'Multilingual (1024d)', warn: true },
|
|
367
|
+
'balanced': { label: t('index.modelBalanced') || 'Balanced (1024d)', warn: true }
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
// If no models installed, show placeholder
|
|
371
|
+
if (installedModels.length === 0) {
|
|
372
|
+
return '<option value="" disabled selected>' + (t('index.noModelsInstalled') || 'No models installed') + '</option>';
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Build options for installed models only
|
|
376
|
+
var options = '';
|
|
377
|
+
var firstInstalled = null;
|
|
378
|
+
|
|
379
|
+
// Preferred order: code, fast, minilm, base, multilingual, balanced
|
|
380
|
+
var preferredOrder = ['code', 'fast', 'minilm', 'base', 'multilingual', 'balanced'];
|
|
381
|
+
|
|
382
|
+
preferredOrder.forEach(function(profile) {
|
|
383
|
+
if (installedModels.includes(profile) && modelConfig[profile]) {
|
|
384
|
+
var config = modelConfig[profile];
|
|
385
|
+
var style = config.warn ? ' style="color: var(--muted-foreground)"' : '';
|
|
386
|
+
var suffix = config.star ? ' ⭐' : (config.warn ? ' ⚠️' : '');
|
|
387
|
+
var selected = !firstInstalled ? ' selected' : '';
|
|
388
|
+
if (!firstInstalled) firstInstalled = profile;
|
|
389
|
+
options += '<option value="' + profile + '"' + style + selected + '>' + config.label + suffix + '</option>';
|
|
390
|
+
}
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
return options;
|
|
394
|
+
}
|
|
395
|
+
|
|
352
396
|
// ========== Tools Section (Left Column) ==========
|
|
353
397
|
function renderToolsSection() {
|
|
354
398
|
var container = document.getElementById('tools-section');
|
|
@@ -404,12 +448,7 @@ function renderToolsSection() {
|
|
|
404
448
|
(codexLensStatus.ready
|
|
405
449
|
? '<span class="tool-status-text success"><i data-lucide="check-circle" class="w-3.5 h-3.5"></i> v' + (codexLensStatus.version || 'installed') + '</span>' +
|
|
406
450
|
'<select id="codexlensModelSelect" class="btn-sm bg-muted border border-border rounded text-xs" onclick="event.stopPropagation()" title="' + (t('index.selectModel') || 'Select embedding model') + '">' +
|
|
407
|
-
|
|
408
|
-
'<option value="base">' + (t('index.modelBase') || 'Base (768d)') + '</option>' +
|
|
409
|
-
'<option value="fast">' + (t('index.modelFast') || 'Fast (384d)') + '</option>' +
|
|
410
|
-
'<option value="minilm">' + (t('index.modelMinilm') || 'MiniLM (384d)') + '</option>' +
|
|
411
|
-
'<option value="multilingual" style="color: var(--muted-foreground)">' + (t('index.modelMultilingual') || 'Multilingual (1024d)') + ' ⚠️</option>' +
|
|
412
|
-
'<option value="balanced" style="color: var(--muted-foreground)">' + (t('index.modelBalanced') || 'Balanced (1024d)') + ' ⚠️</option>' +
|
|
451
|
+
buildModelSelectOptions() +
|
|
413
452
|
'</select>' +
|
|
414
453
|
'<button class="btn-sm btn-primary" onclick="event.stopPropagation(); initCodexLensIndex(\'full\', getSelectedModel())" title="' + (t('index.fullDesc') || 'FTS + Semantic search (recommended)') + '"><i data-lucide="layers" class="w-3 h-3"></i> ' + (t('index.fullIndex') || '全部索引') + '</button>' +
|
|
415
454
|
'<button class="btn-sm btn-outline" onclick="event.stopPropagation(); initCodexLensIndex(\'vector\', getSelectedModel())" title="' + (t('index.vectorDesc') || 'Semantic search with embeddings') + '"><i data-lucide="sparkles" class="w-3 h-3"></i> ' + (t('index.vectorIndex') || '向量索引') + '</button>' +
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -35,8 +35,17 @@ from .output import (
|
|
|
35
35
|
app = typer.Typer(help="CodexLens CLI — local code indexing and search.")
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
def _configure_logging(verbose: bool) -> None:
|
|
39
|
-
|
|
38
|
+
def _configure_logging(verbose: bool, json_mode: bool = False) -> None:
|
|
39
|
+
"""Configure logging level.
|
|
40
|
+
|
|
41
|
+
In JSON mode, suppress INFO logs to keep stderr clean for error parsing.
|
|
42
|
+
Only WARNING and above are shown to avoid mixing logs with JSON output.
|
|
43
|
+
"""
|
|
44
|
+
if json_mode and not verbose:
|
|
45
|
+
# In JSON mode, suppress INFO logs to keep stderr clean
|
|
46
|
+
level = logging.WARNING
|
|
47
|
+
else:
|
|
48
|
+
level = logging.DEBUG if verbose else logging.INFO
|
|
40
49
|
logging.basicConfig(level=level, format="%(levelname)s %(message)s")
|
|
41
50
|
|
|
42
51
|
|
|
@@ -53,10 +62,27 @@ def _parse_languages(raw: Optional[List[str]]) -> Optional[List[str]]:
|
|
|
53
62
|
|
|
54
63
|
|
|
55
64
|
def _get_index_root() -> Path:
|
|
56
|
-
"""Get the index root directory from config or default.
|
|
65
|
+
"""Get the index root directory from config or default.
|
|
66
|
+
|
|
67
|
+
Priority order:
|
|
68
|
+
1. CODEXLENS_INDEX_DIR environment variable
|
|
69
|
+
2. index_dir from ~/.codexlens/config.json
|
|
70
|
+
3. Default: ~/.codexlens/indexes
|
|
71
|
+
"""
|
|
57
72
|
env_override = os.getenv("CODEXLENS_INDEX_DIR")
|
|
58
73
|
if env_override:
|
|
59
74
|
return Path(env_override).expanduser().resolve()
|
|
75
|
+
|
|
76
|
+
# Read from config.json
|
|
77
|
+
config_file = Path.home() / ".codexlens" / "config.json"
|
|
78
|
+
if config_file.exists():
|
|
79
|
+
try:
|
|
80
|
+
cfg = json.loads(config_file.read_text(encoding="utf-8"))
|
|
81
|
+
if "index_dir" in cfg:
|
|
82
|
+
return Path(cfg["index_dir"]).expanduser().resolve()
|
|
83
|
+
except (json.JSONDecodeError, OSError):
|
|
84
|
+
pass # Fall through to default
|
|
85
|
+
|
|
60
86
|
return Path.home() / ".codexlens" / "indexes"
|
|
61
87
|
|
|
62
88
|
|
|
@@ -95,7 +121,7 @@ def init(
|
|
|
95
121
|
If semantic search dependencies are installed, automatically generates embeddings
|
|
96
122
|
after indexing completes. Use --no-embeddings to skip this step.
|
|
97
123
|
"""
|
|
98
|
-
_configure_logging(verbose)
|
|
124
|
+
_configure_logging(verbose, json_mode)
|
|
99
125
|
config = Config()
|
|
100
126
|
languages = _parse_languages(language)
|
|
101
127
|
base_path = path.expanduser().resolve()
|
|
@@ -314,7 +340,7 @@ def search(
|
|
|
314
340
|
# Force hybrid mode
|
|
315
341
|
codexlens search "authentication" --mode hybrid
|
|
316
342
|
"""
|
|
317
|
-
_configure_logging(verbose)
|
|
343
|
+
_configure_logging(verbose, json_mode)
|
|
318
344
|
search_path = path.expanduser().resolve()
|
|
319
345
|
|
|
320
346
|
# Validate mode
|
|
@@ -487,7 +513,7 @@ def symbol(
|
|
|
487
513
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
|
|
488
514
|
) -> None:
|
|
489
515
|
"""Look up symbols by name and optional kind."""
|
|
490
|
-
_configure_logging(verbose)
|
|
516
|
+
_configure_logging(verbose, json_mode)
|
|
491
517
|
search_path = path.expanduser().resolve()
|
|
492
518
|
|
|
493
519
|
registry: RegistryStore | None = None
|
|
@@ -538,7 +564,7 @@ def inspect(
|
|
|
538
564
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
|
|
539
565
|
) -> None:
|
|
540
566
|
"""Analyze a single file and display symbols."""
|
|
541
|
-
_configure_logging(verbose)
|
|
567
|
+
_configure_logging(verbose, json_mode)
|
|
542
568
|
config = Config()
|
|
543
569
|
factory = ParserFactory(config)
|
|
544
570
|
|
|
@@ -588,7 +614,7 @@ def status(
|
|
|
588
614
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable debug logging."),
|
|
589
615
|
) -> None:
|
|
590
616
|
"""Show index status and configuration."""
|
|
591
|
-
_configure_logging(verbose)
|
|
617
|
+
_configure_logging(verbose, json_mode)
|
|
592
618
|
|
|
593
619
|
registry: RegistryStore | None = None
|
|
594
620
|
try:
|
|
@@ -648,7 +674,7 @@ def status(
|
|
|
648
674
|
# Embedding manager not available
|
|
649
675
|
pass
|
|
650
676
|
except Exception as e:
|
|
651
|
-
|
|
677
|
+
logging.debug(f"Failed to get embeddings status: {e}")
|
|
652
678
|
|
|
653
679
|
stats = {
|
|
654
680
|
"index_root": str(index_root),
|
|
@@ -737,7 +763,7 @@ def projects(
|
|
|
737
763
|
- show <path>: Show details for a specific project
|
|
738
764
|
- remove <path>: Remove a project from the registry
|
|
739
765
|
"""
|
|
740
|
-
_configure_logging(verbose)
|
|
766
|
+
_configure_logging(verbose, json_mode)
|
|
741
767
|
|
|
742
768
|
registry: RegistryStore | None = None
|
|
743
769
|
try:
|
|
@@ -892,7 +918,7 @@ def config(
|
|
|
892
918
|
Config keys:
|
|
893
919
|
- index_dir: Directory to store indexes (default: ~/.codexlens/indexes)
|
|
894
920
|
"""
|
|
895
|
-
_configure_logging(verbose)
|
|
921
|
+
_configure_logging(verbose, json_mode)
|
|
896
922
|
|
|
897
923
|
config_file = Path.home() / ".codexlens" / "config.json"
|
|
898
924
|
|
|
@@ -1057,7 +1083,7 @@ def migrate(
|
|
|
1057
1083
|
This is a safe operation that preserves all existing data.
|
|
1058
1084
|
Progress is shown during migration.
|
|
1059
1085
|
"""
|
|
1060
|
-
_configure_logging(verbose)
|
|
1086
|
+
_configure_logging(verbose, json_mode)
|
|
1061
1087
|
base_path = path.expanduser().resolve()
|
|
1062
1088
|
|
|
1063
1089
|
registry: RegistryStore | None = None
|
|
@@ -1183,7 +1209,7 @@ def clean(
|
|
|
1183
1209
|
With path, removes that project's indexes.
|
|
1184
1210
|
With --all, removes all indexes (use with caution).
|
|
1185
1211
|
"""
|
|
1186
|
-
_configure_logging(verbose)
|
|
1212
|
+
_configure_logging(verbose, json_mode)
|
|
1187
1213
|
|
|
1188
1214
|
try:
|
|
1189
1215
|
mapper = PathMapper()
|
|
@@ -1329,7 +1355,7 @@ def semantic_list(
|
|
|
1329
1355
|
Shows files that have LLM-generated summaries and keywords.
|
|
1330
1356
|
Results are aggregated from all index databases in the project.
|
|
1331
1357
|
"""
|
|
1332
|
-
_configure_logging(verbose)
|
|
1358
|
+
_configure_logging(verbose, json_mode)
|
|
1333
1359
|
base_path = path.expanduser().resolve()
|
|
1334
1360
|
|
|
1335
1361
|
registry: Optional[RegistryStore] = None
|
|
@@ -1798,7 +1824,7 @@ def embeddings_generate(
|
|
|
1798
1824
|
codexlens embeddings-generate ~/.codexlens/indexes/project/_index.db # Specific index
|
|
1799
1825
|
codexlens embeddings-generate ~/projects/my-app --model fast --force # Regenerate with fast model
|
|
1800
1826
|
"""
|
|
1801
|
-
_configure_logging(verbose)
|
|
1827
|
+
_configure_logging(verbose, json_mode)
|
|
1802
1828
|
|
|
1803
1829
|
from codexlens.cli.embedding_manager import generate_embeddings, generate_embeddings_recursive
|
|
1804
1830
|
|
|
@@ -279,6 +279,21 @@ def generate_embeddings(
|
|
|
279
279
|
|
|
280
280
|
try:
|
|
281
281
|
with VectorStore(index_path) as vector_store:
|
|
282
|
+
# Check model compatibility with existing embeddings
|
|
283
|
+
if not force:
|
|
284
|
+
is_compatible, warning = vector_store.check_model_compatibility(
|
|
285
|
+
model_profile, embedder.model_name, embedder.embedding_dim
|
|
286
|
+
)
|
|
287
|
+
if not is_compatible:
|
|
288
|
+
return {
|
|
289
|
+
"success": False,
|
|
290
|
+
"error": warning,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
# Set/update model configuration for this index
|
|
294
|
+
vector_store.set_model_config(
|
|
295
|
+
model_profile, embedder.model_name, embedder.embedding_dim
|
|
296
|
+
)
|
|
282
297
|
# Use bulk insert mode for efficient batch ANN index building
|
|
283
298
|
# This defers ANN updates until end_bulk_insert() is called
|
|
284
299
|
with vector_store.bulk_insert():
|