feat(core): 자기지식 접지·웹 접근·환경 자가점검 — 할루시네이션 방어 3중화 (v2.2.247)
- Alignment Self-Learning: 자가 조사(질문 전 두뇌 검색)·사용자 답변 두뇌 저장·핵심메시지/프로젝트 컨텍스트 주입 (alignmentResearch.ts 신규)
- 웹 접근: Bridge 폴백 직접 fetch(webFetch.ts 신규)·<fetch_url> 액션 태그·기업 모드 URL/아키텍처 컨텍스트 주입·bare 도메인 인식
- 트리거 버그 수정: startsWith('/') 가 절대경로를 슬래시 명령으로 오인 — 분석 지시·URL 주입 전멸 원인 (회귀 테스트 고정)
- 자기지식 접지: 기능 인벤토리 lazy 재생성·학습 메커니즘 정본 섹션·[인벤토리 대조] 태그 의무화·결정론적 재구현 제안 정정 훅(featureConceptMap.ts 신규)
- 환경 자가점검: HealthCheckMonitor 에 Bridge/두뇌 볼륨/git 자격증명/확장 버전 검사 4종 + readyBar ⚠ 표시
- 두뇌 동기화: 원격 미설정 시 로컬 새로고침 모드·staged 기준 commit 판정·인증 부재 안내
- 기타: outputFormat 기본 markdown(제목 렌더 복구)·레슨/행동제약 truncation 보호 구역 이동·[CONTEXT] 절단 우선순위 재정렬
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+92
-4
@@ -1,16 +1,33 @@
|
||||
import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { execSync } from 'child_process';
|
||||
import { getConfig } from '../config';
|
||||
import { logInfo, logWarn, logError } from '../utils';
|
||||
import { logInfo, logWarn, logError, getActiveBrainProfile } from '../utils';
|
||||
import { getBridgeBaseUrl } from '../features/datacollect/bridgeClient';
|
||||
|
||||
/**
|
||||
* HealthCheckMonitor: Periodically monitors the environment
|
||||
* HealthCheckMonitor: Periodically monitors the environment
|
||||
* (Ollama, Disk, API) to ensure the agent stays functional.
|
||||
*
|
||||
*
|
||||
* v2.2.245: 머신 로컬 전제 조건 4종 추가 — Bridge 응답·두뇌 볼륨 마운트·
|
||||
* git push 자격증명·Antigravity 확장 버전 정합. 한 세션에서 이 4가지가 전부
|
||||
* 사고로 터진 적이 있는데 (URL 분석 실패 / 인벤토리 미생성 / 동기화 실패 /
|
||||
* 구버전 실행), 전부 사후 디버깅으로만 발견됐다. 이제 readyBar ⚠️ 로 사전 가시화.
|
||||
*
|
||||
* Properly tracks the interval timer for cleanup on deactivation.
|
||||
*/
|
||||
export class HealthCheckMonitor {
|
||||
private static intervalHandle: ReturnType<typeof setInterval> | null = null;
|
||||
/** 마지막 검사 결과 — readyBar payload 가 읽어간다 (재검사 비용 없이). */
|
||||
private static _lastReports: string[] = [];
|
||||
/** 직전 토스트 내용 — 같은 경고를 10분마다 반복 토스트하지 않기 위한 dedupe. */
|
||||
private static _lastToastKey = '';
|
||||
|
||||
public static get lastReports(): string[] {
|
||||
return this._lastReports.slice();
|
||||
}
|
||||
|
||||
public static async runAllChecks(): Promise<{ ok: boolean; reports: string[] }> {
|
||||
const reports: string[] = [];
|
||||
@@ -46,9 +63,80 @@ export class HealthCheckMonitor {
|
||||
reports.push('Write permissions denied in the current workspace.');
|
||||
}
|
||||
|
||||
// 4. Datacollect Bridge 응답 — 어떤 HTTP 응답이든(404 포함) 살아 있는 것.
|
||||
// 네트워크 오류만 다운으로 판정. Bridge 다운이어도 URL 분석은 직접
|
||||
// fetch 폴백으로 동작하므로 경고는 영향 범위를 정확히 알린다.
|
||||
try {
|
||||
const bridgeUrl = getBridgeBaseUrl();
|
||||
if (bridgeUrl) {
|
||||
try {
|
||||
await fetch(bridgeUrl, { signal: AbortSignal.timeout(3000) });
|
||||
} catch {
|
||||
reports.push(`Datacollect Bridge(${bridgeUrl})가 응답하지 않습니다 — /wikify·/benchmark 와 고품질 URL 추출이 비활성 (URL 분석 자체는 직접 fetch 폴백으로 동작).`);
|
||||
}
|
||||
}
|
||||
} catch { /* config 읽기 실패 등 — 검사 자체를 조용히 skip */ }
|
||||
|
||||
// 5. 두뇌 볼륨/경로 — 외장 볼륨이 늦게 마운트되면 검색·레슨·인벤토리가
|
||||
// 조용히 비활성화되던 사고의 사전 감지.
|
||||
let brain: ReturnType<typeof getActiveBrainProfile> | undefined;
|
||||
try {
|
||||
brain = getActiveBrainProfile();
|
||||
if (brain?.localBrainPath && !fs.existsSync(brain.localBrainPath)) {
|
||||
reports.push(`두뇌 폴더가 없습니다 (외장 볼륨 미마운트?): ${brain.localBrainPath} — 검색·레슨·인벤토리가 비활성화됩니다.`);
|
||||
}
|
||||
} catch { /* profile 읽기 실패 — skip */ }
|
||||
|
||||
// 6. git push 자격증명 — 원격 동기화를 *설정한* 두뇌만 검사 (secondBrainRepo
|
||||
// 비어 있으면 두뇌 동기화가 로컬 새로고침 모드라 자격증명 불필요).
|
||||
try {
|
||||
if (brain?.secondBrainRepo?.trim() && brain.localBrainPath && fs.existsSync(brain.localBrainPath)) {
|
||||
try {
|
||||
execSync('git push --dry-run', {
|
||||
cwd: brain.localBrainPath,
|
||||
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
||||
timeout: 5000,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
});
|
||||
} catch (e: any) {
|
||||
const msg = String(e?.stderr || e?.message || '');
|
||||
if (/could not read Username|Authentication failed|terminal prompts disabled/i.test(msg)) {
|
||||
reports.push(`두뇌 원격 push 자격증명이 없습니다 — 터미널에서 "cd ${brain.localBrainPath} && git push" 1회 실행으로 키체인에 저장하세요.`);
|
||||
}
|
||||
// 그 외(오프라인·upstream 없음 등)는 소음 방지 — 보고하지 않음.
|
||||
}
|
||||
}
|
||||
} catch { /* skip */ }
|
||||
|
||||
// 7. Antigravity 확장 버전 정합 — VS Code 와 Antigravity 양쪽에 설치된
|
||||
// 경우 버전이 갈리면 "고쳤는데 안 고쳐짐" 혼란의 단골 원인 (실사례:
|
||||
// 2.2.19 vs 2.2.232 공존). Antigravity 미사용 머신에서는 자동 skip.
|
||||
try {
|
||||
const agExtRegistry = path.join(os.homedir(), '.antigravity', 'extensions', 'extensions.json');
|
||||
if (fs.existsSync(agExtRegistry)) {
|
||||
const arr = JSON.parse(fs.readFileSync(agExtRegistry, 'utf8'));
|
||||
const mine = Array.isArray(arr)
|
||||
? arr.find((e: any) => e?.identifier?.id === 'g1nation.astra')
|
||||
: null;
|
||||
const myVersion = vscode.extensions.getExtension('g1nation.astra')?.packageJSON?.version;
|
||||
if (mine?.version && myVersion && mine.version !== myVersion) {
|
||||
reports.push(`Antigravity 에 다른 버전의 Astra(${mine.version})가 설치되어 있습니다 — 현재 실행 중 ${myVersion}. Antigravity 쪽은 수동 업데이트가 필요합니다.`);
|
||||
}
|
||||
}
|
||||
} catch { /* registry 파싱 실패 — skip */ }
|
||||
|
||||
this._lastReports = reports;
|
||||
|
||||
if (reports.length > 0) {
|
||||
logWarn(`Health Check Warnings: ${reports.join(' | ')}`);
|
||||
vscode.window.showWarningMessage(`Astra Health Warning: ${reports[0]}`);
|
||||
// 동일 경고 반복 토스트 방지 — 내용이 바뀐 경우에만 1회 토스트.
|
||||
const toastKey = reports.join('|');
|
||||
if (toastKey !== this._lastToastKey) {
|
||||
this._lastToastKey = toastKey;
|
||||
vscode.window.showWarningMessage(`Astra Health Warning: ${reports[0]}${reports.length > 1 ? ` (외 ${reports.length - 1}건 — 준비 상태 바 참조)` : ''}`);
|
||||
}
|
||||
} else {
|
||||
this._lastToastKey = '';
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user