Update code

This commit is contained in:
User
2026-03-12 12:47:56 +08:00
parent 92e7fc5bda
commit 9dab61345c
9383 changed files with 1463454 additions and 1 deletions

View File

@@ -0,0 +1,176 @@
import { exec } from "child_process";
import { promisify } from "util";
import { readdirSync, readFileSync, statSync } from "fs";
import { join, extname, relative } from "path";
const execAsync = promisify(exec);
export const searchCodeTool = {
name: "search_code",
description: "在项目中搜索代码。支持正则表达式、文本搜索、文件名搜索。返回匹配的文件、行号和上下文。类似 grep/ripgrep。",
inputSchema: {
type: "object",
properties: {
project_path: {
type: "string",
description: "项目根目录(绝对路径)",
},
query: {
type: "string",
description: "搜索内容(支持正则表达式)",
},
mode: {
type: "string",
description: "搜索模式content=代码内容默认、filename=文件名、symbol=函数/类名",
enum: ["content", "filename", "symbol"],
},
includes: {
type: "string",
description: "文件过滤 glob如 *.ts, *.py",
},
case_sensitive: {
type: "boolean",
description: "是否区分大小写(默认 false",
},
max_results: {
type: "number",
description: "最大结果数(默认 50",
},
},
required: ["project_path", "query"],
},
};
const SKIP_DIRS = new Set([
"node_modules", ".git", "__pycache__", "dist", "build", ".next",
".nuxt", "coverage", ".cache", ".tsbuildinfo", "vendor",
]);
const TEXT_EXTS = new Set([
".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs", ".c", ".cpp", ".h",
".css", ".scss", ".less", ".html", ".vue", ".svelte", ".json", ".yaml", ".yml",
".toml", ".md", ".txt", ".sh", ".bat", ".ps1", ".sql", ".graphql", ".prisma",
".env", ".gitignore", ".eslintrc", ".prettierrc",
]);
function searchInDir(dir, rootDir, regex, mode, includeExt, results, maxResults, depth = 0) {
if (depth > 10 || results.length >= maxResults)
return;
try {
const entries = readdirSync(dir);
for (const entry of entries) {
if (results.length >= maxResults)
break;
if (SKIP_DIRS.has(entry) || entry.startsWith("."))
continue;
const fullPath = join(dir, entry);
try {
const stat = statSync(fullPath);
if (stat.isDirectory()) {
searchInDir(fullPath, rootDir, regex, mode, includeExt, results, maxResults, depth + 1);
}
else if (stat.isFile()) {
const ext = extname(entry).toLowerCase();
// 文件名搜索
if (mode === "filename") {
if (regex.test(entry)) {
results.push({ file: relative(rootDir, fullPath), line: 0, content: entry });
}
continue;
}
// 内容搜索 - 只搜索文本文件
if (!TEXT_EXTS.has(ext) && ext !== "")
continue;
if (includeExt && !entry.endsWith(includeExt.replace("*", "")))
continue;
if (stat.size > 1024 * 512)
continue; // 跳过 >512KB 的文件
const content = readFileSync(fullPath, "utf-8");
const lines = content.split("\n");
for (let i = 0; i < lines.length; i++) {
if (results.length >= maxResults)
break;
if (mode === "symbol") {
// 只匹配函数/类/接口定义
const line = lines[i];
if (/(?:function|class|interface|def|const|let|var|export)\s/.test(line) && regex.test(line)) {
results.push({
file: relative(rootDir, fullPath),
line: i + 1,
content: line.trim(),
context_before: i > 0 ? lines[i - 1].trim() : undefined,
context_after: i < lines.length - 1 ? lines[i + 1].trim() : undefined,
});
}
}
else {
if (regex.test(lines[i])) {
results.push({
file: relative(rootDir, fullPath),
line: i + 1,
content: lines[i].trim(),
context_before: i > 0 ? lines[i - 1].trim() : undefined,
context_after: i < lines.length - 1 ? lines[i + 1].trim() : undefined,
});
}
}
}
}
}
catch { }
}
}
catch { }
}
export async function executeSearchCode(args) {
const { project_path, query, mode = "content", includes, case_sensitive = false, max_results = 50 } = args;
const flags = case_sensitive ? "" : "i";
let regex;
try {
regex = new RegExp(query, flags);
}
catch {
regex = new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), flags);
}
const results = [];
const includeExt = includes ? includes.replace("*", "") : null;
searchInDir(project_path, project_path, regex, mode, includeExt, results, max_results);
if (results.length === 0) {
return `# 搜索结果\n\n🔍 "${query}" (${mode})\n📂 ${project_path}\n\n_未找到匹配结果_`;
}
// 按文件分组
const grouped = {};
for (const r of results) {
(grouped[r.file] || (grouped[r.file] = [])).push(r);
}
const fileCount = Object.keys(grouped).length;
const output = [
`# 搜索结果`,
``,
`🔍 "${query}" | 模式: ${mode}${includes ? ` | 过滤: ${includes}` : ""}`,
`📂 ${project_path}`,
`📊 ${results.length} 个匹配,${fileCount} 个文件`,
``,
];
for (const [file, matches] of Object.entries(grouped)) {
output.push(`## 📄 ${file} (${matches.length} 处)`);
for (const m of matches) {
if (mode === "filename") {
output.push(`- ${m.content}`);
}
else {
output.push(`**行 ${m.line}:**`);
if (m.context_before)
output.push(`\`\`\`\n ${m.context_before}`);
else
output.push("```");
output.push(`${m.content}`);
if (m.context_after)
output.push(` ${m.context_after}\n\`\`\``);
else
output.push("```");
}
}
output.push(``);
}
if (results.length >= max_results) {
output.push(`\n⚠️ 结果已截断(最大 ${max_results} 条),可增大 max_results 或缩小搜索范围`);
}
return output.join("\n");
}
//# sourceMappingURL=searchCode.js.map