claude-self-reflect 6.0.5 ā 7.1.8
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/.claude/agents/csr-validator.md +87 -1
- package/.env.example +49 -0
- package/Dockerfile.batch-monitor +36 -0
- package/Dockerfile.batch-watcher +38 -0
- package/README.md +189 -29
- package/docker-compose.yaml +114 -15
- package/installer/setup-wizard-docker.js +195 -8
- package/installer/update-manager.js +88 -1
- package/mcp-server/src/standalone_client.py +314 -0
- package/package.json +1 -1
- package/src/runtime/batch_monitor.py +300 -0
- package/src/runtime/batch_watcher.py +455 -0
- package/src/runtime/config.py +61 -0
- package/src/runtime/hooks/__init__.py +21 -0
- package/src/runtime/hooks/ralph_state.py +397 -0
- package/src/runtime/hooks/session_end_hook.py +245 -0
- package/src/runtime/hooks/session_start_hook.py +259 -0
- package/src/runtime/precompact-hook.sh +60 -3
- package/src/runtime/qdrant_connection.py +73 -0
- package/src/runtime/unified_state_manager.py +35 -10
package/docker-compose.yaml
CHANGED
|
@@ -2,13 +2,16 @@ volumes:
|
|
|
2
2
|
qdrant_data:
|
|
3
3
|
|
|
4
4
|
services:
|
|
5
|
-
# Fix permissions for config directory
|
|
5
|
+
# Fix permissions for config directory (UID 1001 matches appuser in Dockerfiles)
|
|
6
|
+
# Now runs by default since batch services are always-on
|
|
6
7
|
init-permissions:
|
|
7
8
|
image: alpine
|
|
8
|
-
command: chown -R
|
|
9
|
+
command: sh -c "mkdir -p /config /batch_queue /batch_state && chown -R 1001:1001 /config && chown -R 1001:1001 /batch_queue && chown -R 1001:1001 /batch_state"
|
|
9
10
|
volumes:
|
|
10
|
-
- ${CONFIG_PATH
|
|
11
|
-
|
|
11
|
+
- ${CONFIG_PATH:-${HOME}/.claude-self-reflect/config}:/config
|
|
12
|
+
- ${CSR_BATCH_QUEUE_DIR:-${HOME}/.claude-self-reflect/batch_queue}:/batch_queue
|
|
13
|
+
- ${CSR_BATCH_STATE_DIR:-${HOME}/.claude-self-reflect/batch_state}:/batch_state
|
|
14
|
+
# No profiles = starts by default (required for batch services)
|
|
12
15
|
|
|
13
16
|
# Qdrant vector database - the heart of semantic search
|
|
14
17
|
qdrant:
|
|
@@ -20,7 +23,7 @@ services:
|
|
|
20
23
|
- qdrant_data:/qdrant/storage
|
|
21
24
|
# Note: Using CONFIG_PATH variable to support global npm installs (fixes #71)
|
|
22
25
|
# macOS Docker Desktop restricts mounts to /Users, /Volumes, /private, /tmp
|
|
23
|
-
- ${CONFIG_PATH
|
|
26
|
+
- ${CONFIG_PATH:-${HOME}/.claude-self-reflect/config}/qdrant-config.yaml:/qdrant/config/config.yaml:ro
|
|
24
27
|
environment:
|
|
25
28
|
- QDRANT__LOG_LEVEL=INFO
|
|
26
29
|
- QDRANT__SERVICE__HTTP_PORT=6333
|
|
@@ -38,10 +41,11 @@ services:
|
|
|
38
41
|
- init-permissions
|
|
39
42
|
- qdrant
|
|
40
43
|
volumes:
|
|
41
|
-
- ${CLAUDE_LOGS_PATH
|
|
42
|
-
- ${CONFIG_PATH
|
|
44
|
+
- ${CLAUDE_LOGS_PATH:-${HOME}/.claude/projects}:/logs:ro
|
|
45
|
+
- ${CONFIG_PATH:-${HOME}/.claude-self-reflect/config}:/config
|
|
43
46
|
environment:
|
|
44
47
|
- QDRANT_URL=http://qdrant:6333
|
|
48
|
+
- HF_HUB_OFFLINE=1
|
|
45
49
|
- STATE_FILE=/config/imported-files.json
|
|
46
50
|
- LOGS_DIR=/logs
|
|
47
51
|
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
|
@@ -67,11 +71,12 @@ services:
|
|
|
67
71
|
- init-permissions
|
|
68
72
|
- qdrant
|
|
69
73
|
volumes:
|
|
70
|
-
- ${CLAUDE_LOGS_PATH
|
|
71
|
-
- ${CONFIG_PATH
|
|
74
|
+
- ${CLAUDE_LOGS_PATH:-${HOME}/.claude/projects}:/logs:ro
|
|
75
|
+
- ${CONFIG_PATH:-${HOME}/.claude-self-reflect/config}:/config
|
|
72
76
|
- /tmp:/tmp
|
|
73
77
|
environment:
|
|
74
78
|
- QDRANT_URL=http://qdrant:6333
|
|
79
|
+
- HF_HUB_OFFLINE=1
|
|
75
80
|
- STATE_FILE=/config/imported-files.json
|
|
76
81
|
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
|
77
82
|
- VOYAGE_API_KEY=${VOYAGE_API_KEY:-}
|
|
@@ -97,10 +102,11 @@ services:
|
|
|
97
102
|
- init-permissions
|
|
98
103
|
- qdrant
|
|
99
104
|
volumes:
|
|
100
|
-
- ${CLAUDE_LOGS_PATH
|
|
101
|
-
- ${CONFIG_PATH
|
|
105
|
+
- ${CLAUDE_LOGS_PATH:-${HOME}/.claude/projects}:/logs:ro
|
|
106
|
+
- ${CONFIG_PATH:-${HOME}/.claude-self-reflect/config}:/config
|
|
102
107
|
environment:
|
|
103
108
|
- QDRANT_URL=http://qdrant:6333
|
|
109
|
+
- HF_HUB_OFFLINE=1
|
|
104
110
|
- STATE_FILE=/config/streaming-state.json # FIXED: Use streaming-specific state file
|
|
105
111
|
- VOYAGE_API_KEY=${VOYAGE_API_KEY:-}
|
|
106
112
|
- VOYAGE_KEY=${VOYAGE_KEY:-}
|
|
@@ -136,10 +142,11 @@ services:
|
|
|
136
142
|
depends_on:
|
|
137
143
|
- qdrant
|
|
138
144
|
volumes:
|
|
139
|
-
- ${CLAUDE_LOGS_PATH
|
|
140
|
-
- ${CONFIG_PATH
|
|
145
|
+
- ${CLAUDE_LOGS_PATH:-${HOME}/.claude/projects}:/logs:ro
|
|
146
|
+
- ${CONFIG_PATH:-${HOME}/.claude-self-reflect/config}:/config
|
|
141
147
|
environment:
|
|
142
148
|
- QDRANT_URL=http://qdrant:6333
|
|
149
|
+
- HF_HUB_OFFLINE=1
|
|
143
150
|
- STATE_FILE=/config/imported-files.json
|
|
144
151
|
- VOYAGE_API_KEY=${VOYAGE_API_KEY:-}
|
|
145
152
|
- VOYAGE_KEY=${VOYAGE_KEY:-}
|
|
@@ -171,10 +178,11 @@ services:
|
|
|
171
178
|
- init-permissions
|
|
172
179
|
- qdrant
|
|
173
180
|
volumes:
|
|
174
|
-
- ${CLAUDE_LOGS_PATH
|
|
175
|
-
- ${CONFIG_PATH
|
|
181
|
+
- ${CLAUDE_LOGS_PATH:-${HOME}/.claude/projects}:/logs:ro
|
|
182
|
+
- ${CONFIG_PATH:-${HOME}/.claude-self-reflect/config}:/config
|
|
176
183
|
environment:
|
|
177
184
|
- QDRANT_URL=http://qdrant:6333
|
|
185
|
+
- HF_HUB_OFFLINE=1
|
|
178
186
|
- STATE_FILE=/config/csr-watcher.json
|
|
179
187
|
- LOGS_DIR=/logs # Fixed: Point to mounted volume
|
|
180
188
|
- VOYAGE_KEY=${VOYAGE_KEY:-}
|
|
@@ -210,6 +218,7 @@ services:
|
|
|
210
218
|
- qdrant
|
|
211
219
|
environment:
|
|
212
220
|
- QDRANT_URL=http://qdrant:6333
|
|
221
|
+
- HF_HUB_OFFLINE=1
|
|
213
222
|
- VOYAGE_KEY=${VOYAGE_KEY:-}
|
|
214
223
|
- PREFER_LOCAL_EMBEDDINGS=${PREFER_LOCAL_EMBEDDINGS:-true}
|
|
215
224
|
- ENABLE_MEMORY_DECAY=${ENABLE_MEMORY_DECAY:-true}
|
|
@@ -221,6 +230,96 @@ services:
|
|
|
221
230
|
tty: true
|
|
222
231
|
profiles: ["mcp"]
|
|
223
232
|
|
|
233
|
+
# Batch watcher - Queues conversations and triggers batch narrative generation
|
|
234
|
+
# Requires ANTHROPIC_API_KEY for AI-powered narratives (9.3x better search quality)
|
|
235
|
+
# Now starts by default if ANTHROPIC_API_KEY is set
|
|
236
|
+
batch-watcher:
|
|
237
|
+
build:
|
|
238
|
+
context: .
|
|
239
|
+
dockerfile: Dockerfile.batch-watcher
|
|
240
|
+
container_name: claude-reflection-batch-watcher
|
|
241
|
+
depends_on:
|
|
242
|
+
- init-permissions
|
|
243
|
+
- qdrant
|
|
244
|
+
volumes:
|
|
245
|
+
- ${CLAUDE_LOGS_PATH:-${HOME}/.claude/projects}:/logs:ro
|
|
246
|
+
- ${CONFIG_PATH:-${HOME}/.claude-self-reflect/config}:/home/appuser/.claude-self-reflect/config
|
|
247
|
+
- ${CSR_BATCH_QUEUE_DIR:-${HOME}/.claude-self-reflect/batch_queue}:/home/appuser/.claude-self-reflect/batch_queue
|
|
248
|
+
- ${CSR_BATCH_STATE_DIR:-${HOME}/.claude-self-reflect/batch_state}:/home/appuser/.claude-self-reflect/batch_state
|
|
249
|
+
environment:
|
|
250
|
+
- QDRANT_URL=http://qdrant:6333
|
|
251
|
+
- HF_HUB_OFFLINE=1
|
|
252
|
+
- QDRANT_API_KEY=${QDRANT_API_KEY:-}
|
|
253
|
+
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
|
254
|
+
- CSR_HOME=/home/appuser/.claude-self-reflect
|
|
255
|
+
- CSR_CONFIG_DIR=/home/appuser/.claude-self-reflect/config
|
|
256
|
+
- CSR_BATCH_QUEUE_DIR=/home/appuser/.claude-self-reflect/batch_queue
|
|
257
|
+
- CSR_BATCH_STATE_DIR=/home/appuser/.claude-self-reflect/batch_state
|
|
258
|
+
- CLAUDE_PROJECTS_DIR=/logs
|
|
259
|
+
- BATCH_SIZE_TRIGGER=${BATCH_SIZE_TRIGGER:-10}
|
|
260
|
+
- BATCH_TIME_TRIGGER_MINUTES=${BATCH_TIME_TRIGGER_MINUTES:-30}
|
|
261
|
+
- HOT_WINDOW_MINUTES=${HOT_WINDOW_MINUTES:-5}
|
|
262
|
+
- WARM_WINDOW_HOURS=${WARM_WINDOW_HOURS:-24}
|
|
263
|
+
- MAX_COLD_FILES=${MAX_COLD_FILES:-5}
|
|
264
|
+
- SUBPROCESS_TIMEOUT_SECONDS=${SUBPROCESS_TIMEOUT_SECONDS:-1800}
|
|
265
|
+
- PYTHONUNBUFFERED=1
|
|
266
|
+
- PYTHONPATH=/app
|
|
267
|
+
restart: unless-stopped
|
|
268
|
+
# profiles: ["batch-automation"] # REMOVED - now starts by default
|
|
269
|
+
mem_limit: 2g
|
|
270
|
+
memswap_limit: 2g
|
|
271
|
+
healthcheck:
|
|
272
|
+
test: ["CMD-SHELL", "kill -0 1 2>/dev/null || exit 1"]
|
|
273
|
+
interval: 30s
|
|
274
|
+
timeout: 10s
|
|
275
|
+
retries: 3
|
|
276
|
+
start_period: 10s
|
|
277
|
+
logging:
|
|
278
|
+
driver: "json-file"
|
|
279
|
+
options:
|
|
280
|
+
max-size: "10m"
|
|
281
|
+
max-file: "3"
|
|
282
|
+
labels: "service=batch-watcher"
|
|
283
|
+
|
|
284
|
+
# Batch monitor - Monitors batch API jobs and triggers evaluations
|
|
285
|
+
# Requires ANTHROPIC_API_KEY. Now starts by default.
|
|
286
|
+
batch-monitor:
|
|
287
|
+
build:
|
|
288
|
+
context: .
|
|
289
|
+
dockerfile: Dockerfile.batch-monitor
|
|
290
|
+
container_name: claude-reflection-batch-monitor
|
|
291
|
+
depends_on:
|
|
292
|
+
- init-permissions
|
|
293
|
+
- qdrant
|
|
294
|
+
volumes:
|
|
295
|
+
- ${CSR_BATCH_STATE_DIR:-${HOME}/.claude-self-reflect/batch_state}:/home/appuser/.claude-self-reflect/batch_state
|
|
296
|
+
environment:
|
|
297
|
+
- QDRANT_URL=http://qdrant:6333
|
|
298
|
+
- HF_HUB_OFFLINE=1
|
|
299
|
+
- QDRANT_API_KEY=${QDRANT_API_KEY:-}
|
|
300
|
+
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
|
301
|
+
- CSR_HOME=/home/appuser/.claude-self-reflect
|
|
302
|
+
- CSR_BATCH_STATE_DIR=/home/appuser/.claude-self-reflect/batch_state
|
|
303
|
+
- CHECK_INTERVAL=${BATCH_MONITOR_INTERVAL:-60}
|
|
304
|
+
- PYTHONUNBUFFERED=1
|
|
305
|
+
- PYTHONPATH=/app
|
|
306
|
+
restart: unless-stopped
|
|
307
|
+
# profiles: ["batch-automation"] # REMOVED - now starts by default
|
|
308
|
+
mem_limit: 512m
|
|
309
|
+
memswap_limit: 512m
|
|
310
|
+
healthcheck:
|
|
311
|
+
test: ["CMD-SHELL", "kill -0 1 2>/dev/null || exit 1"]
|
|
312
|
+
interval: 30s
|
|
313
|
+
timeout: 10s
|
|
314
|
+
retries: 3
|
|
315
|
+
start_period: 10s
|
|
316
|
+
logging:
|
|
317
|
+
driver: "json-file"
|
|
318
|
+
options:
|
|
319
|
+
max-size: "10m"
|
|
320
|
+
max-file: "3"
|
|
321
|
+
labels: "service=batch-monitor"
|
|
322
|
+
|
|
224
323
|
networks:
|
|
225
324
|
default:
|
|
226
325
|
name: claude-reflection-network
|
|
@@ -557,6 +557,109 @@ async function enrichMetadata() {
|
|
|
557
557
|
}
|
|
558
558
|
}
|
|
559
559
|
|
|
560
|
+
async function setupBatchAutomation() {
|
|
561
|
+
console.log('\nš AI-Powered Narratives (NEW in v7.0!)...');
|
|
562
|
+
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
|
|
563
|
+
console.log('Transform your conversations into rich, searchable narratives.');
|
|
564
|
+
console.log('');
|
|
565
|
+
console.log('š Benefits:');
|
|
566
|
+
console.log(' ⢠9.3x better search quality (0.074 ā 0.691 relevance score)');
|
|
567
|
+
console.log(' ⢠82% token compression while maintaining searchability');
|
|
568
|
+
console.log(' ⢠50% cost savings using Anthropic Batch API (~$0.012/conversation)');
|
|
569
|
+
console.log(' ⢠Automatic extraction: tools used, files modified, concepts');
|
|
570
|
+
console.log('');
|
|
571
|
+
console.log('š What You Get:');
|
|
572
|
+
console.log(' ⢠Problem-solution structured summaries');
|
|
573
|
+
console.log(' ⢠Rich metadata (tools, concepts, files)');
|
|
574
|
+
console.log(' ⢠Fully automated batch processing');
|
|
575
|
+
console.log('');
|
|
576
|
+
console.log('āļø How It Works:');
|
|
577
|
+
console.log(' 1. Background watcher queues new conversations');
|
|
578
|
+
console.log(' 2. Auto-triggers batch when threshold reached (default: 10)');
|
|
579
|
+
console.log(' 3. Anthropic Batch API generates narratives');
|
|
580
|
+
console.log(' 4. Enhanced narratives auto-imported to Qdrant');
|
|
581
|
+
console.log('');
|
|
582
|
+
console.log('š Privacy: Conversations sent to Anthropic Batch API for narrative generation.');
|
|
583
|
+
console.log(' Review: https://www.anthropic.com/privacy');
|
|
584
|
+
console.log('');
|
|
585
|
+
|
|
586
|
+
const enableChoice = await question('Enable AI-powered narratives? (y/n) [recommended for best search]: ');
|
|
587
|
+
|
|
588
|
+
if (enableChoice.toLowerCase() === 'y') {
|
|
589
|
+
console.log('\nš Anthropic API Key Required');
|
|
590
|
+
console.log(' Get your key: https://console.anthropic.com/settings/keys');
|
|
591
|
+
console.log(' Cost: ~$0.012 per conversation via Batch API');
|
|
592
|
+
|
|
593
|
+
const apiKey = await question('\nPaste your Anthropic API key (sk-ant-...): ');
|
|
594
|
+
|
|
595
|
+
if (apiKey && apiKey.trim().startsWith('sk-ant-')) {
|
|
596
|
+
// Read current .env
|
|
597
|
+
const envPath = path.join(projectRoot, '.env');
|
|
598
|
+
let envContent = '';
|
|
599
|
+
try {
|
|
600
|
+
envContent = await fs.readFile(envPath, 'utf8');
|
|
601
|
+
} catch {
|
|
602
|
+
// File doesn't exist yet
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Remove existing ANTHROPIC_API_KEY if present
|
|
606
|
+
envContent = envContent.replace(/ANTHROPIC_API_KEY=.*/g, '');
|
|
607
|
+
|
|
608
|
+
// Add new key
|
|
609
|
+
envContent += `\n# Batch Automation (v7.0 AI-Powered Narratives)\nANTHROPIC_API_KEY=${apiKey.trim()}\n`;
|
|
610
|
+
|
|
611
|
+
// Write back
|
|
612
|
+
await fs.writeFile(envPath, envContent.trim() + '\n');
|
|
613
|
+
|
|
614
|
+
console.log('ā
API key saved to .env');
|
|
615
|
+
|
|
616
|
+
// Start batch automation services
|
|
617
|
+
console.log('\nš Starting batch automation services...');
|
|
618
|
+
try {
|
|
619
|
+
safeExec('docker', ['compose', '--profile', 'batch-automation', 'up', '-d'], {
|
|
620
|
+
cwd: projectRoot,
|
|
621
|
+
stdio: 'inherit'
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
console.log('\nā
Batch automation enabled!');
|
|
625
|
+
console.log(' ⢠batch-watcher: Monitors for new conversations');
|
|
626
|
+
console.log(' ⢠batch-monitor: Processes narrative generation');
|
|
627
|
+
console.log('');
|
|
628
|
+
console.log('š Monitor Progress:');
|
|
629
|
+
console.log(' docker compose logs batch-watcher -f');
|
|
630
|
+
console.log(' docker compose logs batch-monitor -f');
|
|
631
|
+
console.log('');
|
|
632
|
+
console.log('šÆ Next: New conversations will be automatically enhanced with narratives');
|
|
633
|
+
|
|
634
|
+
} catch (error) {
|
|
635
|
+
console.log('\nā ļø Could not start batch services automatically');
|
|
636
|
+
console.log(' Start manually: docker compose --profile batch-automation up -d');
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
} else if (apiKey && apiKey.trim()) {
|
|
640
|
+
console.log('\nā Invalid API key format. Anthropic keys start with "sk-ant-"');
|
|
641
|
+
console.log(' Skipping batch automation. You can enable it later by:');
|
|
642
|
+
console.log(' 1. Adding ANTHROPIC_API_KEY to .env');
|
|
643
|
+
console.log(' 2. Running: docker compose --profile batch-automation up -d');
|
|
644
|
+
} else {
|
|
645
|
+
console.log('\nš Skipping batch automation.');
|
|
646
|
+
console.log(' You can enable it later by:');
|
|
647
|
+
console.log(' 1. Get API key: https://console.anthropic.com/settings/keys');
|
|
648
|
+
console.log(' 2. Add to .env: ANTHROPIC_API_KEY=sk-ant-...');
|
|
649
|
+
console.log(' 3. Run: docker compose --profile batch-automation up -d');
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
} else {
|
|
653
|
+
console.log('\nš Skipping batch automation (staying with standard search).');
|
|
654
|
+
console.log(' You can enable AI narratives later by:');
|
|
655
|
+
console.log(' 1. Get API key: https://console.anthropic.com/settings/keys');
|
|
656
|
+
console.log(' 2. Add to .env: ANTHROPIC_API_KEY=sk-ant-...');
|
|
657
|
+
console.log(' 3. Run: docker compose --profile batch-automation up -d');
|
|
658
|
+
console.log('');
|
|
659
|
+
console.log('š” Tip: Even without narratives, you still get excellent local search!');
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
560
663
|
async function startWatcher() {
|
|
561
664
|
console.log('\nš Starting the streaming watcher...');
|
|
562
665
|
console.log(' ⢠HOT files (<5 min): 2-second processing');
|
|
@@ -577,28 +680,106 @@ async function startWatcher() {
|
|
|
577
680
|
}
|
|
578
681
|
}
|
|
579
682
|
|
|
683
|
+
async function setupRalphHooks() {
|
|
684
|
+
console.log('\nš» Ralph Loop Memory Integration (NEW!)...');
|
|
685
|
+
console.log('āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā');
|
|
686
|
+
console.log('The Ralph Wiggum technique helps Claude maintain context across long sessions.');
|
|
687
|
+
console.log('With CSR integration, Ralph loops gain cross-session memory!');
|
|
688
|
+
console.log('');
|
|
689
|
+
console.log('š Benefits:');
|
|
690
|
+
console.log(' ⢠Session state preserved across context compactions');
|
|
691
|
+
console.log(' ⢠Past learnings automatically injected into new sessions');
|
|
692
|
+
console.log(' ⢠Failed approaches remembered to avoid repeating mistakes');
|
|
693
|
+
console.log(' ⢠Works with the ralph-wiggum Claude Code plugin');
|
|
694
|
+
console.log('');
|
|
695
|
+
console.log('š How It Works:');
|
|
696
|
+
console.log(' ⢠SessionStart hook: Searches CSR for past Ralph sessions');
|
|
697
|
+
console.log(' ⢠PreCompact hook: Backs up state before context is lost');
|
|
698
|
+
console.log(' ⢠SessionEnd hook: Stores session narrative for future reference');
|
|
699
|
+
console.log('');
|
|
700
|
+
console.log('āļø Requirements:');
|
|
701
|
+
console.log(' ⢠ralph-wiggum plugin (Claude Code plugin)');
|
|
702
|
+
console.log(' ⢠Python 3.8+ (for hooks)');
|
|
703
|
+
console.log('');
|
|
704
|
+
|
|
705
|
+
const enableChoice = await question('Enable Ralph Loop memory integration? (y/n) [recommended]: ');
|
|
706
|
+
|
|
707
|
+
if (enableChoice.toLowerCase() === 'y') {
|
|
708
|
+
console.log('\nš¦ Installing Ralph hooks...');
|
|
709
|
+
|
|
710
|
+
try {
|
|
711
|
+
// Check if Python 3 is available
|
|
712
|
+
try {
|
|
713
|
+
safeExec('python3', ['--version'], { stdio: 'pipe' });
|
|
714
|
+
} catch {
|
|
715
|
+
console.log('\nā ļø Python 3 not found');
|
|
716
|
+
console.log(' Ralph hooks require Python 3.8+');
|
|
717
|
+
console.log(' Install Python and run: ./scripts/ralph/install_hooks.sh');
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// Run the hook installation script
|
|
722
|
+
const installScript = join(projectRoot, 'scripts', 'ralph', 'install_hooks.sh');
|
|
723
|
+
|
|
724
|
+
// Make sure the script is executable
|
|
725
|
+
try {
|
|
726
|
+
await fs.chmod(installScript, 0o755);
|
|
727
|
+
} catch {
|
|
728
|
+
// Ignore if already executable
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
safeExec('bash', [installScript], {
|
|
732
|
+
cwd: projectRoot,
|
|
733
|
+
stdio: 'inherit'
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
console.log('\nā
Ralph hooks installed successfully!');
|
|
737
|
+
console.log('');
|
|
738
|
+
console.log('š To use Ralph loops with memory:');
|
|
739
|
+
console.log(' 1. Install ralph-wiggum plugin in Claude Code:');
|
|
740
|
+
console.log(' /plugin install ralph-wiggum@anthropics');
|
|
741
|
+
console.log(' 2. Start a loop: /ralph-wiggum:ralph-loop "Your task"');
|
|
742
|
+
console.log(' 3. Session state will be automatically backed up to CSR');
|
|
743
|
+
console.log('');
|
|
744
|
+
console.log('š Verify hook installation:');
|
|
745
|
+
console.log(' ./scripts/ralph/install_hooks.sh --check');
|
|
746
|
+
|
|
747
|
+
} catch (error) {
|
|
748
|
+
console.log('\nā ļø Could not install Ralph hooks automatically');
|
|
749
|
+
console.log(` Error: ${error.message}`);
|
|
750
|
+
console.log(' You can install manually: ./scripts/ralph/install_hooks.sh');
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
} else {
|
|
754
|
+
console.log('\nš Skipping Ralph hooks installation.');
|
|
755
|
+
console.log(' You can install later: ./scripts/ralph/install_hooks.sh');
|
|
756
|
+
console.log(' Docs: https://github.com/ramakay/claude-self-reflect/blob/main/docs/development/ralph-memory-integration.md');
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
|
|
580
760
|
async function showFinalInstructions() {
|
|
581
761
|
console.log('\nā
Setup complete!');
|
|
582
|
-
|
|
762
|
+
|
|
583
763
|
console.log('\nšÆ Your Claude Self-Reflect System:');
|
|
584
764
|
console.log(' ⢠š Qdrant Dashboard: http://localhost:6333/dashboard/');
|
|
585
765
|
console.log(' ⢠š Status: All services running');
|
|
586
766
|
console.log(' ⢠š Search: Semantic search with memory decay enabled');
|
|
587
767
|
console.log(' ⢠š Watcher: HOT/WARM/COLD prioritization active');
|
|
588
|
-
|
|
768
|
+
|
|
589
769
|
console.log('\nš Quick Reference Commands:');
|
|
590
770
|
console.log(' ⢠Check status: docker compose ps');
|
|
591
771
|
console.log(' ⢠View logs: docker compose logs -f');
|
|
592
772
|
console.log(' ⢠Import conversations: docker compose run --rm importer');
|
|
593
773
|
console.log(' ⢠Enrich metadata: docker compose run --rm importer python /app/scripts/delta-metadata-update-safe.py');
|
|
594
774
|
console.log(' ⢠Start watcher: docker compose --profile watch up -d');
|
|
775
|
+
console.log(' ⢠Ralph hooks: ./scripts/ralph/install_hooks.sh --check');
|
|
595
776
|
console.log(' ⢠Stop all: docker compose down');
|
|
596
|
-
|
|
777
|
+
|
|
597
778
|
console.log('\nšÆ Next Steps:');
|
|
598
779
|
console.log('1. Restart Claude Code');
|
|
599
780
|
console.log('2. Look for "claude-self-reflect" in the MCP tools');
|
|
600
781
|
console.log('3. Try: "Search my past conversations about Python"');
|
|
601
|
-
|
|
782
|
+
|
|
602
783
|
console.log('\nš Documentation: https://github.com/ramakay/claude-self-reflect');
|
|
603
784
|
}
|
|
604
785
|
|
|
@@ -684,16 +865,22 @@ async function main() {
|
|
|
684
865
|
|
|
685
866
|
// Configure Claude
|
|
686
867
|
await configureClaude();
|
|
687
|
-
|
|
868
|
+
|
|
688
869
|
// Import conversations
|
|
689
870
|
await importConversations();
|
|
690
|
-
|
|
871
|
+
|
|
691
872
|
// Enrich metadata (new in v2.5.19)
|
|
692
873
|
await enrichMetadata();
|
|
693
|
-
|
|
874
|
+
|
|
875
|
+
// Setup batch automation (new in v7.0)
|
|
876
|
+
await setupBatchAutomation();
|
|
877
|
+
|
|
878
|
+
// Setup Ralph hooks (new in v7.1 - Memory-Augmented Ralph Loops)
|
|
879
|
+
await setupRalphHooks();
|
|
880
|
+
|
|
694
881
|
// Start the watcher
|
|
695
882
|
await startWatcher();
|
|
696
|
-
|
|
883
|
+
|
|
697
884
|
// Show final instructions
|
|
698
885
|
await showFinalInstructions();
|
|
699
886
|
|
|
@@ -94,6 +94,48 @@ class UpdateManager {
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
async checkRalphHooks() {
|
|
98
|
+
// Check if Ralph hooks are installed in ~/.claude/settings.json
|
|
99
|
+
const claudeSettings = path.join(this.homeDir, '.claude', 'settings.json');
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
if (!fs.existsSync(claudeSettings)) {
|
|
103
|
+
return {
|
|
104
|
+
installed: false,
|
|
105
|
+
name: 'Ralph Memory Hooks',
|
|
106
|
+
critical: false, // Optional feature
|
|
107
|
+
fix: () => this.installRalphHooks()
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const settings = JSON.parse(fs.readFileSync(claudeSettings, 'utf8'));
|
|
112
|
+
|
|
113
|
+
// Check for Ralph hooks in SessionStart or SessionEnd
|
|
114
|
+
const hasRalphHooks = settings.hooks &&
|
|
115
|
+
(
|
|
116
|
+
(settings.hooks.SessionStart &&
|
|
117
|
+
JSON.stringify(settings.hooks.SessionStart).includes('ralph')) ||
|
|
118
|
+
(settings.hooks.SessionEnd &&
|
|
119
|
+
JSON.stringify(settings.hooks.SessionEnd).includes('ralph'))
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
installed: hasRalphHooks,
|
|
124
|
+
name: 'Ralph Memory Hooks',
|
|
125
|
+
critical: false, // Optional feature
|
|
126
|
+
fix: hasRalphHooks ? null : () => this.installRalphHooks()
|
|
127
|
+
};
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return {
|
|
130
|
+
installed: false,
|
|
131
|
+
name: 'Ralph Memory Hooks',
|
|
132
|
+
critical: false,
|
|
133
|
+
fix: () => this.installRalphHooks(),
|
|
134
|
+
error: `Could not check Ralph hooks: ${error.message}`
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
97
139
|
async checkDocker() {
|
|
98
140
|
try {
|
|
99
141
|
execSync('docker info', { stdio: 'ignore' });
|
|
@@ -265,6 +307,48 @@ class UpdateManager {
|
|
|
265
307
|
}
|
|
266
308
|
}
|
|
267
309
|
|
|
310
|
+
async installRalphHooks() {
|
|
311
|
+
this.log('Installing Ralph Memory Hooks...', 'info');
|
|
312
|
+
|
|
313
|
+
// Check if Python 3 is available
|
|
314
|
+
try {
|
|
315
|
+
execSync('python3 --version', { stdio: 'ignore' });
|
|
316
|
+
} catch {
|
|
317
|
+
this.log('Python 3 is required for Ralph hooks', 'error');
|
|
318
|
+
this.log('Install Python 3.8+ and run: ./scripts/ralph/install_hooks.sh', 'info');
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const installScript = path.join(this.packageRoot, 'scripts', 'ralph', 'install_hooks.sh');
|
|
323
|
+
|
|
324
|
+
if (!fs.existsSync(installScript)) {
|
|
325
|
+
this.log(`Ralph hooks script not found: ${installScript}`, 'error');
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
// Make sure the script is executable
|
|
331
|
+
fs.chmodSync(installScript, 0o755);
|
|
332
|
+
|
|
333
|
+
execSync(`bash "${installScript}"`, {
|
|
334
|
+
cwd: this.packageRoot,
|
|
335
|
+
stdio: 'inherit'
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
this.log('Ralph Memory Hooks installed successfully!', 'success');
|
|
339
|
+
this.log('', 'info');
|
|
340
|
+
this.log('To use Ralph loops with memory:', 'info');
|
|
341
|
+
this.log(' 1. Install plugin: /plugin install ralph-wiggum@anthropics', 'info');
|
|
342
|
+
this.log(' 2. Start a loop: /ralph-wiggum:ralph-loop "Your task"', 'info');
|
|
343
|
+
this.log(' 3. Session state will be automatically backed up to CSR', 'info');
|
|
344
|
+
return true;
|
|
345
|
+
} catch (error) {
|
|
346
|
+
this.log(`Failed to install Ralph hooks: ${error.message}`, 'error');
|
|
347
|
+
this.log('You can install manually: ./scripts/ralph/install_hooks.sh', 'info');
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
268
352
|
async startQdrant() {
|
|
269
353
|
this.log('Starting Qdrant...', 'info');
|
|
270
354
|
|
|
@@ -313,7 +397,8 @@ class UpdateManager {
|
|
|
313
397
|
{ name: 'Docker Config', fn: () => this.checkDockerComposeConfig() },
|
|
314
398
|
{ name: 'cc-statusline', fn: () => this.checkCCStatusline() },
|
|
315
399
|
{ name: 'csr-status', fn: () => this.checkCSRStatusScript() },
|
|
316
|
-
{ name: 'AST-Grep', fn: () => this.checkASTGrep() }
|
|
400
|
+
{ name: 'AST-Grep', fn: () => this.checkASTGrep() },
|
|
401
|
+
{ name: 'Ralph Hooks', fn: () => this.checkRalphHooks() }
|
|
317
402
|
];
|
|
318
403
|
|
|
319
404
|
const settledResults = await Promise.allSettled(checks.map(c => c.fn()));
|
|
@@ -391,6 +476,8 @@ class UpdateManager {
|
|
|
391
476
|
recheckResult = await this.checkCSRStatusScript();
|
|
392
477
|
} else if (recheckName.includes('ast-grep')) {
|
|
393
478
|
recheckResult = await this.checkASTGrep();
|
|
479
|
+
} else if (recheckName.includes('ralph')) {
|
|
480
|
+
recheckResult = await this.checkRalphHooks();
|
|
394
481
|
}
|
|
395
482
|
|
|
396
483
|
// Guard against undefined recheckResult (no matching verifier)
|