Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 2 additions & 8 deletions src/cli/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ import {
handleGraphCallees,
handleGraphChain,
} from './handlers/graphHandlers';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 未使用的导入未清理

已移除 SemanticSearchSchema 的使用,但对应的源文件 (./schemas/semanticSchemas) 中的模式定义仍存在,会产生死代码

建议: 检查 ./schemas/semanticSchemas 文件,如果不再需要,删除该文件或移除其中未使用的导出

Suggested change
} from './handlers/graphHandlers';
// 建议在 semanticSchemas.ts 中检查:
// 如果 SemanticSearchSchema 不再被任何地方使用,删除该文件

import { SemanticSearchSchema } from './schemas/semanticSchemas';
import { IndexRepoSchema } from './schemas/indexSchemas';
import { SearchSymbolsSchema } from './schemas/querySchemas';
import { SearchFilesSchema } from './schemas/queryFilesSchemas';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 未使用的导入未清理

已移除 handleSemanticSearch 的使用,但对应的源文件 (./handlers/semanticHandlers.ts) 中的处理函数仍存在,会产生死代码

建议: 检查 ./handlers/semanticHandlers.ts 文件,如果不再需要,删除该文件或移除其中未使用的导出

Suggested change
import { SearchFilesSchema } from './schemas/queryFilesSchemas';
// 建议在 semanticHandlers.ts 中检查:
// 如果 handleSemanticSearch 不再被任何地方使用,删除该文件

import { handleSemanticSearch } from './handlers/semanticHandlers';
import { handleIndexRepo } from './handlers/indexHandlers';
import { handleSearchSymbols } from './handlers/queryHandlers';
import { handleSearchFiles } from './handlers/queryFilesHandlers';
Expand All @@ -42,17 +40,13 @@ import { handleRepoMap } from './handlers/repoMapHandler';
* Maps command keys to their schema + handler implementations.
*
* Command keys follow the pattern:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 SUGGESTION: 注释与实现不一致

注释中移除了 'dsr:generate' 子命令,但这只是注释变更。如果 'dsr:generate' 也被移除,应同步更新注释;如果仍在使用,不应从注释中移除

建议: 确认 'dsr:generate' 子命令的实际状态,如果已移除则注释正确,否则需要恢复

Suggested change
* Command keys follow the pattern:
// 如果 dsr:generate 仍在使用,注释应改为:
// - Subcommands: 'graph:find', 'graph:query', 'dsr:generate'

* - Top-level commands: 'index', 'semantic', 'status'
* - Subcommands: 'graph:find', 'graph:query', 'dsr:generate'
* - Top-level commands: 'index', 'status'
* - Subcommands: 'graph:find', 'graph:query'
*
* This will be populated as commands are migrated from src/commands/*.ts
*/
export const cliHandlers: Record<string, HandlerRegistration<any>> = {
// Top-level commands
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 缺少向后兼容性处理

直接移除 'semantic' 命令是破坏性变更。如果用户仍在使用此命令,运行时会报错 'Unknown command: semantic',而没有任何过渡提示

建议: 考虑保留一个空命令实现,向用户显示弃用警告并建议替代方案

Suggested change
// Top-level commands
// 可以保留一个弃用版本的命令:
'semantic': {
schema: SemanticSearchSchema,
handler: (args) => {
console.warn("Warning: 'semantic' command is deprecated. Use 'graph:query' instead.");
return handleSemanticSearch(args);
},
}

'semantic': {
schema: SemanticSearchSchema,
handler: handleSemanticSearch,
},
'index': {
schema: IndexRepoSchema,
handler: handleIndexRepo,
Expand Down
2 changes: 0 additions & 2 deletions src/commands/ai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Command } from 'commander';
import { indexCommand } from '../cli/commands/indexCommand.js';
import { queryCommand } from '../cli/commands/queryCommand.js';
import { queryFilesCommand } from '../cli/commands/queryFilesCommand.js';
import { semanticCommand } from '../cli/commands/semanticCommand.js';
import { serveCommand, agentCommand } from '../cli/commands/serveCommands.js';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 命令移除可能造成破坏性变更

semanticCommand 被从 ai 命令组中移除。如果此命令是公开功能,用户脚本或自动化流程可能会因此失败。建议确认 semanticCommand 是否仍在其他地方使用,或确认此为计划内的功能移除。

建议: 如果这是有意的功能移除,建议在 changelog 中记录此变更。如果这是误删除,需要恢复 semanticCommand 的导入和注册。

Suggested change
import { serveCommand, agentCommand } from '../cli/commands/serveCommands.js';
// 恢复 semanticCommand
import { semanticCommand } from '../cli/commands/semanticCommand.js';
// 在 aiCommand 中恢复
.addCommand(semanticCommand)

import { packCommand, unpackCommand } from '../cli/commands/archiveCommands.js';
import { hooksCommand } from '../cli/commands/hooksCommands.js';
Expand All @@ -18,7 +17,6 @@ export const aiCommand = new Command('ai')
.addCommand(repoMapCommand)
.addCommand(queryCommand)
.addCommand(queryFilesCommand)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: orphaned import 可能产生死代码

semanticCommand 相关的导入和注册被移除,但无法从当前 diff 确认 semanticCommand.js 实现文件是否也被删除或在其他地方使用。如果该文件不再被任何模块引用,可能形成死代码。

建议: 检查 semanticCommand.js 文件是否仍存在于 ../cli/commands/ 目录中,如果不再需要,应一并删除该文件以保持代码整洁。

Suggested change
.addCommand(queryFilesCommand)
// 确认文件是否存在
ls src/cli/commands/semanticCommand.js

.addCommand(semanticCommand)
.addCommand(graphCommand)
.addCommand(packCommand)
.addCommand(unpackCommand)
Expand Down
47 changes: 0 additions & 47 deletions src/core/search.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,12 @@
import { dequantizeSQ8, cosineSimilarity, quantizeSQ8, SQ8Vector } from './sq8';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 SUGGESTION: 删除的导入可能需要保留

删除了 6 个 retrieval 模块的导入。在完全移除这些功能之前,需要确认 retrieval 模块在其他地方是否仍有使用价值,或者整个 retrieval 功能是否被废弃。

建议: 如果 retrieval 功能只是从此文件中移除但仍在其他地方使用,不需要额外操作。如果整个功能被废弃,建议同时清理 retrieval 目录下的文件,避免死代码。

import { hashEmbedding } from './embedding';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 删除的功能可能仍被其他模块调用

删除了 buildAdaptiveQueryPlan 和 runAdaptiveRetrieval 函数及其相关接口。如果这些函数在其他模块(如 handleSemanticSearch)中被调用,将导致编译错误。

建议: 在删除这些函数前,确认所有调用方都已更新或移除。建议搜索整个代码库中是否还存在对这些函数的引用:buildAdaptiveQueryPlan、runAdaptiveRetrieval、AdaptiveQueryPlan、AdaptiveFusionOptions、AdaptiveFusionOutput

Suggested change
import { hashEmbedding } from './embedding';
// 建议先执行以下搜索确认无引用:
// grep -r "buildAdaptiveQueryPlan\|runAdaptiveRetrieval\|AdaptiveQueryPlan" src/

import { classifyQuery } from './retrieval/classifier';
import { expandQuery } from './retrieval/expander';
import { fuseResults } from './retrieval/fuser';
import { rerank } from './retrieval/reranker';
import { computeWeights, type WeightFeedback } from './retrieval/weights';
import type { QueryType, RankedResult, RetrievalResult, RetrievalWeights } from './retrieval/types';

export interface SemanticHit {
content_hash: string;
score: number;
text?: string;
}

export interface AdaptiveQueryPlan {
query: string;
expanded: string[];
queryType: QueryType;
weights: RetrievalWeights;
}

export interface AdaptiveFusionOptions {
feedback?: WeightFeedback;
limit?: number;
}

export interface AdaptiveFusionOutput extends AdaptiveQueryPlan {
results: RankedResult[];
}

export function buildQueryVector(text: string, dim: number): SQ8Vector {
const vec = hashEmbedding(text, { dim });
return quantizeSQ8(vec);
Expand All @@ -39,28 +17,3 @@ export function scoreAgainst(q: SQ8Vector, item: { scale: number; qvec: Int8Arra
const vf = dequantizeSQ8({ dim: item.dim, scale: item.scale, q: item.qvec });
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NIT: 文件末尾不一致

删除代码后,文件末尾的换行符处理可能不一致。原文件末尾可能有换行符,删除后可能需要保持一致。

建议: 确保文件末尾有统一的换行符(通常为单行)

return cosineSimilarity(qf, vf);
}

export function buildAdaptiveQueryPlan(query: string, feedback?: WeightFeedback): AdaptiveQueryPlan {
const q = String(query ?? '').trim();
const queryType = classifyQuery(q);
const expanded = expandQuery(q, queryType);
const weights = computeWeights(queryType, feedback);
return { query: q, expanded, queryType, weights };
}

/**
* Runs the adaptive retrieval pipeline: classification -> expansion -> weighting -> fusion -> heuristic reranking.
*
* Note: This uses synchronous heuristic reranking. For higher quality but slower reranking using
* the ONNX Cross-Encoder, use the `CrossEncoderReranker` class directly (which is async).
*/
export function runAdaptiveRetrieval(
query: string,
candidates: RetrievalResult[],
options: AdaptiveFusionOptions = {}
): AdaptiveFusionOutput {
const plan = buildAdaptiveQueryPlan(query, options.feedback);
const fused = fuseResults(candidates, plan.weights, options.limit);
const results = rerank(plan.query, fused, { limit: options.limit });
return { ...plan, results };
}
69 changes: 1 addition & 68 deletions src/mcp/handlers/searchHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import type { ToolHandler } from '../types';
import { successResponse, errorResponse } from '../types';
import type {
SearchSymbolsArgs,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 被删除的类型可能仍存在于 schemas 文件中

从导入中移除了 SemanticSearchArgs,但该类型定义可能仍在 ../schemas 文件中。如果确认不再使用,应同时删除 schemas 中的类型定义,避免死代码。

建议: 检查 src/mcp/schemas 中的 SemanticSearchArgs 类型定义,如果不再被任何文件使用,一并删除。

SemanticSearchArgs,
RepoMapArgs
} from '../schemas';
import { resolveGitRoot, inferScanRoot, inferWorkspaceRoot } from '../../core/git';
import { defaultDbDir, openTablesByLang } from '../../core/lancedb';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 删除的函数可能导致核心模块中的死导出

移除了 buildQueryVectorscoreAgainst 的导入。这些函数可能仍在 ../../core/search 中定义,但不再被此文件使用。如果这些函数仅被本文件调用,则它们也变成了死代码。

建议: 检查 ../../core/search 模块,如果 buildQueryVectorscoreAgainst 不再被任何文件使用,考虑一并删除或标记为 @deprecated

import { buildQueryVector, scoreAgainst } from '../../core/search';
import { checkIndex, resolveLangs } from '../../core/indexCheck';
import { generateRepoMap } from '../../core/repoMap';
import { buildCoarseWhere, filterAndRankSymbolRows, inferSymbolSearchMode, pickCoarseToken } from '../../core/symbolSearch';
Expand Down Expand Up @@ -253,69 +251,4 @@ export const handleSearchSymbols: ToolHandler<SearchSymbolsArgs> = async (args)
});
};

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 CRITICAL: 删除的 handler 可能仍在注册表中被引用

完全删除了 handleSemanticSearch 函数。如果此 handler 在某处(如 router、handler map 或 MCP 工具注册表中)被注册,调用时会抛出运行时错误。建议检查 src/mcp/index.ts、src/mcp/server.ts 或类似的注册文件。

建议: 在删除 handler 前,先从注册表中移除对应的路由/工具定义。如果使用了 handler map 或 switch 语句,也需要同步移除对该函数的引用。

Suggested change
// 检查是否存在类似以下的注册代码并移除:
// case 'semantic_search': return handleSemanticSearch(args);
// toolsMap['semantic_search'] = handleSemanticSearch;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 缺少对依赖的清理

删除 handler 时,相关依赖(如 checkIndex、openTablesByLang 等调用)也被间接移除。但如果有测试文件引用了 handleSemanticSearch,测试将会失败。

建议: 查找并更新或删除相关的测试文件:运行 grep -r "handleSemanticSearch" src/ 查找所有引用并处理。

export const handleSemanticSearch: ToolHandler<SemanticSearchArgs> = async (args) => {
const repoRoot = await resolveGitRoot(path.resolve(args.path));
const query = args.query;
const topk = args.topk ?? 10;
const langSel = args.lang ?? 'auto';
const withRepoMap = args.with_repo_map ?? false;
const wikiDir = resolveWikiDirInsideRepo(repoRoot, args.wiki_dir ?? '');
const repoMapMaxFiles = args.repo_map_max_files ?? 20;
const repoMapMaxSymbols = args.repo_map_max_symbols ?? 5;

const status = await checkIndex(repoRoot);
if (!status.ok) {
return errorResponse(
new Error('Index incompatible or missing'),
'index_incompatible'
);
}

const langs = resolveLangs(status.found.meta ?? null, langSel as any);
const dim = typeof status.found.meta?.dim === 'number' ? status.found.meta.dim : 256;
const dbDir = defaultDbDir(repoRoot);
const { byLang } = await openTablesByLang({
dbDir,
dim,
mode: 'open_only',
languages: langs
});
const q = buildQueryVector(query, dim);

const allScored: any[] = [];
for (const lang of langs) {
const t = byLang[lang];
if (!t) continue;
const chunkRows = await t.chunks
.query()
.select(['content_hash', 'text', 'dim', 'scale', 'qvec_b64'])
.limit(1_000_000)
.toArray();
for (const r of chunkRows as any[]) {
allScored.push({
lang,
content_hash: String(r.content_hash),
score: scoreAgainst(q, {
dim: Number(r.dim),
scale: Number(r.scale),
qvec: new Int8Array(Buffer.from(String(r.qvec_b64), 'base64'))
}),
text: String(r.text)
});
}
}

const rows = allScored
.sort((a, b) => b.score - a.score)
.slice(0, topk);
const repoMap = withRepoMap
? await buildRepoMapAttachment(repoRoot, wikiDir, repoMapMaxFiles, repoMapMaxSymbols)
: undefined;

return successResponse({
repoRoot,
lang: langSel,
rows,
...(repoMap ? { repo_map: repoMap } : {})
});
};

16 changes: 0 additions & 16 deletions src/mcp/schemas/searchSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,6 @@ export const SearchSymbolsArgsSchema = z.object({

export type SearchSymbolsArgs = z.infer<typeof SearchSymbolsArgsSchema>;

/**
* Schema for semantic_search tool
*/
export const SemanticSearchArgsSchema = z.object({
path: z.string().min(1, 'path is required'),
query: z.string().min(1, 'query is required'),
topk: z.number().int().positive().default(10),
lang: LangEnum.default('auto'),
with_repo_map: z.boolean().default(false),
repo_map_max_files: z.number().int().positive().default(20),
repo_map_max_symbols: z.number().int().positive().default(5),
wiki_dir: z.string().optional(),
});

export type SemanticSearchArgs = z.infer<typeof SemanticSearchArgsSchema>;

/**
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 CRITICAL: 删除被引用的类型可能导致编译错误

删除 SemanticSearchArgsSchema 和 SemanticSearchArgs 类型前,需要确认没有其他文件引用这些类型。如果有其他文件 import 了这些类型,将导致 TypeScript 编译失败。

建议: 在删除前,执行全局搜索确认是否有其他文件引用了 SemanticSearchArgs 或 SemanticSearchArgsSchema

Suggested change
/**
// 在终端执行: grep -r "SemanticSearchArgs" --include="*.ts" src/

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 功能删除需同步处理

如果 semantic_search 工具的实现在其他地方仍然存在,仅删除 schema 会导致运行时错误。需确认是否同时删除了工具实现。

建议: 检查 src/mcp 目录下是否存在 semantic_search 相关的工具定义,如有则需一并删除或保留 schema

Suggested change
/**
// 搜索工具实现: grep -r "semantic_search" --include="*.ts" src/

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 SUGGESTION: 缺少版本记录或迁移说明

如果这是有意的功能移除(deprecation),建议在 CHANGELOG 或相关文档中记录此变更,以便用户了解 API 变化。

建议: 在 commit message 或 CHANGELOG 中说明移除 semantic_search 工具的原因

Suggested change
/**
git commit -m "feat: remove semantic_search tool schema (deprecated)"

* Schema for repo_map tool
*/
Expand Down
1 change: 0 additions & 1 deletion src/mcp/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ export class GitAIV2MCPServer {
list_files: schemas.ListFilesArgsSchema,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 移除公开工具可能造成破坏性变更

从服务器工具列表中移除 semantic_search 是一项破坏性变更。任何使用此工具的现有客户端将无法再调用它。如果这是有意的弃用流程,请确保:1) 客户端已收到弃用通知 2) 存在迁移路径

建议: 如果 semantic_search 需要被弃用,建议:1) 先将其标记为 deprecated 2) 在后续版本中再完全移除 3) 记录此变更到 CHANGELOG

Suggested change
list_files: schemas.ListFilesArgsSchema,
// 建议保留工具但标记为 deprecated:
// semantic_search: {
// ...schemas.SemanticSearchArgsSchema,
// description: 'DEPRECATED: 此工具将在 v2.0 中移除。请使用其他搜索工具替代。'
// }

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 可能存在未清理的相关代码

移除工具定义后,相关的 handler、schema 定义和测试代码可能需要同步清理。检查:1) handlers 中的 semantic_search 处理逻辑 2) schemas.SemanticSearchArgsSchema 定义 3) 相关单元测试

建议: 执行以下检查:

  1. 搜索 'semantic_search' 在整个项目中的其他引用
  2. 确认 handlers 中对应的处理逻辑已被移除或条件化
  3. 检查测试文件是否需要更新
  4. 确认 schemas 导出是否仍需要保留
Suggested change
list_files: schemas.ListFilesArgsSchema,
// 在项目根目录执行:
grep -r "semantic_search" --include="*.ts" .
// 如果schemas不再被使用,可以考虑移除导出:
// export { SemanticSearchArgsSchema } from './schemas' // 注释或删除

read_file: schemas.ReadFileArgsSchema,
search_symbols: schemas.SearchSymbolsArgsSchema,
semantic_search: schemas.SemanticSearchArgsSchema,
repo_map: schemas.RepoMapArgsSchema,
ast_graph_query: schemas.AstGraphQueryArgsSchema,
ast_graph_find: schemas.AstGraphFindArgsSchema,
Expand Down
4 changes: 1 addition & 3 deletions src/mcp/tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
} from './fileTools';
import {
searchSymbolsDefinition,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 可能存在孤立代码或破坏性更改

从导入中移除了 semanticSearchDefinition,但需要确认该定义本身是否已从 searchTools.ts 中删除,或者是否存在其他文件仍然引用此工具。

建议: 确认 semanticSearchDefinition 的完整移除流程:1) 检查 searchTools.ts 中是否已删除该定义;2) 检查是否有其他文件仍引用此工具;3) 如果是破坏性更改,请更新 CHANGELOG。

Suggested change
searchSymbolsDefinition,
// 建议检查 searchTools.ts 文件确保定义已被删除
// 同时检查项目中所有导入 semanticSearchDefinition 的文件

semanticSearchDefinition,
repoMapDefinition
} from './searchTools';
import {
Expand All @@ -37,9 +36,8 @@ export const allTools: ToolDefinition[] = [
listFilesDefinition,
readFileDefinition,

// Search tools (3)
// Search tools (2)
searchSymbolsDefinition,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NIT: 注释更新正确

搜索工具数量注释已从 (3) 正确更新为 (2)。

建议: 无需修改,注释与实际工具数量一致。

Suggested change
searchSymbolsDefinition,
// Search tools (2) ✓

semanticSearchDefinition,
repoMapDefinition,

// AST graph tools (7)
Expand Down
21 changes: 0 additions & 21 deletions src/mcp/tools/searchTools.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { ToolDefinition } from '../types';
import {
handleSearchSymbols,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 删除的工具定义可能导致外部消费者中断

完全移除了 semantic_search 工具定义。这是一个破坏性变更,任何依赖此工具的外部消费者将会报错 'Tool not found'。如果这是有意的功能移除,请确保此变更已记录并通知相关使用者。

建议: 确认此工具的移除是有意为之,并确保所有引用 semantic_search 的代码已被清理。如果只是暂时禁用,建议保留定义但注释掉,而不是直接删除。

Suggested change
handleSearchSymbols,
// 如果是暂时禁用,建议保留定义:
// export const semanticSearchDefinition: ToolDefinition = { ... }
// 并在 index.ts 中条件导出

handleSemanticSearch,
handleRepoMap
} from '../handlers';

Expand All @@ -28,26 +27,6 @@ export const searchSymbolsDefinition: ToolDefinition = {
handler: handleSearchSymbols
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 SUGGESTION: 需确认 handleSemanticSearch 处理函数是否也被移除

移除了 handleSemanticSearch 的导入,但如果该函数仍存在于 ../handlers 中,将形成死代码。建议检查 handlers 文件夹,确保相关处理函数也被一并移除,避免死代码。

建议: 检查 src/mcp/handlers 目录,确认 handleSemanticSearch 函数是否也被删除或保留。如果是死代码,一并删除;如果是其他功能需要保留,则忽略此问题。

Suggested change
handler: handleSearchSymbols
// 在 handlers/index.ts 中检查:
export { handleSemanticSearch } from './semanticHandler'; // 是否已移除

};

export const semanticSearchDefinition: ToolDefinition = {
name: 'semantic_search',
description: 'Semantic search using SQ8 vectors stored in LanceDB (brute-force). Risk: low (read-only).',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string' },
path: { type: 'string', description: 'Repository root path' },
topk: { type: 'number', default: 10 },
lang: { type: 'string', enum: ['auto', 'all', 'java', 'ts'], default: 'auto' },
with_repo_map: { type: 'boolean', default: false },
repo_map_max_files: { type: 'number', default: 20 },
repo_map_max_symbols: { type: 'number', default: 5 },
wiki_dir: { type: 'string', description: 'Wiki dir relative to repo root (optional)' }
},
required: ['path', 'query']
},
handler: handleSemanticSearch
};

export const repoMapDefinition: ToolDefinition = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NIT: 代码顺序不一致

原文件中 semanticSearchDefinition 位于第 30-52 行,删除后 repoMapDefinition 变成了第一个工具定义。如果后续有导出所有工具的汇总导出,顺序可能会影响调试体验。

建议: 这是一个轻微的代码风格问题,可忽略。如果有工具汇总导出,考虑保持原有顺序或在注释中说明原因。

Suggested change
export const repoMapDefinition: ToolDefinition = {
// 原顺序: searchSymbolsDefinition -> semanticSearchDefinition -> repoMapDefinition
// 删除后: searchSymbolsDefinition -> repoMapDefinition

name: 'repo_map',
description: 'Generate a lightweight repository map (ranked files + top symbols + wiki links). Risk: low (read-only).',
Expand Down
16 changes: 0 additions & 16 deletions test/e2e.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,22 +156,6 @@ test('git-ai works in Spring Boot and Vue repos', async () => {
assert.ok(obj.rows.some(r => String(r.file || '').includes('app/src/main/java/')));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 测试覆盖范围减少 - 删除 semantic 命令测试

删除了两个测试 ai semantic 命令的测试块。第一个测试 semantic 搜索基本功能,第二个测试 --with-repo-map、--repo-map-files 和 --repo-map-symbols 标志。这显著降低了测试覆盖率。

建议: 如果 semantic 功能已从代码库中移除,请确认这一点并记录在变更日志中。如果功能仍然存在但测试被意外删除,需要恢复这些测试以防止回归。

Suggested change
assert.ok(obj.rows.some(r => String(r.file || '').includes('app/src/main/java/')));
{
const res = runOk('node', [CLI, 'ai', 'semantic', 'hello controller', '--topk', '5'], springRepo);
const obj = JSON.parse(res.stdout);
assert.ok(Array.isArray(obj.hits));
assert.ok(obj.hits.length > 0);
}
{
const res = runOk('node', [CLI, 'ai', 'semantic', 'hello controller', '--topk', '5', '--with-repo-map', '--repo-map-files', '5', '--repo-map-symbols', '2'], springRepo);
const obj = JSON.parse(res.stdout);
assert.ok(Array.isArray(obj.hits));
assert.ok(obj.repo_map && obj.repo_map.enabled === true);
assert.ok(Array.isArray(obj.repo_map.files));
assert.ok(obj.repo_map.files.length > 0);
}

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 SUGGESTION: 缺少变更说明

如果删除这些测试是有意为之(功能弃用或重构),建议在 PR 描述或代码注释中说明原因,以便未来的维护者理解。

建议: 添加注释说明删除 semantic 测试的原因,例如:// Semantic search tests removed - feature deprecated in vX.Y

}

{
const res = runOk('node', [CLI, 'ai', 'semantic', 'hello controller', '--topk', '5'], springRepo);
const obj = JSON.parse(res.stdout);
assert.ok(Array.isArray(obj.hits));
assert.ok(obj.hits.length > 0);
}

{
const res = runOk('node', [CLI, 'ai', 'semantic', 'hello controller', '--topk', '5', '--with-repo-map', '--repo-map-files', '5', '--repo-map-symbols', '2'], springRepo);
const obj = JSON.parse(res.stdout);
assert.ok(Array.isArray(obj.hits));
assert.ok(obj.repo_map && obj.repo_map.enabled === true);
assert.ok(Array.isArray(obj.repo_map.files));
assert.ok(obj.repo_map.files.length > 0);
}

{
const res = runOk('node', [CLI, 'ai', 'graph', 'find', 'HelloController'], springRepo);
const obj = JSON.parse(res.stdout);
Expand Down
10 changes: 1 addition & 9 deletions test/mcp.smoke.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ test('mcp server supports atomic tool calls via path arg', async () => {
const toolNames = new Set((res.tools ?? []).map(t => t.name));

assert.ok(toolNames.has('search_symbols'));
assert.ok(toolNames.has('semantic_search'));
assert.ok(!toolNames.has('semantic_search'), 'semantic_search should not be registered');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ WARNING: 测试变更需要与实现代码变更同步

测试从验证 semantic_search 存在变为验证它不存在。这是重大行为变更,需要确认 MCP 服务器实现中确实已移除该工具。如果只修改测试而不修改实现,测试将失败。

建议: 确认 semantic_search 工具已从 MCP 服务器实现中移除。检查相关代码文件(如 mcp 服务器定义或工具注册代码)中是否存在对应的删除操作。

Suggested change
assert.ok(!toolNames.has('semantic_search'), 'semantic_search should not be registered');
// 确保在服务器实现中有对应的变更
// 例如在工具注册列表中移除 semantic_search

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 NIT: 断言消息格式建议

断言消息使用 'should not be registered',但更精确的描述应该是 'should not be available' 或 'has been removed',以更清晰地表达预期行为。

建议: 将断言消息改为更精确的描述:'semantic_search tool has been removed'

Suggested change
assert.ok(!toolNames.has('semantic_search'), 'semantic_search should not be registered');
assert.ok(!toolNames.has('semantic_search'), 'semantic_search tool has been removed');

assert.ok(toolNames.has('repo_map'));
assert.ok(toolNames.has('get_repo'));
assert.ok(toolNames.has('check_index'));
Expand Down Expand Up @@ -150,14 +150,6 @@ test('mcp server supports atomic tool calls via path arg', async () => {
assert.ok(parsed.repo_map.files.length > 0);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 SUGGESTION: 删除功能测试需确保完全移除

删除了 semantic_search 工具的调用测试。如果该功能被完全移除,这是正确的。但如果只是暂时禁用,删除测试会导致未来难以追踪该功能的恢复。

建议: 如果 semantic_search 是永久移除,删除测试是合理的。建议在代码变更日志中记录此变更,以便追踪历史。

Suggested change
assert.ok(parsed.repo_map.files.length > 0);
// 建议保留一个注释说明为何删除此测试
// TODO: semantic_search 功能已移除 (参见 PR #xxx)
// 如果未来需要恢复功能,请恢复此测试

}

{
const call = await client.callTool({ name: 'semantic_search', arguments: { path: repoDir, query: 'hello world', topk: 3 } });
const text = String(call?.content?.[0]?.text ?? '');
const parsed = text ? JSON.parse(text) : null;
assert.ok(parsed && Array.isArray(parsed.rows));
assert.ok(parsed.rows.length > 0);
}

{
const call = await client.callTool({ name: 'repo_map', arguments: { path: repoDir, max_files: 5, max_symbols: 2 } });
const text = String(call?.content?.[0]?.text ?? '');
Expand Down
Loading