claude-self-reflect 3.0.0 → 3.0.2
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/claude-self-reflect-test.md +110 -66
- package/README.md +1 -1
- package/installer/setup-wizard.js +4 -2
- package/mcp-server/pyproject.toml +1 -0
- package/mcp-server/src/server.py +84 -0
- package/package.json +2 -1
- package/scripts/import-conversations-unified.py +225 -44
- package/scripts/importer/__init__.py +25 -0
- package/scripts/importer/__main__.py +14 -0
- package/scripts/importer/core/__init__.py +25 -0
- package/scripts/importer/core/config.py +120 -0
- package/scripts/importer/core/exceptions.py +52 -0
- package/scripts/importer/core/models.py +184 -0
- package/scripts/importer/embeddings/__init__.py +22 -0
- package/scripts/importer/embeddings/base.py +141 -0
- package/scripts/importer/embeddings/fastembed_provider.py +164 -0
- package/scripts/importer/embeddings/validator.py +136 -0
- package/scripts/importer/embeddings/voyage_provider.py +251 -0
- package/scripts/importer/main.py +393 -0
- package/scripts/importer/processors/__init__.py +15 -0
- package/scripts/importer/processors/ast_extractor.py +197 -0
- package/scripts/importer/processors/chunker.py +157 -0
- package/scripts/importer/processors/concept_extractor.py +109 -0
- package/scripts/importer/processors/conversation_parser.py +181 -0
- package/scripts/importer/processors/tool_extractor.py +165 -0
- package/scripts/importer/state/__init__.py +5 -0
- package/scripts/importer/state/state_manager.py +190 -0
- package/scripts/importer/storage/__init__.py +5 -0
- package/scripts/importer/storage/qdrant_storage.py +250 -0
- package/scripts/importer/utils/__init__.py +9 -0
- package/scripts/importer/utils/logger.py +87 -0
- package/scripts/importer/utils/project_normalizer.py +120 -0
|
@@ -12,13 +12,22 @@ You are a resilient and comprehensive testing specialist for Claude Self-Reflect
|
|
|
12
12
|
- Streaming importer maintains <50MB memory while processing every 60s
|
|
13
13
|
- MCP tools enable reflection and memory storage
|
|
14
14
|
- System must handle sensitive API keys securely
|
|
15
|
+
- Modular importer architecture in `scripts/importer/` package
|
|
16
|
+
- Voyage API key read from `.env` file automatically
|
|
17
|
+
|
|
18
|
+
## CRITICAL Testing Protocol
|
|
19
|
+
1. **Test Local Mode First** - Ensure all functionality works with FastEmbed
|
|
20
|
+
2. **Test Cloud Mode** - Switch to Voyage AI and validate
|
|
21
|
+
3. **RESTORE TO LOCAL** - Machine MUST be left in 100% local state after testing
|
|
22
|
+
4. **Certify Both Modes** - Only proceed to release if both modes pass
|
|
23
|
+
5. **NO Model Changes** - Use sentence-transformers/all-MiniLM-L6-v2 (384 dims) for local
|
|
15
24
|
|
|
16
25
|
## Comprehensive Test Suite
|
|
17
26
|
|
|
18
27
|
### Available Test Categories
|
|
19
|
-
The project
|
|
28
|
+
The project includes a well-organized test suite:
|
|
20
29
|
|
|
21
|
-
1. **MCP Tool Integration** (`
|
|
30
|
+
1. **MCP Tool Integration** (`tests/integration/test_mcp_tools.py`)
|
|
22
31
|
- All MCP tools with various parameters
|
|
23
32
|
- Edge cases and error handling
|
|
24
33
|
- Cross-project search validation
|
|
@@ -67,21 +76,20 @@ The project now includes a comprehensive test suite in `/tests/` directory:
|
|
|
67
76
|
```bash
|
|
68
77
|
# Run ALL tests
|
|
69
78
|
cd ~/projects/claude-self-reflect
|
|
70
|
-
python tests/
|
|
79
|
+
python -m pytest tests/
|
|
71
80
|
|
|
72
|
-
# Run specific categories
|
|
73
|
-
python
|
|
81
|
+
# Run specific test categories
|
|
82
|
+
python -m pytest tests/integration/
|
|
83
|
+
python -m pytest tests/unit/
|
|
84
|
+
python -m pytest tests/performance/
|
|
74
85
|
|
|
75
86
|
# Run with verbose output
|
|
76
|
-
python tests/
|
|
77
|
-
|
|
78
|
-
# List available test categories
|
|
79
|
-
python tests/run_all_tests.py --list
|
|
87
|
+
python -m pytest tests/ -v
|
|
80
88
|
|
|
81
89
|
# Run individual test files
|
|
82
|
-
python tests/
|
|
83
|
-
python tests/
|
|
84
|
-
python tests/
|
|
90
|
+
python tests/integration/test_mcp_tools.py
|
|
91
|
+
python tests/integration/test_collection_naming.py
|
|
92
|
+
python tests/integration/test_system_integration.py
|
|
85
93
|
```
|
|
86
94
|
|
|
87
95
|
### Test Results Location
|
|
@@ -367,77 +375,113 @@ if [ -n "$VOYAGE_KEY" ]; then
|
|
|
367
375
|
fi
|
|
368
376
|
```
|
|
369
377
|
|
|
370
|
-
###
|
|
378
|
+
### CRITICAL: Verify Actual Imports (Not Just API Connection!)
|
|
371
379
|
```bash
|
|
372
|
-
echo "===
|
|
373
|
-
|
|
374
|
-
# Step 1:
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
echo "Current embedding mode: ${PREFER_LOCAL_EMBEDDINGS:-true}"
|
|
379
|
-
|
|
380
|
-
# Step 2: Check prerequisites
|
|
381
|
-
if [ -z "$VOYAGE_KEY" ]; then
|
|
382
|
-
echo "⚠️ WARNING: VOYAGE_KEY not set"
|
|
383
|
-
echo "To test cloud mode, set: export VOYAGE_KEY='your-key'"
|
|
384
|
-
echo "Skipping cloud test..."
|
|
385
|
-
exit 0
|
|
380
|
+
echo "=== REAL Cloud Embedding Import Test ==="
|
|
381
|
+
|
|
382
|
+
# Step 1: Verify prerequisites
|
|
383
|
+
if [ ! -f .env ] || [ -z "$(grep VOYAGE_KEY .env)" ]; then
|
|
384
|
+
echo "❌ FAIL: No VOYAGE_KEY in .env file"
|
|
385
|
+
exit 1
|
|
386
386
|
fi
|
|
387
387
|
|
|
388
|
-
#
|
|
389
|
-
|
|
388
|
+
# Extract API key
|
|
389
|
+
export VOYAGE_KEY=$(grep VOYAGE_KEY .env | cut -d= -f2)
|
|
390
|
+
echo "✅ Found Voyage key: ${VOYAGE_KEY:0:10}..."
|
|
391
|
+
|
|
392
|
+
# Step 2: Count existing collections before test
|
|
393
|
+
BEFORE_LOCAL=$(curl -s http://localhost:6333/collections | jq -r '.result.collections[].name' | grep "_local" | wc -l)
|
|
394
|
+
BEFORE_VOYAGE=$(curl -s http://localhost:6333/collections | jq -r '.result.collections[].name' | grep "_voyage" | wc -l)
|
|
395
|
+
echo "Before: $BEFORE_LOCAL local, $BEFORE_VOYAGE voyage collections"
|
|
396
|
+
|
|
397
|
+
# Step 3: Create NEW test conversation for import
|
|
398
|
+
TEST_PROJECT="test-voyage-$(date +%s)"
|
|
399
|
+
TEST_DIR=~/.claude/projects/$TEST_PROJECT
|
|
400
|
+
mkdir -p $TEST_DIR
|
|
401
|
+
TEST_FILE=$TEST_DIR/voyage-test.jsonl
|
|
402
|
+
|
|
403
|
+
cat > $TEST_FILE << 'EOF'
|
|
404
|
+
{"type":"conversation","uuid":"voyage-test-001","name":"Voyage Import Test","messages":[{"role":"human","content":"Testing actual Voyage AI import"},{"role":"assistant","content":[{"type":"text","text":"This should create a real Voyage collection with 1024-dim vectors"}]}],"conversation_id":"voyage-test-001","created_at":"2025-09-08T00:00:00Z"}
|
|
405
|
+
EOF
|
|
406
|
+
|
|
407
|
+
echo "✅ Created test file: $TEST_FILE"
|
|
408
|
+
|
|
409
|
+
# Step 4: Switch to Voyage mode and import
|
|
410
|
+
echo "Switching to Voyage mode..."
|
|
390
411
|
export PREFER_LOCAL_EMBEDDINGS=false
|
|
391
|
-
|
|
392
|
-
docker compose --profile watch up -d streaming-importer
|
|
412
|
+
export USE_VOYAGE=true
|
|
393
413
|
|
|
394
|
-
#
|
|
395
|
-
|
|
396
|
-
|
|
414
|
+
# Run import directly with modular importer
|
|
415
|
+
cd ~/projects/claude-self-reflect
|
|
416
|
+
source venv/bin/activate
|
|
417
|
+
python -c "
|
|
418
|
+
import os
|
|
419
|
+
os.environ['VOYAGE_KEY'] = '$VOYAGE_KEY'
|
|
420
|
+
os.environ['PREFER_LOCAL_EMBEDDINGS'] = 'false'
|
|
421
|
+
os.environ['USE_VOYAGE'] = 'true'
|
|
422
|
+
|
|
423
|
+
from scripts.importer.main import ImporterContainer
|
|
424
|
+
container = ImporterContainer()
|
|
425
|
+
processor = container.processor()
|
|
426
|
+
|
|
427
|
+
# Process test file
|
|
428
|
+
import json
|
|
429
|
+
with open('$TEST_FILE') as f:
|
|
430
|
+
data = json.load(f)
|
|
431
|
+
|
|
432
|
+
result = processor.process_conversation(
|
|
433
|
+
conversation_data=data,
|
|
434
|
+
file_path='$TEST_FILE',
|
|
435
|
+
project_path='$TEST_PROJECT'
|
|
436
|
+
)
|
|
437
|
+
print(f'Import result: {result}')
|
|
438
|
+
"
|
|
397
439
|
|
|
398
|
-
# Step 5:
|
|
399
|
-
echo "
|
|
400
|
-
sleep
|
|
440
|
+
# Step 5: Verify actual Voyage collection created
|
|
441
|
+
echo "Verifying Voyage collection..."
|
|
442
|
+
sleep 5
|
|
443
|
+
AFTER_VOYAGE=$(curl -s http://localhost:6333/collections | jq -r '.result.collections[].name' | grep "_voyage" | wc -l)
|
|
401
444
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
445
|
+
if [ "$AFTER_VOYAGE" -gt "$BEFORE_VOYAGE" ]; then
|
|
446
|
+
echo "✅ SUCCESS: New Voyage collection created!"
|
|
447
|
+
|
|
448
|
+
# Get the new collection name
|
|
449
|
+
NEW_COL=$(curl -s http://localhost:6333/collections | jq -r '.result.collections[].name' | grep "_voyage" | tail -1)
|
|
450
|
+
|
|
451
|
+
# Verify dimensions
|
|
452
|
+
DIMS=$(curl -s http://localhost:6333/collections/$NEW_COL | jq '.result.config.params.vectors.size')
|
|
453
|
+
POINTS=$(curl -s http://localhost:6333/collections/$NEW_COL | jq '.result.points_count')
|
|
407
454
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
455
|
+
echo "Collection: $NEW_COL"
|
|
456
|
+
echo "Dimensions: $DIMS (expected 1024)"
|
|
457
|
+
echo "Points: $POINTS"
|
|
458
|
+
|
|
459
|
+
if [ "$DIMS" = "1024" ] && [ "$POINTS" -gt "0" ]; then
|
|
460
|
+
echo "✅ PASS: Voyage import actually worked!"
|
|
413
461
|
else
|
|
414
|
-
echo "❌ FAIL: Wrong dimensions
|
|
462
|
+
echo "❌ FAIL: Wrong dimensions or no points"
|
|
415
463
|
fi
|
|
416
464
|
else
|
|
417
|
-
echo "❌ FAIL: No
|
|
465
|
+
echo "❌ FAIL: No new Voyage collection created - import didn't work!"
|
|
418
466
|
fi
|
|
419
467
|
|
|
420
|
-
# Step
|
|
421
|
-
echo "
|
|
422
|
-
# Note: MCP must also use PREFER_LOCAL_EMBEDDINGS=false
|
|
423
|
-
|
|
424
|
-
# Step 8: Restore local mode
|
|
425
|
-
echo "5. Restoring local FastEmbed mode..."
|
|
468
|
+
# Step 6: Restore to local mode
|
|
469
|
+
echo "Restoring local mode..."
|
|
426
470
|
export PREFER_LOCAL_EMBEDDINGS=true
|
|
427
|
-
|
|
428
|
-
docker compose --profile watch up -d streaming-importer
|
|
471
|
+
export USE_VOYAGE=false
|
|
429
472
|
|
|
430
|
-
# Step
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
echo "✅ Restored: Found $LOCAL_COLS local collections"
|
|
434
|
-
|
|
435
|
-
# Step 10: Cleanup
|
|
436
|
-
rm -f $TEST_FILE
|
|
437
|
-
cp config/imported-files.json.local-backup config/imported-files.json
|
|
438
|
-
echo "✅ Cloud embedding test complete and restored to local mode"
|
|
473
|
+
# Step 7: Cleanup
|
|
474
|
+
rm -rf $TEST_DIR
|
|
475
|
+
echo "✅ Test complete and cleaned up"
|
|
439
476
|
```
|
|
440
477
|
|
|
478
|
+
### Verification Checklist for Real Imports
|
|
479
|
+
1. **Check Collection Suffix**: `_voyage` for cloud, `_local` for FastEmbed
|
|
480
|
+
2. **Verify Dimensions**: 1024 for Voyage, 384 for FastEmbed
|
|
481
|
+
3. **Count Points**: Must have >0 points for successful import
|
|
482
|
+
4. **Check Logs**: Look for actual embedding API calls
|
|
483
|
+
5. **Verify State File**: Check imported-files.json for record
|
|
484
|
+
|
|
441
485
|
## Success Criteria
|
|
442
486
|
|
|
443
487
|
### System Functionality
|
package/README.md
CHANGED
|
@@ -108,7 +108,7 @@ See your conversation indexing progress directly in your statusline:
|
|
|
108
108
|
### Active Indexing (50% with backlog)
|
|
109
109
|

|
|
110
110
|
|
|
111
|
-
Works with [Claude Code Statusline](https://github.com/sirmalloc/ccstatusline) - shows progress bars, percentages, and indexing lag in real-time!
|
|
111
|
+
Works with [Claude Code Statusline](https://github.com/sirmalloc/ccstatusline) - shows progress bars, percentages, and indexing lag in real-time! The statusline also displays MCP connection status (✓ Connected) and collection counts (28/29 indexed).
|
|
112
112
|
|
|
113
113
|
## Key Features
|
|
114
114
|
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
// This is the new Docker-based setup wizard
|
|
4
4
|
// It runs everything in Docker to avoid Python environment issues
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
5
|
+
import { fileURLToPath, pathToFileURL } from 'url';
|
|
6
6
|
import { dirname, join } from 'path';
|
|
7
7
|
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = dirname(__filename);
|
|
10
10
|
|
|
11
11
|
// Simply forward to the Docker-based wizard
|
|
12
|
-
|
|
12
|
+
// Fix for Windows: Use pathToFileURL for dynamic imports (Issue #51)
|
|
13
|
+
const wizardPath = join(__dirname, 'setup-wizard-docker.js');
|
|
14
|
+
import(pathToFileURL(wizardPath).href);
|
package/mcp-server/src/server.py
CHANGED
|
@@ -143,6 +143,90 @@ mcp = FastMCP(
|
|
|
143
143
|
# Create Qdrant client
|
|
144
144
|
qdrant_client = AsyncQdrantClient(url=QDRANT_URL)
|
|
145
145
|
|
|
146
|
+
# Add MCP Resources for system status
|
|
147
|
+
@mcp.resource("status://import-stats")
|
|
148
|
+
async def get_import_stats():
|
|
149
|
+
"""Current import statistics and progress."""
|
|
150
|
+
await update_indexing_status()
|
|
151
|
+
|
|
152
|
+
return json.dumps({
|
|
153
|
+
"indexed_conversations": indexing_status["indexed_conversations"],
|
|
154
|
+
"total_conversations": indexing_status["total_conversations"],
|
|
155
|
+
"percentage": indexing_status["percentage"],
|
|
156
|
+
"backlog_count": indexing_status["backlog_count"],
|
|
157
|
+
"last_check": datetime.fromtimestamp(indexing_status["last_check"]).isoformat() if indexing_status["last_check"] else None
|
|
158
|
+
}, indent=2)
|
|
159
|
+
|
|
160
|
+
@mcp.resource("status://collection-list")
|
|
161
|
+
async def get_collection_list():
|
|
162
|
+
"""List of all Qdrant collections with metadata."""
|
|
163
|
+
try:
|
|
164
|
+
collections = await qdrant_client.get_collections()
|
|
165
|
+
collection_data = []
|
|
166
|
+
|
|
167
|
+
for collection in collections.collections:
|
|
168
|
+
# Get collection info
|
|
169
|
+
info = await qdrant_client.get_collection(collection_name=collection.name)
|
|
170
|
+
collection_data.append({
|
|
171
|
+
"name": collection.name,
|
|
172
|
+
"points_count": info.points_count,
|
|
173
|
+
"indexed_vectors_count": info.indexed_vectors_count,
|
|
174
|
+
"status": info.status,
|
|
175
|
+
"config": {
|
|
176
|
+
"vector_size": info.config.params.vectors.size if hasattr(info.config.params.vectors, 'size') else 384,
|
|
177
|
+
"distance": str(info.config.params.vectors.distance) if hasattr(info.config.params.vectors, 'distance') else "Cosine"
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
return json.dumps({
|
|
182
|
+
"total_collections": len(collection_data),
|
|
183
|
+
"collections": collection_data
|
|
184
|
+
}, indent=2)
|
|
185
|
+
except Exception as e:
|
|
186
|
+
return json.dumps({"error": str(e)}, indent=2)
|
|
187
|
+
|
|
188
|
+
@mcp.resource("status://system-health")
|
|
189
|
+
async def get_system_health():
|
|
190
|
+
"""System health and configuration information."""
|
|
191
|
+
try:
|
|
192
|
+
# Check Qdrant connectivity
|
|
193
|
+
qdrant_info = await qdrant_client.get_collections()
|
|
194
|
+
qdrant_healthy = True
|
|
195
|
+
qdrant_version = "Connected"
|
|
196
|
+
except:
|
|
197
|
+
qdrant_healthy = False
|
|
198
|
+
qdrant_version = "Disconnected"
|
|
199
|
+
|
|
200
|
+
# Check embedding configuration
|
|
201
|
+
embedding_info = {}
|
|
202
|
+
if embedding_manager:
|
|
203
|
+
embedding_info = {
|
|
204
|
+
"model_type": embedding_manager.model_type,
|
|
205
|
+
"model_name": embedding_manager.model_name,
|
|
206
|
+
"dimension": embedding_manager.dimension
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return json.dumps({
|
|
210
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
211
|
+
"qdrant": {
|
|
212
|
+
"healthy": qdrant_healthy,
|
|
213
|
+
"url": QDRANT_URL,
|
|
214
|
+
"version": qdrant_version
|
|
215
|
+
},
|
|
216
|
+
"embeddings": embedding_info,
|
|
217
|
+
"configuration": {
|
|
218
|
+
"memory_decay_enabled": ENABLE_MEMORY_DECAY,
|
|
219
|
+
"decay_weight": DECAY_WEIGHT,
|
|
220
|
+
"decay_scale_days": DECAY_SCALE_DAYS,
|
|
221
|
+
"prefer_local_embeddings": PREFER_LOCAL_EMBEDDINGS
|
|
222
|
+
},
|
|
223
|
+
"indexing_status": {
|
|
224
|
+
"indexed": indexing_status["indexed_conversations"],
|
|
225
|
+
"total": indexing_status["total_conversations"],
|
|
226
|
+
"percentage": indexing_status["percentage"]
|
|
227
|
+
}
|
|
228
|
+
}, indent=2)
|
|
229
|
+
|
|
146
230
|
# Track indexing status (updated periodically)
|
|
147
231
|
indexing_status = {
|
|
148
232
|
"last_check": 0,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-self-reflect",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "Give Claude perfect memory of all your conversations - Installation wizard for Python MCP server",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"mcp-server/run-mcp-clean.sh",
|
|
42
42
|
"mcp-server/run-mcp-docker.sh",
|
|
43
43
|
"scripts/import-*.py",
|
|
44
|
+
"scripts/importer/**/*.py",
|
|
44
45
|
"scripts/delta-metadata-update-safe.py",
|
|
45
46
|
"scripts/force-metadata-recovery.py",
|
|
46
47
|
".claude/agents/*.md",
|