mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
feat: 添加 CodexLens 配置接口,增强索引状态检查功能,支持并行获取状态和配置
This commit is contained in:
@@ -330,6 +330,17 @@ interface ModelInfo {
|
|||||||
updated_at?: string;
|
updated_at?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CodexLensConfig {
|
||||||
|
config_file?: string;
|
||||||
|
index_dir?: string;
|
||||||
|
embedding_backend?: string; // 'fastembed' (local) or 'litellm' (api)
|
||||||
|
embedding_model?: string;
|
||||||
|
reranker_enabled?: boolean;
|
||||||
|
reranker_backend?: string; // 'onnx' (local) or 'api'
|
||||||
|
reranker_model?: string;
|
||||||
|
reranker_top_k?: number;
|
||||||
|
}
|
||||||
|
|
||||||
interface IndexStatus {
|
interface IndexStatus {
|
||||||
indexed: boolean;
|
indexed: boolean;
|
||||||
has_embeddings: boolean;
|
has_embeddings: boolean;
|
||||||
@@ -337,6 +348,7 @@ interface IndexStatus {
|
|||||||
embeddings_coverage_percent?: number;
|
embeddings_coverage_percent?: number;
|
||||||
total_chunks?: number;
|
total_chunks?: number;
|
||||||
model_info?: ModelInfo | null;
|
model_info?: ModelInfo | null;
|
||||||
|
config?: CodexLensConfig | null;
|
||||||
warning?: string;
|
warning?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,12 +402,39 @@ function splitResultsWithExtraFiles<T extends { file: string }>(
|
|||||||
*/
|
*/
|
||||||
async function checkIndexStatus(path: string = '.'): Promise<IndexStatus> {
|
async function checkIndexStatus(path: string = '.'): Promise<IndexStatus> {
|
||||||
try {
|
try {
|
||||||
const result = await executeCodexLens(['status', '--json'], { cwd: path });
|
// Fetch both status and config in parallel
|
||||||
|
const [statusResult, configResult] = await Promise.all([
|
||||||
|
executeCodexLens(['status', '--json'], { cwd: path }),
|
||||||
|
executeCodexLens(['config', 'show', '--json'], { cwd: path }),
|
||||||
|
]);
|
||||||
|
|
||||||
if (!result.success) {
|
// Parse config
|
||||||
|
let config: CodexLensConfig | null = null;
|
||||||
|
if (configResult.success && configResult.output) {
|
||||||
|
try {
|
||||||
|
const cleanConfigOutput = stripAnsi(configResult.output);
|
||||||
|
const parsedConfig = JSON.parse(cleanConfigOutput);
|
||||||
|
const configData = parsedConfig.result || parsedConfig;
|
||||||
|
config = {
|
||||||
|
config_file: configData.config_file,
|
||||||
|
index_dir: configData.index_dir,
|
||||||
|
embedding_backend: configData.embedding_backend,
|
||||||
|
embedding_model: configData.embedding_model,
|
||||||
|
reranker_enabled: configData.reranker_enabled,
|
||||||
|
reranker_backend: configData.reranker_backend,
|
||||||
|
reranker_model: configData.reranker_model,
|
||||||
|
reranker_top_k: configData.reranker_top_k,
|
||||||
|
};
|
||||||
|
} catch {
|
||||||
|
// Config parse failed, continue without it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!statusResult.success) {
|
||||||
return {
|
return {
|
||||||
indexed: false,
|
indexed: false,
|
||||||
has_embeddings: false,
|
has_embeddings: false,
|
||||||
|
config,
|
||||||
warning: 'No CodexLens index found. Run smart_search(action="init") to create index for better search results.',
|
warning: 'No CodexLens index found. Run smart_search(action="init") to create index for better search results.',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -403,7 +442,7 @@ async function checkIndexStatus(path: string = '.'): Promise<IndexStatus> {
|
|||||||
// Parse status output
|
// Parse status output
|
||||||
try {
|
try {
|
||||||
// Strip ANSI color codes from JSON output
|
// Strip ANSI color codes from JSON output
|
||||||
const cleanOutput = stripAnsi(result.output || '{}');
|
const cleanOutput = stripAnsi(statusResult.output || '{}');
|
||||||
const parsed = JSON.parse(cleanOutput);
|
const parsed = JSON.parse(cleanOutput);
|
||||||
// Handle both direct and nested response formats (status returns {success, result: {...}})
|
// Handle both direct and nested response formats (status returns {success, result: {...}})
|
||||||
const status = parsed.result || parsed;
|
const status = parsed.result || parsed;
|
||||||
@@ -443,12 +482,14 @@ async function checkIndexStatus(path: string = '.'): Promise<IndexStatus> {
|
|||||||
total_chunks: totalChunks,
|
total_chunks: totalChunks,
|
||||||
// Ensure model_info is null instead of undefined so it's included in JSON
|
// Ensure model_info is null instead of undefined so it's included in JSON
|
||||||
model_info: modelInfo ?? null,
|
model_info: modelInfo ?? null,
|
||||||
|
config,
|
||||||
warning,
|
warning,
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
return {
|
return {
|
||||||
indexed: false,
|
indexed: false,
|
||||||
has_embeddings: false,
|
has_embeddings: false,
|
||||||
|
config,
|
||||||
warning: 'Failed to parse index status',
|
warning: 'Failed to parse index status',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -719,10 +760,43 @@ async function executeStatusAction(params: Params): Promise<SearchResult> {
|
|||||||
|
|
||||||
const indexStatus = await checkIndexStatus(path);
|
const indexStatus = await checkIndexStatus(path);
|
||||||
|
|
||||||
|
// Build detailed status message
|
||||||
|
const statusParts: string[] = [];
|
||||||
|
|
||||||
|
// Index status
|
||||||
|
statusParts.push(`Index: ${indexStatus.indexed ? 'indexed' : 'not indexed'}`);
|
||||||
|
if (indexStatus.file_count) {
|
||||||
|
statusParts.push(`Files: ${indexStatus.file_count}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Embeddings status
|
||||||
|
if (indexStatus.embeddings_coverage_percent !== undefined) {
|
||||||
|
statusParts.push(`Embeddings: ${indexStatus.embeddings_coverage_percent.toFixed(1)}%`);
|
||||||
|
}
|
||||||
|
if (indexStatus.total_chunks) {
|
||||||
|
statusParts.push(`Chunks: ${indexStatus.total_chunks}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config summary
|
||||||
|
if (indexStatus.config) {
|
||||||
|
const cfg = indexStatus.config;
|
||||||
|
// Embedding backend info
|
||||||
|
const embeddingType = cfg.embedding_backend === 'litellm' ? 'API' : 'Local';
|
||||||
|
statusParts.push(`Embedding: ${embeddingType} (${cfg.embedding_model || 'default'})`);
|
||||||
|
|
||||||
|
// Reranker info
|
||||||
|
if (cfg.reranker_enabled) {
|
||||||
|
const rerankerType = cfg.reranker_backend === 'onnx' ? 'Local' : 'API';
|
||||||
|
statusParts.push(`Reranker: ${rerankerType} (${cfg.reranker_model || 'default'})`);
|
||||||
|
} else {
|
||||||
|
statusParts.push('Reranker: disabled');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
status: indexStatus,
|
status: indexStatus,
|
||||||
message: indexStatus.warning || `Index status: ${indexStatus.indexed ? 'indexed' : 'not indexed'}, embeddings: ${indexStatus.has_embeddings ? 'available' : 'not available'}`,
|
message: indexStatus.warning || statusParts.join(' | '),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1445,8 +1519,9 @@ async function executeHybridMode(params: Params): Promise<SearchResult> {
|
|||||||
allResults = baselineResult.filteredResults;
|
allResults = baselineResult.filteredResults;
|
||||||
baselineInfo = baselineResult.baselineInfo;
|
baselineInfo = baselineResult.baselineInfo;
|
||||||
|
|
||||||
// 1. Filter noisy files (coverage, node_modules, etc.) and excluded extensions
|
// 1. Filter noisy directories (node_modules, etc.)
|
||||||
allResults = filterNoisyFiles(allResults, { excludeExtensions, codeOnly });
|
// NOTE: Extension filtering is now done engine-side via --code-only and --exclude-extensions
|
||||||
|
allResults = filterNoisyFiles(allResults, {});
|
||||||
// 2. Boost results containing query keywords
|
// 2. Boost results containing query keywords
|
||||||
allResults = applyKeywordBoosting(allResults, query);
|
allResults = applyKeywordBoosting(allResults, query);
|
||||||
// 3. Enforce score diversity (penalize identical scores)
|
// 3. Enforce score diversity (penalize identical scores)
|
||||||
|
|||||||
Reference in New Issue
Block a user