// 텍스트 채널 질문 판정 휴리스틱. // 구조화 질문 도구(AskUserQuestion 등)가 없는 하네스에서 에이전트가 평문으로 // 사용자에게 되묻는지를 1차로 스크리닝한다. 원문은 항상 결과에 같이 남기고, // 최종 판정은 오케스트레이터가 원문을 직접 읽어 내린다(이 함수는 신호 수집용). const REQUEST_PHRASES = [ /알려\s*주세요/, /말씀해\s*주세요/, /선택해\s*주세요/, /답변해\s*주세요/, /알려\s*줄래/, /알려\s*줘/, /선택해\s*줘/, /여쭤/, /궁금합니다/, /어떤.{0,12}(원하시|하시나요|인가요|할까요|드릴까요)/, /어느.{0,12}(인가요|하시나요|할까요)/, /무엇.{0,12}(인가요|일까요)/, /확인.{0,6}(부탁|해주세요|해줘)/, ]; const NUMBERED_OPTION_LINE = /(^|\n)\s*(?:[0-9]{1,2}[.)]|[A-Ea-e][.)])\s+\S/; /** * @param {string} text 에이전트가 낸 텍스트 블록(들)을 합친 원문 * @returns {{isQuestion: boolean, questionMarks: number, optionLines: number, phraseHits: string[]}} */ export function scoreQuestionText(text) { const s = String(text || ""); const questionMarks = (s.match(/[??]/g) || []).length; const optionLineMatches = s.match(new RegExp(NUMBERED_OPTION_LINE, "gm")) || []; const optionLines = optionLineMatches.length; const phraseHits = REQUEST_PHRASES.filter((re) => re.test(s)).map((re) => re.source); // 질문으로 볼 신호: 물음표가 1개 이상 있거나, 요청형 한국어 어미가 있으면서 // 선택지 나열(번호/알파벳) 패턴이 함께 있으면 더 강한 신호로 취급한다. const hasQuestionMark = questionMarks >= 1; const hasRequestPhrase = phraseHits.length >= 1; const hasOptionList = optionLines >= 1; const isQuestion = hasQuestionMark || hasRequestPhrase || (hasOptionList && s.length < 4000); return { isQuestion, questionMarks, optionLines, phraseHits }; }