Files
connectai/tests/turnIntentBrief.test.ts
T
koriweb c79eda1862 v2.2.313~319: 보고 품질·조사 신뢰성 수술 + 네이버 쇼핑인사이트/검색어트렌드 연동
- 파트별 완성, 웹 실접속 증빙, 턴 의도 브리핑, 본문 불일치 검증, 하위 질문
  체크리스트, 사이트 심층 수집 (PATCHNOTES.md v2.2.313~318 참조)
- /naver-shopping, /naver-trend: 네이버 데이터랩 API 연동. compare/discover
  자동 판별, API 배치 상한 캡슐화, 카테고리 트리 fuzzy 매칭, 자격증명은
  Astra 설정 패널 SecretStorage 로 관리
2026-08-05 18:20:32 +09:00

74 lines
3.5 KiB
TypeScript

/**
* [v2.2.316] 턴 의도 브리핑 — "질문 의도를 판단하지 못한다" 문제의 구조적 해결.
* 게이팅(잡담 제외) / JSON 파싱 내성 / 주입 블록의 근거-경로 강제를 검증.
*/
import {
shouldBuildTurnIntentBrief,
parseIntentBrief,
buildTurnIntentBrief,
formatTurnIntentBlock,
} from '../src/intelligence/turnIntentBrief';
describe('shouldBuildTurnIntentBrief — 게이팅', () => {
test('실질 요청형 턴은 대상', () => {
expect(shouldBuildTurnIntentBrief('E:\Wiki\connectai 프로젝트 분석하고 보고해줘', false)).toBe(true);
expect(shouldBuildTurnIntentBrief('HTTPS://KORITIPS.COM 사이트에 대한 분석 및 평가해줘', false)).toBe(true);
});
test('잡담·초단문·슬래시 명령은 제외', () => {
expect(shouldBuildTurnIntentBrief('잘 지내?', true)).toBe(false);
expect(shouldBuildTurnIntentBrief('응 고마워', false)).toBe(false);
expect(shouldBuildTurnIntentBrief('/wikify https://x.com 정리해줘', false)).toBe(false);
});
});
describe('parseIntentBrief — 파싱 내성', () => {
test('코드펜스·잡담 섞인 응답에서도 JSON 추출', () => {
const raw = '알겠습니다.\n```json\n{"purpose":"사이트 품질 평가","realQuestions":["구독자층"],"deliverable":"평가 보고","audience":"본인","accessPath":"web","constraints":""}\n```';
const b = parseIntentBrief(raw)!;
expect(b.purpose).toBe('사이트 품질 평가');
expect(b.accessPath).toBe('web');
});
test('purpose 없는 JSON / 비 JSON 은 null', () => {
expect(parseIntentBrief('{"realQuestions":[]}')).toBeNull();
expect(parseIntentBrief('그냥 텍스트')).toBeNull();
});
});
describe('buildTurnIntentBrief — 호출·타임아웃', () => {
test('정상 응답 → 브리핑 객체', async () => {
const b = await buildTurnIntentBrief({
prompt: '사이트 분석해줘',
llm: async () => '{"purpose":"P","realQuestions":["Q"],"deliverable":"D","audience":"A","accessPath":"web","constraints":""}',
});
expect(b?.purpose).toBe('P');
});
test('LLM 실패 → null (턴을 막지 않음)', async () => {
const b = await buildTurnIntentBrief({ prompt: 'x분석해줘', llm: async () => { throw new Error('down'); } });
expect(b).toBeNull();
});
test('타임아웃 → null', async () => {
const b = await buildTurnIntentBrief({
prompt: 'x분석해줘',
timeoutMs: 50,
llm: () => new Promise((res) => setTimeout(() => res('{}'), 500)),
});
expect(b).toBeNull();
});
});
describe('formatTurnIntentBlock — 근거 경로 강제', () => {
const base = { purpose: '사이트 평가', realQuestions: ['구독자층'], deliverable: '평가 보고', audience: '본인', constraints: '' };
test('web → 실데이터 근거 강제 + 일반론 금지', () => {
const blk = formatTurnIntentBlock({ ...base, accessPath: 'web' });
expect(blk).toContain('[질문자 의도 브리핑');
expect(blk).toContain('URL CONTENT');
expect(blk).toContain('일반 지식으로 사이트를 평하는 것은 금지');
});
test('local-files → 파일 정독 강제', () => {
expect(formatTurnIntentBlock({ ...base, accessPath: 'local-files' })).toContain('investigate_files');
});
test('null 브리핑 → 빈 문자열', () => {
expect(formatTurnIntentBlock(null)).toBe('');
});
});