moai-adk 0.3.1__py3-none-any.whl → 0.3.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of moai-adk might be problematic. Click here for more details.
- moai_adk/__init__.py +1 -1
- {moai_adk-0.3.1.dist-info → moai_adk-0.3.2.dist-info}/METADATA +152 -147
- {moai_adk-0.3.1.dist-info → moai_adk-0.3.2.dist-info}/RECORD +6 -37
- moai_adk/templates/.claude/agents/alfred/cc-manager.md +0 -474
- moai_adk/templates/.claude/agents/alfred/code-builder.md +0 -534
- moai_adk/templates/.claude/agents/alfred/debug-helper.md +0 -302
- moai_adk/templates/.claude/agents/alfred/doc-syncer.md +0 -175
- moai_adk/templates/.claude/agents/alfred/git-manager.md +0 -200
- moai_adk/templates/.claude/agents/alfred/project-manager.md +0 -152
- moai_adk/templates/.claude/agents/alfred/spec-builder.md +0 -256
- moai_adk/templates/.claude/agents/alfred/tag-agent.md +0 -247
- moai_adk/templates/.claude/agents/alfred/trust-checker.md +0 -332
- moai_adk/templates/.claude/commands/alfred/0-project.md +0 -523
- moai_adk/templates/.claude/commands/alfred/1-spec.md +0 -531
- moai_adk/templates/.claude/commands/alfred/2-build.md +0 -413
- moai_adk/templates/.claude/commands/alfred/3-sync.md +0 -552
- moai_adk/templates/.claude/hooks/alfred/README.md +0 -238
- moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -165
- moai_adk/templates/.claude/hooks/alfred/core/__init__.py +0 -79
- moai_adk/templates/.claude/hooks/alfred/core/checkpoint.py +0 -271
- moai_adk/templates/.claude/hooks/alfred/core/context.py +0 -110
- moai_adk/templates/.claude/hooks/alfred/core/project.py +0 -284
- moai_adk/templates/.claude/hooks/alfred/core/tags.py +0 -244
- moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +0 -23
- moai_adk/templates/.claude/hooks/alfred/handlers/compact.py +0 -51
- moai_adk/templates/.claude/hooks/alfred/handlers/notification.py +0 -25
- moai_adk/templates/.claude/hooks/alfred/handlers/session.py +0 -80
- moai_adk/templates/.claude/hooks/alfred/handlers/tool.py +0 -71
- moai_adk/templates/.claude/hooks/alfred/handlers/user.py +0 -41
- moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -635
- moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -691
- moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -469
- moai_adk/templates/.claude/settings.json +0 -135
- moai_adk/templates/CLAUDE.md +0 -733
- {moai_adk-0.3.1.dist-info → moai_adk-0.3.2.dist-info}/WHEEL +0 -0
- {moai_adk-0.3.1.dist-info → moai_adk-0.3.2.dist-info}/entry_points.txt +0 -0
- {moai_adk-0.3.1.dist-info → moai_adk-0.3.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
# Alfred Hooks System
|
|
2
|
-
|
|
3
|
-
**Event-Driven Context Management for MoAI-ADK**
|
|
4
|
-
|
|
5
|
-
Alfred Hooks는 Claude Code의 이벤트 시스템과 통합되어 프로젝트 컨텍스트를 자동으로 관리하고, 위험한 작업 전에 checkpoint를 생성하며, JIT (Just-in-Time) 문서 로딩을 제공합니다.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 📐 Architecture
|
|
10
|
-
|
|
11
|
-
### Modular Design (9 Files, ≤284 LOC each)
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
.claude/hooks/alfred/
|
|
15
|
-
├── alfred_hooks.py # Main entry point (CLI router)
|
|
16
|
-
├── core/ # Core business logic
|
|
17
|
-
│ ├── __init__.py # Type definitions (HookPayload, HookResult)
|
|
18
|
-
│ ├── project.py # Language detection, Git info, SPEC counting
|
|
19
|
-
│ ├── context.py # JIT retrieval, workflow context
|
|
20
|
-
│ ├── checkpoint.py # Event-driven checkpoint creation
|
|
21
|
-
│ └── tags.py # TAG search, verification, caching
|
|
22
|
-
└── handlers/ # Event handlers
|
|
23
|
-
├── __init__.py # Handler exports
|
|
24
|
-
├── session.py # SessionStart, SessionEnd
|
|
25
|
-
├── user.py # UserPromptSubmit
|
|
26
|
-
├── compact.py # PreCompact
|
|
27
|
-
├── tool.py # PreToolUse, PostToolUse
|
|
28
|
-
└── notification.py # Notification, Stop, SubagentStop
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### Design Principles
|
|
32
|
-
|
|
33
|
-
- **Single Responsibility**: 각 모듈은 하나의 명확한 책임
|
|
34
|
-
- **Separation of Concerns**: core (비즈니스 로직) vs handlers (이벤트 처리)
|
|
35
|
-
- **CODE-FIRST**: 중간 캐시 없이 코드 직접 스캔 (mtime 기반 무효화)
|
|
36
|
-
- **Context Engineering**: JIT Retrieval로 초기 컨텍스트 부담 최소화
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## 🎯 Core Modules
|
|
41
|
-
|
|
42
|
-
### `core/project.py` (284 LOC)
|
|
43
|
-
|
|
44
|
-
**프로젝트 메타데이터 및 언어 감지**
|
|
45
|
-
|
|
46
|
-
```python
|
|
47
|
-
# Public API
|
|
48
|
-
detect_language(cwd: str) -> str
|
|
49
|
-
get_project_language(cwd: str) -> str
|
|
50
|
-
get_git_info(cwd: str) -> dict[str, Any]
|
|
51
|
-
count_specs(cwd: str) -> dict[str, int]
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
**Features**:
|
|
55
|
-
- 20개 언어 자동 감지 (Python, TypeScript, Java, Go, Rust, etc.)
|
|
56
|
-
- `.moai/config.json` 우선, fallback to auto-detection
|
|
57
|
-
- Git 정보 조회 (branch, commit, changes)
|
|
58
|
-
- SPEC 진행도 계산 (total, completed, percentage)
|
|
59
|
-
|
|
60
|
-
### `core/context.py` (110 LOC)
|
|
61
|
-
|
|
62
|
-
**JIT Context Retrieval 및 워크플로우 관리**
|
|
63
|
-
|
|
64
|
-
```python
|
|
65
|
-
# Public API
|
|
66
|
-
get_jit_context(prompt: str, cwd: str) -> list[str]
|
|
67
|
-
save_phase_context(phase: str, data: Any, ttl: int = 600)
|
|
68
|
-
load_phase_context(phase: str, ttl: int = 600) -> Any | None
|
|
69
|
-
clear_workflow_context()
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
**Features**:
|
|
73
|
-
- 프롬프트 분석 기반 문서 자동 추천
|
|
74
|
-
- `/alfred:1-spec` → `spec-metadata.md`
|
|
75
|
-
- `/alfred:2-build` → `development-guide.md`
|
|
76
|
-
- 워크플로우 단계별 컨텍스트 캐싱 (TTL 10분)
|
|
77
|
-
- Anthropic Context Engineering 원칙 준수
|
|
78
|
-
|
|
79
|
-
### `core/checkpoint.py` (244 LOC)
|
|
80
|
-
|
|
81
|
-
**Event-Driven Checkpoint 자동화**
|
|
82
|
-
|
|
83
|
-
```python
|
|
84
|
-
# Public API
|
|
85
|
-
detect_risky_operation(tool: str, args: dict, cwd: str) -> tuple[bool, str]
|
|
86
|
-
create_checkpoint(cwd: str, operation: str) -> str
|
|
87
|
-
log_checkpoint(cwd: str, branch: str, description: str)
|
|
88
|
-
list_checkpoints(cwd: str, max_count: int = 10) -> list[dict]
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
**Features**:
|
|
92
|
-
- 위험한 작업 자동 감지:
|
|
93
|
-
- Bash: `rm -rf`, `git merge`, `git reset --hard`
|
|
94
|
-
- Edit/Write: `CLAUDE.md`, `config.json`
|
|
95
|
-
- MultiEdit: ≥10 files
|
|
96
|
-
- Git checkpoint 자동 생성: `checkpoint/before-{operation}-{timestamp}`
|
|
97
|
-
- checkpoint 이력 관리 및 복구 가이드
|
|
98
|
-
|
|
99
|
-
### `core/tags.py` (244 LOC)
|
|
100
|
-
|
|
101
|
-
**CODE-FIRST TAG 시스템**
|
|
102
|
-
|
|
103
|
-
```python
|
|
104
|
-
# Public API
|
|
105
|
-
search_tags(pattern: str, scope: list[str], cache_ttl: int = 60) -> list[dict]
|
|
106
|
-
verify_tag_chain(tag_id: str) -> dict[str, Any]
|
|
107
|
-
find_all_tags_by_type(tag_type: str) -> dict[str, list[str]]
|
|
108
|
-
suggest_tag_reuse(keyword: str) -> list[str]
|
|
109
|
-
get_library_version(library: str, cache_ttl: int = 86400) -> str | None
|
|
110
|
-
set_library_version(library: str, version: str)
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
**Features**:
|
|
114
|
-
- ripgrep 기반 TAG 검색 (JSON 출력 파싱)
|
|
115
|
-
- mtime 기반 캐시 무효화 (CODE-FIRST 보장)
|
|
116
|
-
- TAG 체인 검증 (@SPEC → @TEST → @CODE 완전성 확인)
|
|
117
|
-
- 라이브러리 버전 캐싱 (TTL 24시간)
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## 🎬 Event Handlers
|
|
122
|
-
|
|
123
|
-
### `handlers/session.py`
|
|
124
|
-
|
|
125
|
-
**SessionStart, SessionEnd 핸들러**
|
|
126
|
-
|
|
127
|
-
- **SessionStart**: 프로젝트 정보 표시
|
|
128
|
-
- 언어, Git 상태, SPEC 진행도, 최근 checkpoint
|
|
129
|
-
- `systemMessage` 필드로 사용자에게 직접 표시
|
|
130
|
-
- **SessionEnd**: 정리 작업 (stub)
|
|
131
|
-
|
|
132
|
-
### `handlers/user.py`
|
|
133
|
-
|
|
134
|
-
**UserPromptSubmit 핸들러**
|
|
135
|
-
|
|
136
|
-
- JIT Context 추천 문서 리스트 반환
|
|
137
|
-
- 사용자 프롬프트 패턴 분석 및 관련 문서 로드
|
|
138
|
-
|
|
139
|
-
### `handlers/compact.py`
|
|
140
|
-
|
|
141
|
-
**PreCompact 핸들러**
|
|
142
|
-
|
|
143
|
-
- 세션 요약 트리거 (>70% 토큰 사용)
|
|
144
|
-
- Compaction 권장 메시지 생성
|
|
145
|
-
|
|
146
|
-
### `handlers/tool.py`
|
|
147
|
-
|
|
148
|
-
**PreToolUse, PostToolUse 핸들러**
|
|
149
|
-
|
|
150
|
-
- **PreToolUse**: 위험한 작업 감지 시 자동 checkpoint 생성
|
|
151
|
-
- **PostToolUse**: 후처리 작업 (stub)
|
|
152
|
-
|
|
153
|
-
### `handlers/notification.py`
|
|
154
|
-
|
|
155
|
-
**Notification, Stop, SubagentStop 핸들러**
|
|
156
|
-
|
|
157
|
-
- 기본 구현 (stub, 향후 확장 가능)
|
|
158
|
-
|
|
159
|
-
---
|
|
160
|
-
|
|
161
|
-
## 🧪 Testing
|
|
162
|
-
|
|
163
|
-
### Test Suite
|
|
164
|
-
|
|
165
|
-
```bash
|
|
166
|
-
# Run all tests
|
|
167
|
-
uv run pytest tests/unit/test_alfred_hooks_*.py -v --no-cov
|
|
168
|
-
|
|
169
|
-
# Run specific module tests
|
|
170
|
-
uv run pytest tests/unit/test_alfred_hooks_core_tags.py -v
|
|
171
|
-
uv run pytest tests/unit/test_alfred_hooks_core_context.py -v
|
|
172
|
-
uv run pytest tests/unit/test_alfred_hooks_core_project.py -v
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### Test Coverage (18 tests)
|
|
176
|
-
|
|
177
|
-
- ✅ **tags.py**: 7 tests (캐시, TAG 검증, 버전 관리)
|
|
178
|
-
- ✅ **context.py**: 5 tests (JIT, 워크플로우 컨텍스트)
|
|
179
|
-
- ✅ **project.py**: 6 tests (언어 감지, Git, SPEC 카운트)
|
|
180
|
-
|
|
181
|
-
### Test Structure
|
|
182
|
-
|
|
183
|
-
```python
|
|
184
|
-
# Dynamic module loading for isolated testing
|
|
185
|
-
def _load_{module}_module(module_name: str):
|
|
186
|
-
repo_root = Path(__file__).resolve().parents[2]
|
|
187
|
-
hooks_dir = repo_root / ".claude" / "hooks" / "alfred"
|
|
188
|
-
sys.path.insert(0, str(hooks_dir))
|
|
189
|
-
|
|
190
|
-
module_path = hooks_dir / "core" / "{module}.py"
|
|
191
|
-
spec = importlib.util.spec_from_file_location(module_name, module_path)
|
|
192
|
-
# ...
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
## 🔄 Migration from moai_hooks.py
|
|
198
|
-
|
|
199
|
-
### Before (Monolithic)
|
|
200
|
-
|
|
201
|
-
- **1 file**: 1233 LOC
|
|
202
|
-
- **Issues**:
|
|
203
|
-
- 모든 기능이 하나의 파일에 집중
|
|
204
|
-
- 테스트 어려움, 유지보수 복잡
|
|
205
|
-
- 책임 분리 불명확
|
|
206
|
-
|
|
207
|
-
### After (Modular)
|
|
208
|
-
|
|
209
|
-
- **9 files**: ≤284 LOC each
|
|
210
|
-
- **Benefits**:
|
|
211
|
-
- 명확한 책임 분리 (SRP)
|
|
212
|
-
- 독립적인 모듈 테스트 가능
|
|
213
|
-
- 확장 용이, 유지보수 간편
|
|
214
|
-
- Context Engineering 원칙 준수
|
|
215
|
-
|
|
216
|
-
### Breaking Changes
|
|
217
|
-
|
|
218
|
-
**없음** - 외부 API는 동일하게 유지됩니다.
|
|
219
|
-
|
|
220
|
-
---
|
|
221
|
-
|
|
222
|
-
## 📚 References
|
|
223
|
-
|
|
224
|
-
### Internal Documents
|
|
225
|
-
|
|
226
|
-
- **CLAUDE.md**: MoAI-ADK 사용자 가이드
|
|
227
|
-
- **.moai/memory/development-guide.md**: SPEC-First TDD 워크플로우
|
|
228
|
-
- **.moai/memory/spec-metadata.md**: SPEC 메타데이터 표준
|
|
229
|
-
|
|
230
|
-
### External Resources
|
|
231
|
-
|
|
232
|
-
- [Claude Code Hooks Documentation](https://docs.claude.com/en/docs/claude-code)
|
|
233
|
-
- [Anthropic Context Engineering](https://docs.anthropic.com/claude/docs/context-engineering)
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
**Last Updated**: 2025-10-16
|
|
238
|
-
**Author**: @Alfred (MoAI-ADK SuperAgent)
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# @CODE:HOOKS-REFACTOR-001 | SPEC: SPEC-HOOKS-REFACTOR-001.md
|
|
3
|
-
"""Alfred Hooks - Main entry point for MoAI-ADK Claude Code Hooks
|
|
4
|
-
|
|
5
|
-
Claude Code 이벤트를 적절한 핸들러로 라우팅하는 메인 진입점
|
|
6
|
-
|
|
7
|
-
Setup sys.path for package imports
|
|
8
|
-
"""
|
|
9
|
-
import sys
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
|
|
12
|
-
# Add the hooks directory to sys.path to enable package imports
|
|
13
|
-
HOOKS_DIR = Path(__file__).parent
|
|
14
|
-
if str(HOOKS_DIR) not in sys.path:
|
|
15
|
-
sys.path.insert(0, str(HOOKS_DIR))
|
|
16
|
-
|
|
17
|
-
# Now we can import from the package
|
|
18
|
-
|
|
19
|
-
"""
|
|
20
|
-
Architecture:
|
|
21
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
22
|
-
│ alfred_hooks.py (Router) │
|
|
23
|
-
├─────────────────────────────────────────────────────────────┤
|
|
24
|
-
│ - CLI argument parsing │
|
|
25
|
-
│ - JSON I/O (stdin/stdout) │
|
|
26
|
-
│ - Event routing to handlers │
|
|
27
|
-
└─────────────────────────────────────────────────────────────┘
|
|
28
|
-
▼
|
|
29
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
30
|
-
│ handlers/ (Event Handlers) │
|
|
31
|
-
├─────────────────────────────────────────────────────────────┤
|
|
32
|
-
│ - session.py: SessionStart, SessionEnd │
|
|
33
|
-
│ - user.py: UserPromptSubmit │
|
|
34
|
-
│ - compact.py: PreCompact │
|
|
35
|
-
│ - tool.py: PreToolUse, PostToolUse │
|
|
36
|
-
│ - notification.py: Notification, Stop, SubagentStop │
|
|
37
|
-
└─────────────────────────────────────────────────────────────┘
|
|
38
|
-
▼
|
|
39
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
40
|
-
│ core/ (Business Logic) │
|
|
41
|
-
├─────────────────────────────────────────────────────────────┤
|
|
42
|
-
│ - project.py: Language detection, Git info, SPEC progress │
|
|
43
|
-
│ - context.py: JIT Retrieval, workflow context │
|
|
44
|
-
│ - checkpoint.py: Event-Driven Checkpoint system │
|
|
45
|
-
│ - tags.py: TAG search/verification, library version cache │
|
|
46
|
-
└─────────────────────────────────────────────────────────────┘
|
|
47
|
-
|
|
48
|
-
Usage:
|
|
49
|
-
python alfred_hooks.py <event_name> < payload.json
|
|
50
|
-
|
|
51
|
-
Supported Events:
|
|
52
|
-
- SessionStart: 세션 시작 (프로젝트 상태 표시)
|
|
53
|
-
- UserPromptSubmit: 프롬프트 제출 (JIT 문서 로딩)
|
|
54
|
-
- PreCompact: 컨텍스트 초과 경고 (새 세션 제안)
|
|
55
|
-
- PreToolUse: Tool 사용 전 (Checkpoint 자동 생성)
|
|
56
|
-
- SessionEnd, PostToolUse, Notification, Stop, SubagentStop
|
|
57
|
-
|
|
58
|
-
Exit Codes:
|
|
59
|
-
- 0: 성공
|
|
60
|
-
- 1: 에러 (인수 없음, JSON 파싱 실패, 예외 발생)
|
|
61
|
-
|
|
62
|
-
TDD History:
|
|
63
|
-
- RED: 모듈 분리 설계, 이벤트 라우팅 테스트
|
|
64
|
-
- GREEN: 1233 LOC → 9개 모듈 분리 구현 (SRP 준수)
|
|
65
|
-
- REFACTOR: Import 최적화, 에러 처리 강화
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
import json
|
|
69
|
-
|
|
70
|
-
from core import HookResult
|
|
71
|
-
from handlers import (
|
|
72
|
-
handle_notification,
|
|
73
|
-
handle_post_tool_use,
|
|
74
|
-
handle_pre_compact,
|
|
75
|
-
handle_pre_tool_use,
|
|
76
|
-
handle_session_end,
|
|
77
|
-
handle_session_start,
|
|
78
|
-
handle_stop,
|
|
79
|
-
handle_subagent_stop,
|
|
80
|
-
handle_user_prompt_submit,
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def main() -> None:
|
|
85
|
-
"""메인 진입점 - Claude Code Hook 스크립트
|
|
86
|
-
|
|
87
|
-
CLI 인수로 이벤트명을 받고, stdin으로 JSON 페이로드를 읽습니다.
|
|
88
|
-
이벤트에 맞는 핸들러를 호출하고, 결과를 JSON으로 stdout에 출력합니다.
|
|
89
|
-
|
|
90
|
-
Usage:
|
|
91
|
-
python alfred_hooks.py <event_name> < payload.json
|
|
92
|
-
|
|
93
|
-
Supported Events:
|
|
94
|
-
- SessionStart: 세션 시작 (프로젝트 상태 표시)
|
|
95
|
-
- UserPromptSubmit: 프롬프트 제출 (JIT 문서 로딩)
|
|
96
|
-
- PreCompact: 컨텍스트 초과 경고 (새 세션 제안)
|
|
97
|
-
- SessionEnd, PreToolUse, PostToolUse, Notification, Stop, SubagentStop
|
|
98
|
-
|
|
99
|
-
Exit Codes:
|
|
100
|
-
- 0: 성공
|
|
101
|
-
- 1: 에러 (인수 없음, JSON 파싱 실패, 예외 발생)
|
|
102
|
-
|
|
103
|
-
Examples:
|
|
104
|
-
$ echo '{"cwd": "."}' | python alfred_hooks.py SessionStart
|
|
105
|
-
{"message": "🚀 MoAI-ADK Session Started\\n...", ...}
|
|
106
|
-
|
|
107
|
-
Notes:
|
|
108
|
-
- Claude Code가 자동으로 호출 (사용자 직접 실행 불필요)
|
|
109
|
-
- stdin/stdout으로 JSON I/O 처리
|
|
110
|
-
- stderr로 에러 메시지 출력
|
|
111
|
-
- UserPromptSubmit은 특별한 출력 스키마 사용 (hookEventName + additionalContext)
|
|
112
|
-
|
|
113
|
-
TDD History:
|
|
114
|
-
- RED: 이벤트 라우팅, JSON I/O, 에러 처리 테스트
|
|
115
|
-
- GREEN: 핸들러 맵 기반 라우팅 구현
|
|
116
|
-
- REFACTOR: 에러 메시지 명확화, exit code 표준화, UserPromptSubmit 스키마 분리
|
|
117
|
-
"""
|
|
118
|
-
# Check for event argument
|
|
119
|
-
if len(sys.argv) < 2:
|
|
120
|
-
print("Usage: alfred_hooks.py <event>", file=sys.stderr)
|
|
121
|
-
sys.exit(1)
|
|
122
|
-
|
|
123
|
-
event_name = sys.argv[1]
|
|
124
|
-
|
|
125
|
-
try:
|
|
126
|
-
# Read JSON from stdin
|
|
127
|
-
input_data = sys.stdin.read()
|
|
128
|
-
data = json.loads(input_data)
|
|
129
|
-
|
|
130
|
-
cwd = data.get("cwd", ".")
|
|
131
|
-
|
|
132
|
-
# Route to appropriate handler
|
|
133
|
-
handlers = {
|
|
134
|
-
"SessionStart": handle_session_start,
|
|
135
|
-
"UserPromptSubmit": handle_user_prompt_submit,
|
|
136
|
-
"PreCompact": handle_pre_compact,
|
|
137
|
-
"SessionEnd": handle_session_end,
|
|
138
|
-
"PreToolUse": handle_pre_tool_use,
|
|
139
|
-
"PostToolUse": handle_post_tool_use,
|
|
140
|
-
"Notification": handle_notification,
|
|
141
|
-
"Stop": handle_stop,
|
|
142
|
-
"SubagentStop": handle_subagent_stop,
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
handler = handlers.get(event_name)
|
|
146
|
-
result = handler({"cwd": cwd, **data}) if handler else HookResult()
|
|
147
|
-
|
|
148
|
-
# UserPromptSubmit은 특별한 출력 스키마 사용
|
|
149
|
-
if event_name == "UserPromptSubmit":
|
|
150
|
-
print(json.dumps(result.to_user_prompt_submit_dict()))
|
|
151
|
-
else:
|
|
152
|
-
print(json.dumps(result.to_dict()))
|
|
153
|
-
|
|
154
|
-
sys.exit(0)
|
|
155
|
-
|
|
156
|
-
except json.JSONDecodeError as e:
|
|
157
|
-
print(f"JSON parse error: {e}", file=sys.stderr)
|
|
158
|
-
sys.exit(1)
|
|
159
|
-
except Exception as e:
|
|
160
|
-
print(f"Unexpected error: {e}", file=sys.stderr)
|
|
161
|
-
sys.exit(1)
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if __name__ == "__main__":
|
|
165
|
-
main()
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Core module for Alfred Hooks
|
|
3
|
-
|
|
4
|
-
공통 타입 정의 및 유틸리티 함수
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from dataclasses import asdict, dataclass, field
|
|
8
|
-
from typing import Any, NotRequired, TypedDict
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class HookPayload(TypedDict):
|
|
12
|
-
"""Claude Code Hook 이벤트 페이로드 타입 정의
|
|
13
|
-
|
|
14
|
-
Claude Code가 Hook 스크립트에 전달하는 데이터 구조.
|
|
15
|
-
이벤트에 따라 필드가 다를 수 있으므로 NotRequired 사용.
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
cwd: str
|
|
19
|
-
userPrompt: NotRequired[str] # UserPromptSubmit 이벤트만 포함
|
|
20
|
-
tool: NotRequired[str] # PreToolUse/PostToolUse 이벤트
|
|
21
|
-
arguments: NotRequired[dict[str, Any]] # Tool arguments
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@dataclass
|
|
25
|
-
class HookResult:
|
|
26
|
-
"""Hook 실행 결과"""
|
|
27
|
-
|
|
28
|
-
message: str | None = None
|
|
29
|
-
systemMessage: str | None = None # 사용자에게 직접 표시되는 메시지
|
|
30
|
-
blocked: bool = False
|
|
31
|
-
contextFiles: list[str] = field(default_factory=list)
|
|
32
|
-
suggestions: list[str] = field(default_factory=list)
|
|
33
|
-
exitCode: int = 0
|
|
34
|
-
|
|
35
|
-
def to_dict(self) -> dict[str, Any]:
|
|
36
|
-
"""일반 Hook용 딕셔너리 변환"""
|
|
37
|
-
return asdict(self)
|
|
38
|
-
|
|
39
|
-
def to_user_prompt_submit_dict(self) -> dict[str, Any]:
|
|
40
|
-
"""UserPromptSubmit Hook 전용 출력 형식
|
|
41
|
-
|
|
42
|
-
Claude Code는 UserPromptSubmit에 대해 특별한 스키마를 요구:
|
|
43
|
-
{
|
|
44
|
-
"hookEventName": "UserPromptSubmit",
|
|
45
|
-
"additionalContext": "string (required)"
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
Returns:
|
|
49
|
-
Claude Code UserPromptSubmit Hook 스키마에 맞는 딕셔너리
|
|
50
|
-
|
|
51
|
-
Examples:
|
|
52
|
-
>>> result = HookResult(contextFiles=["tests/"])
|
|
53
|
-
>>> result.to_user_prompt_submit_dict()
|
|
54
|
-
{'hookEventName': 'UserPromptSubmit', 'additionalContext': '📎 Context: tests/'}
|
|
55
|
-
"""
|
|
56
|
-
# contextFiles를 additionalContext 문자열로 변환
|
|
57
|
-
if self.contextFiles:
|
|
58
|
-
context_str = "\n".join([f"📎 Context: {f}" for f in self.contextFiles])
|
|
59
|
-
else:
|
|
60
|
-
context_str = ""
|
|
61
|
-
|
|
62
|
-
# message가 있으면 추가
|
|
63
|
-
if self.message:
|
|
64
|
-
if context_str:
|
|
65
|
-
context_str = f"{self.message}\n\n{context_str}"
|
|
66
|
-
else:
|
|
67
|
-
context_str = self.message
|
|
68
|
-
|
|
69
|
-
# 빈 문자열이면 기본값 사용
|
|
70
|
-
if not context_str:
|
|
71
|
-
context_str = ""
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
"hookEventName": "UserPromptSubmit",
|
|
75
|
-
"additionalContext": context_str
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
__all__ = ["HookPayload", "HookResult"]
|