claude-memory-layer 1.0.16 → 1.0.18
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.
- package/dist/cli/index.js +52 -34
- package/dist/cli/index.js.map +2 -2
- package/dist/hooks/session-start.js +23 -13
- package/dist/hooks/session-start.js.map +2 -2
- package/memory/_index.md +2 -0
- package/memory/agent_response/uncategorized/2026-02-26.md +176 -0
- package/memory/session_summary/uncategorized/2026-02-26.md +13 -0
- package/memory/tool_observation/uncategorized/2026-02-26.md +9 -1
- package/memory/user_prompt/uncategorized/2026-02-26.md +16 -1
- package/package.json +1 -1
- package/src/cli/index.ts +55 -33
- package/src/hooks/session-start.ts +9 -3
package/memory/_index.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Generated automatically by MarkdownMirror.
|
|
4
4
|
|
|
5
5
|
- memory/.claude-plugin/commands/2026-02-25.md
|
|
6
|
+
- memory/agent_response/uncategorized/2026-02-26.md
|
|
6
7
|
- memory/default/uncategorized/2026-02-25.md
|
|
7
8
|
- memory/node_modules/abbrev/2026-02-25.md
|
|
8
9
|
- memory/node_modules/abort-controller/2026-02-25.md
|
|
@@ -391,6 +392,7 @@ Generated automatically by MarkdownMirror.
|
|
|
391
392
|
- memory/node_modules/yallist/2026-02-25.md
|
|
392
393
|
- memory/node_modules/yocto-queue/2026-02-25.md
|
|
393
394
|
- memory/node_modules/zod/2026-02-25.md
|
|
395
|
+
- memory/session_summary/uncategorized/2026-02-26.md
|
|
394
396
|
- memory/specs/20260207-dashboard-upgrade/2026-02-25.md
|
|
395
397
|
- memory/specs/citations-system/2026-02-25.md
|
|
396
398
|
- memory/specs/endless-mode/2026-02-25.md
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
|
|
2
|
+
## 2026-02-26T13:24:02.294Z | aff47d45-6a32-45d6-b584-15f4d93e2ff8
|
|
3
|
+
- type: agent_response
|
|
4
|
+
- session: f8003696-c17e-4e1d-819b-9502d73b9bd4
|
|
5
|
+
이제 문제를 파악했습니다. 현재 프롬프트에서 챗봇이 실제로 수행할 수 없는 기능(재고 확인, 쿠폰 적용, 배송 추적 등)도 제안 가능하도록 허용하고 있습니다.
|
|
6
|
+
|
|
7
|
+
챗봇의 실제 기능 목록을 기반으로 두 프롬프트 모두 개선하겠습니다.
|
|
8
|
+
|
|
9
|
+
먼저 **일반 프롬프트** (`_SYSTEM_PROMPT`)에 제한 사항을 추가합니다.
|
|
10
|
+
|
|
11
|
+
수정 완료했습니다. 변경 요약:
|
|
12
|
+
|
|
13
|
+
### 변경 사항 (`app/services/suggestion_service.py`)
|
|
14
|
+
|
|
15
|
+
**1. 일반 프롬프트 (`_SYSTEM_PROMPT`)에 추가:**
|
|
16
|
+
- "챗봇이 제공할 수 없는 기능" 섹션 신규 추가
|
|
17
|
+
- 재고/품절 확인, 쿠폰/할인코드, 주문/결제, 배송 추적, 교환/반품/환불, A/S/보증, 회원/포인트, 매장 정보
|
|
18
|
+
- 챗봇이 할 수 있는 기능 명시 (상품 검색, 가격 비교, 리뷰 분석, 방송 일정, 판매량 순위, 설명서 정보 등)
|
|
19
|
+
- 좋은 예시에서 '배송 가능 지역 알려줘' → '홈쇼핑 방송 일정 알려줘'로 교체
|
|
20
|
+
|
|
21
|
+
**2. PDID 프롬프트 (`_SYSTEM_PROMPT_PDID`) 변경:**
|
|
22
|
+
- 허용 유형에서 불가능한 항목 제거: 배송/교환/반품, 할인/프로모션, A/S, 색상/사이즈 옵션
|
|
23
|
+
- "챗봇이 제공할 수 없는 기능" 섹션 신규 추가 (재고, 쿠폰, 주문, 배송, 교환/반품, A/S, 회원, 색상/사이즈 옵션)
|
|
24
|
+
- 챗봇이 이 상품에 대해 할 수 있는 것 명시 (설명서 기반 정보, 리뷰 분석, 방송 일정)
|
|
25
|
+
|
|
26
|
+
이제 "각 색상·사이즈별 재고 가능 여부 확인해줘" 같은 제안이 생성되지 않습니다.
|
|
27
|
+
## 2026-02-26T13:53:54.660Z | 798fb69b-1aed-469f-96e3-167b90a5e186
|
|
28
|
+
- type: agent_response
|
|
29
|
+
- session: bench-session-2
|
|
30
|
+
문제를 파악했습니다. `retrieval_traces` 테이블은 `sqlite-event-store.ts`에서 `CREATE TABLE IF NOT EXISTS`로 정의되어 있지만, API 엔드포인트에서 사용하는 DB 인스턴스가 해당 테이블을 초기화하지 못하고 있는 것 같습니다.
|
|
31
|
+
|
|
32
|
+
좀 더 정확한 원인을 확인하겠습니다.
|
|
33
|
+
## 2026-02-26T13:53:54.688Z | 8519d875-d5db-4b5c-8c6b-0542fbadf52c
|
|
34
|
+
- type: agent_response
|
|
35
|
+
- session: bench-session-2
|
|
36
|
+
원인을 찾았습니다. `sqlite-event-store.ts:56-60`에서:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// In read-only mode, skip schema creation
|
|
40
|
+
if (this.readOnly) {
|
|
41
|
+
this.initialized = true;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
API 대시보드는 `readOnly: true`로 서비스를 생성하므로 스키마 생성을 건너뜁니다. 만약 DB가 `retrieval_traces` 테이블이 추가되기 전에 생성되었다면, read-only 모드에서는 테이블을 만들 수 없어서 에러가 발생합니다.
|
|
47
|
+
|
|
48
|
+
`getRecentRetrievalTraces`와 `getRetrievalTraceStats`에서 테이블 미존재 시 빈 결과를 반환하도록 수정하겠습니다.
|
|
49
|
+
## 2026-02-26T13:53:54.697Z | cc73dce3-e4db-44f1-8a44-e6e1156f5c24
|
|
50
|
+
- type: agent_response
|
|
51
|
+
- session: bench-session-2
|
|
52
|
+
수정 완료했습니다. 빌드해서 확인하겠습니다.
|
|
53
|
+
## 2026-02-26T13:53:54.706Z | 66619324-dfef-4d55-bad6-406528e4cefa
|
|
54
|
+
- type: agent_response
|
|
55
|
+
- session: bench-session-2
|
|
56
|
+
빌드 성공했습니다.
|
|
57
|
+
|
|
58
|
+
**원인**: `getServiceFromQuery()`가 `readOnly: true`로 `MemoryService`를 생성 → `initialize()`에서 read-only 모드일 때 스키마 생성을 건너뜀 → 이전 버전 DB에 `retrieval_traces` 테이블이 없으면 쿼리 시 에러 발생
|
|
59
|
+
|
|
60
|
+
**수정 내용** (`sqlite-event-store.ts`):
|
|
61
|
+
- `getRecentRetrievalTraces()`: `no such table` 에러 시 빈 배열 `[]` 반환
|
|
62
|
+
- `getRetrievalTraceStats()`: `no such table` 에러 시 기본 빈 stats 객체 반환
|
|
63
|
+
- 다른 에러는 기존대로 throw
|
|
64
|
+
## 2026-02-26T13:53:54.714Z | 2ab64c5d-2185-43ab-9077-3907362a96de
|
|
65
|
+
- type: agent_response
|
|
66
|
+
- session: bench-session-2
|
|
67
|
+
`sqlite-event-store.ts:53-60`에서 보면:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
async initialize(): Promise<void> {
|
|
71
|
+
if (this.initialized) return;
|
|
72
|
+
|
|
73
|
+
// In read-only mode, skip schema creation
|
|
74
|
+
if (this.readOnly) {
|
|
75
|
+
this.initialized = true;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Create all tables in a single exec...
|
|
80
|
+
sqliteExec(this.db, `CREATE TABLE IF NOT EXISTS ...`);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**스키마 생성 시점**: `MemoryService`가 **write 모드**로 `initialize()`를 처음 호출할 때입니다.
|
|
85
|
+
|
|
86
|
+
이건 실제로 MCP 플러그인이 Claude Code 세션에서 메모리를 기록할 때 발생합니다 (retrieve/store 호출 시).
|
|
87
|
+
|
|
88
|
+
**문제 상황**:
|
|
89
|
+
- 대시보드 API는 `readOnly: true`로 서비스를 생성 → 스키마 생성 안 함
|
|
90
|
+
- 해당 프로젝트 DB가 `retrieval_traces` 테이블 추가 **이전 버전**에서 만들어졌으면, write 모드 세션이 한 번도 다시 초기화되지 않은 상태
|
|
91
|
+
- 결과적으로 read-only API에서 존재하지 않는 테이블을 쿼리 → 에러
|
|
92
|
+
|
|
93
|
+
**정상 흐름**: 해당 프로젝트에서 Claude Code를 한번 사용하면 write 모드 초기화가 실행되고 `CREATE TABLE IF NOT EXISTS`로 테이블이 생성됩니다. 그 이후엔 대시보드에서도 정상 조회됩니다.
|
|
94
|
+
|
|
95
|
+
방금 수정은 그 사이 간극(테이블 없는 상태)에서 에러 대신 빈 결과를 반환하도록 한 것입니다.
|
|
96
|
+
## 2026-02-26T13:53:54.721Z | f362a4f6-a91c-4f25-89fa-4108e6418340
|
|
97
|
+
- type: agent_response
|
|
98
|
+
- session: bench-session-2
|
|
99
|
+
커밋 완료: `60d59c6`
|
|
100
|
+
|
|
101
|
+
`getRecentRetrievalTraces()`와 `getRetrievalTraceStats()`에서 `no such table` 에러 시 빈 결과를 반환하도록 수정했습니다.
|
|
102
|
+
## 2026-02-26T13:54:46.336Z | 08733485-243f-4a65-a81d-ec962bc9a1d5
|
|
103
|
+
- type: agent_response
|
|
104
|
+
- session: bench-session-3
|
|
105
|
+
문제를 파악했습니다. `retrieval_traces` 테이블은 `sqlite-event-store.ts`에서 `CREATE TABLE IF NOT EXISTS`로 정의되어 있지만, API 엔드포인트에서 사용하는 DB 인스턴스가 해당 테이블을 초기화하지 못하고 있는 것 같습니다.
|
|
106
|
+
|
|
107
|
+
좀 더 정확한 원인을 확인하겠습니다.
|
|
108
|
+
## 2026-02-26T13:54:46.356Z | acc9926e-20d3-477d-8fa0-e67983db0c0c
|
|
109
|
+
- type: agent_response
|
|
110
|
+
- session: bench-session-3
|
|
111
|
+
원인을 찾았습니다. `sqlite-event-store.ts:56-60`에서:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// In read-only mode, skip schema creation
|
|
115
|
+
if (this.readOnly) {
|
|
116
|
+
this.initialized = true;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
API 대시보드는 `readOnly: true`로 서비스를 생성하므로 스키마 생성을 건너뜁니다. 만약 DB가 `retrieval_traces` 테이블이 추가되기 전에 생성되었다면, read-only 모드에서는 테이블을 만들 수 없어서 에러가 발생합니다.
|
|
122
|
+
|
|
123
|
+
`getRecentRetrievalTraces`와 `getRetrievalTraceStats`에서 테이블 미존재 시 빈 결과를 반환하도록 수정하겠습니다.
|
|
124
|
+
## 2026-02-26T13:54:46.365Z | fca49e8b-4b39-48e7-a250-bd6100f96bab
|
|
125
|
+
- type: agent_response
|
|
126
|
+
- session: bench-session-3
|
|
127
|
+
수정 완료했습니다. 빌드해서 확인하겠습니다.
|
|
128
|
+
## 2026-02-26T13:54:46.374Z | 4e471294-7597-4a58-abc9-c220ac92b4bc
|
|
129
|
+
- type: agent_response
|
|
130
|
+
- session: bench-session-3
|
|
131
|
+
빌드 성공했습니다.
|
|
132
|
+
|
|
133
|
+
**원인**: `getServiceFromQuery()`가 `readOnly: true`로 `MemoryService`를 생성 → `initialize()`에서 read-only 모드일 때 스키마 생성을 건너뜀 → 이전 버전 DB에 `retrieval_traces` 테이블이 없으면 쿼리 시 에러 발생
|
|
134
|
+
|
|
135
|
+
**수정 내용** (`sqlite-event-store.ts`):
|
|
136
|
+
- `getRecentRetrievalTraces()`: `no such table` 에러 시 빈 배열 `[]` 반환
|
|
137
|
+
- `getRetrievalTraceStats()`: `no such table` 에러 시 기본 빈 stats 객체 반환
|
|
138
|
+
- 다른 에러는 기존대로 throw
|
|
139
|
+
## 2026-02-26T13:54:46.382Z | a2ece559-3e19-4553-a558-ec809b54b527
|
|
140
|
+
- type: agent_response
|
|
141
|
+
- session: bench-session-3
|
|
142
|
+
`sqlite-event-store.ts:53-60`에서 보면:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
async initialize(): Promise<void> {
|
|
146
|
+
if (this.initialized) return;
|
|
147
|
+
|
|
148
|
+
// In read-only mode, skip schema creation
|
|
149
|
+
if (this.readOnly) {
|
|
150
|
+
this.initialized = true;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Create all tables in a single exec...
|
|
155
|
+
sqliteExec(this.db, `CREATE TABLE IF NOT EXISTS ...`);
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**스키마 생성 시점**: `MemoryService`가 **write 모드**로 `initialize()`를 처음 호출할 때입니다.
|
|
160
|
+
|
|
161
|
+
이건 실제로 MCP 플러그인이 Claude Code 세션에서 메모리를 기록할 때 발생합니다 (retrieve/store 호출 시).
|
|
162
|
+
|
|
163
|
+
**문제 상황**:
|
|
164
|
+
- 대시보드 API는 `readOnly: true`로 서비스를 생성 → 스키마 생성 안 함
|
|
165
|
+
- 해당 프로젝트 DB가 `retrieval_traces` 테이블 추가 **이전 버전**에서 만들어졌으면, write 모드 세션이 한 번도 다시 초기화되지 않은 상태
|
|
166
|
+
- 결과적으로 read-only API에서 존재하지 않는 테이블을 쿼리 → 에러
|
|
167
|
+
|
|
168
|
+
**정상 흐름**: 해당 프로젝트에서 Claude Code를 한번 사용하면 write 모드 초기화가 실행되고 `CREATE TABLE IF NOT EXISTS`로 테이블이 생성됩니다. 그 이후엔 대시보드에서도 정상 조회됩니다.
|
|
169
|
+
|
|
170
|
+
방금 수정은 그 사이 간극(테이블 없는 상태)에서 에러 대신 빈 결과를 반환하도록 한 것입니다.
|
|
171
|
+
## 2026-02-26T13:54:46.390Z | e21b392c-87c3-44b0-a355-2fb753804ba6
|
|
172
|
+
- type: agent_response
|
|
173
|
+
- session: bench-session-3
|
|
174
|
+
커밋 완료: `60d59c6`
|
|
175
|
+
|
|
176
|
+
`getRecentRetrievalTraces()`와 `getRetrievalTraceStats()`에서 `no such table` 에러 시 빈 결과를 반환하도록 수정했습니다.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
## 2026-02-26T13:53:54.921Z | 3fa78495-3f90-45ff-a85c-43dc29ddedb7
|
|
3
|
+
- type: session_summary
|
|
4
|
+
- session: bench-session-2
|
|
5
|
+
Session with 1 user prompts and 6 responses.
|
|
6
|
+
Topics discussed:
|
|
7
|
+
- 최근 변경 사항 때문에 claude code 가 느려진 원인을 분석해줘.
|
|
8
|
+
## 2026-02-26T13:54:46.584Z | cb94a8e4-4a9d-4bfc-8ee5-1458f5e304e7
|
|
9
|
+
- type: session_summary
|
|
10
|
+
- session: bench-session-3
|
|
11
|
+
Session with 1 user prompts and 6 responses.
|
|
12
|
+
Topics discussed:
|
|
13
|
+
- 최근 변경 사항 때문에 claude code 가 느려진 원인을 분석해줘.
|
|
@@ -198,4 +198,12 @@
|
|
|
198
198
|
## 2026-02-26T12:51:57.850Z | 3b09d82b-7fa3-4673-978e-87ec65d901dd
|
|
199
199
|
- type: tool_observation
|
|
200
200
|
- session: 2f324dae-7d8f-4f67-842e-acf507b79c59
|
|
201
|
-
{"toolName":"Bash","toolInput":{"command":"git add src/core/sqlite-event-store.ts && git commit -m \"$(cat <<'EOF'\nfix(api): handle missing retrieval_traces table in read-only mode\n\nDashboard API creates read-only MemoryService which skips schema\ncreation. If the DB was created before retrieval_traces was added,\nqueries fail with \"no such table\". Now returns empty results gracefully.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\nEOF\n)\"","description":"Commit retrieval_traces fix"},"toolOutput":"[main 60d59c6] fix(api): handle missing retrieval_traces table in read-only mode\n 1 file changed, 52 insertions(+), 40 deletions(-)","durationMs":0,"success":true,"metadata":{"command":"git add","turnId":"6ee6b497-8756-43c8-a208-8830a70efc1a"}}
|
|
201
|
+
{"toolName":"Bash","toolInput":{"command":"git add src/core/sqlite-event-store.ts && git commit -m \"$(cat <<'EOF'\nfix(api): handle missing retrieval_traces table in read-only mode\n\nDashboard API creates read-only MemoryService which skips schema\ncreation. If the DB was created before retrieval_traces was added,\nqueries fail with \"no such table\". Now returns empty results gracefully.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\nEOF\n)\"","description":"Commit retrieval_traces fix"},"toolOutput":"[main 60d59c6] fix(api): handle missing retrieval_traces table in read-only mode\n 1 file changed, 52 insertions(+), 40 deletions(-)","durationMs":0,"success":true,"metadata":{"command":"git add","turnId":"6ee6b497-8756-43c8-a208-8830a70efc1a"}}
|
|
202
|
+
## 2026-02-26T13:53:54.436Z | 4ced656c-1426-44fd-9f2d-148c5432c1f8
|
|
203
|
+
- type: tool_observation
|
|
204
|
+
- session: bench-session-2
|
|
205
|
+
{"toolName":"Bash","toolInput":{"cmd":"echo hello"},"toolOutput":"hello\n","durationMs":0,"success":true,"metadata":{"turnId":"ccd580af-30da-4227-8a48-6ce91c3bfeba"}}
|
|
206
|
+
## 2026-02-26T13:54:46.108Z | 0fa770e5-f71d-4eda-be4d-7a6529171718
|
|
207
|
+
- type: tool_observation
|
|
208
|
+
- session: bench-session-3
|
|
209
|
+
{"toolName":"Bash","toolInput":{"cmd":"echo hello"},"toolOutput":"hello\n","durationMs":0,"success":true,"metadata":{"turnId":"03e597c8-295a-43d8-9959-bc77607d30f8"}}
|
|
@@ -7,4 +7,19 @@ api/stats/retrieval-traces?limit=20
|
|
|
7
7
|
## 2026-02-26T12:50:53.044Z | 71b502de-eda8-4d54-a1f4-3ef06fd9edb3
|
|
8
8
|
- type: user_prompt
|
|
9
9
|
- session: 2f324dae-7d8f-4f67-842e-acf507b79c59
|
|
10
|
-
스키마 생성은 언제 하는거야?
|
|
10
|
+
스키마 생성은 언제 하는거야?
|
|
11
|
+
## 2026-02-26T13:24:02.278Z | dd9328f4-430f-49d7-b8ab-62f39cea6164
|
|
12
|
+
- type: user_prompt
|
|
13
|
+
- session: f8003696-c17e-4e1d-819b-9502d73b9bd4
|
|
14
|
+
suggested_actions 를 생성할때
|
|
15
|
+
"각 색상·사이즈별 재고 가능 여부 확인해줘"
|
|
16
|
+
같이 없는 기능은 생성하지 않도록 프롬프트 개선해줘
|
|
17
|
+
|
|
18
|
+
## 2026-02-26T13:53:54.228Z | efefccef-1a9a-4e89-b1fa-b855fd8fdc85
|
|
19
|
+
- type: user_prompt
|
|
20
|
+
- session: bench-session-2
|
|
21
|
+
최근 변경 사항 때문에 claude code 가 느려진 원인을 분석해줘.
|
|
22
|
+
## 2026-02-26T13:54:45.879Z | f7fca9e1-5169-4732-8845-34fdb5e699c5
|
|
23
|
+
- type: user_prompt
|
|
24
|
+
- session: bench-session-3
|
|
25
|
+
최근 변경 사항 때문에 claude code 가 느려진 원인을 분석해줘.
|
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -32,6 +32,7 @@ interface ClaudeSettings {
|
|
|
32
32
|
PostToolUse?: Array<{ matcher: string; hooks: Array<{ type: string; command: string }> }>;
|
|
33
33
|
SessionStart?: Array<{ matcher: string; hooks: Array<{ type: string; command: string }> }>;
|
|
34
34
|
Stop?: Array<{ matcher: string; hooks: Array<{ type: string; command: string }> }>;
|
|
35
|
+
SessionEnd?: Array<{ matcher: string; hooks: Array<{ type: string; command: string }> }>;
|
|
35
36
|
};
|
|
36
37
|
[key: string]: unknown;
|
|
37
38
|
}
|
|
@@ -79,30 +80,39 @@ function saveClaudeSettings(settings: ClaudeSettings): void {
|
|
|
79
80
|
fs.renameSync(tempPath, CLAUDE_SETTINGS_PATH);
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
const REQUIRED_HOOK_FILES = [
|
|
84
|
+
'user-prompt-submit.js',
|
|
85
|
+
'post-tool-use.js',
|
|
86
|
+
'session-start.js',
|
|
87
|
+
'stop.js',
|
|
88
|
+
'session-end.js'
|
|
89
|
+
] as const;
|
|
90
|
+
|
|
91
|
+
function hasHook(settings: ClaudeSettings, hookName: keyof NonNullable<ClaudeSettings['hooks']>, commandFragment: string): boolean {
|
|
92
|
+
const hookEntries = settings.hooks?.[hookName];
|
|
93
|
+
if (!hookEntries) return false;
|
|
94
|
+
return hookEntries.some((entry) => entry.hooks?.some((hook) => hook.command?.includes(commandFragment)));
|
|
95
|
+
}
|
|
96
|
+
|
|
82
97
|
function getHooksConfig(pluginPath: string): ClaudeSettings['hooks'] {
|
|
98
|
+
const makeHook = (fileName: string) => [
|
|
99
|
+
{
|
|
100
|
+
matcher: '',
|
|
101
|
+
hooks: [
|
|
102
|
+
{
|
|
103
|
+
type: 'command',
|
|
104
|
+
command: `node ${path.join(pluginPath, 'hooks', fileName)}`
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
];
|
|
109
|
+
|
|
83
110
|
return {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
type: 'command',
|
|
90
|
-
command: `node ${path.join(pluginPath, 'hooks', 'user-prompt-submit.js')}`
|
|
91
|
-
}
|
|
92
|
-
]
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
PostToolUse: [
|
|
96
|
-
{
|
|
97
|
-
matcher: '',
|
|
98
|
-
hooks: [
|
|
99
|
-
{
|
|
100
|
-
type: 'command',
|
|
101
|
-
command: `node ${path.join(pluginPath, 'hooks', 'post-tool-use.js')}`
|
|
102
|
-
}
|
|
103
|
-
]
|
|
104
|
-
}
|
|
105
|
-
]
|
|
111
|
+
SessionStart: makeHook('session-start.js'),
|
|
112
|
+
UserPromptSubmit: makeHook('user-prompt-submit.js'),
|
|
113
|
+
PostToolUse: makeHook('post-tool-use.js'),
|
|
114
|
+
Stop: makeHook('stop.js'),
|
|
115
|
+
SessionEnd: makeHook('session-end.js')
|
|
106
116
|
};
|
|
107
117
|
}
|
|
108
118
|
|
|
@@ -129,9 +139,12 @@ program
|
|
|
129
139
|
const pluginPath = options.path || getPluginPath();
|
|
130
140
|
|
|
131
141
|
// Verify hooks exist
|
|
132
|
-
const
|
|
133
|
-
|
|
142
|
+
const missingHooks = REQUIRED_HOOK_FILES.filter((file) =>
|
|
143
|
+
!fs.existsSync(path.join(pluginPath, 'hooks', file))
|
|
144
|
+
);
|
|
145
|
+
if (missingHooks.length > 0) {
|
|
134
146
|
console.error(`\n❌ Hook files not found at: ${pluginPath}`);
|
|
147
|
+
console.error(` Missing: ${missingHooks.join(', ')}`);
|
|
135
148
|
console.error(' Make sure you have built the plugin with "npm run build"');
|
|
136
149
|
process.exit(1);
|
|
137
150
|
}
|
|
@@ -151,8 +164,11 @@ program
|
|
|
151
164
|
|
|
152
165
|
console.log('\n✅ Claude Memory Layer installed!\n');
|
|
153
166
|
console.log('Hooks registered:');
|
|
167
|
+
console.log(' - SessionStart: Register session -> project mapping');
|
|
154
168
|
console.log(' - UserPromptSubmit: Memory retrieval on user input');
|
|
155
|
-
console.log(' - PostToolUse: Store tool observations
|
|
169
|
+
console.log(' - PostToolUse: Store tool observations');
|
|
170
|
+
console.log(' - Stop: Store assistant responses');
|
|
171
|
+
console.log(' - SessionEnd: Persist session summary\n');
|
|
156
172
|
console.log('Plugin path:', pluginPath);
|
|
157
173
|
console.log('\n⚠️ Restart Claude Code for changes to take effect.\n');
|
|
158
174
|
console.log('Commands:');
|
|
@@ -183,8 +199,11 @@ program
|
|
|
183
199
|
}
|
|
184
200
|
|
|
185
201
|
// Remove our hooks
|
|
202
|
+
delete settings.hooks.SessionStart;
|
|
186
203
|
delete settings.hooks.UserPromptSubmit;
|
|
187
204
|
delete settings.hooks.PostToolUse;
|
|
205
|
+
delete settings.hooks.Stop;
|
|
206
|
+
delete settings.hooks.SessionEnd;
|
|
188
207
|
|
|
189
208
|
// Clean up empty hooks object
|
|
190
209
|
if (Object.keys(settings.hooks).length === 0) {
|
|
@@ -219,19 +238,22 @@ program
|
|
|
219
238
|
console.log('\n🧠 Claude Memory Layer Status\n');
|
|
220
239
|
|
|
221
240
|
// Check hooks
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
);
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
);
|
|
241
|
+
const hasSessionStartHook = hasHook(settings, 'SessionStart', 'session-start');
|
|
242
|
+
const hasUserPromptHook = hasHook(settings, 'UserPromptSubmit', 'user-prompt-submit');
|
|
243
|
+
const hasPostToolHook = hasHook(settings, 'PostToolUse', 'post-tool-use');
|
|
244
|
+
const hasStopHook = hasHook(settings, 'Stop', 'stop');
|
|
245
|
+
const hasSessionEndHook = hasHook(settings, 'SessionEnd', 'session-end');
|
|
228
246
|
|
|
229
247
|
console.log('Hooks:');
|
|
248
|
+
console.log(` SessionStart: ${hasSessionStartHook ? '✅ Installed' : '❌ Not installed'}`);
|
|
230
249
|
console.log(` UserPromptSubmit: ${hasUserPromptHook ? '✅ Installed' : '❌ Not installed'}`);
|
|
231
250
|
console.log(` PostToolUse: ${hasPostToolHook ? '✅ Installed' : '❌ Not installed'}`);
|
|
251
|
+
console.log(` Stop: ${hasStopHook ? '✅ Installed' : '❌ Not installed'}`);
|
|
252
|
+
console.log(` SessionEnd: ${hasSessionEndHook ? '✅ Installed' : '❌ Not installed'}`);
|
|
232
253
|
|
|
233
254
|
// Check plugin files
|
|
234
|
-
const hooksExist =
|
|
255
|
+
const hooksExist = REQUIRED_HOOK_FILES
|
|
256
|
+
.every((file) => fs.existsSync(path.join(pluginPath, 'hooks', file)));
|
|
235
257
|
console.log(`\nPlugin files: ${hooksExist ? '✅ Found' : '❌ Not found'}`);
|
|
236
258
|
console.log(` Path: ${pluginPath}`);
|
|
237
259
|
|
|
@@ -239,7 +261,7 @@ program
|
|
|
239
261
|
const dashboardRunning = await isServerRunning(37777);
|
|
240
262
|
console.log(`\nDashboard: ${dashboardRunning ? '✅ Running at http://localhost:37777' : '⏹️ Not running'}`);
|
|
241
263
|
|
|
242
|
-
if (!hasUserPromptHook || !hasPostToolHook) {
|
|
264
|
+
if (!hasSessionStartHook || !hasUserPromptHook || !hasPostToolHook || !hasStopHook || !hasSessionEndHook) {
|
|
243
265
|
console.log('\n💡 Run "claude-memory-layer install" to set up hooks.\n');
|
|
244
266
|
} else {
|
|
245
267
|
console.log('\n✅ Plugin is fully installed and configured.\n');
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
|
-
|
|
8
|
+
getLightweightMemoryService,
|
|
9
9
|
registerSession
|
|
10
10
|
} from '../services/memory-service.js';
|
|
11
11
|
import type { SessionStartInput, SessionStartOutput } from '../core/types.js';
|
|
@@ -18,8 +18,8 @@ async function main(): Promise<void> {
|
|
|
18
18
|
// Register session with project path for other hooks to find
|
|
19
19
|
registerSession(input.session_id, input.cwd);
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
const memoryService =
|
|
21
|
+
// Use lightweight service to avoid starting background workers in hook process
|
|
22
|
+
const memoryService = getLightweightMemoryService(input.session_id);
|
|
23
23
|
|
|
24
24
|
try {
|
|
25
25
|
// Start session in memory service
|
|
@@ -42,6 +42,12 @@ async function main(): Promise<void> {
|
|
|
42
42
|
} catch (error) {
|
|
43
43
|
console.error('Memory hook error:', error);
|
|
44
44
|
console.log(JSON.stringify({ context: '' }));
|
|
45
|
+
} finally {
|
|
46
|
+
try {
|
|
47
|
+
await memoryService.close();
|
|
48
|
+
} catch {
|
|
49
|
+
// Best-effort cleanup
|
|
50
|
+
}
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
|