[Phase 17-C] 훅 시스템 고도화 — 11종 이벤트 연결 + Prompt 모드 구현
AppSettings.AgentConfig.cs:
- ExtendedHooksConfig에 4개 이벤트 추가:
preToolUse, postToolUse, postToolUseFailure, agentStop
AgentLoopService.ExtendedHooks.cs (신규, 150줄):
- RunExtendedEventAsync(): 이벤트 훅 실행, 결과(additionalContext) 시스템 메시지 주입, HookFired 이벤트 로그
- GetExtendedHooks(): 설정에서 HookEventKind별 런타임 엔트리 조회
- ConvertToRuntimeEntries(): ExtendedHookEntryConfig → ExtendedHookEntry 변환
- ApplyExtendedHookResult(): additionalContext in-place 주입 (marker 기반 교체)
ExtendedHookRunner.cs:
- RunEventAsync() / ExecuteSingleAsync()에 LlmService? llm 파라미터 추가
- RunPromptHookAsync() 신규: {{tool_name/input/output/user_message/event/session_id}} 치환
→ LLM 호출 → block/deny/차단 감지 시 Block=true 반환
- using AxCopilot.Models 추가
AgentLoopService.cs:
- SessionStart 훅 (fire-and-forget, TaskState init 직후)
- UserPromptSubmit 훅 (동기, Block=true 시 즉시 반환 "⚠ 훅 정책에 의해 차단")
- PreCompact 훅 (적극적 압축 직전, 동기)
- PostCompact 훅 × 2 (기본/적극적 압축 완료 후, fire-and-forget)
- SessionEnd + AgentStop 훅 (finally 블록, fire-and-forget)
AgentLoopService.Execution.cs:
- RunToolHooksAsync() 개선: 레거시 AgentHookRunner 유지
+ ExtendedHookRunner PreToolUse/PostToolUse/PostToolUseFailure 추가
이벤트 커버리지: 11종 완전 연결. Agent 모드는 Phase 18-A 예정.
빌드: 경고 0, 오류 0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -176,6 +176,23 @@ public partial class AgentLoopService
|
||||
_ = _eventLog?.AppendAsync(AgentEventLogType.UserMessage,
|
||||
JsonSerializer.Serialize(new { length = userQuery.Length }));
|
||||
await InitTaskStateAsync(userQuery, _sessionId);
|
||||
|
||||
// Phase 17-C: SessionStart 훅 실행 (fire-and-forget)
|
||||
_ = RunExtendedEventAsync(HookEventKind.SessionStart, messages, CancellationToken.None,
|
||||
userMessage: userQuery);
|
||||
|
||||
// Phase 17-C: UserPromptSubmit 훅 실행 — 차단 시 즉시 종료
|
||||
if (!string.IsNullOrWhiteSpace(userQuery))
|
||||
{
|
||||
var promptBlocked = await RunExtendedEventAsync(
|
||||
HookEventKind.UserPromptSubmit, messages, ct, userMessage: userQuery);
|
||||
if (promptBlocked)
|
||||
{
|
||||
EmitEvent(AgentEventType.Complete, "", "훅 정책에 의해 요청이 차단되었습니다");
|
||||
return "⚠ 요청이 훅 정책에 의해 차단되었습니다.";
|
||||
}
|
||||
}
|
||||
|
||||
var consecutiveErrors = 0; // Self-Reflection: 연속 오류 카운터
|
||||
var totalToolCalls = 0; // 복잡도 추정용
|
||||
|
||||
@@ -357,6 +374,8 @@ public partial class AgentLoopService
|
||||
_ = _eventLog?.AppendAsync(AgentEventLogType.CompactionCompleted,
|
||||
JsonSerializer.Serialize(new { messageCount = messages.Count }));
|
||||
UpdateTaskStateSummaryAsync("컨텍스트 압축 완료");
|
||||
// Phase 17-C: PostCompact 훅 (fire-and-forget)
|
||||
_ = RunExtendedEventAsync(HookEventKind.PostCompact, messages, CancellationToken.None);
|
||||
}
|
||||
|
||||
// 임계치 기반 적극적 압축 (이전 LLM 호출의 토큰 사용량 기준)
|
||||
@@ -374,6 +393,8 @@ public partial class AgentLoopService
|
||||
$"⚠ 컨텍스트 사용량 {usagePct}% — 적극적 컴팩션 실행");
|
||||
_ = _eventLog?.AppendAsync(AgentEventLogType.CompactionTriggered,
|
||||
JsonSerializer.Serialize(new { aggressive = true, usagePct }));
|
||||
// Phase 17-C: PreCompact 훅 — 적극적 압축 직전 (압축 발생 확실)
|
||||
await RunExtendedEventAsync(HookEventKind.PreCompact, messages, ct);
|
||||
var targetTokens = (int)(llm.MaxContextTokens * Defaults.ContextCompressionTargetRatio);
|
||||
var compacted = await ContextCondenser.CondenseIfNeededAsync(
|
||||
messages, _llm, targetTokens, ct);
|
||||
@@ -383,6 +404,8 @@ public partial class AgentLoopService
|
||||
_ = _eventLog?.AppendAsync(AgentEventLogType.CompactionCompleted,
|
||||
JsonSerializer.Serialize(new { aggressive = true, messageCount = messages.Count }));
|
||||
UpdateTaskStateSummaryAsync($"적극적 컴팩션 완료 (이전 컨텍스트 사용량 {usagePct}%)");
|
||||
// Phase 17-C: PostCompact 훅 (fire-and-forget)
|
||||
_ = RunExtendedEventAsync(HookEventKind.PostCompact, messages, CancellationToken.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -778,6 +801,10 @@ public partial class AgentLoopService
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Phase 17-C: SessionEnd + AgentStop 확장 훅 실행 (fire-and-forget)
|
||||
_ = RunExtendedEventAsync(HookEventKind.SessionEnd, null, CancellationToken.None, userMessage: userQuery);
|
||||
_ = RunExtendedEventAsync(HookEventKind.AgentStop, null, CancellationToken.None, userMessage: userQuery);
|
||||
|
||||
// 세션 종료 이벤트 기록
|
||||
if (_eventLog != null)
|
||||
_ = _eventLog.AppendAsync(AgentEventLogType.SessionEnd,
|
||||
|
||||
Reference in New Issue
Block a user