pub fn needs_code_search(input: &str) -> bool {
let trimmed = input.trim();
if trimmed.chars().count() < 6 {
return false;
}
let lower = trimmed.to_lowercase();
if lower.starts_with('/') {
return false;
}
let skip_prefixes = [
"git ", "push", "pull", "commit", "merge", "rebase", "deploy", "release", "thank",
"thanks", "ok", "yes", "no", "ㄱㅅ", "고마", "좋아", "알겠", "네", "아니",
];
for prefix in &skip_prefixes {
if lower.starts_with(prefix) {
return false;
}
}
let code_signals = [
"error",
"bug",
"fix",
"implement",
"add",
"create",
"update",
"refactor",
"where",
"how",
"find",
"search",
"function",
"struct",
"class",
"method",
"module",
"file",
"test",
"why",
"what",
"change",
"modify",
"delete",
"remove",
"performance",
"optimize",
"slow",
"fast",
"import",
"에러",
"버그",
"수정",
"구현",
"추가",
"만들",
"변경",
"리팩",
"함수",
"파일",
"모듈",
"테스트",
"어디",
"왜",
];
for signal in &code_signals {
if lower.contains(signal) {
return true;
}
}
if trimmed.contains('/') || trimmed.contains("::") || trimmed.contains('_') {
return true;
}
trimmed.len() > 30
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum QueryIntent {
Code,
Docs,
Skip,
}
pub fn classify_query(input: &str) -> QueryIntent {
let trimmed = input.trim();
if trimmed.chars().count() < 6 || trimmed.starts_with('/') {
return QueryIntent::Skip;
}
let lower = trimmed.to_lowercase();
let skip_prefixes = [
"git ", "push", "pull", "commit", "merge", "rebase", "deploy", "release", "thank",
"thanks", "ok", "yes", "no", "ㄱㅅ", "고마", "좋아", "알겠", "네", "아니",
];
for prefix in &skip_prefixes {
if lower.starts_with(prefix) {
return QueryIntent::Skip;
}
}
let doc_signals = [
"readme",
"document",
"explain",
"architecture",
"design",
"convention",
"rule",
"guide",
"how does",
"how do",
"overview",
"summary",
"describe",
"설명",
"문서",
"아키텍",
"구조",
"설계",
"가이드",
];
for signal in &doc_signals {
if lower.contains(signal) {
return QueryIntent::Docs;
}
}
if needs_code_search(input) {
return QueryIntent::Code;
}
QueryIntent::Skip
}