v2.2.313~319: 보고 품질·조사 신뢰성 수술 + 네이버 쇼핑인사이트/검색어트렌드 연동
- 파트별 완성, 웹 실접속 증빙, 턴 의도 브리핑, 본문 불일치 검증, 하위 질문 체크리스트, 사이트 심층 수집 (PATCHNOTES.md v2.2.313~318 참조) - /naver-shopping, /naver-trend: 네이버 데이터랩 API 연동. compare/discover 자동 판별, API 배치 상한 캡슐화, 카테고리 트리 fuzzy 매칭, 자격증명은 Astra 설정 패널 SecretStorage 로 관리
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* [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('');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user